SO_REUSEADDR和AF_UNIX。

问题描述 投票:23回答:1

事实上

在POSIX文档中,我看不出有什么东西可以阻止使用 SO_REUSEADDR 插座选项,带 AF_UNIX 的UNIX域套接字。

然而,它总是在 bind 的时候,如果socket节点已经存在,似乎会被忽略,而且似乎需要在调用 bind;简而言之,它不会重复使用地址。网上有很多关于这个问题的帖子,但都没有找到解决办法。

问题是

我也不坚持,不行就不行(至少在BSD和Linux系统上好像都一样),只是有一个问题:这到底是不是正常的行为?有没有什么指针表明应该支持,或者反过来说,有没有什么指针表明不应该支持?还是没有说明?请注意,这个问题是在POSIX上下文中提出的,而不是在任何特定的平台上下文中提出的。

我欢迎任何关于这个问题的POSIX参考。

号外:一个小小的片段,不要盲目的进行 unlink 不知道什么

我在网络上看到一些帖子,建议要。unlink 之前的任何一个预期名称的节点。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 … */
sockets unix posix
1个回答
32
投票

我只有一个POSIX规范文档,那就是 系统接口所以我打算从这里开始尽力而为。

我们规范的洞穴探险当然要从这里开始 2.10.6 选择权的使用,它定义了 SO_REUSEADDR 选项的内容如下。

SO_REUSEADDR选项表明,在验证bind()提供的地址时使用的规则应允许重用本地地址。这个选项的操作是针对协议的。SO_REUSEADDR的默认值是关闭,也就是说,不允许重用本地地址。

本段基本上不对这个选项的真正作用进行任何说明,而是将其委托给底层协议的规范。

第2.10.17节 本地UNIX连接的套接字的用途 描述了创建UNIX域套接字的机制,但实际上它只告诉我们使用什么套接字类型的常量和使用哪个结构作为地址。的文档,但实际上它只告诉我们使用什么样的套接字类型常量和使用哪个结构来表示地址。sockaddr_un 结构 只告诉我们它的格式,而不告诉我们它的行为在 bind.

文件 bind 本身 是可以理解的协议无关性的,它只告诉我们当地址已经在使用时发生了什么,而不是告诉我们在什么情况下重新绑定同一个socket是有效的。

虽然它不是POSIX标准文档,但富士通公司已经 POSIX套接字API的文档 这很有意思,因为它不是专门针对 Linux 或 BSD 的。本文档第2.6.4节对以下行为做了说明 bind 在UNIX套接字上。

路径名必须在 sun.sun_path 组件,在文件系统中以文件形式创建,使用 bind(). 呼叫的过程 bind() 因此,必须有写入文件所在目录的写权限。系统不会删除该文件。因此,当不再需要它的时候,它应该被进程删除。

虽然这并没有说明 SO_REUSEADDR 特别是,它确实说明了以下行为 bind 是为了 创造 的文件,并且当它不再被使用时,绑定过程有责任将其删除。

最后,本文档对 setsockopt 有如下说法 SO_REUSEADDR:

指定为bind()指定的地址的有效性检查规则应允许重用本地地址。只要协议支持.

因此,虽然这没有具体提到 AF_UNIX,它 是否 承认这个选项并不适用于所有协议。

我还发现 (非权威性的)摘要,描述 预期 目的 SO_REUSEADDR:

这个套接字选项告诉内核,即使这个端口处于繁忙状态(在 TIME_WAIT 状态),无论如何都要继续重用它。 如果它很忙,但有另一个状态,你还是会得到一个已经在使用的地址错误。

忙的时候,你还是会得到一个已经在使用中的地址错误。TIME_WAIT 状态主要存在于面向Internet的套接字,以避免新程序绑定到一个最近被另一个程序使用的端口,而无意中接收到与旧程序有关的数据包。这个问题可以说不适用于UNIX域套接字,因为两个程序试图在同一路径上创建一个套接字的可能性很小,所以如果 TIME_WAIT 没有为UNIX套接字实现,那么这可能是解释为什么 SO_REUSEADDR 不适用于 AF_UNIX.

© www.soinside.com 2019 - 2024. All rights reserved.