SO_REUSEADDR和AF_UNIX [英] SO_REUSEADDR and AF_UNIX

查看:115
本文介绍了SO_REUSEADDR和AF_UNIX的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在POSIX文档中,看不到任何阻止SO_REUSEADDR套接字选项与AF_UNIX一起用于UNIX域套接字的信息.

In the POSIX documentation, I can't see anything preventing the use of the SO_REUSEADDR socket option with AF_UNIX for UNIX Domain Sockets.

但是,如果套接字节点已经存在,它总是在bind时失败,并且似乎被忽略,并且似乎需要在调用bind之前先取消链接文件系统上的套接字节点.简而言之,它不会重用地址.网路上有很多关于这个问题的主题,却没有解决的方法.

However, it invariably fails at bind time if the socket node already exists, and seems to be ignored and seems it is required to unlink the socket node on the file‑system first prior to invoke bind; in short, it does not reuse the address. There are plenty of threads on the web about this issue, and none with a solution.

我不会坚持认为,如果它不起作用,那么它将不起作用(至少在BSD和Linux系统上似乎是相同的),只是有一个问题:这是正常现象吗?是否有任何建议应支持它的指针,或者相反,有任何建议不应该支持它的指针?还是未指定?请注意,该问题是在POSIX上下文中提出的,而不是在任何特定的平台上下文中提出的.

I won't insist, if it doesn't work, it doesn't work (seems to be the same at least on both BSD and Linux systems), and just have a question: is this normal behaviour or not? Is there any pointers suggesting it should be supported, or on the opposite, any pointers suggesting it should not? Or is this unspecified? Note the question is asked in the POSIX context, not in any particular platform context.

我对此事欢迎任何POSIX参考.

I welcome any POSIX reference on the matter.

我在网上看到一些线程,建议unlinkbind之前的任何具有期望名称的节点.我觉得这是不安全的,在这种情况下,只能取消链接已经是套接字节点的节点:例如.取消链接名为mysocket的文本文件以重新创建具有相同名称的套接字节点,可能是错误的.为此,下面是一个小片段:

I've seen some threads on the web, suggesting to unlink any node of the expected name prior to bind. I feel it's unsafe, and one should only unlink a node which is already a socket node in this case: ex. it's probably wrong, to unlink a text file named mysocket to recreate a socket node of the same name in place. In this purpose, here is a tiny snippet:

/* 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规范文档,该文档是

I only have access to one POSIX specification document, which is System Interfaces, so I'm going to do my best from here.

我们的规范冒险之旅当然必须始于 2.10.6选项的使用 ,它对SO_REUSEADDR选项的定义如下:

Our specification spelunking adventure must of course start in 2.10.6 Use of Options, which defines the SO_REUSEADDR option as follows:

SO_REUSEADDR选项指示用于验证bind()中提供的地址的规则应允许重用本地地址.此选项的操作是特定于协议的. SO_REUSEADDR的默认值是off;也就是说,不允许重复使用本地地址.

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.

通过将其委托给基础协议的规范,该段落基本上不声明该选项真正起作用的任何规范.

This paragraph basically disclaims any specification of what this option truly does, by delegating it to the specification of the underlying protocol.

第2.10.17节将套接字用于本地UNIX连接" 描述了以下机制:创建UNIX域套接字,但实际上它唯一告诉我们的是要使用的套接字类型常量和用于地址的结构. sockattr_un结构的文档仅告诉我们其格式,而不是其格式bind上的行为.

Section 2.10.17 Use of Sockets for Local UNIX Connections describes the mechanics of creating UNIX domain sockets, but really the only thing it tells us is what socket type constant to use and which struct to use for addresses. The documentation for the sockattr_un struct tells us only about its format, not about its behavior on bind.

bind本身的文档可以理解为协议无关,这告诉我们仅当地址已被使用时会发生什么,而不是在重新绑定同一套接字的情况下有效.

The documentation for bind itself is understandably protocol-agnostic, telling us only what happens when the address is already in use, not the circumstances under which re-binding the same socket is valid.

Fujitsu虽然它不是POSIX标准文档,但有关POSIX套接字API的文档仅仅是因为它与Linux或BSD无关,才很有意思.本文档的第2.6.4节对UNIX套接字上bind的行为有以下说法:

Although it's not a POSIX standard document, Fujitsu has a document on the POSIX sockets API which is interesting if only because it's not specifically about Linux or BSD. Section 2.6.4 of this document has the following to say about the behavior of bind on UNIX sockets:

必须使用bind()在文件系统中的文件中创建必须在sun.sun_path组件中指定的路径名​​.因此,调用bind()的进程必须对要在其中写入文件的目录具有写权限.系统不会删除该文件.因此,当不再需要它时,应将其删除.

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的行为是 create 一个文件,并且绑定过程有责任删除它当它不再被使用时.

Although this says nothing about SO_REUSEADDR in particular, it does state that the behavior of bind is to create a file, and that it is the responsibility of the binding process to remove it when it's no longer being used.

最后,本文档对setsockopt的描述中对SO_REUSEADDR的描述如下:

Finally, this document's description of setsockopt has the following to say about SO_REUSEADDR:

指定在为bind()指定的地址上进行有效性检查的规​​则应允许重用本地地址前提是协议支持.

因此,尽管这里没有具体提及AF_UNIX,但它确实承认该选项并不适用于所有协议.

So while this makes no specific mention of AF_UNIX, it does acknowledge that this option doesn't apply to all protocols.

我还找到了一个(非权威性的)摘要,该摘要描述了预期的目的SO_REUSEADDR :

I also found a (non-authoritative) summary describing the intended purpose of SO_REUSEADDR:

此套接字选项告诉内核,即使此端口繁忙(处于TIME_WAIT状态),也可以继续使用并重新使用它.如果很忙,但是处于另一种状态,您仍然会得到一个已经在使用中的地址错误.

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状态主要存在于面向Internet的套接字上,以避免新程序绑定到另一个程序最近正在使用的端口,并且无意间接收了与旧程序有关的数据包.该问题可以说不适用于UNIX域套接字,因为两个程序不太可能尝试在同一路径上创建套接字,因此,如果未为UNIX套接字实现TIME_WAIT,则可能是一个(近似)解释为什么SO_REUSEADDR不适用于AF_UNIX.

The TIME_WAIT state exists primarily for Internet-facing sockets to avoid a new program binding to a port that was recently being used by another program and inadvertently receiving packets relating to the old program. This problem is arguably not applicable to UNIX domain sockets because it's very unlikely that two programs would attempt to create a socket at the same path, so if TIME_WAIT is not implemented for UNIX sockets then that could be one (approximation of an) explanation for why SO_REUSEADDR does not apply to AF_UNIX.

这篇关于SO_REUSEADDR和AF_UNIX的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆