【问题标题】:C: unix socket -> broken pipe [closed]C: unix socket -> 破管[关闭]
【发布时间】:2017-04-14 19:05:04
【问题描述】:

我正在尝试让套接字在 C 代码中工作,而不是调用命令行 find。

通过管道传输到 child2 函数 'cut' 的子 3'sort' 函数工作正常,当执行时包含所有 3 个子函数时,程序会卡在父进程 waitpid() 中。

我试图隔离参与套接字的唯一孩子,当我在 gdb 上运行可执行文件时,我收到消息“find: 'standard output': Broken pipe”和“find: write error”

以下是与套接字交互的两个子函数的示例: 孩子 1:

void child1()
{
    int sock;
    struct sockaddr_un  remote;

    sock = socket(AF_UNIX, SOCK_STREAM, 0)
    memset(&remote, 0, sizeof(struct sockaddr_un));
    remote.sun_family = AF_UNIX;
    strncpy(remote.sun_path, "socket", sizeof(remote.sun_path) - 1);

    while((connect(sock, (struct sockaddr *)&remote,   (socklen_t)sizeof(remote))) == -1)
    {
        if(errno != ENOENT && errno != ECONNREFUSED)
            erro("child 2 failed to connect to socket");
    }
    dup2(sock, 1);
    close(sock);
    execlp("find", "find", ".", "-type" , "f", "-ls", NULL);
}

还有孩子2:

void child2(int *pipe_fd)
{
    int sock;
    struct sockaddr_un local, remote;
    socklen_t sock_size = (socklen_t)sizeof(remote);

    sock= socket(AF_UNIX, SOCK_STREAM, 0);

    memset(&local, 0, sizeof(struct sockaddr_un));
    memset(&remote, 0, sizeof(struct sockaddr_un));

    local.sun_family = AF_UNIX;
    strncpy(local.sun_path, "socket", sizeof(local.sun_path) - 1);
    unlink("socket");
    bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_un));

    listen(sock, 1);
    sock = accept(sock,(struct sockaddr *)&remote, &sock_size));
    dup2(sock, STDOUT_FILENO);
    close(sock);

    close(pipe_fd[0]);
    dup2(pipe_fd[1],1);
    close(pipe_fd[1]); 
    execlp("cut", "cut", "-d", " ", "-f", "3-", NULL);
}

这个问题没必要专门解决,我只是想了解一下我在创作过程中做错了什么,以后不会再犯了。 我提前感谢任何帮助。

【问题讨论】:

  • 两个孩子都在写入同一个套接字。这真的是你想要的吗?
  • child2 从不执行任何操作。
  • 为什么child2 将标准输出连接到套接字?不应该是读者吗?
  • 如果您在读取过程关闭套接字后尝试写入套接字,则会收到“Broken pipe”。阅读过程在哪里?
  • 如果 } 是孩子 2 的结尾,find 输出的接收者(莫名其妙地被那里的 STDOUT_FILENO 欺骗)将在那里隐式关闭,这将破坏孩子 1 的套接字。跨度>

标签: c sockets unix


【解决方案1】:

如果我将child2 中的dup2(sock, STDOUT_FILENO); 更改为dup2(sock, STDIN_FILENO);(输入是袜子,输出是通向child3 的管道),您的示例基本上可以工作:

(需要错误检查)

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/un.h>
#include <sys/wait.h>
void child1()
{
    int sock;
    struct sockaddr_un  remote;

    sock = socket(AF_UNIX, SOCK_STREAM, 0);
    memset(&remote, 0, sizeof(struct sockaddr_un));
    remote.sun_family = AF_UNIX;
    strncpy(remote.sun_path, "socket", sizeof(remote.sun_path) - 1);

    while((connect(sock, (struct sockaddr *)&remote,   (socklen_t)sizeof(remote))) == -1)
    {
        perror("connect");
        if(errno != ENOENT && errno != ECONNREFUSED)
            perror("child 2 failed to connect to socket");
    }
    dup2(sock, 1);
    close(sock);
    execlp("find", "find", ".", "-type" , "f", "-ls", (char*)0);
}
void child2(int *pipe_fd)
{
    int sock;
    struct sockaddr_un local, remote;
    socklen_t sock_size = (socklen_t)sizeof(remote);

    sock= socket(AF_UNIX, SOCK_STREAM, 0);

    memset(&local, 0, sizeof(struct sockaddr_un));
    memset(&remote, 0, sizeof(struct sockaddr_un));

    local.sun_family = AF_UNIX;
    strncpy(local.sun_path, "socket", sizeof(local.sun_path) - 1);
    unlink("socket");
    bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_un));

    listen(sock, 1);
    puts("listened");
    sock = accept(sock,(struct sockaddr *)&remote, &sock_size);
    dup2(sock, STDIN_FILENO);
    close(sock);

    close(pipe_fd[0]);
    dup2(pipe_fd[1],1);
    close(pipe_fd[1]); 
    execlp("cut", "cut", "-d", " ", "-f", "3-", (char*)0);
}
void child3(int *pipe_fd)
{
    dup2(pipe_fd[0],0);
    close(pipe_fd[0]);
    execlp("sort", "sort", (char*)0);
}

int main()
{
    int pi[2];
    pid_t pid0, pid1, pid2;
    pid0 = fork();
    if (0==pid0){
        child1();
        _exit(1);
    }
    pipe(pi);
    pid1 = fork();
    if(0==pid1){
        child2(pi);
        _exit(1);
    }
    close(pi[1]);
    pid2 = fork();
    if(0==pid2){
        child3(pi);
        _exit(1);
    }
    close(pi[0]);

    wait(0);
    wait(0);
    wait(0);
}

这基本上是一个三重管道:

find | cut | sort 

第一个| 不是常规管道,而是通过"socket" 的UNIX 套接字连接。

【讨论】:

  • 谢谢!我真的需要下定决心检查这些错误。
猜你喜欢
  • 2014-08-12
  • 1970-01-01
  • 2012-12-06
  • 2016-03-16
  • 2015-01-27
  • 2014-02-15
  • 2014-11-01
  • 2012-02-11
  • 2018-09-06
相关资源
最近更新 更多