IO复用-----poll服务器的实现

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 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YanWenCheng_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值