Linux IO多路复用之epoll网络编程,高并发的使用例子 (含源码)
生活随笔
收集整理的這篇文章主要介紹了
Linux IO多路复用之epoll网络编程,高并发的使用例子 (含源码)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本章節是用基本的Linux基本函數加上epoll調用編寫一個完整的服務器和客戶端例子,可在Linux上運行,客戶端和服務端的功能如下:
客戶端從標準輸入讀入一行,發送到服務端
服務端從網絡讀取一行,然后輸出到客戶端
客戶端收到服務端的響應,輸出這一行到標準輸出
?
服務端
代碼如下:
#include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ #include <arpa/inet.h> /* inet(3) functions */ #include <sys/epoll.h> /* epoll function */ #include <fcntl.h> /* nonblocking */ #include <sys/resource.h> /*setrlimit */#include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h>#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) {int servPort = 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; }下載和編譯
下載地址
編譯和啟動服務端
gcc epollserver.c -o epollserver ./epollserver至于客戶端可以參考本文的Linux/Unix服務端和客戶端Socket編程入門實例的echoclient例子下載編譯。
總結
以上是生活随笔為你收集整理的Linux IO多路复用之epoll网络编程,高并发的使用例子 (含源码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 试比较瀑布模型、快速原型模型、增量模型和
- 下一篇: linux 其他常用命令