为什么网络socket编程是阻塞的?因为非阻塞轮询占CPU,用多线程和IO复用

2020.8.27

一直不明白为什么网络socket编程默认都是阻塞的,阻塞了程序不就停了不响应了吗,好纠结。

现在有点了解了,阻塞时是等待状态,类似于内核把它sleep,不占用CPU,对操作系统正常运转是非常有利的。

非阻塞方式:程序不会停止响应,socket函数会马上返回,但程序需要一直轮询socket,如果socket没有动作,那其实就是在while(1)啊,CPU占用是100%啊。不行啊,操作系统要完蛋的。

所以还是用阻塞方式吧,内核已经把最优方案给我们了。

但是,一个socket这么用是没问题的,多个socket就麻烦了。

主要有二个方法:

1. 多线程:
一个socket放入一个线程,阻塞了后,线程处于停止状态,不影响主程序和其它socket。
线程程序是按正常socket通讯交互流程走,符合正常编程思路,编程容易些,但开销大,线程多了扛不住。
线程要占用内存,有人试过linux大约是可以开到300个线程,每个线程占10MB,好大。
所以一般十几、几十个socket可以用多线程玩一玩。

2. IO多路复用:select,poll,epoll等。
主程序一个线程就可以处理所有socket。
编程比较麻烦,得判断各个socket是在通讯交互流程的哪一步。
read/recv()取决于对方有没有发来数据,阻塞可能性很大,write/send()则是自己发送数据,一般不阻塞,所以一般只判断读取标志即可,发送则直接用write()或send(),这样程序比较简单。

参考网友说的:

qeesung
如果只有一个套接字的情况下,使用阻塞IO是极好的,读到数据就返回。
但是如果在有很多套接字的情况下,比如有100个套接字:
1.    如果使用阻塞IO,可能因为读取一个没有数据的套接字而阻塞剩下的99个套接字的数据处理,那么就会造成服务器的响应性很差。
2.    如果使用非阻塞IO,那么就需要轮询这一百个套接字到底可不可以读取到数据,这个轮询操作会浪费CPU时间片,照样也不是一个高效的方式,套接字多了,照样性能很差。
那有没有一种比较好的方式来同时检测多个套接字是否可读可写,并且不浪费CPU时间片呢?那就是要用IO多路复用了,使用IO多路复用可以同时检测多个不同的套接字是否就绪。有多种IO多路复用的实现,其中包括select,poll, epoll, /dev/poll, kqueue等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值