我有一个程序有时会忘记关闭 TCP 连接。
程序结束后,我可以看到端口已被占用。TCPViewer 在“进程”列中显示“不存在”。
如果我尝试“结束进程”或“关闭连接”,什么也不会发生。
如果我重启服务器,端口就会被释放。但是我怎样才能告诉 Windows 释放这个端口而不重启呢?
解决方案:是 dw20.exe(Microsoft 错误报告)阻碍了它。
答案1
当一个进程退出时,操作系统会自动关闭所有的TCP连接1。
您看到的可能是处于 TIME-WAIT 状态的连接(“......表示等待足够的时间以确保远程对等方收到其连接终止请求的确认”)。
这应该不是这对客户端来说是一个问题,因为主机可以与同一个远程主机:端口建立多个 TCP 连接。
对于服务器,可以使用SO_REUSEADDR。
SO_REUSEADDR 到底起什么作用?
此套接字选项告诉内核,即使此端口繁忙(处于 TIME_WAIT 状态),也请继续重用它。如果它繁忙,但处于其他状态,您仍会收到地址已在使用中的错误。如果您的服务器已关闭,然后在其端口上的套接字仍处于活动状态时立即重新启动,则此功能很有用。您应该知道,如果有任何意外数据进入,可能会使您的服务器感到困惑,但尽管这种情况是可能的,但可能性不大。
有人指出,“套接字是一个 5 元组(proto、本地地址、本地端口、远程地址、远程端口)。SO_REUSEADDR 只是表示您可以重用本地地址。5 元组仍然必须是唯一的!”作者:Michael Hunter([电子邮件保护])。这是真的,这就是为什么您的服务器不太可能看到意外数据的原因。危险在于,这样的 5 元组仍然在网络上浮动,当它四处浮动时,来自同一客户端、同一系统的新连接恰好会获得相同的远程端口。Richard Stevens 在“2.7 请解释 TIME_WAIT 状态”中对此进行了解释。
另请参阅此 StackOverflow 答案:使用 SO_REUSEADDR-之前打开的套接字会发生什么?
1从技术上讲,当该连接的所有句柄都被销毁时。多个进程可能拥有一个文件句柄。