ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

网络原理(一)应用层协议、传输层UDP/TCP报文格式解析

网络原理(一)应用层协议、传输层UDP/TCP报文格式解析 前言hello hello这里是洋不写bug~欢迎大家点赞关注收藏前面的博客中已经解析了网络通信的基础知识、TCP/UDP服务器和客户端的代码实现也就是初始网络编程和网络编程一二这三篇博客初学的铁汁建议看完网络编程部分的三篇博客再来看网络原理部分对知识点会更加清晰从这篇博客就会开始解析网络原理是理论上的知识设计代码的部分比较少在网络通信过程中进行调参、排查故障网络原理是必备的基础知识这部分知识也是面试高频考点还是非常重要的网络原理部分主要解析TCP/IP五层体系中的应用层和传输层网络层和数据链路层只会进行简单的介绍对大部分Java程序员是不会涉及到这两层的只有开发路由器/交换机会用到物理层是硬件岗位程序员就更涉及不到了个人主页洋不写bug的博客所属专栏JavaEE学习铁汁们对于JavaEE的各种常用核心语法都可以在上面的前端专栏学习专栏正在持续更新中有问题可以写在评论区或者私信我哦~1应用层协议应用层对于程序员来说是最重要的一层因为下面的4层都是系统已经实现好的而应用层则是用户自己写的在应用层中程序员通常需要定义好数据的传输格式调用传输层apisocket api进行网络通信程序员定义数据格式就相当于是在自定义应用层协议在实际开发中也称为“约定前后端交换接口”大体上就可以把前端理解成客户端后端理解成服务器自定义协议的过程主要是约定两件事通信的信息通信的数据的格式1通信信息首先是通信的信息就是约定客户端给服务器要发送什么信息服务器收到信息做出响应后返回什么信息就比如外卖软件打开软件时会根据个人喜好来推荐一些附近的餐厅这就是客户端访问服务器后服务器返回的结果如下图客户端访问服务器时要发送用户信息和当前的位置信息然后服务器会返回很多的信息当点击某个商家进入到菜品列表中时显示菜品信息也是访问服务器得到的如下图客户端发送用户信息和商家的id服务器返回各个菜品的数据这些需求就是产品经理提出来的因为大部分用户是没法准确的表达自己的需求的规模稍微大点的公司都有产品经理2通信数据格式数据通信格式主要有以下四种行文本方式XMLJSONgoogle protobuffer在网络编程一博客中提到了这样一个例子在聊天软件上给好友发送信息发送方的id为1234接收方的id为5678发送时间为2026-9- 21 8:41:00发送内容是hello如下图程序员就可以在应用层规定用这种方式来传输数据这个叫做行文本方式行文本方式的可读性非常差对于一些复杂的数据也难以表达因此现在使用就比较少了XML格式的可读性是非常好的就是通过成对的标签来对数据内容进行解释说明跟html看起来比较类似只不过标签是我们自己定义的如下图XML的缺点就是引入了很多标签这些标签需要占用网络带宽网络链路在单位时间内最多能传输的数据量网络带宽资源还是比较贵的因此现在XML用的也不多在本地配置文件中会用到JSON算是当前最流行的一种方案在实际开发中会经常用到如下图XML每个部分中需要有开始标签和结束标签而JSON中只写一次即可相比XML就更节省网络带宽google protobuffer就是二进制压缩方案也就是把要传输的数据按照一定的规则编码成二进制比特位再进行传输可读性非常差但是消耗的网络带宽是最少的google protobuffer适合在特别缺网络带宽的时候使用不缺的话一般都是使用JSON2UDP报文格式传输层主要有TCP协议和UDP协议虽然程序员不需要在传输层实现代码但需要调用传输层提供的api因此就要学习传输层的报文格式这里先来解析UDP报文格式传输层收到应用层的数据包后会在前面加上个UDP报头构造出传输层数据报如下图UDP报头中不只存储了源/目的端口号还存储了其他的数据UDP报头部分有8个字节里面分成了四个部分每部分存储的空间为2个字节分别负责存储源端口号、目的端口号、UDP长度、校验和如下图因为端口号是16位无符号整数十进制就是0 - 65535这里源端口和目的端口部分的大小就都是两个字节第三个部分表示UDP 报头 UDP 载荷的总长度单位是字节因为是用两个字节来表示的UDP长度最大也就是65535也就是说UDP数据报的最大长度大概就是64KB数据报再大就没办法记录长度了一个UDP数据报最大长度大概是64KB现在用手机拍张照片大小就十几MB了很多数据UDP数据报是装不下的在15年前计算机的内存还是比较小的主流就是2GB - 4GB就拿浏览器搜索来说会显示很多搜索结果每个搜索结果基本上都是用文字描述的比较简单用UDP数据报传输是绰绰有余的后来每个搜索结果中显示的东西就多了如下图搜索腾讯视频会发现一个搜索结果中包含很多东西客户端下载、电影、综艺、历史、以及一些剧的图片和链接等等一个UDP数据报大小是64KB是装不下的有的铁汁可能会想为什么那些大佬不把UDP协议改一下例如存储UDP长度的部分从2个字节改成4个字节让UDP数据报能发送更多的数据这个在具体实施上是非常难的升级之后两台设备想要通信就都需要升级但是升级后一定会出现一部分设备是旧版本一部分设备是新版本的情况这两种设备之间就无法用UDP进行通信后果还是很严重的而且协议具体的实现是操作系统的厂家完成的Windows系统的厂家是微软macOS的厂家是苹果这些厂家也不会随便升级协议因为可能会引入新的bug在绝大多数需要传输大型文件的场景都使用TCP协议接着是校验和校验和就是验证UDP数据报是否在传输过程中出错了数据报的传输本质上是在物理层通过电信号/光信号/电磁波传输的日常通信数据传输会受到磁场的影响太空中卫星的数据传输会受到高能粒子流的影响这些影响就会造成比特翻转也就是0变成11变成0通过校验和数据在传输过程中出错就能发现那就可以让这次数据传输失败重新发送数据校验和的原理是这样的发送方在构造完成UDP数据报后大概就是对 UDP 报中的所有数据做反码求和最后对总和按位取反了解下即可就得到了校验和check1就把check1填充到UDP报头的校验和字段那里接收方在接收到数据报后按照相同的算法重新算一遍校验和得到check2再从UDP报头部分取出check1对比check1和check2是否相等不相等就说明数据传输过程中出错了校验和的计算准确率并不是100%一些特定的情况下恰好两个bit的翻转在计算时抵消了那就判断不出来数据出错了但是这种情况出现的概率相对来说比较小可以看作是校验和判断出现的误差对于准确性要求非常高的场景那就不只是用校验和判断数据传输是否出错会加入一些其他的校验算法来判断例如计组中的”海明码“可以识别出是哪一位出现了比特翻转并进行自动纠错当然这样的方案就比较复杂代价也更大了UDP主要会用于分布式系统中服务器之间的通信原因有两个这些服务器在同一个机房中网络环境简单出现丢包的概率比较小UDP的传输效率相对较高在教材中UDP数据报的格式如下这样适合教材排版3TCP报文格式UDP是面向报文的传输单元叫数据报TCP是面向字节流的传输单元叫报文段报文段相比数据报就要复杂了TCP报文段如下图TCP报文段首部最大为60个字节包含的数据还是比较多的源端口号、目的端口号、校验和跟UDP校验和算法原理一样这些就不再赘述了选项部分是用来扩展TCP的基础功能的可以选择是否扩展以及扩展多少选项部分的大小就是 0 - 40个字节不扩展选项部分就是0个字节选项也算是数据报首部的一部分因此TCP首部的大小就是20 - 60字节有的铁汁可能会想首部长度部分只有4位也就是能表示0 - 15而TCP首部最小就20个字节如何表示呢这里相当于做了个压缩优化这里的值还要乘以4个字节这里的值为10那首部长度就是40个字节这里的值为15那首部长度就是60个字节TCP头部还有6位的保留位前面提到想升级UDP协议是特别麻烦的TCP这6位的保留位就是先预留下来给未来协议升级扩展用TCP是可靠传输那这个可靠传输是什么意思呢传输的可靠性不是保证数据能100%的到达对方那里这个是做不到的因为这个数据传输不只是软件层面还受各种硬件因素的影响就比如15年支付宝有几个小时用不了就是因为在杭州挖机工作时把光纤挖断了可靠性主要解决四个问题丢包重复收到乱序比特差错比特翻转这个比特差错问题就是靠16位校验和来解决的前三个问题又如何解决呢首先是丢包的问题丢包是没办法避免的可以约定接收方接收到数据后给发送方回复个收到发送方收到回复就说明这个数据发送成功了发送方没有收到回复就说明这个数据丢包了就采取补救措施例如重发但是这样约定就又引入了一个问题如果接收方发送的收到在传输过程中丢包了发送方没有收到回复就认为前面数据传输丢包了再去发送一遍这样接收方对于收到前面已经收到过的数据这就是重复收到问题后果还是比较严重的例如重复扣款、重复发货乱序问题在数据传输中发送方发送多个数据报不一定先发送到的数据报就先到达因为两个数据报传输的路径可能不一样可能有的路径会比较堵就会出现“先发后到”的情况这个“先发后到”就类似于结婚的车队因为路途中有很多红绿灯道路情况比较复杂有的车可能出发时走到了车队前面途中就会到后面乱序问题有个比较搞笑的例子小帅喜欢小美给小美发微信说周末能不能约个饭小美说可以呀小帅又问小美能不能做我女朋友小美说滚通信流程如下图如果小美发送的数据出现了乱序如下图发送的“可以”在传输过程中堵了一会发送的“滚”先到了那在小帅的视角来看就是问小美周末能不能约饭小美说滚接下来向小美表白小美同意了小帅还以为小美刚开始是跟自己开玩笑的丢包、乱序、重复收到这三个问题可以通过32位序号和32位确认序号来解决TCP是传输字节流序号和确认序号就是针对字节进行编号因为编号是连续递增的所以只需要存储TCP 报文段数据部分第一个字节的编号即可后面每个字节的编号就知道了如下图接收器会返回个应答报文段Acknowledgement又称ACK应答报文段中的确认序号就是收到数据的最后一个字节的序号 1如下图收到数据的最后一个字节的序号为1那就返回1001确认序号有以下两层含义所以小于确认序号的数据接收方已经收到了发送方接下来从确认序号的位置继续发送数据应答报文段的数据载荷部分基本上都为空只有 TCP 头部确认序号只在应答报文中生效那如何确定当前接收端返回的报文段是不是应答报文呢这个就用到了6位标志位的ACK位如下图ACK位的值为0或者1ACK为1就说明这个报文段是应答报文ACK位的值为0就说明报文段不是应答报文通过这种接收方给发送方返回应答报文段的方式丢包、重复收到、乱序问题就都能够解决对于丢包问题如果一段时间后发送方没有收到接收方的应答报文段就重新传送数据这个过程称为“超时重传”不同系统上超时时间是不同的超时重传是对抗丢包的核心机制对于重复收到问题接收方在接收到数据的时候会在操作系统内核中维护一个“接收缓冲区”如果又收到了同一个数据就可以根据数据的序号在接收缓冲区中进行去重操作确保应用程序从接收缓冲区中读到的数据不会重复对于乱序问题接收方会在数据缓冲区中对收到的数据进行排序来解决这个问题超时重传的时间不是固定的是动态变化的超时重传后还是没有收到ack那等待的时间就会变长如下图第一次发送数据时如果等待t1时间没有收到接收端的应答报文就进行数据重传重传后的等待时间为t2t2 t1那为什么要这样设定呢假设网络传输数据的丢包率为10%这时候就已经属于是严重卡顿了在这种情况下数据第一次传输丢包第二次传输仍然丢包的概率是很小的仅为1%不考虑ack丢包这里只是大概计算下如果重传后仍然没有收到ack那就说明网络的丢包率可能已经远远大于10%了如果再去频繁重传会加重网络的故障程度这里等待时间增加可以理解为已经摆烂了如果能收到ack更好但是已经不指望能传输成功了如果重传次数/重传等待时间达到一定的上限重传还没有成功tcp连接就会被重置也就是单方面的释放连接也就是删除保存的对方的信息在断开连接前还会向对方发送一个复位报文意味着这个连接不要了如果能传到对方对方也释放连接这个也属于是单方面的通知对方有没有收到复位报文无所谓标志位中的RSTReset就是区分当前报文是不是复位报文如果值为1就是复位报文否则就不是结语网上一些资料会说“三次握手”下篇博客会提到保证了TCP传输的可靠性这种说法是不太科学的三次握手是在建立连接时涉及的环节连接建立好就不涉及握手了可以看作是可靠传输的一个前提条件确认应答、超时重传才是TCP实现可靠传输的重要机制之一这部分知识就是比较繁杂通信时的一些设定或者遇到的问题跟日常生活中的一些事情是比较类似的结合起来就会更好的理解TCP报文中还有一些数据项没有解析基本上每个都是涉及到一个大的知识点会在后面博客中慢慢解析以上就是今天的所有内容啦完结撒花
返回列表