socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto
设置成非阻塞模式:
先用fcntl的F_GETFL获取flags,用F_SETFL设置flags|O_NONBLOCK;
即:
flags = fcntl(sockfd, F_GETFL, 0); //获取文件的flags值。
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); //设置成非阻塞模式;
同时在接收和发送数据时,需要使用MSG_DONTWAIT标志
即:
在recv,recvfrom和send,sendto数据时,将flag设置为MSG_DONTWAIT。
设置成阻塞模式:
先用fcntl的F_GETFL获取flags,用F_SETFL设置flags&~O_NONBLOCK;
即:
flags = fcntl(sockfd,F_GETFL,0); //获取文件的flags值。
fcntl(sockfd,F_SETFL,flags&~O_NONBLOCK); //设置成阻塞模式;
同时在接收和发送数据时,需要使用阻塞标志
即:
在recv,recvfrom和send,sendto数据时,将flag设置为0,默认是阻塞。
在将socket设置成非阻塞模式后,每次的对于sockfd 的操作都是非阻塞的;
非阻塞模式下:
connect
=0 当返回0时,表示立即创建了socket链接,
<0 当返回-1时,需要判断errno是否是EINPROGRESS(表示当前进程正在处理),否则失败。
例如:下面会有select或epoll监听fd是否建立链接,
select监听connect是否成功的例子,注意getsockopt验证,因为三次握手的第三个ACK有可能会丢失,但是客户端认为链接已经建立:
int ret = ::connect(_socket_fd, add.addr(), add.length());
if(ret == 0)
{
//建立链接成功
}
else if(ret < 0 && errno == EINPROGRESS) //errno == EINPROGRESS表示正在建立链接
{
// 等待连接完成,errno == EINPROGRESS表示正在建立链接
fd_set set;
FD_ZERO(&set);
FD_SET(_socket_fd,&set); //相反的是FD_CLR(_sock_fd,&set)
time_t = 10; //(超时时间设置为10毫秒)
struct timeval timeo;
timeo.tv_sec = timeout / 1000;
timeo.tv_usec = (timeout % 1000) * 1000;
int retval = select(_socket_fd + 1, NULL, &set, NULL, &timeo); //事件监听
if(retval < 0)
{
//建立链接错误close(_socket_fd)
}
else if(retval == 0) // 超时
{
//超时链接没有建立close(_socket_fd)
}
//将检测到_socket_fd读事件或写时间,并不能说明connect成功
if(FD_ISSET(_socket_fd,&set))
{
int error = 0;
socklen_t len = sizeof(error);
if(getsockopt(_socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
{
//建立简介失败close(_socket_fd)
}
if(error != 0) // 失败
{
//建立链接失败close(_socket_fd)
}
else
{
//建立链接成功
}
}
}
else
{
//出现错误 close(_sock_fd)
}
注意:这里主要是想强调当epoll或select监听到sockfd上有EPOLL_IN或EPOLL_OUT时,即读写事件时,并不能说明链接已经建立,如上面的代码。
/*
int error = 0;
socklen_t ilen = sizeof(error);
ret = getsockopt(fd,SOL_SOCKET,SO_ERROR,&error,&ilen);
if(ret < 0)
{
//说明链接建立失败,close(fd);
}
else if(error != 0 )
{
//说明链接建立失败,close(fd);
}
else
{
//说明链接建立成功。即可以向fd上写数据。
}
*/
recv 和 recvfrom
=0 当返回值为0时,表示对端已经关闭了这个链接,我们应该自己关闭这个链接,即close(sockfd)。另外因为异步操作会用select或epoll做事件触发,所以:
1、如果使用select,应该使用FD_CLR(sockfd,fd_set)将sockfd清除掉,不再监听。
2、如果使用epoll,系统会自己将sockfd清除掉,不再进行监听。
>0 当返回值大于0 且 小于sizeof(buffer)时,表示数据肯定读完。(如果等于sizeof(buffer),可能有数据还没读,应该继续读,不可能有大于)
<0 当返回值小于0,即等于-1时,分情况判断:
1、如果 errno 为 EAGAINE 或 EWOULDBLOCK
表示暂时无数据可读,可以继续读,或者等待epoll或select的后续通知。(EAGAINE,EWOULDBLOCK产生的
原因:可能是多进程读同一个sockfd,可能一个进程读到数据,其他进程就读取不到数据(类似惊群效应),当然
单个进程也可能出现这种情况。对于这种错误,不需用close(sockfd)。可以等待select或epoll的下一次触发,
继续读。)
2、如果 errno 为 EINTR
表示被中断了,可以继续读,或者等待epoll或select后续的通知。
否则,真的是读取数据失败。(此时应该close(sockfd))
send和sendto
返回值是实际发送的字符数,因为我们知道要发送的总长度,所以,如果没有发送完,我们可以继续发送。
<0 当返回值为 -1 时, 我们需要判断 errno:
1、如果errno为 EAGAINE 或 EWOULDBLOCK ,表示当前缓冲区写满,可以继续写,
或者等待epoll或select的后续通知,一旦有缓冲区,就会触发写操作,这个也是经常利用的一个特性。
2、如果errno为EINTR ,表示被中断了,可以继续写,或者等待epoll或select的后续通知。
否则真的出错了,即errno不为EAGAINE或EWOULDBLOCK或EINTR,此时应该close(sockfd)
>=0 >=0且不等于要求发送的长度,应该继续send,如果等于要求发送的长度,发送完毕。
socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto的更多相关文章
- IO模式设置网络编程常见问题总结—IO模式设置,阻塞与非阻塞的比较,recv参数对性能的影响—O_NONBLOCK(open使用)、IPC_NOWAIT(msgrcv)、MSG_DONTWAIT(re
非阻塞IO 和阻塞IO: 在网络编程中对于一个网络句柄会遇到阻塞IO 和非阻塞IO 的概念, 这里对于这两种socket 先做一下说明: 基本概念: 阻塞IO:: socket 的阻塞模式 ...
- linux socket设置阻塞与非阻塞
非阻塞IO 和阻塞IO: 在网络编程中对于一个网络句柄会遇到阻塞IO 和非阻塞IO 的概念, 这里对于这两种socket 先做一下说明: 基本概念: 阻塞IO:: socket 的阻塞模式 ...
- socket阻塞与非阻塞,同步与异步、I/O模型,select与poll、epoll比较
1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步: 所谓同步,就 ...
- socket阻塞与非阻塞,同步与异步
socket阻塞与非阻塞,同步与异步 作者:huangguisu 转自:http://blog.csdn.net/hguisu/article/details/7453390 1. 概念理解 在进行网 ...
- socket编程-阻塞和非阻塞
转自:https://www.cnblogs.com/sunziying/p/6501045.html 建立连接 阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的 ...
- linux-socket connect阻塞和非阻塞模式 示例
~/cpp$ ./connect 192.168.1.234 1234 kkkk block mode: ubuntu 14.04 : time used:21.0.001053s connect ...
- Socket调用方式(同步,异步,阻塞,非阻塞)
同步: 我调用一个功能,该功能没有结束前,我死等结果. 异步: 当一个异步过程调用发出后,调用者不能立刻得到结果.该功能在完成后,通过状态.通知和回调来通知调用者. 同步和非同步关注的是调用者是否等待 ...
- 网络编程中阻塞和非阻塞socket的区别
阻塞socket和非阻塞socket 建立连接阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的确认时,则connect返回.否则的话一直阻塞.非阻塞方式,conn ...
- 怎样通过MSG_WAITALL设置阻塞时间,IO模式精细讲解: MSG_DONTWAIT 、 MSG_WAITALL
首先给出MSDN上一段设置阻塞超时的代码:(网址为http://social.msdn.microsoft.com/Forums/zh-SG/visualcpluszhchs/thread/3d9da ...
随机推荐
- 【转】 BSS段 数据段 代码段 堆栈 指针 vs 引用
原文:http://blog.csdn.net/godspirits/article/details/2953721 BSS段 数据段 代码段 堆栈 (转+) 声明:大部分来自于维基百科,自由的百科全 ...
- 第二章 管理程序流(In .net4.5) 之 管理多线程
1. 概述 本章包括同步资源以及取消长时间任务相关的内容. 2. 主要内容 2.1 同步资源 ① lock关键字实现.会阻塞程序,有可能会导致死锁. ② volatile关键字可以禁用编译优化,用于避 ...
- 深入理解Java String#intern() 内存模型
原文出处: codelog.me 大家知道,Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,就会在字符串常量池中创建该字符串然后再返回. 字符串 ...
- DTAP street
一个网站程序的上线一般要经过开发[Development]测试[Testing]验收[Acceptance]生产[Production].所以又叫做DTAP street.对应有开发环境.测试环境.验 ...
- WPF Event 在 Command 中的应用初级篇,支持所有Event 展示松耦合设计的全部代码 - 解决TextBoxBase.TextChanged或者TextBox.TextChanged等类似事件绑定问题。
做过WPF开发的人,都知道做MVVM架构,最麻烦的是Event的绑定,因为Event是不能被绑定的,同时现有的条件下,命令是无法替代Event.而在开发过程中无法避免Event事件,这样MVVM的架构 ...
- java软件包的访问权限和继承
public:公共权限,可以修饰类.成员变量和成员函数,不论是否在同一个包中均可自由访问 package wang; //当一个类的权限为public时,类名必须和文件名相同 public class ...
- Jquer的三种初始化方式
$(document).ready(function(){ alert(200); }); jQuery(function($){ alert(100); }); $(function(){ aler ...
- 条款20:以const-reference传递替换by-value传递
缺省情况下,C++中函数参数的传递方式为by-value.即函数都是以实际参数的副本进行传递,而函数返回的也是一个副本.考虑如下实例程序: #include <iostream> clas ...
- Qt的进度条设置
progress bar 颜色设置 QProgressBar { border: 2px solid grey; border-radius: 5px; background-color: ...
- 用cmd命令合并N个文件
今天早上朋友发我一篇小说(42个TXT文件),让我给他合并为一个文件.我首先想到的是“Copy”命令,它可以复制文件,也可以合并文件. 例如:合并1.txt和2.txt到12.txt(其为ASCII文 ...