0x01 Unix domain socket 的作用

1,允许在同一host上的不同进程通信,另外一种IPC方式

2,可以方便的实现子进程向父进程传递文件描述符

3,通过 socketpair 可以在父子进程之间通过文件描述模拟管道,更加高效

0x02 创建 Unix domain docket

1,地址结构

struct sockaddr_un {
    sa_family_t sun_family;    //固定为 AF_UNIX
    char sun_path[108];        //Unix domain socket中socket地址是一个文件路径名
};

说明:
1,对于路径名,各系统之间的限制长度不同,但是为了移植行,一般推荐使用一个较短的路径名。
2,最好是通过 snprintf 或者 strcopy 函数来避免缓冲区溢出的问题

2,创建一个 Unix socket 同时将 socket 地址绑定到指定路径上

char* socketName = "/tmp/mysock.sock";

int sfd;
struct sockaddr_un addr;

sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1) {
    errExit("socket");
}

memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketName, sizeof(addr.sun_path) - 1);

if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) {
    errExit("bind");
}

说明:
1,使用memset函数来初始化结构体,这是通用的做法了
2,通过strncopy来将 sun_path 初始化成其长度减1的目的是要保证其值一定是以null结尾的

3,一个使用 Unix domain socket 互相通信的客户端-服务器程序



4,使用 Unix domain socket 在父子进程之间传递文件描述符

有一种场景,一个进程创建一对socket,然后把它们相互连起来。
这可以通过使用 socket, bind, listen, connect 这些函数相互组合实现,但是另外一个系统调用函数 socketpair 提供了一种
快捷方式。
由于这个函数的存在,这就使得在父子进程之间传递文件描述符变得异常简单了,因为当执行 fork 之后子进程可以继承父进程的文件描述符
所以我们可以在父进程中调用 socketpair 然后再执行 fork,这样父子进程就可以通过文件描述符进行通信了。

示例代码:

int UnixDomainSocketDemo()
{
    int sockfd[2];

    if ( socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) == -1 ) {
        perror("socketpair");
        exit(0);
    }

    int pid = fork();

    if ( pid == -1 ) {
        perror("fork");
        exit(0);
    }

    if ( pid == 0 ) { //child
        close(sockfd[0]);

        char buf[] = "koma";
        write(sockfd[1], buf, sizeof(buf));
    } else {
        close(sockfd[1]);

        sleep(3);

        char buf[1024];
        read(sockfd[0], buf, 1024);

        printf("recv data: %s\n", buf);

        int status;
        waitpid(pid, &status, WNOHANG);
    }
}

int main(int argc, char * argv[]) {

    UnixDomainSocketDemo();

    return 0;
}

results matching ""

    No results matching ""