Sockets 如何知道是否有任何进程绑定到Unix域套接字?
我正在为Linux编写一个Unix域套接字服务器 我很快发现Unix域套接字的一个特点是,在创建侦听Unix套接字创建匹配的文件系统条目时,关闭套接字并不会删除它。此外,在手动删除文件系统条目之前,无法将套接字再次Sockets 如何知道是否有任何进程绑定到Unix域套接字?,sockets,unix-socket,Sockets,Unix Socket,我正在为Linux编写一个Unix域套接字服务器 我很快发现Unix域套接字的一个特点是,在创建侦听Unix套接字创建匹配的文件系统条目时,关闭套接字并不会删除它。此外,在手动删除文件系统条目之前,无法将套接字再次bind()绑定到同一路径:bind()如果文件系统中已经存在给定的路径,则会导致EADDRINUSE失败 因此,在服务器关闭时,套接字的文件系统条目需要取消链接(),以避免在服务器重新启动时获得EADDRINUSE。但是,这并不总是可以做到(即:服务器崩溃)。我找到的大多数常见问题解
bind()
绑定到同一路径:bind()
如果文件系统中已经存在给定的路径,则会导致EADDRINUSE
失败
因此,在服务器关闭时,套接字的文件系统条目需要取消链接()
,以避免在服务器重新启动时获得EADDRINUSE
。但是,这并不总是可以做到(即:服务器崩溃)。我找到的大多数常见问题解答、论坛帖子和问答网站都建议在调用bind()
之前先取消套接字的链接(),作为一种解决方法。然而,在这种情况下,在取消链接()之前,需要知道进程是否绑定到此套接字
实际上,unlink()
“在进程仍绑定到Unix套接字时,取消其链接,然后重新创建侦听套接字不会产生任何错误。”。但是,结果是,旧的服务器进程仍在运行,但无法访问:旧的侦听套接字被新的套接字“屏蔽”。必须避免这种行为
理想情况下,使用Unix域套接字时,套接字API应该公开与绑定TCP或UDP套接字时相同的“互斥”行为:“我想将套接字绑定到地址A;如果进程已绑定到此地址,请投诉!”不幸的是,情况并非如此
有没有办法强制执行这种“互斥”行为?或者,给定一个文件系统路径,有没有办法通过套接字API知道系统上的任何进程是否有一个Unix域套接字绑定到此路径?我是否应该使用套接字API外部的同步原语(flock()
,…)?还是我遗漏了什么
谢谢你的建议
注意:Linux的抽象名称空间Unix套接字似乎解决了这个问题,因为
unlink()
没有文件系统条目。然而,我正在编写的服务器旨在实现通用性:它必须对这两种类型的Unix域套接字都具有健壮性,因为我不负责选择侦听地址。除了您已经考虑过的事情之外,我认为没有什么可以做的。你似乎研究得很好
有多种方法可以确定套接字是否绑定到unix套接字(显然是lsof和netstat绑定的),但它们非常复杂,并且依赖于系统,因此我怀疑它们是否值得处理您提出的问题
您确实提出了两个问题—处理与其他应用程序的名称冲突和处理您自己应用程序的以前实例
根据定义,pgm的多个实例不应尝试绑定到同一路径,因此这可能意味着您一次只希望运行一个实例。如果是这种情况,您可以使用标准的pid filelock技术,这样两个实例就不会同时运行。如果无法获得锁,则不应断开现有套接字的链接,甚至不应运行。这也解决了服务器崩溃的情况。如果可以获得锁,那么就知道可以在绑定之前取消现有套接字路径的链接
对于控制其他创建冲突的程序,您可以做的事情不多。文件权限并不完美,但如果您可以使用该选项,您可以将应用程序放在其自己的用户/组中。如果存在一个现有的套接字路径,而您不拥有它,那么不要取消链接并发出错误消息,让用户或系统管理员对其进行排序。使用配置文件使其易于更改(并可供客户端使用)可能会奏效。除此之外,您几乎必须使用某种类型的发现服务,除非这是一个真正关键的应用程序,否则这似乎是一种巨大的过度使用
总的来说,你可以感到安慰的是,这种情况其实并不经常发生。我知道我参加聚会已经很晚了,而且很久以前就得到了答复,但我只是在寻找其他东西时遇到了这种情况,我还有另一个建议 当遇到来自
bind()
的EADDRINUSE
返回时,可以输入连接到套接字的错误检查例程。如果连接成功,则有一个正在运行的进程至少足够活跃,可以执行accept()
。我觉得这是实现你想要的目标的最简单、最便捷的方式。它的缺点在于,最初创建UDS的服务器实际上可能仍在运行,但不知何故“卡住”,无法执行accept()
,因此此解决方案当然不是傻瓜式的,但我认为这是朝着正确方向迈出的一步
如果
connect()
失败,请继续unlink()
端点,然后再次尝试bind()
。谢谢您的回答。无可否认,使用传统的锁文件系统是最安全的方法。另外,关于服务发现系统是否过度使用:具有讽刺意味的是,该服务器本身计划成为服务发现系统的一部分(服务“注册”系统似乎更合适)。这应该回答您的问题;-)我已经测试了这个,它似乎工作的广告。明亮的