server端:
1#include <unistd.h> 2#include <sys/types.h> /* basic system data types */ 3#include <sys/socket.h> /* basic socket definitions */ 4#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ 5#include <arpa/inet.h> /* inet(3) functions */ 6#include <sys/epoll.h> /* epoll function */ 7#include <fcntl.h> /* nonblocking */ 8#include <sys/resource.h> /*setrlimit */ 9 10#include <stdlib.h> 11#include <errno.h> 12#include <stdio.h> 13#include <string.h> 14 15 16 17#define MAXEPOLLSIZE 10000 18#define MAXLINE 10240 19int handle(int connfd); 20int setnonblocking(int sockfd) 21{ 22 if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) { 23 return -1; 24 } 25 return 0; 26} 27 28int main(int argc, char **argv) 29{ 30 int servPort = 6888; 31 int listenq = 1024; 32 33 int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0; 34 struct sockaddr_in servaddr, cliaddr; 35 socklen_t socklen = sizeof(struct sockaddr_in); 36 struct epoll_event ev; 37 struct epoll_event events[MAXEPOLLSIZE]; 38 struct rlimit rt; 39 char buf[MAXLINE]; 40 41 /* 设置每个进程允许打开的最大文件数 */ 42 rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE; 43 if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 44 { 45 perror("setrlimit error"); 46 return -1; 47 } 48 49 50 bzero(&servaddr, sizeof(servaddr)); 51 servaddr.sin_family = AF_INET; 52 servaddr.sin_addr.s_addr = htonl (INADDR_ANY); 53 servaddr.sin_port = htons (servPort); 54 55 listenfd = socket(AF_INET, SOCK_STREAM, 0); 56 if (listenfd == -1) { 57 perror("can't create socket file"); 58 return -1; 59 } 60 61 int opt = 1; 62 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 63 64 if (setnonblocking(listenfd) < 0) { 65 perror("setnonblock error"); 66 } 67 68 if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 69 { 70 perror("bind error"); 71 return -1; 72 } 73 if (listen(listenfd, listenq) == -1) 74 { 75 perror("listen error"); 76 return -1; 77 } 78 /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */ 79 kdpfd = epoll_create(MAXEPOLLSIZE); 80 ev.events = EPOLLIN | EPOLLET; 81 ev.data.fd = listenfd; 82 if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) 83 { 84 fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd); 85 return -1; 86 } 87 curfds = 1; 88 89 printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq); 90 91 for (;;) { 92 /* 等待有事件发生 */ 93 nfds = epoll_wait(kdpfd, events, curfds, -1); 94 if (nfds == -1) 95 { 96 perror("epoll_wait"); 97 continue; 98 } 99 /* 处理所有事件 */ 100 for (n = 0; n < nfds; ++n) 101 { 102 if (events[n].data.fd == listenfd) 103 { 104 connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen); 105 if (connfd < 0) 106 { 107 perror("accept error"); 108 continue; 109 } 110 111 sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); 112 printf("%d:%s", ++acceptCount, buf); 113 114 if (curfds >= MAXEPOLLSIZE) { 115 fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE); 116 close(connfd); 117 continue; 118 } 119 if (setnonblocking(connfd) < 0) { 120 perror("setnonblocking error"); 121 } 122 ev.events = EPOLLIN | EPOLLET; 123 ev.data.fd = connfd; 124 if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0) 125 { 126 fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno)); 127 return -1; 128 } 129 curfds++; 130 continue; 131 } 132 // 处理客户端请求 133 if (handle(events[n].data.fd) < 0) { 134 epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev); 135 curfds--; 136 137 138 } 139 } 140 } 141 close(listenfd); 142 return 0; 143} 144int handle(int connfd) { 145 int nread; 146 char buf[MAXLINE]; 147 nread = read(connfd, buf, MAXLINE);//读取客户端socket流 148 149 if (nread == 0) { 150 printf("client close the connection\n"); 151 close(connfd); 152 return -1; 153 } 154 if (nread < 0) { 155 perror("read error"); 156 close(connfd); 157 return -1; 158 } 159 write(connfd, buf, nread);//响应客户端 160 return 0; 161}
client端:
1#include <unistd.h> 2#include <sys/types.h> /* basic system data types */ 3#include <sys/socket.h> /* basic socket definitions */ 4#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ 5#include <arpa/inet.h> /* inet(3) functions */ 6#include <sys/select.h> /* select function*/ 7 8#include <stdlib.h> 9#include <errno.h> 10#include <stdio.h> 11#include <string.h> 12 13#define MAXLINE 10240 14#define max(a,b) ((a) > (b) ? (a) : (b)) 15//typedef struct sockaddr SA; 16 17void handle(int sockfd); 18 19int main(int argc, char **argv) 20{ 21 char * servInetAddr = "127.0.0.1"; 22 int servPort = 6888; 23 char buf[MAXLINE]; 24 int connfd; 25 struct sockaddr_in servaddr; 26 27 if (argc == 2) { 28 servInetAddr = argv[1]; 29 } 30 if (argc == 3) { 31 servInetAddr = argv[1]; 32 servPort = atoi(argv[2]); 33 } 34 if (argc > 3) { 35 printf("usage: selectechoclient <IPaddress> <Port>\n"); 36 return -1; 37 } 38 39 connfd = socket(AF_INET, SOCK_STREAM, 0); 40 41 bzero(&servaddr, sizeof(servaddr)); 42 servaddr.sin_family = AF_INET; 43 servaddr.sin_port = htons(servPort); 44 inet_pton(AF_INET, servInetAddr, &servaddr.sin_addr); 45 46 if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { 47 perror("connect error"); 48 return -1; 49 } 50 printf("welcome to selectechoclient\n"); 51 handle(connfd); /* do it all */ 52 close(connfd); 53 printf("exit\n"); 54 exit(0); 55} 56 57 58void handle(int connfd) 59{ 60 FILE* fp = stdin; 61 char sendline[MAXLINE], recvline[MAXLINE]; 62 fd_set rset; 63 FD_ZERO(&rset); 64 int maxfds = max(fileno(fp), connfd) + 1; 65 int nread; 66 for (;;) { 67 FD_SET(fileno(fp), &rset); 68 FD_SET(connfd, &rset); 69 70 if (select(maxfds, &rset, NULL, NULL, NULL) == -1) { 71 perror("select error"); 72 continue; 73 } 74 75 if (FD_ISSET(connfd, &rset)) { 76 //接收到服务器响应 77 nread = read(connfd, recvline, MAXLINE); 78 if (nread == 0) { 79 printf("server close the connection\n"); 80 break; 81 } 82 else if (nread == -1) { 83 perror("read error"); 84 break; 85 } 86 else { 87 //server response 88 write(STDOUT_FILENO, recvline, nread); 89 } 90 } 91 92 if (FD_ISSET(fileno(fp), &rset)) { 93 //标准输入可读 94 if (fgets(sendline, MAXLINE, fp) == NULL) { 95 //eof exit 96 break; 97 } 98 else { 99 write(connfd, sendline, strlen(sendline)); 100 } 101 } 102 103 } 104}