问题描述
在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.
我在网上看到一些线程,建议unlink
在bind
之前的任何具有期望名称的节点.我觉得这是不安全的,在这种情况下,只能取消链接已经是套接字节点的节点:例如.取消链接名为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:
通过将其委托给基础协议的规范,该段落基本上不声明该选项真正起作用的任何规范.
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:
尽管这没有特别说明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
:
因此,尽管这里没有具体提及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
状态主要存在于面向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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!