-
Notifications
You must be signed in to change notification settings - Fork 0
/
select.c
163 lines (153 loc) · 4.12 KB
/
select.c
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <unistd.h>
#include <sys/types.h>
#define IPADDRESS "192.168.8.22"
#define PORT 12345
#define MAXLINE 1024
#define LISTENQ 5
//函数声明
//创建套接字并进行绑定
static int socket_bind(const char* ip,int port);
//IO多路复用select
static void do_select(int listenfd);
//处理多个连接
static void handle_connection(int *connfds,int num,fd_set *prset,fd_set *pallset);
int main(int argc,char *argv[])
{
int listenfd,connfd,sockfd;
struct sockaddr_in cliaddr;
socklen_t cliaddrlen;
listenfd = socket_bind(IPADDRESS,PORT);
listen(listenfd,LISTENQ);
do_select(listenfd);
return 0;
}
static int socket_bind(const char* ip,int port)
{
int listenfd;
struct sockaddr_in servaddr;
listenfd = socket(AF_INET,SOCK_STREAM,0);
if (listenfd == -1)
{
perror("socket error:");
exit(1);
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET,ip,&servaddr.sin_addr);
servaddr.sin_port = htons(port);
if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)
{
perror("bind error: ");
exit(1);
}
return listenfd;
}
static void do_select(int listenfd)
{
int connfd,sockfd;
struct sockaddr_in cliaddr;
socklen_t cliaddrlen;
fd_set rset,allset;
int maxfd,maxi;
int i;
int clientfds[FD_SETSIZE]; //保存客户连接描述符
int nready;
//初始化客户连接描述符
for (i = 0;i < FD_SETSIZE;i++)
clientfds[i] = -1;
maxi = -1;
FD_ZERO(&allset);
//添加监听描述符
FD_SET(listenfd,&allset);
maxfd = listenfd;
//循环处理
for ( ; ; )
{
rset = allset;
//获取可用描述符的个数
nready = select(maxfd+1,&rset,NULL,NULL,NULL);
printf("%d\n",nready);
if (nready == -1)
{
perror("select error:");
exit(1);
}
//测试监听描述符是否准备好
if (FD_ISSET(listenfd,&rset))
{
cliaddrlen = sizeof(cliaddr);
//接受新的连接
if ((connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddrlen)) == -1)
{
if (errno == EINTR)
continue;
else
{
perror("accept error:");
//exit(1);
}
}
//printf("234234234dgfg\n");
printf("accept a new client: %s:%d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, NULL,4 ),ntohs(cliaddr.sin_port));
//将新的连接描述符添加到数组中
for (i = 0;i <FD_SETSIZE;i++)
{
if (clientfds[i] < 0)
{
clientfds[i] = connfd;
break;
}
}
if (i == FD_SETSIZE)
{
printf("too many clients.\n");
//exit(1);
}
//将新的描述符添加到读描述符集合中
FD_SET(connfd,&allset);
//描述符个数
maxfd = (connfd > maxfd ? connfd : maxfd);
//记录客户连接套接字的个数
maxi = (i > maxi ? i : maxi);
if (--nready <= 0)
continue;
}
//处理客户连接
handle_connection(clientfds,maxi,&rset,&allset);
}
}
static void handle_connection(int *connfds,int num,fd_set *prset,fd_set *pallset)
{
int i,n;
char buf[MAXLINE];
memset(buf,0,MAXLINE);
for (i = 0;i <= num;i++)
{
if (connfds[i] < 0)
continue;
//测试客户描述符是否准备好
if (FD_ISSET(connfds[i],prset))
{
//接收客户端发送的信息
n = read(connfds[i],buf,MAXLINE);
if (n == 0)
{
close(connfds[i]);
FD_CLR(connfds[i],pallset);
connfds[i] = -1;
continue;
}
printf("read msg is: ");
write(STDOUT_FILENO,buf,n);
//向客户端发送buf
write(connfds[i],buf,n);
}
}
}