【网络编程】网络IO模型1-阻塞式IO

Input/Output (I/O 或者IO)在维基百科中,Input/Output被定义为信息处理系统之间的通信。比如一个电脑和另一个电脑之间的通信,人与电脑的通信。I是某系统接收的信号或者数据,O则是从该系统输出出来的数据。今天要讲的IO是网络IO,一般都是电脑与电脑之间,调制解调器和网卡之间的。

网络IO一共分为5类,其中最基础的就是阻塞式(Blocking IO)模型。

1. 一线程一进程方案

linux下面的socket都是blocking的。当一个应用想要调用系统内核程序,如果一直没有程序,就要等待数据的到来,等数据到了之后,才能把数据拷贝到用户空间,再返回给用户。这里有两个点,一个是等待数据和数据的拷贝,这两个可能耗时的步骤都可能被block掉。对于网络编程来说也是如此。

在网络编程里,我们常用的函数有listen(), send()和recv()等。这些接口都是blocking型接口,非常方便构建server/client(服务器、客机)模型。一个完整的阻塞式tcp过程,比如说,先创建socket()接口之,客户端请求服务器连接connect(),服务器需要接受客户端的链接accept()。接受了之后,客户端才可以给服务器发送数据send(),然后服务器接受(recv())数据之后,服务器进行一些处理,然后再给客户端返回数据send(),客户端通过recv()接收到服务器返回的数据。

2. 多线程多进程方案

我们可以看到,在上面过程中,服务器和客户端各自都是一进程或者一线程如果服务器不返回结果,客户端的线程就会被阻塞,因为它在等待服务器的回应。所以,如果想要改进这个方案,我们可以让服务端使用多线程或者多进程,这样,任何一个连接的阻塞都不会影响到其他连接。比如说客户端A和客户端B同时使用服务器C,如果服务器只有一个进程,客户端A请求数据处理之后,服务端C就忙着处理A的数据,这时候,B突然想要给C数据,则会收到A的线程/进程的影响而不得不等待A做完才能轮到自己。所以,如果让服务器多进程,每个客户端开始对服务器发出请求,服务器就会创建一个线程pthread_create()或者fork出一个进程。它的优点是实现方面非常简单。

然后socket可以accpet多次,accpet的接口如下

int accept(int s, struct sockaddr *addr, socklen_t *addrlen);

其中,s是socket()的句柄。服务器先执行socket(),然后是bind()和listen()。addr就是socket的地址,第三个参数是第二个参数的长度。但是,这个方案,仍然有缺点。因为如果有几万个连接请求,可能hold不住。King老师说过,一个客户端的线程开销是8mb,如果有1万个来自客户端的请求,则占用80G内存。这就给服务器带来非常大的负担。Apache就是一个典型的例子。

当然,也有一些服务器考虑到了线程池连接池,比如tomcat等等,这样可以减少创建和销毁线程的频率,但是池子也是有上线的。所以还是需要非阻塞IO来解决这个问题。下一章将介绍非阻塞IO。

文章参考与<零声教育>的C/C++linux服务期高级架构系统教程学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值