首页 » SEO优化 » php断定tcp中止技巧_4个实验彻底搞懂TCP连接的断开

php断定tcp中止技巧_4个实验彻底搞懂TCP连接的断开

访客 2024-11-22 0

扫一扫用手机浏览

文章目录 [+]

在我们的电脑上,可以利用 python 的 SimpleHTTPServer 来快速起一个 http 做事(http 也是基于 TCP 协议),比如这样:

python -m SimpleHTTPServer 20880

php断定tcp中止技巧_4个实验彻底搞懂TCP连接的断开

再通过 nc 或 telnet 这两个命令来创建 TCP 连接,比如我测试利用 nc 来创建连接

php断定tcp中止技巧_4个实验彻底搞懂TCP连接的断开
(图片来自网络侵删)

nc -v ip port

Connection to ip port [tcp/] succeeded! 表示连接成功

我们如何不雅观察这个连接呢?可以通过 netstat 或 lsof 来查看这条"连接",这里我利用 lsof(mac 与 Linux 系统的 netstat 命令不太一样,利用起来有点别扭 )

lsof -i:20880

无论是客户端还是做事端都会占用一个端口,不过做事端端口是固定的,客户端端口是随机的。

如果我们想看 TCP 连接和断开时握手与挥手的 TCP 报文怎么查看呢?可以利用 tcpdump 命令

三次握手

tcpdump -A -vv -i any -S host 10.179.245.95

为了方便查看,和上面的经典图放在了一起

这里的参数须要提一下的是 -S,如果不加 -S 参数看到的第三次握手的ack=1,与书上的理论不太一样,实在这里只是 tcpdump 简化了展示,想看实际值须要加 -S

这里的 Flags [S]/[S.]/[.]

[S] 代表 SYN[.] 代表 ACK,[S.] 便是 SYN + ACK四次挥手

命令与抓三次握手相同,我们抓到如下挥手数据

[F] 代表 FIN

这张图有点奇怪,四次挥手居然变成了三次,这实在是 TCP 协议的实现问题,如果第二次与第三次挥手之间没有数据发送,那么被动断开连接的一方就可能会把第二次的 ACK 与 第三次的 FIN 合并为一次挥手。

当然我也抓到过正常的四次挥手,大概长这样

非常断开

上面铺垫了这么多,现在开始进入正题。

TCP 连接断开是谁发起的

我们来思考一个问题:TCP 连接的断开是谁发起的?程序本身还是操作系统?

我们来看一段非常大略的 TCP 连接创建与断开的代码

tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:20880")conn, err := net.DialTCP("tcp", nil, tcpAddr)if err != nil { fmt.Println("Client connect error ! " + err.Error()) return}defer func() { err := conn.Close() fmt.Println("Client connect closed !") if err != nil { fmt.Println(err) }}()fmt.Println(conn.LocalAddr().String() + " : Client connected!")time.Sleep(10 time.Second)

运行后,效果如下,也符合我们预期:当程序打印 Client connected! 时,能看到连接,当打印 Client connect closed! 时,连接断开

如果我们在连接断开前利用 kill -9 强杀进程呢?(这里我用了两台电脑来测试)

我们创造 conn.Close() 并没有实行,但四次挥手还是发生了!

查阅资料创造如下结论:

a、b 两个正常连接的对端进程。
如果 b 进程没有调用 close 就非常终止,那么发送 FIN 包是内核 OS 代劳

断电/断网时的连接是若何断开的

我们通过上面的实验创造就算进程非常终止,操作系统也会帮忙发起四次挥手

但如果是断电或断网的情形下,操作系统就无法代劳了,这时会若何呢?为了便于测试,这里用两台电脑,client 连接 server,断开 server 的网络来仿照断网断电情形。

可以肯定的是断网,断电后,连接不会立即断开,那么后续连接是否会断开呢?我们分成下面几种情形来看

断网时有数据传输

断网时如果有数据发送,由于收不到 ACK,以是会重试,但并不会无限重试下去,达到一定的重发次数之后,如果仍旧没有任何确认应答返回,就会判断为网络或者对端主机发生了非常,逼迫关闭连接。
此时的关闭是直接关闭,而没有挥手(数据都发不出去,还挥啥手),Linux 下的设置为

最小重传韶光是200ms 最大重传韶光是120s 重传次数为15

断网时没有数据传输

断网时如果没有数据传输,还得看 TCP 连接的 KeepAlive 是否打开,关于 TCP 的 KeepAlive 简介如下:

TCP KeepAlive 是一种在不影响数据流内容的情形下探测对方的办法,采取 保活计时器实现,当计时器被触发时,一端发送保活报文,另一端吸收到报文后发送 ACK 相应它并不是 TCP 的规范,但大部分的实现都供应了这一机制该机制存在争议,有的人保活机制该当在运用程序中实现开启KeepAlive

操作系统中有这么几个参数掌握 KeepAlive 的配置:

Keepalive_time:空闲韶光,即多永劫光连接没有发送数据时开始 KeepAlive 检测Keepalive_intvl:发送间隔韶光,即上述代码的设置Keepalive_probs:最多发送多少个检测数据包

在 Linux 上可以通过如下文件查看

cat /proc/sys/net/ipv4/tcp_keepalive_timecat /proc/sys/net/ipv4/tcp_keepalive_intvlcat /proc/sys/net/ipv4/tcp_keepalive_probes

如果按照这个默认值来看,得2小时没有数据传输,KeepAlive 才开始事情!

而在 Go 中只有两个参数可以设置:

conn.SetKeepAlive(true)conn.SetKeepAlivePeriod(5 time.Second)

个中第二个 SetKeepAlivePeriod 源码是这样的:

func setKeepAlivePeriod(fd netFD, d time.Duration) error { // The kernel expects seconds so round to next highest second. secs := int(roundDurationUp(d, time.Second)) if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err != nil { return wrapSyscallError("setsockopt", err) } err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs) runtime.KeepAlive(fd) return wrapSyscallError("setsockopt", err)}

SetKeepAlivePeriod 的参数同时设置了 tcp_keepalive_intvl 和 tcp_keepalive_time,tcp_keepalive_probes 没法设置

做个大略测试:client 开启 KeepAlive 连接 server 后,什么数据都不发送,把server 的网断掉,可以看到 KeepAlive 心跳包,一段韶光后连接被置为 CLOSED 状态

关闭KeepAlive

关闭 KeepAlive 后,如果没有数据传输,连接永久不会断开

断电/断网后 server 重启再规复

再思考一个场景,如果 client 与 server 建立连接后,没有数据传输,断掉 server 真个网络,这时如果把 server 程序重启一下,再规复网络,那这条连接还能用吗?

如果 server 重启后,client 还是不发数据,那这条连接看起来还是可用的,由于他们根本不知道对方是个什么情形,但如果此时 client 发送一点数据给 server,你会创造 server 会发送一个 RST 给client,然后 client 就断开连接了

总结

除了正常情形之外,本文从 TCP 连接断开的角度结合实验给出了一些结论:

TCP 连接断开的挥手,在进程崩溃时,会由操作系统内核代劳当 TCP 连接建立后,如果某一方断电或断网,如果此时刚好正在发送数据,TCP 数据包发送失落败后会重试,重试达到上限时也会断开连接当 TCP 连接建立后,如果某一方断电或断网,且这条连接没有数据传输时 如果开启了 KeepAlive 则会在一定心跳检测后断开连接,这个默认检测韶光大概2个多小时,比较久如果未开启 KeepAlive 则连接永久存在如果一方发送 RST 包给另一方,也是会逼迫对方断开连接的

搜索关注"捉虫大师",后端技能分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。

相关文章

Go语言,高效、安全、并发编程的未来

随着互联网技术的飞速发展,编程语言的选择成为许多开发者关注的焦点。在众多的编程语言中,Go语言以其高效、安全、并发编程的特点,逐渐...

SEO优化 2024-12-26 阅读0 评论0

Go语言,性能卓越、简洁高效的编程语言

随着信息技术的飞速发展,编程语言层出不穷,而Go语言作为一种新兴的编程语言,凭借其卓越的性能、简洁高效的语法和丰富的库函数,在短短...

SEO优化 2024-12-26 阅读0 评论0

Go语言,引领未来编程新潮流的璀璨明珠

随着信息技术的飞速发展,编程语言也在不断更新迭代。在众多编程语言中,Go语言凭借其简洁、高效、并发等优势,逐渐成为开发者们的新宠。...

SEO优化 2024-12-26 阅读0 评论0

银行保险IT,新时代金融创新的引擎

随着科技的飞速发展,信息技术在金融行业的应用日益广泛。其中,银行保险IT作为金融科技创新的重要驱动力,正引领着金融行业迈向一个新的...

SEO优化 2024-12-26 阅读0 评论0

长治拓达IT,科技引领未来,创新驱动发展

随着科技的飞速发展,信息技术产业已成为推动经济社会发展的关键力量。在我国,长治拓达IT公司作为一家专注于信息技术服务的领军企业,凭...

SEO优化 2024-12-26 阅读0 评论0