Linux 建立 TCP 连接的超时时间分析

tags: linux | network

Linux 系统默认的建立 TCP 连接的超时时间为 127 秒,对于许多客户端来说,这个时间都太长了, 特别是当这个客户端实际上是一个服务的时候,更希望能够尽早失败,以便能够选择其它的可用服务重新尝试。

socket 是 Linux 下实现的传输控制层协议,包括 TCP 和 UDP,一个 socket 端点由 IP 和端口对来唯一标识; 如果开启了地址复用,那么可以进一步由协议,IP 和端口来唯一标识。

系统调用 connect(2) 则是用来尝试建立 socket 连接(TCP)或者和远程协商一致(UDP)的函数。 connect 对于 UDP 来说并不是必须的,而对于 TCP 来说则是一个必须过程,注明的 TCP 3 次握手实际上也由 connect 来完成。

注:这里只分析 TCP 连接超时

网络中的连接超时非常常见,不管是广域网还是局域网,为了一定程度上容忍失败,所以连接加入了重试机制, 而另一方面,为了不给服务端带来过大的压力,重试也是有限制的。

在 Linux 中,连接超时典型为 2 分 7 秒,而对于一些 client 来说,这是一个非常长的时间; 所以在编程中,可以使用非阻塞的方式来实现,例如:使用 poll(2), epoll(2), select(2) 等系统调用来实现多路复用等待。

下面来看看 2 分 7 秒是怎样来的,以及怎样配置 Linux kernel 来缩短这个超时。

这里的net.ipv4.tcp_syn_retries的值等于n  的话,也就是说tcp的链接超时时间是2的n+1次方减1

2 分 7 秒


2 分 7 秒即 127 秒,刚好是 2 的 7 次方减一,聪明的读者可能已经看出来了,如果 TCP 握手的 SYN 包超时重试按照 2 的幂来 backoff, 那么:

  1. 第 1 次发送 SYN 报文后等待 1s(2 的 0 次幂),如果超时,则重试
  2. 第 2 次发送后等待 2s(2 的 1 次幂),如果超时,则重试
  3. 第 3 次发送后等待 4s(2 的 2 次幂),如果超时,则重试
  4. 第 4 次发送后等待 8s(2 的 3 次幂),如果超时,则重试
  5. 第 5 次发送后等待 16s(2 的 4 次幂),如果超时,则重试
  6. 第 6 次发送后等待 32s(2 的 5 次幂),如果超时,则重试
  7. 第 7 次发送后等待 64s(2 的 6 次幂),如果超时,则超时失败

上面的结果刚好是 127 秒。也就是说 Linux 内核在尝试建立 TCP 连接时,最多会尝试 7 次。

那么下面通过具体方法来验证。

首先,配置 iptables 来丢弃指定端口的 SYN 报文

# iptables -A INPUT --protocol tcp --dport 5000 --syn -j DROP

然后,打开 tcpdump 观察到达指定端口的报文

# tcpdump -i lo -Ss0 -n src 127.0.0.1 and dst 127.0.0.1 and port 5000

最后,使用 telnet 连接指定端口

$ date; telnet 127.0.0.1 5000; date

上面命令的输出如下:

Tue Jan  3 16:39:05 CST 2017
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection timed out
Tue Jan 3 16:41:12 CST 2017

而从 tcpdump 命令的输出可以看到:

16:39:05.690238 IP 127.0.0.1.58933 > 127.0.0.1.5000: Flags [S], seq 2286786481, win 43690, options [mss 65495,sackOK,TS val 179222486 ecr 0,nop,wscale 7], length 0
16:39:06.686988 IP 127.0.0.1.58933 > 127.0.0.1.5000: Flags [S], seq 2286786481, win 43690, options [mss 65495,sackOK,TS val 179222736 ecr 0,nop,wscale 7], length 0
16:39:08.690980 IP 127.0.0.1.58933 > 127.0.0.1.5000: Flags [S], seq 2286786481, win 43690, options [mss 65495,sackOK,TS val 179223237 ecr 0,nop,wscale 7], length 0
16:39:12.702973 IP 127.0.0.1.58933 > 127.0.0.1.5000: Flags [S], seq 2286786481, win 43690, options [mss 65495,sackOK,TS val 179224240 ecr 0,nop,wscale 7], length 0
16:39:20.718991 IP 127.0.0.1.58933 > 127.0.0.1.5000: Flags [S], seq 2286786481, win 43690, options [mss 65495,sackOK,TS val 179226244 ecr 0,nop,wscale 7], length 0
16:39:36.766986 IP 127.0.0.1.58933 > 127.0.0.1.5000: Flags [S], seq 2286786481, win 43690, options [mss 65495,sackOK,TS val 179230256 ecr 0,nop,wscale 7], length 0
16:40:08.830996 IP 127.0.0.1.58933 > 127.0.0.1.5000: Flags [S], seq 2286786481, win 43690, options [mss 65495,sackOK,TS val 179238272 ecr 0,nop,wscale 7], length 0

其中,Flags [S] 表示为 SYN 报文,可以看到总共发送了 7 次 SYN 报文,最后一次的时间为 16:40:08,而 telnet 超时退出的时间为 16:41:12,相差 64 秒。

怎样修改 connect timeout


对于很多客户端程序来说,127 秒都是一个很长的时间,特别是对于局域网来说,公司内部往往都具有网络质量较好的局域网, 访问内部的服务并不需要等待这么长的超时,而可以 fail earlier。

Linux 内核中,net.ipv4.tcp_syn_retries 表示建立 TCP 连接时 SYN 报文重试的次数,默认为 6,可以通过 sysctl 命令查看。

# sysctl -a | grep tcp_syn_retries
net.ipv4.tcp_syn_retries = 6

将其修改为 1,则可以将 connect 超时时间改为 3 秒,例如:

# sysctl net.ipv4.tcp_syn_retries=1

再次使用 telnet 验证超时时间,如下:

$ date; telnet 127.0.0.1 5000; date
Fri Feb 17 09:50:12 CST 2017
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection timed out
Fri Feb 17 09:50:15 CST 2017

注意:sysctl 修改的内核参数在系统重启后失效,如果需要持久化,可以修改系统配置文件

例如:,对于 CentOS 7 来说,添加 net.ipv4.tcp_syn_retries = 1 到 /etc/sysctl.conf 中即可。

原文章:http://www.chengweiyang.cn/2017/02/18/linux-connect-timeout/

Tcp超时修改的更多相关文章

  1. TCP超时与重传机制

    TCP超时与重传机制    TCP协议是一种面向连接的可靠的传输层协议,它保证了数据的可靠传输,对于一些出错,超时丢包等问题TCP设计的超时与重传机制.其基本原理:在发送一个数据之后,就开启一个定时器 ...

  2. TCP超时重传、滑动窗口、拥塞控制、快重传和快恢复

    TCP超时重传 原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止. 影响超时重传机制协议效率的一个关键参数是重传超时时 ...

  3. 【原创】TCP超时重传机制探索

    TCP超时重传机制探索 作者:tll (360电商技术) 1)通信模型 TCP(Transmission Control Protocol)是一种可靠传输协议.在传输过程中当发送方(sender)向接 ...

  4. TCP超时与重传机制与拥塞避免

    TCP超时与重传机制 TCP协议是一种面向连接的可靠的传输层协议,它保证了数据的可靠传输,对于一些出错,超时丢包等问题TCP设计的超时与重传机制. 基本原理:在发送一个数据之后,就开启一个定时器,若是 ...

  5. TCP超时重传时间的选择

    一---导读 TCP超时重传时间的选择是计算机网络中较复杂的问题之一,但幸好前辈们都把路铺好了,我们只需要学习并且遵循这些规则,有能力的话去进一步改正. 二---必知的一些专业术语 A--RTT( r ...

  6. TCP超时重传、序列号、滑动窗口简介

    文章目录 12 TCP:传输控制协议(初步) 12.1 引言 12.1.1 ARQ和重传 12.1.2 分组窗口和滑动窗口 12.1.3 变量窗口:流量控制和拥塞控制 12.1.4 变量窗口:设置重传 ...

  7. linux tcp超时重传实现分析

    kernel version 3.18.20 1.函数调用关系 tcp_ack-> tcp_clean_rtx_queue-> tcp_ack_update_rtt-> tp-> ...

  8. 《TCP/IP详解 卷一》读书笔记-----TCP超时重传

    1.TCP提供的是可靠传输,它通过接收方发送一个确认报文ACK来提供这种可靠性.但是数据报文和确认报文都可能会丢失,所以TCP会给发出的数据报文设置一个时间,如果超时了则进行重传 2.Karn's A ...

  9. TCP/IP笔记 三.运输层(3)——TCP超时重传算法

    TCP 每发送一个报文段,就对这个报文段设置一次计时器.只要计时器设置的重传时间到但还没有收到确认,就要重传这一报文段 1. 平均往返时延RTT 往返时延:一个报文段发出的时间,以及收到相应的确认报文 ...

随机推荐

  1. Eclipse使用Maven创建Dynamic Web Project

    1. 点击File->New->Other,在弹出的对话框中选择Maven->Maven Project: 2. 点击Next,选择maven-archetype-webapp: 3 ...

  2. ES6学习笔记十:模块的导入、导出

    一:模块导入 1) import { 要导入的属性.方法民 } from '模块路径'; 2)该种方法需要有配置文件,指明模块所在路径 import { 要导入的属性.方法民 } from '模块名' ...

  3. VIM自定义快捷键 abort

    "在选择模式下系统级复制 vmap ,c "+y<ESC>vmap ,C "+Y<ESC>"在选择模式下系统级剪切vmap ,x x:l ...

  4. java常见数据结构整理

    java中容器类数据结构主要在java.util包中. java.util包中三个重要的接口及特点:List(列表).Set(保证集合中元素唯一).Map(维护多个key-value键值对,保证key ...

  5. 微信小程序云端解决方案探索之路

    小程序刚推出的时候,很多人都觉得它就是 H5,因为开发小程序的三大语言和 HTML.CSS.JS 是一脉相承的,即使改变了扩展名也改不了其实质. 那么小程序的实质到底是不是 H5 呢?经过我们的论证分 ...

  6. Dockerfile 构建后端springboot应用并用shell脚本实现jenkins自动构建

    Dockerfile 文件构建docker镜像 FROM centos MAINTAINER zh*****eng "z*******ch.cn" ENV LANG en_US.U ...

  7. 做一个合格的Team Leader -- 领导和管理基本概念 三种激励手段:恐吓、贪念、承诺

    做一个合格的Team Leader -- 基本概念 1.领导和管理   人们乐于被领导:他们不喜欢被管理,不喜欢像牛一样被驱赶或指挥.   管理者强迫人们服从他们的命令,而领导者则会带领他们一起工作. ...

  8. 【Oracle】Oracle的内外连接

    目录结构: contents structure [+] Oracle的内外连接 内连接 等值连接 非等值连接 自连接 外连接 外连接的特点 如何实现外连接 SQL99的内外连接 SQL99的内连接 ...

  9. Postman 网络调试工具

    1.Postman 简介 Postman 是一款功能强大的网页调试与发送网页 HTTP 请求的工具.我们可以用来很方便的模拟 get 或者 post 或者其他方式的请求来调试接口. 官网下载地址 Po ...

  10. error nr.1045 access denied for user 'root'@'localhost' (using passwd:no)

    在windows上卸载了mysql,再次重新安装的时候运行失败,并报以下错误: 解决办法: 1.服务里面停止Mysql服务. 2.卸载Mysql,删除MySQL的安装目录. 3.此外还要删除以下目录的 ...