1.accept超时

  accept等待并接受连接请求的过程是阻塞的,可以通过IO转接来设置等待一定的时长,如果超时没有连接,就让这个函数返回,让当前进程/线程处理别的任务。

例:

// 最大的文件描述符是: lfd
fd_set rdset;
FD_ZERO(&rdset);
FD_SET(lfd, &rdset);
struct timeval tm = {, }; //设置超时时长10s
int ret = select(lfd+, &rdset, NULL, NULL, &tm);
if(ret == )
{
// 超时, 不等了
return;
}
//有连接请求
else if(ret > )
{
accept(lfd, addr, len); // 必然不阻塞
}

2.read、write超时

  同accept。

/*read*/
// 最大的文件描述符是: 通信的 connfd
fd_set rdset;
FD_ZERO(&rdset);
FD_SET(connfd, &rdset);
struct timeval tm = {, };
int ret = select(connfd+, &rdset, NULL, NULL, &tm);
if(ret == )
{
// 超时, 不等了
}
//有数据可读
else if(ret > )
{
read(connfd, buf, size); // 必然不阻塞
} /*write*/
//写缓冲区被写满,在写会造成阻塞
//对方不接收数据,本地写缓冲区一直阻塞。
fd_set wrset;
FD_ZERO(&wrset);
FD_SET(connfd, &wrset);
struct timeval tm = {, };
int ret = select(connfd+, NULL, &wrset, NULL, &tm);
if(ret == )
{
// 超时, 不等了, 写缓冲区还是满的
}
else if(ret > )
{
// 写缓冲区可写
write(connfd, buf, size);
}

3.connect超时

  connect内部有一个超时检测,connect是一个阻塞函数,会阻塞等待服务器返回连接的结果。

  如果要完成自己的connect超时检测,首先要将connect变成非阻塞。然后根据connect函数返回判断。

  Posix定义了与select/epoll和非阻塞connect相关的规定:

    connect连接建立成功,Socket描述符变为可写。

    connect连接建立失败,Socket描述符既可读又可写。(由于有未决的错误,从而可读又可写)

  连接失败,错误判定方式:

    使用select检测,socket可读可写,只能在可读集合通过getsockopt获取错误代码。

    使用epoll检测,socket可读可写,只能在EPOLLERR中通过getsockopt获取错误码。

// 1. 设置connect的非阻塞, 修改fd的属性
int fl = fcntl(fd, F_GETFL);
fl |= O_NONBLOCK;
fcntl(fd, F_SETFL, fl);
// 2. 连接服务器
int ret = conect(connfd, serveraddr, len);
// 返回-1: 连接失败, errno==EINPROGRESS,说明在连接过程中
if(ret == - && errno == EINPROGRESS)
{
fd_set wrset;
FD_ZERO(&wrset);
FD_SET(connfd, &wrset);
struct timeval tm = {, };
int ret = select(connfd+, NULL, &wrset, NULL, &tm);
if(ret == )
{
// 超时, 连接还没有完成
}
else if(ret > ) // ==1
{
// 判断连接是成功还是失败
int op;
int len = sizeof(op);
getsockopt(connfd, SOL_SOCKET, SO_ERROR, &op, &len);
if(op == )
{
// 正常
}
else if(op == -)
{
// 错误
}
}
}
//4.设置回阻塞模式
fcntl(fd, F_SETFL, fl&(~O_NONBLOCK);

  windows下设置阻塞模式

  unsigned long ul = 1;

  ioctlsocket(this->m_connfd, FIONBIO, &ul);

  非阻塞

  ul = 0;
  ioctlsocket(this->m_connfd, FIONBIO, &ul);
 

  int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);

  // 判断错误
  sockfd: 文件描述符
  level: SOL_SOCKET
  optname: SO_ERROR
  optval: int 类型, 存储错误状态
  optlen: optval大小对一个的以地址

Linux网络编程五、套接字超时的更多相关文章

  1. Linux网络编程——原始套接字实例:MAC 头部报文分析

    通过<Linux网络编程——原始套接字编程>得知,我们可以通过原始套接字以及 recvfrom( ) 可以获取链路层的数据包,那我们接收的链路层数据包到底长什么样的呢? 链路层封包格式 M ...

  2. Linux网络编程之套接字基础

    1.套接字的基本结构 struct sockaddr 这个结构用来存储套接字地址. 数据定义: struct sockaddr { unsigned short sa_family; /* addre ...

  3. Linux网络编程——原始套接字编程

    原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据.区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有 ...

  4. Linux网络编程——原始套接字能干什么?

    通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...

  5. LINUX 网络编程 原始套接字

    一 原始套接字 原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM.SOCK_DGRAM的套接字,它实现于系统核心.然而,原始套接字能做什么呢?首先来说,普通的套接字无法处理ICMP.I ...

  6. UNIX网络编程——设置套接字超时

    在涉及套接字的I/O操作上设置超时的方法有以下3种: 调用alarm,它在指定超时期时产生SIGALRM信号.这个方法涉及信号处理,而信号处理在不同的实现上存在差异,而且可能干扰进程中现有的alarm ...

  7. Linux 网络编程 高级套接字

    一.套接字选项: 有以下3中方式可以对套接字选项进行设置: getsockopt 和 setsockopt 函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数用于获得 ...

  8. Linux网络编程(五)

    /*Linux网络编程(五)——多路IO复用之select() 网络编程中,使用IO复用的典型场合: 1.当客户处理多个描述字时(交互式输入以及网络接口),必须使用IO复用. 2.一个客户同时处理多个 ...

  9. TCP/IP网络编程之网络编程和套接字

    网络编程和套接字 网络编程又称为套接字编程,就是编写一段程序,使得两台连网的计算机彼此之间可以交换数据.那么,这两台计算机用什么传输数据呢?首先,需要物理连接,将一台台独立的计算机通过物理线路连接在一 ...

  10. 【TCP/IP网络编程】:01理解网络编程和套接字

    1.网络编程和套接字 网络编程与C语言中的printf函数和scanf函数以及文件的输入输出类似,本质上也是一种基于I/O的编程方法.之所以这么说,是因为网络编程大多是基于套接字(socket,网络数 ...

随机推荐

  1. 分布式session一致性问题

    1.分布式session一致性 :指服务器集群情况下session共享的问题. 2.session的作用:保存服务器(tomcat)与客户端(浏览器)整个通讯的会话基本信息. 3.session应用场 ...

  2. SMTP实现发送邮箱2(封装版)

    SMTP.h #ifndef __SMTP_H__ //避免重复包含 #define __SMTP_H__ #include <iostream> #include <list> ...

  3. Scala学习十八——高级类型

    一.本章要点 单例类型可用于方法串接和带对象参数的方法 类型投影对所有外部类的对象都包含了其他内部类的实例 类型别名给类型指定一个短小的名称 结构类型等效于”鸭子类型“ 存在类型为泛型的通配参数提供了 ...

  4. springMVC接受json类型数据

    springMVC接受json格式的数据很简单 使用@RequestBody 注解,标识从请求的body中取值 服务端示例代码 @RequestMapping(value = "/t4&qu ...

  5. MongoDB实战读书笔记(二):面向文档的数据

    1 schema设计原则 1.1 关系型数据库的三大设计范式 第一范式(1NF)无重复的列 第二范式(2NF)属性完全依赖于主键 [ 消除部分子函数依赖 ] 第三范式(3NF)属性不依赖于其它非主属性 ...

  6. 【原创】大叔经验分享(79)mysql内存设置

    mysql内存设置,首先要知道当前的设置 MySQL [(none)]> show variables like '%buffer%'; +--------------------------- ...

  7. echarts 内存泄漏

    最近使用vue + Echarts 实现vue项目的数据可视化功能的时候,在ios环境下,点击列表页进入详情页几次就白屏了. 感觉白屏的原因是:echarts频繁初始化画图时候有内存泄漏,吃掉了所有内 ...

  8. S5PV210 点亮Led

    GPC1CON, R/W, Address = 0xE020_0080 GPC1DAT, R/W, Address = 0xE020_0084 举例 #define GPC1CON *((volati ...

  9. android项目笔记整理(2)

    31.利用SharedPreferences存储时间     读取时间:     SharedPreferences sp=this.getSharedPreferences("actm&q ...

  10. 【Git】三、版本回退&撤消修改&文件删除

    提要 //查看git操作日志 $ git log //单行格式查看操作日志 $ git log --pretty=oneline //还原操作到上一次版本,有几个^就上几次 $ git reset - ...