Skip to content

TCP 面向字节流,所以应用程序直接给过去的一段内容可能会被拆分为多个字节流,或者合并

TCP 只支持 1 对 1 模型,单播。UDP 支持单播,多播,广播。

TCP 头部至少是 20 字节,至多 60 字节。UDP 则固定为 8 字节

HTTP/3.0 之前是基于 TCP 协议的,而 HTTP/3.0 将弃用 TCP,改用基于 UDP 的 QUIC 协议(目前 3.0 就是最新的,它和 html5 是两个东西)

注:FTP 是和 HTTP 一样,也有对应的 SFTP、FTPS

三次握手

1、

首先,服务器是一直跑的,客户端选择一个时机访问服务器。并且只能是客户端访问先访问服务器

所以,第一次是客户端 -> 服务器 : SYN 报文

Synchronize Sequence Numbers :同步序列号

其中包含一个随机的初始序列号 Initial Sequence Number, ISN

这里一般写为 seq=x

然后 客户端发送好了,就可以等着了,其进入** SYN_SEND**

2、

服务器收到以后,同意建立连接

其发送一个确认报文,包含 SYN+ACK

其中:

SYN 和第一次一样,是服务器自己的同步序列号,写为 seq=y

ACK 用于告诉客户端我已经收到了,就给客户端的 x+1,即 ack=x+1

发送后,服务器可以等着,进入** SYN_RECV**

3、

客户端收到以后

发送一个 ack=y+1,确认一下,然后客户端进入 ESTABLISHED

服务器收到以后,也进入 ESTABLISHED

这三次发送,是要确定双方,都既可以接收,又可以发送

是双方要站在自己的视角确认这个事情,你自己确认后,对方其实不知道

  • 第一次握手 (客户端 → 服务器) :客户端发送 SYN 包。

    • 客户端:自己能发。
    • 服务器:客户能发,自己能收。

    第二次握手 (服务器 → 客户端) :服务器回复 SYN+ACK 包。

    • 客户端:自己能收能发,服务器能收能发
    • 服务端:客户能发,自己能收+发(这里是关键:为什么需要第三次,因为服务器不知道客户端能不能收到)

    第三次握手 (客户端 → 服务器) :客户端发送 ACK 包。

    • 客户端:客户端在收到服务器回复以后,自己的视角就确定双方是都是好使的,只是服务端视角不知道自己(自己指服务器视角下的客户端)能不能收到
    • 服务端:收到 ACK 以后,确认客户能收即可

第三次握手,不仅能告诉服务器,我能收到,而且还可以拒绝服务器。比如第一次握手发慢了,又不想连接了,可以拒绝

四次挥手

当不想再服务时,任何一方都可以率先提出终止服务,所以是对称的。这里假设是客户端先提出

1、FIN

客户端 -> 服务器 FIN

FIN = finish = 终止,包含 seq=u

客户端进入,FIN-WAIT-1

2、ACK

服务器收到以后,回复可以,但是稍等

ACK ,包含 seq=u+1

服务器进入 CLOSE-WAIT 状态,等待关闭

客户端收到以后,进入 FIN-WAIT-2

此时 TCP 处于半关闭状态,客户端到服务端的发送通道已关闭,但服务端到客户端的发送通道仍然可以传输数据

3、FIN

服务器把所有的数据都发送完以后,说可以彻底关闭了

FIN 包含 seq=y

服务器进入 LAST-ACK,等着最后回复即可

4、ACK

客户端收到 FIN 后,回复 ACK 包含 seq=y+1

客户端进入就 TIME-WAIT

服务器收到以后,进入 CLOSE

客户端等一会,等 2MSL 之后,直接 CLOSE

(关键:为什么要等一会,现在确实已经确定要关机了,但是客户端不确定自己发的 ACK 服务器能不能收到,如果服务器收到,服务器关机,则自己不会收到消息,即确定电话里没有声音了,再关机,否则服务器没收到 ACK,会重复发 FIN)

TCP 提供可靠的数据传输服务,但这并不意味着在连接关闭过程中不会出现报文丢失。可靠传输是通过确认、重传等机制实现的,但在连接关闭阶段,同样需要这些机制来保证关闭的可靠性。

至于开始时也有可能丢包,确实,但是那样就直接无法建立就完了,不是更好吗?

当说 TCP 是"可靠"的,意思是应用层最终能得到完整、有序的数据,而不是说每个报文都不会丢失。

这里关键点就是:

服务器不能直接和客户端说,直接关了吧

他们怕网络延迟,所以怕服务器还再说,但是 A 没收到呢

服务器必须先安慰客户端,然后等自己真说完了,才结束

流量控制

1、TCP 想的很美好,那就是让接收方告诉发送方,我现在的能力是多少,发送方动态调整

(服务器和客户端都可以即作为发送方也可以是接收方,双向嘛)

2、TCP 有确认机制,你收到了,你必须发送”收到“,所以,就把你的现在的能力写在 确认报文中的窗口字段

在发送方的视角里:

1、已经收到对方确认的

2、发送了但是还没有确认

3、我还没发送的

(3 这里他们有的分为两种,一种是在窗口内,一种是窗口外)

窗口内的即将发送,窗口外无法发送

窗口大小有接收者告诉我,然后我把 发送了但是还没有确认 + 窗口内的即将发送,设置为窗口大小

拥塞控制

1、这个是所有主机所有路由器一起做的事情

2、

慢开始 cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍

拥塞避免让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送方的 cwnd 加 1.

快重传 快恢复