linux非阻塞的socket EAGAIN的错误处理
http://blog.csdn.net/tianmohust/article/details/8691644
在Linux中使用非阻塞的socket的情形下。
(一)发送时
当客户通过Socket提供的send函数发送大的数据包时,就可能返回一个EAGAIN的错误。该错误产生的原因是由于send 函数中的size变量大小超过了tcp_sendspace的值。tcp_sendspace定义了应用在调用send之前能够在kernel中缓存的数据量。当应用程序在socket中设置了O_NDELAY或者O_NONBLOCK属性后,如果发送缓存被占满,send就会返回EAGAIN的错误。
为了消除该错误,有三种方法可以选择:
1.调大tcp_sendspace,使之大于send中的size参数
---no -p -o tcp_sendspace=65536
2.在调用send前,在setsockopt函数中为SNDBUF设置更大的值
3.使用write替代send,因为write没有设置O_NDELAY或者O_NONBLOCK
(二)接收时
接收数据时常遇到Resource temporarily unavailable的提示,errno代码为11(EAGAIN)。这表明你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误,这个错误不会破坏socket的同步,不用管它,下次循环接着recv就可以。对非阻塞socket而言,EAGAIN不是一种错误。在VxWorks和Windows上,EAGAIN的名字叫做EWOULDBLOCK。其实这算不上错误,只是一种异常而已。
另外,如果出现EINTR即errno为4,错误描述Interrupted system call,操作也应该继续。
最后,如果recv的返回值为0,那表明对方已将连接断开,我们的接收操作也应该结束。
(三)以下是另一种解释
假如发送端流量大于接收端的流量(意思是epoll所在的程序读比转发的socket要快),由于是非阻塞的socket,那么send()函数虽然返回,但实际缓冲区的数据并未真正发给接收端,这样不断的读和发,当缓冲区满后会产生EAGAIN错误(参考man send),同时,不理会这次请求发送的数据.所以,
- size_t socket_send(int sockfd, const char* buffer, size_t buflen)
- {
- size_t tmp;
- size_t total = buflen;
- const char *p = buffer;
- while(1)
- {
- tmp = send(sockfd, p, total, 0);
- if(tmp < 0)
- {
- // 当send收到信号时,可以继续写,但这里返回-1.
- if(errno == EINTR)
- {
- return -1;
- }
- // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满,
- // 在这里做延时后再重试.
- if(errno == EAGAIN)
- {
- usleep(1000);
- continue;
- }
- return -1;
- }
- if((size_t)tmp == total)
- {
- return buflen;
- }
- total -= tmp;
- p += tmp;
- }
- return tmp;
- }
linux非阻塞的socket EAGAIN的错误处理的更多相关文章
- linux非阻塞的socket EAGAIN的错误处理【转】
转自:http://blog.csdn.net/tianmohust/article/details/8691644 版权声明:本文为博主原创文章,未经博主允许不得转载. 在Linux中使用非阻塞的s ...
- Linux - 非阻塞socket编程处理EAGAIN错误
在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN),这表明你在非阻塞模式下调用 ...
- 非阻塞式socket的select()用法
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只 是习惯写诸如 connect.accept.recv或recvfrom这样的阻塞程 ...
- Linux 非阻塞connect,错误码:EINPROGRESS
当我们以非阻塞的方式来进行连接的时候,返回的结果如果是 -1,这并不代表这次连接发生了错误,如果它的返回结果是 EINPROGRESS,那么就代表连接还在进行中. 后面可以通过poll或者select ...
- Linux非阻塞IO(六)使用poll实现非阻塞的服务器端
关于poll模型监听的事件以及返回事件,我们定义宏如下: #define kReadEvent (POLLIN | POLLPRI) #define kWriteEvent (POLLOUT | PO ...
- Linux非阻塞IO(四)非阻塞IO中connect的实现
我们为客户端的编写再做一些工作. 这次我们使用非阻塞IO实现connect函数. int connect(int sockfd, const struct sockaddr *addr, sockle ...
- Linux非阻塞IO(八)使用epoll重新实现非阻塞的回射服务器
本文无太多内容,主要是几个前面提到过的注意点: 一是epoll的fd需要重新装填.我们将tcp_connection_t的指针保存在数组中,所以我们以这个数组为依据,重新装填fd的监听事件. //重新 ...
- Linux非阻塞IO(七)使用epoll重新实现客户端
使用poll与epoll的区别主要在于: poll可以每次重新装填fd数组,但是epoll的fd是一开始就加入了,不可能每次都重新加入 于是采用这种策略: epoll除了listenfd一开始就监听r ...
- Linux非阻塞IO(五)使用poll实现非阻塞的回射服务器客户端
前面几节我们讨论了非阻塞IO的基本概念.Buffer的设计以及非阻塞connect的实现,现在我们使用它们来完成客户端的编写. 我们在http://www.cnblogs.com/inevermore ...
随机推荐
- 一些值得思考的"小题"一
如下是我们查找数组中某个元素的一种通常做法 const int *Find(const int *array, int length, int x) { const int *p = array; ; ...
- xamarin android——数据绑定到控件(四)
本文为通过自定义列表适配器定义ListView,以上文为基础,基于ListActivity. 定义列表项布局,包含一个图片显示,标题和描述 <LinearLayout xmlns:android ...
- ssh 登陆指定 验证文件
当前用户jim ssh-keygen -t rsa 生成密钥 把pub结尾的公用密钥数据追加到192.168.1.3上的 /home/tom/.ssh/authKeys(文件名可能不一样) ssh - ...
- [Testing] 測試電子原文書
測試電子原文書 http://files.cnblogs.com/vincentmylee/SoftwareTesting2ndEdition.7z
- js 操作cookie
jquery.cookie中的操作: jquery.cookie.js是一个基于jquery的插件,点击下载! 创建一个会话cookie: $.cookie(‘cookieName’,'cookieV ...
- 同时安装vs2010和VS2012后IEnumerable<ModelClientValidationRule>编译错误
错误 类型“System.Web.Mvc.ModelClientValidationRule”同时存在于“c:\Program Files (x86)\Microsoft ASP.NET\ASP.NE ...
- fineui框架
http://fineui.com/demo/#/demo/layout/fit.aspx 虽然比较丑陋,但功能实用 此框架比较简单, 框架的作用你懂的,重点是要有帮助文档, 进阶型的容易上手的帮助文 ...
- Java注解处理器(转)
Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...
- 常见架构TLB miss处理方法(转)
转自网站:http://blog.sina.com.cn/s/blog_633f462901018reb.html 0. 综述 总的来说TLB miss处理分为硬件处理和软件处理两种,硬件 ...
- linux驱动系列之ubuntu快捷键(转)
Ubuntu快捷键-终端快捷键 1.关于终端的快捷键: Tab:tab键是比较常用的一个快捷键,它的作用是补全文件名或者路径.举例 来说,输入”cd /ho”在按一下tab键,终端里就会显示 ...