Linux下如何断开TCP连接? (linux断开tcp连接)

在Linux系统中,TCP连接是一种非常重要的网络通信方式。一般情况下,TCP连接能够稳定地保持通信,但是有时候需要手动断开TCP连接。本文将介绍在Linux系统中如何断开TCP连接。

断开TCP连接的方法有很多种,以下是一些常用的方法:

1. 使用kill命令终止进程

如果TCP连接是由一个进程建立的,那么可以使用kill命令终止该进程,进而断开TCP连接。需要查找建立TCP连接的进程ID。可以使用如下命令查找:

“`

netstat -a | grep :

“`

其中,和是远程主机的IP地址和端口号。该命令的输出结果包含了建立该TCP连接的进程ID。然后,可以使用kill命令以该进程ID终止该进程,来断开TCP连接:

“`

kill

“`

其中,是建立TCP连接的进程ID。

2. 使用iptables

如果TCP连接无法通过终止进程来断开,可以使用iptables命令实现。iptables是Linux系统中用来管理网络流量和安全性的命令。可以使用iptables命令添加一条规则,来强制断开TCP连接。具体步骤如下:

(1)查找建立TCP连接的进程ID和端口号,使用如下命令:

“`

netstat -apt | grep :

“`

其中,和是远程主机的IP地址和端口号。该命令的输出结果包含了建立该TCP连接的进程ID和端口号。

(2)使用iptables命令添加规则,强制断开TCP连接。具体命令如下:

“`

iptables -A OUTPUT -p tcp –sport –tcp-flags RST RST -j DROP

“`

其中,是建立TCP连接的本地端口号。该命令的作用就是将发送的TCP数据包重置为RST并丢弃。

3. 使用tcpkill命令

tcpkill命令是一种用来终止TCP连接的命令。该命令是tcpdump命令的扩展功能,可以指定要终止的TCP连接。具体命令如下:

“`

tcpkill host

“`

其中,是远程主机的IP地址。该命令的作用就是终止所有与该远程主机建立的TCP连接。

4. 使用ss命令

如果不能确定建立TCP连接的进程ID和端口号,可以使用ss命令来列出当前所有的TCP连接。具体命令如下:

“`

ss -t -a

“`

该命令的输出结果列出了所有的TCP连接。然后,可以使用如下命令断开指定的TCP连接:

“`

ss -K dst dport

“`

其中,和是要断开的远程主机的IP地址和端口号。该命令的作用是断开与该远程主机建立的TCP连接。

相关问题拓展阅读:

【TCP】 tcp四次挥手状态 TIME_WAIT

首先,我们需要明确, 只有主动断开的那一方才会进入 TIME_WAIT 状态 ,且会在那个状态持续 2 个 MSL(Max Segment Lifetime)。

为了讲清楚 TIME_WAIT,需要先介绍一下 MSL 的概念。

MSL(报文更大生存时间)是 TCP 报文在网络中的更大生存时间。这个值与 IP 报文头的 TTL 字段有密切的关系。

IP 报文头中有一个 8 位的存活时间字段(Time to live, TTL)如下图。 这个存活时间存储的不是具体的时间,而是一个 IP 报文更大可经过的路由数,每经过一个路由器,TTL 减 1,当 TTL 减到 0 时这个 IP 报文会被丢弃。

TTL 经过路由器不断减小的过程如下图所示,假设初始的 TTL 为 12,经过下一个路由器 R1 以后 TTL 变为 11,后面每经过一个路由器以后 TTL 减 1

从上面可以看到 TTL 说的是「跳数」限制而不是「时间」限制,尽管如此我们依然假设 更大跳数的报文在网络中存活的时间不可能超过 MSL 秒 。

Linux 的套接字实现假设 MSL 为 30 秒,因此在 Linux 机器上 TIME_WAIT 状态将持续 60秒。

要构造一个 TIME_WAIT 非常简单,只需要建立一个 TCP 连接,然后断开某一方连接,主动断开的那一方就会进入 TIME_WAIT 状态,我们用 Linux 上开箱即用的 nc 命令来构造一个。

过程如下图:

在机器 c2 上用nc -l 8888启动一个 TCP 服务器

在机器 c1 上用 nc c创建一条 TCP 连接

在机器 c1 上用 Ctrl+C 停止 nc 命令,随后在用netstat -atnp | grep 8888查看连接状态。

之一个原因是:数据报文可能在发送途中延迟但最终会到达,册搭因此要等老的“迷路”的重复报文段在网络中过期失效,这样可以避免用相同源端口和目标端口创建新连接时收到旧连接姗姗来迟的数据包,造成数据错乱。

比如下面的例子

假设客户端 10.211.55.2 的端口与服务端 10.211.55.10 的 8080 端口一开始建立了一个 TCP 连接。

假如客户端发送完 FIN 包以后不等待直接进入 CLOSED 状态,老连接 SEQ=3 的包因为网络的延迟。过了一段时间 相同缺姿辩 的 IP 和端口号又新建了另一条连接,这样 TCP 连接的四元组就完全一样了。

恰好 SEQ 因为回绕等原因 也正好相同,那么 SEQ=3 的包就无法知道到底是旧连伏缺接的包还是新连接的包了,造成新连接数据的混乱。

TIME_WAIT 等待时间是 2 个 MSL,已经足够让一个方向上的包最多存活 MSL 秒就被丢弃,保证了在创建新的 TCP 连接以后,老连接姗姗来迟的包已经在网络中被丢弃消逝,不会干扰新的连接。

第二个原因是确保可靠实现 TCP 全双工终止连接。

关闭连接的四次挥手中,最终的 ACK 由主动关闭方发出,如果这个 ACK 丢失,对端(被动关闭方)将重发 FIN,如果主动关闭方不维持 TIME_WAIT 直接进入 CLOSED 状态,则无法重传 ACK,被动关闭方因此不能及时可靠释放。

如果四次挥手的第 4 步中客户端发送了给服务端的确认 ACK 报文以后不进入 TIME_WAIT 状态,直接进入 CLOSED状态,然后重用端口建立新连接会发生什么呢?

如下图所示

主动关闭方如果马上进入 CLOSED 状态,被动关闭方这个时候还处于LAST-ACK状态,主动关闭方认为连接已经释放,端口可以重用了, 如果使用相同的端口三次握手发送 SYN 包,会被处于 LAST-ACK状态状态的被动关闭方返回一个 RST,三次握手失败。

为什么时间是两个 MSL?

1 个 MSL 确保四次挥手中主动关闭方最后的 ACK 报文最终能达到对端

1 个 MSL 确保对端没有收到 ACK 重传的 FIN 报文可以到达

2MS = 去向 ACK 消息更大存活时间(MSL) + 来向 FIN 消息的更大存活时间(MSL)

在一个非常繁忙的服务器上,如果有大量 TIME_WAIT 状态的连接会怎么样呢?

连接表无法复用

socket 结构体内存占用

连接表无法复用  因为处于 TIME_WAIT 的连接会存活 2MSL(60s),意味着相同的TCP 连接四元组(源端口、源 ip、目标端口、目标 ip)在一分钟之内都没有办法复用,通俗一点来讲就是“占着茅坑不拉屎”。

假设主动断开的一方是客户端,对于 web 服务器而言,目标地址、目标端口都是固定值(比如本机 ip + 80 端口),客户端的 IP 也是固定的,那么能变化的就只有端口了,在一台 Linux 机器上,端口最多是个( 2 个字节)。

如果客户端与服务器通信全部使用短连接,不停的创建连接,接着关闭连接,客户端机器会造成大量的 TCP 连接进入 TIME_WAIT 状态。

可以来写一个简单的 shell 脚本来测试一下,使用 nc 命令连接 redis 发送 ping 命令以后断开连接。

如果在 60s 内有超过次 redis 短连接操作,就会出现端口不够用的情况,这也是使用 连接池 的一个重要原因。

针对 TIME_WAIT 持续时间过长的问题,Linux 新增了几个相关的选项,net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_tw_recycle。

下面我们来说明一下这两个参数的用意。 这两个参数都依赖于 TCP 头部的扩展选项:timestamp

TCP 头部时间戳选项(TCP Timestamps Option,TSopt)

除了我们之前介绍的 MSS、Window Scale 还有以一个非常重要的选项:时间戳(TCP Timestamps Option,TSopt)

它由四部分构成:类别(kind)、长度(Length)、发送方时间戳(TS value)、回显时间戳(TS Echo Reply)。

时间戳选项类别(kind)的值等于 8,用来与其它类型的选项区分。长度(length)等于 10。两个时间戳相关的选项都是 4 字节。

如下图所示:

是否使用时间戳选项是在三次握手里面的 SYN 报文里面确定的。

下面的包是 curl github.com 抓包得到的结果:

发送方发送数据时,将一个发送时间戳放在发送方时间戳 TSval 中

接收方收到数据包以后,将收到的时间戳原封不动的返回给发送方,放在 TSecr 字段中,同时把自己的时间戳放在 TSval 中

后面的包以此类推

有几个需要说明的点:

1. 时间戳是一个单调递增的值,与我们所知的 epoch 时间戳不是一回事。 这个选项不要求两台主机进行时钟同步

2. timestamps 是一个双向的选项,如果只要有一方不开启,双方都将停用 timestamps。

比如下面是curl

www.baidu.com

得到的包

可以看到客户端发起 SYN 包时带上了自己的TSval,服务器回复的SYN+ACK 包没有TSval和TSecr,从此之后的包都没有带上时间戳选项了。

有了这个选项,我们来看一下 tcp_tw_reuse 选项。

缓解紧张的端口资源,一个可行的方法是重用“浪费”的处于 TIME_WAIT 状态的连接,当开启 net.ipv4.tcp_tw_reuse 选项时,处于 TIME_WAIT 状态的连接可以被重用。

下面把主动关闭方记为 A, 被动关闭方记为 B,它的原理是:

如果主动关闭方 A 收到的包时间戳比当前存储的时间戳小,说明是一个迷路的旧连接的包,直接丢弃掉

如果因为 ACK 包丢失导致被动关闭方还处于LAST-ACK状态,并且会持续重传 FIN+ACK。这时 A 发送SYN 包想三次握手建立连接,此时 A 处于SYN-SENT阶段。 当收到 B 的 FIN 包时会回以一个 RST 包给 B,B 这端的连接会进入 CLOSED 状态,A 因为没有收到 SYN 包的 ACK,会重传 SYN,后面就一切顺利了。

tcp_tw_recyle 是一个比 tcp_tw_reuse 更激进的方案, 系统会缓存每台主机(即 IP)连接过来的最新的时间戳。

对于新来的连接,如果发现 SYN 包中带的时间戳与之前记录的来自同一主机的同一连接的分组所携带的时间戳相比更旧,则直接丢弃;如果更新则接受复用 TIME-WAIT 连接。

这种机制在客户端与服务端一对一的情况下没有问题,如果经过了 NAT 或者负载均衡,问题就很严重了。

什么是 NAT呢?

NAT(Network Address Translator)的出现是为了缓解 IP 地址耗尽的临时方案,IPv4 的地址是 32 位,全部利用最 多只能提 42.9 亿个地址,去掉保留地址、组播地址等剩下的只有 30 多亿,互联网主机数量呈指数级的增长,如果给每个设备都分配一个唯一的 IP 地址,那根本不够。于是 1994 年推出的 NAT 规范,NAT 设备负责维护局域网私有 IP 地址和端口到外网 IP 和端口的映射规则。

它有两个明显的优点:

出口 IP 共享:通过一个公网地址可以让许多机器连上网络,解决 IP 地址不够用的问题

安全隐私防护:实际的机器可以隐藏自己真实的 IP 地址 当然也有明显的弊端:NAT 会对包进行修改,有些协议无法通过 NAT。

当 tcp_tw_recycle 遇上 NAT 时,因为客户端出口 IP 都一样,会导致服务端看起来都在跟同一个 host 打交道。

不同客户端携带的 timestamp 只跟自己相关,如果一个时间戳较大的客户端 A 通过 NAT 与服务器建连,时间戳较小的客户端 B 通过 NAT 发送的包服务器认为是过期重复的数据,直接丢弃,导致 B 无法正常建连和发数据。

TIME_WAIT 状态是最容易造成混淆的一个概念,这个状态存在的意义是:

1. 可靠的实现 TCP 全双工的连接终止(处理最后 ACK 丢失的情况)

2. 避免当前关闭连接与后续连接混淆(让旧连接的包在网络中消逝)

假设 MSL 是 60s,请问系统能够初始化一个新连接然后主动关闭的更大速率是多少(忽略1~1024区间的端口)?

2MSL = 120s,() / 120 = 537.6 次/秒

每120秒可以初始化()个

“时间戳是一个单调递增的值,与我们所知的 epoch 时间戳不是一回事” 这个epoch和时间戳分别是什么差异?

不是一回事,跟时间没有什么关系,只是随着时钟信号CPU中断递增。

SO_REUSEADDR是针对服务端的,tcp_tw_reuse和tcp_tw_recyle是针对客户端的,可以这样理解吗?

SO_REUSEADDR 两端都可以用,不过服务端上因为经常要固定端口,不设置,下次重启就bind 失败 。

tcp_tw_reuse和tcp_tw_recyle 也是主要用于繁忙的“服务端”,“客户端”和“服务端”这个说法是在不同的场景下可以互相转换的,服务端也可以发起请求充当客户端 。

深入理解 TCP 协议:从原理到实战

从SO_REUSEADDR选项说起

linux下tcp通信怎么限制客户端的连接数量

listen(int fd, int backlog); 设置第二个参数就行。

listen的backlog参数指定的是已经三次握手完成,达到了established状态但是等待accept的队列的容量。当迟举这个容量超过上限的时候服务器端便不处理客户端的三次握手了。这个队列的容量当然乎旦数不是楼主所说的并发连接数。

但是lisen的再后一道程序便是accept了。如果你想要的是在tcp并发连接数量超过上限的时候服务器不再处理了三次握手那么只有两种办法:

1.关闭listen的socket

2.自己修改tcp协议栈的实现,当然这个就比较麻烦了。

用iptables防火墙来限制tcp连接岁首,

如下,限制用户的tcp连接数为50

iptables -I INPUT-p tcp -m connlimit –connlimit-above 50 -j REJECT

iptables防悔没哪火碧码墙察滑

iptables -I INPUT-p tcp -m connlimit –connlimit-above 50 -j REJECT

linux断开tcp连接的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux断开tcp连接,Linux下如何断开TCP连接?,【TCP】 tcp四次挥手状态 TIME_WAIT,linux下tcp通信怎么限制客户端的连接数量的信息别忘了在本站进行查找喔。


数据运维技术 » Linux下如何断开TCP连接? (linux断开tcp连接)