Linux IO多路复用之epoll网络编程(含源码)
来源:互联网 发布:查看占用80端口的进程 编辑:程序博客网 时间:2024/05/16 20:27
前言
本章节是用基本的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 10240int 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例子下载编译。
阅读全文
0 0
- Linux IO多路复用之epoll网络编程(含源码)
- Linux IO多路复用之epoll网络编程(含源码)
- Linux IO多路复用之epoll网络编程(含源码)
- Linux IO多路复用之epoll网络编程(含源码)
- Linux IO多路复用之epoll网络编程(含源码)
- Linux IO多路复用之epoll网络编程(含源码)
- Linux IO多路复用之epoll网络编程,高并发的使用例子 (含源码)
- Linux/Unix IO多路复用之poll网络编程(含源码)
- Linux/Unix IO多路复用之select网络编程(含源码)
- Linux/Unix IO多路复用之select网络编程(含源码)
- Linux/Unix IO多路复用之poll网络编程(含源码)
- Linux IO多路复用之epoll网络编程
- (转)Linux IO多路复用之epoll网络编程
- linux网络编程 IO多路复用 select epoll
- 【网络编程】IO 多路复用之 epoll 总结
- python网络编程--IO多路复用之epoll
- python网络编程——IO多路复用之epoll
- python网络编程——IO多路复用之epoll
- vi 和 vim 编辑器的使用
- 给单元素艺术添加动画
- 大数据平台搭建-简单说
- Functional GPU Algorithm
- Android NDK 开发:实战案例
- Linux IO多路复用之epoll网络编程(含源码)
- golang -- slice元素去重
- Github遇到Permanently added the RSA host key for IP address '192.30.252.128' to the list of known host
- Python3 执行Linux Bash命令
- 数据库(第一范式,第二范式,第三范式)
- Rightware的Kanzi界面很快你的全液晶汽车仪表盘
- Python的序列(2)-元组
- CommonsMultipartFile 文件上传
- HDU 6126 Give out candies (贼巧妙的最小割)