Linux网络编程实现非阻塞I/O的三种方法

套接字的默认行为为:“一直到阻塞到请求动作完成为止”。比如recv函数或者accept函数在收到数据之前会默认一直处于阻塞,含有阻塞函数的进程会在阻塞期间被操作系统挂起。

有三种方法实现非阻塞套接字、异步I/O和超时。

非阻塞套接字

实现非阻塞套接字的方法就是更改套接字的行为,使得所有的调用都是非阻塞的。用fcntl函数就能更改套接字行为

int fcntl ( int socket ,  int command , ... ) ;

顺便说一句:fcntl是file control的缩写。

对于设置为非阻塞的套接字,每次调用的时候,要么立即完成IO操作,要么立刻返回失败。返回失败的时候系统会把errno的值设置为EWOULDBLOCK,connect函数除外,它会将errno设置为EINPROGRESS。

由于在网络编程中,我们并不知道何时调用会成功,只能周期性地调用recv或者read函数,一次又一次得去实验它,我们把这种方式称为“轮询”。

异步I/O

异步I/O的原理就是当套接字上发生摸个与IO相关的事件之后把SIGIO信号发送给该进程。实例代码如下:

...
int sock ;
int main ( int argc ,  char  *argv [ ] )
{
    ...
     signal (SIGIO , sig_handler ) ;
    ...
}

void sig_handler ( int signalType )
{
    ...
     recv (sock , buffer , length , flags ) ;
    ...
}

设置超时

unsigned int alarm(unsigned int secs);
Linux中的alarm()函数会设置一个计时器,经过secs秒之后,进程会收到SIGALRM信号。调用alarm()也会返回之前设置的报警剩余时间。

...
int main ( int argc ,  char  *argv [ ] )
{
    signal (SIGALRM , func ) ;
    ...
     alarm (TIME_OUT_VALUE ) ;
     while (times  < MAX_TIMES )
     {
        sock  = recv (... ) ;
        ...
     }
    alarm ( 0 ) ;           //取消报警计时器
    ...
}

void func ( int signalType )
{
    times  +=  1 ;
}

记得把sock设置为非阻塞

如果有什么问题,请在下面留言。

原文链接:http://www.yucoat.com/internet/linux_unblock.html


你可能感兴趣的:(linux网络编程)