简体   繁体   English

使用抽象名称空间UNIX套接字时连接被拒绝

[英]Connection refused when using abstract namespace unix sockets

I have a strange problem with unix socket (US) using so-called abstract namespaces when using Python and "pure" C (Python 3.x but looks like 2.x have the same problem). 我在使用Python和“纯” C时使用所谓的抽象命名空间的unix套接字(美国)遇到一个奇怪的问题(Python 3.x但看起来像2.x一样有同样的问题)。 "Normal" socket works like a charm. “普通”插座的工作原理很像。 With "abstract" one US my code works only when I'm using same "code platform" (C or Python). 使用“抽象”一个美国语言,我的代码仅在使用相同的“代码平台”(C或Python)时有效。

First I thought it has something to do with memset / str(n)cpy (see Can not connect to an abstract unix socket in python ) but imho it's not that case. 首先,我认为这与memset / str(n)cpy (请参阅python中无法连接到抽象的unix套接字 ),但是恕我直言,不是这种情况。

Test matrix (srv - server, cli - client): 测试矩阵(srv-服务器,cli-客户端):

  • srv + cli @ "abstract" unix sock: srv + cli @“抽象” unix袜子:
    • python + python = OK python + python =确定
    • c + c = OK c + c =好
  • srv + cli @ "normal" unix sock: srv + cli @“普通” unix袜子:
    • python + python = OK python + python =确定
    • c + c = OK c + c =好
  • srv + cli @ "normal" unix sock: srv + cli @“普通” unix袜子:
    • python + c = OK python + c =确定
    • c + python = OK c + python =确定
  • srv + cli @ "abstract" unix sock: srv + cli @“抽象” unix袜子:
    • python + c = FAIL [cli / strace output: ECONNREFUSED (Connection refused)] python + c = FAIL [cli / strace输出:ECONNREFUSED(连接被拒绝)]
    • c + python = FAIL [cli / raised exception: socket.error: [Errno 111] Connection refused] c + python = FAIL [cli /引发异常:socket.error:[Errno 111]连接被拒绝]

/proc/net/unix / lsof or strace show nothing unusual: /proc/net/unix / lsofstrace没有显示任何异常:

  • working "normal" socket C client: 工作“普通”套接字C客户端:
    // ...
    socket(PF_LOCAL, SOCK_STREAM, 0) = 3
    connect(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"}, 110) = 0
    // ...

  • misbehaving "abstract" socket C client: 行为异常的“抽象”套接字C客户端:
    // ...
    socket(PF_LOCAL, SOCK_STREAM, 0) = 3
    connect(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"}, 110) = -1 ECONNREFUSED (Connection refused)
    // ...

Python bug or what...? Python错误还是什么...?

Gist with code samples for my test matrix : https://gist.github.com/soutys/ffbe2e76a86835a9cc6b 要点与我的测试矩阵的代码示例: https : //gist.github.com/soutys/ffbe2e76a86835a9cc6b

Original code / samples: 原始代码/样本:

Update 2015-11-02 更新2015-11-02

More info about system and compilations: 有关系统和编译的更多信息:

  • host system: Ubuntu 14.04.3 LTS (x64); 主机系统:Ubuntu 14.04.3 LTS(x64);
  • all C test files compiled with gcc (example: gcc -Wall -Wextra -pedantic -o abs_cli abs_cli.c ); 使用gcc编译的所有C测试文件(例如: gcc -Wall -Wextra -pedantic -o abs_cli abs_cli.c );
  • all programs (both compiled and built-in python) run as non-root user; 所有程序(已编译和内置python)均以非root用户身份运行;

When binding a UNIX domain socket to an abstract name, the addrlen argument should be sizeof(struct sockaddr_un's sun_family) + number of characters in abstract name + 1. The "+1" is for the null byte in front of the abstract name in sockaddr_un's sun_path. 将UNIX域套接字绑定到抽象名称时,addrlen参数应为sizeof(struct sockaddr_un的sun_family)+抽象名称中的字符数+ 1。“ + 1”表示sockaddr_un中抽象名称前面的空字节。 sun_path。 Let's look at an example: 让我们看一个例子:

  • Server in C: C服务器:

     int sockfd; struct sockaddr_un addr; /* create socket, set addr.sun_family, set addr.sun_path to null byte followed by abstract_name */ bind(sockfd, (struct sockaddr *)&addr, sizeof(addr.sun_family) + strlen(abstract_name) + 1); 
  • Client in Python: Python客户端:

     client = socket.socket(socket.AF_UNIX, ...) client.connect( "\\0abstract_name" ) 

References: 参考文献:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM