当前位置: 首页 > article >正文

linux网络 | 传输层TCP | 认识tcp报头字段与分离

        前言: 本节内容继续传输层的讲解, 本节讲解的是tcp协议。 tcp协议是我们日常中最常用的协议。就比如我们浏览网页,我们知道网页时http或者https协议。 其实http或者https底层就是用的tcp协议。tcp协议,全名又称为传输控制协议,Translation Control protocol。现在为话不多说, 开始我们的学习吧!

        ps:关于讲解tcp, 仍旧采取和udp同样的策略。 先讨论tcp的报头和有效载荷如何分离, 然后讨论报头里面的内容, 最后是tcp的相关知识点。 本节内容是进入传输层tcp的第一节内容, 没有前置知识点, 友友们只要使用过tcp的socket相关接口就可以学习哦!

目录

为什么叫做TCP(传输控制协议)

TCP报头分离

十六位窗口大小 

流量控制

确认应答机制 

十六位窗口控件 

32位序号和32位确认序号  

捎带应答 

超时重传

32位序号 

32位确认序号 

为什么要有两种序号


为什么叫做TCP(传输控制协议)

        

        tcp协议在操作系统内部有一个叫做发送缓冲区,一个叫做接收缓冲区。然后平时我们在写代码的时候,我们自己在上层写的缓冲区,叫做用户缓冲区。

        我们平时使用的write,rev,read,send这些,本质上不是发送函数,而是拷贝函数。是将用户级缓冲区里面的内容,拷贝到内存级缓中区里面。至于数据什么时候发送,发送多少,出错了怎么办,由TCP协议自主决定。 这个就是自主控制,又因为它在传输层是来传输的, 所以就是传输控制。 

        这个知识点,就和我们之前学习文件是一样的,我们之前使用write,等接口,本质上就是把数据拷贝到内核的文件缓冲区里面。至于这个数据什么时候刷,刷多少,出错了怎么办,是由内核决定的。所以,从今天来看,磁盘和网络没有区别,只是将磁盘设备换成了网卡,就可以完成数据的IO,文件是IO,网络也是IO。下面这张图, 就是整个的传输控制过程:

        这里有个小的点就是关于全双工:tcp无论是客户端,还是服务端都能够接收和发送,这个过程,就叫做全双工。

TCP报头分离

        下面是整个的TCP报文。 

        十六位源端口号和十六位目的端口号,就知道我们要把数据交给哪个主机。

        标准报头是固定大小,固定20个字节。所以拿20个字节就是把标准报头全部拿到了。这个时候,就能拿到里面的一个字段:4位首部长度,标识报头的总长度是多少(标准 + 选项)。 四位首部长度长度最大范围是[0000, 1111], 也就是[0, 15]。 单位是4,也就是说, 四位首部长度的范围是[0, 60]。 所以, tcp报头最多是60字节, 标准占20, 所以选项最多就是40个。

        如果我们不谈选项,这个四位首部长度x * 4 = 20 ==> x = 5;也就是说0101, 那么四位首部长度最少就是0101。 最多是1111。另外,这里这个四位首部长度, 我们可以叫他自描述字段。 

        所以, 如何分离报头和报文, 就是:固定长度 + 自描述字段。

十六位窗口大小 

        我们第一个要谈的报头信息是十六位窗口大小。

        先说结论, 这个十六位窗口大小填写的是自己的接收缓冲区的大小。 

        为什么要有这个十六位窗口大小? 这个就涉及到了两个其他的知识点。 一个是‘流量控制’, 一个是‘确认应答’。下面我们来看一下这两个知识点:

流量控制

首先看一下流量控制

        首先我们先看一下客户端和服务端的报文交互:

        对于客户端和服务端来讲, 双方的任何通信, 都要有完整的报头, 就比如客户端发送一个你好,就要添加上完整的报头, 然后你好作为数据。 发送给服务端, 然后就写入了服务端的接收缓冲区。 服务端发送给客户端同样如此, 都是写入到客户端的接收缓冲区。

        但是, 有一个问题,我们的客户端向服务端发送请求的时候, 如果客户端请求发送的很快,服务端请求拿的很慢, 或者根本就不拿。 那么是不是就总是有一刻服务端的接收缓冲区被打满?服务端的接收缓冲区一旦被打满, 客户端如果再向服务端发送数据, 那么这些数据就写不进去, 就一定会出现大面积丢包的情况。所以, 客户端就要有手段能够降低发送请求的速度或者干脆不发了, 这种手段, 就叫做流量控制!!!

确认应答机制 

        什么是确认应答,就比如我们在和朋友在微信上面现天我们对我们的用友说,吃饭了吗。我们的朋友如果看到了,就会说:吃了。我们看到"吃了“,我们就知道对方看到了我们的消息,这就是确认应答。

        所以,确认应答机制, 就是:客户端向服务器发送任何请求、消息的时候,服务器都要向客户端进行响应。这样客户端就能保证,客户端到服务器方向的可靠性。相反,服务器向客户端发送的任何请求,客户端都响应,就能保证服务器到客户端方向的可靠性。

十六位窗口控件 

        客户端流量控制,发送的慢一点,依据是什么?对于发送方来说,发送的速度是由对方的接收缓冲区中剩余空间的大小来决定。问题是,我怎么知道对方的接收缓冲区中剩余的空间大小呢?别忘了,我们的tp是基于确认应答机制的,我们给服务端发送一个信息,对方就要返回给我们一个响应。对方给我们的响应里面又是包含完整的报头的! 报头里面又有一个16位窗口大小! 所以,这个16位窗口大小,填充的就是自身的接收缓冲区的剩余空间的大小!!! 

        所以, 下一个定义:16位窗口大小,填写的是自己的接收缓冲区中的大小!!  

32位序号和32位确认序号  

        在正式讲解这个报头字段之前先讨论两个小知识点:捎带应答和超时重传。

捎带应答 

什么是捎带应答,就是C或者S发了应答,又要发送tcp数据的时候,不再发送两次了,而是合成一份发送,这种情况下就叫做捎带应答。

        就类似于我们平时说话,你说吃了吗,朋友说吃了, 你吃了吗。 这种情况就是朋友将应答”吃了“和tcp数据”你吃了吗“合在了一起。即为捎带应答。

        另外一个知识点就是超时重传。

超时重传

        下面是tcp最基本, 最原本的通信过程:

        上面这种,一端发送数据,另一方进行应答。双方都发送数据,双方都进行应答,就能保证两个方向上的可靠性。
        另外,对于双方来说,如何确认一条消息对方没有收到呢?难道要一直等着对方的应答吗? 要知道,如果确认到对方没有收到应答后,就应该重传数据了。 所以一直等待对方的应答是不合理的。所以,一段时间后,如果没有收到应答,双方就会认为数据丢失,就要重新发送数据。——即为,超时重传。

 

32位序号 

        先来思考一下,世界上存不存在100%可靠的网络协议? 

        确认应答机制,有一个现象,就是我收到了应答,那么我就能保证应答之前的最新的发送的消息是被对方收到了。没有应答的数据,我们无法保证可靠性。
        所以,最新的一条消息,是没有应答的。在人类世界里,我们无法保证发送出去的消息是100%可靠的!所以,从全局的角度上,我们这个世界上是不存在100%可靠的协议的但是能保证局部上的消息的可靠性(最新消息之前的消息的可靠性。)

        一个发送,一个应答,效率是非常低下的。通常我们的客户端向服务器发消息,一次是发一批消息。

 

        但是, 这里有一个问题, 我们的服务器按顺序把它发出,服务器是否按顺序把它接受呢?

        就像一开始一群人在东北,现在要去广东。是否到达广东的顺序就是这群人离开东北的顺序呢。答案是不是的,有些人是坐飞机过去,有些人坐火车过去,有些人坐客车过去。有些人可能虽然出发的比较晚,但是人家是做飞机过去的,有些人虽然出发比较早,但是他是坐或者过去的。坐飞机的就有可能比坐火车的先到目的地。 

        所以,服务器按顺序发出信息,并不一定是按照顺序接收到。 这就导致了一个问题一一数据包乱序问题。

        乱序本身就是不可靠的一种,所以,每一个tcp报头里,会包含一个序号的东西一就是这个32位序号。这个32位序号,就是保证数据的按序到达。

         下面就是32位序号: 

32位确认序号 

        假如我今天一次给对方发送了多个报文,那么对方一定也要给我多个响应。我怎么知道响应对应的是哪一个报文呢?

        所以tcp为了区分响应对应的是哪一个报文的响应,就有了32位确认序号的概念。
        确认序号,填充的是,收到报文的序号 +1。
        为什么要这么规定,确认序号的意义: 表示确认序号之前的数据,我已经全部收到了!!!
        下一次发送请从确认序号指定的数字开始发送、就是说,客户端发送的序号是1000,那么服务端响应的序号就得是1001。
        这样做的意义是什么?
        这样做是为了允许应答有少量的丢失、就发送的数有100,200,300,那应只有3001,但是没有10012001但是不需要重传,默认就认为3001%前的报文全都响应了。

为什么要有两种序号

        我们知道,请求是有数据的,用的是32位序号,然后响应是没有数据的,用的是32位确认序号。但是,为什么不直接只使用32位序号或者32位确认序号呢?为什么非要用两种序号呢?
        原因就在于客户端给服务器发消息,服务器要给我应答,服务器应答,可能只是应答,也可能是指捎带应答。应答就是纯报头,只是用32位确认序号,捎带应答就是要有数据,并且捎带应答因为也有数据,所以就要有32位序号。也就是说,因为一个报文,他可能有双重身份,既可能是应答,也可能是带有数据,所以序号和确认序号有可能同时存在,所以协议里面必须把这两个分开,不能复用。 

 

  ——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!!   


http://www.kler.cn/a/515755.html

相关文章:

  • RabbitMQ 在实际应用时要注意的问题
  • Apache Hive3定位表并更改其位置
  • 运算放大器应用电路设计笔记(六)
  • 【网络协议】【http】【https】TLS解决了HTTP存在的问题-加密通信+摘要,数字签名+CA证书
  • 纯前端实现表格中的数据导出功能-使用xlsx和file-saver
  • Axios HTTP库基础教程:从安装到GET与POST请求的实现
  • 心法利器[127] | 24年算法思考-特征工程和经典深度学习
  • 【计算机网络】- 应用层HTTP协议
  • JavaScript —— 输入与输出
  • Java TCP可靠传输(1)
  • 简识JVM栈帧中的操作数栈
  • Postgres与MySQL对比
  • 基于微信小程序的优购电商系统设计与实现(LW+源码+讲解)
  • flask常见问答题
  • 【华为交换的vlan配置】
  • C#语言的区块链
  • 基于51单片机和ESP8266(01S)、八位数码管、独立按键的WiFi定时器时钟
  • IDEA运行Java项目总会报程序包xxx不存在
  • MMDetection学习系列(5)——Mask R-CNN深度探索与实战指南
  • 如何“看到” Spring 容器?
  • pytorch torch.vmap函数介绍
  • 爬虫工程师视角:如何确保电商平台API稳定性的策略与实践?
  • View Shadcn UI 2025.1.2 发布公告:全新跑马灯组件与多项优化更新
  • 什么是Memecoin?它如何在加密货币世界崭露头角
  • MySQL为什么使用B+树?B+树和B树的区别
  • 【论文笔记】TranSplat:深度refine的camera-required可泛化稀疏方法