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。
代码实现:
1 #include<stdio.h>
2 #include"wrap.h"
3 #include<poll.h>
4 #include<errno.h>
5 #include<signal.h>
6 #define SERV_PORT 8888
7 #define OPEN_MAX 1024
8 int main()
9 {
10 int lfd, cfd;
11 struct sockaddr_in saddr,caddr;
12 struct pollfd client[OPEN_MAX];
13
14 lfd = Socket(AF_INET,SOCK_STREAM,0);
15
16 int option = 1;
17 setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
18
19 bzero(&saddr,sizeof(saddr));
20 saddr.sin_family = AF_INET;
21 saddr.sin_port = htons(SERV_PORT);
22 saddr.sin_addr.s_addr= htonl(INADDR_ANY);
25 Listen(lfd,128);
26
27 client[0].fd = lfd;
28 client[0].events = POLLIN;
29
30 int i=0,j=0,nready;
31 for(i =1;i<OPEN_MAX;i++)
32 client[i].fd=-1;
33
34
35 int maxi=0;
36 while(1)
37 {
38 nready = poll(client ,maxi+1,-1);
39 if(client[0].revents & POLLIN)//(1)如果是监听套接字有事件发生
40 {
41 socklen_t len = sizeof(caddr);
42 cfd = Accept(lfd,(struct sockaddr*)&caddr,&len);
43 char str[64] ;
45 ,ntohs(caddr.sin_port));
46
47 for(i=1;i<OPEN_MAX;i++)//找空闲位置插入客户端描述符
48 if(client[i].fd ==-1)
49 {
50 client[i].fd=cfd;
51 client[i].events=POLLIN;
52 break;
53 }
54 if(i==OPEN_MAX)
55 perr_exit("client fill");//客户端已经最大数了
56 if(i > maxi)
57 maxi = i;
58
59 nready--;
60 if(nready <= 0) //只有一个lfd有事件发生,没必要往下面在执行了;
61 continue;
62 }
63 int n;
64 char buf[BUFSIZ];
65 for( i =1 ;i<= maxi;i++)//(2)lfd之外就是client有事件发生
66 {
67 printf("client[%d] =%d\n",i,client[i].fd);
68 if(client[i].fd == -1)
69 continue;
70
71 if(client[i].revents & POLLIN) //判断每个client是否有事件操作
72 {
73 n = Read(client[i].fd, buf,sizeof(buf));
74 if(n == 0) //客户端关闭或者read出错
75 {
76 printf("client %d closeed\n",i);
77 Close(client[i].fd);
78 client[i].fd =-1;
79 }
80 else //读出数据了
81 {
82 for(j=0;j<n;j++)
83 buf[j] = toupper(buf[j]);
84 Write(client[i].fd,buf,n);
85 }
86
87 nready--;
88 if(nready <=0)
89 break;
90 }
91 }
92
93 }
94
95 }