IO多路复用
select
内容介绍
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| sockfd = socket(AF_INEF,SOCK_STREAM,0); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = hton(2000); addr_sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)); listen(socfd, 5);
for(int i = 0; i < 5; i++) { memset(&client,0,sizeof(client)); addrlen = sizeof(client); fds[i] = accept(sockfd, (struct sockaddr*)&client, &addrlen); if(fds[i] > max) max = fds[i]; }
while(1) { fd_set rset; FD_ZERO(&rest); for(int i=0;i<5;i++) FD_SET(fds[i],&rset); select(max+1, &rest, NULL, NULL, NULL); for(int i=0;i<5;i++) { if(FD_ISSET(fds[i], &rset)) { memset(buffer,0,MAXBUF); read(fds[i],buffer,MAXBUF); puts(buffer); } } }
|
使用内核态来判断那个套接字描述符有数据
缺点:有1024个文件描述符的限制;fd_set不可以重用,每次循环需要重新置位0;内核态复制文件描述符导致文件描述符列表越长需要复制的次数越多;O(n)遍历判断哪个位置的描述符被置位
poll
poll函数格式如下:
1 2
| # include <poll.h> int poll (struct pollfd * fds, unsigned int nfds, int timeout);
|
参数:指向pollfd结构体类型的指针,数组指针
关注的文件描述符的个数
时间
poolfd结构体定义如下
1 2 3 4 5
| struct pollfd { int fd; short events; short revents; } ;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| for(int i=0;i<5;i++) { memset(&client,0, sizeof(client)); addrlen = sizeof(client); pollfds[i].fd = accept(sockfd, (struct sockaddr*)&client, &addrlen); pollfds[i].events = POLLIN; } sleep(1); while(1) { poll(pollfds, 5, 50000); for(int i=0;i<5;i++) { if(pollfds[i].revents & POLLIN) { pollfds[i].revents = 0; } } }
|
epoll
epoll函数原理详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| struct epoll_event events[5]; int c = epoll_create1(10); int epfd = epoll_create(10);//创建一个epoll对象,返回文件描述符,参数只要大于0即可 ....... ....... for(int i=0;i<5;i++) { static struct epoll_event ev; //临时变量 memset(&client, 0, sizeof(client)); addrlen = sizeof(client); ev.data.fd = accept(sockfd, (struct sockaddr*)&client, &addrlen); //监听的套接字文件描述符 ev.events = EPOLLIN; //监听事件是读事件 epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev); }
while(1) { nfds = epoll_wait(epfd, events, 5, 10000); for(i=0;i<ndfs;i++) { //处理数据 } }
|