无法连接到Linux"抽象"unix socket

Paw*_*lov 10 linux unix-socket

我正在尝试使用UNIX套接字进行线程间通信.该程序仅适用于在Linux上运行.为了避免创建套接字文件,我想使用"抽象"套接字,如unix(7)中所述.

但是,我似乎无法连接到这些套接字.但是,如果我使用"pathname"套接字,一切都会正常工作.

这是代码(我没有引用任何错误处理,但它已经完成):线程#1:

int log_socket = socket(AF_LOCAL, SOCK_STREAM, 0);
struct sockaddr_un logaddr;
socklen_t sun_len = sizeof(struct sockaddr_un);
logaddr.sun_family = AF_UNIX;
logaddr.sun_path[0] = 0;
strcpy(logaddr.sun_path+1, "futurama");
bind(log_socket, &logaddr, sun_len);
listen(log_socket, 5);
accept(log_socket, &logaddr, &sun_len);
... // send - receive
Run Code Online (Sandbox Code Playgroud)

线#2:

struct sockaddr_un tolog;
int sock = socket(AF_LOCAL, SOCK_STREAM, 0);
tolog.sun_family = AF_UNIX;
tolog.sun_path[0] = 0;
strcpy(tolog.sun_path+1, "futurama");
connect(sock, (struct sockaddr*)&tolog, sizeof(struct sockaddr_un));
Run Code Online (Sandbox Code Playgroud)

如果我在上面的代码中所做的只是将sun_path更改为没有前导\ 0,那么事情就完美了.

strace输出:

t1: socket(PF_FILE, SOCK_STREAM, 0)         = 0
t1: bind(0, {sa_family=AF_FILE, path=@"futurama"}, 110)
t1: listen(0, 5)
t2: socket(PF_FILE, SOCK_STREAM, 0) = 1
t2: connect(1, {sa_family=AF_FILE, path=@"futurama"}, 110 <unfinished ...>
t2: <... connect resumed> )     = -1 ECONNREFUSED (Connection refused)
t1: accept(0,  <unfinished ...>
Run Code Online (Sandbox Code Playgroud)

我知道连接在接受之前,这不是问题(我尝试确保在connect()之前调用accept(),结果相同.另外,如果套接字是"路径名",那么一切都很好).

Paw*_*lov 16

当我发布这个问题并重新阅读unix(7)手册页时,这句话引起了我的注意:

抽象套接字地址的区别在于sun_path [0]是一个空字节('\ 0'). sun_path中的所有剩余字节定义套接字的"名称"

所以,如果我在填写我的名字之前先把sun_path改成了,那么事情就开始起作用了.我认为这不一定是直截了当的.另外,正如@davmac和@StoneThrow正确指出的那样,通过仅指定套接字地址结构的足够长度来覆盖您想要考虑作为地址的字节,可以减少那些"剩余字节"的数量.一种方法是使用SUN_LEN宏,但是,sun_path必须将will 的第一个字节设置为!0,作为SUN_LEN使用strlen.

阐述

如果sun_path [0]为\ 0,则内核使用sun_path的全部余数作为套接字的名称,无论它是否为0终止,因此所有剩余的都计数.在我的原始代码中,我将第一个字节归零,然后将套接字名称strcpy()放入位置1的sun_path.当分配结构时,sun_path中存在任何乱码(特别是可能包含乱码,因为它已在堆栈上分配) ,并且包含在套接字结构的长度中(传递给syscalls),计为套接字的名称,并且在bind()和connect()中有所不同.

恕我直言,strace应该修复它显示抽象套接字名称的方式,并显示sun_path从1到所提供的结构长度的所有字节,如果sun_path[0]是0

  • @KarolyHorvath是的,确切地说.可以说不改变行为,只是定义套接字地址.*ALL*sun_path中的字节很重要,无论它们是什么. (2认同)