最近在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 tcp
net.ipv4.tcp_timestamps =
net.ipv4.tcp_window_scaling =
net.ipv4.tcp_sack =
net.ipv4.tcp_retrans_collapse =
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries =
net.ipv4.tcp_max_orphans =
net.ipv4.tcp_max_tw_buckets =
net.ipv4.tcp_keepalive_time =
net.ipv4.tcp_keepalive_probes =
net.ipv4.tcp_keepalive_intvl =
net.ipv4.tcp_retries1 =
net.ipv4.tcp_retries2 =
net.ipv4.tcp_fin_timeout =
net.ipv4.tcp_syncookies =
net.ipv4.tcp_tw_recycle =
net.ipv4.tcp_abort_on_overflow =
net.ipv4.tcp_stdurg =
net.ipv4.tcp_rfc1337 =
net.ipv4.tcp_max_syn_backlog =
net.ipv4.tcp_orphan_retries =
net.ipv4.tcp_fack =
net.ipv4.tcp_reordering =
net.ipv4.tcp_ecn =
net.ipv4.tcp_dsack =
net.ipv4.tcp_mem =
net.ipv4.tcp_wmem =
net.ipv4.tcp_rmem =
net.ipv4.tcp_app_win =
net.ipv4.tcp_adv_win_scale =
net.ipv4.tcp_tw_reuse =
net.ipv4.tcp_frto =
net.ipv4.tcp_frto_response =
net.ipv4.tcp_low_latency =
net.ipv4.tcp_no_metrics_save =
net.ipv4.tcp_moderate_rcvbuf =
net.ipv4.tcp_tso_win_divisor =
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_abc =
net.ipv4.tcp_mtu_probing =
net.ipv4.tcp_base_mss =
net.ipv4.tcp_workaround_signed_windows =
net.ipv4.tcp_challenge_ack_limit =
net.ipv4.tcp_limit_output_bytes =
net.ipv4.tcp_dma_copybreak =
net.ipv4.tcp_slow_start_after_idle =
net.ipv4.tcp_available_congestion_control = cubic reno
net.ipv4.tcp_allowed_congestion_control = cubic reno
net.ipv4.tcp_max_ssthresh =
net.ipv4.tcp_thin_linear_timeouts =
net.ipv4.tcp_thin_dupack =
net.ipv4.tcp_min_tso_segs =
net.ipv4.tcp_invalid_ratelimit =

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

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

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

#include <iostream>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h> long long GetCurrentMSecond()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * + tv.tv_usec / ;
} int main()
{
int fd = ;
struct sockaddr_in addr; fd = socket(AF_INET, SOCK_STREAM, ); socklen_t bufSize = * ;
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(); //连接一个不用的端口,以保证会触发超时
long long llBeginTime = GetCurrentMSecond();
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -)
{
long long llEndTime = GetCurrentMSecond();
std::cout << "connect failed, errno: " << errno << ", error: " << strerror(errno)
<< ", cost time: " << llEndTime - llBeginTime << std::endl;
return ;
}
std::cout << "connect success" << std::endl;
}

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

$ g++ connect.cpp -o main
$ sudo sysctl -w net.ipv4.tcp_syn_retries=1
net.ipv4.tcp_syn_retries = 1
$ ./main
connect failed, errno: 110, error: Connection timed out, cost time: 3000
$ sudo sysctl -w net.ipv4.tcp_syn_retries=2
net.ipv4.tcp_syn_retries = 2
$ ./main
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的超时时间。

linux下connect超时时间探究的更多相关文章

  1. Linux下connect超时处理【总结】

    1.前言 最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口.当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口.我们知道端口属于网络的应用层, ...

  2. Linux下connect超时处理

    1.前言 最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口.当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口.我们知道端口属于网络的传输层, ...

  3. 设置linux中tcp默认的20秒connect超时时间(转)

    无论你用任何语言或者是网络库,你都可以设置网络操作的超时时间,特别是connect.read.write的超时时间. 你可以在代码中把超时时间设置任意大小值,但是connect方法会有一点特殊. co ...

  4. Linux下获得系统时间的C语言实现

    Linux下获得系统时间的C语言的实现方法 #include<time.h> //C语言的头文件#include<stdio.h> //C语言的I/O   int main() ...

  5. 解决Linux下SSH超时自动断开

    title: 解决Linux下SSH超时自动断开 comments: false date: 2019-08-19 19:22:55 description: Linux 下 SSH 超时自动断开?? ...

  6. linux 设置connect 超时代码[select/epoll]

    转载请注明来源:https://www.cnblogs.com/hookjc/ linux下socket编程有常见的几个系统调用: 对于服务器来说, 有socket(), bind(),listen( ...

  7. linux 设置connect 超时

    转载请注明来源:https://www.cnblogs.com/hookjc/ 将一个socket 设置成阻塞模式和非阻塞模式,使用fcntl方法,即: 设置成非阻塞模式: 先用fcntl的F_GET ...

  8. VC socket Connect 超时时间设置

    设置connect超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案.偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使 ...

  9. Linux下修改系统时间并写入BIOS

    我们一般使用“date -s”命令来修改系统时间.比如将系统时间设定成2005年7月26日的命令如下. #date -s 07/26/2005 将系统时间设定成下午11点12分0秒的命令如下. #da ...

随机推荐

  1. 《selenium2 python 自动化测试实战》(13)——上传文件

    看代码: # coding: utf-8 from selenium import webdriver from time import sleep driver = webdriver.Firefo ...

  2. CentOS常用基础命令汇总

    1.关机 (系统的关机.重启以及登出 ) 的命令 shutdown -h now 关闭系统(1) init 0 关闭系统(2) telinit 0 关闭系统(3) shutdown -h hours: ...

  3. matplotlib ----- 同一线条的不同颜色

    对同一线条的各个段或者特殊点,  用不同的颜色. 参考下面 http://stackoverflow.com/questions/30121773/python-is-it-possible-to-c ...

  4. dict 没有 key 的情况

    如何处理, 请参考下文,  主要是要理解思路, https://www.polarxiong.com/archives/Python-%E6%93%8D%E4%BD%9Cdict%E6%97%B6%E ...

  5. 关于json格式字符串解析并用mybatis存入数据库

    园子里面找了很多关于json解析后存入数据库的方法,不是太乱,就是没有写完,我下面的主题代码多是受下面两位的启发,请按顺序查看 http://www.cnblogs.com/tian830937/p/ ...

  6. drone 学习六 发布部署&&集成私有容器仓库&&构建代码s3 保存

    备注:      需要进行drone 以及gitlab 环境的配置,可以参考相关资料   1. 参考项目 https://github.com/rongfengliang/drone-appdemo ...

  7. VS2010 代码前出现虚线

    VS2010 代码前出现虚线的问题,解决方法: 只需要用快捷键:Ctrl+E+S三个组合键就可以让其取消或显示了

  8. hadoop之 解析HDFS的写文件流程

    文件是如何写入HDFS的 ? 下面我们来先看看下面的“写”流程图:  假如我们有一个文件test.txt,想要把它放到Hadoop上,执行如下命令: 引用         # hadoop fs  - ...

  9. Errors running builder 'DeploymentBuilder' on project ' 解决方法

    此问题一般发生在Myeclipse 保存文件并自动部署时候. Errors occurred during the build. Errors running builder 'DeploymentB ...

  10. VS2003在vista/win7下搜索会出现僵死

    1.  VS2003在vista下搜索关键词的时候会出现僵死的问题的解决方案: VS2003快捷方式右击选中属性->兼容性页签 : 选中用兼容模式运行这个程序,下拉框中用windows xp2 ...