怎么理解IO多路复用(select)?

发布于 2022-09-04 03:14:13 字数 363 浏览 14 评论 0

sockfd1,sockfd2,sockfd3..sockfdn 同时监听这n个客户,当其中有一个发来消息
时就从select的阻塞中返回,然后就调用read 读取收到消息的sockfd,然后又循环回select 阻塞;
这样就不会因为阻塞在其中一个上而不能处 理另一个客户的消息

我的问题是:

那这样子,在读取sockfd1的数据时,如果其它socket有数据来,那么也要等到sockfd1读取完了才能继续读取其它socket的数据吧。那这样子如果sockfd1的数据如果读取比较费时,那么其它socket不就被阻塞住了吗? 而且读取到的数据也要开启线程处理吧,那这和开启多个线程进行socket IO有什么区别呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

雨巷深深 2022-09-11 03:14:14

我觉得你的困惑在于为什么select就多路复用了?

假设现在没有使用多路复用,你的服务器逻辑在多用户情况下会这样写:

1:主线程while循环accept,接收完连接之后创建新的线程并且将accept返回的fd传入线程,此后这个线程while循环recv,也就是专门为一个客户端服务,并且我们会把每个fd保存进一个全局结构。
2:之后对于客户端发起的任何操作我们全部是在单独线程中处理的。

现在假设有10个客户端连接我们,他们同时活动时候,我们能处理是因为我们为每一个客户端配备了一个线程。但是缺点也很明显,操作系统能创建的线程数是一定的(32位,线程栈大小10M,默认创建300个左右),这也就限制了你系统的并发数。那用了select又是怎么的一种情况呢?

1:我们给select的线程注册事件,假设注册500个事件。select可以帮我们管理这些事件,主要我们注册了。之后我们处理这些事件可以选择不同的策略,可以开新的线程去处理,也可以直接用select的线程处理,这当然是不耗时间的操作,其实一个线程就够了。
2:这时候你要是还不太理解那我为什么要用它,是因为有些场景它是适用的,比如经常连接我的并发数非常大,假设10w,但是活动的就1000,那我不可能开10w线程什么也不干就等着吧,所以你用select(或者别的IO多路复用方法Epoll)处理就非常高效了。

与风相奔跑 2022-09-11 03:14:14

第一个确实会堵塞,但是读取会很快,都是在内存操作,基本上这里不会是瓶颈。

真正瓶颈一般就出现在你说的『读取到的数据也要开启线程处理』这块。数据处理如果需要大量计算或磁盘IO这种耗时较长的操作,确实是需要用开启线程处理。但也有不少情况是无需开启线程的,这就是纯事件驱动了,比如nginx作为简单的反向代理,只是把请求收进来再转出去,就无需多线程。

开启线程这块往往不是一个请求就建一个新线程,而是预先分配好线程池。

另外我们还可以把干活的线程池给移出去,放到别的进程或者机器上,这样当前的处理进程就没什么重活,也就无需多线程了,就像前面说的请求收进来简单处理就丢出去一样。

为你拒绝所有暧昧 2022-09-11 03:14:14

第一问,是被阻塞了。

“读取到的数据也要开启线程处理”,这句话没太看懂。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文