应用层
应用层:描述了应用程序如何理解和使用网络中的通信数据。
我们程序员在应用层的主要工作是自定义协议,因为下面四层都在系统内核/驱动程序/硬件中已经实现好了,不能去修改。
自定义协议需要做好两件事:
1.明确协议要传递那些信息
2.确定数据组织格式: xml,json,protobuffer
当然我们的应用层也有一些成品的协议:http协议
传输层
传输层是紧接着应用层的一层,虽然传输层已经被操作系统内核实现好了,但是我们在写代码的时候,要调用系统的socket api去完成网络编程
端口号: ip是用来确定网上上的一台主机,那么端口号就是用来确定主机上的一个进程的,端口号是传输层的一个概念
tcp和udp协议的报头中都会包含源端口和目的端口,并且都是使用2个字节,16bit来表示,端口号的范围是 0 -> 65535,但是我们日常使用一般都是从1024开始的,因为0 -> 1023这个范围的端口系统已经分配给了一些知名的应用程序了,也称这些端口为" 知名端口号/具名端口号".
虽然我们建议1023以下的端口别使用,但不代表完全不能使用,虽然这些端口分配给了特定程序,但是这些程序是否在主机运行着,是否安装了这些程序都是不确定的,如果我们想要使用1023以下的这些端口,需要注意以下2点:
1.确定这个端口是否有程序在绑定
2.是否具有管理员权限。
我们在前面为大家介绍过了udp协议的一些特点:无连接,不可靠,面向数据报,全双工,这些特性在我们实现回显udp服务器客户端程序的时候有所体现,那么今天我们来研究以下udp协议的报文结构。
相信学过计算机网络这门课的小伙伴们,看到这张图都不陌生,但实际上我们课本这样画是为了排版方便。
udp的载荷数据就是通过udp socket send()要发送的数据,在前面拼接上8个字节的报头)
我们来看一下udp报头所包含的信息,udp报头一共8个字节,4个部分每部分占2个字节,但正是因为,我们的udp报文的长度也受到了限制,udp报文长度是用2个字节表示的,2个字节表示0 -> 65535(64kb),也就表示了我们udp数据报最大只能传输64kb的数据。
相信有同学会问,如果我想传一个大于64kb的数据报呢?
有两种解决办法:
1.我们应用层在代码层面将我们要传输的数据报进行分包,通过多个udp数据报进行发送。
如果采用1,本来我们send一次,现在需要多次send,就好比我们扔垃圾,垃圾太多,一个小袋子装不下,需要装许多个,装垃圾,提垃圾,倒垃圾都比较麻烦,基于上面这种情况,我们可以直接用一个超大垃圾袋,一次性就搞定了,这也是第二种方案。
2.不使用udp,使用tcp,tcp没有长度限制。
我们报头信息中还有源端口和目的端口信息,我们的一次网络通信,涉及到五元组:源ip,源端口,目的ip,目的端口,协议类型,端口信息就是由我们传输层体现的。
校验和:验证传输的数据是否是正确的,我们在网络传输中往往不是一帆风顺的,可能会受到一些干扰,在这些干扰下可能会出现比特翻转的现象, 0 -> 1,1 -> 0的现象。
我们网络传输中,物理层传输的本质就是光信号/电信号,这些信号会受到一些物理环境的影响,比如电磁场,高能射线等等,有时候仅仅是一个比特位的变化,对于原本数据的含义就发生了致命的变化,我们对于这些不可避免的现象,只能是及时识别当前的数据是否出现问题。
因此就引入了校验和来干这一项工作,针对数据内容进行一系列的数学运算,得到一个短小的结果,如果我们的数据内容一定,那么我们得到的校验和就是一定的,如果我们的数据变了,那么我们的校验和就变了。
我们接收方在接收到数据之后会在计算一边校验和,看看是否和发送方发来的校验码对的上,如果对上了就证明传输没问题,如果对不上,证明传输出错了。
我们根据收到的数据我要吃火锅计算出了0x1122发现和接收到校验码一致,证明我们这次数据传输没问题。
我们根据接收到的数据我要吃烤肉计算出来0x5566发现和接收到的校验码不一致,证明我们的传输出错了。
当然有同学肯定想到了,是否存在一种这样的情况,我们接收到不同的数据,但是计算出的校验码恰好相同,这种情况理论上是存在的,但是概率特别小,就忽略不计了。
我们网络传输中,生成校验和的算法有很多,我们这里只介绍比较知名的几个:
crc(循环冗余校验): 实际的crc校验码生成是采用二进制的模2算法(即减法不借位、加法不进位)计算出来的,这是一种异或操作。这种方法比较好算,但是校验的效果不够理想。
md5: md5是使用一系列公式来进行更复杂的数学运算,具有以下几个特点:
1.定长:无论原始数据多长,得到的md5值都是固定长度(4/8字节)
2.冲突概率小:我们的原始数据即使变动了一点点,算出来的md5值的差别都很大(md5结果更分散了)
3.不可逆:我们通过原始数据即使出md5比较容易,但是通过md5还原成原始数据很难,理论上是不可实现的。
基于md5的这些特点,md5的应用场景就有许多了:
1.校验和
2.加密
3.计算hash值
可能大家在网上会看到一些md5的方法,其实也很好理解,有人将一些常见的字符串的md5值进行汇总成一张表,解密的过程相当于查表,但仅限于一些常见的字符串,其他也查不到。
sha1: sha1和md5类型,这里就不具体介绍了,感兴趣的同学可以上网查询下资料。