从IP数据包到端口发送究竟经历了什么?

475 阅读5分钟

我一直以为IP数据包,到物理层发送这之间不再有什么操作性了。因为在平常的交流中谈协议,谈到IP这一层基本就止住了,仿佛IP打包后就可以直接发送了是的。然而当我读了《TCP/IP详解卷一:协议》后,我才发现其中并没有那么简单。也许是因为接近真实世界的原因,不同的网络连接方式最终封装的IP都不太一样。

以太网和IEEE 802

以太网和IEEE 802是最常见的两种协议,它们的数据报如下:

IEEE802和以太网数据报

目的地址和原地址指的就是物理地址(MAC地址),它们是通过ARP协议获取的(下文会介绍)。

我们将目光放到封装的数据部分,可以看到封装的三种报文(IP、ARP、RARP)类型是一致的,但是后面的数据长度范围并不一致。IEEE802的最小值是36字节(PAD 代表填充字节的意思),而以太网的是46。

在观察除了数据以外的部分,会发现他们源地址、目的地址都在开头并占据相同长度,尾部都是4字节的CRC(检验码),不一样的是IEEE802比以太网多占用了8个字节(长度+几个不明就里的固定字段)。

在我看来以太网应该是IEEE 802的升级版(因为减少了一些不需要的固定字节的占用),然而以太网出现的时间比IEEE 802提前,也就是说IEEE 802才是升级版。更神奇的是RFC标准规定,以太网必须支持而IEEE选择支持。然而我查找了半天资料没有发现两个同时存在的原因,因此我能想到的IEEE 802存在的原因是历史商业竞争的产物了。

ARP:地址解析协议

ARP(Address Resolution Protocol)为协议地址(通常是IP,也就是说可以用在非IP协议上)到硬件地址之间提供一种映射。主要不是用于消息通信,而是为了消息通信而查出硬件地址。

用于以太网的ARP请求或应答报文如下:

ARP数据报

  • 帧类型:表示后面的数据类型,应答或请求(0X0806)
  • 硬件类型:表示硬件地址的类型,值为 1即表示以太网地址
  • 协议类型:表示要映射的协议地址类型。它的值为 0x0800 即表示IP地址
  • 硬件地址长度/协议地址长度:单位byte
  • op:代表操作,发送为响应报文时为2

硬件类型和协议类型决定最后4个字段(源硬件地址、源协议地址、目的硬件地址、目的协议地址)的长度和内容

解析过程:

  1. ARP发送请求到广播地址(物理地址每个bit都为1,FF:FF:FF:FF:FF:FF)
  2. 与ARP请求的目标IP地址对应的主机,填充上地址段
  3. 根据请求端的地址直接将响应报文发送回请求主机

主机在接收到请求或响应ARP报文时,会将地址缓存下来。完整的表项(能够正常响应的)一般为20分钟,不完整的表项(未被正常响应的)一般为3分钟。可以通过指令arp进行查看。

SLIP:串行线路IP

SLIP(Serial Line IP)是一种对IP数据报进行封装的简单形式,适用于RS-232串行端口和高速调制解调器接入Internet。RS-232常见于液晶显示屏与电脑的链接。

RS-232数据线:

RS-232数据线

SLIP数据报:

SLIP数据报

从数据报可以看出SLIP协议是一种很简单的协议,除了头尾字段用于区分数据报,然后将数据报中会影响判断的(标志字节:0xc0,转义字节:0xdb)进行转义就完成了封装可以进行发送了。

优点:

简单、字节少。

我想这也是它会被用在显示器上(RS-232)和接入Internet等对时延要求高、传输量大的场合。

缺点:

  1. 根据IP知道对端机器(原话是“每端必须知道对方IP”)。该协议没有使用ARP进行广播,确定发送机器,所以必须的通过IP层的目的IP地址知道对应的机器。
  2. 数据帧没有类型字段,只能发送一种类型的报文。(原话是“如果一条串行线路用于SLIP,那么它不能同时使用其他协议。”)
  3. 没有校验和,受噪声影响,传输出错只能在上层校验。

我想也就是因为这些不稳定性,所以主要是在有线传输中见到它的身影。

CSLIP

CSLIP(Compressed SLIP)是SLIP的更进一步,它将SLIP传输的TCP数据包头进行压缩,减少传输量。但并不影响UDP包头。

PPP:点对点协议

PPP(Point to Point Protocol)协议修改了SLIP协议中的所有缺点。PPP就是被设计来用于取代SLIP的。其数据报如下:

PPP数据报

可以看到CRC加入了协议字段和CRC字段(校验和)字段,因此可以解决只能够传输一种类型报文,以及没有校验和易受噪声干扰的问题。至于PPP的IP协商机制,有兴趣的可以自己查查资料。

PPP与SLIP一样有头尾标志字节,这就说明PPP也需要将数据报中的标志字节和转义字节进行转移。与SLIP不一样的是,标志位(0x7e)、转义字节(0x7d)。

除了这两个字节外PPP还需要对小于0x20的字节进行转移,因为0x20的字节在ascii码中有控制含义,怕影响底层驱动程序。

因此PPP具有转移规则,规则是在0x7d接下去的第1个byte的第6个bit取补码(即将byte取补码后,将这个byte的第6位,用补码的第6位取代)。

公众号二分之一程序员,专注计算机基础的学习,欢迎关注 :)

公众号