首页
登录 | 注册

TCP深入详解

TCP三次握手、四次挥手时序图:

TCP深入详解

#TCP协议状态机
TCP深入详解


1.TCP建立连接时的初始化序列号X、Y可以是写死固定的吗?
     如果初始化序列号(缩写为ISN:Inital Sequence Number)可以固定,我们来看看会出现什么问题。假设ISN固定是1,Client和Server建立好一条TCP连接后,Client连续给Server发了10个包,这10个包不知怎么被链路上的路由器缓存了(路由器会毫无先兆地缓存或者丢弃任何的数据包),这个时候碰巧Client挂掉了,然后Client用同样的端口号重新连上Server,Client又连续给Server发了几个包,假设这个时候Client的序列号变成了5。接着,之前被路由器缓存的10个数据包全部被路由到Server端了,Server给Client回复确认号10,这个时候,Client整个都不好了,这是什么情况?我的序列号才到5,你怎么给我的确认号是10了,整个都乱了。所以现在的方法是在一个基准值得上产生一个随机值。
 
 
2.假如Client发送一个SYN包给Server后就挂了或是不管了,这个时候这个连接处于什么状态呢?会超时吗?为什么呢?

  Client发送SYN包给Server后挂了,Server回给Client的SYN-ACK一直没收到Client的ACK确认,这个时候这个连接既没建立起来,也不能算失败。这就需要一个超时时间让Server将这个连接断开,否则这个连接就会一直占用Server的SYN连接队列中的一个位置,大量这样的连接就会将Server的SYN连接队列耗尽,让正常的连接无法得到处理。目前,Linux下默认会进行5次重发SYN-ACK包,重试的间隔时间从1s开始,下次的重试间隔时间是前一次的双倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s,TCP才会把断开这个连接。由于,SYN超时需要63秒,那么就给攻击者一个攻击服务器的机会,攻击者在短时间内发送大量的SYN包给Server(俗称 SYN flood 攻击),用于耗尽Server的SYN队列。对于应对SYN 过多的问题,linux提供了几个TCP参数:tcp_syncookies、tcp_synack_retries、tcp_max_syn_backlog、tcp_abort_on_overflow 来调整应对。

3.Client和Server同时发起断开连接的FIN包会怎么样呢,TCP状态是怎么转移的?

TCP的Peer两端同时发起FIN包进行断开连接,那么两端Peer可能出现完全一样的状态转移 FIN_WAIT1——>CLOSEING——->TIME_WAIT,也就会Client和Server最后同时进入TIME_WAIT状态。

TCP深入详解


4.上图中的四次挥手过程中,Server端的ACK确认包能不能和接下来的FIN包合并成一个包呢,这样四次挥手就变成三次挥手了?

答案是可能的。

TCP是全双工通信,Cliet在自己已经不会在有新的数据要发送给Server后,可以发送FIN信号告知Server,这边已经终止Client到对端Server那边的数据传输。但是,这个时候对端Server可以继续往Client这边发送数据包。于是,两端数据传输的终止在时序上是独立并且可能会相隔比较长的时间,这个时候就必须最少需要2+2 = 4 次挥手来完全终止这个连接。但是,如果Server在收到Client的FIN包后,在也没数据需要发送给Client了,那么对Client的ACK包和Server自己的FIN包就可以合并成为一个包发送过去,这样四次挥手就可以变成三次了(似乎linux协议栈就是这样实现的)。

5.四次挥手过程中,首先断开连接的一端,在回复最后一个ACK后,为什么要进行TIME_WAIT呢(超时设置是 2*MSL,RFC793定义了MSL为2分钟,Linux设置成了30s),在TIME_WAIT的时候又不能释放资源,白白让资源占用那么长时间,能不能省了TIME_WAIT呢,为什么?

1)据TCP协议规范,不对ACK进行ACK,如果主动关闭方不进入TIME_WAIT,那么主动关闭方在发送完ACK就走了的话,如果最后发送的ACK在路由过程中丢掉了,最后没能到被动关闭方,这个时候被动关闭方没收到自己FIN的ACK就不能关闭连接,接着被动关闭方会超时重发FIN包,但是这个时候已经没有对端会给该FIN回ACK,被动关闭方就无法正常关闭连接了,所以主动关闭方需要进入TIME_WAIT以便能够重发丢掉的被动关闭方FIN的ACK。

2)防止链路上已经关闭的连接的残余数据包(a lost duplicate packet or a wandering duplicate packet) 干扰正常的数据包,造成数据流的不正常。这个问题和2)类似。

6.TIME_WAIT会带来哪些问题呢?

TIME_WAIT带来的问题注意是源于:一个连接进入TIME_WAIT状态后需要等待2*MSL(一般是1到4分钟)那么长的时间才能断开连接释放连接占用的资源,会造成以下问题.


1) 作为服务器,短时间内关闭了大量的Client连接,就会造成服务器上出现大量的TIME_WAIT连接,占据大量的tuple,严重消耗着服务器的资源。


2) 作为客户端,短时间内大量的短连接,会大量消耗的Client机器的端口,毕竟端口只有65535个,端口被耗尽了,后续就无法在发起新的连接了。
(由于上面两个问题,作为客户端需要连本机的一个服务的时候,首选UNIX域套接字而不是TCP)


TIME_WAIT很令人头疼,很多问题是由TIME_WAIT造成的,但是TIME_WAIT又不是多余的不能简单将TIME_WAIT去掉,那么怎么来解决或缓解TIME_WAIT问题呢?可以进行TIME_WAIT的快速回收和重用来缓解TIME_WAIT的问题。有没一些清掉TIME_WAIT的技巧呢?

【1】TIME_WAIT快速回收

同时打开tcp_tw_recycle和tcp_timestamps(默认打开)两选项

【2】TIME_WAIT重用

要同时开启tcp_tw_reuse选项和tcp_timestamps 选项才可以开启TIME_WAIT重用


相关文章

  • 详解linux进程间通信-消息队列
    前言:前面讨论了信号.管道的进程间通信方式,接下来将讨论消息队列. 一.系统V IPC 三种系统V IPC:消息队列.信号量以及共享内存(共享存储器)之间有很多相似之处. 每个内核中的 I P C结构(消息队列.信号量或共享存储段)都用一个 ...
  • 详解linux进程间通信-管道 popen函数 dup2函数
    前言:进程之间交换信息的唯一方法是经由f o r k或e x e c传送打开文件,或通过文件系统.本章将说明进程之间相互通信的其他技术—I P C(InterProcess Communication).今天将介绍半双工的管道. 一.匿名管 ...
  • python接口自动化(二十三)--unittest断言——上(详解)
    简介 在测试用例中,执行完测试用例后,最后一步是判断测试结果是 pass 还是 fail,自动化测试脚本里面一般把这种生成测试结果的方法称为断言(assert).用 unittest 组件测试用例的时候,断言的方法还是很多的,下面介绍几种常 ...
  • python接口自动化(二十一)--unittest简介(详解)
    简介 前边的随笔主要介绍的requests模块的有关知识个内容,接下来看一下python的单元测试框架unittest.熟悉 或者了解java 的小伙伴应该都清楚常见的单元测试框架 Junit 和 TestNG,这个招聘的需求上也是经常见到 ...
  • 补习系列(20)-大话 WebSocket 与 "尬聊"的实现
    目录 一.聊聊 WebSocket 二.Stomp 是个什么鬼 三.SpringBoot 整合 WebSocket A. 引入依赖 B. WebSocket 配置 C. 控制器 D. 前端实现 四.参考文档 一.聊聊 WebSocket 从 ...
  • 从 docker 到 runC
    笔者在前文<RunC 简介>和<Containerd 简介>中分别介绍了 runC 和 containerd.本文我们将结合 docker 中的其它组件探索 docker 是如何把这些组件组织起来协调工作的. Doc ...

2020 cecdns.com webmaster#cecdns.com
12 q. 0.071 s.
京ICP备10005923号