【问题标题】:Can't connect a Unix domain socket using Python: No such file or directory无法使用 Python 连接 Unix 域套接字:没有这样的文件或目录
【发布时间】:2013-02-06 02:42:08
【问题描述】:

我有几段代码来建立一个 Unix 域套接字和使用这个套接字的服务。虽然这里有一些令人困惑的错误会导致失败。

创建 Unix 域套接字的代码是用 c: 编写的:

#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

int main(int ac, char *av[])
{
if (ac != 4) {
    printf("Usage: %s dummy-fd sockpath binary\n", av[0]);
    exit(-1);
    }

    char *sockpn = av[2];
    char *bin = av[3];

    int srvfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (srvfd < 0) {
    perror("socket");
    exit(-1);
    }

    fcntl(srvfd, F_SETFD, FD_CLOEXEC);

    struct stat st;
    if (stat(sockpn, &st) >= 0) {
    if (!S_ISSOCK(st.st_mode)) {
        fprintf(stderr, "socket pathname %s exists and is not a socket\n",
            sockpn);
        exit(-1);
    }

    unlink(sockpn);
    }

    struct sockaddr_un addr;
    addr.sun_family = AF_UNIX;
    snprintf(&addr.sun_path[0], sizeof(addr.sun_path), "%s", sockpn);
    if (bind(srvfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        fprintf(stderr, "WARNING: cannot bind to socket %s (%s), exiting\n",
                sockpn, strerror(errno));
    exit(-1);
    }

    // allow anyone to connect; for access control, use directory permissions
    chmod(sockpn, 0777);

    listen(srvfd, 5);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    for (;;) {
    struct sockaddr_un client_addr;
    unsigned int addrlen = sizeof(client_addr);

    int cfd = accept(srvfd, (struct sockaddr *) &client_addr, &addrlen);
    if (cfd < 0) {
        perror("accept");
        continue;
    }

    int pid = fork();
    if (pid < 0) {
        perror("fork");
        close(cfd);
        continue;
    }

    if (pid == 0) {
        // Child process
        dup2(cfd, 0);
        dup2(cfd, 1);
        close(cfd);

        execl(bin, bin, 0);
        perror("execl");
        exit(-1);
    }

    close(cfd);
    }
}

使用此 sock 的客户端 Python 如下(unixclient.py):

def call(pn, req):
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.connect(pn)
    sock.send(req)
    sock.shutdown(socket.SHUT_DOWN)
    data = ""
    while True:
        buf = sock.recv(1024)
        if not buf:
             break
        data += buf
    sock.close()
    return data

我在另一个 Python 代码中触发这段客户端代码,方法是导入这个文件并调用 call 函数:(“/jail/zoobar/echosvc”和“/jail/zoobar/echosvc/袜子”会失败)

   resp = call("/jail/zoobar/echosvc", str1)

出现错误,显示:

   FIle "zoobar/unixclient.py", line 8, in call
    sock.connect(pn)
   File "<string>", line 1, in connect
   error: [ERROR 2] No such file or directory

但我发誓该目录和套接字确实存在(/jail/zoobar/echosvc/sock),并且权限也是正确的(777),所以我无法理解这个奇怪的错误。有人知道吗?

非常感谢您抽出时间提供帮助。

【问题讨论】:

  • 我在第一段代码中添加了一行memset(&amp;address, 0, sizeof(struct sockaddr_un));,但同样的失败。
  • pn是域socket的路径,这里是"/jail/zoobar/echosvc"req是一个参数,连接上没关系。当pn"/jail/zoobar/echosvc/sock" 时,仍然会发生同样的故障。
  • 抱歉打错字了,第二个sock其实是socket,我马上改正
  • 可能对你没有帮助,但我在我的机器上运行你的程序没有问题。我能想到的唯一一件事是:我在我的主目录下运行这一切(尽管 777 建议这无论如何都不重要)。所以看起来不像是程序;更像是系统中的东西。
  • 还是谢谢你:),但是除了权限我找不到其他问题。

标签: python c unix-socket


【解决方案1】:

您似乎试图打开错误的文件名。代码如下:

resp = call("/jail/zoobar/echosvc", str1)

但你说“文件存在”:

/jail/zoobar/echosvc/sock

尝试将您的呼叫线路更改为:

resp = call("/jail/zoobar/echosvc/sock", str1)

【讨论】:

  • 其实我已经试过了,还是不行。 :( 还是一样的结果。也许它更像是系统中的东西。
  • 嗯。好的。我见过的大多数示例代码在 /tmp 中创建 unix 套接字。也许这是有原因的?此外,“/jail/...”暗示可能正在进行某种 chroot 或沙盒。您是否以同一用户身份运行 python 脚本和 C 程序?
  • 不,我不知道。 C 程序由一个守护进程启动。 python 脚本由使用 HTTP 请求的 .cgi 文件触发。它们在不同的 UID 下运行。
  • 好的,所以除了文件权限之外,我相信您还需要确保目录是世界可读的(也可能是父目录)。或者,在文件系统上找出 HTTP 用户可以访问的位置,并将套接字文件放在那里。
  • 父目录的权限都是755,sock本身是777,而且socket文件确实在HTTP用户的访问范围内退出,这……好奇怪……
猜你喜欢
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 2020-11-14
  • 2021-09-05
  • 2014-04-11
  • 2018-12-29
  • 2019-09-17
  • 1970-01-01
相关资源
最近更新 更多