21.非阻塞I/O

设置一个I/O成为非阻塞很简单,只需要:

int val = fcntl(sockfd, F_GETFL, 0);

fcntl(sockfd, F_SETFL, val | O_NONBLOCK);

第一步是获取描述字原来的属性。第2步是为描述字增加O_NONBLOCK(非阻塞)属性。

fcntl包含在头文件fcntl.h中,同时记得带上头文件unistd.h。

这样的设置会影响套接字读写,比如调用read时候,如果是非阻塞描述字,read不会等待,而会立即返回。但不会影响select函数,也就是说如果你把描述字放在select中,不管描述字是阻塞还是非阻塞的,select函数都会阻塞,当然要让select函数不阻塞很简单,只用在等待时间上设置即可。

在没有设置非阻塞I/O情况下,有下面几种函数调用会引起阻塞:

1.read系列:包括readv, recv, recvfrom, recvmsg。这些函数只要描述字中没有数据就会阻塞。(一般是这样,某些情况还要视具体设置而定)。

2.write系列:包括writev, send, sendto, sendmsg。

3.accept函数:如果已连接队列中没有连接,则会引起阻塞。

这3种如果设置了非阻塞,会立即返回,所以在返回要进行检查其返回值,鉴定是不是正确返回,还是因为非阻塞而导致的错误返回。

4.用于TCP的connect(不包括UDP的connect)。如果是阻塞情况,在三路握手完成之前,也就是说客户在接受到它的SYN的ACK之前是不会返回的。如果是设置成了非阻塞,则会立即返回,但并不表示三路握手没有成功,实际上三路握手还在进行。关于非阻塞的connect看下一篇。

猜你喜欢

转载自memorymyann.iteye.com/blog/654310
今日推荐