目录
🚩进一步讲应用层
🎈自定义应用层协议
🎈用什么格式组织
👩🏻💻xml(远古的数据组织格式)
👩🏻💻json(当下最流行得一种数据组织格式)
👩🏻💻protobuffer(使用二进制方式来组织数据)
🚩进一步讲传输层中UDP(重点)
🎈UDP协议
👩🏻💻UDP报文长度
👩🏻💻校验和
👩🏻💻代码中了解UDP特点
👩🏻💻基于UDP的应用层协议
🚩进一步讲应用层
🎈自定义应用层协议
在应用层这里,很多时候,都是程序员“自定义”应用层协议的。
就是自己定义协议,约定好数据如何传输。
- 1.根据需求,明确要传输的信息
- 2.约定好信息按照什么格式来组织
点外卖:点开外卖软件,首先会看到商家列表,这里就涉及到程序和服务器之间进行的网络通信交互。
客户端请求:用户信息,位置信息 (此处假设就使用简单的格式来组织,使用文本的方式,三个属性,使用","来分割。
1000,100,30
服务器响应:商家列表(多个商家),每个商家,包含 名称,图片,距离,简介,评分。
此处假设使用简单格式来组织,使用文本格式,每个商家信息占一行,每个属性使用“,”来分割。
上述的过程就是自定义协议,自定义协议,具体的方式,也是非常灵活的,针对这里的情况,使用啥样的格式来组织,都ok,只要客户端和服务器这边都能够对应上即可。(上述通过行文本方式构造的协议,属于比较粗糙的方式)
🎈用什么格式组织
👩🏻💻xml(远古的数据组织格式)
通过标签来组织数据
<request><userid>1000</userid><position>100,30</position>
</request>
HTML属于xml的变种
xml是一个通用的数据格式,这里有啥标签,标签有啥含义,都是程序员自定义的
html则是一个专属的数据格式,有啥标签,标签是啥含义,都是有一个标准委员会,规定好的。<a>超链接 <img>图片 <input>输入框 <li>有序列表
xml优势:让数据的可读性变得更好了
xml劣势:标签写起来非常繁琐,传输得时候也占用更多网络宽带
👩🏻💻json(当下最流行得一种数据组织格式)
{userid:"1000",position:"100,30"
}
键值对结构:{}把所有的键值对给包裹起来。键值对之间,使用","分割,键和值之间,使用":"分割。键固定就是string类型,值得话可以是数字,可是是字符串,也可以是json,还可以是数组。
json优势:可读性比较好得,比xml更简洁
json劣势:同样也是会在网络传输中,消耗额外得带宽(需要把key也进行传输)
👩🏻💻protobuffer(使用二进制方式来组织数据)
pb的优势:占用带宽最低,传输效率最高,非常适合于对于性能要求比较高的场景。
pb的劣势:可读性不好(二进制结构,肉眼无法阅读),一定程度上影响开发的效率。
相对于计算机的执行效率来说,对于程序员,开发效率是最重要的。
🚩进一步讲传输层中UDP(重点)
- UDP:无连接,不可靠,面向数据报,全双工
- TCP:有连接,可靠传输,面向字节流,全双工
端口号:
- 写一个服务器,必须手动指定一个端口号,通过端口号来区分当前主机上的不同的应用程序
- 写一个客户端,客户端在通信的时候也会有一个端口号(代码感受不到),系统自动分配。(如果指定端口号发现和自己主机的程序的端口号一样,那么就冲突了)
端口号固定占2个字节,表示的数据范围0--65535,一般来说,0是不用的。
- 1-1023 称为“知名端口号”
- 1024-65535 普通端口号(不要冲突即可)
🎈UDP协议
学习一个协议,其中最主要的工作,就是去理解协议报文格式。
👩🏻💻UDP报文长度
UDP报文长度,是2个字节,16位表示的数据,表示的范围是0-65535=》64kb
UDP报文长度有限制64k
我们知道搜狗的浏览器有些网页下面会显式广告俩字,由于业务的发展,广告越来越多了,广告的样式也越来越复杂了,导致商搜服务器和入口服务器之间交互的数据流,已经接近64kb,如果超过上限,数据就会出现截断,最终展示在页面上的数据肯定会出错的。
解决方法:
- 1.把数据拆分成2个包,使用多个UDP数据报进行传输,这个方案,秒被否定(开发成本比较大),拆包,又如何组包呢。
- 2.直接使用TCP,TCP没有包大小的限制(从这里可以说明,如果是大文件的话都是需要用到TCP,UDP是有包大小限制的)。
👩🏻💻校验和
前提:网络传输中,由于一些外部干扰,就可能会出现数据传输出错的情况。
(光信号/电信号,磁场,电场,高能离子....某个地方本来是传输低电平,在干扰下就成了高电平了)因此我们就需要有办法,能够识别出出错的数据,校验和,就是这种的一种检查手段。
举个例子:
- 就比如我去超市买菜,妈妈告诉我需要买 西红柿 鸡蛋 芹菜 黄瓜 四样菜,当我买完数数是5样,那么肯定是出错了,然后再数数是3样,发现买少了,继续进行校验。(这里我们用个数来表示校验机制,但是还不够,需要结合内容来计算)
- 生活中都需要很多校验才能确保自己做的事情是否有错误。我们小时候计算一个题目需要通过校验来检查等等
校验和,其实本质上是一个字符串,体积比原始的数据更小,又是通过原始数据生成的。原始数据相同,得到的校验和就一定相同,反正,校验和相同,原始数据大概率相同。
如何基于校验和来完成数据校验呢?
- 1.发送方,把要发送的数据整理好(称为data1),通过一定的算法,计算出checksum1
- 2.发送方把data1和checksum1一起通过网络发送出去
- 3.接收方收到数据,收到的数据称为data2(数据可能和data1就不一样了),收到数据checksum1
- 4.接收方再根据data2重新计算校验和(按照相同的算法),得到checksum2
- 5.对比checksum1和checksum2是否相同,如果不同,则认为data2和data1一定不相同, 如果checksum1和checksum2相同,则认为data1和data2大概率是相同的(理论上存在不同的可能性,概率比较低)
校验和是怎么算的?
计算校验和,有很多算法
- UDP中使用的是CRC算法(循环冗余算法)
把当前要计算校验和的数据,每个字节,都进行累加,把结果保存到这俩个字节的变量中,累加过程中如果溢出,也没关系。如果中间某个数据,出现传输错误,第二次计算的校验和就会和第一次不同。
CRC这个算法不是特别的靠谱,导致俩个不同的数据,得到相同的校验和概率比较大,比如如果前一个字节恰好少1,后一个字节恰好多1,但是最终得到相同的校验和。
- md5 / sha1算法
1.定长:无论你的原始数据多长,计算得到的md5,都是固定长度。(校验和本身就不能太长,如果太长就不方便网络传输)
2.分散:给定两个原始数据,哪怕绝大部分内容都一样,只要其中一个字节不同,得到的md5值都会差异很大。md5也非常适合作为hash算法(哈希表是把一个key通过hash函数转换成数组下标,希望hash函数能够做到尽量分散,产生hash冲突的概率才会比较低)
3.不可逆:给你一定原始数据,计算md5,很容易,给你md5,还原出原始数据,计算量非常庞大,以至于超出了现有计算机的算力极限,理论上是不行的。md5也可以应用在一些密码学场景中。
👩🏻💻代码中了解UDP特点
1.面向数据报:
需要将数据用DatagramPacket对象存储起来
2.无连接:UDP本身是不会存储对端的信息,所以在发送的时候需要显式指定发送给谁
3.全双工:通过一个socket对象,既可以send,也可以接收
4.不可靠,代码中体现不出来
👩🏻💻基于UDP的应用层协议
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
当然,也包括你自己写 UDP 程序时自定义的应用层协议
相比较于UDP,TCP更值得关注。期待下一篇TCP的详细解说。
也许适当的休息和摆烂是为了更好的重新出发。