Программирование на сокете C # - Как определить размер буфера приема - PullRequest
0 голосов
/ 06 декабря 2010

Я пытаюсь написать простое консольное приложение, которое отправляет на страницу и выводит возвращенный html на консоль.

У меня работает код, но он возвращает только часть ответа.Единственный способ понять, как это работает, - установить для байтового буфера размер, который, как я знаю, достаточно велик для возвращаемого содержимого.

В любом случае можно проверить, насколько большим должен быть буферЧтобы получить полный ответ?

Вот код ...

Uri uri = new Uri(@"http://bobssite/");

// Get the IPAddress of the website we are going to and create the EndPoint
IPAddress ipAddress = Dns.GetHostEntry(uri.Host).AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddress, 80);

// Create a new Socket instance and open the socket for communication
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
socket.Connect(endPoint);

// Attempt to send the request
int byteCount = 0;
try
{
    string requestString = 
        "POST " + uri.PathAndQuery + " HTTP/1.1\r\n" + 
        "Host: " + uri.Host + "\r\n" + 
        "Content-Type: application/x-www-form-urlencoded\r\n" + 
        "Content-Length: 11\r\n" + 
        "\r\n" + 
        "user=bob";

    byte[] bytesToSend = Encoding.ASCII.GetBytes(requestString);
    byteCount = socket.Send(bytesToSend, SocketFlags.None);
}
catch (SocketException se)
{
    Console.WriteLine(se.Message);
}

// Attempt to receive the response
if (byteCount > 0)
{
    byte[] bytesReceived = new byte[256];
    try
    {
        byteCount = socket.Receive(bytesReceived, SocketFlags.None);
    }
    catch (Exception e)
    {
        System.Diagnostics.Debug.WriteLine("HELP!! --> " + e.Message);
    }

    // Out the html we received
    string html = Encoding.ASCII.GetString(bytesReceived);
    Console.WriteLine(html);
}
else
{
    Console.WriteLine("byteCount is zero!");
}

Console.Read();

Ответы [ 4 ]

2 голосов
/ 06 декабря 2010

Это перебор просто за то, что вы сделали ПОСТ!Весь ваш код может работать, но при использовании WebClient вызов будет сокращен до пары строк.

Суть TCP-сокетов заключается в том, что вы продолжаете чтение, пока не получите идентификатор для закрытия сеанса.Теперь, когда вы используете HTTP, вы читаете заголовки и находите значение content-length, читаете точную длину байта из потока, и нет идентификатора для закрытия сеанса.

1 голос
/ 06 декабря 2010

Вообще говоря, вы читаете из сокета в цикле, пока не останется никаких данных.Если вы хотите избежать этого, вы можете сначала прочитать кусок, предположительно достаточно большой, чтобы содержать заголовки ответа HTTP, проанализировать строку Content-Length и использовать результат для выделения следующего буфера - но это похоже на боль.

Есть ли причина, по которой вы делаете это на таком низком уровне вместо использования класса WebClient ?

0 голосов
/ 06 декабря 2010

Я поместил вызов Receive в цикл, чтобы продолжать вызывать прием до тех пор, пока полученные байты не станут равны нулю, и добавил данные, возвращенные в строковую переменную.

0 голосов
/ 06 декабря 2010

Возможно, вы захотите проверить значение Content-Length в заголовке ответа.

Кроме того, сервер может отправлять данные, используя кодированную кодированную передачу , которая позволяет ему начать передачу до того, как он узнает фактическую длину (например, для данных, сжатых на лету).

См. Также RFC для протокола HTTP .

...