无法连接到Linux的“抽象"目录. Unix套接字 [英] Can not connect to Linux "abstract" unix socket

查看:200
本文介绍了无法连接到Linux的“抽象"目录. Unix套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to use UNIX sockets for inter-thread communication. The program is only intended to run on Linux. To avoid creating the socket files, I wanted to use "abstract" sockets, as documented in unix(7).

但是,我似乎无法连接到这些插座.不过,如果我使用路径名"套接字,一切都会正常.

However, I don't seem to be able to connect to these sockets. Everything works if I'm using "pathname" sockets, though.

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

Here is the code (I haven't quoted any error handling, but it's done): thread#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

线程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));

如果我在上面的代码中所做的只是将sun_path更改为没有前导\ 0,则表示一切正常.

If all I do in the above code, is change the sun_path to not have leading \0, things work perfect.

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 ...>

我知道连接在接受之前发生,这不是问题(我尝试确保在connect()之前调用accept(),结果相同.此外,如果套接字始终为路径名",一切都会好起来的).

I know that the connect comes before accept, that's not an issue (I tried making sure that accept() is called before connect(), same result. Also, things are fine if the socket is "pathname" anyway).

推荐答案

当我发布此问题并重新阅读unix(7)手册页时,此措辞引起了我的注意:

While I was posting this question, and re-reading unix(7) man page, this wording caught my attention:

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

an abstract socket address is distinguished by the fact that sun_path[0] is a null byte (’\0’). All of the remaining bytes in sun_path define the "name" of the socket

因此,如果我先将sun_path归零,然后再填写我的名字,那么事情就开始起作用了.我认为这不一定是直截了当的.此外,正如@davmac和@StoneThrow正确指出的那样,可以通过仅指定套接字地址结构的足够长度来覆盖要用作地址的字节,来减少剩余字节"的数量.一种实现方法是使用SUN_LEN宏,但是sun_path的第一个字节必须设置为!0,因为SUN_LEN使用strlen.

So, if I bzero'ed the sun_path before filling in my name into it, things started to work. I figured that's not necessarily straight-forward. Additionally, as rightfully pointed out by @davmac and @StoneThrow, the number of those "remaining bytes" can be reduced by specifying only enough length of the socket address structure to cover the bytes you want to consider as your address. One way to do that is to use SUN_LEN macro, however, the first byte of the sun_path will have to be set to !0, as SUN_LEN uses strlen.

阐述

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

If sun_path[0] is \0, The kernel uses the entirety of the remainder of sun_path as the name of the socket, whether it's \0-terminated or not, so all of that remainder counts. In my original code I would zero the first byte, and then strcpy() the socket name into the sun_path at position 1. Whatever gibberish that was in sun_path when the structure was allocated (especially likely to contain gibberish since it's allocated on the stack), and was included in the length of the socket structure (as passed to the syscalls), counted as the name of the socket, and was different in bind() and connect().

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

IMHO, strace should fix the way it displays abstract socket names, and display all the sun_path bytes from 1 to whatever the structure length that was supplied, if sun_path[0] is 0

这篇关于无法连接到Linux的“抽象"目录. Unix套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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