Linux 下 poll模型
来源:互联网 发布:大数据专业课程设置 编辑:程序博客网 时间:2024/06/05 08:19
poll调用和select调用实现的功能一样,都是网络IO利用的一种机制。poll() 没有像 select() 构建 fd_set 结构体的 3 个数组 ( 针对每个条件分别有一个数组 : 可读性、可写性和错误条件 ) ,然后检查从 0 到 nfds 每个文件描述符。
先看一下poll的调用形式
一,poll调用
二,参数说明
fds:存放需要被检测状态的Socket描述符;与select不同(select函数在调用之后,会清空检测socket描述符的数组),每当调用这个函数之后,系统不会清空这个数组,而是将有状态变化的描述符结构的revents变量状态变化,操作起来比较方便;
nfds:用于标记数组fds中的struct pollfd结构元素的总数量;
timeout:poll函数调用阻塞的时间,单位是MS(毫秒)
struct pollfd结构如下:【在源码文件poll.h文件中】
这个结构中
fd表示文件描述符,
events表示请求检测的事件位掩码,
常量说明POLLIN普通或优先级带数据可读POLLRDNORM普通数据可读POLLRDBAND优先级带数据可读POLLPRI高优先级数据可读POLLOUT普通数据可写POLLWRNORM普通数据可写POLLWRBAND优先级带数据可写POLLERR发生错误POLLHUP发生挂起POLLNVAL描述字不是一个打开的文件注意:后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中。
revents表示检测之后返回的事件位掩码,如果当某个文件描述符有状态变化时,revents的值就不为空。
三,返回值
- 大于0:表示数组fds中有socket描述符的状态发生变化,或可以读取、或可以写入、或出错。并且返回的值表示这些状态有变化的socket描述符的总数量;此时可以对fds数组进行遍历,以寻找那些revents不空的socket描述符,然后判断这个里面有哪些事件以读取数据。
- 等于0:表示没有socket描述符有状态变化,并且调用超时。
- 小于0:此时表示有错误发生,此时全局变量errno保存错误码。
服务端
#include <stdio.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h> /* See NOTES */#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h> /* superset of previous */#include <sys/time.h>#include <arpa/inet.h>#include <poll.h>#define backlog 5#define BUFFSIZE 1024int create_listenfd(const char *ip, unsigned short port){ int listenfd = socket(PF_INET, SOCK_STREAM, 0); if(-1 == listenfd) { perror("socket"); return -1; } struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); serv_addr.sin_addr.s_addr = (ip == NULL ? INADDR_ANY :inet_addr(ip)); if(-1 == bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) { perror("bind"); close(listenfd); return -1; } printf("bind success!\n"); if(-1 == listen(listenfd, backlog)) { perror("listen"); close(listenfd); return -1; } printf("listening ...\n"); return listenfd;}int main(int argc, char *argv[]){ int listenfd = create_listenfd(NULL,atoi(argv[2])); if(-1 == listenfd) { return 0; } char buff[BUFFSIZE]; int recvbytes, sendbytes; struct pollfd eventfds[BUFFSIZE]; memset(eventfds, 0, sizeof(eventfds)); eventfds[0].fd = STDIN_FILENO; eventfds[0].events = POLLIN; eventfds[1].fd = listenfd; eventfds[1].events = POLLIN; while(1) { int ret = poll(eventfds, BUFFSIZE, 3*1000); if(-1 == ret) { perror("poll"); break; } else if(0 == ret) { printf("timeout...\n"); } else { for(int i = 0; i <= BUFFSIZE; i++) { int fd = eventfds[i].fd; if(eventfds[i].revents & POLLIN) { if(fd == STDIN_FILENO) { fgets(buff, sizeof(buff), stdin); printf("gets:%s",buff); } else if(fd == listenfd) { int connectfd = accept(listenfd, NULL, NULL); if(-1 == connectfd) { perror("accept"); close(listenfd); return 0; } printf("A new client(fd=%d) is connect success!\n", connectfd); eventfds[connectfd - listenfd + 1].fd = connectfd; eventfds[connectfd - listenfd + 1].events = POLLIN; } else { recvbytes = recv(fd, buff, sizeof(buff), 0); if(recvbytes < 0) { perror("recv"); eventfds[i].events = 0; eventfds[i].fd = -1; close(fd); break; } if(recvbytes == 0) { printf("client(fd=%d) is closed!\n", fd); eventfds[i].events = 0; eventfds[i].fd = -1; close(fd); break; } printf("server recv from client(fd=%d):%s", fd, buff); } } } } } close(listenfd); return 0;}
客户端
#include <stdio.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h> /* See NOTES */#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h> /* superset of previous */#define backlog 5#define BUFFSIZE 1024int main(int argc, char *argv[]){ int sockfd = socket(PF_INET, SOCK_STREAM, 0); if(-1 == sockfd) { perror("socket"); exit(EXIT_FAILURE); } struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(atoi(argv[2])); serv_addr.sin_addr.s_addr = inet_addr(argv[1]); if(-1 == connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) { perror("connect"); close(sockfd); exit(EXIT_FAILURE); } printf("connect success!\n"); char buff[BUFFSIZE]; int recvbytes, sendbytes; while(1) { fgets(buff, sizeof(buff), stdin); if(0 == strncmp(buff, "quit", 4)) { printf("client quit!\n"); break; } sendbytes = send(sockfd, buff, strlen(buff)+1, 0); if(sendbytes <= 0) { perror("send"); break; } } close(sockfd); return 0;}
运行
./server 127.0.0.1 8888
./client 127.0.0.1 8888
./client 127.0.0.1 8888
./client 127.0.0.1 8888
./client 127.0.0.1 8888
阅读全文
0 0
- Linux 下 poll模型
- 浅谈Linux下select/poll模型
- Linux网络poll模型
- Linux c++ poll 模型
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- Linux下select, poll和epoll IO模型的详解
- 遥感影像镶嵌-黑边去除-无效区域去除方法
- MyBatis与Hibernate的区别
- 斐波那契数列推导及应用
- MATLAB——scatter的简单应用
- 深入理解JVM之二:垃圾收集器概述
- Linux 下 poll模型
- python加密
- error An unexpected error occurred: "https://registry.yarnpkg.com/react-native: connect ETIMEDOUT 10
- java中抽象类和接口的区别
- 【转】秒懂,Java 注解 (Annotation)你可以这样学
- Trailing Zeroes (III)
- 服务器模型
- c++实现双向链表
- sql server查询NodeId字段中距离某一时间最近的所有数据