【问题标题】:C# Socket Programming - How to determine the size of the receive bufferC# Socket 编程 - 如何确定接收缓冲区的大小
【发布时间】:2010-12-06 19:50:43
【问题描述】:

我正在尝试编写一个简单的控制台应用程序,它可以发布到页面并将返回的 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();

【问题讨论】:

    标签: .net http sockets


    【解决方案1】:

    这只是发一个帖子矫枉过正!您的所有代码都可能有效,但使用 WebClient 将使调用减少到几行。

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

    【讨论】:

    • 我强迫自己使用 Sockets 类。
    • 还不错,但工作量很大,而且水平很低。您还将接触到套接字可能发生的许多问题,并且已经由更高级别的类处理。
    • 我同意,但在这件事上我别无选择:) 这只是玩弄代码,不是什么严重的事情。感谢您的意见!
    【解决方案2】:

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

    您是否有理由在如此低的级别上执行此操作而不是使用WebClient class

    【讨论】:

    • 我知道我可以使用 WebClient 或 HttpWebRequest 轻松做到这一点,但我强迫自己使用 Socket 类。
    【解决方案3】:

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

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

    另请参阅RFC for HTTP protocol

    【讨论】:

    • 这似乎是一种可行的方法,但我找到了一种无需检查内容长度的方法。感谢您的帮助!
    【解决方案4】:

    我将 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();
    

    【讨论】:

      猜你喜欢
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-15
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 2015-03-18
      相关资源
      最近更新 更多