跳转到内容

串行编程/串行连接上的 IP

来自 Wikibooks,开放世界中的开放书籍

先决条件

[编辑 | 编辑源代码]

本页假设读者熟悉 TCP/IP 协议族和一般的 IP 通信。

关于术语的说明

[编辑 | 编辑源代码]

本模块使用正常的 TCP/IP 术语,其中术语表示以下内容

TCP
TCP 协议本身,在传输层。
IP
IP 协议本身,在互联网层。
TCP/IP
完整的互联网协议族,包括比 TCP 或 IP 更多的协议。

此外,本模块使用 TCP/IP 的协议层符号,而不是 OSI 模型,除非另有说明。

+--------------------+
| Application Layer  |  e.g. SMTP
+--------------------+
| Transport Layer    |  e.g. TCP
+--------------------+
| Internetwork Layer |  e.g. IP
+--------------------+
| Link Layer         |  e.g. SLIP or PPP
+--------------------+

通过串行 (RS-232) 线传输 IP 数据会遇到一些问题,其中包括:

  1. 缺少帧
  2. 缺少流量控制
  3. 缺少会话管理

其中缺少帧是最严重的问题。所有提到的问题都将解释如下。

缺少帧

[编辑 | 编辑源代码]

不同的层在 TCP/IP 协议栈中承担不同的任务。上层协议期望下层协议提供特定的服务。IP 协议期望链路层提供的服务之一是 IP 数据包的帧和去帧。这意味着,链路层负责在数据包通过通信链路时正确分离每个数据包并识别 IP 数据包的开始和结束。链路层应该这样做,以便在将数据包放置在某个数据流中时,可以正确地从数据流中提取它们。

在使用“裸”串行连接作为链路层的情况下,会产生一个问题,因为简单的串行连接不提供任何帧功能。相反,数据只是一个流。接收方将无法明确识别数据包的开始和结束。

在 100% 可靠的串行连接中,这可以容忍,因为 IP 数据包中的长度信息可以用来将数据包从串行数据流中分离出来。但是,连接通常不是 100% 可靠的,特别是如果它是通过调制解调器在公共电话线上进行的。如果数据包被损坏、部分丢失等,接收方将失去同步,传输将完全混乱。如果可以可靠地识别损坏的 IP 数据包,TCP 等上层协议可以处理问题并启动重新传输。因此,正确识别,以及 IP 数据包的帧/去帧是必不可少的。

缺少流量控制

[编辑 | 编辑源代码]

由于串行连接的性质,需要对串行连接跃点进行流量控制。但是,IP 没有提供任何在链路层控制流量的机制,TCP 等协议使用完全不同的方式进行端到端流量控制,并且根本不处理单个跃点。

缺少会话管理

[编辑 | 编辑源代码]

在串行线上运行 IP 时,通常需要做一些额外的“管理工作”,特别是当该串行线由调制解调器连接支持时。这包括建立这样的调制解调器连接(拨号到某个远程站点)并在该远程站点进行身份验证。IP 本身不支持这些任务。

解决方案

[编辑 | 编辑源代码]

解决上述问题的办法是在链路层引入一个额外的协议。该协议实际上代表了上层协议的链路层,并在内部使用串行连接。

目前常用的协议有两种。一种非常简单的协议叫 SLIP,另一种更复杂但更强大的协议叫 PPP。新服务通常使用 PPP,而 SLIP 仍然可以在一些旧服务中找到。

+-------------+
| TCP         |
+-------------+
| IP          |
+-------------+---------------+
| Link Layer  | Modem Control |
+-------------+---------------+
| Serial Line                 |
+-----------------------------+
| Modem                       |
+-----------------------------+
| Phone Line                  |
+-----------------------------+

SLIP 解决了将 IP 数据报发送到串行线上的一个最严重的问题:缺乏帧定界。流量控制由调制解调器传输协议和更高级别的 TCP/IP 协议处理。会话管理应该在 SLIP 之外处理,例如调制解调器连接的设置(“拨号”)不是由 SLIP 完成的。SLIP 假设串行连接已经建立。

SLIP 在 RFC 1055 中进行了标准化,标题为 *通过串行线路传输 IP 数据报的非标准方法:SLIP*。标题中的 *非标准* 一词源于历史原因。SLIP 很久以来都没有被描述,直到它最终在 RFC 1055 中被描述,这个描述仅仅是作为对当时实践情况的非正式总结。直到后来才决定将该 RFC 赋予 IETF 官方标准的地位,但由于 SLIP 的局限性,它不应该成为首选。

SLIP 非常简单,几乎令人尴尬。它需要 8 位数据位、无奇偶校验和硬件流控制或 CLOCAL 模式(3 线空闲模式)的串口配置。它只定义了四个特殊的 8 位序列(字符)和很少的功能,超过了标准的串行线路协议。

十六进制值 八进制值 缩写 描述
0xC0 0300 END 帧结束
0xDB 0333 ESC 转义
0xDC 0334 ESC_END 转置的帧结束符,在转义序列中使用
0xDD 0335 ESC_ESC 转置的转义符,在转义序列中使用

当 SLIP 驱动程序从互操作层接收 IP 数据报时,它简单地逐字节复制(除了一个小的例外,见下文)并附加一个值为 0xC0(十六进制)的额外字节。这个额外的字节标记 IP 数据报的结束,因此称为 *END* 字符。

为了避免随机线路噪声被解释为数据报的开头,习惯上在 IP 数据报之前添加 *END* 字符,如果数据报不是连续且以全速发送到线路上的,并且传输恢复。这样,可能的随机噪声本身就被封装成一个数据报,而更高层(特别是 IP 层)将丢弃这些“数据报”,因为它们将被识别为非法的(错误的校验和、错误的大小、低于最小大小)。

连续发送时的帧

+-----------------+-----------------+-----------------+
| IP datagram |END| IP datagram |END| IP datagram |END| ...
+-----------------+-----------------+-----------------+

延迟发送数据包时的帧,在数据包之前添加额外的 END 字符以排除线路噪声

+-----------------+            +----+-----------------+            +----+-----------------+
| IP datagram |END| line noise |END | IP datagram |END| line noise |END | IP datagram |END| ...
+-----------------+            +----+-----------------+            +----+-----------------+

上图中用红色标记的 END 字符是在它们后面的 IP 数据报之前添加的 END 字符。但它们实际上充当前面线路噪声的结束标记,将潜在的随机线路噪声与真实数据分开。

用 0xC0 *END* 字符进行帧定界会产生一个问题。如果该字符本身出现在 IP 数据报中,SLIP 会错误地将它解释为数据报的结束。这个问题通过引入另一个特殊字符 *ESC* 字符(值为 0xDB(十六进制))来解决。它用于构建两个转义序列

0xDB 0xDC
替换 IP 数据报内的 0xC0 值
这确保了传输数据报中永远不会出现 *END* 字符
0xDB 0xDD
替换 IP 数据报内的 0xDB 值
这是“转义转义”字符。

SLIP 将这些转义序列插入它从互操作层接收的 IP 数据报中进行传输,并在转发接收到的数据报到互操作层时用原始值替换转义序列。

这就是 SLIP 所做的全部。没有错误检测、压缩或设备(调制解调器)控制。也没有对主机配置、安全性、会话管理和其他控制功能的支持。因此,SLIP 本身在容易出错的拨号连接上并不令人满意,尽管它在 MNP4(或更高版本)错误纠正调制解调器链路上可靠地运行。

PPP(点对点协议)提供了一种标准方法,用于在点对点链路上传输数据报,包括标准串行线。PPP 的规范定义了以下三个主要组成部分

  1. 一种在 PPP 帧中封装数据报的方法。它支持 IP 数据报以及其他网络协议的数据报。
  2. 链路控制协议 (LCP)。该协议定义了建立、配置和测试数据链路连接的过程。
  3. 一个网络控制协议 (NCP) 家族,用于建立和配置不同的网络层协议。

PPP 是一个相当复杂的协议,由强制性和可选部分以及扩展组成。下面列出了一个可能不完整的 PPP 相关 RFC 标准列表

  • RFC 1661 - 点对点协议 (PPP)
  • RFC 1332 - PPP 互联网协议控制协议 (IPCP)
  • RFC 1334 - PPP 认证协议
  • RFC 1377 - PPP OSI 网络层控制协议 (OSINLCP)
  • RFC 1378 - PPP AppleTalk 控制协议 (ATCP)
  • RFC 1552 - PPP 互操作分组交换控制协议 (IPXCP)
  • RFC 1570 - PPP LCP 扩展
  • RFC 1618 - PPP over ISDN
  • RFC 1662 - PPP 在类似 HDLC 的帧定界中
  • RFC 1962 - PPP 压缩控制协议 (CCP)
  • RFC 1968 - PPP 加密控制协议 (ECP)
  • RFC 1973 - PPP 在帧中继中
  • RFC 1989 - PPP 链路质量监控
  • RFC 1990 - PPP 多链路协议 (ML)
  • RFC 1994 - PPP 质询握手身份验证协议 (CHAP)
  • RFC 2043 - PPP SNA 控制协议 (SNACP)
  • RFC 2097 - PPP NetBIOS 帧控制协议 (NBFCP)
  • RFC 2125 - PPP 带宽分配协议 (BAP) / PPP 带宽分配控制协议 (BACP)
  • RFC 2290 - PPP IPCP 的移动 IPv4 配置选项
  • RFC 2364 - PPP over AAL5
  • RFC 2472 - PPP 上的 IPv6 版本
  • RFC 2516 - 通过以太网传输 PPP 的方法 (PPPoE)
  • RFC 2615 - PPP over SONET / SDH
Clipboard

待办事项
以某种方式标记与串行线路通信相关的 RFC。可能根本不提及其他 RFC。


简而言之,实现 PPP 并非易事。这是一项严肃的任务,需要扎实的编程、协议和电信知识,即使只考虑与串行线路通信相关的部分。希望实现 PPP 的程序员应该提前预留数周时间来学习相关标准。定义需要实现哪些可选 PPP 部分的明确需求也是一个好主意。还应该考虑获得兼容性测试套件以验证自身实现的标准符合性。对现有协议消费者实现进行简单的试错通常不切实际。这只能在一定程度上“保证”PPP 实现与特定配置下的特定其他实现兼容。它不能保证该实现与各种现有的 PPP 实现兼容。

如果购买特定平台的 PPP 实现是一个可行的选择,而不是进行自己的实现,那么应该认真考虑这个选择。

HDLC(高级数据链路控制)是另一个第二层协议,可用于在串行(和其他)连接上承载 IP 流量。HDLC 早于 PPP 并且是一个通用的第二层协议。它可以在工业应用中找到,并且在 IP 路由器 之间的串行点对点链路中也很流行。它在最终用户应用程序(如拨号连接到 ISP)中并不常见。关于 HDLC 的维基百科文章 提供了关于 HDLC 的良好概述,并提供了对相关标准的引用。

HDLC 主要关注帧定界,并提供了一些额外的控制消息(*过程*)。它在串行线上相对容易实现。


华夏公益教科书