TCP/IP详解(一)
TCP/IP协议是Internet互联网最基本的协议,其在一定程度上参考了七层OSI(Open System Interconnect,即开放式系统互联)模型
OSI参考模型是国际组织ISO在1985年发布的网络互联模型,目的是为了让所有公司使用统一的规范来控制网络,让所有的公司遵循相同的通信规范,使网络能够互联互通;
OSI模型定义了网络互联的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层),每一层实现各自的功能协议,并完成与相邻层的接口通信。
在TCP/IP
协议中,OSI
的7层被简化为4层,分别是链路层(也称为数据链路层或网络接口层)、网络层、传输层、应用层;
应用层协议:HTTP
、Telnet
、SMTP
、FTP
、DNS
等;主要是为了接收来自传输层的消息,或将数据传输写入传输层;
传输层协议:TCP
、UDP
等;主要是为了实现端对端的数据传输、传输服务分为可靠(TCP
)与不可靠(UDP
)、为端到端提供流量控制、差错控制、QoS
(Quality of Service);
网络层协议:IP
、ICMP
(Internet Control Message Protocol)、IGMP(Internet Group Management Protocol,网络群组管理协议)等;主要是为了网络中的数据包传送;
链路层协议(又称为数据链路层或网络接口层):ARP
(地址解析协议)、RARP
(逆地址解析协议)等;通常包括操作系统中的设备驱动程序或计算机中对应的网络接口卡,它们一起处理与传输媒介(如电缆或其它物理设备)的物理接口细节;
每一层协议的作用
物理层:使用MAC地址解决设备身份问题;
通信工具的演变史:单根或多跟网线、集线器、交换机、路由器
单根或多跟网线:用一根网线将两台电脑连接起来就可以进行通信,至于它们为什么能够进行通信,这就涉及到操作系统方面的知识,大家有兴趣可以去了解一下IO
、中断、缓冲区、以及网卡是如何转换成电信号等,或者后面我在整理一下这方面的知识。
集线器:随着越来越多的电脑设备加入,每台电脑上需要开的网口会越来越多,但是一台电脑所开的网口有限,不可能无限增加网口,于是就出现了集线器,即中间器。将每一台电脑的网线插入这个集线器,由这个设备进行转发,这样每台设备就可以彼此进行通信。这种集线器的通信模式本质上与单根或多根网线的通信方式是一样的,只是每台电脑的网口数量减少了。
集线器仅仅是电脑将电信号转发到所有出口(广播),对转发消息不做任何处理。如,在A向B发送数据时,只需要在数据包头部提供源MAC地址和目标MAC地址,当B收到数据包后,只需根据数据包头部的目标MAC地址判断是否是发送给自己的,而其它设备在收到数据包后,也是一样通过从数据包头部的目标MAC地址判断是否发送给自己的,如果目标MAC地址与自己的MAC
地址不一致,便丢弃该数据包。
虽然集线器使整个布局变得简洁,但是从A发到B的数据,会将数据包发给所有连接该集线器的设备,容易造成数据的安全性问题,而且也容易浪费网络资源。
那么,假如是否存在一种设备,能够将数据只发送给B设备呢?
交换机:为了解决集线器的问题,将消息只发送给目标MAC
地址所指向的设备,该设备放在数据链路层。
交换机内部维护着一张MAC
地址表,记录着每一台设备的MAC地址,同时也记录着该设备连接在哪一个端口上。假设A设备发送数据到B设备,当数据包到达交换机时,交换机通过查内部维护的MAC地址表,发现B设备的MAC地址为XXXX,在1号端口上,于是交换机将数据包从1号端口发送到B设备,通过这种传输方式而组成的小范围网络,我们称之为以太网。
当然,MAC
地址表刚开始建立时是空的,当你向B设备发送消息时,A设备的消息从端口1发出,此时交换机将A设备的MAC
地址和端口号记录到交换机内部映射表中,当交换机在内部映射表中查不到B设备的MAC
地址和端口号时,会将此数据包发送给所有端口,即发给了所有设备,当只有机器B收到数据是发送给自己时,于是做出响应,响应码从3号端口发出进入交换机,此时交换机会在MAC
地址表中更新B设备的MAC地址和端口。当该网络中的机器不断通信时,交换机中的MAC
地址表会不断完善。
但是,随着网络中的设备数量越来越多,交换机内部需要维护的MAC地址数量也越来越多,交换机的端口数量会出现不足。
此时交换机已经无法满足如此庞大的映射关系。
路由器:作为一台独立的拥有MAC
地址的设备,并且可以把数据包做一次转发(注意:路由器的每个端口都拥有独立的MAC
地址);路由器是属于网络层。路由器专门负责IP
地址的寻找。
有了路由器,自然而然就诞生了IP
地址,IP
地址长度为32位,而MAC
地址长度为48位;
当A设备与C设备不在同一个子网时,A设备会将数据包发送给路由器,然后由路由器进行转发;
但是,A设备是怎么知道和C设备不在同一个子网,以及A如何知道那台设备是路由器?
这时就诞生了子网和网关
子网得由来:
A给C发送数据,怎么知道是否要通过路由器进行转发?答案是通过子网
目的IP和源IP处于同一个子网,直接通过交换机进行转发;
目的IP和源IP不处于同一个子网,就交给路由器去进行处理;
假入某台子网掩码定义为255.255.255.0
将源IP和目的IP分别与这个子网掩码进行与运算,相等则是在一个子网,不相等就是在不同的子网。例如,对于192.168.0.1来说,192.168.0.xxx就算是在一个子网,否则就是在不同子网。
比如:
A电脑:192.168.0.1&255.255.255.0 = 192.168.0.0
B电脑:192.168.0.3&255.255.255.0 = 192.168.0.0
C电脑:192.168.2.1&255.255.255.0 = 192.168.2.0
D电脑:192.168.2.6&255.255.255.0 = 192.168.2.0
那么A与B在同一个子网,C与D在同一个子网,但是A与C和D不在同一个子网;
默认网关(如192.168.0.254),当A与C不在一个子网时,A会将包发送到同一子网下的默认网关,至于是那台设备,A不在关心,只需发出即可。
子网掩码其实就是表示前多少位为子网网段,如192.168.0.0(255.255.255.0),可以简写为192.168.0.0/24;
当A向C传输数据时,除了加上数据链路层的头部之外,还要在增加一个网络层的头部;
A发送给路由器的信息如下:
路由器发送给C的信息如下:
至于上述过程的发送流程为什么是这样,与前面讲到的子网有关系,理解了子网的概念,就明白了A到C的发送过程;
至于路由器怎么知道收到的这个数据包该从自己的那个端口出去呢?
答案是路由器中也维护着一张路由表,与MAC地址表一样。不同于MAC地址的是,路由表并不是一对一的确定关系;
由于子网掩码其实就是表示前多少位表示子网网段,如192.168.0.0(255.255.255.0)也可以简写为192.168.0.0/24;
于是,路由表就表示,192.168.0.XXX的都发送到0好端口,192.168.1.XXX的都发送到1号端口,上图中下一跳暂时没有值,可以先忽略;
这样我们从A发送到C的数据,就能够正常发出;
但是,现在又有一个问题,发送数据还需要数据链路层的包,而我们只知道IP地址,数据是怎么发送出去的呢?
答案是ARP协议,在网络层中,通过IP地址找到对应设备的MAC地址,同时电脑A和C都会缓存一张ARP缓存表,记录着IP与MAC地址的对应关系;
刚开始的时候,ARP缓存表是空的,A为了知道C的MAC地址,将会广播一条ARP请求,C收到该请求后,将会发送自己的MAC地址和响应码,A收到后便更新了自己的ARP缓存表。
通过这种方式不断的进行广播ARP
请求,最终电脑里面的ARP缓存表都将会更新完整;
上面讲到的MAC
地址表、路由表、ARP
缓存表,这三张表是怎么来的呢?
MAC
地址表:以太网内各节点之间不断通过交换机通信,逐步进行完善;用于映射MAC
地址和它的端口号;
路由表:路由算法+人工配置逐步完善;用于映射IP地址和它的端口号;
ARP
缓存表:通过ARP
协议广播请求逐步完善;电脑和路由器中都有ARP缓存表,用于IP
地址和MAC
地址的映射关系;
HTTP
报文传输原理
利用TCP/IP
进行网络通信时,数据包会按照分层顺序与对方进行通信。发送端从应用层往下走,接收端从链路层往上走。从客户端到服务端的数据,每一帧的数据传输顺序为:应用层–>传输层–>网络层–>链路层–>链路层–>网络层–>传输层–>应用层;
TCP
协议的报文格式
在TCP/IP
协议栈中,IP
协议层只关心如何使数据传输跨越本地网络的边界问题,而不关心数据是如何传输。整体的TCP/IP
协议栈,共同配合解决数据如何通过许多个点对点通路,顺利传输到达目的地。一个点对点通路被称为一跳(hop),通过TCP/IP
协议栈,网络成员能够在许多“跳”的基础上建立相互的数据通路。
传输层TCP协议提供一种面向连接的,可靠的字节流服务,其数据帧格式如下图所示:
TCP协议的数据帧,大致分为以下几个部分:
源端口:源端口表示报文的发送端口,占16位。源端口和IP地址组合起来,可以标识报文的发送地址;
目的端口:目的端口表示报文的接收端口,占16位。目的端口和IP地址组合起来,可以标识报文的接收地址;
序号:TCP
传输过程中,发送端发出的字节流中,传输报文的数据部分的每一个字节都有它的编号。序号占用32位,即4个字节,发送方发送数据时,都需要标记序号。
序号与SYN
控制标志的值相关,根据控制标志中的SYN
是否为1,序号表达的含义不同:
(1)当SYN
=1时,当前为连接建立阶段,此时的序号为初始序号ISN
,通过算法来随机生成序号;
(2)当SYN
=0时,在数据传输开始时,第一个报文的序号为ISN+1
,后面的报文序号为前一个报文的SN
值+TCP
报文的净字节数(不包含TCP头)。例如,如果发送端发送的一个TCP
帧的净荷为16byte,序号为6,则发送端在发送下一个数据包时,序号应设置为:16 + 6 = 22;
在数据传输过程中,TCP
协议通过序号对上层提供有序的数据流。发送端可以根据序号来跟踪发送的数据量,接收端可以根据序号来识别重复的TCP
包,从而将重复的TCP
包丢弃,对于乱序的数据包,接收端可以根据序号进行排序。
确认序号:标识报文接收端期望接收的字节序列。如果设置了ACK
控制位,确认序号的值表示一个准备接收的包的序列码,它所指向的是准备接收的数据包,也就是下一个期望接收的包的序列码;
假设发送端发送6个净荷为1024byte
,起始SN号为1的数据包给服务端,服务端每收到一个包之后,需要回复一个ACK
响应,确认数据包给发送端,ACK响应数据包的ACK值为每个发送端包的SN
+包净荷,表示服务端已经接收到的字节数,还表示期望收到下一个发送端发送数据包的SN序号。
只有控制标志的ACK
标志为1时,数据帧中的确认序号ACK
序号才有效。TCP
协议规定,在建立连接后,所有发送报文的ACK
值必须为1,所有报文的确认序号有效。如果是SYN类型的报文,ACK
标志为0,没有确认序号。
头部长度:该字段占用4位,用来表示TCP
报文的首部长度;其值所表示的并不是字节数,而是头部的所含有的32bit的数目(或者倍数),或者4个字节的倍数,所以TCP头部最多可以有60字节(4*15=60)。没有任何选项字段的TCP
头部长度为20字节,所以其头部长度为5,可以通过20/4=5计算得到。
预留6为:头部长度后面预留的字段长度为6位,作为保留字段,暂时没有什么用处。
控制标志:控制标志(Control Bits)共6个bit位,具体的标志位为:URG、ACK、PSH、RST、SYN、FIN
。
窗口:长度为16为,共2个字节。此字段用来进行流量控制,流量控制的单位为字节数,表示接收方一次希望收到的字节数;
校验和:长度为16位,共2个字节。对整个TCP
报文段和数据进行校验和计算,接收端用于对收到的数据包进行验证;
紧急指针:长度为16为,共2个字节。它是一个偏移量,与SN
序号值相加表示紧急数据最后一个字节的序号;
以上是TCP
协议报文首部必须需要的字段,也称固有字段,长度为20个字节,后面的为TCP
报文的可选项和填充项,以及数据位。
暂时先写到这里,内容太多,一次讲不完,下次再继续更新。
相关文章:

TCP/IP详解(一)
TCP/IP协议是Internet互联网最基本的协议,其在一定程度上参考了七层OSI(Open System Interconnect,即开放式系统互联)模型 OSI参考模型是国际组织ISO在1985年发布的网络互联模型,目的是为了让所有公司使用统一的规范来…...

three.js的学习
Threejs 1 前言 Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。 既然Threejs是一款WebGL三维引擎,那么它可以用来做什么想必你一定很关心。所以接下来内容会展示大量基于…...

Spark
Spark 概述 Apache Spark是用于大规模数据处理的统一分析计算引擎 Spark基于内存计算,提高了在大数据环境下数据处理的实时性,同时保证了高容错性和高可伸缩性,允许用户将Spark部署在大量硬件之上,形成集群。 spark与Hadoop的…...

poi生成excel饼图设置颜色
效果 实现 import com.gideon.entity.ChartPosition; import com.gideon.entity.LineChart; import com.gideon.entity.PieChart; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xddf.usermodel.PresetColo…...

多版本管理node.js
多版本管理node.js 1. 安装2. 配置使用2.1 修改node源2.2 常用命令 在Windows 计算机上管理node.js的多个安装版本。 这是朋友推荐的,就是自己在升级node的时候给搞崩了, 不得不提升效率,于是发现了这个好工具,可以反过来理解&…...

【深入浅出 Spring Security(七)】RememberMe的实现原理详讲
RememberMe 的实现原理 一、RememberMe 的基本使用二、RememberMeAuthenticationFilter 源码分析RememberMeServicesTokenBasedRememberMeServicesTokenBasedRememberMeServices 中对 processAutoLoginCookie 方法的实现总结原理图式 三、提高安全性PersistentTokenBasedRememb…...

Cesium 实战 - 使用 gltf-vscode 查看、预览以及编辑 glTF 和 GLB 模型
Cesium 实战 - 使用 gltf-vscode 查看、预览以及编辑 glTF 和 GLB 模型 VScode(Visual Studio Code) 安装模型必要插件VScode 预览自定义关节(articulations)动作VScode 导入 GLB 格式模型VScode 导出 GLB 格式模型 模型渲染作为 …...

Python自动化测试框架:Pytest和Unittest的区别
pytest和unittest是Python中常用的两种测试框架,它们都可以用来编写和执行测试用例,但两者在很多方面都有所不同。本文将从不同的角度来论述这些区别,以帮助大家更好地理解pytest和unittest。 1. 原理 pytest是基于Python的assert语句和Pytho…...

考研算法29天:希尔排序 【希尔排序】
算法介绍 希尔排序 等差数列 普通版插入排序 循环数组 第一次每n/2为间隔分为4组,然后组内排序。 第二次每n/4为间隔分为2组。然后组内排序 第三次n/8为间隔分为一组。然后组内排序。 组内排序用插入排序来排序。 注:也可以第一次为n/3为间隔&am…...

RN 学习小记之使用 Expo 创建项目
本文Hexo博客链接🔗 https://ysx.cosine.ren/react-native-note-1 xLog链接🔗 https://x.cosine.ren/react-native-note-1 RSS订阅 📢 https://x.cosine.ren/feed/xml 由于业务需要,开始学习RN以备后面的需求,而虽然之…...

python爬虫从入门到精通
目录 一、正确认识Python爬虫 二、了解爬虫的本质 1. 熟悉Python编程 2. 了解HTML 3. 了解网络爬虫的基本原理 4. 学习使用Python爬虫库 三、了解非结构化数据的存储 1. 本地文件 2. 数据库 四、掌握各种技巧,应对特殊网站的反爬措施 1. User-Agent 2. C…...

从0到1精通自动化,接口自动化测试——数据驱动DDT实战
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 DDT简介 名称&am…...

【微服务】springboot整合swagger多种模式使用详解
目录 一、前言 1.1 编写API文档 1.2 使用一些在线调试工具 1.3 postman 1.4 swagger 二、swagger简介</...

AI 绘画(1):生成一个图片的标准流程
文章目录 文章回顾感谢人员生成一个图片的标准流程前期准备,以文生图为例去C站下载你需要的绘画模型导入参数导入生成结果?可能是BUG事后处理 图生图如何高度贴合原图火柴人转角色 涂鸦局部重绘 Ai绘画公约 文章回顾 AI 绘画(0)&…...

CPU、内存、缓存的关系
术语解释 (1)CPU(Central Processing Unit) 中央处理器 (2)内存 内存用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。它是外存与CPU进行沟通的桥梁,内存的运行决定…...
AI黑客松近期比赛清单;36氪AI淘宝店盈利复盘;GitHub Copilot官方最佳实践;AI在HR领域的应用探索 | ShowMeAI日报
👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! ⋙ 点击查看 AI Hackathon (黑客马拉松) 汇总清单 🤖 〖飞桨〗2023大模型应用创新挑战赛 百度飞桨联合上海市青年五十人创新创业研究院等…...

想要让视频素材格式快速调整转换的方法分享
有时候有些视频播放软件不支持播放某些格式的视频文件?那要怎么解决呢?换一个播放软件?不妨试试批量转换视频格式,简单的几步操作就能快速解决烦恼,跟着小编一起来看看具体的操作环节吧。 首先先进入“固乔科技”的官网…...

面向对象分析与设计 UML2.0 学习笔记
一、认识UML UML-Unified Modeling Language 统一建模语言,又称标准建模语言。是用来对软件密集系统进行可视化建模的一种语言。UML的定义包括UML语义和UML表示法两个元素。 UML是在开发阶段,说明、可视化、构建和书写一个面向对象软件密集系统的制品的…...

[数据库系统] 五、数据增删改
第一关:数据插入 用insert给数据库添加数据 相关知识 有关系student(sno,sname,ssex,sage,sdept),属性对应含义:学号,姓名,性别,所在系。现有的部分元组如下所示 insert 向数据库表插入数据的基本格式有…...

docker私有注册表创建和使用
说明 本文给出了一个具体的使用docker registry和nginx配置docker私有注册表的方案。 创建和配置 docker compose 使用docker compose的方式运行registry容器,配置如下: # cat docker-compose.yml services:registry:image: registry:2ports:- &quo…...

用OpenCV进行OCR字符分割
1. 引言 本文重点介绍如何利用传统的图像处理的方法来进行OCR字符切分,进而可以用分割后的单个字符做相应的后续任务,虽然现在计算机视觉依然是卷积神经网络的天下,但是对于一些相对简单的落地场景传统方案还是很有效的。 闲话少说ÿ…...

MyCat Docker 搭建与测试
mycat 是mysql分库分表的中间件,由java编写,本次进行mysql、mycat 的docker搭建,理解mycat的原理与特性。 一、mysql docker 搭建 这里启动两个实例: docker run -itd --name mysql1 -p 3307:3306 -e MYSQL_ROOT_PASSWORD123 m…...

车载通讯USB开发,增强车内娱乐体验
车载通讯开发中使用的 USB 协议常见于车内娱乐系统、车载设备和汽车诊断工具等应用。USB(Universal Serial Bus,通用串行总线)是一种常见的数字通信接口标准,用于连接计算机、外部设备及其他电子设备之间的数据传输和通信。 USB …...

js的一些小技巧
大厂面试题分享 面试题库 前后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 web前端面试题库 VS java后端面试题库大全 作用域 全局作用域局部作用域(函数里)也称函数作用域块级作用域 {…...

Springboot Mybatis 自定义顺序排序查询,指定某个字段
前言 与本文无关 "我进去了" ....... 正文 今天要讲些什么? 其实很简单,就是查询数据的时候,想根据自己指定的字段的自定义顺序,做排序查询数据。 本篇文章会讲到的几个点 : 1. 单纯sql 怎么实现 排序2. …...

期刊会议审稿意见
AAAI 修改意见 违背了研究方向的假设;虽然实验结果不错,但是没有明确地指向任何成功的方向,作者也没有充分地处理失败的案例——The results, though good are not clearly pointing to any direction of success, and the authors have no…...

Java类加载机制:从字节码到对象的奇妙之旅
目录 什么是类加载机制? 类加载顺序 类加载顺序图 双亲委派模型 双亲委派模型示意图 如何打破双亲委派模型? 要想学好java,首先得知道它是什么,怎么运行的,怎么加载的,运行的是个什么东西,…...

代码随想录第一天|二分法、双指针
代码随想录第一天 Leetcode 704 二分查找Leetcode 35 搜索插入位置Leetcode 34 在排序数组中查找元素的第一个和最后一个位置Leetcode 69 x 的平方根Leetcode 367 有效的完全平方数Leetcode 27 移除元素Leetcode 26 删除有序数组中的重复项Leetcode 283 移动零Leetcode 844 比较…...

Flink中KeyedStateStore实现--怎么做到一个Key对应一个State
背景 在Flink中有两种基本的状态:Keyed State和Operator State,Operator State很好理解,一个特定的Operator算子共享同一个state,这是实现层面很好做到的。 但是 Keyed State 是怎么实现的?一般来说,正常的…...

flex: 0 0 100%;
flex: 0 0 100%; flex: 0 0 100%; 是一个用于设置flex项的flex-grow、flex-shrink和flex-basis属性的缩写flex-grow:指定了flex项在剩余空间中的放大比例,默认为0,表示不放大。在这个例子中,设置为0表示不允许flex项在水平方向上…...