Socket.Close不真正closuresTCP套接字? (C#)

看来,使用socket.Close()为一个TCP套接字,并没有完全closures套接字。 在下面的例子中,我试图连接到端口9999的example.com,它不是打开的,在短暂的超时之后,我试图closures套接字。

for (int i = 0; i < 200; i++) { Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.LingerState = new LingerOption(false, 0); sock.BeginConnect("www.example.com", 9999, OnSocketConnected, sock); System.Threading.Thread.Sleep(50); sock.Close(); } 

但是当我在循环完成后看看netstat时,我发现有很多半打开的套接字:

  TCP israel-xp:6506 www.example.com:9999 SYN_SENT TCP israel-xp:6507 www.example.com:9999 SYN_SENT TCP israel-xp:6508 www.example.com:9999 SYN_SENT TCP israel-xp:6509 www.example.com:9999 SYN_SENT 

编辑 。 好吧,一些情况下失踪了。 我正在使用beginconnect,因为我期望套接字连接失败(9999未打开),在我的真实代码中,一旦定时器被设置,我就调用socket.Close()。 OnSocketConnected我调用EndConnect,它引发exception(试图调用一个处置对象的方法)。 我的目标是有一个短暂的套接字连接阶段。

任何线索我做错了什么? 谢谢!

它将关闭套接字的.NET部分。 然而,根据TCP规范,为了检测重传,操作系统必须保持套接字的较低级别信息点打开一定的时间,等等。 在这种情况下,为了检测对发送的SYN数据包的回复,可能需要稍微保留一下套接字,以便它可以更明智地回复,而不会与发送的其他数据包混淆在一起。

按照设计,在关闭套接字之前,您应该始终调用Shutdown

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

这样做可以有效地禁用套接字上的发送和接收,因此,即使操作系统仍然可以控制它,关闭后也不会接收传入的数据。

Jon Skeet也有一个观点,即你打开连接异步,它可能实际上是连接,而你试图关闭它。 但是,如果您打电话Shutdown ,它将不会允许您收到的信息正在经历。

编辑:你只能Shutdown一个已经连接的套接字,所以当你写代码的时候记住这一点。

你打电话*Begin*Connect – 这样做是异步的。 你甚至可能试图在连接之前关闭套接字 – 所以当它连接时,它仍然是打开的。

尝试连接同步 – 或关闭它在OnSocketConnected所以你可以看到关闭一个真正连接的套接字的效果。

您正在初始化每个循环中的一个新的套接字…使用* .close()关闭旧套接字,并在开始时创建一个与之前的套接字参数相同的新套接字。