将一个socket 设置成阻塞模式和非阻塞模式,使用fcntl方法,即:
设置成非阻塞模式:
先用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 为 EAGAIN 或 EWOULDBLOCK
表示暂时无数据可读,可以继续读,或者等待epoll或select的后续通知。(EAGAIN,EWOULDBLOCK产生的
原因:可能是多进程读同一个sockfd,可能一个进程读到数据,其他进程就读取不到数据(类似惊群效应),当然
单个进程也可能出现这种情况。对于这种错误,不需用close(sockfd)。可以等待select或epoll的下一次触发,
继续读。)
2、如果 errno 为 EINTR
表示被中断了,可以继续读,或者等待epoll或select后续的通知。
否则,真的是读取数据失败。(此时应该close(sockfd))
send和sendto
返回值是实际发送的字符数,因为我们知道要发送的总长度,所以,如果没有发送完,我们可以继续发送。
<0 当返回值为 -1 时, 我们需要判断 errno:
1、如果errno为 EAGAIN 或 EWOULDBLOCK ,表示当前缓冲区写满,可以继续写,
或者等待epoll或select的后续通知,一旦有缓冲区,就会触发写操作,这个也是经常利用的一个特性。
2、如果errno为EINTR ,表示被中断了,可以继续写,或者等待epoll或select的后续通知。
否则真的出错了,即errno不为EAGAIN或EWOULDBLOCK或EINTR,此时应该close(sockfd)
>=0 >=0且不等于要求发送的长度,应该继续send,如果等于要求发送的长度,发送完毕。
- linux 设置connect 超时代码[select/epoll]
转载请注明来源:https://www.cnblogs.com/hookjc/ linux下socket编程有常见的几个系统调用: 对于服务器来说, 有socket(), bind(),listen( ...
- Linux下connect超时处理【总结】
1.前言 最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口.当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口.我们知道端口属于网络的应用层, ...
- Linux下connect超时处理
1.前言 最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口.当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口.我们知道端口属于网络的传输层, ...
- linux下connect超时时间探究
最近在linux做服务器开发的时候,发现了一个现象:服务器在启动的时候调用了 connect 函数,因为连接了一个不可用的端口,导致connect最后报出了 “Connection timed out ...
- iOS 设置connect超时
NSLock *theLock; [theLock lock]; int fd, error; struct sockaddr_in addr; ))<) { cout<<" ...
- VC socket Connect 超时时间设置
设置connect超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案.偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使 ...
- C Socket编程之Connect超时 (转)
网络编程中socket的分量我想大家都很清楚了,socket也就是套接口,在套接口编程中,提到超时的概念,我们一下子就能想到3个:发送超时,接收超时,以及select超时(注:select函数并不是只 ...
- 设置linux中tcp默认的20秒connect超时时间(转)
无论你用任何语言或者是网络库,你都可以设置网络操作的超时时间,特别是connect.read.write的超时时间. 你可以在代码中把超时时间设置任意大小值,但是connect方法会有一点特殊. co ...
- linux ssh连接超时断连设置
以下均针对redhat6.5系统进行说明. 一.设置ssh超时断连 使用root用户,编辑/etc/profile文件,在 HOSTNAME='/bin/hostname' HISTIZE=30 后增 ...
随机推荐
- 【jvm】04-我偷偷改了你编译后的class文件
[jvm]04-我偷偷改了你编译后的class文件 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请 ...
- 在页面上绘制一张表格,使用 DOM 节点的动态添加和删除向表格中插入数据,点击表格每行后的“删除”超链接
查看本章节 查看作业目录 需求说明: 在页面上绘制一张表格,使用 DOM 节点的动态添加和删除向表格中插入数据,点击表格每行后的"删除"超链接,使用 DOM 节点的删除操作将对应的 ...
- Parallel.ForEach 之 MaxDegreeOfParallelism
参考:Max Degree of Parallelism最大并行度配置 结论: 与设置的线程数有关 有设置的并行度有关 测试如下: @@@code System.Threading.ThreadPoo ...
- Redis真的又小又快又持久吗
一本正经 面试官:小伙子,谈谈对Redis的看法. 我:啊,看法呀,坐着看还是躺着看.Redis很小?很快?但很持久? 面试官:一本正经的说,我怀疑你在开车,不仅开开车还搞颜色. 我:... 面试官: ...
- [ bootstrap ] 实现卡片里面包含图片、内容、操作按钮,形成左中右的布局
描述: 如图 实现: <div class="card border-0 mb-3 mt-3"> <!-- 列表头部 --> <div class=& ...
- openlayers素材网站
1.教程网站 http://weilin.me/ol3-primer/ch05/05-03.html 2.特效气象图 https://earth.nullschool.net/zh-cn/#curre ...
- atroot 的个人博客
我的个人博客 左上角 MENU 打开导航菜单! 向下滚动查看内容! 为啥我要坚持更新博客 周围有很多小伙伴在问,你写博客会有人看嘛?如果没人看,那岂不是写的就没有意义了吗? 这个问题也一度让我陷入是否 ...
- python极简教程05:生成器和匿名函数
测试奇谭,BUG不见. 讲解之前,我先说说我的教程和网上其他教程的区别: 1 我分享的是我在工作中高频使用的场景,是精华内容: 2 我分享的是学习方法,亦或说,是指明你该学哪些.该重点掌握哪些内容: ...
- [开发笔记usbTOcan]用树莓派搭建私有Git服务器
0 | 思路 在开始编程前,先创建一个版本管理库,以前一直用SVN,但目前用Git的还是比较,正好利用这个机会学习GIt. 想过使用Github提供的免费服务器,但项目目前还没有做开源的准备,于是就有 ...
- fidder无法下载证书的最佳解决办法
为什么有的小伙伴安装fidder不好使,手机无法下载证书? 1.安装一定要去官网安装! 一定要去官网安装! 一定要去官网安装!官方网址:https://www.telerik.com/download ...