IO复用poll 发表于 2020-03-02 | 分类于 Linux学习 | 阅读次数: | IO复用pollpoll函数123456789int poll(struct pollfd fds[],int len,int timeout);struct pollfd{ int fd; //用户设置关注的文件描述符 short events; //用户关注的事件类型 short revemts; //由内核填充,就绪的事件类型};//成功返回就绪文件描述符的个数,失败返回-1,超时返回0timeout:定时时间 poll所支持的事件类型 服务端123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126#define _GNU_SOURCE#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<assert.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>#include<netinet/in.h>#include<poll.h>#define LEN 100int initsocket(){ int sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1) return -1; struct sockaddr_in ser; memset(&ser,0,sizeof(ser)); ser.sin_family=AF_INET; ser.sin_port=htons(6000); ser.sin_addr.s_addr=inet_addr("127.0.0.1"); int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser)); if(res==-1) return -1; res=listen(sockfd,5); if(res==-1) return -1; return sockfd;}void initfds(struct pollfd *fds){ int i=0; for(;i<LEN;++i) { fds[i].fd=-1; fds[i].events=0; }}void insertfd(struct pollfd *fds,int fd,short events){ int i=0; for(;i<LEN;++i) { if(fds[i].fd==-1) { fds[i].fd=fd; fds[i].events=events; break; } }}void dealfinish_event(struct pollfd *fds,int sockfd){ int i=0; for(;i<LEN;++i) { if(fds[i].fd==-1) continue; else if(fds[i].fd==sockfd) { if(fds[i].revents&POLLIN) { struct sockaddr_in cli; socklen_t len=sizeof(cli); int c=accept(sockfd,(struct sockaddr*)&cli,&len); if(c<0) { printf("accept error\n"); continue; } printf("one client link success\n"); insertfd(fds,c,POLLIN|POLLRDHUP); } } else //客户端连接文件描述符 { if(fds[i].revents&POLLRDHUP) { printf("one client unlink\n"); close(fds[i].fd); fds[i].fd=-1; fds[i].events=0; } else if(fds[i].revents&POLLIN) { char buff[128]={0}; int n=recv(fds[i].fd,buff,127,0); if(n<=0) { printf("recv error\n"); continue; } printf("%d: %s\n",fds[i].fd,buff); send(fds[i].fd,"OK",2,0); } } }}int main(){ int sockfd=initsocket(); assert(sockfd!=-1); struct pollfd fds[LEN]; initfds(fds); insertfd(fds,sockfd,POLLIN); while(1) { int n=poll(fds,LEN,-1);//n>0返回就绪文件描述符的个数 if(n<=0) { printf("poll error\n"); continue; } //看下是不是sockfd,是就接受新的客户端连接,不是就是客户端有数据到达 dealfinish_event(fds,sockfd); }} 客户端12345678910111213141516171819202122232425262728293031323334353637383940414243#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<assert.h>#include<sys/types.h>#include<sys/socket.h>#include<arpa/inet.h>#include<netinet/in.h>int main(){ int sockfd=socket(AF_INET,SOCK_STREAM,0); assert(sockfd!=-1); struct sockaddr_in ser; memset(&ser,0,sizeof(ser)); ser.sin_family=AF_INET; ser.sin_port=htons(6000); ser.sin_addr.s_addr=inet_addr("127.0.0.1"); int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser)); assert(res!=-1); while(1) { printf("please input: "); char buff[128]={0}; fgets(buff,127,stdin); if(strncmp(buff,"end",3)==0) break; send(sockfd,buff,strlen(buff)-1,0); char result[128]={0}; int n=recv(sockfd,result,127,0); if(n<=0) break; printf("result: %s\n",result); } close(sockfd);} 通信测试