TCP协议解析

Aki 发布于 2023-03-11 301 次阅读


TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。通俗说,它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送;而UDP则不为IP提供可靠性、 流控或差错恢复功能。一般来说,TCP对应的是可靠性要求高的应用,而UDP对应的则是可靠性要求低、传输经济的应用。 TCP支持的应用协议主要有:Telnet、FTP、SMTP等; UDP支持的应用层协议主要有:NFS(网络文件系统)、SNMP(简单网络管理协议)、DNS(主域名称系统)、TFTP(通用文件传输协议)等。 TCP/IP协议与低层的数据链路层和物理层无关,这也是TCP/IP的重要特点

tcp报文段解析、

  • 16位源/目的端口号字段:表示数据从哪个进程来到那个进程去,有利于套接字的多路分解和多路复用。
  • 32位的序号字段和32位的确认号字段:这些字段被tcp发送方和接收方用来实现可靠数据传输服务。
  • 4位TCP报头长度字段:该字段指示了以32比特的字为单位的tcp头部长度。由于tcp选项字段的原因,tcp头部的长度是可变的。通常选项字段为空,tcp头部典型长度为40个字节。
  • 可选与变长的选项字段:该字段用于发送发与接收方协商最大报文长度(MMS),或在高速环境下用作窗口调节因子使用。
  • 16位的窗口字段:用于实现流量控制和拥塞控制的重要字段。TCP协议通过窗口字段来控制发送方可以发送的数据量,以避免发送方发送过多的数据导致网络拥塞或接收方无法及时处理数据。
  • 16位检验和:在发送TCP报文时,发送方会计算TCP报文首部的校验和,并将其添加到TCP报文首部中。接收方在接收到TCP报文时,也会计算TCP报文首部的校验和,并将其与报文首部中存储的校验和进行比较。如果计算出的校验和与存储的校验和不一致,接收方会认为TCP报文首部发生了错误或被篡改,并且会丢弃该报文。
  • 6位的标志字段:
    URG:标识紧急指针是否有效
    ACK:用于确认字段中的值是有效的,即该报文段包括一个对已被成功接收报文段的确认,一般称携带 ACK 标志的 TCP 报文段为「确认报文段」
    PSH:表示该报文段高优先级,接收方 TCP 应该尽快推送给接收应用程序,而不用等到整个 TCP 缓存都填满了后再交付
    RST:对方要求重新建立连接,一般称携带 RST 的报文段为「复位报文段」
    SYN:请求建立连接,一般称携带 SYN 标志的 TCP 报文段为「同步报文段」
    FIN:通知对方,本段要关闭了,一般称携带 FIN 的报文段为「结束报文段」

上面是一个tcp报文的格式。tcp是全双工的连接,双方可以同时发送和接收数据。网络层协议即ip地址协议是不可靠的,但是tcp协议通过诸多机制使得tcp协议变得可靠!

tcp可靠传输五大机制、

(1)确认和重传机制--通过序号和确认号来实现

TCP协议通过发送ACK确认报文来确认接收到的数据,并通过发送重传报文来重新传输未确认或丢失的数据。发送方会定时重传未收到ACK确认的数据,确保数据能够被接收方正确接收。

TCP协议中的确认重传机制是一种可靠传输的机制,用于确保数据能够可靠地传输到接收方。其工作流程如下:

  1. 发送方发送数据包:发送方将要发送的数据划分成多个数据包,每个数据包都会带有一个序列号。发送方将数据包发送给接收方,并启动一个定时器,等待接收方发送确认消息。
  2. 接收方接收数据包:接收方接收到数据包后,会检查序列号是否正确,并将数据包存储在缓存区中。如果数据包的序列号正确,则向发送方发送一个确认消息(ACK)。
  3. 发送方接收确认消息:发送方接收到接收方的确认消息后,会停止定时器,并将该数据包标记为已发送。如果发送方没有接收到确认消息,则认为数据包丢失,会启动超时重传机制,重新发送该数据包。
  4. 丢失数据包的处理:如果接收方没有接收到某个数据包,则会等待一段时间,如果还没有收到该数据包,则会向发送方发送一个重传请求。发送方在收到重传请求后,会重新发送丢失的数据包。

tcp报文段首部中最重要的字段是序号字段和确认字段,这两个字段是可靠传输的关键部分。tcp把数据看成一个无结构、有序的字节流。tcp对序号的使用是建立在传送的字节流上而不是建立在传送的报文段的序列之上。一个报文段的序号是该报文段首字节的字节流编号。

例如主机A上的一个进程通过一个tcp套接字连接主机B的一个进程,主机A中的tcp将隐式的对数据流中的每一个字节编号。假设数据流有一个包含500000字节的文件组成,其MSS为1000,数据流的首字节编号为0。那么tcp将该字节流分成500个报文段,每个报文段的序号依次是0,1000,2000......依次类推,每一个序号被填入tcp首部报文段的序号中。

确认号要比序号难处理一些,因为tcp是全双工的结构,主机A在发数据的同时也可能收到主机B的数据,都是在同一条tcp连接上。从主机B到达主机A的每个报文段都有一个序号用于标识从B流向A的数据。主机A填充进报文段的确认号是主机A期望从主机B收到的下一个字节的编号!

假设主机A已经收到了来自主机B的编号为0-535的所有字节,同时它打算发送一个报文给主机B,那么主机A填写的确认号是536,因为主机A希望能够收到来自主机B字节流536之后的字节。

(2)流量控制--通过窗口字段来实现

TCP协议通过窗口字段来控制发送方可以发送的数据量,避免发送方发送过多的数据导致网络拥塞或接收方无法及时处理数据。

(3)拥塞控制--通过窗口字段来实现

TCP协议通过拥塞窗口来调整发送速率,避免发送过多的数据导致网络拥塞。拥塞控制算法通常会动态地调整窗口大小,以达到最优的网络传输效果。TCP协议的拥塞控制主要通过动态调整发送方的窗口大小来实现。发送方维护一个拥塞窗口(Congestion Window),用于控制发送的数据量。

当网络出现拥塞时,TCP协议会减小拥塞窗口的大小,从而减缓发送方的发送速率,避免继续发送数据导致网络拥塞。反之,当网络拥塞情况得到改善时,TCP协议会增大拥塞窗口的大小,从而提高发送方的发送速率。

TCP协议中使用的拥塞控制算法有多种,其中比较常用的是拥塞避免算法(Congestion Avoidance)和快速重传算法(Fast Retransmit)。拥塞避免算法通过每次发送数据时动态调整拥塞窗口的大小,从而控制发送速率;快速重传算法则可以在接收到多个重复的ACK报文时立即重传未确认的数据,从而提高重传的效率。

(4)排序机制--通过序号seq来实现

TCP协议中的排序机制主要是通过接收方收到的序列号(Sequence Number)来对数据进行排序的。在TCP协议中,每个发送的数据包都会带有一个序列号,用于标识数据在传输过程中的顺序。接收方会根据序列号来确定数据的顺序,将乱序接收的数据按照序列号进行排序,最终按照正确的顺序交付给上层应用程序。

TCP协议中的每个数据包都包含了一个32位的序列号(Sequence Number),用于标识发送数据的起始位置。接收方会根据序列号来判断接收到的数据是否是按照正确的顺序到达的,如果数据乱序到达,接收方会将其存放在缓存区中,等待后续的数据包到达。当接收方收到一个数据包时,如果序列号比当前期望的序列号小,则说明该数据包是之前已经接收过的数据包,可以直接丢弃;如果序列号比期望的序列号大,则说明数据包是乱序到达的,需要存放在缓存区中等待后续的数据包到达;如果序列号与期望的序列号相等,则说明数据包是正确到达的,可以交付给上层应用程序处理。

TCP协议中的序列号(Sequence Number)是一个32位的整数,因此理论上最大可以表示4294967296个字节的数据。如果要发送的文件大小超过了序列号的范围,TCP协议会如何处理呢?

实际上,在TCP协议中,序列号是一个循环计数器,当序列号达到最大值时,会重新从0开始计数。因此,如果要发送的数据大小超过了序列号的范围,TCP协议会自动将序列号回绕到0,从而重新开始计数。这种方式被称为循环序列号(Wrap-Around Sequence Number)。

当序列号回绕到0时,需要注意的是,此时数据的顺序可能会出现混乱。因为接收方会根据序列号来判断数据的顺序,如果序列号回绕到0,接收方可能会将之前的一些数据误认为是新的数据,从而导致数据顺序出现混乱。为了解决这个问题,TCP协议中采用了一种称为Timestamps的机制,用于判断序列号的正确性。每个TCP数据包都带有一个时间戳,接收方可以根据时间戳来判断数据包的正确性,从而避免数据顺序出现混乱。

总之,当要发送的数据大小超过了序列号的范围时,TCP协议会自动将序列号回绕到0,从而重新开始计数。为了避免数据顺序出现混乱,TCP协议中使用了Timestamps机制,用于判断数据包的正确性。

(5)校验和--通过检验和字段来实现

TCP协议使用校验和机制对数据进行校验,以检测数据传输过程中是否发生错误或被篡改。

tcp三次握手、

tcp协议在通信之前需要进行三次握手建立连接,建立连接之后服务器端会分配一个新的已连接tcp套接字来与客户端进行通信。注意连接是与监听套接字进行通信,通信是与新的已连接套接字进行通信,这两个套接字是不同的。在TCP连接建立成功之后,客户端和服务器之间可以通过这个新的TCP套接字进行通信,包括传输Web请求和响应数据。

  • 1、客户端发送建立TCP连接的请求报文,其中报文中包含seq序列号,是由发送端随机生成的,并且将报文中的SYN字段置为1,表示需要建立TCP连接。(SYN=1,seq=x,x为随机生成数值);
  • 2、服务端回复客户端发送的TCP连接请求报文,其中包含seq序列号,是由回复端随机生成的,并且将SYN置为1,而且会产生ACK字段,ACK字段数值是在客户端发送过来的序列号seq的基础上加1进行回复,以便客户端收到信息时,知晓自己的TCP建立请求已得到验证。(SYN=1,ACK=x+1,seq=y,y为随机生成数值)这里的ack加1可以理解为是确认和谁建立连接;
  • 3、客户端收到服务端发送的TCP建立验证请求后,会使自己的序列号加1表示,并且再次回复ACK验证请求,在服务端发过来的seq上加1进行回复。(SYN=1,ACK=y+1,seq=x+1)。

tcp四次挥手、

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  • 1、客户端发送断开TCP连接请求的报文,其中报文中包含seq序列号,是由发送端随机生成的,并且还将报文中的FIN字段置为1,表示需要断开TCP连接。(FIN=1,seq=x,x由客户端随机生成)。
  • 2、服务端会回复客户端发送的TCP断开请求报文,其包含seq序列号,是由回复端随机生成的,而且会产生ACK字段,ACK字段数值是在客户端发过来的seq序列号基础上加1进行回复,以便客户端收到信息时,知晓是自己的TCP断开请求已经得到验证。(FIN=1,ACK=x+1,seq=y,y由服务端随机生成)。
  • 3、服务端在回复完客户端的TCP断开请求后,不会马上进行TCP连接的断开,服务端会先确保断开前,所有传输到A的数据是否已经传输完毕,一旦确认传输数据完毕,就会将回复报文的FIN字段置1,并且产生随机seq序列号。(FIN=1,ACK=x+1,seq=z,z由服务端随机生成)。
  • 4、客户端收到服务端的TCP断开请求后,会回复服务端的断开请求,包含随机生成的seq字段和ACK字段,ACK字段会在服务端的TCP断开请求的seq基础上加1,从而完成服务端请求的验证回复。(FIN=1,ACK=z+1,seq=h,h为客户端随机生成),至此连接断开。