C#套接字编程 - 如何确定接收缓冲区的大小

时间:2010-12-06 19:50:43

标签: .net http sockets

我正在尝试编写一个简单的控制台应用程序,该应用程序POST到页面并将返回的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 个答案:

答案 0 :(得分:2)

这只是矫枉过正,只是为了发帖!您的所有代码都可能有效,但使用WebClient会将调用缩减为几行。

TCP套接字的要点是,在收到关闭会话的标识符之前,请继续阅读。现在您正在使用HTTP,这是通过读取标头并查找content-length的值并从流中读取确切的字节长度,并且没有关闭会话的标识符。

答案 1 :(得分:1)

一般来说,你会从循环中的套接字读取,直到没有数据为止。如果你想避免这种情况,你可以先读取一个估计大到足以包含HTTP响应头的块,解析Content-Length行,并使用结果来分配你的下一个缓冲区 - 但这似乎很痛苦

你是否有理由这样做而不是使用WebClient class

答案 2 :(得分:0)

您可能需要检查响应标头中的Content-Length值。

此外,服务器可能正在使用chunked transfer encoding发送数据,这允许它在知道实际长度之前开始发送(例如,对于即时压缩的数据)。

另请参阅RFC for HTTP protocol

答案 3 :(得分:0)

我将Receive调用放在一个循环中以保持调用receive,直到接收到的字节为零并将返回的数据附加到字符串变量中。

工作守则......

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];
    string page = "";
    try
    {
        while (byteCount > 0)
        {
            byteCount = socket.Receive(bytesReceived, SocketFlags.None);
            page += Encoding.ASCII.GetString(bytesReceived);
            Array.Clear(bytesReceived, 0, bytesReceived.Length);
        }
    }
    catch (Exception e)
    {
        System.Diagnostics.Debug.WriteLine("HELP!! --> " + e.Message);
    }

    // Out the html we received
    Console.WriteLine(page);
}
else
{
    Console.WriteLine("byteCount is zero!");
}

Console.Read();