参考图片源自小林coding
TCP 连接
什么是TCP?
TCP,全称传输控制协议,Transform Control Protocol
是面向连接的、可靠的、基于字节流的传输层控制协议。
- 面向连接: 一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的
- 可靠:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
- 字节流: 用户消息通过 TCP 协议传输时,消息可能会被操作系统「分组」成多个的 TCP 报文,如果接收方的程序如果不知道「消息的边界」,是无法读出一个有效的用户消息的。并且 TCP 报文是「有序的」,当「前一个」TCP 报文没有收到的时候,即使它先收到了后面的 TCP 报文,那么也不能扔给应用层去处理,同时对「重复」的 TCP 报文会自动丢弃。
TCP的头格式
- 序列号: 在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。
- 确认应答号: 指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题。
- 控制位
- ACK 该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。
- RST 该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
- SYN 该位为 1 时,表示希望建立连接,并在其「序列号」的字段进行序列号初始值的设定
- FIN 该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位为 1 的 TCP 段。
为什么需要TCP协议? 不是已经有了IP协议吗?
TCP 是传输层协议,IP是网络层协议,HTTP是应用层的。
IP层是不可靠的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性。 如果需要保障网络数据包的可靠性,那么就需要由上层(传输层)的 TCP 协议来负责。 因为 TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。
TCP/IP 五层模型以及 OSI七层参考模型
TCP 连接的建立
TCP三次握手
TCP 是面向连接的协议,在使用TCP 传输数据之前必须先建立连接,TCP连接的建立是通过三次握手来进行的。
- 一开始,客户端和服务端都处于
CLOSED状态。先是服务端主动监听某个端口,处于LISTEN状态。 - 然后客户端主动发起连接
SYN,之后处于SYN-SENT状态。 - 服务端收到发起的连接,返回
SYN,并且ACK客户端的SYN,之后处于SYN-RCVD状态。 - 客户端收到服务端发送的
SYN和ACK之后,发送对SYN确认的ACK,之后处于ESTABLISHED状态,因为它一发一收成功了。 - 服务端收到
ACK的ACK之后,处于ESTABLISHED状态,因为它也一发一收了。
为什么要进行三次握手?
- 三次握手,让双方在同步序列号的过程中都执行了发送和接收的操作,保证双方都具有接收和发送信息的能力
更主要、更深入的原因是:为什么三次握手才可以建立TCP连接?
什么是连接? :
在 RFC 793 标准中,连接是这么定义的: 用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket 序列号 和 窗口大小称为连接
在TCP中,建立一个TCP 连接意味着服务端与客户端达成 Socket,序列号,窗口大小的共识。
-
三次握手才能阻止重复历史链接的初始化(主要原因) 三次握手可以防止旧的重复连接初始化造成混乱。
在两次握手的情况下,「被动发起方」没有中间状态给「主动发起方」来阻止历史连接,导致「被动发起方」可能建立一个历史连接,造成资源浪费。
两次握手的情况下,「被动发起方」在收到 SYN 报文后,就进入 ESTABLISHED 状态,意味着这时可以给对方发送数据,但是「主动发起方」此时还没有进入 ESTABLISHED 状态,假设这次是历史连接,「主动发起方」判断到此次连接为历史连接,那么就会回 RST 报文来断开连接,而「被动发起方」在第一次握手的时候就进入 ESTABLISHED 状态,所以它可以发送数据的,但是它并不知道这个是历史连接,它只有在收到 RST 报文后,才会断开连接。
可以看到,上面这种场景下,「被动发起方」在向「主动发起方」发送数据前,并没有阻止掉历史连接,导致「被动发起方」建立了一个历史连接,又白白发送了数据,妥妥地浪费了「被动发起方」的资源。
- 三次握手才可以同步双方的初始序列号
序列号的作用:
- 接收方,去除重复的数据
- 接收方,根据序号按序接收
- 发送方,根据ACK的的序列号,知道已经发送出去的数据包中,哪些已经被对方收到
所以说序列号在TCP连接中有着重要的保证信息传输可靠的功能,为此必须通过TCP的三次握手将两端的序列号同步
-
三次握手避免资源浪费 四次握手的情况下,占用的资源更多;而如果两次握手,不仅有建立历史链接占用资源的风险,而且如果网络卡顿进行多次重传SYN报文,也会占用过多资源,可能造成信道堵塞。
如果握手丢失,会发生什么?
第一次握手丢失
第二次握手丢失
第三次握手丢失
SYN 泛洪攻击
五层因特网协议栈
从客户端发出HTTP请求到服务器接收,中间会经过一系列的流程,五层互联网协议栈就是自顶向下的一个数据传输处理的流程,由上向下的委托工作。
xiaolincoding.com/network/1_b…