博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux下connect超时时间探究
阅读量:4222 次
发布时间:2019-05-26

本文共 3974 字,大约阅读时间需要 13 分钟。

最近在linux做服务器开发的时候,发现了一个现象:服务器在启动的时候调用了 connect 函数,因为连接了一个不可用的端口,导致connect最后报出了 “Connection timed out” 的错误。但是这中间过了六十多秒的时间。

为何会等待这么长的时间才超时呢?这个时间又在哪里设置?

《UNIX网络编程(第一卷)——套接口 API 和 X/Open 传输接口 API》一书的4.3节有写到:

  对于TCP套接口来说,函数 connect 激发TCP的三路握手过程,且仅在链接成功建立或出错时才返回,返回的错误可能有如下几种情况:

  1. 如果TCP客户没有收到SYN分节的响应,则返回ETIMEDOUT。例如在4.4BSD中,当调用函数 connect 时,发出一个SYN,若无响应,等待6秒之后再发一个;若仍无响应,24秒钟之后再发一个。若总共等待了75秒钟之后仍未响应,则返回错误...

从书中可以看到 connect 建立TCP链接的过程中,会发送SYN包,如果没有收到SYN包的回包,内核会多次发送SYN包,并且每次重试的间隔会逐渐增加,避免发送太多的SYN包影响网络。

在CentOS上,这个重试次数是可以设置的:

$ sysctl net.ipv4 | grep tcpnet.ipv4.tcp_timestamps = 1net.ipv4.tcp_window_scaling = 1net.ipv4.tcp_sack = 1net.ipv4.tcp_retrans_collapse = 1net.ipv4.tcp_syn_retries = 5net.ipv4.tcp_synack_retries = 5net.ipv4.tcp_max_orphans = 262144net.ipv4.tcp_max_tw_buckets = 262144net.ipv4.tcp_keepalive_time = 7200net.ipv4.tcp_keepalive_probes = 9net.ipv4.tcp_keepalive_intvl = 75net.ipv4.tcp_retries1 = 3net.ipv4.tcp_retries2 = 15net.ipv4.tcp_fin_timeout = 60net.ipv4.tcp_syncookies = 1net.ipv4.tcp_tw_recycle = 0net.ipv4.tcp_abort_on_overflow = 0net.ipv4.tcp_stdurg = 0net.ipv4.tcp_rfc1337 = 0net.ipv4.tcp_max_syn_backlog = 2048net.ipv4.tcp_orphan_retries = 0net.ipv4.tcp_fack = 1net.ipv4.tcp_reordering = 3net.ipv4.tcp_ecn = 2net.ipv4.tcp_dsack = 1net.ipv4.tcp_mem = 639168       852224  1278336net.ipv4.tcp_wmem = 4096        16384   4194304net.ipv4.tcp_rmem = 4096        87380   4194304net.ipv4.tcp_app_win = 31net.ipv4.tcp_adv_win_scale = 2net.ipv4.tcp_tw_reuse = 0net.ipv4.tcp_frto = 2net.ipv4.tcp_frto_response = 0net.ipv4.tcp_low_latency = 0net.ipv4.tcp_no_metrics_save = 0net.ipv4.tcp_moderate_rcvbuf = 1net.ipv4.tcp_tso_win_divisor = 3net.ipv4.tcp_congestion_control = cubicnet.ipv4.tcp_abc = 0net.ipv4.tcp_mtu_probing = 0net.ipv4.tcp_base_mss = 512net.ipv4.tcp_workaround_signed_windows = 0net.ipv4.tcp_challenge_ack_limit = 1000net.ipv4.tcp_limit_output_bytes = 262144net.ipv4.tcp_dma_copybreak = 4096net.ipv4.tcp_slow_start_after_idle = 1net.ipv4.tcp_available_congestion_control = cubic renonet.ipv4.tcp_allowed_congestion_control = cubic renonet.ipv4.tcp_max_ssthresh = 0net.ipv4.tcp_thin_linear_timeouts = 0net.ipv4.tcp_thin_dupack = 0net.ipv4.tcp_min_tso_segs = 2net.ipv4.tcp_invalid_ratelimit = 500

其中的 net.ipv4.tcp_syn_retries 选项控制着SYN的重试次数,可以通过如下命令来查看和设置:

$ sysctl net.ipv4.tcp_syn_retries       #查看net.ipv4.tcp_syn_retries = 5$ sudo sysctl -w net.ipv4.tcp_syn_retries=1 #设置net.ipv4.tcp_syn_retries = 1

下面用一个简单的程序,来验证各种次数下的connect超时时间:

#include 
#include
#include
#include
#include
#include
#include
long long GetCurrentMSecond(){ struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000 + tv.tv_usec / 1000;}int main(){ int fd = 0; struct sockaddr_in addr; fd = socket(AF_INET, SOCK_STREAM, 0); socklen_t bufSize = 128 * 1024; int retCode = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufSize, sizeof(bufSize)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("192.168.207.128"); addr.sin_port = htons(13500); //连接一个不用的端口,以保证会触发超时 long long llBeginTime = GetCurrentMSecond(); if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { long long llEndTime = GetCurrentMSecond(); std::cout << "connect failed, errno: " << errno << ", error: " << strerror(errno) << ", cost time: " << llEndTime - llBeginTime << std::endl; return 0; } std::cout << "connect success" << std::endl;}

通过设置不同的重试次数,探究各种重试次数下的time out时间:

 
  1. $ g++ connect.cpp -o main

  2. $ sudo sysctl -w net.ipv4.tcp_syn_retries=1

  3. net.ipv4.tcp_syn_retries = 1

  4. $ ./main

  5. connect failed, errno: 110, error: Connection timed out, cost time: 3000

  6. $ sudo sysctl -w net.ipv4.tcp_syn_retries=2

  7. net.ipv4.tcp_syn_retries = 2

  8. $ ./main

  9. connect failed, errno: 110, error: Connection timed out, cost time: 7000

 

重试次数 超时时间(单位:毫秒)
1 3000  
2 7000
3 14999
4 31000
5 63001
6 126999

从表格中可以看到,当前设置重试次数为5的时候,超时时间是63秒,可以通过修改重试次数的方式,来改变connect的超时时间。

转载于:https://www.cnblogs.com/minglee/p/10161899.html

你可能感兴趣的文章
Oracle Linux 6.1 + Oracle 11.2.0.1 RAC + RAW 安装文档
查看>>
Oracle 11g 新特性 -- Online Patching (Hot Patching 热补丁)说明
查看>>
Oracle 11g 新特性 -- ASM 增强 说明
查看>>
Oracle 11g 新特性 -- Database Replay (重演) 说明
查看>>
Oracle 11g 新特性 -- 自动诊断资料档案库(ADR) 说明
查看>>
Oracle 11g 新特性 -- RMAN Data Recovery Advisor(DRA) 说明
查看>>
CSDN博客之星 投票说明
查看>>
Oracle wallet 配置 说明
查看>>
Oracle smon_scn_time 表 说明
查看>>
VBox fdisk 不显示 添加的硬盘 解决方法
查看>>
Secure CRT 自动记录日志 配置 小记
查看>>
RMAN RAC 到 单实例 duplicate 自动分配通道 触发 ORA-19505 错误
查看>>
mysql 随机分页的优化
查看>>
DB2快速创建测试库
查看>>
利用db2look查看ddl
查看>>
SD卡驱动分析--基于高通平台
查看>>
[图文] Seata AT 模式分布式事务源码分析
查看>>
pm 源码分析
查看>>
Sending the User to Another App
查看>>
kmsg_dump
查看>>