C:unix socket - >破管

时间:2017-04-14 19:05:04

标签: c sockets unix

我正在尝试使用C代码工作,而不是调用命令行find。

子3'的'功能'通过pi2传递给child2函数'cut'工作正常,当执行时包含所有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);
}

和Child2:

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);
}

没有必要具体解决这个问题,我只是想了解我在创作过程中做错了什么,所以我将来不再这样做了。 我事先得到任何帮助。

1 个答案:

答案 0 :(得分:2)

如果我将dup2(sock, STDOUT_FILENO);更改为dup2(sock, STDIN_FILENO);中的child2(输入有袜子,输出是通向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套接字连接。