none
为什么TCP Socket.Receive不阻塞,直接返回0字节 RRS feed

  • 问题

  • 使用.NET 4.5 WIN7系统
    很奇怪,在调试的时候发现一个接收数据的线程里面Receive 一直返回0字节造成100%CPU占用率
    代码片段:

    public void Receive()
            {
                byte[] recByteBuffer = new byte[1024];
                int sindex = 0,nindex = 0;
                int rdLength = 0;
                uint dataLength = 0;
                 
                //socket.ReceiveTimeout = 5000;
                while(true)
                {
                    try
                    {
                        rdLength = socket.Receive(recByteBuffer);
                        if (rdLength == 0)
                        {
                            //if (stRemote.Connected == false)
                            //    break; //没有接收到数据
                            //else
                            Thread.Sleep(5);
                                continue;
                        }

    Receive()直接返回0,不是应该没数据0字节不返回而一直阻塞的嘛?


    2012年12月7日 8:43

答案

  • 如果远程主机使用 Shutdown 方法关闭了 Socket 连接,并且所有可用数据均已收到,则 Receive 方法将立即完成并返回零字节。 http://msdn.microsoft.com/zh-cn/library/8s4y8aff(v=vs.80).aspx

    http://feiyun0112.cnblogs.com/

    2012年12月7日 14:28
    版主
  • dear

    这要看你所连接 server 的游戏规则,这没有绝对的控制方式。

    http://msdn.microsoft.com/zh-cn/library/8s4y8aff(v=vs.80).aspx

    Receive 方法将数据读入缓冲区参数,并返回成功读取的字节数。从面向连接的套接字和无连接套接字中都可以调用 Receive

    此重载仅要求您提供接收缓冲区。缓冲区偏移量的默认值为 0,缓冲区的默认大小为缓冲区参数的长度,而 SocketFlags 的默认值为 None

    如果您使用的是面向连接的协议,则在调用 Receive 之前,必须调用 Connect 以建立远程主机连接,或者调用 Accept 以接受传入的连接。Receive 方法只读取在 Connect 或 Accept 方法中建立的远程主机发送的数据。如果当前使用的是无连接协议,则还可以使用 ReceiveFrom 方法。ReceiveFrom 将允许您接收来自任何主机的数据。

    如果没有可读取的数据,则 Receive 方法将一直处于阻止状态,直到数据可用,除非使用 Socket.ReceiveTimeout 设置了超时值。如果超过超时值,Receive 调用将引发 SocketException。如果您处于非阻止模式,并且协议堆栈缓冲区中没有可用的数据,则 Receive 方法将立即完成并引发 SocketException。您可以使用 Available 属性确定是否有数据可以读取。如果 Available 为非零,请重试接收操作。

    如果当前使用的是面向连接的 Socket,那么 Receive 方法将会读取所有可用的数据,直到达到缓冲区的大小为止。如果远程主机使用 Shutdown 方法关闭了 Socket 连接,并且所有可用数据均已收到,则 Receive 方法将立即完成并返回零字节。

    如果您使用的是无连接 Socket,则 Receive 将从您在 Connect 方法中指定的目标地址处读取第一个排队的数据报。如果您接收到的数据报大于 buffer 参数的大小,则 buffer 将用消息的第一部分填充,多余的数据都会丢失,并且会引发 SocketException


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    2012年12月8日 16:27

全部回复

  • 如果远程主机使用 Shutdown 方法关闭了 Socket 连接,并且所有可用数据均已收到,则 Receive 方法将立即完成并返回零字节。 http://msdn.microsoft.com/zh-cn/library/8s4y8aff(v=vs.80).aspx

    http://feiyun0112.cnblogs.com/

    2012年12月7日 14:28
    版主
  • dear

    这要看你所连接 server 的游戏规则,这没有绝对的控制方式。

    http://msdn.microsoft.com/zh-cn/library/8s4y8aff(v=vs.80).aspx

    Receive 方法将数据读入缓冲区参数,并返回成功读取的字节数。从面向连接的套接字和无连接套接字中都可以调用 Receive

    此重载仅要求您提供接收缓冲区。缓冲区偏移量的默认值为 0,缓冲区的默认大小为缓冲区参数的长度,而 SocketFlags 的默认值为 None

    如果您使用的是面向连接的协议,则在调用 Receive 之前,必须调用 Connect 以建立远程主机连接,或者调用 Accept 以接受传入的连接。Receive 方法只读取在 Connect 或 Accept 方法中建立的远程主机发送的数据。如果当前使用的是无连接协议,则还可以使用 ReceiveFrom 方法。ReceiveFrom 将允许您接收来自任何主机的数据。

    如果没有可读取的数据,则 Receive 方法将一直处于阻止状态,直到数据可用,除非使用 Socket.ReceiveTimeout 设置了超时值。如果超过超时值,Receive 调用将引发 SocketException。如果您处于非阻止模式,并且协议堆栈缓冲区中没有可用的数据,则 Receive 方法将立即完成并引发 SocketException。您可以使用 Available 属性确定是否有数据可以读取。如果 Available 为非零,请重试接收操作。

    如果当前使用的是面向连接的 Socket,那么 Receive 方法将会读取所有可用的数据,直到达到缓冲区的大小为止。如果远程主机使用 Shutdown 方法关闭了 Socket 连接,并且所有可用数据均已收到,则 Receive 方法将立即完成并返回零字节。

    如果您使用的是无连接 Socket,则 Receive 将从您在 Connect 方法中指定的目标地址处读取第一个排队的数据报。如果您接收到的数据报大于 buffer 参数的大小,则 buffer 将用消息的第一部分填充,多余的数据都会丢失,并且会引发 SocketException


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/

    2012年12月8日 16:27