AI摘要:本文详细介绍了网络原理,包括传输层的UDP和TCP协议,网络层的IP地址和路由选择,数据链路层的以太网和MTU,以及应用层的DNS、NAT和NAPT。UDP协议无连接、不可靠,适用于小数据量传输;TCP协议可靠、面向字节流,通过确认应答、超时重传等机制保证数据传输。IP地址用于网络层寻址,而MAC地址用于数据链路层。DNS用于域名解析,NAT解决IPv4地址不足问题,NAPT允许多个设备共享一个公网IP。文章还讨论了NAT的缺陷。
Powered by AISummary.
网络原理
一.传输层(UDP报文)
1.1 UDP报文结构
UDP是传输层协议之一,其主要特点是无连接,不可靠传输,面向数据报,全双工
UDP报文主体分为两个部分:UDP报头(占8个字节)+UDP数据/UDP载荷
UPD报头:源端口号+目的端口号+数据报长度+校验和
源端口号和目的端口号
- 源端口号和目的端口号均占用16个比特位,即为2个字节
UDP长度
- 总共16位,占两个字节
- UDP报文长度=UDP报头(首部)+UDP载荷
- 2个字节能表示的数据范围是0~65535,也就是能够表示的报文长度是65536字节(Byte),转换成KB,65536/1024 = 64 KB 这就是一个UDP报文所能表示的最大长度.
校验和
- 数据在传输的时候,本质上是0/1bit流,通过光信号或者电信号来表示,如果在传输的时候收到干扰,就可能会出现比特翻转现象.这个时候就需要校验和校验数据是否出错.
1.2UDP报文特点
1.无连接
知道对端的 IP 和端口号就直接进行传输,不需要建立连接;
2.不可靠
没有任何安全机制,发送端发送数据报以后,如果因为某些问题无法发送到对端, UDP 协议层也不会给应用层返回任何错误信息;
3.面向数据报
应用层无论交给 UDP 多大的报文,UDP原样发送,不会拆分或者合并;
4.缓冲区
UDP 只有接收缓冲区,没有发送缓冲区
5.大小受限
UDP 协议首部中有一个 16 位的最大长度。也就是说一个 UDP 能传输的数据最大长度是 64K (包含 UDP首部)。
1.3 基于UDP的应用层协议
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
二.传输层(TCP报文)
2.1 TCP报文结构
源/目的端口号:表示数据是从哪个进程进入,从哪个进程出去
32位序号/32位确认号:后面详细讲;
4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是
15 * 4 = 60
6位标志位:
- URG:紧急指针是否有效
- ACK:确认号是否有效
- PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
- RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
- SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
- FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段
16位窗口大小:后面再说
16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不光
包含TCP首部,也包含TCP数据部分。
16位紧急指针:标识哪部分数据是紧急数据;
40字节头部选项:暂时忽略;
2.2 TCP特点
- 有连接
- 可靠传输
- 面向字节流
- 全双工
其中,可靠传输是TCP最为重要的一点,TCP是通过六个重要的机制来实现的这一点
2.2.1 确认应答
确认应答是TCP最为核心的机制,支持了TCP的可靠传输
发送方将数据发送给接收方之后,接收方收到数据就会返回一个竞答报文(ack,acknowledge)
发送发,如果收到了这个应答报文,就知道自己的数据是否发送成功了。
但当连续发送多条数据时,可能会出现"先发后至"即某个数据时先发的,反而晚到了,例如图中的情况。
那么为什么会出现先发后至呢?
因为网络上从A->B的路线有很多,两个包从A->B走的路线并不一定是相同的。另外每个节点(交换机/路由器)的繁忙程度也是不同的。此时数据包传输就像过红绿灯一样,有的先到,有的后到了。
TCP在此处就要完成两个工作:
1.确保应答报文和发送输出的数据能对上号,不要出现歧义
2.确保在出现后发后至的现象时,能够让应用程序仍然按照正确顺序来理解数据
TCP将每个字节的数据都进行了编号,即为序列号。
每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。确认序列号的数值就是收到的最后一个字节编号再+1
这里所说到的序列号,就是图中的32位序号和32位确认序号。序号占用 4 字节,即 32 位。也就是说表示的数据范围是42亿9千万,即为4GB。
其次,TCP报头中记录的序号,是这一次传输的在和数据中第一个字节的序号,剩下其他字节的序号,都需要依次的推出。
那么我们是如何区分这是普通报文还是确认应答报文呢?
ACK为0即表示这是一个普通报文,此时只有32位序号是有效的
ACK为1即表示这是一个应答报文,这个报文的32位序号和确认序号都是有效的
2.2.2超时重传
确认应答机制,描述的是一个比较理想的情况,如果网络传输过程中出现了丢包,怎么办?
路由器/交换机就像一个交通枢纽一样,结构复杂,传输的数据量也不确定,如果设备此时过于繁忙,后面新来的数据等太久了就会被抛弃,网络负载越高,就越繁忙从而容易丢包。
例如当我们ping一个网站时候,如果提示请求超时,那么就意味着发生了丢包现象,此时网站多半是负载过高(禁ping情况除外)。
那么这时超时重传机制就发挥了重大作用,超时重传相当于针对确认应答机制做出的重要补充!
站在发送方的角度,是无法区分这两种情况的,无论发生哪一种,都需要重传。第一次丢了,重传一下试试,很大概率就能传过去。
因此接收方会收到很多重复数据。那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。
那么tcp是如何去重的呢?
TCP会在内核中,给每个socket对象都申请一个内从空间,相当于一个队列,类似生产者消费者模型,也被称作“接受缓冲区”。接收到的数据都会被存放在这里,并按照序号进行排序。此时就可以轻松地找到新接收到的数据是否重复了。
那么,超时重传的时间如何确定?
- 最理想的情况下,找到一个最小的时间,保证 "确认应答一定能在这个时间内返回"。
- 但是这个时间的长短,随着网络环境的不同,是有差异的。
- 如果超时时间设的太长,会影响整体的重传效率;
- 如果超时时间设的太短,有可能会频繁发送重复的包;
TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间。
- Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定
- 超时重发的超时时间都是500ms的整数倍。
- 如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。
- 如果仍然得不到应答,等待 4*500ms 进行重传。依次类推,以指数形式递增。
- 累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接。
2.2.3 连接管理
2.2.3.1 三次挥手
在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接
tcp这里的握手,类似于给对方传输一个简短的,没有业务的数据报,通过这个数据报,来唤起对方的注意,从而触发后续操作。
握手这个操作并非是TCP独有的,甚至不是网络通信独有的,在计算机中很多操作都会涉及到握手。
例如手机充电头的快充协议
U盘的3.0 2.0端口
......
TCP的三次握手.TCP在建立连接的过程中,需要通信双方一共打三次招呼才能建立连接。
A想和B建立连接,A就会主动发起握手操作。实际开发中,主动发起的一方就是所谓的“客户端”,被动接受的乙方就是“服务器”。此时我手完成,A和B记录了对方的信息。
建立连接的过程,其实是通信双发都要给对方发送SYN,也要给对方返回ack。一共是4次握手,但是中间的两次恰好可以合并成一次。
三次握手的作用
- 投石问路,确认当期网络是否畅通
- 让发送方和接收方都能确认自己的发送能力和接受能力均正常
- 让通信双方,在握手过程中,针对一些重要的参数,进行协商
协商:握手这里的协商信息是有很多的,例如tcp通信过程中的序号从几开始,就是双方协商出来的,每次建立连接的时候,都会写上出一个比较大的,和上次不一样的数值
这种协商设定,是避免了“前朝的剑,斩本朝的官”
当网络不好时,客户端和服务端之间可能会断开连接,再重新建立连接.重连的时候,就可能在新的连接好了之后,旧连接的数据姗姗来迟。这种迟到的数据就应该毒气,不能让上个朝代的数据影响本朝的业务逻辑。
那么如何区分数据是否来自上个朝代呢?
则可以通过上述序号来区分,如果收到的数据序号和当前正常数据序号差异非常大,则可以判定是上个朝代的数据就可以直接丢弃了。
2.3.3.2四次挥手
建立连接一般是由客户端主动发起
断开连接,客户端和服务端都可以主动发起
四次挥手和三次握手不同.此处的四次挥手能否把中间的两次交互合二为一呢?不一定!
不能合并的原因是ACK和第二个FIN的触发时机是不同的。ACK是内核的响应,B收到FIN就会立刻返回ACK。但是第二个FIN是应用程序的代码处罚的。B这边调用了close()方法才会触发FIN。
FIN就会在socket对象click时被发起,可能是手动调用close方法,也可能是进程结束。
像前面的三次回收,ACK和第二个SYN都是同一时间内核触发的,可以合并
这里的四次挥手,ACK是内核触发的,第二个FIN是应用程序执行close触发的,时机不同不能合并。
但是TCP还有一个机制,延时应答,能够拖延ACK的回应时间,一旦ACK滞后,就有机会和下一个FIN合并在一起了。
哪一方主动断开连接,那一方就会进入TIME_WAIT状态。TIME_WAIT状态存在的意义在于,防止最后一个ACK丢失,留的一个后手。
如果最后一个ACK丢失。
站在B的角度,B就会超时重传,重新发送一遍FIN
如果刚才A没有TIME_WAIT状态,就意味着A这时就已经真正的释放连接了。此时重传的FIN也就没人处理,没人能够返回ACK了,不永远也收不到ACK了
A这边使用了TIME_WAIT状态机就会进行等待,等待的这个时间就是为了处理后续B重传的FIN。此时有重传的FIN来了,就可以继续返回ACK。
那么TIME_WAIT状态持续多久呢?
建设网络上两个节点通信消耗的最大时间为MSL,此时TIME_WAIT的等待时间就是2MSL。
2.3.4滑动窗口
前面所讲的三个机制,都是在保证tcp的可靠性。而滑动窗口的目的是为了提高效率,缩短确认应答的等待时间。
既然这样一发一收的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)。
批量传输数据,就是不等ack返回,直接发送下一个数据。但批量传输也不是“无限的”传输。批量传输也是存在一定的上限,达到上限之后,再统一ACK
- 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。上图的窗口大小就是4000个字节(四个段)。
- 发送前四个段的时候,不需要等待任何ACK,直接发送;
- 收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据;依次类推;
- 操作系统内核为了维护这个滑动窗口,需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉;窗口越大,则网络的吞吐率就越高;
TCP的初心是“可靠传输”上述滑动窗口中,确认应答是可以正常工作的,但是如果出现了丢包咋办?这里的重传,相比于前面的超时重传又有了变化。
情况一.ACK丢失
这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认;
确认序号,表示的含义是,当前序号之前的数据已经确认到了,下一个应该从确认序号这里,继续发送。如果1001这个ack丢失,但是2001ack到了,那么就代表2001之前的数据已经确认传输成功了,涵盖了1001的情况。
由于1001~2000这个数据丢失了,此处返回的ack仍然是索要1001,无论当前传输的数值是多少,都会一直索要1001这个数据,但这个过程中B仍然会接受数据,并把接受的数据默默地存起来。
此时主机A看到B连续的几个ACK都是在索要1001,A就会重传一次1001。1001~2000顺利到达,B所要的就变成了7001
如果通信双方传输的数据量比较小,也并不频发,就仍是使用普通的确认应答和普通的超时重传
如果通信双方,传输数据量更大,也比较频繁,就会进入到滑动窗口模式,按照快速重传的方式处理
2.2.5 流量控制
站在接收方的角度,反向制约发送方的传输速率
发送方发送的速率,不应该超过接收方处理的能力
数据到达B的系统内核中时,tcp socket对象上带有接受缓冲区。A -> B发送的数据,就会先到达B的接受缓冲区。
B再通过应用程序调用read这样的方法,把接受缓冲区中的数据读出来,进一步进行处理。类似一个生产者消费者模型。0
- 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段,通过ACK端通知发送端;
- 窗口大小字段越大,说明网络的吞吐量越高;
- 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;
- 发送端接受到这个窗口之后,就会减慢自己的发送速度;
- 如果接收端缓冲区满了,就会将窗口置为0;这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
接收端如何把窗口大小告诉发送端呢?回忆我们的TCP首部中,有一个16位窗口字段,就是存放了窗口大小信息;
那么问题来了,16位数字最大表示65535,那么TCP窗口最大就是65535字节么?
实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是 窗口字段的值左移 M 位;
2.2.6拥塞控制
虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据。但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题。
因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的。
TCP引入 慢启动 机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据,随着窗口大小不断增大,达到一定程度,可能中间的节点就会出现问题了,此时这个节点发送方发现丢包了,就把窗口大小调整小。此时如果发现还是继续丢包,就继续缩小,如果不丢包了就继续尝试增大。
在这个过程中,发送方不停地调整窗口大小,逐渐达成动态平衡。这种做法就相当于把所有中间节点看做成一个整体,通过实验的方式,来找到中间节点的瓶颈在哪里。
流量控制 拥塞控制
都是在限制发送方发送的窗口大小,最终发送的窗口大小,取决于流量控制和拥塞控制中窗口的较小值。
2.2.67延时应答
正常情况:A把数据传输给B,B就会立刻返回ack给A
延时应答:A传输给B,此时B等一会再返回ACK给A
延时应答本质上也是为了提升传输速率。发送方的窗口大小,就是传输效率的关键。
假设接收端缓冲区为1M。一次收到了500K的数据;如果立刻应答,返回的窗口就是500K。但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了。在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来。如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M。
一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高。我们的目标是在保证网络不拥塞的情况尽量提高传输效率;
也是延时应答,促成了四次挥手,能够三次挥完。
2.2.8 捎带应答
在延时应答的基础上,进一步提高效率。(类似于四次挥手中FIN和ACK一同发回的情况)网络通信过程中,往往是这种“一问一答”这样通信模型。
ack是内核立即返回的,response则是应用程序代码来返回的。由于TCP引入了延时应答,ACK不一定是立即返回,可能要等一会。在这过程中,B正好把response计算好了,计算好之后就会把response返回,于是顺便把刚才要返回的ack带上了。此时ACK和response就合并成一个数据了。
2.2.9面向字节流
这里有一个重要的问题,粘包问题(并非TCP独有的,所有面向字节流的机制都有类似情况)
此处包是指应用层数据报,如果同时有多个应用层数据包被传说过去,此时就容易出现粘包问题。
站在传输层的角度,TCP是一个一个传输过来,并按序号排列好的。但站在应用层的角度,看到的只是一串连续的数字。
相比之下,像UDP这样的面向数据包的通信方式,就不会出现上述情况。
UDP接受缓冲区里的数据,就相当于一个一个的DatagramPacket对象。应用程序读取的时候,能清晰的知道哪里到哪里是一个完整的数据。使用UDP的时候,要么收到完整的UDP报文,要么什么也不收。 不会出现收到半份数据包的情况。
那么如何避免出现粘包问题呢?
- 对于定长的包,可以固定读写大小
- 对于变长的包,可以在报头写入数据长度
- 对于变长的包,也可以在包与包之间使用不和正文数据冲突的分隔符来隔开。
2.2.10 异常情况的处理
如果在使用tcp的过程中,出现了意外如何处理呢?
2.2.10.1 进程崩溃
进程崩溃后,文件描述表也就释放了,等于钓鱼了socket.close()。此时可以正常触发FIN,对端收到后,返回FIN和ACK,这边再发发回ACK。和和正常关闭没有区别。
TCP连接是可以独立于进程存在的。进程崩溃,TCP连接不一定消失
2.2.10.2 主机关机(正常情况)
主机关机时,会强制终止进程(相当于进程崩溃)
此时就会和进程崩溃一样,本机发送FIN,对端返回FIN和ACK,本机再发出ACK。
但上面的情况是理想情况,即为对端发送的ACK和FIN在本机系统关闭前到了,本机才可能返回FIN。
如果ACK和FIN在系统关闭后才来,那么对端就会认为是自己的FIN丢包了,会多次重传FIN,多次重传无果后,会自动放弃连接。
2.2.10.3 主机掉电(非正常情况)
主机掉电为一瞬间的事,所以来不及发送FIN。
- 接收方掉电:对端发送数据后会一直等待接收方返回ACK。从而触发超时重传,多次重传无效后,就会 进行reset操作(发送复位报文段)进行连接重置功能。如果符文报文段发送后也没有效果,此时就会释放连接
- 发送方掉电:对端会一直等待接收数据,此时对端是无法判断是丢包还是对方离线了。接收方会定时的给发送方发送一个不携带数据的特殊包(心跳包),询问对端是否在线,若多次五回应,就会释放连接
2.2.10.4 网线断开
和主机掉电情况相似
上述十种情况,是TCP中是个比较重要的机制。
2.3.1 总结
可靠性:
- 校验和序列号
- 确认应答
- 超时重发
- 连接管理
- 流量控制
- 拥塞控制
提高性能:
- 滑动窗口
- 快速重传
- 延迟应答
- 捎带应答
三.网络层
3.1IP地址
IP协议:是TCP/IP协议中最为核心的协议
TCP/IP协议网络上每个适配器都有唯一的IP地址
IP地址是一个32位的地址,IP地址通常被分为4段,每8个二进制为一段。为了方便阅读,通常会将每段转为十进制显示。eg 192.168.0.1/8.8.8.8
上面我们说IP地址是一个32位地址,32位整数表示的数据范围 是42亿9千万,这就造就了IP地址是非常稀缺的。故我们通常使用如下方法来解决
- 动态分配
NAT网络地址转换(主流方案)
将IP分为内网IP和公网IP
内网IP:局域网内不可重复,内网设备在访问外网时,通过路由器NAT设备进行转换
公网IP:公网IP不能重复
IPv6
IPv6使用16个字节来表示ip,IPv6的数量之大不亚于给地球上每一粒沙子都分配一个ip,但IPv6对比IPv4来说是一个全新的协议,需要更换硬件设备,故普及度较低(中国的大部分单位企业均以适配IPv6)
IP地址分为两部分,网络ID和主机ID
同一个局域网中的设备,网络号必须相同,主机号必须不同
一个IP地址,那部分是网络号,哪部分是主机号并不是确定的。我们可以通过子网掩码来判断
子网掩码同IP地址一样,也都是32位的整数,左侧都是1,右侧都是0,被标记成1的部分就是网络号
例如我的子网掩码为:11111111 11111111 11111111 11111111 10000000
3.1.1 分包组包
1.数据包是什么?
数据包是TCP/IP协议上通信传输中的数据单位,简称为'包',也可以叫为'分组'.
数据包主要作用于网络层中,起始地与目的地都是网络层.在第三层的分组传输中.
像我们平时上网,其实就是数据包的交换.当我们访问网站的时候,会向服务器发送一个包进行请求,服务器在接受到请求后并作出响应,如果服务器允许我们的访问则会返回相应的数据包给我们.网页上呈现出的内容就是这样传输过来被我们看到的.
2.数据包的结构
一个数据包主要分成两个部分:控制信息和负载.
- 控制信息则是表头部分,装载着'五元组'之类的信息,表明了数据的来处与去处的信息
- 负载则是本身要传输的数据本身.
3.分包是什么?为什么需要分包呢?
每一种物理网络都会规定链路层数据帧的最大长度,称为链路层MTU(Maximum Transmission Unit).
IP协议在传输数据包的时候,如果一个完整的数据长度大于MTU的时候,就会把一个数据包分成若干份进行传输.这个过程就叫做分包/分片.被分出来的每一个数据包中的包头还会含有原数据包的五元组、偏移量和其他报头信息。偏移量主要用来在传输过后数据包的组包过程中给数据排序使用.
分包除了可以让数据在一定规格内传输,还因为一个较大的数据包会占用较多的带宽,容易造成网络的拥塞.而分包可以在一定程度上减轻这种情况,提高传输效率.
4.组包是什么?
在数据包进行分包后,目标主机收到的就不是一个完整的数据包了,而是许多小的数据包.将这些被分包过后的数据包进行组装恢复成为原来完成的IP数据包的过程就成为组包
5.分包组包过程中和哪些 IP 报头字段有关联?
对于分包,通俗的话来说就是讲一支完整的队伍拆成固定人数的小组进行通过.
校验和字段(Header Checksum): 对于传输的小组中的人员,在经过时要检查小组中的人员是否与原来发出的人员一致,这时就要通过校验和来检验数据包在传输的过程中是否遭到了破坏。在 IP 数据包传输过程中,每个路由器都会重新计算这个校验和字段,以确保数据的完整性。
标识符字段(Identification): 在传输过程中,发送端发送的完整数据包并非只有一个,每发送一个数据包,报头的标识符就会+1.对于分片/分包后的数据包,在目标主机中该怎么知道哪一些分片后的数据包该放在一堆呢?就可以通过标识符来辨别这个小组是哪一个大队伍的.
标志位字段(Flags): 对于目标主机来说,不知道对方传来的数据包总的规格是多少,被分成了多少包.这时就可以通过标记位来辨别.对于被分片/分包后的数据包们,只有最后一位的数据包的标记位的最后一位为0,其余的数据包的标记位的最后一位都为1.1表示为,后面还有同一个队伍的数据包要到达.0则表示我是这一组的末尾咯,后面已经没有本组的数据包了.
片偏移字段(Fragment Offset): 数据包分片传输后,对于原来数据最重要的就是这些分段数据的顺序了.只有每一小段的数据的顺序都对的上才能重新在目标主机中恢复成原来的模样。偏移量指示当前片段在整个原始数据包中的位置。例如,偏移量为 0 的片段包含数据包的头部。
协议字段(Protocol):协议字段用于指示 IP 数据报携带的数据的协议类型。例如,1 表示 ICMP 协议,6 表示 TCP 协议,17 表示 UDP 协议等。这个字段是在组包过程中进行处理的。
6.组包时如何保证数据的顺序和完整性?
片偏移字段:每个 IP 片段的片偏移字段指示该片段在原始数据包中的位置。接收方可以利用这些字段将片段按照正确的顺序进行组装。
标识符字段:每个 IP 数据包都有一个唯一的标识符字段。接收方可以利用这个字段将不同的 IP 片段与正确的数据包相匹配。
更多片位标记:如果一个 IP 数据包被分成多个片段,则每个片段的“更多片位”标记位指示是否还有更多的 IP 片段等待接收。接收方可以利用这个标记位来确定是否已经接收到所有的 IP 片段。
排序和重组:当接收方收到所有的 IP 片段后,需要按照片偏移字段对它们进行排序,并将它们重组为原始数据包的完整形式。
计算校验和:当接收方重组 IP 片段时,需要重新计算 IP 报头的校验和字段以验证数据包的完整性和正确性。如果计算出的校验和与原始 IP 报头中的校验和不匹配,则表明数据包已经被损坏。
3.2路由选择
路由选择,就是描述了IP协议(IP数据报)转发的过程
进行IP数据报转发时,每个路由器都不知道网络的“全貌”,只知道和自己相连的一些设备。这就意味着IP数据报在转发时是一个探索的过程。
网络层的数据包,每到达一个路由器,就会进行类似问路的操作,摸索前进
每一个路由器颞部都有一个“路由表”,根据IP数据包中的目的IP查找路由表
如果查到了,就直接按照路由表给定的方法,继续转发
如果没查到,就按照路由表的默认表进行转发
四.数据链路层
4.1以太网
以太网,横跨数据链路层+物理层
以太网数据帧格式:帧头+载荷+帧尾
- 源地址和目的地址(均为6个字节)是指网卡的硬件地址(也叫MAC地址),长度是48位,是在网卡出厂时固
化的; - 帧协议类型字段有三种值,分别对应IP、ARP、RARP;
- 帧末尾是CRC校验码
MAC地址是网卡出场时写死的,每个硬件有其唯一的MAC地址,MAC地址也是溯源的途径之一。
IP地址和MAC地址各自的用途是什么?
- IP协议立足于全局,完成整个通信过程的路径规划
- 以太网的MAC则是关注局部,负责相邻设备的通信过程
eg:我从我家到学校,需要经历的过程如下
家里->天津站
(源IP:家,目的IP:学校 | 源mac:家,目的mac 天津站)
天津站->北京南站
(源IP:家,目的IP:学校 | 源mac:天津站,目的mac 北京南站)
北京北站->呼和浩特站
(源IP:家,目的IP:学校 | 源mac:北京北站,目的mac 呼和浩特站)
.......
4.2 APR和RAPR
APR和RAPR这两种协议并不传输业务数据,而是辅助转发的协议
交换机在收到以太网数据帧时就需要进行转发。(转发过程需要根据mac地址判断数据走哪个网口)
交换机内部有一个“转发表”类似前面的“路由表”
转发表类似于hash表这样的映射,转发表主要就是通过arp协议生成的
4.3 MTU
MTU:数据链路层的数据包能携带的最大载荷长度
- 以太网帧中的数据长度规定最小46字节,最大1500字节,ARP数据包的长度不够46字节,要
在后面补填充位;- 最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU;
- 如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对
数据包进行分片(fragmentation)- IP数据包的分包大概率是因为MTU引起的,而不是触发64kb上限引起的
- 不同的数据链路层标准的MTU是不同的;
五.应用层
5.1DNS
TCP/IP中使用IP地址来确定网络上的一台主机,但是IP地址不方便记忆,且不能表达地址组织信息,于是人们发明了域名,并通过域名系统来映射域名和IP地址
最早的我们通过hosts文件来管理域名-IP的对应关系
现在我们通常使用DNS服务器来管理。eg 8.8.8.8 114.114.114.114......
5.2NAT
之前我们讨论了,IPv4协议中,IP地址数量不充足的问题
NAT技术当前解决IP地址不够用的主要手段,是路由器的一个重要功能;
5.3NAPT
那么问题来了,如果局域网内,有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中,
目的IP都是相同的。那么NAT路由器如何判定将这个数据包转发给哪个局域网的主机?
这时候NAPT来解决这个问题了。使用IP+port来建立这个关联关系
5.4NAT的缺陷
- 无法从NAT外部向内部服务器建立连接;
- 转换表的生成和销毁都需要额外开销;
- 通信过程中一旦NAT设备异常,即使存在热备,所有的TCP连接也都会断开;