AF_UNIX本地数据报套接字的自动命名?

JB.*_*JB. 5 unix sockets bind datagram local

我正在使用unix本地套接字上的数据报实现一个简单的服务(AF_UNIX地址系列,即不是UDP).服务器绑定到公共地址,它接收请求就好了.不幸的是,当谈到回复时,sendto除非客户端也被绑定,否则失败.(常见的错误是Transport endpoint is not connected).

绑定到一些随机名称(基于文件系统或抽象)的工作.但我想避免这种情况:我是谁保证我选择的名字不会碰撞?

unix套接字的流模式文档告诉我们,connect如果它们还没有抽象名称,那么它们将在时间分配给它们.这种功能是否适用于面向数据报的套接字?

小智 5

我引用的unix(7)手册页有关于autobind UNIX套接字的信息:

如果bind(2)调用将addrlen指定为sizeof(sa_family_t),或者为未明确绑定到地址的套接字指定了SO_PASSCRED套接字选项,则套接字将自动生成为抽象地址.

这就是Linux内核检查地址长度等于sizeof(short)的原因,因为sa_family_t是一个简短的.Rob的优秀答案引用的另一个unix(7)手册页说客户端套接字总是在连接上自动响应,但由于SOCK_DGRAM套接字是无连接的(尽管在它们上面调用了连接),我相信这只适用于SOCK_STREAM套接字.

另请注意,在提供自己的抽象命名空间套接字名称时,此命名空间中的套接字地址由sun_path中指定长度的地址结构所覆盖的其他字节给出.

struct sockaddr_un me;
const char name[] = "\0myabstractsocket";
me.sun_family = AF_UNIX;
// size-1 because abstract socket names are not null terminated
memcpy(me.sun_path, name, sizeof(name) - 1);
int result = bind(fd, (void*)&me, sizeof(me.sun_family) + sizeof(name) - 1);
Run Code Online (Sandbox Code Playgroud)

sendto()同样应该限制地址长度,而不是传递sizeof(sockaddr_un).


Rob*_*obᵩ 4

我假设你运行的是Linux;我不知道这个建议是否适用于 SunOS 或任何 UNIX。

\n\n

首先,答案:在 socket() 之后和 connect() 或第一个 sendto() 之前,尝试添加以下代码:

\n\n
struct sockaddr_un me;\nme.sun_family = AF_UNIX;\nint result = bind(fd, (void*)&me, sizeof(short));\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,解释一下:unix (7)手册页是这样说的:

\n\n
\n

当连接套接字并且它\n 没有\xe2\x80\x99\n 已有本地地址时\n 将自动生成\n 抽象命名空间中的唯一地址。

\n
\n\n

可悲的是,手册页撒了谎。

\n\n

检查Linux源代码,我们发现只有在套接字标志中设置了SOCK_PASSCRED时,unix_dgram_connect()才会调用unix_autobind()。因为我不知道 SOCK_PASSCRED 是什么,而且现在是凌晨 1:00,所以我需要寻找另一个解决方案。

\n\n

检查unix_bind,我注意到如果传入的大小等于“sizeof(short)”,则 unix_bind 调用 unix_autobind 。于是就有了上面的解决方案。

\n\n

祝你好运,早上好。

\n\n

\n