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. - 多次点击事件 MD

  2. 12-MySQL DBA笔记-MySQL复制

    第12章 MySQL复制 本章将为读者讲述MySQL的复制技术,首先,介绍最基础的主从复制,它是其他所有复制技术的基础,接着再为读者讲述各种复制架构的搭建,最后,列举了一些常见的复制问题及处理方式.复 ...

  3. RestShrap Simple REST and HTTP Client for .NET 了解

    最近做一个项目,需要上传文件到文件服务器, 文件服务器是 内部的webapi形式的接口.经朋友推荐使用restshrap , 例子: //上传文件 var request=new RestClient ...

  4. SIP 3pcc

    3PCC全称Third Party Call Control,中文即第三方电话呼叫控制,指的是由第三方控制者在另外两者之间建立一个会话,由控制者负责会话双方的媒体协商.3PCC是一种非常灵活的会话控制 ...

  5. HTML Ueditor图片宽度超出编辑器

    问题描述 Ueditor上传图片宽度尺寸超出编辑器宽度,显示异常 解决方案 ueditor.all.js 添加img宽度限制(搜索body{margin:8px;font-family:sans-se ...

  6. 把app(apk和ipa文件)安装包放在服务器上供用户下方法

    怎么把app(apk和ipa文件)安装包放在服务器上供用户下载? IIS服务器网站不能下载.apk文件的原因:IIS的默认MIME类型中没有.apk文件,所以无法下载.解决办法:给.apk格式文件添加 ...

  7. go爬虫之爬取豆瓣电影

    go爬取豆瓣电影 好久没使用go语言做个项目了,上午闲来无事花了点时间使用golang来爬取豆瓣top电影,这里我没有用colly框架而是自己设计简单流程.mark一下 思路 定义两个channel, ...

  8. WebLogic 12c Linux 命令行 静默安装

    CentOS 6.3安装配置Weblogic 10  http://www.linuxidc.com/Linux/2014-02/96918.htm Oracle WebLogic 11g 安装部署文 ...

  9. $(selector).each() 和$each() 的区别

    今天在做项目的时候, 后台数据需要循环遍历出来, 想到each,    结果,竟然不记得语法了 现在来回顾一下,而搜索了一下,竟然发现有两种each  一种就是$(selector).each()  ...

  10. C语言创建线程以及使用锁进行读写分离

    线程的使用 1.线程的创建 线程的相关操作放在<pthread.h>中. 1.1我们定义一个线程,首先要进行定义一个函数,类似我们创建一个a线程 void *thread_a(void * ...