应用层
协议就是一种约定
应用层:对应应用程序,是程序员打交道最多的一层,调用系统提供的网络api写出的代码都是属于应用层的。应用层有很多现成的协议,但程序员一般用的还是自定义协议
自定义协议要约定好哪些内容?
1.服务器和客户端之间要交互哪些信息(产品经理规定)
2.数据的具体格式(与产品经历无关,客户端和服务器的程序员共同敲定)
客户端和服务器之间往往要进行交互的是结构化数据;网络传输的数据其实是字符串或者二进制比特流
约定协议的过程,就是把结构化数据转成字符串/二进制比特流的过程
把结构化数据转成字符串/二进制比特流这个操作,称为序列化
把字符串/二进制比特流还原成结构化数据,这个操作叫做反序列化
序列化/反序列化具体要组织成什么样的格式,包含哪些信息,约定这两件事的过程就是自定义协议的过程
常见的协议约定格式
1.XML
请求:
<request>
<userId> 1000 </userId>
<position> [经纬度] </position>
</request>
响应:
<response>
<shops>
<shop>
<id> 1001 </id>
<name> 杨国富麻辣烫 </name>
<image> 图片地址 </image>
<rank> 4.8 </rank>
<description> 这是好吃的麻辣烫 </descitption>
</shop>
</shops>
</response>
< > 表示标签,标签往往是成对出现的
<userId>是开始标签
</userId>是结束标签
开始标签和结束标签之间夹着的就是标签的值,标签可以嵌套
优点:拓展性和可读性极大地提升了
如果后面要添加一些属性,就新增一个标签即可,对于已有代码影响不大
缺点:整个数据冗余信息就非常多了,标签这种描述性信息占据的空间反而比数据本身更多
尤其是网络传输的时候,带宽就会消耗很大
HTML和XML的区别
XML:里面的标签/格式/值都是自定义的,程序员自由度比较高
HTML:里面的标签/格式/值都是大佬们规定好了,程序员只能遵守已有规则
2.JSON
请求:
{
userId: 1000,
position: [经纬度]
}
响应:
{
{
id: 1001,
name: "杨国福麻辣烫"
},
{
id: 1002,
name: "魏家凉皮"
}
}
json是键值对结构
键和值之间用 :进行分割
键值对之间用 , 进行分割
把若干个键值对使用{ } 括起来,此时就形成了一个json对象。
还可以把多个json对象放到一起,使用“ ,”分隔开,,并且用 { } 整体括起来,可以形成一个json数组
优点:可读性和扩展性很好,相比起XML,带宽明显减少
缺点:key名字重复传输
3.protobuffer
更节省带宽的方式,效率最高的方式
在开发阶段定义出都有哪些资源,描述每个字段的含义。程序真正运行的时候,实际传输的数据是不包含这样的描述信息
这样的数据是按照二进制的方式来组织的
虽然protobuffer运行效率更高,但是使用没有比json更广泛
传输层
端口号:是一个2个字节的整数,使用端口号的时候,1~1024都是系统保留的自用的端口,一般都是把这些端口给知名的服务器使用
HTTP服务器:80
HTTPS服务器:443
UDP协议
研究这个协议就是研究UDP报文格式,也就是UDP数据报
UDP数据报 = 报头 + 载荷
UDP报头一共4个字段,每个字段2个字节,一共8个字节
协议报头中使用2个字节表示端口号,端口号取值范围就是0~65535(64KB),一个UDP数据报最大长度就是64KB
检验和/校验和
验证数据在传输过程中是否正确,如果发现错误,就把错误的数据报丢掉
检验原理:通过原始数据中的部分内容进行一系列的运算,得到一个更短的字符串,通过原始整体数据再计算一次这样的结果,再对比是否一致
前提:数据在网络传输中可能损坏(网络数据传输,本质上是光信号/电信号/电磁波,非常容易受到外界的干扰)
网络中的校验和并非是简单的按照长度/数量作为校验标准的,一定要让数据的内容能够参与
CRC算法
UDP中校验和采用比较简单的方式比如CRC算法进行校验(循环冗余校验)
//比如要产生一个两个字节的校验和
short checksum = 0;
for(遍历取出数据报中每个字节的数据){
checksum+=当前字节的数据//暂时先不管溢出
}
UDP数据报发送方,在发送之前先计算一遍CRC,把算好的CRC值放到UDP数据报中(设这个CRC值为value 1)
接下来把这个数据报通过网络传输到接收端,接收端收到这个数据之后,也会按照同样的算法,再算一遍CRC的值,得到的结果是value2,再对value1和value2之间进行比较。如果是一致的就说明数据是ok的;如果不一致,说明传输过程中就发生了比特翻转了
更加精确的算法:MD5算法/sha1算法
MD5算法
特点:
1.定长。无论原始数据有多长,算出来的md5的最终值都是固定长度
2.分散。计算md5的过程中,原始数据只要变化一点点,算出来的md5值就会差异很大
网络传输中,如果出现bit反转(只有少数的bit进行翻转),但是即使只是翻转1bit,得到的md5差异会很大。这个特性也能使md5成为一个字符串哈希算法
3.不可逆。给你一个源字符串,计算md5值,可以很容易实现。但是如果给你一个md5值,让你返回源字符串,理论上无法完成
因为原始的字符串转成md5的过程中有很多信息量缺失了,所以无法直接还原