我是靠谱客的博主 无心香烟,最近开发中收集的这篇文章主要介绍TCP自连接,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. 什么是自连接(self-connection)?

在发起连接时,TCP/IP的协议栈会先选择source IP和source port,在没有显示调用bind()的情况下,source IP由路由表确定,source port由TCP/IP协议栈从local port range中选取尚未使用的port。如果destination IP正好是本机,而destination port位于local port range,且没有服务器监听(listen)的话,source port可能正好选中了destination port,这就出现了**(source IP,source port)=(destination IP,destination port)**的情况,即发生了自连接。

2. 现象分析:

destination IP为本机比较好理解,例如服务器程序和客户端程序位于同一台电脑上。但为什么会出现source port = destination port的现象呢?
考虑tcp正常建立连接过程,首先svr要在b端口上listen,cli再使用a端口connect,客户端一般不显式bind,而由内核代为选取一个空闲端口号,那么,因为svr已将b端口占用,cli不管是用户bind还是内核选择,都不可能选到b(不妨试试,在svr已bind时,cli再使用这个端口是会报错的),这样看来,同一个端口自连接就是一个伪命题。
那如果svr没有绑定呢?考虑下面两种情况:

  1. 同时打开:svr和cli同时发送SYN,又分别回答ACK+SYN,双方收到对方的ACK后,两个TCP连接均正常建立。如图:
    在这里插入图片描述
    (注意,同时打开是TCP协议中明确表明的正确行为,即使它没有listen监听,而是双方都使用主动发送SYN来建立连接。)

在同时打开的情况下,就有可能出现source port = destination port的情况。例如:程序(svr或cli)向destport发送一个SYN,因为目的 IP是自己,因此会被loopback网络接口处理程序回送给本机TCP/IP协议栈,又因为port是自己,于是这个SYN送给了正在等SYN的自己,之后发送SYN+ACK,同样原理,这个报文又会会送给自己,于是连接建立。

  1. 本来正常运行的cli和svr,svr偶然挂掉之后,cli再去连接它,就有可能出现自连接现象。

同一台机器上的cli和svr建立了一个长连接,svr挂掉了,端口释放,cli去connect这个目的端口的时候正好选择了这个端口作为源端口,此时该端口没人用,使用是合法的,于是自连接形成了。
为什么svr程序崩溃后应用没有主动关闭连接呢?根据TCP协议,一个空闲的TCP连接,除非主动断开连接,否则连接一直维持。即使中间路由器崩溃,连接也存在,甚至对端主机崩溃,另一端也是不知道的,连接依然存在。(Linux的TCP实现默认不开启保活功能)

3. 自连接的解决办法:

首先要了解本机local port range的范围,在系统文件/etc/sysctl.conf的net.ip_local_port_range参数规定了该范围。我们只需要限定服务监听端口在该范围以外,就不会出现自连接现象了。

参考:
详解tcp端口自连接,成因及后果-腾讯游戏学院https://gameinstitute.qq.com/community/detail/112599

最后

以上就是无心香烟为你收集整理的TCP自连接的全部内容,希望文章能够帮你解决TCP自连接所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部