Commit faa3a30be0bce7fd679b8c07692381b1f8a3b58d

Authored by Grzegorz Jabłoński
1 parent ce434124

Fixed epoll example

Showing 1 changed file with 193 additions and 171 deletions
epoll4.c
1 -/* 1 +/*
2 * Attention: 2 * Attention:
3 - * To keep things simple, do not handle socket/bind/listen/.../epoll_create/epoll_wait API error 3 + * To keep things simple, do not handle
  4 + * socket/bind/listen/.../epoll_create/epoll_wait API error
4 */ 5 */
5 -#include <sys/types.h>  
6 -#include <sys/socket.h>  
7 -#include <netdb.h>  
8 -#include <string.h>  
9 -#include <unistd.h>  
10 -#include <fcntl.h>  
11 -#include <sys/epoll.h> 6 +#include <arpa/inet.h>
12 #include <errno.h> 7 #include <errno.h>
  8 +#include <fcntl.h>
  9 +#include <netdb.h>
13 #include <stdio.h> 10 #include <stdio.h>
14 #include <stdlib.h> 11 #include <stdlib.h>
15 -#include <arpa/inet.h>  
16 - 12 +#include <string.h>
  13 +#include <sys/epoll.h>
  14 +#include <sys/socket.h>
  15 +#include <sys/types.h>
  16 +#include <unistd.h>
17 17
18 -#define DEFAULT_PORT 9734  
19 -#define MAX_CONN 16  
20 -#define MAX_EVENTS 32  
21 -#define BUF_SIZE 16  
22 -#define MAX_LINE 256 18 +#define DEFAULT_PORT 9734
  19 +#define MAX_CONN 16
  20 +#define MAX_EVENTS 32
  21 +#define BUF_SIZE 16
  22 +#define MAX_LINE 256
23 23
24 void server_run(); 24 void server_run();
25 void client_run(); 25 void client_run();
26 26
27 -int main(int argc, char *argv[])  
28 -{  
29 - int opt;  
30 - char role = 's';  
31 - while ((opt = getopt(argc, argv, "cs")) != -1) {  
32 - switch (opt) {  
33 - case 'c':  
34 - role = 'c';  
35 - break;  
36 - case 's':  
37 - break;  
38 - default:  
39 - printf("usage: %s [-cs]\n", argv[0]);  
40 - exit(1);  
41 - }  
42 - }  
43 - if (role == 's') {  
44 - server_run();  
45 - } else {  
46 - client_run();  
47 - }  
48 - return 0; 27 +int main(int argc, char *argv[]) {
  28 + int opt;
  29 + char role = 's';
  30 + while ((opt = getopt(argc, argv, "cs")) != -1) {
  31 + switch (opt) {
  32 + case 'c':
  33 + role = 'c';
  34 + break;
  35 + case 's':
  36 + break;
  37 + default:
  38 + printf("usage: %s [-cs]\n", argv[0]);
  39 + exit(1);
  40 + }
  41 + }
  42 + if (role == 's') {
  43 + server_run();
  44 + } else {
  45 + client_run();
  46 + }
  47 + return 0;
49 } 48 }
50 49
51 /* 50 /*
52 * register events of fd to epfd 51 * register events of fd to epfd
53 */ 52 */
54 -static void epoll_ctl_add(int epfd, int fd, uint32_t events)  
55 -{  
56 - struct epoll_event ev;  
57 - ev.events = events;  
58 - ev.data.fd = fd;  
59 - if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {  
60 - perror("epoll_ctl()\n");  
61 - exit(1);  
62 - } 53 +static void epoll_ctl_add(int epfd, int fd, uint32_t events) {
  54 + struct epoll_event ev;
  55 + ev.events = events;
  56 + ev.data.fd = fd;
  57 + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
  58 + perror("epoll_ctl()\n");
  59 + exit(1);
  60 + }
63 } 61 }
64 62
65 -static void set_sockaddr(struct sockaddr_in *addr)  
66 -{  
67 - bzero((char *)addr, sizeof(struct sockaddr_in));  
68 - addr->sin_family = AF_INET;  
69 - addr->sin_addr.s_addr = INADDR_ANY;  
70 - addr->sin_port = htons(DEFAULT_PORT); 63 +static void set_sockaddr(struct sockaddr_in *addr) {
  64 + bzero((char *)addr, sizeof(struct sockaddr_in));
  65 + addr->sin_family = AF_INET;
  66 + addr->sin_addr.s_addr = INADDR_ANY;
  67 + addr->sin_port = htons(DEFAULT_PORT);
71 } 68 }
72 69
73 -static int setnonblocking(int sockfd)  
74 -{  
75 - if (fcntl(sockfd, F_SETFD, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK) ==  
76 - -1) {  
77 - return -1;  
78 - }  
79 - return 0; 70 +static int setnonblocking(int sockfd) {
  71 + if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK) == -1) {
  72 + perror("fcntl set nonblock");
  73 + return -1;
  74 + }
  75 + return 0;
80 } 76 }
81 77
82 /* 78 /*
83 * epoll echo server 79 * epoll echo server
84 */ 80 */
85 -void server_run()  
86 -{  
87 - int i;  
88 - int n;  
89 - int epfd;  
90 - int nfds;  
91 - int listen_sock;  
92 - int conn_sock;  
93 - int socklen;  
94 - char buf[BUF_SIZE];  
95 - struct sockaddr_in srv_addr;  
96 - struct sockaddr_in cli_addr;  
97 - struct epoll_event events[MAX_EVENTS];  
98 -  
99 - listen_sock = socket(AF_INET, SOCK_STREAM, 0);  
100 -  
101 - set_sockaddr(&srv_addr);  
102 - bind(listen_sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr));  
103 -  
104 - setnonblocking(listen_sock);  
105 - listen(listen_sock, MAX_CONN);  
106 -  
107 - epfd = epoll_create(1);  
108 - epoll_ctl_add(epfd, listen_sock, EPOLLIN | EPOLLOUT | EPOLLET);  
109 -  
110 - socklen = sizeof(cli_addr);  
111 - for (;;) {  
112 - nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);  
113 - for (i = 0; i < nfds; i++) {  
114 - if (events[i].data.fd == listen_sock) {  
115 - /* handle new connection */  
116 - conn_sock =  
117 - accept(listen_sock,  
118 - (struct sockaddr *)&cli_addr,  
119 - &socklen);  
120 -  
121 - inet_ntop(AF_INET, (char *)&(cli_addr.sin_addr),  
122 - buf, sizeof(cli_addr));  
123 - printf("[+] connected with %s:%d\n", buf,  
124 - ntohs(cli_addr.sin_port));  
125 -  
126 - setnonblocking(conn_sock);  
127 - epoll_ctl_add(epfd, conn_sock,  
128 - EPOLLIN | EPOLLET | EPOLLRDHUP |  
129 - EPOLLHUP);  
130 - } else if (events[i].events & EPOLLIN) {  
131 - /* handle EPOLLIN event */  
132 - for (;;) {  
133 - bzero(buf, sizeof(buf));  
134 - n = read(events[i].data.fd, buf,  
135 - sizeof(buf) - 1);  
136 - if (n <= 0 /* || errno == EAGAIN */ ) {  
137 - break;  
138 - } else {  
139 - printf("[+] data: %s\n", buf);  
140 - write(events[i].data.fd, buf,  
141 - strlen(buf));  
142 - }  
143 - }  
144 - } else {  
145 - printf("[+] unexpected\n");  
146 - }  
147 - /* check if the connection is closing */  
148 - if (events[i].events & (EPOLLRDHUP | EPOLLHUP)) {  
149 - printf("[+] connection closed\n");  
150 - epoll_ctl(epfd, EPOLL_CTL_DEL,  
151 - events[i].data.fd, NULL);  
152 - close(events[i].data.fd);  
153 - continue;  
154 - }  
155 - }  
156 - } 81 +void server_run() {
  82 + int i;
  83 + int n;
  84 + int epfd;
  85 + int nfds;
  86 + int listen_sock;
  87 + int conn_sock;
  88 + socklen_t socklen;
  89 + char buf[BUF_SIZE];
  90 + struct sockaddr_in srv_addr;
  91 + struct sockaddr_in cli_addr;
  92 + struct epoll_event events[MAX_EVENTS];
  93 +
  94 + listen_sock = socket(AF_INET, SOCK_STREAM, 0);
  95 +
  96 + set_sockaddr(&srv_addr);
  97 +
  98 + int reuseaddr = 1;
  99 + if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
  100 + sizeof(int)) < 0)
  101 + perror("setsockopt(SO_REUSEADDR)");
  102 +
  103 + if (bind(listen_sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr)) < 0) {
  104 + perror("bind");
  105 + exit(1);
  106 + }
  107 +
  108 + setnonblocking(listen_sock);
  109 + if (listen(listen_sock, MAX_CONN) < 0) {
  110 + perror("listen");
  111 + exit(1);
  112 + }
  113 +
  114 + epfd = epoll_create(1);
  115 + epoll_ctl_add(epfd, listen_sock, EPOLLIN | EPOLLOUT);
  116 +
  117 + socklen = sizeof(cli_addr);
  118 + for (;;) {
  119 + nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
  120 + for (i = 0; i < nfds; i++) {
  121 + if (events[i].data.fd == listen_sock) {
  122 + /* handle new connection */
  123 + conn_sock = accept(listen_sock, (struct sockaddr *)&cli_addr, &socklen);
  124 +
  125 + inet_ntop(AF_INET, (char *)&(cli_addr.sin_addr), buf, sizeof(buf));
  126 + printf("[+] connected with %s:%d\n", buf, ntohs(cli_addr.sin_port));
  127 +
  128 + setnonblocking(conn_sock);
  129 + epoll_ctl_add(epfd, conn_sock,
  130 + EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP);
  131 + } else if (events[i].events & EPOLLIN) {
  132 + /* handle EPOLLIN event */
  133 + for (;;) {
  134 + bzero(buf, sizeof(buf));
  135 + errno = 0;
  136 + n = read(events[i].data.fd, buf, sizeof(buf) - 1);
  137 + if (n == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {
  138 + break;
  139 + } else if (n == 0) {
  140 + break;
  141 + } else {
  142 + printf("[+] data: %s\n", buf);
  143 + n = 0;
  144 + while (n != strlen(buf)) {
  145 + int rv = write(events[i].data.fd, buf + n, strlen(buf) - n);
  146 + if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
  147 + continue; // FIXME: busy waiting - should wait using epoll
  148 + if (rv == -1)
  149 + break;
  150 + n += rv;
  151 + }
  152 + }
  153 + }
  154 + } else {
  155 + printf("[+] unexpected\n");
  156 + }
  157 + /* check if the connection is closing */
  158 + if (events[i].events & (EPOLLRDHUP | EPOLLHUP)) {
  159 + printf("[+] connection closed\n");
  160 + epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
  161 + close(events[i].data.fd);
  162 + continue;
  163 + }
  164 + }
  165 + }
157 } 166 }
158 167
159 /* 168 /*
160 - * test clinet 169 + * test clinet
161 */ 170 */
162 -void client_run()  
163 -{  
164 - int n;  
165 - int c;  
166 - int sockfd;  
167 - char buf[MAX_LINE];  
168 - struct sockaddr_in srv_addr;  
169 -  
170 - sockfd = socket(AF_INET, SOCK_STREAM, 0);  
171 -  
172 - set_sockaddr(&srv_addr);  
173 -  
174 - if (connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)) < 0) {  
175 - perror("connect()");  
176 - exit(1);  
177 - }  
178 -  
179 - for (;;) {  
180 - printf("input: ");  
181 - fgets(buf, sizeof(buf), stdin);  
182 - c = strlen(buf) - 1;  
183 - buf[c] = '\0';  
184 - write(sockfd, buf, c + 1);  
185 -  
186 - bzero(buf, sizeof(buf));  
187 - while (errno != EAGAIN  
188 - && (n = read(sockfd, buf, sizeof(buf) - 1)) > 0) {  
189 - printf("echo: %s\n", buf);  
190 - bzero(buf, sizeof(buf));  
191 -  
192 - c -= n;  
193 - if (c <= 0) {  
194 - break;  
195 - }  
196 - }  
197 - }  
198 - close(sockfd); 171 +void client_run() {
  172 + int n;
  173 + int c;
  174 + int sockfd;
  175 + char buf[MAX_LINE];
  176 + struct sockaddr_in srv_addr;
  177 +
  178 + sockfd = socket(AF_INET, SOCK_STREAM, 0);
  179 +
  180 + set_sockaddr(&srv_addr);
  181 +
  182 + if (connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)) < 0) {
  183 + perror("connect()");
  184 + exit(1);
  185 + }
  186 +
  187 + for (;;) {
  188 + printf("input: ");
  189 + fgets(buf, sizeof(buf), stdin);
  190 + c = strlen(buf);
  191 +
  192 + n = 0;
  193 + while (n != c) {
  194 + errno = 0;
  195 + int rv = write(sockfd, buf + n, c - n);
  196 + if (rv == -1 && (errno == EINTR))
  197 + continue;
  198 + if (rv == -1)
  199 + exit(1);
  200 + n += rv;
  201 + }
  202 +
  203 + errno = 0;
  204 +
  205 + n = 0;
  206 + while (n != c) {
  207 + errno = 0;
  208 + int rv = read(sockfd, buf + n, c - n);
  209 + if (rv == -1 && (errno == EINTR))
  210 + continue;
  211 + if (rv == -1)
  212 + exit(1);
  213 + if (rv == 0)
  214 + break;
  215 + n += rv;
  216 + }
  217 +
  218 + buf[c] = '\0';
  219 + printf("echo: %s\n", buf);
  220 + }
  221 + close(sockfd);
199 } 222 }
200 -