文章目录
前言
本文直接将直接开始流程,部分东西不在做解释,
一、 TCP报文信息大概
握手是建立连接,挥手是断开连接
标记位
- SYN : 1 标记时表示希望创建连接
- FIN: 1 标记时表示希望断开连接
- ACK: 1 标记时确认号字段有效
- RST: 1 标记时表示TCP连接出现异常,需要断开。
- 。。。。
序列号: 在初次建⽴连接的时候,客户端和服务端都会为「本次的连接」随机初始 化⼀个序列号。(纵观整个TCP流程中,序列号可以⽤来解决⽹络包乱序的问题)
确认号:该字段表示「接收端」告诉「发送端」对上⼀个数据包已经成功接收(确 认号可以⽤来解决⽹络包丢失的问题
二、TCP三次握手(链接)
TCP三次握⼿的过程其实就是在:确认通信双⽅(客户端和服务端)的序列号
1、第一次
-
最开始的状态,,服务器和客户端都是CLOSE状态
服务器主动监听的端口为 LISTEN状态(监听) -
客户端会随机生成要发出的序列号 (这里的序列号一般叫做client_isn),并且把TCP的标志为设置为SYN,发送到服务端发送完后客户端变为 SYN_SEND 状态
2、第二次
- 服务端接收到客户端的请求之后,服务端也会初始化一个对应的序列号(server_isn)
- 在确认号字段里填上 client_isn+1 (意思是服务端已经收到客户端发到的序列号了)
并把SYN和ACK都点亮 (标记为1) - 然后把这个报文发送到客户端,服务端此时变为SYN-revd状态
3、第三次
-
客户端收到报文之后,就能够确定服务端已经收到了自己的序列号 (确认号里面内容),并且接收到了服务端的序列号server_isn了
-
此时客户端需要告诉服务端自己接收到了服务度发送的序列号,所以需要再 确认号字段上填上
server_isn+1,并把ACK标记为1 -
客户端发送报文之后进入 ESTABLISHED(中译:成立)状态,当服务端接收到客户端的报文之后也进入 ESTABLISHED状态
4、总结和问题
就是双⽅都把⾃身的序列号发给对⽅,看对⽅能不能接收到。如果「确 认可以」,那就可以正常通信。(三次握⼿这个过程就可以看到双⽅都有接收和发送的能 ⼒)
每次交互的数据被称为一个小的TCP分组,里面包含的内容大概就是第一张图(通常是40-60字节),这些由TCP/IP的软件进行管理,是不可见的
问题 1 :两次握手会发送什么情况
两次握⼿只能保证客户端的序列号成功被服务端接收,⽽服务端是⽆法确认⾃⼰的 序列号是否被客户端成功接收。所以是不⾏的(:
问题2 :序列号怎么生成的,为什么是随机的
⼀⽅⾯为了安全性(随机ISN能避免⾮同⼀⽹络的攻击),另⼀⽅⾯可以让通信双⽅ 能够根据序号将「不属于」本连接的报⽂段丢弃
TCP报文头部中的序列号(Sequence Number)是一个32位的字段,用于标识数据流中的每个字节。序列号的生成主要由TCP协议栈在发送端负责,其生成方式如下:
-
初始化序列号:当建立TCP连接时,发送端会随机选择一个初始序列号(ISN),通常是一个较大的随机数。ISN的选择是为了防止攻击者通过猜测序列号来发起恶意攻击,因为ISN的空间非常大,攻击者难以预测下一个序列号的值。
-
序列号递增:每发送一个数据段(Segment)时,TCP发送端会将序列号递增,以确保每个数据段的序列号是唯一的,并且按照字节顺序传输。递增的大小取决于发送的数据量,即序列号会根据发送的字节数动态增加。
-
序列号回绕处理:由于序列号是一个32位的字段,当达到最大值后会发生回绕,此时序列号会重新从0开始计数。TCP协议栈会负责处理序列号的回绕,确保序列号在每个TCP连接中都是唯一且连续的。
总的来说,TCP报文头部中的序列号由TCP协议栈在建立连接时随机初始化,并在发送数据时动态递增,以确保每个数据段的序列号是唯一的且按字节顺序传输。
问题 3 : 如果中途报文丢失怎么办
第一次和第二次中断都会触发重试发送
第三次相关的有三种可能
假设第三个包丢了(ACK包),客户端发送完第三个包后单⽅⾯进⼊了 ESTABLISHED 状态,⽽服务端也认为此时连接是正常的,但第三个包没到达服务端
1.如果此时客户端与服务端都还没数据发送,那服务端会认为⾃⼰发送的 SYN+ACK的包没发送⾄客户端,所以会超时重传⾃⼰的SYN+ACK包
2.如果这时候客户端已经要发送数据了,服务端接收到了ACK + Data数据包,那 ⾃然就切换到 ESTABLISHED 状态下,并且接收客户端的Data数据包
3.如果此时服务端要发送数据了,但发送不了,会⼀直周期性超时重传SYN + ACK,直到接收到客户端的ACK包
三 、四次挥手(链接断开请求)
连接状态下 客户端和服务端都为 ESTABLISHED状态,断开连接双方都可以进行这个操作,
以客户端为主动
1、第一次和第二次
- 客户端发送FIN报文给服务端(其实是吧FIN位置点亮:设置为1),客户端发送完进入FIN_WAIT_1状态
- 服务端收到返回ACK告诉客户端收到FIN报文,服务端发送完进入CLOSE-WAIT(等待关闭),客户端收到进入 FIN_WAIT_2状态
2、第三次和第四次
- 当服务端确认⾃⼰已经没有数据返 回给客户端之后,就发送FIN报⽂给客户端了,⾃⼰进⼊ LAST_ACK 状态。客户端收到服务端的FIN报⽂之后,回应ACK报⽂,⾃⼰进⼊ TIME_WAIT 状态
- 服务端收到客户端的ACK报⽂之后,服务端就进⼊ CLOSE 状态
客户端在TIME_WAIT等到2MSL,也进⼊了 CLOSE 状态
3、问题
为什么是四次
其实很好理解,当客户端第⼀次发送 FIN 报⽂之后,只是代表着客户端不再发送数 据给服务端,但此时客户端还是有接收数据的能⼒的。⽽服务端收到FIN报⽂的时候,可能还 有数据要传输给客户端,所以只能先回复 ACK给客户端
TIME_WAIT累计和端口耗尽 (该问题来自HTTP权威指南一书,第四章 4.2.7)
TIME一WAIT端口耗尽是非常严重的性能问题,会影响到性能基准 但是现实中遇到相对较少,但是一旦遇到这个问题,性能会变的非常差
当某个TCP端点关闭TCP连接时,会在内存中维护一个小的控制块,用来记录最近所关闭连接的IP地址和端口号。这类信息只会维持一小段时间,通常是所估计的最大分段使用期的两倍(称为2MSL,通常为2分钟8)左右,以确保在这段时间内
不会创建具有相同地址和端口号的新连接。
实际上,这个算法可以防止在两分钟内创建、关闭并重新创建两个具有相同IP地址和端口号的连接。现在高速路由器的使用,使得重复分组几乎不可能在连接关闭的几分钟之后,出现在服务器上。有些操作系统会将设置为一个较小的值,但超过此值时要特别小心。分组确实会被复制,如果来自之前连接的复制分组插人了具有相同连接值的新TCP流,会破坏TCP数据。
2MSL的连接关闭延迟通常不是什么问题,但在性能基准环境下就可能会成为一个问题。进行性能基准测试时,通常只有一台或几台用来产生流量的计算机连接到某系统中去,这样就限制了连接到服务器的客户端IP地址数。而且,服务器通常会在
HTTP的默认TCP端口80上进行监听。用TIME-WAIT防止端口号重用时,这些情况也限制了可用的连接值组合。
在只有一个客户端和一台web服务器的异常情况下,构建一条TCP连接的4个值:
<source-IP-address,source-port,destination-IP-addregg,destination-port>
其中的3个都是固定的一一一只有源端口号可以随意改变:
<c1ient-IP,source-port,server-IP,80>
客户端每次连接到服务器上去时,都会获得一个新的源端口,以实现连接的唯一性。但由于可用源端口的数量有限(比如,600个),而且在2MSL秒(比如,120秒)内连接是无法重用的,连接率就被限制在了60000/120=500次/秒。如果再不
断进行优化,并且服务器的连接率不高于5次/秒,就可确保不会遇到TIME—WAIT端口耗尽问题。
要修正这个问题,可以增加客户端负载生成机器的数量,或者确保客户端和服务器在循坏使用几个虚拟IP地址以增加更多的连接组合。即使没有遇到端口耗尽问题,也要特别小心有大量连接处于打开状态的情况,或为处于等待状态的连接分配了大量控制块的情况。在有大量打开连接或控制块的情况下,有些操作系统的速度会严重减缓。
四、FIN 报文和 RST报文
FIN
断开连接的,保证数据传输完成
FIN 报文以告知的方式请求终止 TCP 连接。如果我们把连接比作一次对话,那么 FIN
报文就代表着一个实体在宣布:"我已经把该说的都跟你说了:
“我已经把该说的话都对你说了。现在,我会一直听你说,直到你把该说的话都说完为止”。
从技术角度看,FIN 报文会触发一个称为 FIN握手的过程。
一次FIN的握手过程 包括一对双向握手,第一个握手由第一个发送端的FIN报文发起,第二个由,第一次接收FIN报文的发起。
RST
中止链接,无论有没有数据在传输,打断的意思
触发场景
- 当TCP连接出现异常情况时,例如接收到了意外的数据、连接超时、连接被拒绝等,TCP协议栈会发送RST报文来立即中断连接,以避免进一步的数据交换和资源浪费。
- 在某些情况下,T需要强制终止连接,例如在网络攻击或者异常情况下,为了保护系统和网络安全,TCP协议栈会发送RST报文来立即关闭连接。
- 在一些情况下,TCP协议栈可能需要重置连接状态,例如在TCP三次握手过程中,如果收到了无效的连接请求或者连接请求被拒绝,TCP协议栈会发送RST报文来重置连接状态,以便重新建立连接。
- 一个实体收到来自另一个实体的消息,但第一个实体正忙且无法响应。因此,RST 消息从第一个实体发送到第二个实体
欺骗性 TCP 重置攻击
恶意代理会使用连接实体的寻址信息伪造 RST 数据包。然后,该恶意实体将伪造的RST数据包发送到这些连接的任意端。
接收到伪造数据包的服务器或者客户端就会立即中止连接
这两个就是正常的时候用FIN断开,出错误了使用RST断开。
参考文章
个人笔记,不同意见,望有交流
直接可以点击跳转连接
作者
java 3y