gpt4 book ai didi

sockets - SO_REUSEADDR 和 AF_UNIX

转载 作者:行者123 更新时间:2023-12-01 22:27:12 25 4
gpt4 key购买 nike

事实

在 POSIX 文档中,我看不到任何阻止将 SO_REUSEADDR 套接字选项与 AF_UNIX 一起用于 UNIX 域套接字的情况。

但是,如果套接字节点已经存在,它总是会在绑定(bind)时失败,并且似乎被忽略,并且似乎需要在调用之前首先取消链接文件系统上的套接字节点绑定(bind);简而言之,它不会重用该地址。网络上有很多关于此问题的帖子,但没有一个提供解决方案。

问题

我不会坚持,如果它不起作用,它就不起作用(至少在 BSD 和 Linux 系统上似乎是一样的),只是有一个问题:这是正常行为还是不正常?是否有任何指示表明应该支持它,或者相反,是否有任何指示表明不应支持它?或者这是未指定的?请注意,该问题是在 POSIX 上下文中提出的,而不是在任何特定平台上下文中提出的。

我欢迎任何关于此事的 POSIX 引用。

额外:一个小片段,避免盲目取消链接谁知道什么

我在网络上看到了一些帖子,建议在绑定(bind)之前取消链接任何具有预期名称的节点。我觉得这是不安全的,在这种情况下,应该只取消链接已经是套接字节点的节点:例如。取消链接名为 mysocket 的文本文件以重新创建同名的套接字节点可能是错误的。为此,这里有一个小片段:

/* Create the socket node
* ----------------------
* Note `SO_REUSEADDR` does not work with `AF_UNIX` sockets,
* so we will have to unlink the socket node if it already exists,
* before we bind. For safety, we won't unlink an already existing node
* which is not a socket node.
*/

status = stat (path, &st);
if (status == 0) {
/* A file already exists. Check if this file is a socket node.
* * If yes: unlink it.
* * If no: treat it as an error condition.
*/
if ((st.st_mode & S_IFMT) == S_IFSOCK) {
status = unlink (path);
if (status != 0) {
perror ("Error unlinking the socket node");
exit (1);
}
}
else {
/* We won't unlink to create a socket in place of who-know-what.
* Note: don't use `perror` here, as `status == 0` (this is an
* error we've defined, not an error returned by a system-call).
*/
fprintf (stderr, "The path already exists and is not a socket node.\n");
exit (1);
}
}
else {
if (errno == ENOENT) {
/* No file of the same path: do nothing. */
}
else {
perror ("Error stating the socket node path");
exit (1);
}
}

/* … invoke `bind` here, which will create the socket node … */

最佳答案

我只能访问一份 POSIX 规范文档,即 System Interfaces ,所以我将从这里尽力而为。

我们的规范洞穴探险当然必须从 2.10.6 Use of Options 开始。 ,它定义了 SO_REUSEADDR选项如下:

The SO_REUSEADDR option indicates that the rules used in validating addresses supplied in a bind() should allow reuse of local addresses. Operation of this option is protocol-specific. The default value for SO_REUSEADDR is off; that is, reuse of local addresses is not permitted.

本段基本上通过将其委托(delegate)给底层协议(protocol)的规范来否认此选项真正用途的任何规范。

Section 2.10.17 Use of Sockets for Local UNIX Connections描述了创建 UNIX 域套接字的机制,但实际上它唯一告诉我们的是要使用什么套接字类型常量以及要使用哪个结构体作为地址。 The documentation for the sockaddr_un struct只告诉我们它的格式,而不告诉我们它在 bind 上的行为.

The documentation for bind itself可以理解的是,它与协议(protocol)无关,只告诉我们本地址已被使用时会发生什么,而不是在什么情况下重新绑定(bind)同一套接字是有效的。

虽然它不是 POSIX 标准文档,但富士通有 a document on the POSIX sockets API这很有趣,因为它不是专门针对 Linux 或 BSD 的。本文档第 2.6.4 节对 bind 的行为进行了以下说明在 UNIX 套接字上:

The path name, which must be specified in the sun.sun_path component, is created as a file in the file system using bind(). The process that calls bind() must therefore have write rights to the directory in which the file is to be written. The system does not delete the file. It should therefore be deleted by the process when it is no longer required.

虽然这没有说明 SO_REUSEADDR特别是,它确实指出 bind 的行为是创建一个文件,并且绑定(bind)进程有责任在不再使用它时将其删除。

最后,本文档对setsockopt的描述关于 SO_REUSEADDR 有以下说法:

Specifies that the rules for the validity check on the addresses specified for bind() should permit the reuse of local addresses provided this is supported by the protocol.

虽然这没有具体提及 AF_UNIX ,它确实承认此选项并不适用于所有协议(protocol)。

我还发现了a (non-authoritative) summary describing the intended purpose of SO_REUSEADDR :

This socket option tells the kernel that even if this port is busy (in the TIME_WAIT state), go ahead and reuse it anyway. If it is busy, but with another state, you will still get an address already in use error.

TIME_WAIT状态主要针对面向互联网的套接字而存在,以避免新程序绑定(bind)到最近被另一个程序使用的端口并无意中接收与旧程序相关的数据包。这个问题可以说不适用于 UNIX 域套接字,因为两个程序不太可能尝试在同一路径创建套接字,因此如果 TIME_WAIT未针对 UNIX 套接字实现,那么这可能是原因的一个(近似)解释 SO_REUSEADDR不适用于AF_UNIX .

关于sockets - SO_REUSEADDR 和 AF_UNIX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15716302/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com