【问题标题】:How to close a socket left open by a killed program?如何关闭被杀死的程序打开的套接字?
【发布时间】:2011-08-18 00:36:51
【问题描述】:

我有一个 Python 应用程序,它打开一个简单的 TCP 套接字以与单独主机上的另一个 Python 应用程序进行通信。有时程序会出错,或者我会直接杀死它,在这两种情况下,套接字都可能会在未知的时间内保持打开状态。

下次我去运行程序时,我得到了这个错误:

socket.error: [Errno 98] Address already in use

现在程序总是尝试使用同一个端口,所以它看起来好像仍然是打开的。我检查并确定程序没有在后台运行,但我的地址仍在使用中。

那么,我如何手动(或以其他方式)关闭套接字/地址,以便我的程序可以立即重用它?

更新

根据 Mike 的回答,我查看了 socket(7) 页面并查看了 SO_REUSEADDR:

SO_REUSEADDR
    Indicates that the rules used in validating addresses supplied in a bind(2) call should
    allow reuse of local addresses.  For AF_INET sockets this means that a socket may bind,
    except when there is an active listening socket bound to the address.  When the listen‐
    ing  socket is bound to INADDR_ANY with a specific port then it is not possible to bind
    to this port for any local address.  Argument is an integer boolean flag.

【问题讨论】:

  • 对将其移至 SO 有任何反对意见吗?它最终成为一个完全编程问题,所以它可能更有意义
  • 完全没有,我只是在这里发布这个,因为我正在考虑一个Linux命令来关闭套接字,我同意它的编程材料。也许可以更改标题以反映它是一个 Python 程序。
  • @Mr. Shickadance 已迁移,如果您认为有必要,您将不得不改写标题。

标签: python linux sockets networking tcp


【解决方案1】:

假设您的套接字名为s...您需要在绑定到接口之前在服务器的套接字上设置socket.SO_REUSEADDR...这将允许您立即重新启动 TCP 服务器...

s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ADDR, PORT))

【讨论】:

  • 我相信你的意思是setsockopt,我试过了,但还是没有成功。我会在更多测试后报告。
  • @Mr. Shickadance,是的,是setsockopt()...我打错了
  • 我错了,这确实解决了问题……这就是我提到更多测试的原因!在我运行测试之前,我没有推送新的、修改过的代码(不知道我是怎么忘记的)。谢谢!
  • @Mr. Shickadance,不客气……祝你的项目好运
  • 我希望我能不止一次地为一个答案投票!这是救命稻草!
【解决方案2】:

您可能想尝试将 Twisted 用于您的网络。 Mike 给出了正确的低级答案SO_REUSEADDR,但他没有提到在 Windows 上设置这不是一个很好的选择。这是 Twisted 自动为您处理的事情。这种无聊的低级细节还有很多很多其他示例,在直接使用套接字模块时您必须注意这些示例,但如果您使用 Twisted 等更高级别的库,则可能会忘记这些示例。

【讨论】:

  • 在 Windows 上,REUSEADDR 允许一个进程从另一个仍在运行进程接管一个监听端口。
  • 嗯,这是从 unix.stackexchange.com 迁移而来的,所以 windows 可能不是一个大问题。无论如何都是好点。+1
  • 公平地说,您的回答应该是对 Mike 回答的评论。谢谢你的花絮。
【解决方案3】:

您混淆了套接字、连接和端口。套接字是连接的端点,它又是 5 元组 {protocol, local-ip, local-port, remote-ip, remote-port}。被杀死的程序的套接字已被操作系统关闭,连接也是如此。连接的唯一遗物是对等方的套接字和对等主机上的相应端口。所以你真正应该问的是如何重用本地端口。根据其他答案,答案是 SO_REUSEADDR。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 2016-02-14
    • 2017-10-05
    • 1970-01-01
    相关资源
    最近更新 更多