socket阻塞和非阻塞

Linux的网络编程有很多种写法,最简单的是阻塞式(Blocking)的网络程序,其次有非阻塞(Non-Blocking),多路复用(Multiplexing),异步(Asynchronous)模型等。

阻塞模型:

阻塞模型是最为简单的一种网络编程模型。顾名思义,该模型中,socket都工作在阻塞模式下,在调用相应的网络函数时,如accept, recv, send时,这些函数都会阻塞线程,直到socket可读或者可写,或者出错时,线程才会继续执行。
在阻塞模式下,我们一般用多线程来对每一个socket进行处理,一个线程服务一次链接,这种模型在一些web服务器中较为常见,如apache,tomcat等

这里写图片描述
扩展pthread_create函数:

int pthread_create(pthread_t *thread,pthread_attr_t *attr,(void *(*start_routine)(void *),void *arg));

其中第二个参数设置线程属性(线程栈大小,线程优先级等)
第三个参数为线程函数的起始地址
第四个参数为传递给线程函数的参数

会阻塞的socket的API:
accept,connect,recv(recvfrom),send(sendto),closesocket,select(poll/epoll)

非阻塞模型:

非阻塞模型,顾名思义,socket工作在非阻塞模式中,这时对该socket调用相应的函数时,并不会阻塞线程运行,即便没有数据准备好,这些函数也会立即返回,线程将继续执行。那我们将需要在后面的代码中,对返回的结果进行判断,以区分刚才的调用是否有数据可以处理。

非阻塞模型的优点在于,可以在一个线程中处理多个socket事件,而不会阻塞线程,减少多线程切换带来的开销。相应的,也增加了处理的复杂度。

设置为非阻塞
int flags = fcntl(fd,F_GETFL,0);
fcntl(fd,F_SETFL,flags | O_NONBLOCK);
设置为阻塞
int flags = fcntl(fd,F_GETFL,0);
fcntl(fd,F_SETFL,flags &~ O_NONBLOCK);

非阻塞socket代码逻辑(recv):

while(1)
{
    char buff[1024] = {0};
    int num = recv(fd,buff,sizeof(buff),0);
    if(num > 0)
    {
        //recv成功 接收到数据
    }
    else if(num < 0)
    {
        if((errno == EAGAIN || errno == EWOULDBLOCK))
        {
            //非阻塞 连接正常 EAGAIN EWOULDBLOCK 表示在没有数据到来时的返回
            //可以处理一些事件
            continue;
        }
        else
        {
            //error
            break;
        }
    }
}

阻塞和非阻塞函数行为差异:

  • accept在阻塞模式下,没有新连接时,线程会进入睡眠状态;非阻塞模式下没有新连接立即返回并设置errno为WOULDBLOCK
  • connect在阻塞模式下,仅TCP连接建立成功或出错时才返回;非阻塞模式下,该函数会立即返回INPROCESS错误(需用select检测该连接是否建立成功)
  • recv/recvfrom/send/sendto很好理解,因为这两类函数读写socket文件描述符的接收/发送缓冲区
  • closesocket也不是真正意义上的阻塞,它其实是指是否等待关闭,它受套接字选项SO_LINGER和SO_DONTLINGER的影响。若SO_DONTLINGER或SO_LINGER的间隔=0时,closesocket就是非等待关闭的,但是当SO_LINGER的间隔>0时,closesoket就是等待关闭的,直到剩余数据都发送完毕或直到超时才退出。(但是这个地方只有对于阻塞的套接口才有用,如果是非阻塞的套接口,它会立即返回并且指示错误WOULDBLOCK)
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值