TCP
- TCP相关知识
- HTTP请求全过程
三次握手与四次挥手
tcp3次握手
SYN=1 & 设置序列号初始值
ACK: 序列号+1
通过 序号(发送序号) 和 ACK号(返回ack号) 可以确认接收方是否收到网络包
第1次发送: client --> server (client序列号初始值
)
- SYN=1: 表示进行连接
- Seq:客户端序列号的初始值(该值是随机的,目的是防止恶意攻击)
第2次发送: server --> client (ACK号
+ server序列号初始值
)
- SYN=1: 表示进行连接
- ACK(应答) + 服务器序号初始值(之所以分服务器和客户端初始值,因为是 双工模式)
第3次发送: client --> server (ACK号
)
- ACK (序列号+1)
TCP的4次挥手
3次握手,为什么客户端最后还要发送一次确认
简言之:
主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
通俗讲就是: 客户端第一次的连接请求因为网络延时没有发送到服务器,然后又发送了第二次连接请求,当第二次的请求过程整个过程都结束后,第一次的连接请求到达了服务器。如果是2次握手,则会导致错误
如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
为什么客户端最后还要等待2MSL
简言之:
- 如果网络延时导致client发出的最后ACK没有到达server,则服务器会重发,2MSL可以保证client可以接收到server重发的报文。
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
为什么建立连接是三次握手,关闭连接确是四次挥手呢?
简言之:
建立连接时: 服务器是将ACK+SYN一起发送客户端;
关闭连接时: 服务器将ACK和SYN分开发送到客户端,一次多了一次。
之所以分开发,是因为客户端请求关闭时,服务器的数据可能没有发送完,服务器可以先应答在关闭
建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次
TCP的滑动窗口机制与流控介绍
[通俗易懂]深入理解TCP协议(下):RTT、滑动窗口、拥塞处理
滑动窗口: 发送一个包之后,不等待ACK号返回,而是直接发送后续的一系列包。这样一来,等待ACK号的这段时间就被有效利用了。
问题:如果不等待ACK号返回就连续发包,如何处理发送频率 大于 处理能力
?
滑动窗口基本思路: 接收方需要告诉发送方自己最多能接收多少数据(
窗口大小
),然后发送方根据这个值对数据发送进行控制。
- TCP接收到包后,会将包放入
缓冲区
; - 接收方: 从缓存区取数据后,会将缓冲区可用大小发送给发送方;
- 合并多个ACK号: 只需要发送
最后一个ACK号
即可(表示目前已接收数据的最后位置)