TCPIP协议栈的心跳、丢包重传、连接超时机制实例详解

目录

2、TCPIP协议栈的心跳机制

2.2、TCPIP协议栈的心跳机制说明

2.3、修改TCPIP协议栈的默认心跳参数

3、libwebsockets开源库中的心跳机制使用的就是TCPIP协议栈的心跳机制

5、使用非阻塞socket和select接口实现connect连接的超时控制

5.1、MSDN上对connect和select接口的说明

5.2、使用非阻塞socket和select实现连接超时的控制 

最近有个项目,客户的网络环境不太稳定,会时不时出现丢包和网络抖动的情况,导致我们软件客户端会时不时和服务器断链,导致正在进行中的视频会议会被中断。本文借此机会,结合具体的问题实例,详细讲解一下TCP/IP协议栈的 心跳机制 、 丢包重传机制 等内容,给大家提供一个借鉴和参考。

1、问题概述

虽然软件底层模块在网络恢复后能自动重连上服务器,但会议因为网络问题已经退出,需要重新加入会议。因为客户特殊的网络运行环境,会频繁出现网络抖动不稳定的情况,客户要求必须要实现60秒内网络恢复后能依然保持在会议中,保证会议流程不被中断。

客户坚持要实现这个特殊的功能点,项目已经接近尾声,目前处于客户试用阶段,不实现该功能,项目无法通过验收,客户不给钱。

前方同事将当前问题及项目进展情况向研发部门领导反馈,研发部紧急召开讨论会议,商讨60秒不掉会的实现方案。这里面涉及到两大类的网络连接,一类是传输控制信令的 TCP连接 ,另一类是传输音视频码流的 UDP连接 。UDP连接的问题不大,主要是TCP连接的断链与重连问题,下面主要讨论TCP连接相关问题。

在出现网络不稳定掉会时,可能是系统TCPIP协议栈已经检测到网络异常,系统协议层已经将网络断开了;也可能软件应用层的心跳机制检测到网络故障,断开了与服务器的链接。

对于系统TCPIP协议栈自身检测出来的网络异常,则可能存在两种情况,一是TCPIP协议栈自身的心跳机制检测出来的;二是TCP连接的丢包重传机制检测出异常。

对于应用层的心跳检测机制,我们可以放大超时检测时间。 本文我们主要讨论一下TCPIP协议栈的TCP连接的心跳、丢包重传、连接超时等机制 。在检测到网络异常后,我们底层可以自动发起重连或者信令发送触发自动重连,业务模块将会议相关资源保存不释放,在网络恢复后可以继续保持在会议中,可以继续接收到会议中的音视频码流,可以继续进行会议中的一些操作!

2、TCPIP协议栈的心跳机制

2.1、TCP中的ACK机制

TCP建链时的三次握手流程如下所示:

之所以说TCP连接是可靠的,首先是发送数据前要建立连接,再就是收到数据后都会给对方恢复一个ACK包,表明我收到你的数据包了。对于数据发送端,如果数据发出去后没有收到ACK包,则会触发丢包重传机制。

不管是建链时,还是建链后的数据收发时,都有ACK包,TCPIP协议栈的心跳包也不例外。

2.2、TCPIP协议栈的心跳机制说明

TCPIP协议栈有个默认的 TCP心跳机制 ,这个心跳机制是和 socket套接字 (TCP套接字)绑定的,可以对指定的套接字开启协议栈的心跳检测机制。 默认情况下,协议栈的心跳机制对socket套接字是关闭的 ,如果要使用需要人为开启的。

在Windows中,默认是每隔2个小时发一次心跳包,客户端程序将心跳包发给服务器后,接下来会有两种情况:

1) 网络正常时: 服务器收到心跳包,会立即回复ACK包,客户端收到ACK包后,再等2个小时发送下一个心跳包。其中,心跳包发送时间间隔时间keepalivetime,Windows系统中默认是2小时,可配置。如果在2个小时的时间间隔内,客户端和服务器有数据交互,客户端会收到服务器的ACK包,也算作心跳机制的心跳包,2个小时的时间间隔会重新计时。

2) 网络异常时: 服务器收不到客户端发过去的心跳包,没法回复ACK,Windows系统中默认的是1秒超时,1秒后会重发心跳包。如果还收不到心跳包的ACK,则1秒后重发心跳包,如果始终收不到心跳包,则在发出10个心跳包就达到了系统的上限,就认为网络出故障了,协议栈就会直接将连接断开了。其中,发出心跳包收不到ACK的超时时间称为keepaliveinterval,Windows系统中默认是1秒,可配置;收不到心跳包对应的ACK包的重发次数probe,Windows系统是固定的,是固定的10次,不可配置的。

所以TCPIP协议栈的心跳机制也能检测出网络异常,不过在默认配置下可能需要很久才能检测出来,除非网络异常出现在正在发送心跳包后等待对端的回应时,这种情况下如果多次重发心跳包都收不到ACK回应,协议栈就会判断网络出故障,主动将连接关闭掉。

2.3、修改TCPIP协议栈的默认心跳参数

TCPIP协议栈的默认心跳机制的开启, 不是给系统整个协议栈开启心跳监测 ,而是对某个socket套接字开启。

开启心跳机制后,还可以修改心跳的时间参数。从代码上看,先调用setsockopt给目标套接字开启心跳监测机制,再调用WSAIoctl去修改心跳检测的默认时间参数,相关代码如下所示:

 

  SOCKET socket;
  // ......(中间代码省略)

  int optval = 1;
  int nRet = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&optval, 
                                  sizeof(optval));
  if (nRet != 0)
       return;

  tcp_keepalive alive;
  alive.onoff = TRUE;
  alive.keepalivetime = 10*1000;
  alive.keepaliveinterval = 2*1000;
 
  DWORD dwBytesRet = 0;
  nRet = WSAIoctl(socket, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), NULL, 0, 
                            &dwBytesRet, NULL, NULL);
  if (nRet != 0)
      return;

上面的代码可以看到,先调用setsockopt函数,传入SO_KEEPALIVE参数,打开TCP连接的心跳开关,此时心跳参数使用系统默认的心跳参数值。紧接着,调用WSAIoCtrl函数,传入SIO_KEEPALIVE_VALS参数,同时将设置好时间值的心跳参数结构体传进去。</

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值