windows Socket.Close 并没有真正关闭 tcp 套接字?(C#)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2014887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Socket.Close doesn't really close tcp socket? (c#)
提问by r0u1i
It seems that using socket.Close() for a tcp socket, doesn't fully close the socket. In the following example I'm trying to connect to example.com at port 9999, which is not opened, and after a short-timeout, I'm trying to close the socket.
似乎对 tcp 套接字使用 socket.Close() 并没有完全关闭套接字。在以下示例中,我尝试在未打开的端口 9999 上连接到 example.com,在短暂超时后,我尝试关闭套接字。
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();
}
But when I take a look at netstat after the loop completes, I find that there are many half-opened sockets:
但是当我循环完成后查看netstat时,发现有很多半开的socket:
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
EDIT. Ok, some context was missing. I'm using beginconnect because I expect the socket connection to fail (9999 is not opened), and in my real code, I call the socket.Close() once a timer is set. On OnSocketConnected I call EndConnect, which throws an exception (trying to call a method of a disposed object). My goal is having a short timeout for the socket connection stage.
编辑。好的,缺少一些上下文。我正在使用 beginconnect 是因为我希望套接字连接失败(9999 未打开),并且在我的实际代码中,一旦设置了计时器,我就会调用 socket.Close()。在 OnSocketConnected 上,我调用 EndConnect,它会引发异常(尝试调用已处理对象的方法)。我的目标是为套接字连接阶段设置一个短暂的超时时间。
Any clue what I'm doing wrong? Thanks!
任何线索我做错了什么?谢谢!
回答by Ed Altorfer
By design, you should always call Shutdown
before closing the socket.
根据设计,您应该始终Shutdown
在关闭套接字之前调用。
mySocket.Shutdown(SocketShutdown.Both);
mySocket.Close();
Doing so effectively disables send and receive on the socket, so it will not be accepting incoming data after you've closed it, even if the OS still has control of it.
这样做有效地禁用了套接字上的发送和接收,因此在您关闭它后它不会接受传入的数据,即使操作系统仍然可以控制它。
Jon Skeet also has a point, that since you're opening the connection asynchronously, it may actually be connecting while you're trying to close it. However, if you call Shutdown
on it, it will not allow information to be received as you are experiencing.
Jon Skeet 也有一个观点,因为您是异步打开连接的,所以当您尝试关闭它时,它实际上可能正在连接。但是,如果您调用Shutdown
它,它将不允许您在体验中接收信息。
Edit:You can only Shutdown
a socket that is already connected, so bear this in mind as you write your code.
编辑:您只能Shutdown
使用已连接的套接字,因此在编写代码时请记住这一点。
回答by nos
It will close the .NET part of the socket. However according to the TCP specification the OS have to keep the lower level tidbits of the socket open for a certain amount of time in order to detect retransmission, and similar. In this particular case it's likely keeping the socket around for a bit in order to detect a reply to the SYN packet sent so it can reply more sensibly and not mix up the reply with further packets sent.
它将关闭套接字的 .NET 部分。然而,根据 TCP 规范,操作系统必须将套接字的较低级别的花絮保持打开一段时间,以便检测重传等。在这种特殊情况下,它可能会保留套接字一段时间以检测对发送的 SYN 数据包的回复,以便它可以更明智地回复并且不会将回复与发送的其他数据包混淆。
回答by Jon Skeet
You're calling *Begin*Connect
- so doing it asynchronously. You're quite possibly trying to close the socket before it's even connected - so when it then connects, it remains open.
您正在调用*Begin*Connect
- 所以异步进行。您很可能试图在连接之前关闭套接字 - 因此当它连接时,它保持打开状态。
Try connecting synchronously - or closing it in OnSocketConnected
so you can see the effect of closing a genuinely connected socket.
尝试同步连接 - 或关闭它,OnSocketConnected
以便您可以看到关闭真正连接的套接字的效果。
回答by hase
You are initialising a new Socket in every Loop... with *.close() you close the old and at the begin you are creating a new one with the same parameters as the Socket before.
您正在每个循环中初始化一个新的 Socket... 使用 *.close() 关闭旧的,并在开始时使用与之前的 Socket 相同的参数创建一个新的。