目录
一、前沿知识
1.1应用层
应用层是和程序员打交道最多的层,很多时候写的代码都是涉及到应用层协议的~~
应用层:描述了应用程序如何理解和使用网络中的通信数据。
我们程序员在应用层的主要工作是自定义协议,因为下面四层都在系统内核/驱动程序/硬件中已经实现好了,不能去修改。
1、为什么要自定义协议呢~
当前的应用程序要解决的业务场景是错综复杂的,不同的公司有不同的业务,不同的业务有不同的流程,程序也就复杂了,因此很难有一个通用的协议来满足所有业务需求,需要我们程序员自创协议~~
2、怎样去自定义协议呢~
1.明确协议要传递那些信息: 结合需求,分析清楚,请求响应(客户端/服务器之间)要传递那些信息
2.确定信息以什么样的格式来组织: xml,json,protobuffer......约定好协议的具体格式内容之后,客户端就可以按照这个格式构造数据并发送了,服务器按照这个格式解析处理....
组织数据的格式:
XML:标签化的数据组织方式,使用标签来表示键值对,以及树形结构。(2010年前流行)
json:出自js语言,比XML精简
protobuffer(谷歌):二进制的表示数据的方式,占用空间小,传输的带宽也就降低了
当然我们的应用层也有一些现成的协议:HTTP协议
1.2传输层
传输层是紧接着应用层的下一层,虽然传输层已经被操作系统内核实现好了,但是我们在写代码的时候,要调用系统的Socket api去完成网络编程,socket就是属于传输层的部分。
端口号: IP是用来确定网上上的一台主机,那么端口号就是用来确定主机上的一个进程的,端口号是传输层的一个概念。
数据库mysql默认端口3306,起到的效果就是区分一个主机上具体的应用程序,要求在同一个主机上,一个端口不能被多个进程绑定(进程A绑定了3306,此时进程B也尝试绑定3306,进程B的绑定操作就会失败)
TCP和UDP协议的报头中都会包含 源端口 和 目的端口 ,并且都是使用2个字节,16bit来表示,端口号的范围是 0 -> 65535,但是我们日常使用一般都是从1024开始的,因为 0 -> 1023 这个范围的端口系统已经分配给了一些知名的应用程序了,也称这些端口为" 知名端口号/具名端口号".
虽然我们建议1023以下的端口别使用,但不代表完全不能使用,虽然这些端口分配给了特定程序,但是这些程序是否在主机运行着,是否安装了这些程序都是不确定的,如果我们想要使用1023以下的这些端口,需要注意以下2点:
1.确定这个端口是否有程序在绑定
2.确定你具有管理员权限。
二、UDP协议
前面为大家介绍过了UDP协议的一些特点:无连接,不可靠,面向数据报,全双工,这些特性在我们实现回显UDP服务器客户端程序的时候有所体现,那么今天我们来研究以下UDP协议的报文结构。
UDP的载荷数据(就是通过UDP socket ,也就是 send 方法拿来的数据,再在前面拼接上8个字节的报头,相当于字符串拼接)
不同的协议,功能不同,报头中带有的属性信息就不同,对于UDP来说,报头一共就是8个字节,分成4个部分(每个部分2个字节),但正是因为,我们的UDP报文的长度也受到了限制,UDP报文长度是用2个字节表示的,2个字节表示0 -> 65535(64KB),也就表示了我们UDP数据报最大只能传输64KB的数据。(64KB太小了,拍张照都小几个MB了)
如果我想传一个大于64KB的数据报呢?
有两种解决办法:
1.我们应用层在代码层面将我们要传输的数据报进行分包,通过多个UDP数据报进行发送。
如果采用1,本来我们send一次,现在需要多次send,(就好比我们扔垃圾,垃圾太多,一个小袋子装不下,需要装许多个)
2.不使用UDP,使用TCP,TCP没有长度限制。(直接用一个超大垃圾袋,一次性就搞定)由于装垃圾,提垃圾,倒垃圾都比较麻烦,所以第二种方案比较好。
我们报头信息中还有源端口和目的端口信息,我们的一次网络通信,涉及到五元组:源IP,源端口,目的IP,目的端口,协议类型,端口信息就是由我们传输层体现的。
校验和:验证传输的数据是否是正确的。
我们在网络传输中往往不是一帆风顺的,可能会受到一些干扰,在这些干扰下可能会出现"比特翻转"的现象, 0 -> 1,1 -> 0的现象。
网络传输中,物理层传输的本质上就是 光信号/电信号 ,这些信号会受到一些物理环境的影响,比如电磁场,高能射线等等,有时候仅仅是一个比特位的变化,对于原本数据的含义就发生了致命的变化,我们对于这些不可避免的现象,只能是及时识别当前的数据是否出现问题。
因此就引入了校验和来做这一项工作,针对数据内容进行一系列的数学运算,得到一个短小的结果,如果我们的数据内容一定,那么我们得到的校验和就是一定的,如果我们的数据变了,那么我们的校验和就变了。
当然有同学肯定想到了,是否存在一种这样的情况,我们接收到错误的数据,但是计算出的校验码恰好相同,这种情况理论上是存在的,但是概率特别小,就忽略不计了。
实际上网络传输过程中,往往是把数据的所有字节都参与生成校验和的运算,这样任何一个字节出问题都能够及时发现了。
介绍几个比较知名的生成校验和的算法:
一、CRC(循环冗余校验): 简单粗暴,把数据的每个字节循环往上累加,如果累加溢出了,高位就不要了,比较好算,实际的CRC校验码生成是采用二进制的模2算法(即减法不借位、加法不进位)计算出来的,这是一种异或操作。这种方法比较好算,但是校验的效果不够理想。(同时两个比特位,前一个字节少1,后一个字节多1,就会出现内容变了,CRC没变这样的情况)
二、MD5: MD5是使用一系列公式来进行更复杂的数学运算,具有以下几个特点:
1.定长:无论原始数据多长,得到的MD5值都是固定长度(4/8字节)
2.冲突概率小:我们的原始数据即使变动了一点点,算出来的MD5值的差别都很大(MD5结果更分散了)
3.不可逆:我们通过原始数据计算出MD5比较容易,但是通过MD5还原成原始数据很难,理论上是不可实现的(计算量极大)。
基于MD5的这些特点,MD5的应用场景就有许多了:
1.校验和
2.加密
3.计算Hash值
可能大家在网上会看到一些MD5的方法,其实也很好理解,有人将一些常见的字符串的MD5值进行汇总成一张表,解密的过程相当于查表,但仅限于一些常见的字符串,其他也查不到。
三、SHA1: SHA1和MD5类型,这里就不具体介绍了,感兴趣的同学可以上网查询下资料。