今天遇到下面问题
如果socket客户端进程挂点 或者正常close
服务端检测 select检测返回的是0 还是-1
还是大于1呀 这个基本问题 竟然我分不清楚了?
先从read函数 返回实际读取到的字节数 ,属于io基本操作说起
关于
②返回值等于0讨论
非阻塞 返回值等零表示没有数据可读 (这个理解是错误的 如果没有数据返回应该是EAGAIN)
阻塞情况下:select/epoll检测可读的情况下,read返回0表示远端close 异常断开
总结:
阻塞接收的recv有时候会返回0,这仅在socket被正常关闭时才会发生。
而当拔掉设备网线的时候,recv并不会发生变化,仍然阻塞,如果在这个拔网线阶段,
socket被关掉了,后果可能就是recv永久的阻塞了。网络原因检测不出来
③返回值小于0(-1)。
读取出错,在处理网络请求时可能是网络异常。
当errno的值EAGAIN、EINTER不算socket故障,应该继续接收
EAGAIN:表示内核对应的读缓冲区为空 没有数据可读
如果你连续做read操作而没有数据可读。此时程序不会阻塞起来等待数据准备就绪返 回,
read函数会返回一个错误EAGAIN,
提示你的应用程序现在没有数据可读请稍后再试。重新读数据,
在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,
errno代码为11(EAGAIN)
EINTER:系统在接收的时候因为收到其他中断信号而被迫返回,
代码:
cur_len = recv (sockfd, buf + recv_bytes, total - recv_bytes, 0);
if (cur_len == 0) //正常关闭
{
TRACE_LOG ("connection closed by peer, fd=%d", sockfd);
return -1;
}
else if (cur_len == -1)
{
goto recv_again
}
缓冲区为空 对epoll事件涉及2个重要触发方式
read读取数据吧缓冲区的数据完全读取了 返回-1 触发是事件
select函数实现I/O端口的复用 对事件状态关注
#include <sys/select.h>
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);
select函数的参数将告诉内核:
(1) 我们所关心的描述符。
(2) 对于每个描述符我们所关心的条件(是否读一个给定的描述符?是否想写一个给定的
描述符?是否关心一个描述符的异常条件?)。
(3) 希望等待多长时间(可以永远等待,等待一个固定量时间,或完全不等待)
select从内核返回后内核会告诉我们:
(1) 已准备好的描述符的数量。
(2) 哪一个描述符已准备好读、写或异常条件。
正值:某些文件可读写或出错
0:等待超时,没有可读写或错误的文件
负值:select错误
什么条件下述符已经做好准备.(读,写,异常)
验证代码:
int num = select(maxfd+1, &set, NULL, NULL, 0);
if(num < 0)
{
break;
}
else if(num == 0)
{ //在等待时间内没有连接被激活
continue;
}
QA
1 :我监听fd 如果每个都发生事件激活,是否select频繁的返回呀,
回答:是 ,select 如果检测多个不适合业务比较频繁的 我们目前只监控1个
2 read函数缺点
回答 网络异常仍然阻塞住,需要借助keepavlie机制
3 事件触发机制 是如何触发的看?
原理 目前回答不了
参考:
http://www.tuicool.com/articles/mAjiumn
-----------------end------------------