网络为什么要分层呢?
复杂的程序都要分层,这是程序设计的要求
所谓的二层设备、三层设备,都是这些设备上跑的程序不同而已。一个 HTTP 协议的包经过一个二层设备,二层设备收进去的是整个网络包。这里面 HTTP、TCP、 IP、 MAC 都有。什么叫二层设备呀,就是只把 MAC 头摘下来,看看到底是丢弃、转发,还是自己留着。那什么叫三层设备呢?就是把 MAC 头摘下来之后,再把 IP 头摘下来,看看到底是丢弃、转发,还是自己留着。
- 只要是在网络上跑的包,都是完整的。可以有下层没上层,绝对不可能有上层没下层。
- 当交换机的数目越来越多的时候,会遭遇环路问题,让网络包迷路,这就需要使用 STP 协议,通过华山论剑比武的方式,将有环路的图变成没有环路的树,从而解决环路问题。
- stp中如果有掌门死掉了,又得全部重选一次,用的时间比较长,期间网络就会中断的。
- 交换机数目多会面临隔离问题,可以通过 VLAN 形成虚拟局域网,从而解决广播问题和安全问题。
- ICMP 相当于网络世界的侦察兵。我讲了两种类型的 ICMP 报文,一种是主动探查的查询报文,一种异常报告的差错报文;
ping 使用查询报文,Traceroute 使用差错报文。
- Traceroute 的第一个作用就是故意设置特殊的 TTL,来追踪去往目的地时沿途经过的路由器
- Traceroute 还有一个作用是故意设置不分片,从而确定路径的 MTU。
许多人问:tracerouter发udp,为啥出错回icmp?
正常情况下,协议栈能正常走到udp,当然正常返回udp。
但是,你主机不可达,是ip层的(还没到udp)。ip层,当然只知道回icmp。报文分片错误也是同理。
MAC 地址是一个局域网内才有效的地址。因而,MAC 地址只要过网关,就必定会改变,因为已经换了局域网。两者主要的区别在于 IP 地址是否改变。不改变 IP 地址的网关,我们称为转发网关;改变 IP 地址的网关,我们称为 NAT 网关。
- 路由分静态路由和动态路由,静态路由可以配置复杂的策略路由,控制转发策略;
- 动态路由主流算法有两种,距离矢量算法和链路状态算法。基于两种算法产生两种协议,BGP 协议和 OSPF 协议。
- 所谓的建立连接,是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,用这样的数据结构来保证所谓的面向连接的特性。
- 我们可以这样比喻,如果 MAC 层定义了本地局域网的传输行为,IP 层定义了整个网络端到端的传输行为,这两层基本定义了这样的基因:网络传输是以包为单位的,二层叫帧,网络层叫包,传输层叫段。我们笼统地称为包。包单独传输,自行选路,在不同的设备封装解封装,不保证到达。基于这个基因,生下来的孩子 UDP 完全继承了这些特性,几乎没有自己的思想。
- 对于多播,我们在讲 IP 地址的时候,讲过一个 D 类地址,也即组播地址,使用这个地址,可以将包组播给一批机器。当一台机器上的某个进程想监听某个组播地址的时候,需要发送 IGMP 包,所在网络的路由器就能收到这个包,知道有个机器上有个进程在监听这个组播地址。当路由器收到这个组播地址的时候,会将包转发给这台机器,这样就实现了跨路由器的组播。
- 由于维护 TCP 连接需要在内核维护一些数据结构,因而一台机器能够支撑的 TCP 连接数目是有限的,然后 UDP 由于是没有连接的,在异步 IO 机制引入之前,常常是应对海量客户端连接的策略。
- 一方面,物联网领域终端资源少,很可能只是个内存非常小的嵌入式系统,而维护 TCP 协议代价太大;另一方面,物联网对实时性要求也很高,而 TCP 还是因为上面的那些原因导致时延大。
- 如果将 TCP 比作成熟的社会人,UDP 则是头脑简单的小朋友。TCP 复杂,UDP 简单;TCP 维护连接,UDP 谁都相信;TCP 会坚持知进退;UDP 愣头青一个,勇往直前;
- UDP 虽然简单,但它有简单的用法。它可以用在环境简单、需要多播、应用层自己控制传输的地方。例如 DHCP、VXLAN、QUIC 等。
- 我看到有的同学说,TCP是建立了一座桥,我认为这个比喻不恰当,TCP更好的比喻是在码头上增加了记录人员,核查人员和督导人员,至于IP层和数据链路层,它没有任何改造。
- 通过对 TCP 头的解析,我们知道要掌握 TCP 协议,重点应该关注以下几个问题:
- 顺序问题 ,稳重不乱;
- 丢包问题,承诺靠谱;
- 连接维护,有始有终;
- 流量控制,把握分寸;
- 拥塞控制,知进知退;
- TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更
TCP 握手为什么是 3 次,而不是 2 次?或者 4 次?
- a 发送了连接请求,需要有 b 的回复,因此两次是必须要有的,但是 b 的回复包可能中途丢失,或者 a 已经挂掉了,因此 b 也需要得到 a 的答复,只有收到 a 的应答包才表示连接建立了。
- 当然为了确认 a 的应答包已经发到 b 了,最好 b 也能够发送一个确认包,但是一旦这样就没完没了了。所以 4 次握手也是可以的,甚至 40 次也行。但是不管再多次都不能保证可靠。所以只要消息有去有回,也就基本可以了。
TCP 连接的序号为什么不从 1 开始发送?
例如,A 连上 B 之后,发送了 1、2、3 三个包,但是发送 3 的时候,中间丢了,或者绕路了,于是重新发送,后来 A 掉线了,重新连上 B 后,序号又从 1 开始,然后发送 2,但是压根没想发送 3,但是上次绕路的那个 3 又回来了,发给了 B,B 自然认为,这就是下一个包,于是发生了错误。
因而,每个连接都要有不同的序号。这个序号的起始序号是随着时间变化的,可以看成一个 32 位的计数器,每 4 微秒加一,如果计算一下,如果到重复,需要 4 个多小时,那个绕路的包早就死翘翘了,因为我们都知道 IP 包头里面有个 TTL,也即生存时间。
我对TCP,甚至整个网络知识,喜欢用「信息论」中的一些理论去推演它们。我觉得在现在和未来的时代,「信息论」是一把利器。
信息论中,有个很重要的思想:要想消除信息的不确定性,就得引入信息。将这个思想应用到TCP中,很容易理解TCP的三次握手和四次挥手的必要性:它们的存在以及复杂度,就是为了消除不确定性,这里我们叫「不可靠性」吧。拿三次握手举例:
为了描述方便,将通信的两端用字母A和B替代。A要往B发数据,A要确定两件事:
1. B在“那儿”,并且能接受数据 —— B确实存在,并且是个“活人”,能听得见
2. B能回应 —— B能发数据,能说话
为了消除这两个不确定性,所以必须有前两次握手,即A发送了数据,B收到了,并且能回应——“ACK”
同样的,对于B来说,它也要消除以上两个不确定性,通过前两次握手,B知道了A能说,但是不能确定A能听,这就是第三次握手的必要性。
当然你可能会问,增加第四次握手有没有必要?从信息论的角度来说,已经不需要了,因为它的增加也无法再提高「确定性」
- 顺序问题、丢包问题、流量控制都是通过滑动窗口来解决的,这其实就相当于你领导和你的工作备忘录,布置过的工作要有编号,干完了有反馈,活不能派太多,也不能太少;
- 拥塞控制是通过拥塞窗口来解决的,相当于往管道里面倒水,快了容易溢出,慢了浪费带宽,要摸着石头过河,找到最优值
- 在 NALU 头里面,主要的内容是类型 NAL Type。
- 0x07 表示 SPS,是序列参数集,包括一个图像序列的所有信息,如图像尺寸、视频格式等。
- 0x08 表示 PPS,是图像参数集,包括一个图像的所有分片的所有相关信息,包括图像类型、序列号等。
- 一个视频,可以拆分成一系列的帧,每一帧拆分成一系列的片,每一片都放在一个 NALU 里面,NALU 之间都是通过特殊的起始标识符分隔,在每一个 I 帧的第一片前面,要插入单独保存 SPS 和 PPS 的 NALU,最终形成一个长长的 NALU 序列。