IO复用poll

IO复用poll

poll函数

1
2
3
4
5
6
7
8
9
int poll(struct pollfd fds[],int len,int timeout);

struct pollfd
{
int fd; //用户设置关注的文件描述符
short events; //用户关注的事件类型
short revemts; //由内核填充,就绪的事件类型
};//成功返回就绪文件描述符的个数,失败返回-1,超时返回0
timeout:定时时间

poll所支持的事件类型

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#define _GNU_SOURCE

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>

#include<poll.h>
#define LEN 100
int initsocket()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
return -1;

struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(6000);
ser.sin_addr.s_addr=inet_addr("127.0.0.1");
int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
if(res==-1)
return -1;

res=listen(sockfd,5);
if(res==-1)
return -1;

return sockfd;
}
void initfds(struct pollfd *fds)
{
int i=0;
for(;i<LEN;++i)
{
fds[i].fd=-1;
fds[i].events=0;
}
}
void insertfd(struct pollfd *fds,int fd,short events)
{
int i=0;
for(;i<LEN;++i)
{
if(fds[i].fd==-1)
{
fds[i].fd=fd;
fds[i].events=events;
break;
}
}
}
void dealfinish_event(struct pollfd *fds,int sockfd)
{
int i=0;
for(;i<LEN;++i)
{
if(fds[i].fd==-1)
continue;
else if(fds[i].fd==sockfd)
{
if(fds[i].revents&POLLIN)
{
struct sockaddr_in cli;
socklen_t len=sizeof(cli);
int c=accept(sockfd,(struct sockaddr*)&cli,&len);
if(c<0)
{
printf("accept error\n");
continue;
}
printf("one client link success\n");
insertfd(fds,c,POLLIN|POLLRDHUP);
}
}
else //客户端连接文件描述符
{
if(fds[i].revents&POLLRDHUP)
{
printf("one client unlink\n");
close(fds[i].fd);
fds[i].fd=-1;
fds[i].events=0;
}
else if(fds[i].revents&POLLIN)
{
char buff[128]={0};
int n=recv(fds[i].fd,buff,127,0);
if(n<=0)
{
printf("recv error\n");
continue;
}
printf("%d: %s\n",fds[i].fd,buff);
send(fds[i].fd,"OK",2,0);
}
}
}
}
int main()
{
int sockfd=initsocket();
assert(sockfd!=-1);

struct pollfd fds[LEN];
initfds(fds);
insertfd(fds,sockfd,POLLIN);

while(1)
{
int n=poll(fds,LEN,-1);//n>0返回就绪文件描述符的个数
if(n<=0)
{
printf("poll error\n");
continue;
}
//看下是不是sockfd,是就接受新的客户端连接,不是就是客户端有数据到达
dealfinish_event(fds,sockfd);
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>

int main()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);

struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(6000);
ser.sin_addr.s_addr=inet_addr("127.0.0.1");

int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));
assert(res!=-1);

while(1)
{
printf("please input: ");
char buff[128]={0};
fgets(buff,127,stdin);
if(strncmp(buff,"end",3)==0)
break;

send(sockfd,buff,strlen(buff)-1,0);

char result[128]={0};
int n=recv(sockfd,result,127,0);
if(n<=0)
break;
printf("result: %s\n",result);
}
close(sockfd);
}

通信测试