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

news/2024/5/19 4:42:32

目录

  • 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.mrgr.cn/p/22678673

相关文章

IGM焊接机器人RTE 495伺服电机维修详情一览

在当今科技迅速发展的时代,机器人已成为各行各业不可或缺的重要工具。IGM机器人便是其中之一,其工业机械手伺服马达作为机器人的关键部件,确保机器人能够高效、稳定地运行。当出现IGM焊接机器人RTE 495伺服电机故障问题时,及时进行…

魔百盒E900V22D刷机教程

参考:https://www.mydigit.cn/thread-305003-1-1.html https://www.52pojie.cn/forum.php?mod=viewthread&tid=1659478 https://www.znds.com/tv-1241881-1-1.html https://www.znds.com/tv-1241104-1-1.html >之前家里装移动宽带不是送了个机顶盒嘛,之前还一不小心点…

一测知“芯”!芯片测试如何确保电子设备的“心脏”健康?

文章目录 封装:芯片的“铠甲”与“桥梁”测试:芯片质量的“守门员”《芯片封测从入门到精通》亮点内容简介作者简介目录获取方式 在高科技飞速发展的今天,芯片作为电子设备的心脏,承载着计算、控制、存储等核心功能。然而&#xf…

OpenAI下周将发布ChatGPT搜索引擎,挑战谷歌搜索!

目前,多方位消息证实,OpenAI将会在5月9日上午10点公布该消息,大约是北京时间周五的凌晨2点。 5月3日,前Mila研究员、麻省理工讲师Lior S爆料,根据OpenAI最新的SSL证书日志显示,已经创建了search.chatgpt.c…

c++综合实验报告友元

综合性、设计性实验报告 专业:计算机科学与技术 一、实验目的: 1.熟练掌握友元函数和友元类设计的方法 2.掌握友元函数的含义,友元函数和成员函数的区别。 3.掌握友元类的含义。 二、实验仪器或设备:微型计算机 三、总体设计(设计原理、设计方案及流程等) 实验内容: 定…

分层架构上的探索实践

简介 因为身处在应对ToB需求的SAAS行业,复杂的需求在代码上造成的混乱始终是我们的一大困扰,所以我们在一些项目中尝采用整洁架构的分层模式对部分代码做了一些改善和实践。 在这篇文章中我来分享一下我在分层架构上的思考,一些实践方法。 为什么要分层? 我们都知道ToB行业…

Cmake Learn

目录 1 常用命令 (1)configure_file (2).cmake文件 (3) install (4)include_directories (5) add_subdirectory (6) find_libr…

笔记-用Python脚本启停JAR程序

用Python脚本启停JAR程序,需要用到python中的以下内置模块 subprocess 是 Python 的一个标准库模块,用于在新进程中执行子命令,获取子进程的输入/输出/错误以及返回码等os 是 Python 的一个标准库模块,它提供了与操作系统交互的功…

社区版pycharm下载安装教程

参考:韩顺平——下载 在浏览器输入 www.jetbrains.com/进入pycharm官网 指向Developer Tools,点击Pycharm 点击Download 为了更好得跟踪韩老师的教程,我这里选择下载与韩老师一致的版本(对版本无要求的话直接点击download)找到2023.2.2的版本,在PyCharm Community Editio…

嵌入式笔记4.2 USART

目录一、USART 简介二、USART 寄存器详解寄存器基础信息寄存器地址寄存器名称与作用USART 寄存器组简表寄存器详解1. 控制寄存器 1(USART_CR1)2. 控制寄存器 2(USART_CR2)3. 控制寄存器 3(USART_CR3)4. 波特率寄存器(USART_BRR)5. 保护时间和预分频器寄存器(USART_GTP…

嵌入式笔记4.3 异常和中断详解

目录一、异常和中断的简介1. 外设中断处理流程2. 中断处理与异常处理3. 支持的异常和中断数量二、异常类型三、中断管理简介四、优先级定义五、向量表和向量表重定位六、中断输入和挂起行为七、异常流程简介1. 接受异常请求2. 异常进人流程3. 执行异常处理4. 异常返回八、中断控…

学习3:scrapy请求对象、模拟登录、POST请求、管道的使用、crawlspider爬虫类

请求对象 请求对象参数 scrapy.Request(url[],callback,method"GET",headers,body,cookies,meta,dont_filterFalse)callback 表示当前的url响应交给那个函数去处理method 指定请求方式headers 接受一个字典,其中不包括cookiesbody 接收json字符串&#…

数字旅游以科技创新为核心:推动旅游服务的智能化、精准化、个性化,为游客提供更加贴心、专业、高效的旅游服务

目录 一、引言 二、数字旅游以科技创新推动旅游服务智能化 1、智能化技术的应用 2、提升旅游服务的效率和质量 三、数字旅游以科技创新推动旅游服务精准化 1、精准化需求的识别与满足 2、精准化营销与推广 四、数字旅游以科技创新推动旅游服务个性化 1、个性化服务的创…

HTUCTF2024 河南师范大学招新赛

CRYPTO easyMath 题目 中国古代有很多人同名譬如同样叫孙子,有的人会兵法,有的人会数学你能帮我求解出这道题的答案吗?请开启容器后下载对应输出文件难度:简单 from secret import flag from Crypto.Util.number import *def s2n(string):return int(string.encode("u…

2024 年 5 月 1 日 周三 小雨 冷(384 字)

正文祖父见到我和见长,第一句话是好久都没看到我们的孙子了。然后第二句话直接把我们俩都干懵了。“你们有没有阿托品啊?”我第一反应是懵,第二反应是想笑。上哪儿给你找这种处方药去…… 这种 M 受体阻断剂管得还严,严重有机磷中毒的时候,一掰就是几十支。而且这药不是最…

安装库后JupyterLab一直报ModuleNotFoundError问题解决

背景: 先安装的Python3.10,安装在默认路径: C:\Users\#用户名省略#\AppData\Local\Programs\Python\Python310\ 后安装的Anaconda,更改过路径在D盘: D:\ProgramData\anaconda3 此时C盘Python安装路径下Scripts文件…

linux搭建个人博客wordpress(LNMP)

目录 准备阶段: 1.部署LNMP环境 2.配置数据库 3.上线WordPress博客平台 4.来到web界面安装博客平台 5.WordPress博客平台优化 总结: 利用LNMPWordPress搭建博客网站平台 WordPress是一款使用PHP语言开发的博客平台 1.易用性高:操作简单…

linuxI2C驱动核心梳理

参考文章《linux设备驱动开发详解》第15章 【linux iic子系统】i2c整体框图【精髓部分】(五)_bus_for_each_drv-CSDN博客 linux设备驱动程序——i2c总线的添加与实现_如何填充i2c_client-CSDN博客 【linux iic子系统】i2c设备与驱动匹配过程(三)_i2c_add_driver 如何和clen…

Python异步Redis客户端与通用缓存装饰器

前言 这里我将通过 redis-py 简易封装一个异步的Redis客户端,然后主要讲解设计一个支持各种缓存代理(本地内存、Redis等)的缓存装饰器,用于在减少一些不必要的计算、存储层的查询、网络IO等。 具体代码都封装在 HuiDBK/py-tools: …

Java web第五次作业

1.在idea中配置好数据源 2、视频案例中只给出了查询所有结果的示例,请自己完成添加、删除、修改操作的代码。以下供参 考。 Delete("delete from emp where id#{id}") public void delete(Integer id); 测试代码 Test public void testDelete(){ empMa…