8/25 Java学习博客
网络原理
网络里有很多协议,有这个协议分层
应用层:应用程序,数据具体如何使用.
传输层:关注起点和终点
网络层:关注路径规划
数据链路层:关注相邻节点的转发
物理层:硬件设备
一、自定义协议
应用层(和程序员接触最密切)
在应用层这里。很多时候,都是程序员“自定义”应用层协议的。
(当然,也是有一些现成的应用层协议)
这里的自定义协议,其实是非常简单的~~(协议=>约定,程序员在代码中规定好,数据如何进行传输)
1.根据需求,明确要传输的信息 2.约定好信息按照什么格式来组织
就比如点外卖 点开外卖软件,首先会看到商家列表~~这里就涉及到程序和服务器之间进行的网络通信交互.
请求:用户信息,位置信息
此处假设就使用简单的格式来组织,使用文本的方式.三个属性,使用",”来分割
1000,100,30 代码中构造出一个这样的字符串,给写入到Tcp socket 或者Udp的socket中
响应:商家列表(多个商家),每个商家,包含名称,图片,距离,简介,评分.
此处假设使用简单的格式来组织,使用文本的方式.每个商家信息占一行,每个属性使用”,”来分割.
杨国福麻辣烫,图片地址1,1.1km,麻辣烫中的绝绝子,5
张亮麻辣烫,图片地址2,2.3km,麻辣烫绝绝子的外甥,4.8
魏家凉皮,图片地址3,3km,凉皮超好吃,4.7
上述这个过程,就是自定义协议.
自定义协议,具体的方式,也是非常灵活的.
针对这里的情况,使用啥样的格式来组织,都ok.只要客户端和服务器这边能够对应上即可~~
二.几种开发中更常见的格式
1.xml
上古时期的组织数据的格式.
现在很少用于网络通信了.但是在后面还会有一些地方遇到.
通过标签来组织数据.
请求:
1000
100,30
xml 的优势:
让数据的可读性变的更好了.
xml的劣势:
标签写起来非常繁琐,传输的时候也占用更多网络带宽.
(maven,就会使用xml来管理项目配置)
2.json(当下最流行的一种数据组织格式)
{
userld: "1000"
position: "100,30"
}
键值对结构()把所有的键值对给包裹起来。
键值对之间,使用",”来分割键和值之间,使用""来分割
键固定就是 string类型
值的话,可以是数字,可以是字符串,也可以是json,还可以是数组.....
由于json的key 固定就是字符串类型,很多时候也是可以把key的引号给省略的
json 的优势:
可读性比较好;比xml 更简洁.
json的劣势:
同样也是会在网络传输中,消耗额外的带宽(需要把key也进行传输的)
虽然如此,json在网络通信中仍然非常流行.除非是一些对于性能要求非常高的场景,不使用json之外,其余的很多地方都可以使用json.
3.protobuffer 相比于json和xml来说,protobuffer (简称为pb)使用二进制的方式来组织数据.可以保证带宽占用最低(相当于把要传递的信息按照二进制形式压缩了)
pb的优势:占用带宽最低,传输效率最高.非常适合于对于性能要求比较高的场景
pb的劣势:可读性不好(二进制结构,肉眼无法直接阅读),一定程度的影响开发效率.
三.现成的应用层协议
应用层也有一些“现成”的应用层协议
其中最知名的,最广泛使用的,就是HTTP协议(超文本传输协议)
这里暂且没讲
四、传输层协议(重点)
传输层(本章重点)
先复习下
UDP:无连接,不可靠,面向数据报,全双工
TCP:有连接,可靠传输,面向字节流,全双工
端口号
写一个服务器,必须手动指定一个端口号.通过端口来区分当前这个主机上的不同的应用程序.写一个客户端,
客户端在通信的时候也会有一个端口号(代码中感受不到),系统自动分配的.
我们对UDP的报文格式分析下如图

校验和是啥.
计算机中非常广泛使用的概念.
前提:网络传输中,由于一些外部干扰,就可能会出现数据传输出错的情况.
光信号/电信号 磁场,电场,高能离子....某个地方本来是传输低电平,在干扰下就成了高电平了.
因此,就需要有办法,能够识别出 出错的数据
校验和本质上也就是一种字符串,体积比原始的数据更小,又是通过原始的数据生成的,原始数据相同,得到的校验和就一定相同。
反之,校验和相同,原始数据大概率相同(理论上存在不同的情况)
如何基于校验和来完成数据校验呢?
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这个算法其实不是特别的靠谱.导致两个不同的数据,得到相同的crc校验和的概率比较大. : 前一个字节恰好少1,后一个字节恰好多1.
md5/sha1算法(就只介绍md5)
1.定长.无论你原始数据多长,计算得到的md5,都是固定长度校验和本身就不应该很长,要不然不方便网络传输
2.分散.给定两个原始数据,哪怕绝大部分内容都一样,只要其中一个字节不同,得到的md5值都会差异很大.
md5 也非常适合作为hash算法.
(hash算法 哈希表
哈希表是要把一个key通过hash函数,转换成数组下标
希望hash 函数能够做到尽量分散,产生hash冲突的概率才会比较低)
3.不可逆.
给你一个原始数据,计算md5,非常容易。
给你md5,还原出原始数据,计算量非常庞大以至于超出了现有计算机的算力极限,理论上是不可行的.
在UDP代码中,都能感知到,UDP的特点.


需要注意的是 UDP的报文长度是有限制的,而TCP没有
TCP分析
TCP这个协议最大的特点,就是可靠传输~~
首先看下他的格式

数据报=首部(报头header)+载荷
16位源端口号
16位目的端口号
和UDP相同.
选项 option可选的
(可以有,也可以没有)选项也是报头的一部分.
TCP报头长度是不固定的(变长的)报头最短,是20字节.(没有选项)报头最长,是60字节.(选项最多是40字节)
其中 4位首部长度
这个字段是描述TCP 头部本身多大:
字段占:4 bit (4 bit => 0-> 0xF (15)
字段记录的是:多少个 4 字节 (32bit) 字,不是字节!
真实头部大小 = 数值 × 4(字节)
UDP有个问题,长度64kb,改不了
TCP有个保留位,现在不用,但是先占个位置.后面如果有需要,再使用.(留下了扩展的余地~~)
TCP相关特性在代码体现

其中 可靠传输,是TCP最最核心的特性(初心)
可靠传输,不是说,发送方把数据能够100%的传输给接收方(要求太高了)
退而求其次
1)发送方发出去数据之后,能够知道接收方是否收到数据
2)一旦发现对方没收到,就可以通过一系列的手段来“补救”
1.确认应答
发送方,把数据发给接收方之后,接收方收到数据就会给发送方返回一个应答报文(acknowledge,ack).
发送方,如果收到这个应答报文了,就知道自己的数据是否发送成功了.、
实际上网络传输数据可能会出现"后发先至"这样的情况~~
一个数据包在进行传输的过程中
走的路径可能是非常复杂的.
不同的数据包,可能走不同的路线
TCP在此处要完成两个工作:
1.确保应答报文和发出去的数据,能对上号,不要出现歧义.
2.确保在出现后发先至的现象时,能够让应用程序这边仍然按照正确的顺序来理解数据.
解决方法如图 通过序列号

具体过程

通过特殊的ack数据包,里面携带的"确认序号”告诉发送方,哪些数据已经被确认收到了.此时发送方,就心中有数了,就知道了自己刚发的数据是到了还是没到.=>可靠传输
TCP的初心,是为了实现可靠传输=>达成可靠传输的最核心的机制,就是确认应答.
如何区分一个数据包是普通的数据,还是ack应答数据呢??
在TCP的报文格式里面有个**ACK **
这一位为1,表示当前数据包是一个应答报文.此时该数据包中的"确认序号字段”就能够生效.
这一位为0表示当前数据包是一个普通报文.此时数据包中的”确认序号字段”是不生效.
确认应答,是TCP最核心的机制.支持了TCP的可靠传输!!!!
网上很多资料,对于这里的理解,是错误的!!!!
常见面试题:
TCP是如何保证可靠传输的??
正确答案:通过确认应答为核心,借助其他机制辅
最终完成可靠传输.
错误答案:三次握手/四次挥手保证了可靠传输....
2.超时重传
确认应答,描述的是一个比较理想的情况如果网络传输过程中,出现丢包了,咋办??
发送方,势必就无法收到ACK了~~
使用超时重传机制,针对确认应答,进行补充.
丢包:
如果数据包太多了,就会在这些路由器/交换机上出现"堵车”
但是路由器针对"堵车"的处理,往往是比较粗暴的,不会把这些积压
的数据包都保存好,而是会把其中的大部分数据包直接给丢弃掉.
此时这个数据包就在网络上消失了~~
由于丢包是一个"随机”的事件,因此在上述tcp传输过程中,丢包就存在两种情况.
1.传输的数据丢了.
2.返回的ack丟了.
站在发送方的角度,无法区分这两种情况
无论出现上述哪种情况,发送方都会进行"重新传输”第一次是丢了,重传一下试试呗,很大概率就能传过去呢~~
重传操作,大幅度的提升了数据能够被传过去的概率~~
重传就是一个很好的丢包下的补救措施了.
当引入"可靠性"的时候,是会付出代价的.
最明显的代价,是两方面:
1.传输效率
2.复杂程度
这里面很重要的是 发送方,何时进行重传?
等待时间
发送方,发出去数据之后,会等待一段时间.如果这个时间之内,ack来了,此时就自然视为数据到达.超过了等待的时间,再重传如果达到这个时间之后,数据还没到,就会出发重传机制~发送方,发出去数据之后,会等待一段时间.如果这个时间之内,
即 超过了等待的时间,再重传~
1.初始的等待时间,是可配置的.不同的系统上都不一定一样.也可以通过修改一些内核参数来引起这里的时间变化.
2.等待的时间,也会动态变化.每多经历一次超时,等待时间都会变长.
例子:
A->B发了一条数据,第一次,A等待ACK的时间,假设是50ms此时如果达到50ms,还没有ack,A就重传
当A重传的数据,还是没有收到ack,第二次等待的时间就会比第一次更长
拉长也不是无限拉长,重传若干此时,时间拉长到一定程度,认为数据再怎么重传也没用了,就放弃tcp连接(准确的说是会触发tcp的重置连接操作)
那这里就引发了个问题 就是 如果ack丢了,客户端再重传个相同消息,服务端会不会进行对两次都进行个响应?
其实TCP已经非常贴心的帮我们把这个问题解决了.
TCP会有一个**"接收缓冲区” ** 就是一个内存空间,会保存当前已经收到的数据,以及数据的序号.
接收方如果发现,当前发送方发来的数据,是已经在接收缓冲区中存在的(收到过的重复数据了),接收方就会直接把这个后来的数据给丢弃掉.确保应用程序进行read的时候读到的是只有一条数据.
接受缓冲区,不仅仅是能进行去重,还能进行重新排序.确保发送的顺序,和应用程序读取的顺序是一致的.
3.连接管理
建立连接+断开连接
即面试中,最经典的问题:
三次握手和四次挥手~~
建立连接
断开连接
握手 就像 打招呼 内容没有实际意义且比较简短,只是为了唤起对方的注意
TCP这里的握手,也类似,也就是给对方传一个简短的,没有业务数据的数据报,通过这个数据报,来唤起对方的注意,从而触发后续的操作。
那握手这个操作也不是TCP独占,甚至不是网络通信独占,计算机中很多操作的都会设计到握手
TCP的三次握手.TCP在建立连接的过程中,需要通信双方一共“打三次招呼”才能够完成连接建立的
假设
A想和B建立连接
A就会主动发起握手操作
发送一个syn(同步报文段) 给B
(同步报文段,就也是一个特殊的TCP数据包
没有载荷的(不携带业务数据的))
实际开发中,主动发起的一方,就是所谓的"客户端”
被动接受的一方,就是"服务器”
怎么看是不是同步报文段 ?
其实也是看报文格式里面的SYN
如果这一位为1,表示这个报文是一个
同步报文段.
如果这一位为0,则不是~
那B收到A的syn后 就发一个ack应答报文给A
随后也发一个syn给A
A收到后再发一个应答报文给B
此时握手就完成了
此时,A和B记录了对方的信息.(也就是构成了"逻辑"上的连接)
建立连接的过程,其实是,通信双方都要给对方发起syn,也都要给对方反馈ack.
一共是4次握手了.但是中间两次,恰好可以合并成一次.


TCP初心,是为了实现“可靠传输”
进行确认应答和超时重传有个大前提,当前的网络环境是基本可用的,通畅的.
如果当前网络已经存在重大故障了,此时,可靠传输,无从谈起.
三次握手是要解决什么问题??
1.三次握手核心作用一:投石问路,确认当前网络是否是畅通的
就比如地铁 每天早上在正式载客之前,都会先有一趟空车,先跑一趟~~
2.三次握手核心作用二:要让发送方和接收方都能确认自己的发送能力和接收能力均正常.
3.三次握手核心作用三:让通信双方,在握手过程中,针对一些重要的参数,进行协商
握手这里要协商的信息,其实是有好几个的,但是此处不做过多讨论但是至少大家要知道,tcp通信过程中的序号从几开始,就是双方协商出来的(一般不是从1开始的)每次连接建立的时候,都会协商出一个比较大的,和上次不太一样的值.
这种设定方式,是避免"前朝的剑,斩本朝的官”(九品芝麻官)
有的时候,网络如果不太好,客户端和服务器之间可能会连接断开,再重新建立连接.
重连的时候,就可能在新的连接好了之后,旧连接的数据姗姗来迟这种迟到的数据,应该要丢弃掉的!!不应该让这个上个朝代的数据影响到本朝代的业务逻辑
如何区分数据是否是来自于上个朝代?就可以通过上述序号的设定规则来实现~~
如果发现收到的数据序号和当前正常数据的序号差异非常大就可以判定为是上个朝代的数据就可以直接丢弃了.
通过四次握手,是否可行?
可以,但是没必要.两个数据合并成一个数据。效率更高.
通过两次握手,是否可行呢??
两次握手只能确定 客户端的发送能力和接受能力

浙公网安备 33010602011771号