将一个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 后增 ...
随机推荐
- Java Web项目 慧心人力资源管理系统
题目:慧心人力资源管理系统 文档下载:https://download.csdn.net/download/weixin_44893902/16336711 完整项目下载:https://downlo ...
- frontend-maven-plugin插件问题解决
1.插件介绍 frontend-maven-plugin为项目本地下载/安装Node和NPM,运行npm install命令 . 它适用于Windows,OS X和Linux. 这个插件也可以下载No ...
- Linux 进程调度
线程状态(context) 程序计数器(Program Counter),它表示当前线程执行指令的位置. 保存变量的寄存器. 程序的Stack.通常来说每个线程都有属于自己的Stack,Stack记录 ...
- Python_time&datetime
获取常用日常时间 # encoding: utf-8 import time import datetime # 当前时间 datetime_now_time = datetime.datetime. ...
- Flask_蓝图Blueprint(十四)
什么是蓝图? 蓝图:用于实现单个应用的视图.模板.静态文件的集合. 蓝图就是模块化处理的类. 简单来说,蓝图就是一个存储操作路由映射方法的容器,主要用来实现客户端请求和URL相互关联的功能. 在Fla ...
- 实验 1 :Mininet 源码安装和可视化拓扑
实验 1 : Mininet 源码安装和可视化拓扑工具 一 .实验目的 掌握 Mininet 的源码安装方法和 miniedit 可视化拓扑生成工具. 二 .实验任务 使用源码安装 Mininet 的 ...
- MATLAB中插值算法实现
%%%1.M文件%(1).以往少的程序可以在命令行窗口进行编码,但大量的程序编排到命令行窗口,%会有造成乱码的危险.(2).如果将命令编成程序存储在一个文件中(M文件),依次运行文件中的命令,则可以重 ...
- 【记录一个问题】thinkpad x1笔记本,安装ubuntu 16后,拔掉U盘,总是启动到windows,无法启动到ubuntu
如题 昨天使用ubuntu 18没有这个问题 ============================= 12:38 1.安装完成出现重启后,一定要拔掉U盘 2.BIOS里面的security boo ...
- ASP.NET 内联代码、内联表达式、数据绑定表达式使用方法罗列(形式就是常说的尖括号 百分号 等于号 井号)
今天在做渭南电脑维修网的一个小功能时遇到了一些问题,因此特别列出,以备他日之用. 首先对ASP.NET 内联代码.内联表达式.数据绑定表达式的概念进行罗列,详细概念以及基本的用法我就不在这里罗嗦了,请 ...
- 探索新冠肺炎(COVID-19)对全球航班的影响
Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 随着今天从欧洲到美国的旅行限制生效,以及为了减缓新冠病毒的传播更 ...