I/O复用场合:
1.当客户处理多个描述符(通常是交互和网络套接字)时,必须使用I/O复用。
2.一个客户同时处理多个套接字是可能得。
3.如果一个TCP服务器既要处理监听套接字,又要处理已连接套接字。
4.如果一个服务器既要处理TCP,又要处理UDP,一般要用I/O复用。
5.如果一个服务器要处理多个服务或者协议。
I/O复用并非只限于网络编程,许多重要的应用程序也需要使用这项技术。
一个输入操作通常包括两个不同阶段:
1.等待数据准备好。
2.从内核向进程复制数据。
进程把一个套接字设置成非阻塞是在通知内核:当所请求的I/O操作非得把进程投入睡眠才能完成时,不要把本进程投入睡眠。
I/O复用主要调用select或poll,阻塞在这两个系统调用中的某一个之上,而不是阻塞在真正的I/O系统调用上。
事实上由于使用select需要2个而不是1个系统调用,I/O复用还稍有劣势。select的优势在于我们可以等待多个描述符就绪。
另一种I/O模型是在多线程中使用阻塞式I/O
信号驱动式I/O-没有被阻塞,数据准备好的时候产生SIGIO信号。这种模型的优势在于等待数据表到达期间进程不被阻塞。
异步I/O由POSIX规范定义
从移植性考虑,如果我们在捕获信号,那么必须做好select返回RINTR错误的准备。
select的异常条件:
1.某个套接字的带外数据的到达
2.某个已置为分组模式的伪终端存在可从其主端读取的控制状态信息
select的三个指针如果均为空,我们就有了一个比Unix的sleep函数更为准确的定时器。
每次重新调用select函数时我们都得再次把所有描述符集内所关心的位均置1.
套接字“就绪”条件(可读为例)
1.·该套接字的缓冲区中的数据字节数大于等于套接字接收缓冲区低水位标记的当前大小。
2.该连接的读半部关闭(也就是接收了FIN的TCP连接)。对这样的套接字的读操作将不阻塞并返回0(EOF)
3.该套接字是一个监听套接字且已完成的连接数不为0.
4.其上有一个套接字错误待处理
可写--使用非阻塞connect的套接字已建立连接,或者connect已经以失败告终。
shutdown关闭TCP连接其中一半的方法。
混合使用stdio和select被认为是非常容易犯错误的。
close仅仅把引用计数减1,为0才关闭套接字。
shutdown可以不管引用计数就激发TCP的正常连接终止序列
当服务器与处理多个客户时,不能阻塞于只与单个客户相关的某个函数调用。解决办法:
1.使用非阻塞I/O
2.多线程
3.对I/O操作设置超时。
从当今的可移植性角度考虑,支持select的系统比支持poll的系统要多。
C语言数组赋值:放在结构中,C语言允许结构跨等号赋值。
对阻塞式套接字的读操作只要有数据就会返回一个不足计数,然而对阻塞式套接字的写操作将一直阻塞到所有数据能被内核接受为止。