TCP协议简介
TCP 与 UDP 一样,都是传输层的协议,但是提供的服务却不相同,UDP 为上层应用提供的是一种不可靠的,无连接的服务,而 TCP 提供一种面向连接,可靠的字节传输服务,TCP 让两个主机建立连接的关系,应用数据以数据流的形式进行传输,先后发出的数据在网络中虽然也是互不干扰的传输,但是这些数据本身携带的信息确实紧密联系的,TCP 协议会给每个传输的字号进行编号,当然了,两个主机方向上的数据编号是彼此独立的,在传输的过程中,发送方把数据的起始编号与长度放在 TCP 报文中,接收方将所有数据按照编号组装起来,然后返回一个确认,当所有的数据接收完成后才将数据递交到应用层。
TCP的特点
- 面向连接的运输协议
- 每一条TCP连接只能有两个端点,一对一
- TCP提供可靠的交付
- TCP提供全双工,TCP连接的两端都接收发送缓存和接收缓存。
- 面向字节流
TCP发送报文的方式也和UDP不同,TCP不关心应用进程一次把多长的报文发送到TCP缓冲中,而是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段含多少个字节。如果数据太长,TCP可以划分短一些再发送,如果数据太短,TCP可以等待积累到足够长再发送。
tcp报文结构
-
源端口(Source Port),16 位。
-
目的端口(Destination Port),16 位。
-
序列号 (Sequence Numbe) 发送数据包中的第一个字节的,32 位。TCP 协议是基于流发送数据的,所有使用序号给发送的所有数据字节都编上号,并按照序号进行顺序发送。
-
确认序列号 (Acknowledgment Number),32 位。TCP 的通信是全双工的(两端同时发送和接受),当连接建立成功后,每一方都能同时发送和接收数据。每一个方向的序号代表这个报文段携带的第一个字节数据的编号。每一方还需要使用确认号对它已经收到的字节进行确认。即:本端把收到的最后一个字节的编号加一,这个值就是确认号,然后发送给对端。例如,B正确收到了A发送过来的一个报文段,其序号字段为501,数据长度为200,则序号为(501~700),这表明B正确接受了A发送到700为止的数据,因此B的期望收到的下一个数据序号为701。
-
数据偏移 (Data Offset),4 位,该字段的值是 TCP 首部(包括选项)长度除以 4。
-
标志位:6 位,URG 表示紧急指针(Urgent Pointer)字段有意义,ACK 表示确认序(Acknowledgment Number)字段有意义;TCP 规定,只有 ACK=1 时有效,也规定连接建立后所有发送的报文的 ACK 必须为1 。PSH 表示 Push 功能,推送数据。RST 表示复位 TCP 连接。 SYN 表示 SYN 报文,在建立 TCP 连接的时候使用,用来同步序号。当 SYN=1 而 ACK=0 时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使 SYN=1 和 ACK=1。因此, SYN 置 1 就表示这是一个连接请求或连接接受报文。FIN 表示没有数据需要发送了,终止连接。在关闭 TCP 连接的时候使用,用来释放一个连接。当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。
-
窗口(Window)指的是发送本报文段的一方的接收窗口,窗口值告诉对方:从本报文段的确认号算起,接收方目前允许对方发送的数量。窗口值作为接收方让发送方设置其发送窗口的依据。 例如:A发送一个报文段,其确认号是701,窗口字段是1000,就是告诉对方:“从701开始,我还可以接收1000个字节,即701-1700
-
校验和(Checksum),16 位。每一个报文段都包括有校验和字段,若报文有损伤,则由终点 TCP 将其丢弃,并被认为是丢失。TCP 的校验和是强制的。
-
紧急指针(Urgent Pointers),16 位,只有 URG 标志位被设值时该字段才有意义,表示紧急数据相对序列号(Sequence Number字段的值)的偏移。用URG 值 + 序号得到最后一个紧急字节。
-
选项(长度可变,最长可以为40个字节),这里重点说说MSS
TCP在建立连接的时候,就可以确定发送数据包的单位MSS(Maximum Segment Size), MSS是每一个TCP报文段中的数据字段的最大长度。 (注意,不是整个TCP报文段的最大长度)
TCP在传输大量数据的时候,是以MSS大小将数据进行分割发送的,重传时也是以MSS为单位。
为什么要设计一个MSS呢? 我们知道,TCP报文端的数据部分,至少还要加上40字节的首部(20字节TCP头+20字节IP头),如果选择了很小的MSS长度,比如只有一个字节的数据,却要封装上40字节的头,那么网络的利用率就很低了。但是如果设置得非常大,在IP层传输时就可能被拆分成多个数据片,在终点还要重新拼接,传输出错时还要重传,这样也会使得开销增大。 理想状态下是MSS正好是IP不会分片的最大数据长度。 (但是很难达到)
👉MSS是在TCP连接建立时,由两边的主机计算出来的:两端的主机都会将自己能够支持的MSS写入。 如果没有指定,就是默认的536字节长。
三次握手:
- 客户端发送含 SYN 标志的报文,表示要建立一个连接, 初始化连接的同步序号 seq;
- 服务器端接收到含 SYN 的报文后, 也将一条含 SYN 标志报文, 作为 ACK 回复给客户端, 一则表示收到客户端创建连接的请求,二则表示服务端也同时创建与客户端的连接;
- 客户端收到回复后再发送一条 ACK 报文, 表示收到服务端的创建连接请求。
不论是客户端还是服务端, 创建连接发送数据的时候数据包中都包含一个初始化序列号 seq, 对方收到数据并回复时会将收到的 seq 加 1 作为 ACK 的数据。 这样发送端就可以判断是不是对本次数据的回复。 以后每次发数据都会在前一次 seq 的基础上 +1 作为本次的 seq (注意, 建立连接和断开连接时 seq 是加 1, 传输应用数据时 seq 加的是上次发送的数据长度 )。
四次挥手:
- 已经建立连接的其中一段想要断开连接,称为主动关闭方。其发送一个含 FIN 标志、seq 值(假设为 Q)和 ACK 值(假设为 K, 来自上次收到的 seq)的报文到连接对方,称为被关闭方;
- 被关闭方收到含 FIN 标志的报文后,将 K 作为 seq 值,Q 加 1 后作为 ACK 值回复给主动关闭方。
- 被关闭方同时检查自身是否还有处理完的数据包,若没有则开始启动关闭操作,身份转变为主动关闭方,同样发送一个含 FIN、seq(值仍为 K)和 ACK 值(值仍为 Q+1)初始化的报文到连接对方。
- 原主动关闭方转变为被关闭方,收到报文后,回复一条 seq 为 Q+1,ACK 为 K+1 的报文。至此,完成 TCP 连接的断开