select I/O复用机制

本文详细解析了Select机制在Linux平台上的应用,包括所需头文件、关键函数及其作用,如FD_ZERO、FD_SET、FD_CLR、FD_ISSET和select。通过实例演示了如何在socket通信中使用这些函数处理读、写及异常事件。

1.需要的头文件----linux 平台
#include <sys/time.h>
#include <unistd.h>
2.相关函数
FD_ZERO(fd_set *fdset);
FD_SET(int fd, fd_set *fdset);
FD_CLR(int fd, fd_set *fdset);
FD_ISSET(int fd,fd_set *fdset);
int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);
3.功能
主要是在socket监听套接字,处理socket通信中的读、写、异常处理等事件;
换句话说,要学会select机制,需要和socket 一起才能完全掌握用法,单独理解,或者分开学习,都不能很好的理解和掌握,当然有更好的epoll机制,这个将在下一个博客中讲解。

4.接口说明-----按使用顺序讲解,不错乱讲,很多博客都是想到哪里讲哪里,我这里依次讲解,方便大家使用。

fd_set结构:是一组文件描述符集合,这么说,估计新手还是不能理解这是个什么,这么说吧,他只有SOCKET_READABLE、SOCKET_WRITABLE、SOCKET_EXCEPTION这三种类型,明白了吧,就是可读、可写、异常三种事件的结构集合。

4.1 FD_ZERO(fd_set *fdset);
功能:指定的文件描述符清空处理,初始化用的;
4.2 FD_SET(int fd, fd_set *fdset);
参数fd: 就是我们通常建立完socket链接用的fd ,注意这里在操作时有不通,如果是客户端,connect完成后,把fd 设置进入,如果是服务端,就要操作两次,listen 和accept两个,因为服务端在建立链接后,accpet的fd会发生变化,三次握手成功。
参数fdset :就是时间集合了,上面讲的三种事件;
功能:该函数主要是绑定fd 和三种事件,客户端在调用完connect和服务端调用完 accept,把事件绑定到fd,
4.3 int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);
参数1 : 最大监听fd 个数,一般最大为1024,但是可以通过修改内核对该数目进行修改;
参数2:读事件
参数3: 写事件
参数4:异常事件
参数5:超时
返回值: 负数,表示出错,整数为监听fd的数目;
功能:这个函数的主要功能是,根据fd映射出需要操作的事件,这里说一下写事件,写事件一般是由己方主动写的,好比人说话,嘴巴闭上了,人家永远不知道你说什么,因为什么也没有说,所以写事件是需要自己写入的。读事件好说,人家说话你都能听见,发过来的消息,都能监听到,道理一样的。

4.4 FD_ISSET(int fd,fd_set *fdset);
参数1:socket 套接字 fd;
参数2: 事件套接字;
功能: 此函数比较重要,主要是通过fd映射出此前是应该进行读事件、还是写事件,还是异常;

4.5 FD_CLR(int fd, fd_set *fdset);
参数1: 套接字fd;
参数2: 事件套接字;
功能:从fd的映射集合中删除该事件;

OK 函数接口都讲解完毕,那么接下来发一个简单的网上demo
参考链接为https://blog.youkuaiyun.com/cstarbl/article/details/7645298
uint32 SocketWait(TSocket *s,bool rd,bool wr,uint32 timems)
{
fd_set rfds,wfds;
#ifdef _WIN32
TIM tv;
#else
struct tim tv;
#endif
FD_ZERO(&rfds);
FD_ZERO(&wfds);
if (rd) //TRUE
FD_SET(*s,&rfds); //添加要测试的描述字
if (wr) //FALSE
FD_SET(*s,&wfds);
tv.tv_sec=timems/1000; //second
tv.tv_usec=timems%1000; //ms
for (;? //如果errnoEINTR,反复测试缓冲区的可读性
switch(select((*s)+1,&rfds,&wfds,NULL,
(timems
TIME_INFINITE?NULL:&tv))) //测试在规定的时间内套接口接收缓冲区中是否有数据可读
{ //0--超时,-1--出错
case 0:
return 0;
case (-1):
if (SocketError()==EINTR)
break;
return 0; //有错但不是EINTR
default:
if (FD_ISSET(*s,&rfds)) //如果s是fds中的一员返回非0,否则返回0
return 1;
if (FD_ISSET(*s,&wfds))
return 2;
return 0;
};
}

总之,网上很多是demo, demo意思是帮助自己理解的小工具,想深入还得自己写好的商用代码,深入进去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值