关闭和清理 Socket 连接的正确方法是啥?

Posted

技术标签:

【中文标题】关闭和清理 Socket 连接的正确方法是啥?【英文标题】:What is the proper way of closing and cleaning up a Socket connection?关闭和清理 Socket 连接的正确方法是什么? 【发布时间】:2013-02-27 14:17:12 【问题描述】:

我对 Socket 对象上的相关方法的聚宝盆感到有些困惑,这些方法应该关闭和清理套接字连接。考虑以下几点:

var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("192.168.1.22", 8333);
socket.Send(Encoding.UTF8.GetBytes("hello"));

// now for the closing fun
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Close();
socket.Dispose();

另外this guy表示要真正干净地关闭连接,必须执行socket.Shutdown(SocketShudown.Send),然后等待对方响应。

关闭然后清理套接字连接的正确方法是什么?

【问题讨论】:

那家伙说对了一半。我认为这取决于两者之间的协议。如果您希望在一段时间内仍然能够接收,那么可以,您应该告诉对方您打算关闭并说您将停止发送但仍然可以接收。 "that guy" 大部分是正确的,因为我对我的服务器代码进行了类似的建模。但我相信只有异步(非阻塞)套接字才需要半关闭然后等待的方法。我相信在非阻塞套接字的情况下,您调用“发送”后立即关闭,如果有需要重新传输的数据包,可能会发生一些边缘情况。 我对我的套接字服务器使用了混合方法。服务器会先半关闭连接,等待 recv() 返回 0 或错误,表示客户端完成。但是,我有一个计时器,它每 45 秒定期关闭一次,以扫描并关闭自上次扫描以来一直存在的任何半开连接。 使用 TcpClient 有什么办法吗? 【参考方案1】:

关闭套接字关闭连接,而Close是Dispose周围的一个包装方法,所以一般

socket.Shutdown(SocketShutdown.Both);
socket.Close();

应该够了。有些人可能会争辩说,Close 的实现可能有一天会改变(所以它不再调用 Dispose),你应该在调用 Close 之后手动调用 Dispose,但我个人怀疑这会发生:)

或者,考虑使用 using (yeh):

using (var socket = new Socket(...))

    ....
    socket.Shutdown(SocketShutdown.Both);
    socket.Close();

【讨论】:

【参考方案2】:

根据MSDN,对于面向连接的套接字,如果你调用Connect,你应该调用Close。这也适用于BeginConnectConnectAsync

using (var socket = new Socket(...)) 
    socket.Connect(host);
    ...
    socket.Shutdown(SocketShutdown.Both);
    socket.Close();

【讨论】:

以上是关于关闭和清理 Socket 连接的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

IOCP怎么正确关闭socket

如何才能正确的关闭Socket连接

关闭H2的正确方法是啥?

Socket.io - 失败:连接在收到握手响应之前关闭

使用 Spring 和 DBCP 处理 JDBC 连接的正确方法是啥?

IOCP怎么正确关闭socket