即使在客户端ShutDown()之后,Socket.Receive也会阻塞

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了即使在客户端ShutDown()之后,Socket.Receive也会阻塞相关的知识,希望对你有一定的参考价值。

我有一个带套接字监听的服务器应用程序:

server = new TcpListener(myEndPoint);

// etc.

socket = server.AcceptSocket();

while (true) {

    int size = socket.Receive(data); // application waits here for data.

    if (size == 0)
    {
        // handle disconnect
    }
    else
    {
        // process data.
    }
}

现在客户端应用程序连接到此...

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

socket.Connect(remoteIp, remotePort);

发送数据,完成后调用

socket.ShutDown(SocketShutdown.Both);

在这一点上,我希望服务器,在socket.Receive(data)阻止继续,但size为0。

根据此页面:

https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receive?view=netframework-4.7.2

如果远程主机使用Shutdown方法关闭Socket连接,并且已收到所有可用数据,则Receive方法将立即完成并返回零字节。

但它只是在这里永远等待。

有趣的是,如果我用PuTTY连接到服务器应用程序,然后关闭PuTTY,那么Receive()方法确实完成并返回size = 0.什么是PuTTY做的我不是?

注意:我也尝试在客户端应用程序上使用TcpClient,但这也有同样的问题。

答案

事实证明这是我的错,我会留在这里以防万一其他人有同样的问题。

在尝试Minu的建议时,我注意到如果我在没有发送数据的情况下关闭套接字,那么Receive()就能正确完成。

事实证明,在我的代码中的其他地方,我让服务器在收到完成的数据后发回确认。但是,客户端收到确认的方法有一个错误导致它不能从套接字中完全接收它,因此套接字上仍有7个字节的Available,这就是它没有关闭的原因。

以上是关于即使在客户端ShutDown()之后,Socket.Receive也会阻塞的主要内容,如果未能解决你的问题,请参考以下文章

socket中close()和shutdown()区别

socket.shutdown 与 socket.close

Linux上TCP的shutdown/close

u3d局域网游戏网络(c# socket select 模型)

c调用 socket 如果客户端连接断开,怎么判断? 还有怎么向多个 连接在一个服务器上的多个客户

Socket之shutdown()用法