本文主要是介绍多路IO复用--Poll,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
poll
相对与select 优点:
- 定义简单,只需要数组
- pollfd结构包含了要监视的events和内核返回的的revent,不再使用select“参数-值”传递的方式. 接口使用比select更方便
缺点:
- poll返回后,需要轮询pollfd来获取就绪的描述符,对IO的数量有限制,IO数量越多,性能越差
api
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
- fds是一个poll函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返回的事件集合.
- nfds表示fds数组的长度
- timeout表示poll函数的超时时间, 单位是毫秒
- return: 返回值大于0, 表示poll由于监听的文件描述符就绪而返回
pollfd结构:
struct pollfd {int fd; /* file descriptor */short events; /* requested events */short revents; /* returned events */
};
fd是哪个文件描述符,events:用户告诉内核你要帮我关注哪个文件描述符上的什么事件,revent:内核告诉用户,文件描述符上的事件已经就绪了
events和revents的取值:
POLLIN:数据(包括普通数据和优先数据), 可读可写
code
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <string.h>
int main() {int listenfd = socket(AF_INET, SOCK_STREAM, 0); // if (listenfd == -1) return -1;struct sockaddr_in servaddr;servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(9999);if (-1 == bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) {return -2;}listen(listenfd, 10);struct pollfd fds[POLL_SIZE] = {0};fds[sockfd].fd =sockefd;fds[sockfd].events = POLLIN;int maxfd = sockfd;int clientfd = 0;while (1) {int nready = poll(fds,maxfd+1,-1);if (fds[sockfd].revents & POLLIN) {clientfd = accept(listenfd, (struct sockaddr*)&client, &len);fds[clientfd].fd = clientfd;fds[clientfd].events = POLLIN;if(clientfd > maxfd)maxfd = clientfd;if(--nready) continue;} int i = 0;for (i = 0; i <= maxfd;i ++) {if(fds[i].revents & POLLIN) {char buffer[1024] = {0};int ret = recv(clientfd,buffer,1024,0);if(ret == 0) {fds[clientfd].fd = -1;close(clientfd);break;}printf("ret = %d, buffer:%s\n",ret,buffer);send(clientfd,buffer,ret,0);}}}
}
这篇关于多路IO复用--Poll的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!