我用select做多路复用踩到的坑

既然说是用select踩到的坑,那么就先直接贴一段使用select的代码上来瞅一下:

    bool SocketAction(int fd, const char* buf, size_t len, uint64_t milli_expire) {
        struct timeval tv;
        tv.tv_sec = milli_expire / 1000;
        tv.tv_usec = (milli_expire % 1000) * 1000;
        fd_set rd_set, wt_set;
        FD_ZERO(&rd_set);
        FD_ZERO(&wt_set);
        FD_SET(fd, &rd_set);
        FD_SET(fd, &wt_set);

        int ret = 0;
        while (true) {
            ret = select(fd+1, &rd_set, &wt_set, nullptr, &tv);
            if (ret < 0 && errno == EINTR) continue;
            break;
        }

        if(FD_ISSET(fd, &rd_set)) {
			char rd_buf[1024] = {0};
			ret = read(fd, rd_buf, sizeof(rd_buf));
			if(ret < 0)	return false;
			printf("%s\n", rd_buf);
		} else if(FD_ISSET(fd, &wt_set)) {
			ret = send(fd, buf, len, 0);
			if(ret < 0) return false;
		}

        return true;
    }

上面的代码着实非常easy,仅仅是针对某一个socket fd进行读写操作,从逻辑上来说应该是没有不论什么问题的。然而这个在实际的使用过程中确实会出现故障。我们程序中封装了socket的操作,如上代码的方式使用了select。

在出现大量的socket连接时,会出现宕机现象,而且宕机生成的core文件的堆栈也莫名其妙的被破坏了。

遇到这个情况时。我直接被震惊了,由于细致检查了代码确实没有发现不论什么问题。为什么每次都是连接数达到快1500的时候就出现宕机呢?

刚開始以为是其它的逻辑出了问题。于是细致检查了其它的逻辑确实也没有发现存在不论什么问题,而且从堆栈被破坏的情况上分析,也怀疑是某个使用中出现了数组越界訪问引发的。但在整个逻辑中使用的都是stl里的容器,没有申请数组,出现读写越界着实无法理解。

此后仅仅能怀疑底层封装的问题。在一步步尝试凝视代码的过程中。发现select使用的地方出现了问题。那么问题到底在哪里呢?

 int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);

 nfds is the highest-numbered file descriptor in any of the three sets, plus 1.

在select的使用manual中,select的定义和nfds的说明如上所看到的。也仅仅是说明了select的nfds是最大的文件描写叙述符+1。在实际的使用过程中也确实有这么使用。好像也确实没有问题。然而,不止这么简单。select的文件描写叙述符的最大值实际是有一个潜在规则的。那就是select的最大文件描写叙述符最大是1024。该值在centor os系统中。定义在文件/usr/include/sys/select.h文件里。例如以下:

   78 /* Maximum number of file descriptors in `fd_set‘.  */

79 #define FD_SETSIZE      __FD_SETSIZE

而__FD_SETSIZE则定义在:/usr/include/bits/typesizes.h 中,例如以下:

   62 /* Number of descriptors that can fit in an `fd_set‘.  */

63 #define __FD_SETSIZE        1024

这下能够理解了吧。在socket大于1024时。文件描写叙述符自然就大于1024,则在使用select时訪问的大小就实际超越了系统中对于select的支持。因此出现读写越界,造成程序的宕机。

这次所踩的坑很隐晦,但也说明了一个问题。在使用系统接口时须要谨慎。尽管可能用法并没有错误,但也要在使用的时候多注意其“潜规则”。

时间: 2024-08-20 02:08:01

我用select做多路复用踩到的坑的相关文章

做项目管理踩过的坑

忙不过来 项目时间紧张,完全不可能在交期前完成,加班到猝死都来不及 着急忙慌延期个把月做出了系统BUG一大堆,看着就像一坨屎,自己都嫌弃 来不及的项目就别接了,接到也是赔钱 需求不合理 直接面向使用者的开发有这样的风险,实际业务场景如果不熟悉,只能根据使用者的要求做 但是使用者的要求是前后冲突的! 要命的是你不做到那一步都不知道会冲突! 模块负责人一定要熟悉实际业务场景,否则容易出错,浪费时间,效率低下 用户提出的需求一定要做合理性分析 代码设计问题 前面两个问题可以勉强归咎于老板.客户 代码的

《C++之那些年踩过的坑(附录一)》

C++之那些年踩过的坑(附录一) 作者:刘俊延(Alinshans) 本系列文章针对我在写C++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. [版权声明]转载请注明原文来自:http://www.cnblogs.com/GodA/p/6639526.html 本来上个月就开始动笔了,直到现在才发出来,实在太多事情.可能有些小朋友不知道写这一篇随笔的起因,那么你可以看一下我之前写的. 上一篇的最后,我提到了一个问题:代码优化.并留了一个小测试:无符号数与有符号数的性能比

【转载】Fragment 全解析(1):那些年踩过的坑

http://www.jianshu.com/p/d9143a92ad94 Fragment系列文章:1.Fragment全解析系列(一):那些年踩过的坑2.Fragment全解析系列(二):正确的使用姿势3.Fragment之我的解决方案:Fragmentation 本篇主要介绍一些最常见的Fragment的坑以及官方Fragment库的那些自身的BUG,这些BUG在你深度使用时会遇到,比如Fragment嵌套时或者单Activity+多Fragment架构时遇到的坑.如果想看较为实用的技巧,

初学spring boot踩过的坑

一.搭建spring boot环境 maven工程 pom文件内容 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-

Fragment全解析系列(一):那些年踩过的坑

Fragment系列文章:1.Fragment全解析系列(一):那些年踩过的坑2.Fragment全解析系列(二):正确的使用姿势3.Fragment之我的解决方案:Fragmentation 本篇主要介绍一些最常见的Fragment的坑以及官方Fragment库的那些自身的BUG,这些BUG在你深度使用时会遇到,比如Fragment嵌套时或者单Activity+多Fragment架构时遇到的坑.如果想看较为实用的技巧,请直接看第二篇 Fragment是可以让你的app纵享丝滑的设计,如果你的a

使用ffmpeg视频编码过程中踩的一个坑

今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,很多时候一旦思维定势真的挺难突破的.下面是不正确的编码结果: 使用ffmpeg做视频编码过程中,首先要新建数据帧,并为数据帧分配相应内存,以便于保存图像数据,为数据帧分配内存需要用到av_image_alloc()这个函数,该函数将根据传入的图像宽.高.图像格式.数据对齐基数等参数进行内存分配. 这其中有一个参数可能会让人迷惑,那就是数据对齐基数这个参数该设置多少?顺便说说为什么要数据对齐,之所以要对齐,主要

那些年提交AppStore审核踩过的坑

此文刚刚上了CocoaChina的首页:那些年提交AppStore审核踩过的坑  欢迎围观,谢谢大家支持. //add by 云峰小罗,2016.08.04 做iOS开发近5年了,每次提交版本时不可谓不小心翼翼,如履薄冰,但是还是难免踩到了一些坑.苹果的官方文档(AppStore审核条款)这里就不罗列了,太冗长繁琐了,而且大部分是一般app都不会触碰的到的,今天我主要想以自己的亲身经历,跟大家回顾一下这些年我提交AppStore审核时踩过的坑,并且针对如何避免给出一些tips供大家参考.大神请忽

[转至云风的博客]谈谈陌陌争霸在数据库方面踩过的坑( Redis 篇)

« 谈谈陌陌争霸在数据库方面踩过的坑(芒果篇) | 返回首页 | linode 广告时间 » 谈谈陌陌争霸在数据库方面踩过的坑( Redis 篇) 注:陌陌争霸的数据库部分我没有参与具体设计,只是参与了一些讨论和提出一些意见.在出现问题的时候,也都是由肥龙.晓靖.Aply 同学判断研究解决的.所以我对 Redis 的判断大多也从他们的讨论中听来,加上自己的一些猜测,并没有去仔细阅读 Redis 文档和阅读 Redis 代码.虽然我们最终都解决了问题,但本文中说描述的技术细节还是很有可能与事实相悖

游戏服务器数据库踩过的坑

在页游服务器这块很早之前一直没有认真考虑过,大部分是之前搭建好的,我只需要按照他原来的设计继续码代码就好了. 可是这次服务器重构的过程中,还是遇到了很多始料不及的问题.那么就按照踩过的坑,去一个个讲讲分析分析. 1:起初mysql的方案  起初的设计方案是这样,用一个RolePlayer 去做玩家数据的缓存,所有玩家的数据更新到RolePlayer中,定时十秒中更新到数据库.RolePlayer大概是这样一个设计 class RolePlayer { public int roleId; pub