socket recv阻塞与非阻塞error总结

recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结。

首先阻塞接收的recv有时候会返回0,这仅在对端已经关闭TCP连接时才会发生。
      而当拔掉设备网线的时候,recv并不会发生变化,仍然阻塞,如果在这个拔网线阶段,socket被关掉了,后果可能就是recv永久的阻塞了。
      所以一般对于阻塞的socket都会用setsockopt来设置recv超时。
      当超时时间到达后,recv会返回错误,也就是-1,而此时的错误码是EAGAIN或者EWOULDBLOCK,POSIX.1-2001上允许两个任意一个出现都行,所以建议在判断错误码上两个都写上。
      如果socket是被对方用linger为0的形式关掉,也就是直接发RST的方式关闭的时候,recv也会返回错误,错误码是ENOENT
      还有一种经常在代码中常见的错误码,那就是EINTER,意思是系统在接收的时候因为收到其他中断信号而被迫返回,不算socket故障,应该继续接收。但是这种情况非常难再现,我尝试过一边一直在不停的发信号,一边用recv接收数据,也没有出现过。这种异常错误我附近只有一个朋友在用write的时候见到过一次,但是总是会有概率出现的,所以作为完善的程序必须对此错误进行特殊处理。
一般设置超时的阻塞recv常用的方法都如下:
while(1)
{
    cnt = (int)recv(m_socket, pBuf,RECVSIZE, 0);
    if( cnt >0 )
    {
        //正常处理数据
    }
    else
   {
         if((cnt<0) &&(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR)) //这几种错误码,认为连接是正常的,继续接收
        {
            continue;//继续接收数据
        }
        break;//跳出接收循环
    }

}

最后,如果recv的返回值为0,那表明连接已经断开,我们的接收操作也应该结束。

阻塞与非阻塞recv返回值没有区分,都是 <0 出错 =0 连接关闭 >0 接收到数据大小。

Linux环境下,须如下定义:struct timeval timeout = {3,0}; 
//设置发送超时
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));

//设置接收超时
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));

时间: 2024-10-05 01:47:46

socket recv阻塞与非阻塞error总结的相关文章

关于socket阻塞与非阻塞情况下的recv、send、read、write返回值(转载)

1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回值 <0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,继续接收.只是阻塞模式下recv会阻塞着接收数据,非阻塞模式下如果没有数据会返回,不会阻塞着读,因此需要 循环读取 2.阻塞模式与非阻塞模式下writ

面向连接的socket数据处理过程以及非阻塞connect问题

对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后必须调用bind绑定到一个指定的地址,然后调用int listen(int sockfd, int backlog);进行监听.此时服务器socket允许客户端进行连接,backlog提示没被accept的客户连接请求队列的大小,系统决定实际的值,最大值定义为SOMAXCONN在头文件<sys/so

基于MFC的socket编程(异步非阻塞通信)

对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清,只知其所以而不知起所以然. 异步方式指的是发送方不等接收方响应,便接着发下个数据包的通信方式:而同步指发送方发出数据后,等收到接收方发回的响应,才发下一个数据包的通信方式. 阻塞套接字是指执行此套接字的网络调用时,直到成功才返回,否则一直阻塞在此网络调用上,比如调用recv()函数读取网络缓冲区中的数据,

socket阻塞与非阻塞,同步与异步、I/O模型,select与poll、epoll比较

1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步:      所谓同步,就是在c端发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:      异步的概念和同步相对.当c端一个异步过程调用发出后,调

socket阻塞与非阻塞,同步与异步、I/O模型

socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:      异步的概念和同步相对

【转载】socket阻塞与非阻塞,同步与异步、I/O模型

转自:http://blog.csdn.net/hguisu/article/details/7453390 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任

socket编程的同步、异步与阻塞、非阻塞示例详解

socket编程的同步.异步与阻塞.非阻塞示例详解之一 分类: 架构设计与优化 简介图 1. 基本 Linux I/O 模型的简单矩阵 每个 I/O 模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点.本节将简要对其一一进行介绍. 一.同步阻塞模式在这个模式中,用户空间的应用程序执行一个系统调用,并阻塞,直到系统调用完成为止(数据传输完成或发生错误). /* * \brief * tcp client */ #include <stdio.h> #include <stdlib

Socket编程中,阻塞与非阻塞的区别

阻塞:一般的I/O操作可以在新建的流中运用.在服务器回应前它等待客户端发送一个空白的行.当会话结束时,服务器关闭流和客户端socket.如果在队列中没有请示将会出现什么情况呢?那个方法将会等待一个的到来.这个行为叫阻塞.accept()方法将会阻塞服务器线程直到一个呼叫到来.当5个连接处理完闭之后,服务器退出.任何的在队列中的呼叫将会被取消. 非阻塞:非阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回.比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,

win32 socket阻塞与非阻塞函数及设置

win32 socket中有些函数是默认阻塞的,比如accept(),send(),recv()等等,其中send()与recv()的阻塞概念与accept()的阻塞概念不同. send()与recv()只是完成数据的拷贝工作,即send()函数仅仅是将数据放到发送缓冲区中,至于实际的发送工作由网络协议完成:recv()函数仅仅是从接收缓冲区中读取数据,实际接收数据的操作由网络协议完成.send()的阻塞主要由发送数据填满发送缓冲区产生的,recv()的阻塞则是由接收缓冲区中没有数据可读引起的.