IO 多路转接 poll

poll:

    int poll(struct pollfd* fds,nfds_t nfds,int timeout)


        fds: 监听的文件描述符  【数组】

            
            struct pollfd  {

                int fd        待监听的文件描述符

                short events    待监听的文件描述符对应的监听事件

                        取值:POLLIN、POLLOUT、POLLERR


                short revents     传入时,给 0 ;若果满足对应事件的话,
    
                        返回非0 --》POLLIN、POLLOUT  POLLERR


            }

        nfds: 监听数组的, 实际有效监听个数

        timeout: 》0 超时时长 单位毫秒

扫描二维码关注公众号,回复: 9294149 查看本文章

             -1 阻塞等待

             0  不阻塞


        返回值:返回对应监听事件的文件描述符  总个数    


    优点:
        
        自带数组结构。可以将 监听事件集合 和 返回事件集合分离

        拓展监听上限。超出 1024 限制

    缺点: 不能跨平台
        
        无法直接定位满足监听事件的文件描述符。 编码难度大

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<errno.h>
#include<poll.h>


#define MAXLINE 80
#define SERV_PORT 8000
#define OPEN_MAX 1024

int main(){
  int i,j,maxi,listenfd,connfd,sockfd;
  int nready;
  size_t n;

  char buf[MAXLINE],str[INET_ADDRSTRLEN];
  socklen_t clilen;

  struct pollfd client[OPEN_MAX];
  struct sockaddr_in cliaddr,servaddr;
  listenfd = socket(AF_INET,SOCK_STREAM,0);

  int opt =1;
  setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
  bzero(&servaddr,sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(SERV_PORT);
  servaddr.sin_addr.s_addr= htonl(INADDR_ANY);
   bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
   listen(listenfd,128);

   client[0].fd = listenfd;   //要监听的第一个文件描述符
   client[0].events = POLLIN; //listenfd 监听普通读事件

   for(i=1;i<OPEN_MAX;++i){
     client[i].fd= -1;        //用-1 初始化client【】里剩余元素

   }
   maxi = 0;

   for(;;){
     nready = poll(client,maxi+1,-1);  //阻塞监听是否有客户端连接请求

     if(client[0].revents & POLLIN){

       clilen = sizeof(cliaddr);
       connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen); //接受客户端请求 不阻塞
       printf("receiverd from %s PORT %d\n",
           inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),
           ntohs(cliaddr.sin_port));
       for(i=1;i<OPEN_MAX;++i){
         if(client[i].fd<0){
           client[i].fd = connfd;
           break;
         }
       }
       client[i].events = POLLIN;
       if(i>maxi)
         maxi =i;
       if(--nready<=0)
         continue;
     }
     for(i =1;i<=maxi;++i){
       if((sockfd=client[i].fd)<0)
         continue;
       if(client[i].revents & POLLIN){
         if((n=read(sockfd,buf,MAXLINE))<0){
           if(errno = ECONNRESET){    //收到RST标志
             printf("client[%d] aborted connection\n",i);
             close(sockfd);
             client[i].fd = -1;

           }else{
             perror("read error");
             exit(1);
           }
         }else if(n==0){
           printf("client[%d] closed connection\n",i);
           close(sockfd);
           client[i].fd = -1;
         }else{
           for(j=0;j<n;++j)
             buf[j]=toupper(buf[j]);
           write(sockfd,buf,n);
           write(STDOUT_FILENO,buf,n);


         }
       }
     }
   }


  
  return 0;
}
发布了78 篇原创文章 · 获赞 10 · 访问量 3813

猜你喜欢

转载自blog.csdn.net/weixin_44374280/article/details/104383465