浅谈select与epoll函数

来源:互联网 发布:知乐的全部小说目录 编辑:程序博客网 时间:2024/06/06 21:05
第一篇技术博客,哈哈。这里讲的内容都是很浅的,很多细节没讲到,比如select函数读集数量上限,超时,非堵塞设置等等,自己百度吧~~


应用场景:
很多个客户端同时访问服务器,服务器需要处理各个客户端消息。


用法:
select:
1. 设置读集:将一堆客户端fd通通装入readfds集合


FD_ZERO(&readfds); //先清空for(i = 0; i < num_of_client; i++)     FD_SET(&fd[i],&readfds);


2. 调用select函数等待数据,函数返回说明有数据,或者出错,或者超时


int err=select(maxfd+1,&readfds,NULL,NULL,NULL) ;


3. 根据select函数返回值判断什么情况


err = -1 出错

err = 0 超时
else 客户端有数据


4. 在上一步else的基础上用 FD_ISSET 逐个判断这堆客户端是否有数据


for( i = 0; i< num_of_client; i++)if(FD_ISSET(fd[i],readfds)){ //第i号客户端有数据啦dosomething(i);}


最后一步可能有点莫名其妙,这里介绍下select下函数原理。
之前不是设置了一个读集 readfds 吗,把所有客户端fd都放进去了,然后调用select函数,系统就开始轮询这个读集里所有的fd。所以轮询周期取决于你放了几个fd到集合里,放越多效率自然就低。比如在某一次轮询结束后中,系统检测到有20个客户端有新数据过来,它就把这20客户端的fd做个标记。然后函数返回,返回值大于0(具体几我也没去看过)。


然后你需要做的就是把这20个客户端找出来。怎么找?看第4步。所以你自己也得手动轮询一遍,把那些被标记的客户端找出来,再处理消息。比如这个读集里有1000个客户端,然后这1000个客户端,你就需要用 FD_ISSET 每个都去问他一下,哎哥们是你有话要说吗?哥们说,不是,找错人了。而且不管这哥们是不是有话说,你都得把剩下的问完,一个不能拉下。


看到这里你是不是也觉得这个过程有些重复劳动?为什么系统在轮询的时候,在检测到某个客户端有数据的时候,不直接把这个客户端的fd拎出来放到一个地方存起来,还标记毛啊。这样我们可以直接得到那个地方放着的fd。毕竟1000个客户端只有20个有数据过来,问其他980个是不是有数据是浪费时间。

这个时候epoll函数出现了。形式有点不同,理解起来可以当一回事。当然内部实现不一样。
epoll函数就是只把那些有数据的客户端fd放到某个地方,而且函数返回值为有数据的客户端的数量。这样我们就省事多了。20个客户端有数据过来,函数返回20,然后我们只需要循环20次,就把每个消息给处理了。而且成功率百分百,妈妈再也不用担心我像之前那样吃980/1000个闭门羹了。


epoll函数内部实现不像select函数那样用轮询,轮询我也会,这么low。epoll用的是回调函数。这个我自己也没搞清楚怎么实现的,要继续研究。epoll就不一步步讲解了,用起来跟select差不多的。直接贴源码。


0 0