[Linux][网络][TCP][一][TCP基础][TCP报头]详细讲解

目录

  • 1.TCP头部格式
  • 2.TCP协议的特点
  • 3.TCP如何封装与分用
  • 4.通过序列号和确认应答号提高可靠性
    • 1.32位序列号
    • 2.32位确认应答号
    • 3.保证可靠性
    • 4.为什么序列号和确认应答号是单独的字段
  • 5.窗口大小
    • 1.TCP的发送和接收缓冲区
    • 2.窗口大小
  • 6.连接管理机制


1.TCP头部格式

  • TCP全称为"传输控制协议"(Transmission Control Protocol),人如其名, 要对数据的传输进行一个详细的控制
    请添加图片描述

  • 源/目标端口号:表示数据是从哪个进程来,到哪个进程去

  • 序列号:在建立连接时由计算机生成的随机数作为初始值,通过SYN包传给接收端主机,后续每发一次数据,就累加一次数据字节数大小

    • 用来解决网络包乱序问题
  • 确认应答号:指下一次期望收到的序列号,发生端收到这个确认应答号后可以认为这个序列号之前的数据都已经被正常接收

    • 用来解决丢包问题
  • 序列号和确认应答号

    • 将请求和应答进行一一对应
    • 允许部分确认丢失,或者不给应答
  • 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节),所以TCP头部最大长度是15 * 4 = 60

  • 6位标志位

    • URG:该位为1时,表明紧急指针字段有效
      • 它告诉系统此报文段中有紧急数据,应当尽快传输(相当于高优先级的数据),而不要按原来的排队顺序来传送
    • ACK:该位为1时,表明确认应答字段有效
      • TCP规定除了最初建立连接时的SYN包之外,该位必须置为1
    • PSH:该位为1时,提示接收端应用程序立刻从TCP缓冲区把数据读取走
      • 督促对方尽快将数据进行向上交付
    • RST:该位为1时,表示要求重新建立连接,以下四种情况会发送RST包
      • 端口未打开
      • 请求超时
      • 提前关闭
      • 在一个已关闭的socket上收到数据
    • SYN:该位为1时,表示希望建立连接,并在序列号的字段进行初识序列号值的设定
    • FIN:该位为1时,表示今后不会再有数据发送,希望断开连接
  • 16位窗口大小

  • 16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不仅包含TCP首部,也包含TCP数据部分

  • 16位紧急指针:标识哪部分数据是紧急数据

  • 40字节头部选项


2.TCP协议的特点

请添加图片描述

  • 面向连接:一定是一对一才能连接,不能像UDP协议那样可以一个主机同时向多个主机发生消息,也就是一对多是无法做到的
  • 可靠的:无论网络链路层出现了什么变化,TCP都可以保证一个报文一定能够到达接收端
  • 字节流
    • 消息是没有边界的,所以无论消息有多大都可以进行传输
    • 并且消息是有序的,当前一个消息还没收到的时候,即便收到了后面的字节,那么也不能交付给应用层去处理,同时对重复的报文会自动丢弃

3.TCP如何封装与分用

请添加图片描述

  • 4位首部长度
    • 它表示的是TCP的首部长度,基本单位是4字节 ,能够表示的范围 [0000 , 1111]
    • 当这个字段填入的是1111时**(即15)**,那么TCP首部长度为 15 * 4 = 60 字节
    • TCP首部长度 - TCP标准长度 = 60 - 20 = 40字节,这个就表示选项字段的长度
    • 一般4位首部长度用0101表示(即5),那么TCP首部长度就等于20字节,也就是TCP的标准长度
  • 如何封装:将应用层的有效载荷加上TCP的首部长度,交付给下一层
  • 如何分用
    • 根据4位首部长度,计算出TCP的标准长度与选项长度
    • 如果TCP的标准长度刚好是20字节,那么剩下的就是有效载荷
    • 如果大于20字节,则减去20字节后,得到选项字段的长度,再读取完选项的长度后,便可得到有效载荷

4.通过序列号和确认应答号提高可靠性

1.32位序列号

  • 对于32位序列号,TCP将每个字节的数据都进行了编号,即为序列号
  • 从下图可以看出,当想要发送比较大的数据时,TCP会将这些数据按字节进行编号,然后按照编号的顺序发送给服务器
    • 这样一来,32位序列号的作用就是能够保证报文的按序到达
  • **注意:**客户端向服务端发送报文时,序列号初始值并非为0,而是随机初始化这个序列号
    请添加图片描述

2.32位确认应答号

  • 32位确认应答号主要是用来对历史报文数据的一个响应,以客户端发送报文给服务端为例:
    • 当客户端发送报文给服务端时,本质上发送的是序列号,如果发生的序列号为100,当服务端收到客户端发来的序列号后,服务端就会给客户端响应一个报文,报文内部附带着确认应答号,这个确认应答号就是对客户端发来的序列号+1
      请添加图片描述

3.保证可靠性

  • 最核心的机制就是基于序号的确认应答机制 ,TCP不能做到100%可靠,但是通过应答机制来确保上一条信息是不是100%被对方收到

    • 只要有一条信息应答了,就可以肯定上一条消息是可靠的被对方收到了
      请添加图片描述
  • 当客户端向服务端发送了0~100之间的数据时,本质上就是发送了一个报文,如果服务端没有响应,那么客户端就不知道自己发出的数据是否被服务端收到,所以只有当服务端给客户端一个响应后,客户端就知道自己刚刚发出的数据已经被服务端收到了,这个确认应答号就保证了历史报文的可靠性

4.为什么序列号和确认应答号是单独的字段

  • 如果TCP的报头将这两个字段设计成了一个字段(这里假设为序列号),那么新的TCP头部格式如下
    请添加图片描述

  • 如下图所示:当客户端向服务端发送数据时,服务端给出响应;当服务端给客户端发送数据时,客户端再给出响应
    请添加图片描述

  • 这样的效率明显很低,并且TCP是全双工通信协议,双方通信时,一个报文,既可以携带要发送的数据,也可以携带对历史报文的确认

    • 即:TCP是全双工的,任何一方,既可以收,又可以发
      请添加图片描述

5.窗口大小

1.TCP的发送和接收缓冲区

  • TCP本身是具有接收缓冲区和发送缓冲区的

    • 接收缓冲区用来暂时保存接收到的数据
    • 发送缓冲区用来暂时保存还未发送的数据
    • 这两个缓冲区都是在TCP传输层内部实现的
  • 可以理解为在TCP内部malloc了2段空间
    请添加图片描述

  • 当客户端的应用层调用write/send时,并不是将数据发送到网络上,而是将应用层的数据拷贝到TCP自带的发送缓冲区中,在已经连接好的客户服务器中,经由网络传输到服务端的接收缓冲取中,服务端的接收缓冲区有数据后,调用read/recv时,是将服务端的接收缓冲区的数据拷贝给应用层
    请添加图片描述

  • 当数据写入到TCP的发送缓冲区后,对应的write/send函数就可以返回了,至于发送缓冲区当中的数据具体什么时候发,怎么发等问题实际都是由TCP决定的

  • 之所以称TCP为传输层控制协议,就是因为最终数据的发送和接收方式,以及传输数据时遇到的各种问题应该如何解决,都是由TCP自己决定的,用户只需要将数据拷贝到TCP的发送缓冲区,以及从TCP的接收缓冲区当中读取数据即可

  • TCP的发送缓冲区和接收缓冲区存在的意义?

    • 数据在网络中传输时可能会出现某些错误,此时就可能要求发送端进行数据重传,因此TCP必须提供一个发送缓冲区来暂时保存发送出去的数据,以免需要进行数据重传。只有当发出去的数据被对端可靠的收到后,发送缓冲区中的这部分数据才可以被覆盖掉
    • 接收端处理数据的速度是有限的,为了保证没来得及处理的数据不会被迫丢弃,因此TCP必须提供一个接收缓冲区来暂时保存未被处理的数据,因为数据传输是需要耗费资源的,不能随意丢弃正确的报文
      • 此外,TCP的数据重排也是在接收缓冲区当中进行的
    • 因为缓冲区的存在,所以可以做到应用层和TCP进行解耦

2.窗口大小

  • 窗口大小反映的就是客户端或服务端发送和接收缓冲区剩余空间的大小

  • 如下图所示,假设客户端和服务端各自的缓冲区只能容纳100字节的数据,当客户端向服务端发送20个字节的数据后,服务端的接收缓冲区的大小就变成了80字节;反过来对于客户端也是一样
    请添加图片描述

  • 当发送端要将数据发送给对端时,本质是把自己发送缓冲区当中的数据发送到对端的接收缓冲区当中。但缓冲区是有大小的,如果接收端处理数据的速度小于发送端发送数据的速度,那么总有一个时刻接收端的接收缓冲区会被打满,这时发送端再发送数据过来就会造成数据丢包,进而引起丢包重传等一系列的连锁反应

  • 在TCP报文中有了这个字段后, 接收端在对发送端发来的数据进行响应时,就可以通过16位窗口大小这个字段告知发送端自己当前接收缓冲区剩余空间的大小,此时发送端就可以根据这个窗口大小字段来调整自己发送数据的速度

    • 窗口大小字段越大,说明接收端接收数据的能力越强,此时发送端可以提高发送数据的速度
    • 窗口大小字段越小,说明接收端接收数据的能力越弱,此时发送端可以减小发送数据的速度
    • 如果窗口大小的值为0,说明接收端接收缓冲区已经被打满了,此时发送端就不应该再发送数据了

6.连接管理机制

  • 服务端状态转化
    • [CLOSED -> LISTEN]:服务器端调用listen后进入LISTEN状态,等待客户端连接
    • [LISTEN -> SYN_RCVD]:一旦监听到连接请求(同步报文段),就将该连接放入内核等待队列中,并向客户端发送SYN确认报文
    • [SYN_RCVD -> ESTABLISHED]:服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,可以进行读写数据了
    • [ESTABLISHED -> CLOSE_WAIT]:当客户端主动关闭连接(调用close),服务器会收到结束报文段,服务器返回确认报文段并进入CLOSE_WAIT
    • [CLOSE_WAIT -> LAST_ACK]:进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据),当服务器真正调用close关闭连接时,会向客户端发送FIN,此时服务器进入LAST_ACK状态,等待最后一个ACK到来(这个ACK是客户端确认收到了FIN)
    • [LAST_ACK -> CLOSED]:服务器收到了对FIN的ACK, 彻底关闭连接
  • 客户端状态转化:
    • [CLOSED -> SYN_SENT]:客户端调用connect,发送同步报文段
    • [SYN_SENT -> ESTABLISHED]:connect调用成功,则进入ESTABLISHED状态,开始读写数据
    • [ESTABLISHED -> FIN_WAIT_1]:客户端主动调用close时,向服务器发送结束报文段,同时进入FIN_WAIT_1
    • [FIN_WAIT_1 -> FIN_WAIT_2]:客户端收到服务器对结束报文段的确认,则进入FIN_WAIT_2,开始等待服务器的结束报文段
    • [FIN_WAIT_2 -> TIME_WAIT]:客户端收到服务器发来的结束报文段,进入TIME_WAIT,并发出LAST_ACK
    • [TIME_WAIT -> CLOSED]:客户端要等待一个2MSL(Max Segment Life,报文最大生存时间)的时间,才会进入CLOSED状态

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

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

相关文章

Ubuntu20安装torch1.13和pytorch_geometric2.3.0(对应cuda11.6)

在torch下载页面搜索1.13https://pytorch.org/get-started/previous-versions/,wheel安装方式(激活conda虚拟环境) pip install torch1.13.0cu116 torchvision0.14.0cu116 torchaudio0.13.0 --extra-index-url https://download.pytorch.org…

【Trick】conda安装python依赖时出现429 Client Error

起因 我在根据yml文件安装依赖和创建虚拟环境时,出现报错,主要报错信息为以下两点: 【1】Collecting package metadata (repodata.json): failed 【2】requests.exceptions.HTTPError: 429 Client Error: Too Many Requests for url: https…

C++笔记打卡第25天(机房预约系统)

1.机房预约系统需求 1.1 系统简介 学校有几个规格不同的机房,使用时经常会出现重复现象,现开发一套机房预约系统,解决这一问题。 1.2 身份简介 分别有三种身份使用该程序: 学生代表:申请试用机房教师:…

深入理解网络原理3----TCP核心特性介绍(上)【面试高频考点】

文章目录 前言TCP协议段格式一、确认应答【保证可靠性传输的机制】二、超时重传【保证可靠性传输的机制】三、连接管理机制【保证可靠性传输的机制】3.1建立连接(TCP三次握手)---经典面试题3.2断开连接(四次挥手)3.3TCP状态转换 四…

车载电子电器架构 —— 如何理解和使用Update bit

车载电子电器架构 —— 如何理解和使用Update bit 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不…

RabbitMQ(Docker 单机部署)

序言 本文给大家介绍如何使用 Docker 单机部署 RabbitMQ 并与 SpringBoot 整合使用。 一、部署流程 拉取镜像 docker pull rabbitmq:3-management镜像拉取成功之后使用下面命令启动 rabbitmq 容器 docker run \# 指定用户名-e RABBITMQ_DEFAULT_USERusername \# 指定密码-e R…

C++学习--点滴记录011

11函数提高 11.1 函数默认参数 在C中&#xff0c;函数的形参列表中的形参可以有默认值 语法&#xff1a; 返回值类型 函数名 &#xff08;参数 默认值&#xff09;{} 示例&#xff1a; #include <iostream> using namespace std;int func(int a, int b 10, int c …

IoTDB 入门教程 基础篇③——基于Linux系统快速安装启动和上手

文章目录 一、前文二、下载三、解压四、上传五、启动六、执行七、停止八、参考 一、前文 IoTDB入门教程——导读 二、下载 下载二进制可运行程序&#xff1a;https://dlcdn.apache.org/iotdb/1.3.1/apache-iotdb-1.3.1-all-bin.zip 历史版本下载&#xff1a;https://archive.…

springboot 集成 flowable

随着企业对于业务流程管理需求的增加&#xff0c;流程引擎在企业信息化建设中的作用越来越重要。Flowable是一个开源的轻量级业务流程管理&#xff08;BPM&#xff09;和工作流引擎&#xff0c;它支持BPMN 2.0标准。 Flowable的一些特点&#xff1a; 安装集成&#xff1a;Flow…

每日一题(AL001):A+B Format--字符串处理

找输出的顺序很重要&#xff1a; #include<bits/stdc.h> using namespace std; int main(){int a,b;cin>>a>>b;int sumab;if(sum0) cout<<0;bool ftrue;vector<char> v;if(sum<0) {ffalse; sum-sum;}while(sum>0){char cstatic_cast<c…

Redis之Stream流

reidis为了抢占市场份额&#xff0c;推出了自己的消息队列&#xff0c;Stream流&#xff0c; 常用操作如下&#xff1a; xadd name id值 key value key1 value1...&#xff1a;若不存在为name的stream流&#xff0c;则创建一个新的名为name的stream流。这里id相当于数据库中的…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录各章片段 1

以下摘录一些章节片段&#xff1a; 1. 概论 自动驾驶系统的认知中有一些模糊的地方&#xff0c;比如自动驾驶系统如何定义的问题&#xff0c;自动驾驶的研发为什么会有那么多的子模块&#xff0c;怎么才算自动驾驶落地等等。本章想先给读者一个概括介绍&#xff0c;了解自动驾…

R语言中,查看经安装的包,查看已经加载的包,查看特定包是否已经安装,安装包,更新包,卸载包

创建于&#xff1a;2024.5.4 R语言中&#xff0c;查看经安装的包&#xff0c;查看已经加载的包&#xff0c;查看特定包是否已经安装&#xff0c;安装包&#xff0c;更新包&#xff0c;卸载包 文章目录 1. 查看经安装的包2. 查看已经加载的包3. 查看特定包是否已经安装4. 安装包…

【netty系列-03】深入理解NIO的基本原理和底层实现(详解)

Netty系列整体栏目 内容链接地址【一】深入理解网络通信基本原理和tcp/ip协议https://zhenghuisheng.blog.csdn.net/article/details/136359640【二】深入理解Socket本质和BIOhttps://zhenghuisheng.blog.csdn.net/article/details/136549478【三】深入理解NIO的基本原理和底层…

B树与B+树

B树定义 每个节点最多有m-1个关键字&#xff08;可以存有的键值对&#xff0c;m表示树的高度&#xff09;根节点最少可以只有1个关键字非根节点至少有m/2个关键字每个节点中的关键字都按照从小到大的顺序排列&#xff0c;每个关键字的左子树中的所有关键字都小于它&#xff0c…

如何将 redis 快速部署为 docker 容器?

部署 Redis 作为 Docker 容器是一种快速、灵活且可重复使用的方式&#xff0c;特别适合开发、测试和部署环境。本文将详细介绍如何将 Redis 部署为 Docker 容器&#xff0c;包括 Docker 安装、Redis 容器配置、数据持久化、网络设置等方面。 步骤 1&#xff1a;安装 Docker 首…

JavaEE 多线程详细讲解(1)

1.线程是什么 &#xff08;shift F6&#xff09;改类名 1.1.并发编程是什么 &#xff08;1&#xff09;当前的CPU&#xff0c;都是多核心CPU &#xff08;2&#xff09;需要一些特定的编程技巧&#xff0c;把要完成的仍无&#xff0c;拆解成多个部分&#xff0c;并且分别让…

中国打造成熟工艺产能,台积电力推先进工艺,反杀成功了!

分析机构指出2023年Q4全球芯片市场28纳米及以上工艺芯片占比在快速下降&#xff0c;已跌穿五成&#xff0c;这主要是台积电力推芯片企业向先进工艺发展&#xff0c;与中国大陆打造的成熟工艺芯片抗衡。 分析机构指出2023年Q4全球芯片以工艺划分&#xff0c;28纳米及以上工艺的芯…

考研入门55问---基础知识篇

考研入门55问---基础知识篇 01 &#xff1e;什么是研究生入学考试&#xff1f; 研究生是指大专和本科之后的深造课程。以研究生为最高学历, 研究生毕业后&#xff0c;也可称研究生&#xff0c;含义为研究生学历的人。在中国大陆地区&#xff0c;普通民众一般也将硕士毕业生称…

[入门] Unity Shader前置知识(5) —— 向量的运算

在Unity中&#xff0c;向量无处不在&#xff0c;我想很多人都使用过向量类的内置方法 normalized() 吧&#xff0c;我们都知道该方法是将其向量归一化从而作为一个方向与速度相乘&#xff0c;以达到角色朝任一方向移动时速度都相等的效果&#xff0c;但内部具体是如何将该向量进…