select 即是采用轮询内核的方式,获知哪些连接发送或接受消息了。
select 最大监听1024个连接
过程:
(start)监听套接字:创建绑定监听
(select)初始化fd_set ===> select监听fd_set ===> fd_set中未变化的位置置零(0)
依据fd_set中剩余的有变化的位置(1) ===> 判断是监听套接字还是已连接的套接字
===> 分别处理
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/time.h>
#include<sys/select.h>
#include "pub.h"
int main()
{
int lfd = -1, cfd = -1;
char buf[1024];
// 绑定ip和端口号
lfd = socketBind("127.0.0.1", 8080);
// 记录需要监听的fd的allset,初始化为0
fd_set allset, rset;
FD_ZERO(&allset);
FD_ZERO(&rset);
// 记录客户端cfd的值的集合, 监听上线FD_SETSIZE = 1024
int client[FD_SETSIZE], i=0;
for(i=0; i<FD_SETSIZE; i++)
client[i] = -1;
int maxfd = lfd, maxindex = 0;
FD_SET(lfd, &allset);
while(1)
{
rset = allset;
int nready = select(maxfd+1, &rset, NULL, NULL, NULL); // 监听的最大fd数量=最大的fd序号+1
if(nready <= 0)
{
perror("select");
break;
}
// 如果是lfd变化
if(FD_ISSET(lfd, &rset))
{
cfd = Accept_with_print(lfd);
// 连接数超过1024
if(cfd == FD_SETSIZE)
{
printf("too many connect\n");
close(cfd);
continue;
}
// 添加cfd到监听集合,更新maxfd; cfd添加到监听客户端client集合,更新maxindex
FD_SET(cfd, &allset);
if(cfd > maxfd)
maxfd = cfd;
for(i=0; i<FD_SETSIZE; i++)
{
if(client[i] < 0)
{
client[i] = cfd;
break;
}
}
if(i > maxindex)
maxindex = i;
if(--nready == 0)
continue;
}
// cfd变化
for(i=0; i<=maxindex; i++)
{
// 取需要监听的client
if((cfd = client[i]) < 0)
continue;
if(FD_ISSET(cfd, &rset))
{
int num = read(cfd, buf, sizeof(buf));
if(num < 0)
{
perror("read");
return -1;
}
else if(num == 0)
{
printf("cfd=%d closed\n", cfd);
close(cfd);
FD_CLR(cfd, &allset);
client[i] = -1;
}
else
{
write(cfd, buf, num);
}
}
if(--nready == 0)
break;
}
}
}