6 I/O复用:select and poll函数

来源:互联网 发布:汽车改装设计软件 编辑:程序博客网 时间:2024/05/02 00:04

在讨论select和poll之前,让我们一起来整体观察一下5种I/O模型

阻塞式I/O模型:


非阻塞式I/O模型:


I/O复用模型:



信号驱动式模型:



异步I/O模型:


5种模型比较:



总结:这5种模型,第1种最常见,也最简单,一般简单的单进程单线程客户端可以采用。

第2种、第3种常常用在复杂的客户端或服务器上,如果采用第2种,那么程序还需要自己设置调度系统,周期性的循环执行I/O函数。

第3种虽然仍然堵塞在select或epoll函数上,但是程序可以同时处理多个socket fd的情况(这个fd不仅仅是socket,FILE *也ok,不过需要通过fileno()函数转换),并且可以另起一个线程单独处理listen socket fd(由于accept性能比较差,单起一个,可以增加服务器并发的能力),另一个线程处理conn socket fd。

至于后两种模型,目前还未接触过,哪位高人见过不妨一起讨论下。


I/O复用模型 select

例子:

之前写过一个,这里不赘述了,链接如下:http://blog.csdn.net/beginning1126/article/details/8057482

有几点容易出错的:

1、select函数中的read_fdsr和write_fdsr,其值在调用完select之后会被函数改写,所以下次再调select需要重新赋值

2、第1个参数,为最大socket fd + 1

3、出错ret<0,超时ret=0,如果出错需要判断errno是否为EINTR(是否被未知信号中断过)。


准备就绪条件:

读套接字准备就绪:

1、有数据可读,read返回>0;

2、收到FIN,read返回0;

3、收到错误,如RST,read返回-1,同时errno设置错误码;

4、监听套接字就绪,也就是有客户端connect过来。

写套接字准备就绪:

1、发送缓冲区有空间,可写;

2、对端半关闭,已经返回RST消息,对这样的套接字仍然写,将引起SIGPIPE信号;

3、只用非阻塞的connect已经ok或出错;

4、套接字有错误待处理,write不堵塞,返回-1,errno设置为错误码。

总结:套接字出错,select会将其置为可读和可写


close 和 shutdown比较:

close:减少socket fd引用计数,如果引用计数为0,则终止套接字读写两个方向的数据传送

shutdown:无需管引用计数,直接发送FIN消息,但是可以选择关闭哪个方向的。int shutdown(int sockfd, int howto),其中SHUT_RD/SHUT_WR为howto取值,分别表示关闭读、关闭写通道。

有什么用呢?因为tcp是全双工的,发送数据完毕,不代表收数据就完了,如果代码中确实没有数据可发了,这个时候是万万不能调close来关闭的。否则就无法接收后续数据了,并且这个时候如果对端write数据过来,还会发送RST消息过去,可以通过shutdown来完成这个精细活。


原创粉丝点击