SO_REUSEADDR和AF_UNIX(SO_REUSEADDR and AF_UNIX)

2019-08-18 07:22发布

事实

在POSIX文件,我看不到任何东西防止使用的SO_REUSEADDR与socket选项AF_UNIX用于UNIX域套接字。

然而,它总是失败在bind的时间,如果插座节点已经存在,而且似乎被忽略,似乎就需要断开链接的文件系统调用之前首先对插座节点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 … */

Answer 1:

我只能访问一个POSIX规范文件,这是系统接口 ,所以我会尽我所能,从这里开始。

我们的课程的规范洞穴探险冒险必须启动2.10.6使用选项 ,它定义了SO_REUSEADDR选项,如下所示:

SO_REUSEADDR选项指示)在验证以结合(提供的地址使用的规则应该允许本地地址的重复使用。 这个选项的操作是协议特定的。 为SO_REUSEADDR的默认值是关断; 也就是说,本地地址的重复使用是不允许的。

这一段基本上不承担什么该选项真正做任何规范,由它委托给底层协议的规范。

第2.10.17使用套接字本地UNIX联系介绍如何创建UNIX域套接字的机制,但实际上它告诉我们的唯一的事情是什么插槽类型不断使用和使用的地址其结构。 对于文档sockattr_un结构告诉我们,只有它的格式,而不是关注其对行为的bind

对于文档bind本身是可以理解的协议无关,告诉我们当地址已在使用中只发生了什么,而不是在其下再结合同一插座的情况下是有效的。

尽管这不是一个POSIX标准文档,富士通对POSIX套接字API的文档是有趣的,如果仅仅是因为它没有明确关于Linux或BSD。 这个文件的第2.6.4节具有以下要说的行为bind Unix套接字上:

的路径名称,必须在指定sun.sun_path组分,如在文件系统中的文件创建使用bind() 调用进程bind()因此必须有写的权限,并且该文件是要写入的目录。 系统不删除该文件。 因此,应当通过过程中,当不再需要它被删除。

虽然这只字未提SO_REUSEADDR特别,它是国家的行为bind创建一个文件,它是结合过程的责任不再受到使用时将其删除。

最后,这个文件的描述setsockopt有以下谈谈SO_REUSEADDR

指定用于对绑定(指定的地址有效性检查)的规则应允许提供这种本地地址的重用由协议的支持

因此,尽管这使得没有特别提到AF_UNIX ,它承认这个选项并不适用于所有协议。

我还发现描述的预期目的(非授权的)摘要SO_REUSEADDR

这个套接字选项告诉,即使这个端口忙(在内核TIME_WAIT状态),继续前进,反正重用。 如果是忙碌的,但与其他国家,你会仍然在使用错误得到一个地址了。

TIME_WAIT状态对与旧的程序插座,以避免一个新的程序绑定到最近正由另一个程序的端口和接收无意中面向互联网的数据包的存在主要是。 这个问题可以说并不适用于UNIX域套接字,因为它很可能两个方案将试图创建的相同路径的插座,所以如果TIME_WAIT是不是Unix套接字实现,那么这可能是一个(近似)解释为什么SO_REUSEADDR不适用于AF_UNIX



文章来源: SO_REUSEADDR and AF_UNIX