【发布时间】:2015-11-01 17:36:54
【问题描述】:
在使用 Python 和“纯”C 时,使用所谓的抽象命名空间的 unix socket(美国)有一个奇怪的问题(Python 3.x,但看起来 2.x 也有同样的问题)。 “普通”插座就像一个魅力。使用“抽象”一美国,我的代码仅在我使用相同的“代码平台”(C 或 Python)时才有效。
首先我认为这与memset / str(n)cpy(参见Can not connect to an abstract unix socket in python)有关,但恕我直言,事实并非如此。
测试矩阵(srv - 服务器,cli - 客户端):
- srv + cli @“抽象”unix 袜子:
- python + python = OK
- c + c = 确定
- srv + cli @“正常”unix 袜子:
- python + python = OK
- c + c = 确定
- srv + cli @“正常”unix 袜子:
- python + c = OK
- c + python = OK
- srv + cli @“抽象”unix 袜子:
- python + c = FAIL [cli / strace 输出:ECONNREFUSED(连接被拒绝)]
- c + python = FAIL [cli / 引发异常:socket.error: [Errno 111] Connection denied]
/proc/net/unix / lsof 或 strace 显示没有异常:
工作“正常”套接字 C 客户端:
// ...socket(PF_LOCAL, SOCK_STREAM, 0) = 3connect(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"}, 110) = 0// ...行为不端的“抽象”套接字 C 客户端:
// ...socket(PF_LOCAL, SOCK_STREAM, 0) = 3connect(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"}, 110) = -1 ECONNREFUSED (Connection refused)// ...
Python 错误还是什么...?
我的测试矩阵的代码示例要点:https://gist.github.com/soutys/ffbe2e76a86835a9cc6b
原始代码/示例:
- C 服务器/客户端 - 基于 https://github.com/troydhanson/network/tree/master/unixdomain
- Python 服务器/客户端 - 基于 Python 3.X Unix Socket Example
2015 年 11 月 2 日更新
有关系统和编译的更多信息:
- 主机系统:Ubuntu 14.04.3 LTS (x64);
- 所有使用
gcc编译的C测试文件(例如:gcc -Wall -Wextra -pedantic -o abs_cli abs_cli.c); - 所有程序(编译的和内置的 python)都以非 root 用户身份运行;
【问题讨论】:
-
引用的'C'客户端代码,不能编译!!包括原始来源。除其他外,它缺少头文件:
#include <string.h>用于系统功能:memset()和strncpy()。编译时始终启用所有警告,然后修复这些警告。 (对于 gcc,至少使用:-Wall -Wextra -pedantic) -
另外,srv 和 cli 中的 C 代码确实遇到了链接帖子中描述的问题。 strncpy 只会复制 \0 空值,无论您将其作为 n (只要 n > 0)。使用 memcpy()。
-
@user3629249 它在我的 x64 ubuntu 上使用 gcc 编译,同时带有
-Wall和-Wall -Wextra -pedantic... 好的 - 为了清楚起见,我添加了 string.h 标题条目。 -
@thuovila 您可能会看到 strncpy 发生了变化:
strncpy(&addr.sun_path[1], socket_path, sizeof(addr.sun_path) - 2);在零填充结构中给出了适当的“偏移量”。 -
我可能看不到。我至少看过github.com/troydhanson/network/blob/master/unixdomain/srv.c 的版本中不存在它。此外,这不是一个非常明智的方法。如果您的数据中有空值,只需使用 memcpy()。
标签: python c sockets unix unix-socket