如何减少 TCP connect() 系统调用超时?

Posted

技术标签:

【中文标题】如何减少 TCP connect() 系统调用超时?【英文标题】:How to decrease TCP connect() system call timeout? 【发布时间】:2014-08-10 15:00:47 【问题描述】:

在下面的命令中,我启用文件 /dev/tcp/10.10.10.1/80 进行读写,并将其与文件描述符 3 相关联:

$ time exec 3<>/dev/tcp/10.10.10.1/80
bash: connect: Operation timed out
bash: /dev/tcp/10.10.10.1/80: Operation timed out

real    1m15.151s
user    0m0.000s
sys     0m0.000s

这会自动尝试执行 TCP 三次握手。如果 10.10.10.1 如上例所示无法访问,则connect 系统调用会尝试连接 75 秒。这个 75 秒超时是由bash 确定的吗?还是这个系统默认?最后但同样重要的是,有没有办法减少这个超时值?

【问题讨论】:

Stack Overflow 是一个编程和开发问题的网站。这个问题似乎离题了,因为它与编程或开发无关。请参阅帮助中心的What topics can I ask about here。也许Super User 或Unix & Linux Stack Exchange 会是一个更好的提问地点。 【参考方案1】:

如前所述,如果不修改源代码,在 Bash 中是不可能的,尽管这里是使用 timeout 命令的解决方法,例如:

$ timeout 1 bash -c "</dev/tcp/***.com/80" && echo Port open. || echo Port closed.
Port open.
$ timeout 1 bash -c "</dev/tcp/***.com/81" && echo Port open. || echo Port closed.
Port closed.

使用此语法,timeout 命令将在给定时间后终止进程。

更多选项请参见:timeout --help

【讨论】:

这应该是公认的答案,而不是在/proc/sys/net/ipv4/tcp_keepalive_time 上广泛更改值(不推荐)系统是上帝知道向打开套接字的进程的父进程发送信号将关闭它.我想知道为什么这行得通,$ timeout 1 &lt;/dev/tcp/***.com/81 &amp;&amp; echo Port open. 不行【参考方案2】:

否:无法使用/dev/tcp/ 更改超时时间

是的,您可以在任何编程语言中更改 TCP 连接的默认超时时间。

但是,bash 不是编程语言!

您可以查看源代码(参见:Bash Homepage),您可能会找到lib/sh/netopen.c 文件,您可以在_netopen4 函数中读取:

s = socket(AF_INET, (typ == 't') ? SOCK_STREAM : SOCK_DGRAM, 0);

你可以仔细阅读这个文件,没有考虑连接超时。

如果不修补 bash 源,就无法通过 bash 脚本更改连接超时。

使用 netcat 的简单 HTTP 客户端(接近纯 bash)

有一个用 bash 编写的HTTP 客户端示例,但使用netcat

#!/bin/bash

tmpfile=$(mktemp -p $HOME .netbash-XXXXXX)
exec 7> >(nc -w 3 -q 0 ***.com 80 >$tmpfile)
exec 6<$tmpfile
rm $tmpfile

printf >&7 "GET %s HTTP/1.0\r\nHost: ***.com\r\n\r\n" \
    /questions/24317341/how-to-decrease-tcp-connect-system-call-timeout

timeout=100;
while ! read -t .001 -u 6 status ; do read -t .001 foo;done
echo STATUS: $status

[ "$status" ] && [ -z "$status//HTTP*200 OK*" ] || exit 1

echo HEADER:
while read -u 6 -a head && [ "$head//$'\r'" ]; do
    printf "%-20s : %s\n" $head%: "$head[*]:1"
    done

echo TITLE:
sed '/<title>/s/<[^>]*>//gp;d' <&6

exec 7>&-
exec 6<&-

这可以渲染:

STATUS: HTTP/1.1 200 OK
HEADER:
Cache-Control        : private
Content-Type         : text/html; charset=utf-8
X-Frame-Options      : SAMEORIGIN
X-Request-Guid       : 46d55dc9-f7fe-425f-a560-fc49d885a5e5
Content-Length       : 91642
Accept-Ranges        : bytes
Date                 : Wed, 19 Oct 2016 13:24:35 GMT
Via                  : 1.1 varnish
Age                  : 0
Connection           : close
X-Served-By          : cache-fra1243-FRA
X-Cache              : MISS
X-Cache-Hits         : 0
X-Timer              : S1476883475.343528,VS0,VE100
X-DNS-Prefetch-Control : off
Set-Cookie           : prov=ff1129e3-7de5-9375-58ee-5f739eb73449; domain=.***.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly
TITLE:
bash - How to decrease TCP connect() system call timeout? - Stack Overflow
一些解释:

我们首先创建一个临时文件(出于安全原因在私有目录下),在使用它们之前绑定和删除。

$ tmpfile=$(mktemp -p $HOME .netbash-XXXXXX)
$ exec 7> >(nc -w 3 -q 0 ***.com 80 >$tmpfile)
$ exec 6<$tmpfile
$ rm $tmpfile

$ ls $tmpfile
ls: cannot access /home/user/.netbash-rKvpZW: No such file or directory

$ ls -l /proc/self/fd
lrwx------ 1 user user 64 Oct 19 15:20 0 -> /dev/pts/1
lrwx------ 1 user user 64 Oct 19 15:20 1 -> /dev/pts/1
lrwx------ 1 user user 64 Oct 19 15:20 2 -> /dev/pts/1
lr-x------ 1 user user 64 Oct 19 15:20 3 -> /proc/30237/fd
lr-x------ 1 user user 64 Oct 19 15:20 6 -> /home/user/.netbash-rKvpZW (deleted)
l-wx------ 1 user user 64 Oct 19 15:20 7 -> pipe:[2097453]

$ echo GET / HTTP/1.0$'\r\n\r' >&7
$ read -u 6 foo
$ echo $foo
HTTP/1.1 500 Domain Not Found

$ exec 7>&-
$ exec 6>&-

【讨论】:

Bash 无疑是一种编程语言。在网络方面,它的设备不是很完善,但这不是重点。 @tripleee 不,bash 是 shell。基本上不打算成为一种编程语言...命令语言脚本语言,但不是真正的编程语言我>。请参阅my ascii analog clock,特别是为什么无论如何都不要使用它!how to read binary by using pure bash...试试这个纯 bash 脚本并将性能与 C 编写的 base64 编码器进行比较... 咩,po-tah-to po-tay-to。如果您的标准是某些事情不方便,那么 Pascal 和 Fortran 也不是编程语言。 C 语言当然更通用,但这也意味着许多事情不如专用语言方便。 @tripleee 您是否尝试运行ascii-clock.sh 几个小时并检查内存使用情况? (左上角大写的S表示睡眠,你可以和For geeks: Ascii-Art analog clock上的其他版本比较) 这样的内存错误很糟糕,但这只是一个实现细节。如果他们解决了这个问题,你会改变你的看法吗?【参考方案3】:

由 TCP 决定。它可以通过应用程序代码在每个套接字的基础上减少。

NB 超时只有在完全没有响应的情况下才会生效。如果出现连接拒绝,则立即发生错误。

【讨论】:

我明白了。是否也可以在bash 中减少这个?我猜不是。。大概只有Cpython和其他编程语言? 我不知道有任何此类 bash 设置。

以上是关于如何减少 TCP connect() 系统调用超时?的主要内容,如果未能解决你的问题,请参考以下文章

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

accpet和connect设置超时

linux下有系统tcp连接超时时间么

Windows系统下的TCP参数优化

局域网下的客户端调用服务接口超时的问题总结

tcpsocket/tmp很慢