目录
字节序
出现原因
地址是连续的,在内存中存放多字节数据(比如int,32位是4个字节)就涉及到字节存放顺序的问题。
具体分类
字节在内存中的存储分为“大端模式”和“小端模式”。
大端模式:数值的高位放在地址的低位上。
小段模式:数值的地位放在地址的低位上。
这里有两个概念需要辨析,什么是地址的高低位,什么是数值的高低位。
首先地址的高低位,先说结论“从左到右地址从小到大,从低到高地址从小到大”,这里举两个例子,想想数组,从左到右,分别是0,1,2,3...,从左到右底质递增;想想栈在内存的布局,栈底在高地址处,向下生长,从低到高地址递增。
数值的高低位,这里说的是权重的概念,位的权重越大,位越高。例如123,1就是高位,因为其位权重代表的是100,而2位权是10,3位权是1,从左到右位从高到低。
还有一个点,这里序的基本单位是字节,字节本身的顺序并不改变,小端大端模式本身影响的只是字节之前的存储。
举例说明
例如16位的53,写成0x3500就是小端模式,这里是16进制数,一个字节是16进制的两位,所以要排序的字节分别是35和00,其中35属于数值上的低位(位权分别是1和16),00属于数值上的高位(位权分别是16^2,16^3),所以这里把35提前就是数值上的地位放在地址的地位上了,就属于小端模式。写成大端模式就是0x0035,这里可以看出大端模式更符合人类的阅读习惯,所以我们平时写的其实都是大端模式。
区别和应用场景
小端模式和大端模式更有千秋,没有好坏之分。
小端模式:硬件设计比较灵活,无论是32位还是64位,都可以从低地址开始读取字节,因为这都是它的最低有效字节,类型转换比较方便;数学运算遍历,因为加法和乘法都是从最低位开始运算的,小段模式低地址正好是最低有效字节,方便计算。常用x86、ARM(IOS和Android)、现代PC和服务器上。
大端模式:对人类友好,更适合人类阅读。网络协议和部分嵌入式系统。其中网络协议是最重要的应用场景。
这里可以发现大部分的处理器都是小端模式(得益于其便利的计算),而大端模式则在网络协议中·应用,所以网络中拿来的数据一般不能直接在处理器上处理,一般需要进行字节转序才能继续处理。
路由转发
出现原因
路由器在网络中需要转发数据包,但它本身可能有多个接口连接,那么应该如何选择转发接口?
最长前缀匹配原则
在路由器中,存放有配置好的路由表,其中有两个字段,一个是CIDR掩码,一个是下一跳的地址,如下图所示:

如上图路由器有6个端口,当有数据包到来时,它解析其要去的目标IP,之后和自己路由表中的CIDR掩码一一匹配,找到其能匹配的最长掩码,得到其下一条的IP地址,转发数据包。
举例说明

如上图所示,其中对于B选项而言,其能匹配的下一条只有2,4(注意这里1的171.0.15.0/24不匹配),那么这里选择4,因为其CIDR掩码是10位,2只有8位。
ARP协议
概述
ARP(Address Resolution Protocol)地址解析协议,核心功能是在一个局域网内,利用广播,将一个已知的IP地址解析成一个未知的数据链路层地址(这里MAC地址,即以太网地址最常用,以下就以这个代替)。注意ARP也是被具体的数据链路层封装的,即ARP协议整体作为数据被以太网帧头帧尾封装。
局域网和广播
这里先提一下局域网的概念,局域网的定义可以理解为其中一台设备发送一个广播,所有其他设备都能收到这个广播。路由器是局域网(广播域)的边界。以下举两个广播域的例子:
- 在一个子网内。一个子网可以简单包括一个路由器,很多主机通过交换机和路由器都连在一起,在这里任何一个主机发出广播,所有主机包括路由器都能收到。
- 在公网上,一个路由器(A)连着若干个其他路由器(B,C,D...),这构成一个局域网。此时路由器A发出广播,与他相连的所有路由器(B,C,D...)也都能收到广播。此时该路由器A和与他直接相连的其他路由器构成了极小的局域网。
应用场景
ARP的具体作用是将IP地址解析成MAC地址,为什么要解析呢?具体应用场景有以下两个:
- 当一个子网内部不同主机想要通信时,只知道对方的ip地址,具体该如何发送?
- 当路由器查路由表时得知下一跳的ip地址之后,也知道要将数据包送到哪个端口,但端口没有目的MAC地址,不知道该如何发送?
协议字段
具体的协议字段如下图:

- Hardware 硬件字段,表示运行ARP的网络硬件类型,其中0x0001是Ethernet以太网协议,最为常用。
- Protocol 协议字段,定义上层网络层的协议类型。0x0800为IPv4最常用。
- Hardware Length硬件地址长度,定义物理地址的长度,其中MAC地址最常用为0x06.表示为6字节。
- Potocol Length表示协议地址长度,定义网络层IP地址长度,单位是字节,一般是IPv4,0x04表示4个字节。
- Opcode 操作码,定义了该ARP包的功能类型。0x0001是ARP请求,0x0002是ARP应答。
- 之后的数据是可变长地址,根据实际使用的网络层地址和物理地址的长度改变。一般是IP地址和以太网MAC地址。具体包括源MAC地址,源IP地址,目的MAC地址(在请求包中值全为0,但外部的以太网帧头为官博地址全F),目的IP地址。
具体流程
具体流程如下:
- 检查ARP缓存。在应用ARP协议之前,已经拿到了目标的IP地址,在主机/路由器中都有ARP缓存,里面记录了最近的IP地址-ARP地址的映射,如果命中,直接拿来用,否则往下。
- 发起ARP请求(广播)。缓存未命中,主机A在局域网中发起ARP请求广播,其中带有源IP(A)、源MAC(A1)、目标IP(B)、目标MAC(内容为全零,表示自己不知道要对方填空)和L2帧目标MAC(这里为全F,表示以太网广播地址)。这个广播会被局域网内所有主机收到。
- 处理ARP请求。该局域网内其他主机收到ARP请求后,无关设备发现目标IP不是自己,忽略该请求,静默丢弃该包。目标设备发现目标IP是自己,则准备ARP应答,包括源IP(B)、源MAC(B1)、目标IP(A)、目标MAC(A1)和L2帧目标MAC(A1),单播回复。
- 更新缓存并通信。主机A收到主机B的ARP应答后,拿到主机B的MAC地址,更新自己的ARP缓存,并后续和主机B进行通信。
以上为子网内的应用场景,在路由器及其相邻路由器构成的局域网中效果类似。
ARP协议的特殊应用
ARP协议有一些其他用途:
- 免费ARP。这是一个自问自答式ARP,一个设备发送ARP请求,但请求的目标IP是自身。主要用于IP冲突检测(检测该局域网内某个IP是否已经分配)和宣告MAC(告诉局域网内其他主机目前IP地址对应的MAC地址,让他们更新ARP缓存)。
- 代理ARP。一个设备A试图ARP一个不同网段的IP地址(B),中间的路由器配置了代理ARP,会假装自己是B,用自身的MAC地址回应A的ARP请求。这样A以为B就在本地,把要发送给B的数据包全部发送给路由器,路由器再将数据包发送给B。
- ARP欺骗/ARP投毒。从ARP工作流程可知,ARP协议没有验证机制,完全基于信任。这带来了极大的安全漏洞,考虑攻击者C潜入局域网中,向受害者A发视频发送伪造的ARP应答,声称自己是网关R,MAC是C的MAC。随后向网关R发送伪造的ARP应答,声称自己是A,MAC是C的MAC。这样受害者A和网关R的ARP缓存就被“投毒”了。所有A要发送到互联网上的流量都会发送给C(因为A认为C是网关),所有网关发给A的流量也会被发送给C。这样C实现了中间人攻击,获取了A和互联网的所有通信。
TCP协议
TCP协议头格式

- 最重要的Source port和Destination port表示的是源端口和目的端口。
- 接下来是Sequence表示序列号,Acknowledgment Sequence表示确认号。
- 接下来是一些标志位,ACK表示是否是回复的,若此位为0则Ack无效。PSH(PUSH)表示此消息能否等待,若为1说明此消息收到就要立即发送,不能等待其他数据一起发送。SYN和FIN表示同步请求和结束请求。RST表示放弃当前连接,需要重新建立连接。
- Checksum表示检验和,这里的检验和会计算IP层的一些信息(源IP和目的IP),这是因为TCP连接可以通过5个字段唯一标识:源IP,目的IP,源端口,目的端口,协议字段=“TCP”。
三次握手
TCP(Transimition Control Protocol)是建立连接的服务,在正式发送数据前需要先和对方建立连接,数据发送完毕后需要断开连接。之前提到过TCP的三次握手机制,分别是SYN(synchronize)、SYN-ACK(synchronize and acknowledge)、和ACK(acknowledge)。

序列号和确认号
由于TCP需要实现可靠传输,它需要知道数据报哪些到达哪些没到达的情况,所以在建立连接的阶段还会传输序列号和确认号。序列号的作用是标记数据,TCP将连接中发送的每个字节都编上一个号码,ACK是确认号代表的是我希望下次收到的字节的编号。
在三次握手开始时,客户端和服务器都会随机生成一个ISN(Initial Sequence Number),这是为了安全着想,如果初始序列号是有规律或者可预测的则容易被伪造和攻击。随后开始AB的三次握手过程,这里的SYN和ACK表示的标志位,seq和Ack表示的是序列号
- SYN报文,SYN=1,ACK=0,seq=ISN(A),Ack=0(由于ACK=0,所以此位无效)。
- SYN-ACK报文,SYN=1,ACK=1,seq=ISN(B),Ack=ISN(A)+1(SYN包和FIN包虽然不携带上层应用数据,但它本身需要消耗一个序列号,意思就是告诉对方我收到你发送的SYN报文了,现在期望收到你的下一个报文。)
- ACK报文,SYN=0,ACK=1,seq=ISN(A)+1,Ack=ISN(B)+1。
随后,A开始以ISN(A)+1为初始序列号开始发送数据,B开始以ISN(B)+1为初始序列号开始发送数据。
状态变换过程
如上图所示,TCP客户端时主动建立TCB(传输控制块Transimission Ctrol Block),进入CLOSED关闭状态,TCP服务器端被动建立TCB,进入LISTEN监听状态。
- 随后客户端主动发送SYN报文,发送过之后进入SYN-SENT同步已发送状态。
- 服务器端此时处于监听状态,若收到客户端的SYN报文,则进入SYN-RCVD(SYN-RECEIVED)同步已接受状态,并向客户端发送SYN-ACK报文,回复客户端收到其SYN报文,并发送自己的SYN信息。
- 客户端此时处于SYN-SENT同步已发送阶段,若收到来自服务器端的SYN-ACK报文,则进入ESTABLISHED连接已建立阶段,此时对于客户端来说连接已经建立,并发送ACK数据报回复服务器端收到其SYN报文。
- 此时服务器端处于SYN-RCVD同步已接受阶段,若收到来自客户端的ACK报文,则进入ESTABLISHED连接已建立阶段。至此TCP三次握手结束,连接建立。
具体状态变换如下图所示:

TCP的流控制
TCP为什么要有流量控制,考虑发送端发送数据的速度快于接收方处理数据的速度,那么大量数据到接收方以后由于没办法处理而被丢弃,这就浪费了网络资源,所以需要对发送端进行流量控制使得发送端和接收端能够协同,使网络资源得到最大程序的利用。
停止等待协议
最浅显的想法就是发送端的速度不能超过接收端的速度,那么最简单的想法就是每次发送端只能发送一个数据包,随后等待接收端的回复,再发送下一个;同时为了防止回复报文在网络中迷失发送端陷入无限期的等待的情况,在发送端需要设置超时计时器,发送端发送数据包后就需要启动超时计时器,当计时器结束发送端还未收到回复数据包后,则认为自己的数据包没送到或者回复数据包丢失,重新发送该数据包。如下图所示

滑动窗口协议
停止等待协议优势是解决了发送端和接收端协同的问题,但每次发送端只能发送一个数据包,效率太低。滑动窗口协议就是用来解决这个问题的。发送端有一个发送窗口,接收端有一个接收窗口,一般而言发送窗口<接收窗口。在停止等待协议的基础上,发送端每次只能发送窗口内的数据包,接收端根据收到的数据包,发送ACK累计应答数据包,发送端根据收到的ACK数据包的情况滑动窗口向后移动,发送后面的数据包。同时发送端的发送窗口同样对每个数据包有超时重传机制。具体如下图所示:

回退N步 VS 选择重传
考虑在滑动窗口的基础上,如果发送端发送了1,2,3三个数据包,但数据包2丢失了,接收端收到数据包1,3由于2丢失,所以只能回应ACK2.在接收端看来,2丢失了2一定是要重传的,那么后续的3呢?这就有两种策略回退N步和选择充传策略。
- 回退N步。丢失的报文及其之后的报文(窗口内的)全部重传。这种策略大部分应用于接收方无法收到乱序包的情况,回到上述例子,由于2的丢失,即使3被接收方收到但由于无法处理乱序包,故丢弃。而发送方由于知道接收方无法收到乱序包的情况,所以一旦计时器超时(注意这里只有一个计时器维护未确认队列队头的TCPSegment),他的策略就是将超时的TCPSegment和之后的都重传。现代大部分都放弃此策略了。
- 选择重传。和回退N步不同,在TCP的Option字段中加入SACK应答,普通的ACK是累积应答,这个就是单个数据包应答。回到上述例子,接收端收到1,3数据包之后,会发送ACK2,同时还会发送SACK3,告知发送端数据包3我收到了,不需要重传。所以选择重传,发送方的策略就是当计时器超时时,仅重新发送未确认队列队头的TCPSegment。此外一般搭配快速重传策略即当收到偏大的序号时,快速发送3个冗余ACK显性告知发送方我需要的报文段序号,这样发送方收到3个冗余ACK时就会快速重新发送接收方需要的数据报,不需要等到计时器超时。这更符合现代TCP的实现策略。
这两个策略都是发送端针对未收到ACK的数据包的发送策略,各有优劣。当接收端窗口为1时,显然选择回退N步更为有效(这时选择充传也会退化至回退N步),或者网络环境不好,发送端发送的数据包大批量丢失,回退N步都更加有效。当接收端窗口和发送端一样大时,选择选择重传策略会使网络利用更加高效。
四次挥手
当TCP协议数据传输差不多时,TCP需要四次挥手来断开连接。分别是FIN、ACK-FIN、FIN、ACK-FIN。如下图所示:

关于四次挥手中的序列号和确认号就不详述了,和三次握手时类似,这里FIN字段和SYN字段一样占据一字节。
状态变换过程
两者都是从ESTABLISHED开始出发的。
- 首先客户端的应用程序数据传输结束了,关闭TCP的出站流。TCP发送FIN数据报并进入FIN-WAIT-1状态。此时客户端入站流关闭,无法继续传输应用层数据,但还可以传送不带应用层数据的报文。
- 服务器端收到客户端的FIN报文,告知其应用程序端并关闭入站流。TCP发送ACK-FIN报文并进入CLOSE-WAIT报文。此时服务器端还可以持续发送数据给客户端,且可以收到客户端的反馈(注意客户端只是关闭了应用程序端出站流,但还可以发送不带任何数据的ACK数据报反馈服务器端表示其收到数据)。
- 客户端收到服务器端发送的FIN-ACK报文,进入FIN-WAIT-2状态,。
- 服务器端应用程序数据也发送完毕,发送FIN报文,告知其发送数据完毕,同时服务器端也关闭自身的出站流,并进入LAST-ACK状态。这时服务器端也无法继续传输应用层数据。
- 客户端收到服务器端发送的FIN报文,发送ACK报文,并进入TIME-WAIT状态,等待2MSL(最长报文段寿命)时间,期间若没有再次收到服务器端的FIN报文,则客户端进入CLOSED状态。这里等待2MSL时间是为了确保服务器端能够收到客户端最后发送的ACK报文,若服务器端没有收到客户端发送的ACK报文,则FIN报文的超时重传会触发,重新发送FIN报文。这样客户端收到重新发送端FIN报文会再次发送ACK报文。
- 服务器端收到客户端发送的ACK报文,也进入CLOSED状态。
至此,客户端和服务器端都进入了CLOSED状态。四次握手的状态转换图如下;

综上,TCP三次握手和四次握手整个状态机如下图所示:

UDP协议
UDP协议概述
UDP(User Datagram Protocol)协议只是简单的将应用数据打包成UDP数据报,并传递给网络层,它只是简单的标识了数据应该发送给另一个主机的哪个端口,所以UDP协议也被称为用户多路复用协议(Uder Demultiplexing Protocol)。
UDP协议头格式

这里字段很简单,分别是源端口、目的端口、检验和和长度(包括标题和数据)。
UDP协议特点
- UDP面向无连接服务,它并不和TCP一样,它发送数据前不需要建立连接,就只是简单的发送数据。
- 提供尽力而为服务,数据包可能缺失,失序到达,没有流量控制等,就像前文提到的,他就只是简单的发送数据而已。
- UDP的本质就是在IP层上的一个简单包装起,告知端口等信息。由于其简单且无连接的特性,其被应用于简单的请求-响应应用程序,比如:DNS服务、DHCP服务(动态主机配置协议)、NTP (网络时间协议)等。
ICMP协议
ICMP协议概述
我们使用三个机制使得网络层工作,分别是:IP协议,封装成IP数据包并在网络中逐跳的发送他们;路由表,路由器使用他们得知IP数据包如何发送;ICMP(Internet Control Message Protocol)互联网控制消息协议,它的主要作用就是在终端主机和路由器之间传递有关网络层的信息,通常用于报告错误信息,帮助我们诊断。

如上图所示,ICMP严格来说属于传输层,即使他是为网络层服务的。
ICMP特点和格式
ICMP是一种自包含信息,仅用来报告错误,他是不可靠的,提供最简单数据包服务,没有可靠传输。

如上图所示,当路由器收到IP数据包,发现错误时,他会做一下举措:
- 取出IP头部和数据的前8个字节作为ICMP的载荷。
- 在载荷的前方加上ICMP的头部即错误类型和代码。
- 最后将这个ICMP作为传输层数据,送给网络层,即加上网络层头部(这里的源IP是路由器,目的IP是主机)送入网络传输。

一些错误类型和代码如上图所示。
ICMP应用实例-ping和traceroute
ping命令大多数情况下仅仅用来测试网络是否联通,其本质是发送一个ICMP数据包给对方主机,对方主机收到后发送ICMP数据包的回复信息,如下图所示:

traceroute的本质是利用IP段的TTL字段,当路由器收到IP数据包时会将TTL字段-1,若TTL字段为0,说明该数据包可能在网络中遭遇了循环,将其丢弃并发送ICMP数据给源主机。traceroute巧妙利用该字段,将TTL从1开始递增的发送IP数据报,依次探查前方路由器的路径,并且目的端口采用较高端口,使得主机B收到IP数据包后发回端口不可达达ICMP数据给源主机,最终勾勒出整个A到B的路径。如下图所示:



2万+

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



