TCP 协议如何保证性能

概述
TCP/IP 是网络使用中最基本的通信协议,它规定了互联网中进行通信的标准和方法 。其中它包含TCP、UDP、SMTP、IP 等绝大多数协议,因为 TCP、IP 协议最具代表,因此才命名为 TCP/IP 协议 。本篇博客我就来简单整理 TCP 协议相关知识
TCP
TCP()是一种面向连接的、可靠的、基于字节流的传输层通信协议 。本篇博客我打算分以下几个模块介绍 TCP 协议:
TCP 协议的结构
TCP 的结构如下图所示:
其中数据经过传输层会被封装为这种格式:
简单来说,根据 OSI 7层协议,数据从顶层应用层到底层物理层,每一层都会添加部分标识,最终拼装成实际发送的数据 。接受端接受到数据后,自底向上经过层层解析后,最终将数据输出给对应的上层应用 。关于这块的详细内容后面我们出博客专门介绍,本篇主要聚焦到 TCP 协议内容上 。
下面我们主要看 TCP 各结构模块的实际功能:
三次握手与四次挥手
TCP 规定在客户端和服务端建立连接后进行数据交互,其中建立连接需要经过三次握手:
三次握手建立的连接,一方必须是主动打开,另一方被动打开 。下面我们假设主动打开的一方是客户端,被动打开的一方为服务端:
开始三次握手前,客户端主动结束 CLOSE 状态 。服务端被动打开,结束 CLOSE 状态,进入状态
客户端向服务端发送报文段(SYN = 1,seq = X),随后客户端进入 SYN-SENT 状态
服务端收到客户端的报文后,结束状态并返回报文段(SYN = 1,ACK = 1,seq = Y,ack = X + 1)发送完毕后进入 SYN-RCVD 状态 。
客户端收到服务端回复的报文后确定从客户端到服务端的传输是正常的,并返回最后一段报文(ACK = 1,seq = X+1,ack = Y+1)发送完毕后,客户端进入状态 。
服务端收到客户端回复的报文后确定双方传输都是正常的,进入状态,至此三次握手全部结束 。
在三次握手的过程中,客户端和服务端数据包中的序号(seq)和确定号(ack)都是在彼此 seq 和 ack 的基础上进行计算的,通过这种方式保证 TCP 报文传输的连续性 。一旦某一方数据包出现丢失,另一方便可以通过序号值发现异常,从而停止握手 。
为什么需要三次握手,两次握手不行吗?
首先给出结论:两次握手肯定不行,因为它可能导致服务端异常
现假定出现异常情况:客户端发送请求建立数据包,该数据包由于网络问题滞留了 。后来超过最大等待时间后,客户端认为之前发送的数据包已丢失,又发送新的建立连接数据包,这次网络畅通,服务端收到后回复确认连接数据包,连接建立 。数据发送完毕后,连接断开 。
假设此时客户端第一次发送的数据包到达服务器,服务器认为客户端需要建立新的连接,因此回复建立连接数据包,并等待客户端发送数据 。而客户端侧数据已发送完成,不会处理服务端的确认连接数据包,而服务端一直等待客户端发送数据,此时就会出现服务端的资源浪费 。
三次握手的核心是让客户端和服务端都知道:双向传输是畅通的 。
开始客户端发送数据包给服务端,并且收到服务端响应后 。对于客户端来说,它可以确定到服务端以及服务端到自己的传输是正常的,但对于服务端来说,它只能确定客户端到自己的传输是正常的,它不能确定自己到客户端的传输是否正常,因为它并不清楚客户端是否收到它回应的数据包 。只有客户端再次回复数据包后,双方才能都确定传输是双向且畅通的 。
数据传输完毕后,客户端和服务端通过四次挥手的方式释放连接:
四次挥手需要一方主动结束连接,下面我们假设主动结束的一方为客户端,被动结束的一方为服务端: