I/O复用方法——poll

poll

poll 系统调用和 select 类似,也是在指定时间内轮询一定数量的文件描述符,以测试其中是否有就绪者。

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

select 和 poll 的区别:

  1. 在内核实现上,两者都采用轮询方式;时间复杂度:O(n)。
  2. select 传的是一个集合,上限1024;
    poll 支持更多的描述符;因为它传的是一个数组可以动态开辟。
  3. select 支持三种事件类型,读、写、异常;
    poll支持更多的事件类型。

在这里插入图片描述

poll服务器代码:

  1 #define _GNU_SOURCE
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <unistd.h>
  5 #include <string.h>
  6 #include <assert.h>
  7 #include <sys/socket.h>
  8 #include <netinet/in.h>
  9 #include <arpa/inet.h>
 10 #include <poll.h>
 11 
 12 #define MAX  10
 13 void fds_init(struct pollfd fds[])//初始化  清空数组
 14 {
 15     for( int i = 0; i < MAX; i++ )
 16     {
 17         fds[i].fd = -1;//文件描述符
 18         fds[i].events = 0;//注册的事件
 19         fds[i].revents = 0;//实际发生的事件
 20     }
 21 }
 22 
 23 void fds_add(struct pollfd fds[], int fd)//添加描述符
 24 {
 25     for( int i = 0; i< MAX; i++ )
 26     {
 27         if ( fds[i].fd == -1 )
 28         {
 29             fds[i].fd = fd;
 30             fds[i].events = POLLIN | POLLRDHUP;
 31             fds[i].revents = 0;
 32             break;
 33 }
 34     }
 35 }
 36 void fds_del(struct pollfd fds[], int fd )
 37 {
 38     for( int i = 0; i < MAX; i++ )
 39     {
 40         if ( fds[i].fd  == fd )
 41         {
 42             fds[i].fd = -1;
 43             fds[i].events = 0;
 44             fds[i].revents = 0;
 45             break;
 46         }
 47     }
 48 }
 49 int socket_init();
 50 int main()
 51 {
 52     int sockfd = socket_init();
 53     assert( sockfd != -1 );
 54 
 55     struct pollfd fds[MAX];//描述符数组
 56     fds_init(fds);
 57 
 58     fds_add(fds,sockfd);//将sockfd添加到fds数组中
 59 
 60     while( 1 )
 61     {
 62         int n = poll(fds,MAX,5000);//
 63         if ( n == -1 )
 64         {
 65             continue;
 66         }
 67         else if ( n == 0 )
 68         {
 69             printf("time out\n");
 70             continue;
 71         }
 72         else
 73         {
 74             for( int i = 0; i < MAX; i++ )
 75             {
 76                 if ( fds[i].fd == -1 )
 77                 {
 78                     continue;
 79                 }
 80 
 81                 if ( fds[i].revents & POLLRDHUP )
 82                 {
 83                         close(fds[i].fd);
 84                         fds_del(fds,fds[i].fd);
 85                         printf("client hup close\n");
 86                         continue;
 87
 88                 }
 89                 if ( fds[i].revents & POLLIN )
 90                 {
 91                     if ( fds[i].fd == sockfd )//accept
 92                     {
 93                         struct sockaddr_in caddr;
 94                         int len = sizeof(caddr);
 95                         int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
 96                         if ( c < 0 )
 97                         {
 98                             continue;
 99                         }
100                         printf("accept c=%d\n",c);
101                         fds_add(fds,c);
102                     }
103                     else//recv
104                     {
105                         char buff[128] = {0};
106                         int num = recv(fds[i].fd,buff,127,0);
107                         if ( num <= 0 )
108                         {
109                             close(fds[i].fd);
110                             fds_del(fds,fds[i].fd);
111                             printf("client close\n");
112                         }
113                         else
114                         {
115                             printf("read(%d)=%s\n",fds[i].fd,buff);
116                             send(fds[i].fd,"ok",2,0);
117                         }
118                     }
119                 }
120             }
121         }
122     }
123 
124 
125 }
126 int socket_init()
127 {
128     int sockfd = socket(AF_INET,SOCK_STREAM,0);//创建套接字
129     if ( sockfd  == -1 )
130     {
131         return -1;
132     }
133 
134     struct sockaddr_in saddr;
135     memset(&saddr,0,sizeof(saddr));
136     saddr.sin_family = AF_INET;
137     saddr.sin_port = htons(6000);
138     saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
139 
140     int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//绑定
141     if ( res == -1 )
142     {
143         return -1;
144     }
145 
146     if ( listen(sockfd,5) == -1 )//创建监听队列
147     {
148         return -1;
149     }
150 
151     return sockfd;
152 }

cli 客户端代码

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<assert.h>
  6 #include<sys/socket.h>
  7 #include<netinet/in.h>
  8 #include<arpa/inet.h>
  9 
 10 int main()
 11 {
 12     int sockfd=socket(AF_INET,SOCK_STREAM,0);//创建套接字
 13     assert(sockfd!=-1);
 14 
 15     //bind()//可以绑定,但是一般不绑定
 16 
 17     struct sockaddr_in saddr;
 18     memset(&saddr,0,sizeof(saddr));
 19     saddr.sin_family=AF_INET;
 20     saddr.sin_port=htons(6000);
 21     saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
 22 
 23     int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//三次握手
 24     assert(res!=-1);
 25     while(1)
 26     {
 27         char buff[128]={0};
 28         printf("input:\n");
 29         fgets(buff,128,stdin);
 30 
 31         if(strncmp(buff,"end",3)==0)
 32         {
 33             break;
 34         }
 35         send(sockfd,buff,strlen(buff),0);
 36 
 37         memset(buff,0,128);
 38         recv(sockfd,buff,127,0);
 39         printf("buff=%s\n",buff);
 40     }
 41     close(sockfd);
 42 }

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值