epoll实现的回显服务器
服务器端实现:
1 /************************************************************************* 2 > File Name: epoll.c 3 > Created Time: Fri 13 Mar 2015 10:22:19 PM CST 4 ************************************************************************/ 5 #include "utils.h" 6 #include <sys/epoll.h> 7 #include <fcntl.h> 8 9 #define CN 100 10 11 void setnonblocking (int fd) 12 { 13 int op = fcntl(fd, F_GETFL); 14 if (op < 0) 15 { 16 print_error(__func__, __LINE__, strerror(errno)); 17 exit(EXIT_FAILURE); 18 } 19 20 op = op | O_NONBLOCK; 21 22 if (fcntl(fd, F_SETFL, op) < 0) 23 { 24 print_error(__func__, __LINE__, strerror(errno)); 25 exit(EXIT_FAILURE); 26 } 27 } 28 29 int socket_create (int port) 30 { 31 int sk = socket(AF_INET, SOCK_STREAM, 0); 32 if (sk == -1) 33 { 34 print_error(__func__, __LINE__, strerror(errno)); 35 return -1; 36 } 37 38 int on = 1; 39 if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) 40 { 41 print_error(__func__, __LINE__, strerror(errno)); 42 return -1; 43 } 44 45 struct sockaddr_in addr; 46 memset(&addr, 0, sizeof(addr)); 47 addr.sin_family = AF_INET; 48 addr.sin_port = htons(port); 49 addr.sin_addr.s_addr = htonl(INADDR_ANY); 50 51 if (bind(sk, (struct sockaddr*)&addr, sizeof(addr)) == -1) 52 { 53 print_error(__func__, __LINE__, strerror(errno)); 54 return -1; 55 } 56 57 if (listen(sk, 20) == -1) 58 { 59 print_error(__func__, __LINE__, strerror(errno)); 60 return -1; 61 } 62 63 return sk; 64 } 65 66 int socket_accept (int listen_sk) 67 { 68 struct sockaddr_in peeraddr; 69 memset(&peeraddr, 0, sizeof(peeraddr)); 70 socklen_t len = sizeof(peeraddr); 71 int sk; 72 if ((sk = accept(listen_sk, (struct sockaddr*)&peeraddr, &len)) == -1) 73 { 74 print_error(__func__, __LINE__, strerror(errno)); 75 return -1; 76 } 77 78 return sk; 79 } 80 81 82 int socket_recv (int sk) 83 { 84 char buf[BUFSIZE]; 85 memset(buf, 0, BUFSIZE); 86 87 int sz; 88 if ((sz = recv(sk, buf, BUFSIZE, 0)) <= 0) 89 { 90 print_error(__func__, __LINE__, strerror(errno)); 91 return -1; 92 } 93 94 fprintf(stdout, "%s\n", buf); 95 if (send(sk, buf, sz, 0) <= 0) 96 { 97 print_error(__func__, __LINE__, strerror(errno)); 98 return -1; 99 } 100 101 return 0; 102 } 103 104 int main (int argv, char** argc) 105 { 106 if (argv < 2) 107 return EXIT_FAILURE; 108 109 int listen_sk = socket_create(atoi(argc[1])); 110 if (listen_sk == -1) 111 { 112 print_error(__func__, __LINE__, strerror(errno)); 113 close(listen_sk); 114 exit(EXIT_FAILURE); 115 } 116 117 struct epoll_event ev, events[CN]; 118 int epfd = epoll_create(CN); 119 120 setnonblocking(listen_sk); 121 122 ev.data.fd = listen_sk; 123 ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; 124 epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sk, &ev); 125 126 int sk; 127 for (;;) 128 { 129 int nfd = epoll_wait(epfd, events, CN, -1); 130 if (nfd == -1) 131 { 132 print_error(__func__, __LINE__, strerror(errno)); 133 break; 134 } 135 int i; 136 for (i = 0; i < nfd; i++) 137 { 138 if (events[i].data.fd < 0) 139 continue; 140 141 if (events[i].data.fd == listen_sk) 142 { 143 if ((sk = socket_accept(listen_sk)) ==-1) 144 { 145 print_error(__func__, __LINE__, strerror(errno)); 146 break; 147 } 148 setnonblocking(sk); 149 ev.data.fd = sk; 150 ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; 151 152 if (epoll_ctl(epfd, EPOLL_CTL_ADD, sk, &ev) == -1) 153 { 154 print_error(__func__, __LINE__, strerror(errno)); 155 break; 156 } 157 158 continue; 159 } 160 161 if (events[i].events & EPOLLIN) 162 { 163 sk = events[i].data.fd; 164 if (socket_recv(sk) == -1) 165 { 166 close(sk); 167 events[i].data.fd = -1; 168 } 169 } 170 171 if (events[i].events & EPOLLERR) 172 { 173 close(events[i].data.fd); 174 events[i].data.fd = -1; 175 } 176 177 if (events[i].events & EPOLLHUP) 178 { 179 close(events[i].data.fd); 180 events[i].data.fd = -1; 181 } 182 } 183 } 184 185 close(epfd); 186 return EXIT_SUCCESS; 187 }
客户端实现:
1 /************************************************************************* 2 > File Name: echoclt.c 3 > Created Time: Thu 12 Mar 2015 01:15:54 PM CST 4 ************************************************************************/ 5 #include "utils.h" 6 #include <sys/time.h> 7 #include <sys/select.h> 8 9 void echoclt (const char* ip, const int port) 10 { 11 int sk; 12 if ((sk = socket(AF_INET, SOCK_STREAM, 0)) == -1) 13 { 14 print_error(__func__, __LINE__, strerror(errno)); 15 goto end; 16 } 17 18 struct sockaddr_in saddr; 19 memset(&saddr, 0, sizeof(saddr)); 20 saddr.sin_family = AF_INET; 21 saddr.sin_port = htons(port); 22 saddr.sin_addr.s_addr = inet_addr(ip); 23 24 if (connect(sk, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) 25 { 26 print_error(__func__, __LINE__, strerror(errno)); 27 goto end; 28 } 29 30 char buf[BUFSIZE]; 31 //int sz; 32 33 fd_set rset; 34 FD_ZERO(&rset); 35 36 int fn = fileno(stdin); 37 int nr, max; 38 if (sk > fn ) 39 max = sk; 40 else 41 max = fn; 42 43 for (;;) 44 { 45 46 FD_SET(sk, &rset); 47 FD_SET(fn, &rset); 48 if ((nr = select(max + 1, &rset, NULL, NULL, NULL)) == -1) 49 { 50 goto end; 51 } 52 if (FD_ISSET(fn, &rset)) 53 { 54 memset(buf, 0, BUFSIZE); 55 if (fgets(buf, BUFSIZE, stdin) == NULL) 56 { 57 print_error(__func__, __LINE__, strerror(errno)); 58 goto end; 59 } 60 61 62 if (send(sk, buf, strlen(buf), 0) <= 0) 63 { 64 print_error(__func__, __LINE__, strerror(errno)); 65 goto end; 66 } 67 } 68 if (FD_ISSET(sk, &rset)) 69 { 70 memset(buf, 0, BUFSIZE); 71 if (recv(sk, buf, BUFSIZE, 0) <= 0) 72 { 73 print_error(__func__, __LINE__, strerror(errno)); 74 goto end; 75 } 76 fprintf(stdout, "%s", buf); 77 } 78 } 79 end: 80 if (sk) 81 close(sk); 82 } 83 int main (int argv, char** argc) 84 { 85 if (argv <3) 86 { 87 print_error(__func__, __LINE__, NULL); 88 return EXIT_FAILURE; 89 } 90 91 echoclt(argc[1], atoi(argc[2])); 92 return EXIT_SUCCESS; 93 }