select 基本思想
设置lfd为端口复用
将需要监听的文件描述符通过select交给内核进行监听。当有事件发生,则通过select返回事件发生的个数。再对文件描述符集进行逐个扫描,进行事件处理。
包含文件:
<sys/select.h>
select的函数结构如下:
int select(int nfds, fd_set * readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数描述
fd_set: 文件描述符集结构体,是一个1024的位图,0表示无事件发生,1表示有事件发生。转换后的格式为:
typedef struct
{
long int __fds_bits[1024/(8*8))];
}
nfds:现在监听的文件描述符的最大值+1。
readfds:读集合,是一个传入传出参数,传入参数为需要读监听的文件描述符集,传出参数为发生变化的文件描述符。
writefds:写文件描述符(同上,传入传出参数)
execptfds:异常文件描述符(同上,传入传出)
tomeout:
0:不阻塞,扫描完立即返回
大于0:阻塞等待时长,到达时间还没有事件发生则立即返回。
NULL:永久阻塞等待事件发生
return:
-1:监听失败
大于0:发生事件的个数
相关位操作
1.将fd从集合set中移除
void FD_CLR(int fd,set *set);
2.判断描述符是否在集合中
int FD_ISSET(int fd,fd_set *set);
3.将描述符放入到集合中
void FD_SET(int fd,fd_set *set)
4.清空集合
void FD_ZERO(fd_set *set)
select优缺点
优点:跨平台,在windows 和Linux上均支持
缺点:涉及用户区和内核区来回拷贝,当链接较多,但活跃用户极少时候,效率低,最大监听数不可以超过1024。
select 代码
在这里插入代码片
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<ctype.h>
#include<sys/socket.h>
#include<sys/select.h>
#include<iostream>
#include<string>
using namespace std;
int main()
{
/*1.创建socket*/
int lfd=socket(AF_INET,SOCK_STREAM,0);
if