unix-poll
Posted illfuckingkyzb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unix-poll相关的知识,希望对你有一定的参考价值。
poll的用法和select差不多,但是select的最大文件描述符是由FD_SETSIZE限制,若要改变,那么还得修改宏定义,重新编译内核,很麻烦,但是poll可以通过
ulimit -n xxx //修改文件描述符个数
poll使用链表保存文件描述符
poll和select的缺点是一样的,仍然要采用轮询的方式
看代码
//我们这里的客户端只建立连接,每建立一个连接count就加1; #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include<sys/select.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include<iostream> using namespace std; int main(){ int count=0; while(1){ int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket() err"); return -1; } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(8888); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("socket() err"); return -1; } cout<<++count<<endl; } return 0; }
#include<stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include<iostream> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include<sys/select.h> #include<errno.h> #include<sys/poll.h> #include<sys/signal.h> using namespace std; void handler(int sig){ cout<<sig<<endl; } int main() { signal(SIGPIPE,SIG_IGN); //signal(SIGPIPE,handler); int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket() err"); return -1; } int on = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { perror("setsockopt() err"); return -1; } char recvbuf[1024]; int conn; struct pollfd client[2048]; for(int i=0;i<2048;i++){ client[i].fd=-1; } struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(8888); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { perror("bind() err"); return -1; } if (listen(sockfd, SOMAXCONN) == -1) { perror("bind() err"); return -1; } struct sockaddr_in peeraddr; int nready; client[0].fd=sockfd;//设置监听位 client[0].events=POLLIN;//设置我们感兴趣的事件为读取事件 int maxi=0; while(1){ int i; nready=poll(client,maxi+1,-1); if(client[0].revents&POLLIN){ socklen_t peerlen = sizeof(peeraddr); conn=accept(sockfd,(struct sockaddr *) &peeraddr, &peerlen); printf("ip=%s port=%d ",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); for( i=0;i<2048;i++){ if(client[i].fd<0){ client[i].fd=conn; if(i>maxi) maxi=i; break; } } client[i].events=POLLIN;//将conn的事件也设为POLLIN if(--nready<=0) continue; } for(int i=1;i<=maxi;i++){ conn=client[i].fd; if(conn==-1) continue; if(client[i].events&POLLIN){ int rc = read(conn, recvbuf, sizeof(recvbuf)); if (rc == 0) { cout<<"client has closed"<<endl; client[i].fd=-1; close(conn); } else{ printf("recv message:%s ", recvbuf); write(conn, recvbuf, rc); memset(recvbuf, 0, sizeof(recvbuf)); if(--nready<=0) break; } } } } close(conn); close(sockfd); return 0; }
接着分别在客户端终端窗口和服务器终端窗口输入
ulimit -n 2048
接着启动服务端和客户端
看一看到输出了2045,其中0,1,2已被标准输入输出和错误流占用
以上是关于unix-poll的主要内容,如果未能解决你的问题,请参考以下文章