技术宅的结界

 找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 208|回复: 4
收起左侧

【原创】SOCKET编程里select函数的最简单的例子

[复制链接]

34

主题

129

帖子

6810

积分

用户组: 管理员

UID
77
精华
11
威望
112 点
宅币
6273 个
贡献
129 次
宅之契约
0 份
在线时间
83 小时
注册时间
2014-2-22
发表于 2017-12-18 18:34:14 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有帐号?立即注册→加入我们

x
关于SOCKET编程入门,我就不多说了,不懂的看坛主的科普贴。下面直接说说,select的用途,以及使用场合。
首先吐槽一个事情,select这个函数名,真是太不好了。一般人都会顾名思义,select就是选择的意思,结合SOCKET就是“选择socket”,这让人一头雾水:选择SOCKET是啥意思咧?
我当年就是被这个名字带到坑里的,然后一直没理解这个函数有啥用,甚至A5专门发了个帖子解释,我还是不理解,郁闷得A5怀疑人生

先简单概括一下select:
1、功能:挑选出特定情况的socket。
2、意义:提高I/O性能,降低服务器负担。

然后认真介绍一下select的timeout参数:
select一共有5个参数,前4个都很好理解,第1个填0,第2/3/4个就是SOCKET的数组。timeout是一个结构体指针,因此主要可以填写三种类型的数据:NULL,结构体数值为0,结构体数值为非0。
1.NULL:等至少有1个SOCKET可用了函数才返回,否则就一直等下去。
2.结构体数值为0:函数立马返回结果。
3.结构体数值为非0:函数等待N毫秒之后才返回结果。于是有些人在这里动了歪脑筋,随便填写一个无效的SOCKET以及等待的时间,把该函数当作sleep来用。

下面开始讲(编)故事:
在最简C/S架构里,C发起连接,S接受连接。按照最简单的想法,一个线程处理一个C,是没问题的。但是如果C的数量太多,就会引发一个著名的问题,C10K问题。C10K问题的描述很复杂,简单说就是,一个服务器接受了1万个连接,怎么处理?难道要分配10000个线程么?这不是不行,而是线程频繁切换,导致I/O性能降低,系统负担加重(你可以打开任务管理器看看本机的线程数,正常使用的话一般会在1000个线程以下)。于是也许有人说,为何不串行处理,我直接分配N个线程(N为CPU核心数量),再来个FOR循环对所有的SOCKET进行I/O,不就行了。如果你真的这么想,那么恭喜你,答对了,猪也是这么想的(范伟语)。因为是网络环境,C随时可能因为各种原因掉线,而意外掉线对于S来说并不知情。C可以利用带timeout的send和recv进行I/O(一般来说recv函数在没有消息到来的情况下会卡住,send函数发送一定数量的数据而且在对方没有接受你消息时候会卡住,你用“非阻塞模式SOCKET”那就是另外一个故事了),如果失败了重新连接即可。但是服务器没法这么做,因为即使设置10秒超时,在有10000个C的情况下,若有100个C意外掉线,则循环一次至少需要1000秒(大约17分钟)时间,这是不能忍受的。先贤们遇到这个问题之后,考虑很久,终于憋出了一个大招:先利用select函数,把“坏”的socket都给过滤掉,再对“好”的socket进行I/O。保证在“阻塞模式socket”的情况下,也不会卡顿。比如当某个SOCKET有消息到了,会告诉你,可以用这个SOCKET来接收消息;当某个SOCKET一直没人接收消息,会告诉你,别再往这个SOCKET发消息了。

函数和具体怎么使用请参考A5的帖子,我就不赘述了。下面给出一个DEMO,是服务端每隔N秒钟就往客户端发消息,客户端收到消息就回复。个别客户端意外退出,也不影响服务端往其它客户端发消息。
游客,如果您要查看本帖隐藏内容请回复
怎么模拟客户端掉线的情况捏?下面再简单说说:
1、运行程序,会看到各种get-heart-beat、get client[%ld] respond的消息。
2.png
2、运行WIN64AST,查看这个程序的线程,把那10个起始地址都一样的线程挑选出来,然后随机暂停几个。
Untitled.png
3、观看效果。

986

主题

2166

帖子

5万

积分

用户组: 管理员

一只技术宅

UID
1
精华
197
威望
261 点
宅币
15947 个
贡献
30926 次
宅之契约
0 份
在线时间
1518 小时
注册时间
2014-1-26
发表于 2017-12-18 18:51:56 | 显示全部楼层
“于是也许有人说,为何不串行处理,我直接分配N个线程(N为CPU核心数量),再来个FOR循环对所有的SOCKET进行I/O,不就行了。如果你真的这么想,那么恭喜你,答对了,猪也是这么想的(范伟语)”这是epoll模型
8线程CPU,开8个thread,用for循环对每个socket进行epoll。
与非阻塞非常接近。
Linux下非常屌。而Windows则更适合用select

0

主题

1

帖子

19

积分

用户组: 初·技术宅

UID
2928
精华
0
威望
1 点
宅币
16 个
贡献
0 次
宅之契约
0 份
在线时间
1 小时
注册时间
2017-10-7
发表于 2017-12-18 19:13:18 | 显示全部楼层
假装回复 查看帖子内容

19

主题

51

帖子

1164

积分

用户组: 上·技术宅

UID
1043
精华
5
威望
21 点
宅币
1031 个
贡献
15 次
宅之契约
0 份
在线时间
203 小时
注册时间
2015-8-15
发表于 2017-12-18 21:39:35 | 显示全部楼层
走过路过,支持楼主
Only via chaos and excellence can beauty and success be respectively created and achieved.

1

主题

15

帖子

15

积分

用户组: 初·技术宅

UID
2735
精华
0
威望
0 点
宅币
0 个
贡献
0 次
宅之契约
0 份
在线时间
6 小时
注册时间
2017-7-28
发表于 2017-12-25 19:24:33 | 显示全部楼层
走过路过,支持楼主

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号|网站地图

GMT+8, 2018-5-27 05:19 , Processed in 0.090361 second(s), 17 queries , Gzip On, Memcache On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表