TCP报文头(首部)详解

news2024/11/13 10:06:26

        本篇文章基于 RFC 9293: Transmission Control Protocol (TCP) 对TCP报头进行讲解,部分内容会与旧版本有些许区别。

        TCP协议传输的数据单元是报文段,一个报文段由TCP首部(报文头)和TCP数据两部分组成,其中TCP首部尤其重要,首部用于控制(新建、断开)连接、流量和拥塞等。TCP首部的固定长度是20B,最大长度是60B,其中可变选项长度最长为40B(4B×10)。

 字段解释

  • 源端口(Source Port):占用 2 Byte,标识发送方应用程序使用的端口号;
  • 目的端口(Destination Port):占用 2 Byte,标识发送方应用程序的目标端口号,也就是接收方应用程序的端口号
  • 序号(Seq,Sequence Number):占用 4 Byte,范围是[0, 2^32),标识TCP报文段中的第一个字节数据的序列号,用于保证传输数据的可靠性和顺序性。TCP是一个面向字节流的传输控制协议,且支持全双工通信,所以为了保证发送方和接收方都能独立进行传输,两端通信时都必须得知道各自分别发送和接收了多少个字节数据(不含TCP首部),以及接收到数据后如何进行读取、拼接组合。TCP发送方用Seq字段告知接收方自建立连接以来我方已累计(不包含本报文段)已发送了Seq-1个字节数据,本次传输的报文数据第一个字节序列号是Seq,而接收方在成功接收完一段或多段数据后可以根据Seq的大小顺序对数据进行拼接组合,并且用Ack字段告知发送方我方已成功接收了Ack-1个字节数据,期望下次接收的报文段是从Ack序号开始。【为什么都要减1呢?因为TCP成功建立连接后Seq和Ack都会置为1,所以Seq和Ack的起始值都是1。第N次发送数据时的 Seq = Seq初始值1 + 第1次发送的字节长度 + ··· + 第N-1次发送的数据字节长度,也就是第N次发送数据时的 Seq = 第N-1次发送数据时的 Seq + 第N-1次发送的数据字节长度】。请注意,TCP建立连接和断开连接时Seq和Ack跟TCP报文数据长度无关。当Seq到达2^32-1(4GB内容.....)后又会从0重新开始。
  • 确认号(Ack,Acknowledgment Number):占用 4 Byte,标识接收方期望收到下一个报文段的序列号是Ack,也可以理解成接收方已成功接收了Ack-1个字节数据。只有标志位ACK为1时确认号才有效。接收方在成功接收完数据后需要给发送方一个确认,告诉发送方已收到某个报文段(事实上,接收方往往是在成功接收了多条报文段后才发送一次Ack)。

  • 数据偏移(Data Offset):占用 4 bit,标识TCP报文段中报文数据的起始位置距离报文段开始位置有多远,也就是TCP的首部长度是多少,单位是32bit(4字节)。从下图可以看到TCP首部长度 Header Length 为 0101,转换成十进制是5,4Byte × 5 = 20 Byte。而TCP首部固定长度是20Byte,可变长度是40 Byte,最长是60 Byte,所以数据偏移值最小是5,最大是15,[0101, 1111]。

  • 保留(Reserved):占用 3 bit预留给未来使用的一组控制位,目前该值设置为0。TCP首部的数据偏移(首部长度)、保留位和标志位公用16 bit,也就是2 byte,其中数据偏移独占4 bit,保留位和标志位一共可分配12 bit,如果我们把保留位Reserved也当成一个预留的或空白的标志位,那么完全可以理解成TCP最多可分配12个标志位,目前(rfc9293版)已明确的标志位共有8个,还有1个处于实验阶段的标志位AE,一共是9个标志位,每个标志位占用1 bit,剩余的3 bit由Reserved占用。
  • 标志位(Flags):也叫控制位,每一个标志位占用 1 bit。目前已有9个标志位,包括AE、CWR、ECE、URG、ACK、PSH、RST、SYN和FIN,值为0或1,用于控制TCP的拥塞、连接的建立、管理和关闭等。
    1. AE(Accurate ECN):处于试验期的标志位。外文资料也比较少,看了半天也不知道是用来干嘛的,暂且搁置吧。
    2. CWR(Congestion Window Reduce):拥塞窗口减半标志,发送端通过降低“cwnd”和“ssthresh”来应对网络拥塞。CWR和ECE都是用来控制网络拥塞的,而CWR是用来响应ECE的,所以在了解CWR作用之前,我们得先搞懂ECE是用来干嘛的。Explicit Congestion Notification,翻译过来就是“显式拥塞通知”,简写ECN。数据报在发送方发出后可能要经过多个路由器才能到达接收方,如果中间某个路由器根据算法结果判断出自身发生了拥塞,就会在报文的IP首部设置CE标志(ECE),接收方在接收到这段报文后,发现IP头设置了CE标志,表明数据发送途中网络有拥塞,得赶紧把这个消息告诉发送方,不然可能要丢包。接收方在后续返回给发送方的每一条ACK报文都会设置ECN-Echo(ECE)为1,用于告知发送方从贵方到我方的网络有拥塞。而发送方在接收到对方返回的ECE报文后,得知网络有拥塞,就会将拥塞窗口“cwnd”减半,并降低慢启动阈值“ssthresh”,之后再发送CWR报文给接收方,接收方收到CWR报文后表明发送方也采取相应措施来应对网络拥塞,随后便不再发送ECE报文。请注意,数据重传时,TCP报头中不会设置CWR标志位。
    3. ECE(ECN-Echo):用于通知对方,从对方到我方的网络有拥塞。如果发送方收到ECN-Echo (ECE) ACK包(即TCP报头中设置了ECN-Echo标志的ACK包),则发送方知道在从发送方到接收方的路径上遇到了网络拥塞。
    4. URGUrgent):标识是否为紧急报文,配合紧急指针(urgent pointer)一起使用,值为0或1 。当标志位URG为1时,表明该报文段有紧急数据需要尽快发送(发送端此时不会把报文数据写入到缓冲区,而是直接发送给应用层),即使对端窗口大小此时为0系统也要以高优先级发送该段报文,紧急数据会放在TCP报文段数据部分的最前端,紧急指针用于标识紧急数据在TCP报文段数据部分的结束位置,紧急数据之后的字节内容依然是普通数据。
    5. ACKAcknowledgment):标识确认应答是否有效,配合确认号(Ack,Acknowledgment Number)一起使用,值为0或1 。当标志位ACK为1时,确认号Ack才有效。除了最初建立连接时发送的SYN报文段之外,其它情况下发送的报文段ACK都为1。
    6. PSHPush):标识是否立即把报文数据推送给应用层,值为0或1。如果TCP接收方接收到PSH为1的报文段,应尽快把这段报文数据从接收缓冲区中读出并立即推送给应用层,不必等到缓冲区写满后再推送。常用于请求方发送完一个新请求后希望立即得到对端的响应。

    7. RSTReset):标识是否重置连接,值为0或1 。当RST为1时,表明TCP连接发生错误,需要先强制断开连接,再重新建立新的连接,称之为复位TCP连接,这种报文也称之为复位报文段
    8. SYNSynchronize):该标志位用于在建立连接时同步Seq和Ack的初始值,仅在建立连接时使用。TCP三次握手中,第一次握手时,客户端先发送“SYN=1,ACK=0”的报文段,表示请求建立,第二次握手时,如果服务端同意建立连接就返回“SYN=1,ACK=1的报文段。我们把含有SYN标志位的报文称为同步报文段
    9. FINFinish):该标志位用于断开/释放连接,仅在断开连接时使用。当通信结束后需要断开连接时,主动要求断开连接的一方会发送“FIN=1,ACK=1”的报文段给对端,告知对端通信已结束希望断开连接,对端接收后会相应地返回“ACK=1”的报文段,至此连接会彻底关闭。我们把含有FIN标志位的报文称为结束报文段

  • 窗口(Window):占用 2 Byte(16bit),表示TCP接收方当前可用的最大缓冲区(Receive Buffer)大小,常配合Options字段中的Window Scale一起使用用于实现滑动窗口机制,对流量进行控制(接收方通过Window告知发送方我方剩余的接收缓冲区还剩这么多,发送发会根据Window大小灵活调整发送速率,从而避免网络拥塞并确保通信的稳定性)。注意,Window大小值有时候并不代表当前的实际可用窗口大小,因为Window共占用16位,最大值是2^16-1,也就是64K(65535),在当前的网络高带宽情况下,64K显然已无法满足大部分的网络通信,所以后来就在TCP的Options字段中新增了Window Scale对窗口进行放大,Window Scale代表的是一个向左的位移值(Shift count),最大值是14。二进制数据每增加一位1,其换算指数都会加1,所以实际窗口大小最大允许值应该是 2^(16+14) -1 = 2^30 - 1,长达1Gb。TCP在建立连接时的前两次握手过程中,双方都会用Window Scale来向对端声明我方的窗口放大因子并缓存对端的窗口放大因子,后期通信过程中不再声明,仅发送Window,双方会用对方的Window和Window Scale来计算实际的窗口大小,并根据实际窗口大小调整发送速率(如果窗口为0,发送方会定期进行窗口探测)。用图说话

  • 校验和(Checksum):占用 2 Byte,接收方校验接收的数据是否与发送的数据完全一致,用于保证数据的完整性和准确性Checksum是一个强制字段,发送方必须生成并发送它,接收方必须检查它。数据在传输过程可能会出错,所以TCP发送方在发送数据前会先根据伪首部、报文段首部和报文段数据计算校验和值,并将最终得到的值写入Checksum字段。而接收方在收到此报文段后,会根据伪首部、报文段首部和报文段数据再次计算校验和值,如果结果是0,说明数据一致,否则丢弃数据并报告发送方重传这段数据。

TCP发送方计算校验和过程:

        1.先将TCP报文段首部中的Checksum字段置为0,因为Checksum本身也要参与计算;

        2.将伪首部、TCP报文段首部和TCP报文段数据连在一起并分成若干个16位的位串,看是否是偶数个字节(所有数据是否对齐),如果不是则在右侧填充一个全为0的8位位串(填充段仅用于计算校验和值,不会传输给接收方),将每个16位位串看成一个二进制数;

        3.对这些16位的二进制数进行1的补码和运算(one's complement sum),如果最高位有进位应循环进到最低位,累加的结果再取反码即得到校验和;

        4.将校验写入TCP报文首部的Checksum字段。

TCP接收方检查校验和过程:

        1.接收方将伪首部、TCP报文段首部和TCP报文段数据按发送方同样的方式(不包含发送方的第1步操作)进行1的补码和运算,累加的结果再取反码

        2.校验,如果上步的结果为0,表示传输正确;否则,说明传输有差错。 

  • 紧急指针(Urgent Pointer):占用 2 Byte,也称紧急偏移,用于标识紧急数据在TCP报文段数据部分的结束位置/正的偏移量。只有当标志位URG为1时该参数才有效。紧急数据是放在TCP报文段数据部分的最前端,紧急指针用于标识紧急数据在TCP报文段数据部分的结束位置,紧急数据之后的字节内容依然是普通数据。
  • 选项(Options):占用 0~40 Byte,可选字段,用于传输TCP报文的附加信息,Options所有选项也都包含在校验和中。仅Data Offset > 5 时Options才会出现,size(Options) = (Data Offset - 5)×32,每个option的长度必须是8bit的整倍数(最短1个字节),且Options总长度也必须是32bit(4字节)的整倍数如果某个option的长度不够4字节,那么就用“No-Operation(占用1字节)”来补充位数(都是补高位),缺几个字节就补几个“No-Operation”。请注意,当整个选项列表的结束位置无法与TCP报头尾部对齐时,TCP会在整个选项(all options, not each option)列表的尾部填充“End of Option List”选项综上可知,size包含了补位和填充的数据长度。一个option由Kind、Length和Data三部分组成,其中Length和Data是选填参数,Length表示的是当前这个option的总长度,它包含Kind、Length和Data三者总共占用的位数。

常用option如下表:

KindLengthMeaningReference
0-End of Option ListRFC9293仅用于填充整个选项列表尾部。
1-No-Operation,NOPRFC9293补位选项。
24Maximum Segment Size,MSSRFC9293最大报文段长度,具体限制的是TCP报文段中数据部分的长度。
33Window ScaleRFC7323窗口放大因子
42SACK PermittedRFC2018标识是否支持SACK,只有在建立连接时SYN报段使用。
5NSelective Acknowledgment,SACKRFC2018选择性确认,用于数据重传机制。接收方可通过SACK参数告知发送方我方收到了不连续的数据块(Ack=200,SACK=200-400),发送方可根据此信息检查哪部分数据丢失(对方收到200字节数据,接收到的是200-400段,说明0-199段丢失了)并重传这段数据。
810TimestampsRFC7323时间戳

完整的options list请参阅:Transmission Control Protocol (TCP) Parameters/tcp-parameters-1 


参考文章

        RFC 9293: Transmission Control Protocol (TCP) 

        Transmission Control Protocol (TCP) Parameters   TCP所有字段、标志位和参数在这里都能找到!

        RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP

        draft-ietf-tcpm-accurate-ecn-28 - More Accurate Explicit Congestion Notification (ECN) Feedback in TCP        Accurate ECN

        draft-kuehlewind-tcpm-accurate-ecn-05 - More Accurate ECN Feedback in TCP                 Accurate ECN

        RFC 2018: TCP Selective Acknowledgment Options                                                            Options:SACK

        RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP         Options:SACK

        RFC 7323: TCP Extensions for High Performance                                                                Optinos:Window Scale、Timestamps

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1316899.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

node.js mongoose简述

目录 官方文档 mongoose Schema Model Query document 关系 官方文档 Mongoose v8.0.3: Getting Started mongoose Mongoose 是一个 Node.js 环境下 MongoDB 的对象建模工具。它提供了一种在应用程序中与 MongoDB 数据库进行交互的方式,使得开发者能够使用…

怎么使用会声会影?2024年最新使用会声会影的具体步骤

一听说视频剪辑我们就不由得联想到电影、电视等一些高端的视频剪辑技术,大家都觉得视频剪辑是一个非常复杂而且需要很昂贵的设备才可以完成的技术活,这对很多“门外汉”来说都可望而不可及。实际上,使用会声会影剪辑视频不仅是很多人都可以操…

哈希扩展:位图与布隆过滤器

目录 1. 位图1.1 位图引入1.2 位图概念1.3 位图的模拟实现1.4 位图相关问题1.5 位图的应用 2. 布隆过滤器2.1 布隆过滤器概念2.2 模拟实现2.3 布隆过滤器相关问题2.3.1 哈希切分 1. 位图 1.1 位图引入 给40亿个不重复的无符号整数,没排过序。给一个无符号整数&…

Java 基础学习(十二)文本I/O、日期与时间API

1 文本 I/O 1.1 字符流 1.1.1 什么是字符流 在Java中,字符流是指提供了基于字符的I/O能力的API。 Java 1.0中提供的基于字节的I/O流API只能支持8位字节流,无法妥善地处理16位Unicode字符。由于需要支持Unicode处理国际化字符,因此Java 1.…

网络安全——Iptables防DDoS攻击实验

一、实验目的要求: 二、实验设备与环境: 三、实验原理: 四、实验步骤: 五、实验现象、结果记录及整理: 六、分析讨论与思考题解答: 一、实验目的要求: 1、掌握常见DDoS攻击SYN Flood的攻击…

Toyota Programming Contest 2023#8(AtCoder Beginner Contest 333)

A - Three Threes 题目大意:给你一个整数n,将这个数n输出n次。 呃呃 B - Pentagon 题目大意:给你一个正五边形ABCDE,给你任意两条边,判断是否相等 主要问题要判断一下内边:AD,AC,…

小 cookie,大作用:探索网站中的隐私追踪器(下)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

用Flask搭建简单的web模型部署服务

目录结构如下: 分类模型web部署 classification.py import os import cv2 import numpy as np import onnxruntime from flask import Flask, render_template, request, jsonifyapp Flask(__name__)onnx_session onnxruntime.InferenceSession("mobilen…

【图的应用一:最小生成树】- 用 C 语言实现普里姆算法

目录 一、最小生成树 二、普里姆算法的构造过程 三、普里姆算法的实现 一、最小生成树 假设要在 n 个城市之间建立通信联络网,则连通 n 个城市只需要 n - 1 条线路。这时,自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信…

云仓酒庄的品牌雷盛红酒分享红酒里加二氧化硫有害吗?

雷盛葡萄酒是广州万豪酒业有限公司旗下主力葡萄酒品牌,该品牌由云仓酒庄负责全国运营。雷盛(LEESON)品牌系列葡萄酒有幸邀请著名导演张纪中先生担任品牌代言人。采用多国家采购、多葡萄酒品种、多价位区间的全系列整体品牌形式,让…

谷达冠楠科技:抖音网店到底怎么做靠谱

随着互联网的发展,越来越多的人开始尝试在网上开设自己的店铺。而在众多的电商平台中,抖音网店无疑是近年来最受年轻人欢迎的一种方式。那么,抖音网店到底怎么做才能靠谱呢? 首先,我们需要明确一点,无论是在哪个平台上…

JS对象笔记

对象声明 对象也只是一种数据类型/字面值。写对象这个字面值有两种写法,一种是普通的对象,这种对象用new 构造函数(),另一种是JS内特有的json对象。这个对象是直接{}就代表对象。且也是在堆内。 对象的构成 无论是上…

Pytorch当中的.detach()操作是什么意思

.detach() 是 PyTorch 中用于从计算图中分离张量的方法。当我们在PyTorch中进行张量运算时,操作会构建一个计算图来跟踪计算历史,这个计算图用于自动求导和反向传播来计算梯度。 使用.detach()方法可以将一个张量从当前的计算图中分离出来,使…

System作为系统进程陔如何关闭?

一、简介 system进程是不可以关闭的,它是用来运行一些系统命令的,比如reboot、shutdown等,以及用来运行一些后台程序,比如ntfs-3g、v4l2loopback等。system进程也被用于运行一些内核模块,比如nvidia、atd等。system进程…

太阳能电池特性测试用太阳光模拟器24H光源

概述 太阳能模拟器是一种在室内模拟太阳光的设备,能够较为准确地模拟太阳辐射的准直性、均匀性和光谱特性。它的基本原理是利用人工光源模拟太阳光辐射,以克服太阳光辐射受环境、时间和气候等因素影响,并且总辐照度不能调节等缺点&#xff0c…

c++ websocket 协议分析与实现

前言 网上有很多第三方库,nopoll,uwebsockets,libwebsockets,都喜欢回调或太复杂,个人只需要在后端用,所以手动写个; 1:环境 ubuntu18 g(支持c11即可) 第三方库:jsoncpp,openssl 2:安装 jsoncpp 读取json 配置文件 用 自动安装 网…

【Redis】远程访问配置教程与远程客户端连接测试

前言 Redis 是一种基于内存的高性能键值存储数据库,常用于缓存、会话管理和实时数据分析等场景。在默认情况下,Redis 不允许远程连接,为了进行远程连接,需要进行一些配置和操作。接下来将介绍如何修改配置文件以允许远程连接&…

毅速:3D打印随形水路 提高良品率和生产效率的新利器

随着科技的不断发展,3D打印技术已经成为模具制造领域的一种重要技术。其中,模具随形水路的设计和制造是提高注塑产品良品率和生产效率的关键环节。 模具随形水路是一种根据产品形状设计的水路,可以更靠近产品,并在模具内热点集中区…

SpringBoot 源码解析2:启动流程1

SpringBoot 源码解析2:启动流程1 1.启动方式2.SpringBootApplication3.SpringApplication3.1 构造器SpringApplication3.2 SpringApplication#run 3.3 SpringApplication#run 中关键方法3.1 SpringApplication#prepareEnvironment3.2 SpringApplication#prepareCont…

前端登录界面网站设计模板--HTML+CSS

🎀登录表单 💖效果展示 💖HTML代码展示 <!DOCTYPE html> <html lang="en" > <head></