Странный ответ tcpclient https на сообщение

У меня странная проблема с попыткой получить полный ответ с веб-страницы, используя TcpClient, на которую я отправляю POST. Вот код:

byte[] RecvBufferxxxx = new byte[4096];

var returnData = "";
var uri = new Uri(string.Format(core.serverAuth, "app_data"));
var head = new WebHeaderCollection();
head[HttpRequestHeader.Host] = uri.Host;
head[HttpRequestHeader.Connection] = "keep-alive";
head[HttpRequestHeader.AcceptEncoding] = "deflate";

using (var client = new TcpClient(uri.Host, 443))
{
    client.SendTimeout = 10000;
    client.ReceiveTimeout = 10000;
    using (SslStream s = new SslStream(client.GetStream(), false, 
        IgnoreCertificateErrorHandler, null))
    {
        s.AuthenticateAsClient(uri.Host, null, SslProtocols.Tls, false);

        var hhd = "POST " + uri.PathAndQuery + " HTTP/1.0\r\n" + head;

        var bts = Encoding.ASCII.GetBytes(hhd);
        s.Write(bts, 0, bts.Length);
        s.Flush();
        s.ReadByte();

        var n = s.Read(RecvBufferxxxx, 0, RecvBufferxxxx.Length);
        // var tmp = Encoding.ASCII.GetString(RecvBufferxxxx, 0, n);
        // ANOTHER CALL SAMPLE   
        // n = s.Read(RecvBufferxxxx, 0, RecvBufferxxxx.Length);

        using (MemoryStream ms = new MemoryStream(RecvBufferxxxx, 0, n))
        {
            ms.ReadByte();
            ms.ReadByte();
            using (DeflateStream df = new DeflateStream(ms, 
                CompressionMode.Decompress))
            {
                using (StreamReader rd = new StreamReader(df))
                {
                    returnData = rd.ReadToEnd();
                }
            }
        }
    }
}

Этот код работает, но он получает только заголовки ответа, мне нужно сделать еще один вызов, чтобы получить тело ответа, и я не знаю, почему.

Ответ от моего сервера и очень короткий.

Раньше я использовал только Socket, и все получалось за один вызов, но теперь я переписал его как в коде, добавив SSL и дефляцию.

Я проверил ту же ссылку в firefox с помощью firebug, и есть только один полный ответ.

Я дважды проверил это с помощью wireshark и firebug, используя firebug, и этот код wireshark выглядит совершенно одинаково.

Я могу сделать второе чтение с этим кодом, а затем получить тело ответа, но затем я вижу в wirehark, что было установлено другое ssl-соединение, и я не хочу этого, я хочу так же, как это делает firefox.

Другая причина в том, что я просто хочу знать, почему это происходит, и как это исправить, может ли кто-нибудь мне помочь?


person Programista    schedule 27.08.2011    source источник
comment
Почему вы не используете WebClient класс? Или, если вам требуется более подробный контроль над запросом, HttpWebRequest< /а> класс? Оба обрабатывают дефляцию сжатых потоков, SSL и POST-запросов.   -  person casperOne    schedule 27.08.2011
comment
Это не мой вопрос, использование веб-клиента или httpwebrequest не является ответом. Прочитайте мою проблему еще раз.   -  person Programista    schedule 27.08.2011
comment
@svick: Домашнее задание, наверное? Если это так, то к нему следует применить тег homework.   -  person casperOne    schedule 28.08.2011
comment
Конечно, мне не нужен этот ответ, я пытаюсь сделать это с помощью tcpclient, не заставляйте меня менять это, если вы просто не знаете ответа, это быстро, и код выполняется при запуске формы, что является причиной. ЭТО НЕ ДОМАШНЕЕ ЗАДАНИЕ. Но даже если бы это было, вы хотя бы проверяли это?, я проверял. Если вы не знаете ответа, возможно, вы никогда не использовали tcpclient с ssl, но это моя проблема. Использование веб-клиента/веб-запроса не является ответом, я вижу это каждый раз, когда кто-то спрашивает tcpclient, используйте что-то еще, потому что это сложно или первое проще. Я попробую отражатель тогда, чтобы проверить это.   -  person Programista    schedule 28.08.2011


Ответы (2)


Stream.Read() может не дать вам весь буфер, разрешено возвращать меньше. Если вы хотите прочитать весь поток, вы должны вызывать его в цикле, пока он не вернет 0.

person svick    schedule 27.08.2011
comment
Места в буфере предостаточно, ответ очень короткий ‹250 букв. Дело в том, что он возвращает первые заголовки ответа, затем тело ответа, кроме того, firefox делает это за один вызов, если я сделал второе чтение, у меня будет вторая транзакция ssl, и это не желаемый эффект. Мой код близок к низкому уровню, если ff может сделать это и любой другой браузер, то почему этот код не может. И я удивлен, что это происходит. - person Programista; 27.08.2011
comment
Неважно, что в буфере достаточно места. Вы просто не можете предположить, что Read() даст вам все сразу. Одной из причин этого является то, что ответ может быть в нескольких пакетах, и вы можете начать обработку до того, как прибудет последний. Я мало что знаю о SSL, но вы уверены, что еще один Read() создаст еще одну транзакцию? - person svick; 27.08.2011
comment
ответ может быть в более чем одном пакете, но когда я использую только сокет или httpwebrequest, он находится в одном вызове, так что ...? - person Programista; 27.08.2011
comment
Понятия не имею, может быть, вы изменили что-то еще, это имеет значение. - person svick; 28.08.2011
comment
Нет, у вас есть код, просто протестируйте его, это может быть любой источник данных https. - person Programista; 28.08.2011
comment
Я только что сделал. Да, первый Read() возвращает только HTTP-заголовок, а второй Read() не отправляет и не получает никаких данных. - person svick; 28.08.2011

Хорошо, нашел решение, но не источник проблемы, просто используйте ReadByte в цикле, не знаю, почему у Read есть проблемы, с помощью рефлектора я смог обнаружить, что это может быть проблема с внутренней буферизацией SslStream, но кто знает.

person Programista    schedule 28.08.2011