注意recv()如果读到数据为0,那么就表示文件结束了,如果在读的过程中遇到了中断那么会返回-1,同时置errno为EINTR。

因此判断recv的条件:
    如果read返回<=0
       如果==0
           表示文件结束, 处理
       如果<0 && errno==EINTR
           表示中断,处理
       否则,出错

我们举个例子:

int safe_tcp_recv (int sockfd, void *buf, int bufsize)
{
int cur_len;
recv_again:
cur_len = recv (sockfd, buf, bufsize, 0);
//closed by client
if (cur_len == 0)
{
TRACE_LOG ("connection closed by peer, fd=%d", sockfd);
return 0;
}
else if (cur_len == -1)
{
if (errno == EINTR)
goto recv_again;
else
ERROR_LOG ("recv error, fd=%d, errno=%d %m", sockfd, errno);
}
return cur_len;
}
或者
int safe_tcp_recv_n (int sockfd, void *buf, int total)
{
int recv_bytes, cur_len;
for (recv_bytes = 0; recv_bytes < total; recv_bytes += cur_len)
{
cur_len = recv (sockfd, buf + recv_bytes, total - recv_bytes, 0);
//closed by client
if (cur_len == 0) //正常关闭
{
TRACE_LOG ("connection closed by peer, fd=%d", sockfd);
return -1;
}
else if (cur_len == -1)
{
if (errno == EINTR)//还需要在读
cur_len = 0;
else if (errno == EAGAIN)
{
TRACE_LOG ("recv %d bytes from fd=%d", recv_bytes, sockfd);
return recv_bytes;
}
else
{
ERROR_RETURN (("recv tcp packet error, fd=%d, %m", sockfd), -1);
}
}
}
return recv_bytes;
}

但是write()如果写入的数据为0,那么就表示出错,也就是无法写入了,而如果在写的过程中遇到了中断,那么write()会返回-1,同时置errno为EINTR。
 因此判断write是否成功时,条件是write返回的结果是否<=0
 
int safe_tcp_send_n (int sockfd, const void *buf, int total)
{
int send_bytes, cur_len;
for (send_bytes = 0; send_bytes < total; send_bytes += cur_len)
{
cur_len = send (sockfd, buf + send_bytes, total - send_bytes, 0);
//closed by client
if (cur_len == 0)
{
TRACE_LOG ("send tcp packet error, fd=%d, %m", sockfd);
return -1;
}
else if (cur_len == -1)
{
if (errno == EINTR)
cur_len = 0;
else if (errno == EAGAIN)
{
return send_bytes;
}
else
{
TRACE_LOG ("send tcp packet error, fd=%d, %m", sockfd);
return -1;
}
}
}
//TRACE_LOG ("send: fd=%d, len=%d", sockfd, send_bytes);
return send_bytes;
}

首先我们看看recv的返回值:
 EAGAIN、EWOULDBLOCK、EINTR与非阻塞 长连接

EWOULDBLOCK用于非阻塞模式,不需要重新读或者写
EINTR指操作被中断唤醒,需要重新读/写
在Linux环境下开发经常会碰到很多错误(设置errno),其中EAGAIN是其中比较常见的一个错误(比如用在非阻塞操作中)。
从字面上来看,是提示再试一次。这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作(对文件或socket)的时候。例如,以 O_NONBLOCK的标志打开文件/socket/FIFO,如果你连续做read操作而没有数据可读。此时程序不会阻塞起来等待数据准备就绪返 回,read函数会返回一个错误EAGAIN,提示你的应用程序现在没有数据可读请稍后再试。重新读数据,其实这个也就是说明了一点,网络报还没有发完结束呢,还需要继续读,除非返回的是大于0的值,就代表的是读完了,返回正常读到的网络报的长度。
又例如,当一个系统调用(比如fork)因为没有足够的资源(比如虚拟内存)而执行失败,返回EAGAIN提示其再调用一次(也许下次就能成功)。
Linux - 非阻塞socket编程处理EAGAIN错误
在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN),这是什么意思?
这表明你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误,这个错误不会破坏socket的同步,不用管它,下次循环接着recv就可以。 对非阻塞socket而言,EAGAIN不是一种错误。在VxWorks和Windows上,EAGAIN的名字叫做EWOULDBLOCK。
另外,如果出现EINTR即errno为4,错误描述Interrupted system call,操作也应该继续。
最后,如果recv的返回值为0,那表明连接已经断开,我们的接收操作也应该结

关于非阻塞的recv的时候返回的处理相关推荐

  1. linux命令 recv阻塞时间,linux下close 掉socket 之后 阻塞的recv 不会立即返回

    在开发的一个基于rtmp聊天的程序时发现了一个很奇怪的现象. 在windows下当我们执行 closesocket的操作之后,阻塞的 recv会立即返回 -1 . 而在linux下当我们执行close ...

  2. python复制文件夹不阻塞_11.python并发入门(part14阻塞I/O与非阻塞I/O,以及引入I/O多路复用)...

    一.初步了解什么是I/O模型. 1.回顾,用户态与内核态. 操作系统位于应用程序和硬件之间,本质上是一个软件,它由内核以及系统调用组成. 内核:用于运行于内核态,主要作用是管理硬件资源. 系统调用:运 ...

  3. 一个理解同步异步阻塞非阻塞非常好的解释

    作者:知乎用户 链接:https://www.zhihu.com/question/19732473/answer/51734090 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  4. 怎样理解阻塞非阻塞与同步异步的区别

    怎样理解阻塞非阻塞与同步异步的区别? 发现很多人对这两个概念往往混为一谈 6 条评论 分享 按投票排序 按时间排序 47 个回答 605赞同 反对,不会显示你的姓名 卢毅 ,Lyft full-sta ...

  5. 这次,让我们捋清:同步、异步、阻塞、非阻塞

    继上一篇说透I/O模型后,我们来谈谈网络 I/O 经常会伴随的几个容易令人混淆的概念:同步.异步.阻塞.非阻塞的区别. 这篇写完之后铺垫就差不多了,之后就正式开始 Netty 深度剖析了,敬请期待,嘻 ...

  6. 非阻塞recvfrom卡住

    背景 多线程模式下,偶尔会遇到recvfrom在非阻塞模式下不能正常返回的情况,使得系统出现假死锁,从而导致整个系统不能提供服务. 剖析 在上图中,如果threadB在进行recvfrom调用时,so ...

  7. 阻塞/非阻塞 同步/异步

    1.同步和异步 关注的是消息的通讯机制  关注对象是被调用者 同步--发出调用时,在没有得到结果之前,该调用不返回.一旦返回就能得到返回值.  调用者主动等待被调用者返回结果 异步--发出调用时,直接 ...

  8. 网络编程 read 阻塞和非阻塞下的区别

    1,read 原型,参数以及返回值. #include <uinstd.h>ssize_t read(int fd, void *buf, size_t nbytes); -----rea ...

  9. 关于socket阻塞与非阻塞情况下的recv、send、read、write返回值

    recv: 阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小, 特别:非阻塞模式下返回 值 <0时并且(errno == EINTR || e ...

最新文章

  1. 对PostgreSQL的 ctid 的初步认识
  2. IDEA不能下载插件
  3. 吴恩达深度学习(一)-第三周:Planar data classification with one hidden layer
  4. 盘点电机重要应用的七大领域
  5. 一款在线画图工具的使用(推荐)
  6. 【无标题】免费论文查重的方法;知网也可以免费查重啦
  7. excel文件保护忘记密码解除
  8. BW随手记-项目上零碎总结(SAP销售,开票,获利能力分析)
  9. react native 自定义Image实现预加载图片及错误之后图片显示
  10. U-SEM体验模型——让游戏交互设计的维度更加清晰
  11. bzoj1776[Usaco2010 Hol]cowpol 奶牛政坛
  12. 售后服务场景智能调度解决方案
  13. 读书笔记(II) 编译原理及实践
  14. ​【​观察】云栖大会共话JDM模式 揭秘创新背后的价值和启示
  15. 后端线上服务监控与报警方案
  16. 6g运行和8g运行有什么差别
  17. Linux 如何设置当前时间
  18. python对于字典d d.get(x、y)_python--字典
  19. uni-app图片显示
  20. 2018,微信公众号可能要变天了

热门文章

  1. TextView实现自动滚动滚动.
  2. setTimeout里如果有$(this),$(this)指的是谁?
  3. php 处理 mysql to json, 前台js处理
  4. 批量删除html网页,批量删除.html · panghuamama/Clearly Local - Gitee.com
  5. c语言volatile_[技术]为什么单片机C语言编程时某一变量有时乱码
  6. 餐饮水单打印软件_开发一款餐饮手机app系统软件什么价格?有哪些方面需要考虑?...
  7. mysql数据库应用的权限层级_MySQL数据库的用户权限管理
  8. java stack list_JAVA自己实现List接口Stack
  9. 女士细线毛衣起多少针_从起针到缝合,教你织毛衣的各种要点(详细教程)
  10. 计算机二级网址打不开,大神为你解决win7系统打不开二级网页链接的操作教程...