01
概述
TCP协议广泛应用于可靠性要求较高的应用场景,如网页浏览、文件传输、电子邮件等。它提供了可靠的数据传输和流控制机制,能够确保数据的完整性和有序性。然而,由于TCP协议在传输过程中引入了较多的控制信息,因此相比于UDP协议,TCP的传输速度较慢。
和UDP区别
-
是否连接: 可以想象成打电话,比如A给B打电话,只有建立好连接才能通信(交换数据),这种是有连接.而是用微信发消息,不需要建立连接则是无连接
-
是否可靠传输: 这里的可靠,并不是指A给B的数据一定完全能让B收到,只能确保B是不是收到了
-
字节流和数据报: TCP和文件IO一样基于 “流”,UDP则是以"数据报"为基本单位
-
全双工: 一个通道,双向通信
02
TCP协议内容
-
源端口:表示发送方的端口号。
-
目标端口:表示接收方的端口号。
-
4位首部长度: 用于描述TCP报头有多长,这里的单位是4个字节.如果这里是1111->15,表示报头的长度是60
注: TCP的报头长度是可变的,在下面有一个选项(可有可无),可以有一个选项,也可以有多个.
-
TCP报头前面20个字节是固定的,后面的选项是可变的,选项可以是0个字节,最多是40个字节
-
保留位: 协议中预留的一些位,目前没有特定定义或使用规则。以便以后进行扩展或未来使用。
-
校验和:用于检测数据报的完整性
03
TCP应答机制
TCP是可靠的传输协议,确认应答机制是TCP保证可靠性的最核心机制!
在确认应答机制中,发送方在发送数据包后会等待接收方发送确认消息。如果发送方在一定的时间内没有收到确认消息,它会认为数据包丢失或发生错误,并会重新发送数据包。接收方通过发送确认消息来告知发送方数据包已成功接收,或者指示需要重发某个数据包。
-
普通报文: ACK这一位为0
-
应答报文: ACK这一位为1
特殊情况:如果客户端一次性给服务器发多条消息,那么浏览器的应答就会产生歧义
如下图:
在网络上有一种特殊情况,“后发先至”,后发的请求可能先到
因此就会产生上述两种情况.
为了解决上述问题,就可以针对请求和应答报文进行编号!
跟对编号就可以很明确的分出是哪个请求的应答.即使出现"后发先至"的情况也没有问题
而这个编号就对应TCP报文结构中的32位序号和32位确认序号
注: TCP报头只能存一个序号,存的是最后一个字节的序号,是根据报文长度来算的
上述数据的传输过程也不是一帆风顺的,可能会出现丢包,如果丢包,这就需要TCP的超时重传机制了
04
TCP重传机制
超时重传是当发送方发送数据包后,如果在一定的时间内未收到接收方的确认消息(ACK),发送方会认为数据包可能丢失或发生错误,并会重新发送该数据包。
超时重传机制的工作原理如下:
发送方发送数据包后,等待接收方的确认消息。
如果在设定的时间内,发送方未收到接收方的确认消息,就会认为数据包丢失或发生错误。
发送方会重新发送相同的数据包。
接收方收到重复的数据包时,会丢弃重复数据包,并发送之前已接收到的最后一个正确的确认消息。
发送方在收到接收方的确认消息后,继续发送下一个数据包。
超时时间如何确定?
一般操作系统中有一个配置项,描述超时时间的阈值.
如果第一次出现丢包,超出时间阈值后,进行重传.第二次的超时时间阈值就会比第一次更长.
如果重传几次依旧无法传输,就会重置TCP连接,如果还是连不上,就会直接释放连接
超时重传会出现两种情况:
数据报丢了
ack丢了
对于这两种情况发送方都区分不了这两种情况,对于第二种情况,接收方就会收到重复的数据,但可以根据序号进行去重
05
TCP三次握手
三次握手是在TCP协议中建立一个可靠的连接所使用的一种机制。它由发送方和接收方之间进行的三次通信组成,用于确保双方都愿意建立连接,并同步各自的初始序列号。
三次握手类似于打电话
如下图:
三次握手的过程本质上是四次数据的交互.只是中间两条数据可以合并到一起
如下图所示:
三次握手的步骤:
第一次握手(SYN):发送方向接收方发送一个带有SYN标志的数据包(SYN包),请求建立连接。发送方会随机选择一个初始序列号,并将它放在SYN包中的序列号字段中发送给接收方。
第二次握手(SYN+ACK):接收方收到SYN包后,会向发送方发送一个带有SYN和ACK标志的数据包(SYN+ACK包),表示接受建立连接的请求,并回复确认号(ACK)和自己的初始序列号。接收方还会随机选择一个初始序列号,并将它放在SYN+ACK包中的序列号字段中发送给发送方。
第三次握手(ACK):发送方收到SYN+ACK包后,会向接收方发送一个带有ACK标志的数据包(ACK包),确认接收方的确认号,并发送自己的确认号。接收方收到ACK包后,会确认发送方的确认号,并完成连接的建立。
为什么要建立连接以及建立连接的意义:
检查一下当前的网络情况是否畅通
三次握手也是在检查通信双方的发送能力和接收能力是正常的
三次握手过程中,也在协商一些重要的参数
两个重要的TCP状态:
LISTEN:表示服务器正在监听来自客户端的连接请求。服务器在LISTEN状态下,等待客户端发起连接请求。
ESTABLISHED:表示TCP连接已经建立,双方可以进行数据的传输。在ESTABLISHED状态下,双方可以互相发送数据包。
为什么两次不行
1、阻⽌重复历史连接的初始化(主要原因)
当旧的SYN报文先到达服务端,服务端回一个ACK+SYN报文
客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期或超时) ,那么客户端就会发送 RST 报文给服务端,表示中止这一次连接。
两次握手在收到服务端的响应后开始发生数据,不能判断当前连接是否是历史连接。
2、同步双方的初始序列号
TCP 协议的通信双方,都必须维护一个[序列号], 序列号是可靠传输的一个关键因素
接收端可以去除重复数据
接收端可以按照序列号顺序接收
标识发送的数据包,哪些已经被收到
两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。
3、避免资源浪费
两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求 SYN 报文,而造成重复分配资源。
只有两次握手时,如果客户端的SYN请求连接在网络中阻塞,客户端没有收到服务端的ACK报文,会重新发送SYN。
由于没有第三次握手,服务器不清楚客户端是否收到了自己发送的建立连接的 ACK 确认信号,所以每收到一个 SYN 就只能先主动建立一个连接。
06
TCP四次挥手
四次挥手是在TCP协议中用于终止一个已建立的连接的机制。它是TCP连接的正常关闭流程,由发送方和接收方之间进行的四次通信组成。
以下是四次挥手的步骤:
第一次挥手(FIN):发送方向接收方发送一个带有FIN标志的数据包(FIN包),表示发送方已经完成数据的发送,希望关闭连接。发送方不再发送数据,但仍然可以接收数据。
第二次挥手(ACK):接收方收到FIN包后,向发送方发送一个带有确认号(ACK)的数据包,表示已接收到发送方的关闭请求。接收方仍然可以发送数据。
第三次挥手(FIN):接收方向发送方发送一个带有FIN标志的数据包(FIN包),表示接收方也希望关闭连接。接收方停止发送数据,但仍然可以接收数据。
第四次挥手(ACK):发送方收到FIN包后,向接收方发送一个带有确认号(ACK)的数据包,表示已接收到接收方的关闭请求。发送方不再发送数据,也不再接收数据。
两个重要的TCP状态:
CLOSE_WAIT:表示TCP连接的一方已经收到了对方的连接终止请求(FIN包),并发送了确认(ACK包)。在CLOSE_WAIT状态下,接收方等待应用层处理完数据后的连接关闭。
TIME_WAIT:表示TCP连接的一方已经发送了连接终止请求(FIN包),并收到了对方的确认(ACK包)。在TIME_WAIT状态下,发送方等待一段时间后,保持连接状态清理(ACK包没有丢包),并释放资源。
07
TCP滑动窗口
TCP能保证可靠传输,但失去了效率.为了在保证可靠性的前提下,尽可能的提高效率,就有了滑动窗口机制
滑动窗口是在数据传输中用于流量控制和可靠传输的一种机制。它允许发送方在不等待接收方确认的情况下连续发送多个数据包,提高了传输效率。
在不引入滑动窗口的情况下:
发送方和接收方一应一答,可靠性确实能得到保证,但其实大部分的时间都消耗在等待ACK上了.
因此滑动窗口就是每次批量发送一波消息,然后在等一波ACK,再发一波消息
如下图所示:
上图中窗口大小是3000,主机A发送了3000字节的数据,主机B需要确认应答,如果第一个ack成功返回主机A,说明1~1000的数据发送成功,窗口就会向后移动,并发