epoll例程——简单的server和client

客户端从标准输入读入一行,发送到服务端
服务端从网络读取一行,然后输出到客户端
【epoll例程——简单的server和client】 客户端收到服务端的响应,输出这一行到标准输出

服务端 代码如下:
epoll例程——简单的server和client
文章图片

#include #include/* basic system data types */ #include/* basic socket definitions */ #include/* sockaddr_in{} and other Internet defns */ #include/* inet(3) functions */ #include/* epoll function */ #include /* nonblocking */ #include/*setrlimit */#include #include #include #include #define MAXEPOLLSIZE 10000 #define MAXLINE 10240 int handle(int connfd); int setnonblocking(int sockfd) { if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) { return -1; } return 0; }int main(int argc, char **argv) { intservPort = 6888; int listenq = 1024; int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0; struct sockaddr_in servaddr, cliaddr; socklen_t socklen = sizeof(struct sockaddr_in); struct epoll_event ev; struct epoll_event events[MAXEPOLLSIZE]; struct rlimit rt; char buf[MAXLINE]; /* 设置每个进程允许打开的最大文件数 */ rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE; if (setrlimit(RLIMIT_NOFILE, &rt) == -1) { perror("setrlimit error"); return -1; }bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl (INADDR_ANY); servaddr.sin_port = htons (servPort); listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd == -1) { perror("can't create socket file"); return -1; }int opt = 1; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (setnonblocking(listenfd) < 0) { perror("setnonblock error"); }if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) { perror("bind error"); return -1; } if (listen(listenfd, listenq) == -1) { perror("listen error"); return -1; } /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */ kdpfd = epoll_create(MAXEPOLLSIZE); ev.events = EPOLLIN | EPOLLET; ev.data.fd = listenfd; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) { fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd); return -1; } curfds = 1; printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq); for (; ; ) { /* 等待有事件发生 */ nfds = epoll_wait(kdpfd, events, curfds, -1); if (nfds == -1) { perror("epoll_wait"); continue; } /* 处理所有事件 */ for (n = 0; n < nfds; ++n) { if (events[n].data.fd == listenfd) { connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen); if (connfd < 0) { perror("accept error"); continue; }sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); printf("%d:%s", ++acceptCount, buf); if (curfds >= MAXEPOLLSIZE) { fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE); close(connfd); continue; } if (setnonblocking(connfd) < 0) { perror("setnonblocking error"); } ev.events = EPOLLIN | EPOLLET; ev.data.fd = connfd; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0) { fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno)); return -1; } curfds++; continue; } // 处理客户端请求 if (handle(events[n].data.fd) < 0) { epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev); curfds--; } } } close(listenfd); return 0; } int handle(int connfd) { int nread; char buf[MAXLINE]; nread = read(connfd, buf, MAXLINE); //读取客户端socket流if (nread == 0) { printf("client close the connection\n"); close(connfd); return -1; } if (nread < 0) { perror("read error"); close(connfd); return -1; } write(connfd, buf, nread); //响应客户端 return 0; }

epoll例程——简单的server和client
文章图片
客户端 代码如下:
epoll例程——简单的server和client
文章图片
#include #include/* basic system data types */ #include/* basic socket definitions */ #include/* sockaddr_in{} and other Internet defns */ #include/* inet(3) functions */ #include /*gethostbyname function */#include #include #include #include #define MAXLINE 1024void handle(int connfd); int main(int argc, char **argv) { char * servInetAddr = "127.0.0.1"; int servPort = 6888; char buf[MAXLINE]; int connfd; struct sockaddr_in servaddr; if (argc == 2) { servInetAddr = argv[1]; } if (argc == 3) { servInetAddr = argv[1]; servPort = atoi(argv[2]); } if (argc > 3) { printf("usage: echoclient \n"); return -1; }connfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(servPort); inet_pton(AF_INET, servInetAddr, &servaddr.sin_addr); if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { perror("connect error"); return -1; } printf("welcome to echoclient\n"); handle(connfd); /* do it all */ close(connfd); printf("exit\n"); exit(0); }void handle(int sockfd) { char sendline[MAXLINE], recvline[MAXLINE]; int n; for (; ; ) { if (fgets(sendline, MAXLINE, stdin) == NULL) { break; //read eof } /* //也可以不用标准库的缓冲流,直接使用系统函数无缓存操作 if (read(STDIN_FILENO, sendline, MAXLINE) == 0) { break; //read eof } */n = write(sockfd, sendline, strlen(sendline)); n = read(sockfd, recvline, MAXLINE); if (n == 0) { printf("echoclient: server terminated prematurely\n"); break; } write(STDOUT_FILENO, recvline, n); //如果用标准库的缓存流输出有时会出现问题 //fputs(recvline, stdout); } }

epoll例程——简单的server和client
文章图片




下载和编译 下载地址
编译和启动服务器:
gcc echoserver.c -o echoserver ./echoserver

编译和启动客户端
gcc echoclient.c -o echoclient ./echoclient

    推荐阅读