接受连接后我们应该等待多长时间来检查可用数据?

How long should we wait to check for available data after accepting a connection?

情况

我们正在使用以下代码来接受传入的 HTTP 请求。

var localEndPoint = new IPEndPoint(IPAddress.Any, Port);

var serverSocket = new Socket(
    AddressFamily.InterNetwork,
    SocketType.Stream,
    ProtocolType.Tcp);

serverSocket.Bind(localEndPoint);
serverSocket.Listen(backlog: 25);

while (true)
{
    using (var clientSocket = serverSocket.Accept())
    {
        if (clientSocket.Available > 0)
        {
            var builder = new StringBuilder();

            while (clientSocket.Available > 0)
            {
                var currentBytes = new byte[clientSocket.Available];
                var bytesReceived = clientSocket.Receive(currentBytes);

                var currentBytesString = 
                    new string(Encoding.UTF8.GetChars(currentBytes));

                builder.Append(currentBytesString);
            }
        }
    }
}

问题

有时即使连接有数据,clientSocket.Available 仍为零。我们实现的解决方案是接受连接后等待,然后再检查数据是否可用。我们这样做:

var start = DateTime.Now;
var duration = new TimeSpan(0);
while (clientSocket.Available <= 0 || duration.Milliseconds < 1000)
{
    duration = DateTime.Now - start;
    Thread.Sleep(100);
}

问题

接受连接后,我们需要等待多长时间才能在套接字中使用连接数据?

工作解决方案

感谢 szym 为这种方法提供的灵感。它现在正在工作。

while (true)
{
    using (var clientSocket = serverSocket.Accept())
    {
        var builder = new StringBuilder();

        do
        {
            var currentBytes = new byte[50];
            var bytesReceived = clientSocket.Receive(currentBytes);

            var currentBytesString = 
                new string(Encoding.UTF8.GetChars(currentBytes));

            builder.Append(currentBytesString);
        }
        while (clientSocket.Available > 0);
    }
}

一般来说,您可能需要等待一段时间(想想糟糕的网络,往返时间很长),某些平台上的默认超时是 20 秒!

然而,在睡眠循环中检查 Available 的方法是 轮询 并且浪费 CPU。您应该在 Receive 上阻塞,它只会等待数据到达(如果您需要处理多个连接,可能会产生一个线程),或者使用非阻塞方法。

引用 documentation(强调我的):

If you are using a non-blocking Socket, Available is a good way to determine whether data is queued for reading, before calling Receive. The available data is the total amount of data queued in the network buffer for reading. If no data is queued in the network buffer, Available returns 0.