Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 如何知道是否有任何进程绑定到Unix域套接字?_Sockets_Unix Socket - Fatal编程技术网

Sockets 如何知道是否有任何进程绑定到Unix域套接字?

Sockets 如何知道是否有任何进程绑定到Unix域套接字?,sockets,unix-socket,Sockets,Unix Socket,我正在为Linux编写一个Unix域套接字服务器 我很快发现Unix域套接字的一个特点是,在创建侦听Unix套接字创建匹配的文件系统条目时,关闭套接字并不会删除它。此外,在手动删除文件系统条目之前,无法将套接字再次bind()绑定到同一路径:bind()如果文件系统中已经存在给定的路径,则会导致EADDRINUSE失败 因此,在服务器关闭时,套接字的文件系统条目需要取消链接(),以避免在服务器重新启动时获得EADDRINUSE。但是,这并不总是可以做到(即:服务器崩溃)。我找到的大多数常见问题解

我正在为Linux编写一个Unix域套接字服务器

我很快发现Unix域套接字的一个特点是,在创建侦听Unix套接字创建匹配的文件系统条目时,关闭套接字并不会删除它。此外,在手动删除文件系统条目之前,无法将套接字再次
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()

谢谢您的回答。无可否认,使用传统的锁文件系统是最安全的方法。另外,关于服务发现系统是否过度使用:具有讽刺意味的是,该服务器本身计划成为服务发现系统的一部分(服务“注册”系统似乎更合适)。这应该回答您的问题;-)我已经测试了这个,它似乎工作的广告。明亮的