一、应用层相关知识
1.1基本知识
- 应用层是和程序员接触最密切的,在应用层里,很多情况下,都是程序员自定义应用层协议的。
- 自定义协议可以分为两步: 1.根据需求,明确要传输的信息 2.约定好信息按照什么格式来组织。
1.2几种开发中更常见的组织信息的格式
1.2.1xml
- 上古时期用来组织数据的格式,现在很少用于网络通信,它通过标签来组织数据
- 举例:
<request>
<userld> 1000 </useld>
<position> 100,30</position>
</request>
我们可以发现,他和html很类似,不过xml是一个通用的数据格式,有啥标签,标签的含义都是程序员自定义的;而html则是一个专属的数据格式,标签的含义是由标准委员会规定好的。优势:让数据的可读性变得更好了;劣势:标签写起来很繁琐,传输的时候也占用更多的网络宽带。
1.2.2json
- 当下最流行的一种数据组织格式,除了在一些对于性能要求非常高的场景外,其他都可以使用
{
useld:"1000",
position:"100,30"
}
键值对结构,{}把所有的键值对给包裹起来,键值对之间使用",“来分割;键和值之间使用”:"来分割。键固定就是string类型,值可以是数字,字符串,json,数组…
优势:可读性更好,更简洁
劣势:会在网络传输时消耗额外的宽带。
1.2.3protobuffer
- 相比于前面两种,pb使用二进制的形式来组织数据,可以保证宽带占用最低(相当于把要传递的信息按照二进制的形式压缩了)
优势:占用宽带最低,传输效率最高,非常适合对于性能要求较高的场景
劣势:可读性不好(二进制形式,肉眼无法直接阅读),一定程度的影响开发效率
1.3HTTP
- 应用层中也有一些“现成”的应用层协议,其中最知名的,最广泛使用的,就是HTTP协议(超文本传输协议)。超文本——文本,图片,视频,音频,字体…
二、传输层的UDP和TCP
2.1UDP
- 无连接,不可靠,面向数据报,全双工

2.1.1 校验和
- 在网络传输中,由于一些外部干扰,就可能出现数据传输错误的情况,因此就需要有办法识别出出错的数据,而校验和就是这样的检查手段。
- 如何基于校验和来完成数据校验呢?
1.发送方,把要发送的数据整理好(data1),通过一定的算法(个数,首字母),计算出校验和checksum1
2.发送方把data1和checksum1一起通过网络发送出去
3.接收方收到数据,收到的数据称为data2(此数据可能和data1就不一样了),收到数据checksum1
4.接收方在根据data2重新计算校验和(按照相同的算法),得到checksum2
5.对比checksum1和checksum2,如果不同,则认为data1和data2一定不相同;如果相同,则认为data1和data2大概率相同(理论上存在不同的可能,但很小,工程上忽略不计) - 校验和是怎莫算的?
计算校验和,有多种算法。此处UDP中使用的是CRC算法(循环冗余算法):把当前要计算校验和的数据,每个字节都进行累加,把结果保存在这两个字节的变量中,累加的过程中如果出现溢出,也没关系。(CRC算法不是特别靠谱,导致两个不同的数据,得到相同的CRC校验和的概率较大。前一个字节少一,后一个字节多一,这种情况发生的概率较小,但还是有一定风险的)
2.1.2 md5 / sha1算法
1.定长.无论原始数据多长,md5的长是固定的
2.分散.给定两个原始数据,只要有一个字节不同,md5的值就会有巨大的差别(这个特性使md5也非常适合hash算法)
3.不可逆.给你一个原始数据,计算出md5,非常容易,但给出md5,计算出原始数据,由于计算量及其庞大,超出了目前计算机算力的极限,所以理论上是不行的。
2.2TCP
- 有连接,可靠传输(核心特性),面向字节流,全双工

TCP协议的核心机制(部分)
2.2.1确认应答(是达成可靠传输的最核心的机制)
发送方会通过特殊的ack应答数据包,里面携带的“确认序号”告诉发送方,哪些数据已经被确认收到;发送方把数据发给接收方,接收方收到数据就会给发送方返回一个应答报文(acknowledge,ack);发送方如果接收到应答报文了,就知道数据是否发送成功了
如何判断一个数据报是普通的数据,还是ack应答数据那?
- 如果上图中第二位ACK的值为1,则是应答报文;0,则是普通数据包
2.2.2超时重传
- 确认应答描述的是一个比较理想的情概况,如果在网络传输的过程中出现了丢包的情况,发送方个就无法收到ACK了,要使用超时重传机制,针对确认应答,进行补充。发送方会设定一个等待时间,发出数据一段时间之内,ack来了,就视为数据到达,否则就会触发重传机制。(这个时间是可配置的,不同系统不通;等待的时间也会动态变化,每经历一次超时,等待时间都会变长)。
为何会出现丢包的情况给那? - 网络就是公路,公路上的收费站相当于路由器/交换机,如果数据包太多,就会出现堵车,而路由器针对这种情况会把大部分数据报直接丢弃。
丢包有两种情况 - a.传输的数据丢了 b.返回的ack丢了;而发送方无法区分。
如果接收方收到数据后,返回的ack丢失了,那莫发送方会再发送一次数据,站在接收方的角度,他会收到两次一样数据(如果涉及到钱相关的就会很严重)。所以TCP设有的有一个“接收缓冲区”,接收方如果发现发来的数据已经存在,就会丢弃该数据,进行去重操作。同时他还能进行重新排序,确保发送的数据和应用程序读取的顺序是一样的。
2.2.3连接管理(建立连接(三次握手)+断开连接(四次挥手))
- 握手:给对方发送一个没有实际意义,简短的数据报,引起对方的注意,从而触发后续的操作。建立连接一般都是由客户端主动发起。三次握手,TCP在建立连接时,要通信双方“打三次招呼”才能建立连接;当图中的SYN为1时,发送的是“同步报文段”,0则不是。

- 三次握手的核心作用:a.投石问路,确认当前网路是否畅通 b.让发送方和接收方都确认自己的发送和接受能力正常 c.让通信双方在握手过程中,针对一些重要的参数,进行协商。
- 断开连接:客户端和服务器都可以主动发起;“FIN”就叫做“结束报文段”。ACK和FIN在一定情况下才能合并。TIME-WAIT状态存在的意义,是为了防止最后一个ACK丢失,那一方主动断开,哪一方就进入该状态,该状态等待的时间是网络上两个节点通信消耗的最大时间的两倍。

2.2.4滑动窗口
- 前三个机制,都是在保证tcp的可靠性(不是安全性,被黑客截获了也没事)。TCP的可靠性,会影响传输的效率(多出了一些等待的时间,单位时间内能传输的数据就少了),而滑动窗口,就可以让可靠传输对性能的影响要少一些。TCP引入了可靠性,传输效率是不可能超过UDP的,这里的做法是为了缩短和UDP的差距——缩短应答报文的等待时间。窗口越大,等待的ack越多,传输效率就越高。(批量传输)如果窗口太大,传输的数据太快就会使接收方处理不过来,此时,接收方会丢包,发送方还要重传。
丢包 - a.ack丢了,不需要任何重传(确认序号表示当前序号之前的数据都收到了)
b.数据包丢了,主机A要知道那个数据丢了,主机B会告诉他(B从A处接收不到数据,就会反复确认应答,接受继续发送的数据,同时给A发送ack索要丢失的数据,A看到后会重传) - 如果通信双方,传输的数据的量比较小,也不频繁,就任然是普通的确认应答和普通的超时重传;如果传输的数据的量更大更频繁,就会进入到滑动窗口模式,按照快速重传的方式处理。
2.2.5流量控制(站在接收方的角度,反向制约发送方的传输效率)
发送方的发送速率,不应该超过接收方的处理能力。接收方每次接收到数据之后,都会把接收缓冲区剩余空间大小通过ack返回给发送方,发送方会按照这个数值来调整下一论的发送速度。为0时,会暂时不在发送数据,不过会周期性发送一个“窗口探测包”,不带任何数据,只是为了触发ack,查询接收缓冲区剩余空间。

2.2.6拥塞控制
流量控制是考虑的接收方的处理能力,而拥塞控制要考虑到整个通信路径(通信中间节点的情况)。由于中间节点的结构更复杂,难以直接的进行量化,因此就可以使用“实验”的方式,来找到个合适的值。可以让A先以较小的速度发送数据,如果数据传输过程中没有丢包,再尝试使用更大的窗口,以更高的速度进行发送,随着窗口的增大,中间节点就可能出现问题,此时节点就可能出现丢包,发送方发现丢包,就把窗口调整小,不丢,就继续变大(敌退我进,敌进我退)
- 流量控制和拥塞控制都是在限制发送方的发送窗口大小,最终发送窗口的大小,是取流量控制和拥塞控制中窗口的较小值
2.2.7延时应答
A->B,B就会立即返回ack给A(正常);但有时,A->B,B等一会再传ack给A(延时应答)。本质上也是为了提升传输效率;发送窗口的大小是传输效率的关键。延时返回ack,给接收方更多的时间,来读取接收缓冲区的是数据,此时接收方读了这个数据后,缓冲区剩余空间变大了,返回的窗口也就更大了
2.2.8捎带应答
在延时应答的基础上,进一步提高效率

2.2.9面向字节流
- 粘包问题(面向字节流的机制都有类似的情况),此处的“包”指的是应用层数据包,如果有多个应用层数据包被传输过去,就容易出现粘包问题——

,而向UDP这样的面向数据报的通信方式,就没有上述问题

如何解决粘包问题?
核心思路:通过定义好应用层协议,明确应用层数据包的边界 - 1.引入分隔符(例如:使用"\n "作为分隔符 )
- 2.引入长度

自定义应用层协议的格式,xjm,json,protobuffer,本身都是明确了包的边界。
2.2.10异常情况的处理
- 在使用tcp的过程中,出现意外,会如何处理?
1.进程奔溃
进程没了,异常终止了,文件描述符表也就释放了,相当于调用socket.close(),此时会触发FIN,对方收到后,就会返回FIN和ACK(正常四次挥手断开链接的流程),TCP的连接,可以独立于进程存在(进程没了,TCP连接不一定没)
2.主机关机(正常流程)
在进行关机时,会先触发强制终止进程的操作(相当于1),此时会触发FIN,对方收到之后,就会发送ACK和FIN,不仅仅是进程没了,整个系统也可能关闭,如果在系统关闭之前,对端返回的ACK和FIN到了,此时系统还是可以返回ACK,进行正常的四次挥手,如果系统已经关闭,,ACK和FIN迟到了,无法进行后续ACK的响应,对端就以为是自己的FIN包丢了,会重传FIN,重传几次后都没有相应,对端就会放弃连接(把持有的对端的信息就删了)
3.主机掉电(非正常)
这是一瞬间的事,进程来不及关闭,FIN也来不及发送,主机就直接停机了。
两种情况;
a. 如果对端在发送数据(接收方掉电),发送的数据就会一直等待ack,触发超时重传,触发TCP连接重置功能,发起“复位报文段(上面的RST)”,如果还没有收到回复,就会释放连接了
b. 如果对端在接受数据(发送方掉电),对端在等待数据到达,等待不到,无法区分是对端挂了,还是没发消息,所以TCP中提供了“心跳包”机制——接收方也会周期性的给发送方发起一个特殊的,不懈怠业务数据的数据包,并期望对方返回一个应答,如果对方没有应答,并且重复多次,仍然如此,就视为对方挂了,此时就可以单方面释放连接。
4.网线断开
和主机掉电是很像的

- TCP的心跳机制,很常见(尤其是在分布式系统中),如何识别某个机器是否挂了?一般都是通过心跳来检测的,一般后续用到的心跳(往往希望是秒级甚至毫秒级就能检测出对端是否存活),都是在应用程序中自主实现的,而不是直接使用tcp的心跳(因为tcp的心跳机制周期比较长)
2.3TCP和UDP之间的对比
- TCP的优势:可靠传输,适用于绝大部分场景
- UDP的优势:更高效率,更适合于对于“可靠性要求不高”,“性能敏感”的场景,例如:局域网内部(同一个机房)的主机之间的通信。同一个机房内部,网络结构简单,带宽充足,交换机/路由器的网络设备负载程度也不是很高,出现丢包的概率不大,所以往往希望机器之间的数据传输速度更快。
如果要传输比较大的数据包,TCP优先(UDP有64KB的限制),如果要进行“广播传输”,优先考虑UDP,UDP天然支持广播,TCP不支持(要应用程序额外写代码实现)。广播——一种需要把数据发送给局域网的所有机器的特殊场景(例如:投屏功能) - 经典问题:如何基于UDP实现可靠传输?——该问题本质是考察TCP,TCP是怎样实现可靠传输的,照抄到UDP的应用程序中(如确认应答…)
2.4端口号
- 写一个服务器,必须手动指定一个端口号,通过端口来区分当前主机上不同的应用程序;写一个客户端,客户端在通信时也有一个端口号,不过是系统自动分配的。
- 端口号,固定就是占2个字节,表示数据范围 0->65535,0一般不用
1-1023称为“知名端口号”;1024-65535普通的端口号
例如:22:ssh服务器的端口号,ssh协议是用来登录远程主机的;80:http服务器的端口号;443:https服务器的端口号
三、网络层
网络层要做的事,主要分为两方面:1.地址管理2.路由选择。
- 地址管理:制定一系列规则,通过地址,描述出网络上一个设备的位置
- 路由选择:网络环境比较复杂,从一个节点到另一个节点之间存在很多条不同的路径,就要通过这种方式,筛选出更合适的路径进行数据传输
3.1IP协议

- 4位版本——ip v4;6位版本——ip v6
- 4位首部长度——IP协议的报头,也是变长的。4位时能存储的二进制数字位数(所以最大时15),单位是4字节,所以最大是15*4=60字节
- 8位服务类型——能让IP协议,切换形态。3位优先权字段(已弃用),4位TOS字段和一位保留字段(必须置为0)。这4位,彼此之间是冲突的,只有一位可以置为1,不同位置为1,表示IP协议的不同形态。(最小延时,最大吞吐量,最高可靠性,最小成本)
- 16位总长度——描述了Ip数据包最长是多长(ip协议也存在64KB这样的限制,但是ip
协议自身支持“拆包组包”功能) - 通过第二层的三个属性支持ip协议的拆包和组包 ,如果一个大的ip数据包要拆成多个小的,此时拆出来的者多个小包,16位标识是相同的数值;13位片偏移描述当前每个小的数据包(分片)的相对位置;3位标志位,只有两位有用,一位表示是否允许拆包,还有一位表示是否是最后一个包(类似于单链表的结束标志)
- 8位生存时间——描述了这个ip数据包在网络上还能存活多久。TTL的单位是次数,数据包被构造出来时,TTL会被设置一个初始值(32,64,128…),数据包再转发的过程之中,每次经过一个路由器转发,TTL就会-1,如果该数据包TTL耗尽了,还没有到达接收方,就会被丢弃。(为网络兜底,避免浪费网络资源)
- 8位协议——描述的是,Ip数据包的载荷部分,是一个UDP数据包还是一个TCP数据包
- 16位首部校验和——这个校验和,只是校验IP首部,不管Ip数据的载荷(UDP和TCP自身都有校验和)
3.1.1Ip协议的两个核心功能:
- a.地址管理
IP地址,是一个32位的整数,2^32=>42亿9千万。地址理论上来说是不可以重复的,但是当今能上网的设备早已超出这个数字,即出现了IP地址不够用的问题。
解决方案:1.动态分配IP。治标不治本,提高了IP地址的利用率,但是没有增加Ip得知的数量(过渡方案,目前还是广泛使用的) - 2.NAT机制(网络地址转换)
本质上是让一个Ip地址代表一批设备。把Ip地址分为两大类:a.内网Ip(局域网Ip)如果一个Ip地址是以10.* 或者172.16. -172.31或者192.168.*开头 (符合上述一个条件即可)在同一个局域网内部,内网Ip之间不能重复;在不同的局域网中,内网Ip之间,可以重复。b.外网IP(广域网)除上述的,剩下的都是外网Ip。外网Ip始终都不允许重复,务必唯一。
优势:“纯软件的方案”。让局域网内网设备可以访问外网的设备,而外网设备无法访问内网的设备,保护了电脑的安全。
当前的网络环境,就是以NAT+动态分配的方式来解决Ip地址不够用的问题的,而这个问题最终解是使用Ipv6. 3.IPv6 IPv6使用16个字节来表示Ip地址(是Ipv4-2 ^ 32的四倍,2 ^ 128)足以给地球上每一个沙砾分配一个地址。
3.1.2IP地址
- 网段划分:把一个Ip地址分为两个部分,网络号(标识了一个局域网)+主机号(标识了一个局域网中的一个设备)。
- 同一个局域网中的设备,网络号必须相同,主机号必须不同。相邻局域网的网络号不同。
3.1.3路由选择
描述了IP协议(IP数据报)转发过程。
从A到B的路径有很多,地图软件开了全图的,所以可以直接给出最优解。而IP数据报转发的时候,路由器是无法知道网络的全貌的,只能知道一些局部信息(路由器能直到哪些设备和自己相连),这意味着IP数据再转发的过程中,是一个“探索式”的过程。
一个网络层的数据报,每次到达一个路由器都会进行“问路”的过程。每一个路由器内部都有一个数据结构“路由表”,根据数据报中的目的IP,查路由表,如果查到了(问的人告知怎末走),就按照路由表给定的方向(从哪个网络接口进行转发),继续转发;如果没有(问的人也不知道),路由表内有一个“默认的表项”,按照默认的表象转发。
“路由表”的数据结构可以由1.手动配置2.自动获取(背后的复杂生成算法)
四、数据链路层
这里也有很多协议,较为常见常用的,就是“以太网协议”——通过网线/光纤来通信的协议。以太网,横跨数据链路层+物理层。
以太网数据帧,格式:帧头+载荷(IP数据报)+帧尾。

mac地址是6位的,地址目前是够用的,每一个设备都有唯一的mac地址。
- Ip地址和mac地址的用途?
Ip协议立足于全局,完成整个通信过程的路径规划;以太网则是关注于局部两个设备之间的通信过程。
五、应用层
- DNS 应用层协议&一套系统(域名解析系统):使用IP地址,来描述设备在网络中的位置。NDS把域名和IP地址的映射关系保存下来,如果你想要访问一个域名,就先给这个DNS服务器发起请求,查询当前域名对应的IP,然后再访问目标网站,后续如果有域名的更新,只要更新这一组指定的服务器即可,不需要修改每个用户的hosts。
- 网址的Ip地址不适合宣传,所以就引入了“域名”的概念。例如:www.baidu.com;www.guge.com。再应用域名解析系统把域名翻译成IP地址(域名和IP地址可以看作一组键值对)。最早的域名解析系统是通过一个简单的的文件来实现的——hosts文件。
- 问题:世界上每一刻都有很多设备要进行DNS请求,一组DNS服务器,能抗住这莫高的请求量吗?(一个服务器的硬件资源(CPU,内存,硬盘,,网路宽带…)是有限的,服务器没处理一个请求,都要消耗一定的资源,单位时间内消耗的资源超过了机器本身的资源上线,机器不就挂了吗?)
- 答:这种”高并发“的问题,核心思路就两条:
- **1.开源 ** 搭建DNS的人号召网路运营商,自己搭建一组“DNS 镜像服务器”,镜像服务器的数据,则有他们来同步,此时每一个用户就会优先访问离自己最近的镜像服务器。
- 2.节流(让请求量减少,让上网的设备搞本地缓存) 电脑一分钟内访问一个网站10次,只是让第一次请求DNS即可,把得到的结果把存在本地,后面9次请求都使用第一次结果即可(域名的变换并不频繁)。
- 所以一般进行DNS解析,访问的就是就近的运营商镜像。
其他
- 相对于UDP来说,TCP在更多的情况下,更有优势,所以很多时候,都是优先考虑使用TCP
- 传输层关注的是出发地和目的地;网络层关注的是两地之间的路径;数据链路层关注的是相邻结点的转发方式(坐飞机/火车)

1403

被折叠的 条评论
为什么被折叠?



