Linux-进程间通信(四): 域套接字

时间:2021-11-14 04:01:19

1. 域套接字:

(1) 只能用于同一设备上不同进程之间的通信;

(2) 效率高于网络套接字。域套接字仅仅是复制数据,并不走协议栈;

(3) 可靠,全双工;

 

2. 域套接字地址结构:

struct sockaddr_un {
    sa_family_t sun_family; /*AF_UNIX*/
    char sun_path[108]; /*pathname*/
};

当我们将一个地址绑定至域套接字,系统用该路径名创建一个类型为S_IFSOCK的文件,尽告诉客户端名字,不能打开,也不能通信,

不会自动删除,需要程序完成后删除,若文件已存在则bind失败;

 

3. 测试代码:

server.c

 1 #include <sys/types.h>
 2 #include <sys/socket.h>
 3 #include <sys/un.h>
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 
 7 #define UN_PATH "/var/tmp/test_domain_socket"
 8 
 9 
10 int main(int argc, char *argv[])
11 {
12     int sockfd = -1;
13     struct sockaddr_un un;
14     int len = 0;
15 
16     if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
17         perror("create socket error\n");
18         goto _ERROR;
19     }
20 
21     memset(&un, 0, sizeof(un));
22     un.sun_family = AF_UNIX;
23     strcpy(un.sun_path, UN_PATH);
24 
25     len = sizeof(un.sun_family) + sizeof(un.sun_path);
26 
27     if (bind(sockfd, (struct sockaddr *)&un, len) < 0){
28         perror("socket bind error\n");
29         goto _ERROR;
30     }
31 
32     if (listen(sockfd, 5) < 0){
33         perror("socket listen error\n");
34     }
35 
36     int conn = accept(sockfd, (struct sockaddr *)&un, &len);
37     if (conn < 0){
38         perror("accept error\n");
39         goto _ERROR;
40     }
41     char buf[64] = {0};
42     int n = read(conn, buf, 63);
43     printf("recive-msg:%s", buf);
44     write(conn, buf, n);
45     close(conn);
46 
47     close(sockfd);
48     unlink(UN_PATH);
49     return 0;
50 
51 _ERROR:
52     if (sockfd != -1){
53         close(sockfd);
54     }
55 
56     return -1;
57 }

 

client.c

 1 #include <sys/types.h>
 2 #include <sys/socket.h>
 3 #include <sys/un.h>
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 #include <unistd.h>
 7 
 8 #define UN_PATH "/var/tmp/test_domain_socket"
 9 
10 
11 int main(int argc, char *argv[])
12 {
13     int sockfd = -1;
14     struct sockaddr_un un;
15     int len = 0;
16 
17     if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
18         perror("create socket error\n");
19         goto _ERROR;
20     }
21 
22     memset(&un, 0, sizeof(un));
23     un.sun_family = AF_UNIX;
24     strcpy(un.sun_path, UN_PATH);
25 
26     len = sizeof(un.sun_family) + sizeof(un.sun_path);
27 
28     if (connect(sockfd, (struct sockaddr *)&un, len) < 0){
29         perror("socket connect error\n");
30         goto _ERROR;
31     }
32 
33     char buf[64] = {0};
34     int n = read(STDIN_FILENO, buf, 63);
35     write(sockfd, buf, n);
36     printf("send-msg:%s", buf);
37     read(sockfd, buf, 63);
38     buf[64] = '\0';
39     printf("recv-msg:%s", buf);
40 
41     close(sockfd);
42     return 0;
43 
44 _ERROR:
45     if (sockfd != -1){
46         close(sockfd);
47     }
48 
49     return -1;
50 }