linux 下 poll 编程

  poll 与 select 很类似,都是对描述符进行遍历,查看是否有描述符就绪。如果有就返回就绪文件描述符的个数将。poll 函数如下:

  #include <poll.h>

  int poll(struct pollfd *fdarray, unsigned long nfds, int timeout)

  第一个参数指向结构数组第一个元素的指针,每个数组都是一个 pollfd 结构iouyonghu制定额是某个给定描述符的条件。

  struct pollfd

  {

    int fd;

    short events;//关心 fd 上发生的事件

    short revents;//fd 实际上上发生的事件

  }

  第二个参数 nfds 制定数组中元素个数。第三个参数指定 poll 函数返回前等待多长时间。 INFTIM 表示永远等待, 0 代表立即返回, > 0 等待指定数目的秒数。

  poll 编程实例,这是 TCP 连接服务器端代码:

  1 #include <sys/socket.h>
  2 #include <netinet/in.h>
  3 #include <stdio.h>
  4 #include <error.h>
  5 #include <errno.h>
  6 #include <unistd.h>
  7 #include <string.h>
  8 #include <stdlib.h>
  9 #include <sys/wait.h>
 10 #include <limits.h>
 11 #include <poll.h>
 12 #include <sys/stropts.h>
 13 #include <signal.h>
 14 #define MAXLINE 5
 15 #define OPEN_MAX 1024
 16 #define SA struct sockaddr
 17 
 18 
 19 int main()
 20 {
 21     int listenfd, connfd, sockfd, i, maxi;
 22     int nready;
 23     socklen_t clilen;
 24     ssize_t n;
 25     char buf[MAXLINE];
 26     struct pollfd client[OPEN_MAX];
 27     struct sockaddr_in servaddr, cliaddr;
 28     //创建监听套接字
 29     if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 30     {
 31         printf("socket() error!");
 32         exit(0);
 33     }
 34     //先要对协议地址进行清零
 35     bzero(&servaddr,sizeof(servaddr));
 36     //设置为 IPv4 or IPv6
 37     servaddr.sin_family = AF_INET;
 38     //绑定本地端口号
 39     servaddr.sin_port    = htons(9805);
 40     //任何一个 IP 地址,让内核自行选择
 41     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 42     //绑定套接口到本地协议地址
 43     if(bind(listenfd, (SA *) &servaddr,sizeof(servaddr)) < 0)
 44     {
 45         printf("bind() error!");
 46         exit(0);
 47     }
 48     //服务器开始监听
 49     if(listen(listenfd,5) < 0)
 50     {
 51         printf("listen() error!");
 52         exit(0);
 53     }
 54     client[0].fd = listenfd;
 55     client[0].events = POLLRDNORM;//关心监听套机字的读事件
 56     for(i = 1; i < OPEN_MAX; ++i)
 57     {
 58         client[i].fd = -1;
 59     }
 60     maxi = 0;
 61     for(;;)
 62     {
 63         nready = poll(client, maxi + 1, -1);
 64         if(client[0].revents & POLLRDNORM)
 65         {
 66             clilen = sizeof(cliaddr);
 67             //accept 的后面两个参数都是值-结果参数,他们的保留的远程连接电脑的信息,如果不管新远程连接电脑的信息,可以将这两个参数设置为 NULL
 68             connfd = accept(listenfd, (SA *) &cliaddr, &clilen);
 69             if(connfd < 0)
 70             {
 71                 continue;
 72             }
 73             for(i = 1; i < OPEN_MAX; ++i)
 74             {
 75                 if(client[i].fd < 0)
 76                     client[i].fd = connfd;
 77                 break;
 78             }
 79             if(i == OPEN_MAX)
 80             {
 81                 printf("too many clients");
 82                 exit(0);
 83             }
 84             client[i].events = POLLRDNORM;
 85             if(i > maxi)
 86             {
 87                 maxi = i;
 88             }
 89             if(--nready <=0 )
 90                 continue;
 91         }
 92         for(i = 1; i < OPEN_MAX; ++i)
 93         {
 94             if((sockfd = client[i].fd) < 0)
 95             {
 96                 continue;
 97             }
 98             if(client[i].revents & POLLRDNORM | POLLERR)
 99             {
100                 if((n = read(sockfd, buf, MAXLINE)) < 0)
101                 {
102                     if(errno == ECONNRESET)
103                     {
104                         close(sockfd);
105                         client[i].fd = -1;
106                     }
107                     else
108                     {
109                         printf("read error!\n");
110                     }
111                 }
112                 else if(n == 0)
113                 {
114                     close(sockfd);
115                     client[i].fd = -1;
116                 }
117                 else
118                 {
119                     write(sockfd, buf,  n);
120                 }
121                 if(--nready <= 0)
122                     break;
123             }
124         }
125     }
126 }

  配合 linux 下 select 编程 就是一个完整的客户端/服务器端代码了,运行结果截图如下:

  客户端:

  技术分享

  服务器端:

  技术分享  

    

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。