我正在为 Linux 编写一个 Unix 域套接字服务器。
我很快发现 Unix 域套接字的一个特点是,虽然创建侦听 Unix 套接字会创建匹配的文件系统条目,但关闭套接字并不会删除它。此外,在手动删除文件系统条目之前,不可能bind()
再次将套接字连接到同一路径:bind()
失败了EADDRINUSE
如果给定的路径已存在于文件系统中。
因此,套接字的文件系统条目需要unlink()
'ed 在服务器关闭以避免得到EADDRINUSE
服务器重新启动时。然而,这并不总是能够做到(即:服务器崩溃)。我发现的大多数常见问题解答、论坛帖子、问答网站仅建议作为解决方法unlink()
调用之前的套接字bind()
。然而,在这种情况下,需要先知道进程是否绑定到该套接字unlink()
'ing it.
Indeed, unlink()
当进程仍绑定到 Unix 套接字时,然后重新创建侦听套接字不会引发任何错误。然而,结果是旧的服务器进程仍在运行但无法访问:旧的监听套接字被新的监听套接字“屏蔽”。必须避免这种行为。
理想情况下,使用 Unix 域套接字,套接字 API 应该暴露与绑定 TCP 或 UDP 套接字时暴露的相同“互斥”行为:“我想将套接字S绑定到地址A;如果一个进程已经绑定到这个地址,就抱怨吧!“ 不幸的是,这种情况并非如此...
有没有办法强制执行这种“互斥”行为?或者,给定一个文件系统路径,有没有办法知道,via套接字API,系统上是否有任何进程具有绑定到此路径的Unix域套接字?我应该使用套接字 API 外部的同步原语(flock()
,...)?或者我错过了什么?
感谢您的建议。
注意:Linux 的抽象命名空间 Unix 套接字似乎解决了这个问题,因为没有文件系统条目可以访问unlink()
。然而,我正在编写的服务器的目标是通用的:它必须对两种类型的 Unix 域套接字都具有鲁棒性,因为我不负责选择侦听地址。
我知道我参加聚会已经很晚了,而且这个问题很久以前就得到了回答,但我只是在寻找其他东西时遇到了这个问题,我有一个替代提案。
当你遇到EADDRINUSE
从返回bind()
您可以输入连接到套接字的错误检查例程。如果连接成功,则有一个正在运行的进程至少足够活跃以完成以下操作accept()
。我认为这是实现您想要实现的目标的最简单且最便携的方式。它的缺点是,首先创建 UDS 的服务器实际上可能仍在运行,但以某种方式“卡住”并且无法执行操作accept()
,所以这个解决方案当然不是万无一失的,但我认为这是朝着正确方向迈出的一步。
If the connect()
失败然后继续unlink()
端点并尝试bind()
again.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)