【问题标题】:How long should we wait to check for available data after accepting a connection?接受连接后,我们应该等待多长时间来检查可用数据?
【发布时间】:2016-03-25 01:08:27
【问题描述】:

情况

我们使用以下代码来接受传入的 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);
    }
}

【问题讨论】:

  • 为什么不直接调用 Read 让它阻塞直到数据可用?
  • 我不知道。在这种情况下,Available 是什么?

标签: c# .net sockets .net-micro-framework


【解决方案1】:

通常,您可能需要等待一段时间(想想具有巨大往返时间的蹩脚网络),某些平台上的默认超时为 20 秒!

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

引用documentation(强调我的):

如果您使用的是 非阻塞 Socket,Available 是一个很好的方法 在调用 Receive 之前确定数据是否排队等待读取。 可用数据是网络中排队的数据总量 用于读取的缓冲区。如果网络缓冲区中没有数据排队, 可用返回 0。

【讨论】:

  • 您所说的Read 方法在哪里?
  • 文档没有列出这种方法。 msdn.microsoft.com/en-us/library/…
  • 抱歉,已更新为 Receive,这是 .NET 套接字中的名称。
  • 这种方法的问题在于,我们仍然需要继续接收并检查是否有可用字节(请参阅我的问题的编辑。)也许我可以将其更改为 do-while 循环和请先致电Read
  • 看来你不知道什么时候停止Receiveing。这是您的网络协议的问题。基本上有两种协议设计:(1)特殊字节序列分隔消息的结尾(例如,HTTP 1.X 中的 \r\n\r\n)或(2)固定大小的标头指定消息的结构消息(例如,IP 中的数据包长度)。您尝试实现的网络协议是什么?
猜你喜欢
  • 2017-12-13
  • 2023-03-30
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-11
相关资源
最近更新 更多