epoll实现linux进程通信

时间:2022-08-01 16:15:13

server.c

  1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/socket.h>
5 #include <sys/un.h>
6 #include <unistd.h>
7 #include <signal.h>
8 #include <sys/epoll.h>
9 #include <errno.h>
10
11 #define UNIX_DOMAIN "/tmp/UNIX.domain"
12
13
14 void handler(){
15
16 printf("clean program start\n");
17 //unlink(UNIX_DOMAIN);
18 remove(UNIX_DOMAIN);
19 printf("clean end.\n");
20 }
21
22 int main(void)
23 {
24 int lsn_fd, apt_fd;
25 struct sockaddr_un srv_addr;
26 struct sockaddr_un clt_addr;
27 socklen_t clt_len;
28 int ret;
29 int i;
30 char recv_buf[1024];
31 char send_buf[1024];
32
33 signal(SIGTERM,handler);
34
35 //create epoll
36 int epfd,eventfd;
37 struct epoll_event ev,events[1024];
38
39 epfd = epoll_create(1024);
40
41 //create socket to bind local IP and PORT
42 lsn_fd = socket(AF_UNIX, SOCK_STREAM, 0);
43 ev.data.fd = lsn_fd;
44 ev.events = EPOLLIN|EPOLLET;
45
46 epoll_ctl(epfd,EPOLL_CTL_ADD,lsn_fd,&ev);
47
48 if(lsn_fd < 0)
49 {
50 perror("can't create communication socket!");
51 return 1;
52 }
53
54 //create local IP and PORT
55 srv_addr.sun_family = AF_UNIX;
56 strncpy(srv_addr.sun_path, UNIX_DOMAIN, sizeof(srv_addr.sun_path) - 1);
57 //unlink(UNIX_DOMAIN);
58
59 //bind sockfd and sockaddr
60 ret = bind(lsn_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
61 if(ret == -1)
62 {
63 perror("can't bind local sockaddr!");
64 close(lsn_fd);
65 unlink(UNIX_DOMAIN);
66 return 1;
67 }
68
69 //listen lsn_fd, try listen 5
70
71 ret = listen(lsn_fd, 5);
72 if(ret == -1)
73 {
74 perror("can't listen client connect request");
75 close(lsn_fd);
76 unlink(UNIX_DOMAIN);
77
78 return 1;
79 }
80
81 clt_len = sizeof(clt_addr);
82 while(1)
83 {
84 int nfds = epoll_wait(epfd,events,1024,100);
85 int i=0;
86 for(i=0;i<nfds;++i)
87 {
88 if(events[i].data.fd == lsn_fd)
89 {
90 apt_fd = accept(lsn_fd, (struct sockaddr*)&clt_addr, &clt_len);
91 if(apt_fd < 0){
92 perror("can't listen client connect request");
93 close(lsn_fd);
94 unlink(UNIX_DOMAIN);
95 return 1;
96 }
97 char lines[256];
98 sprintf(lines,"server data to client\n");
99 write(apt_fd, lines, 256);
100
101 ev.data.fd = apt_fd;
102 ev.events = EPOLLIN|EPOLLET;
103
104 epoll_ctl(epfd,EPOLL_CTL_ADD,apt_fd,&ev);
105
106 }
107 else if (events[i].events & EPOLLIN)
108 //write数据
109 {
110 printf("EPOLLIN\n");
111 if( (eventfd = events[i].data.fd) < 0 )
112 continue;
113
114 int n=0,ret=0 ;
115 char line[256];
116 if ((ret = read(eventfd,line,256)) < 0){
117
118 if(errno == ECONNRESET){
119 close(eventfd);
120 events[i].data.fd = -1;
121 }
122 else
123 printf("readline error\n");
124 }
125 else if( ret == 0){
126 close(eventfd);
127 events[i].data.fd = -1;
128 }
129 else if( ret > 0 )
130 {
131 line[ret] = '\0';
132 printf("%s",line);
133 while( ( ret = read(eventfd,line,256)) >0)
134 {
135 line[ret] = '\0';
136 printf("%s",line);
137 }
138 printf("\n");
139 }
140 }
141 else if (events[i].events & EPOLLOUT){
142 //写出的数据,在EPOLLIN处理中设置fd的events为EPOLLOUT|EPOLLET时,即触发该事件
143 int eventfd = events[i].data.fd;
144 char line[256];
145 write(eventfd,line,256);
146
147 ev.data.fd = eventfd;
148 ev.events = EPOLLIN | EPOLLET;
149
150 epoll_ctl ( epfd, EPOLL_CTL_ADD, eventfd, &ev);
151 }
152 }
153 }
154
155 close(apt_fd);
156 close(lsn_fd);
157 unlink(UNIX_DOMAIN);
158 return 0;
159 }

 

client.c

 1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/socket.h>
4 #include <sys/un.h>
5 #include <unistd.h>
6
7 #define UNIX_DOMAIN "/tmp/UNIX.domain"
8
9 int main(void)
10 {
11 int connect_fd;
12 struct sockaddr_un srv_addr;
13 char snd_buf[256];
14 char rcv_buf[256];
15 int ret;
16 int i;
17 connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);
18
19 if(connect_fd < 0)
20 {
21 perror("client create socket failed");
22 return 1;
23 }
24 srv_addr.sun_family = AF_UNIX;
25 strcpy(srv_addr.sun_path, UNIX_DOMAIN);
26 ret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
27
28 if(ret == -1)
29 {
30 perror("connect to server failed!");
31 close(connect_fd);
32 unlink(UNIX_DOMAIN);
33 return 1;
34 }
35
36 memset(rcv_buf, 0, 256);
37 int rcv_num = read(connect_fd, rcv_buf, sizeof(rcv_buf));
38 printf("receive message from server (%d) :%s\n", rcv_num, rcv_buf);
39
40 memset(snd_buf, 0, 256);
41 strcpy(snd_buf, "message from client");
42 printf("sizeof(snd_buf): %d\n", sizeof(snd_buf));
43
44 printf("send data to server... ...\n");
45 for(i = 0; i < 4; i++)
46 {
47 write(connect_fd, snd_buf, sizeof(snd_buf));
48 }
49 printf("send end!\n");
50 close(connect_fd);
51 return 0;
52
53 }

 

与网络的socket通信的区别,即socket地址有些区别,其他的一样。

sockaddr_in用于网络的socket通信,sockaddr_un用于本机上的进程之间的通信。