我正在参加「掘金·启航计划」
TCP协议基本认识
什么是TCP?
TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。
- 面向连接:一定是「一对一」才能连接,不能像 UDP 协议 可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的;
- 可靠的:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
- 字节流:消息是「没有边界」的,所以无论我们消息有多大都可以进行传输。并且消息是「有序的」,当「前一个」消息没有收到的时候,即使它先收到了后面的字节已经收到,那么也不能扔给应用层去处理,同时对「重复」的报文会自动丢弃。
TCP 是一个工作在传输层的可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。
TCP报文头部格式
序列号:在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。
确认应答号:指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决不丢包的问题。
控制位:
- ACK:该位为
1时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的SYN包之外该位必须设置为1。
- RST:该位为
1时,表示 TCP 连接中出现异常必须强制断开连接。
- SYC:该位为
1时,表示希望建立连,并在其「序列号」的字段进行序列号初始值的设定。
- FIN:该位为
1时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换FIN位置为 1 的 TCP 段。
TCP如何建立连接?
什么是TCP连接
简单来说就是,用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括Socket、序列号和窗口大小称为连接。
- Socket:由 IP 地址和端口号组成
- 序列号:用来解决乱序问题等
- 窗口大小:用来做流量控制
如何唯一确定一个 TCP 连接呢?
- 源地址
- 源端口
- 目的地址
- 目的端口
建立连接
TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手而进行的。
- 三次握手的第一个报文:
无法复制加载中的内容
- 客户端会随机初始化序号(
client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把SYN标志位置为1,表示SYN报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接
- 三次握手的第二个报文:
无法复制加载中的内容
- 服务端收到客户端的
SYN报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入client_isn + 1, 接着把SYN和ACK标志位置为1。
- 三次握手的第三个报文:
无法复制加载中的内容
- 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部
ACK标志位置为1,其次「确认应答号」字段填入server_isn + 1,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于ESTABLISHED状态。
断开连接
TCP 断开连接是通过四次挥手方式,双方都可以主动断开连接,断开连接后主机的资源将被释放。
- 客户端打算关闭连接,此时会发送一个 TCP 首部
FIN标志位被置为1的报文,也即FIN报文,之后客户端进入FIN_WAIT_1状态。
- 服务端收到该报文后,就向客户端发送
ACK应答报文,接着服务端进入CLOSED_WAIT状态。
- 客户端收到服务端的
ACK应答报文后,之后进入FIN_WAIT_2状态。
- 等待服务端处理完数据后,也向客户端发送
FIN报文,之后服务端进入LAST_ACK状态。
- 客户端收到服务端的
FIN报文后,回一个ACK应答报文,之后进入TIME_WAIT状态
- 服务器收到了
ACK应答报文后,就进入了CLOSE状态,至此服务端已经完成连接的关闭。
- 客户端在经过
2MSL一段时间后,自动进入CLOSE状态,至此客户端也完成连接的关闭。
\