有没有TcpClient.Close或Socket.Close(0)可以阻止我的代码的情况?

时间:2014-09-12 15:02:35

标签: c# sockets tcpclient

由于没有指定Close方法是线程安全的,我应该从锁中调用它。我怎么能确定它不会阻止我的线程?我应该禁用LingerState还是可以启用它?

btw我是否需要同时调用TcpClient.Close和TcpClient.Client.Close?

1 个答案:

答案 0 :(得分:2)

根据documentation for TcpClient.Close,调用此方法会释放实例。快速查看ILSpy可以看出它只是调用Dispose,调用Dispose(true)

此外,文档指出调用Close也会处理基础Socket

事实上,在处置Socket之前,它会调用Shutdown(SocketShutdown.Both)

鉴于.NET套接字是Windows套接字的包装器,还调用shutdown函数,其文档说明:

  

注意无论套接字上的SO_LINGER设置如何,关闭功能都不会阻止。

但是,Socket重载其Close方法以接受超时参数,类似于TcpClientSocket.Close方法调用{{ 1}},它使用 timeout 值来确定它是否可以阻止。

根据documentation for Socket.Close(int)

  

如果您需要在不先调用Shutdown的情况下调用Close,则可以通过将DontLinger选项设置为false并指定非零超时间隔来确保排队等待传出传输的数据。然后关闭将阻止,直到发送此数据或直到指定的超时到期为止。如果将DontLinger设置为false并指定零超时间隔,则Close会释放连接并自动丢弃传出的排队数据。

显然,Socket.Dispose(true)TcpClient都不会将超时值作为可设置属性公开给您,默认值不是Socket;因此,为了避免阻止,您必须在致电0之前自己致电Socket.Close(0)

请注意,TcpClient.Close也可以抛出Close,尽管框架设计指南的建议是永远不会打电话给SocketException。也许这就是为什么它被命名为DisposeClose明确实现TcpClient方法的原因之一。