Linux复用I/O-poll-server代码
2017-08-31 09:23
302 查看
poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多。
poll
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);//第一个参数,传入的是一个结构体数组。
struct pollfd {
int fd; /* 文件描述符*/
short events; /* 监控的事件*/
short revents; /* 监控事件中满足条件返回的事件*/
};
//监控事件的类型
POLLIN普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
POLLRDNORM-数据可读
POLLRDBAND-优先级带数据可读
POLLPRI 高优先级可读数据
POLLOUT普通或带外数据可写
POLLWRNORM-数据可写
POLLWRBAND-优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件
nfds 监控数组中有多少文件描述符需要被监控
timeout 毫秒级等待
-1:阻塞等,#define INFTIM -1 Linux中没有定义此宏
0:立即返回,不阻塞进程
>0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值
如果不再监控某个文件描述符时,可以把pollfd中,fd设置为-1,poll不再监控此
pollfd,下次返回时,把revents设置为0。
ppoll GNU定义了ppoll(非POSIX标准),可以支持设置信号屏蔽字,大家可参考poll模型自行实现C/S
poll
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);//第一个参数,传入的是一个结构体数组。
struct pollfd {
int fd; /* 文件描述符*/
short events; /* 监控的事件*/
short revents; /* 监控事件中满足条件返回的事件*/
};
//监控事件的类型
POLLIN普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
POLLRDNORM-数据可读
POLLRDBAND-优先级带数据可读
POLLPRI 高优先级可读数据
POLLOUT普通或带外数据可写
POLLWRNORM-数据可写
POLLWRBAND-优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件
nfds 监控数组中有多少文件描述符需要被监控
timeout 毫秒级等待
-1:阻塞等,#define INFTIM -1 Linux中没有定义此宏
0:立即返回,不阻塞进程
>0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值
如果不再监控某个文件描述符时,可以把pollfd中,fd设置为-1,poll不再监控此
pollfd,下次返回时,把revents设置为0。
ppoll GNU定义了ppoll(非POSIX标准),可以支持设置信号屏蔽字,大家可参考poll模型自行实现C/S
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <ctype.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <arpa/inet.h> #include <netinet/in.h> #include <poll.h> #include <errno.h> #define SERVER_PORT 8000 #define LISTEN_LEN 128 #define BUF_SIZE 1500 #define FD_MAX 1024 //select 最大限制1024 int main(int argc , char * argv[]) { struct sockaddr_in serveraddr,clientaddr; int maxfd,flag,ready;//maxfd打开的最大文件描述符,flag是client数组中有内容的最大下标,ready存放有事件发生的个数 int listenfd,clientfd,tempfd; int cliaddr_len,len; int i,j; char ipstr[128],buf[BUF_SIZE]; struct pollfd cliARR[FD_MAX]; /*创建socket*/ listenfd = socket(AF_INET,SOCK_STREAM,0); /*初始化bzero*/ bzero(&serveraddr,sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(SERVER_PORT); /*绑定bind()*/ bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); listen(listenfd,LISTEN_LEN); cliARR[0].fd = listenfd; cliARR[0].events = POLLRDNORM;//listen监听事件 for(i = 1;i<FD_MAX;i++) cliARR[i].fd=-1; flag = 0; for( ; ; ){ ready = poll(cliARR,flag+1,-1); /*阻塞*/ if(cliARR[0].revents & POLLRDNORM){
//判断listenfd是否有数据到达 cliaddr_len = sizeof(clientaddr); clientfd = accept(listenfd,(struct sockaddr*)&clientaddr,&cliaddr_len); printf("client IP:%s\tPORT:%d\n", inet_ntop(AF_INET, &clientaddr.sin_addr, ipstr, sizeof(ipstr)), ntohs(clientaddr.sin_port)); for(i = 1;i<FD_MAX;i++) if(cliARR[i].fd<0){ cliARR[i].fd = clientfd; break; } if(i == FD_MAX){ printf("too many cliens\n"); exit(-1); } cliARR[i].events = POLLRDNORM; if(i>flag) flag = i; if(--ready == 0) continue; }
//接收普通socket的数据 for(i=1;i<=flag;i++){ if((tempfd = cliARR[i].fd)<0) continue; if(cliARR[i].revents&(POLLRDNORM | POLLERR)){ if((len = read(tempfd,buf,sizeof(buf)))<0){ if(errno == ECONNRESET){ close(tempfd); cliARR[i].fd=-1; }else{ perror("read ERROR"); exit(-1); } }else if(len == 0){ close(tempfd); cliARR[i].fd=-1; }else{ for(j = 0;j<len;j++) buf[j]=toupper(buf[j]); write(tempfd,buf,len); } if(--ready == 0) break; } } } close(listenfd); return 0; }
相关文章推荐
- Linux复用I/O-Select-server代码
- Linux复用I/O-epoll-server代码
- Linux中I/O复用——poll函数详解及代码实现
- Linux环境C/C++起Socket Server监听8080端口的代码实现
- Linux下多路复用IO接口epoll/select/poll的区别
- Linux网络编程---I/O复用模型之poll
- Linux I/O 模型---I/O复用:Select和Poll函数
- linux device drive 第六章代码示例-scullpipe的实验(poll和fasync方法的实现)之二
- [转载] Linux下多路复用IO接口 epoll select poll 的区别
- Linux下多路复用IO接口 epoll select poll 的区别
- Linux中I/O复用——epoll函数详解及代码实现
- Socket Server 代码, Window/Linux
- linux device drive 第六章代码示例-scullpipe的实验(poll和fasync方法的实现)之三
- 多路复用I/O模型poll() 模型 代码实现
- IO复用,linux poll
- Linux高性能server编程——I/O复用
- Unix网络编程代码 第6章 I/O复用:select、poll和epoll函数
- linux基础——linux下多路IO复用接口之select/poll
- Linux IO多路复用之epoll网络编程基本代码
- Linux的I/O多路复用机制之--select&poll