网际幕後的无名英雄

IP 原理实务探密


在Internet如此风行的今日,一般人所谈论的几乎是在应用方面的范畴, 很少人会去注意到Internet网路核心中非常重要的一环— IP(Internet Protocol) 网际网路协定。因此我们特别开辟此一专栏, 期望能让各位读者更进一步、从较技术的角度去了解Internet的世界。


马得翔


    IP(Internet Protocol网 际 网 路 协 定 ), 是 在 Internet网 路 核 心 非 常 重 要 的 一 环 , 以 OSI而 言 , 它 是 位 於 网 路 资 料 联 结 层 (Data Link Layer)与 传 输 层 (Transport Layer)之 间 的 网 路 层 的 传 输 协 定 . 简 单 的 说 , 它 必 须 把 来 自 上 层 的 资 料 分 封 出 去 , 并 且 把 来 自 下 层 网 路 的 资 料 分 析 , 汇 总 , 然 後 在 往 上 层 的 传 输 层 丢 去 , 此 外 还 必 须 和 ICMP这 位 难 兄 难 弟 合 作 , 以 期 随 时 自 我 调 整 和 监 控 网 路 。

    IP网 际 网 路 协 定 , 多 麽 酷 的 中 文 翻 译 , 顾 名 思 义 , 在 不 同 的 网 路 上 , 只 要 有 了 IP  这 层 通 讯 协 定 , 把 下 层 的 实 体 网 路 介 面 抽 象 化 , 我 们 就 「 出 运 」 啦 ! 它 到 底 是 怎 麽 一 回 事 呢 ? 下 面 我 们 举 出 它 摘 要 。

它 提 供 以 下 的 服 务 :

    (1) 不 可 靠 , 非 联 结 性 的 传 输 。
    (2) 绕 路 的 选 择 。
    (3) 有 限 的 资 料 长 度 。
    (4) 资 料 封 包 和 解 封 包 。
    (5) 网 路 情 况 调 整 和 服 务 。
    (6) 作 为 实 体 网 路 和 传 输 层 的 一 个 介 面 。

但 它 不 提 供 以 下 的 服 务 :

    (1) 流 量 控 制 (只 提 供 一 简 易 的 做 法 )。
    (2) 次 序 控 制 。
    (3) 资 料 检 查 码 (仅 做 HEADER 的 检 查 码 )。
    (4) 逾 时 重 送 。
    (5) 资 料 重 覆 检 查 。
    (6) 资 料 检 知 。

    到 此 , 我 们 已 经 点 出 IP所 提 供 的 重 要 服 务 . 我 们 将 在 以 下 一 点 一 点 的 说 明 ; 而 它 不 提 供 的 服 务 (如 流 量 控 制 , 次 序 控 制 等 )它 的 上 层 TCP都 有 提 供 。 所 以 有 人 说 它 是 网 路 幕 後 无 名 英 雄 , 一 点 也 不 为 过 。 好 康 A 都 被 上 层 抢 走 了 , 剩 下 来 都 是 一 些 吃 力 不 讨 好 的 工 作 , 谁 叫 它 是 无 名 英 雄 呢 ? 不 过 在 网 路 世 界 就 是 如 此 , 各 层 之 间 相 互 合 作 , 各 司 其 职 , 没 有 谁 重 谁 轻 。

揭开IP的面纱

    现 在 , 让 我 们 列 出 以 太 网 路 (Ethernet)的 框 架 ( 图 一 ) , IP的 封 包 格 式 ( 图 二 ) 和 OSI与 Internet( 图 叁 ) , 让 读 者 一 探 其 庐 山 真 面 目 。 ( 为 了 方 便 讨 论 , 我 们 假 设 IP是 架 在 Ethernet之 上 ) 。

    如 果 我 们 以 Ethernet来 传 资 料 , 图 一 的 Ethernet框 架 资 料 栏 将 会 包 含 图 二 的 IP资 料 封 包 。 而 图 二 的 资 料 栏 位 将 会 包 含 上 层 图 叁 TCP/UDP的 封 包 ; 同 理 上 层 封 包 的 资 料 栏 将 会 包 含 上 上 层 的 整 个 封 包 , 而 网 路 就 是 这 样 一 层 一 层 的 运 作 , 封 包 绕 路 , 直 到 到 达 彼 岸 . 到 达 之 後 , 在 解 封 包 , 把 每 层 的 资 料 萃 取 出 来 , 例 如 IP会 决 定 把 其 资 料 栏 内 的 「 封 包 」 丢 给 TCP、 UDP或 ICMP, 然 後 各 层 在 各 忙 各 的 。 就 这 样 整 个 封 包 就 可 在 网 路 上 互 相 交 换 , 传 递 讯 息 了 。

    在 解 释 完 封 包 之 後 , 让 我 们 回 头 看 看 图 一 图 二 各 栏 位 的 意 义 。

● 以 太 框 架 介 绍 :
    前 导 (Preamble): 0与 1交 替 的 64位 元 所 组 成 , 收 方 同 步 用 。
(1)目 地 硬 体 地 址 (destination hardware address):接 收 端 的 实 体 位 址 , 共 48 bits.               所 谓 实 体 位 址 , 就 是 生 产 E t h e r n e t   介 面 的 硬 体 厂 商 向 IEEE所 购 买 的 一 组 连 续 地 址 . 厂 商 在 生 产 时 , 把 此 号 码 烧 入 即 可 . 这 样 一 来 全 世 界 各 家 不 同 的 以 太 网 路 卡 制 造 商 的 网 路 实 体 位 址 就 不 会 冲 突 了 .
(2)来 源 硬 体 地 址 (source hardware address):发 送 端 的 实 体 位 址 , 也 是 48 bits. 这 里 要 注 意 的 是 , 网 路 实 体 位 址 是 和 网 际 位 址 ( IP    A D D R E S S )               是 不 同 的 . 简 单 的 说 , 实 体 位 址 是 给 网 路 卡 用 的 , 网 际 位 址 是 给 IP  用 的 .
(3)框 架 型 态 (frame type): 16位 元 用 来 识 别 资 料 的 型 态 .
(4)框 架 资 料 (frame data): 上 层 传 来 的 资 料 必 须 介 於 368 bits(46 bytes)和 12000 bits(1500 bytes)之 间 . 换 句 话 说 IP  丢 给 e t h e r n e t 驱 动 程 式 的 封 包 不 可 大 於 1500个 byte. 在 这 里 我 们 即 点 出 了 为 什 麽 WINSOCKET的 MTU ( 最 大 传 输 单 位 ) 内 定 值 是 1500位 元 组 . 试 想 一 下 , 我 们 在 每 传 秒 10 mega位 元 的 以 太 网 路 上 我 们 每 次 只 能 丢 小 於 1500个 位 元 组 (12 K位 元 )的 封 包 给 Ethernet, 实 在 蛮 可 怜 的 . 当 然 这 在 高 速 网 路 中 也 是 不 适 用 的 .
(5)循 环 码 (Cyclic Redundancy Check, CRC): 用 以 侦 测 资 料 传 输 过 程 中 , 资 料 是 否 会 发 生 错 误 . 用 软 体 或 硬 体 去 实 作 均 可 .

    简 单 吧 ! 经 由 以 太 网 路 卡 传 出 和 收 到 的 资 料 就 是 如 此 , 看 起 来 笨 笨 的 , 不 过 确 实 如 此 . 现 在 , 让 我 们 再 来 看 看 IP  的 资 料 格 式 .

(1)版 本 (Version): 4个 bit. 目 前 最 新 的 版 本 是 4, 1989年 5月 制 订 .
(2)标 头 长 (Internet Header Length): 4个 bit. 以 32个 位 元 为 单 位 . 如 果 无 IP选 项 的 话 , 它 的 值 为 5( 即 最 小 值 ) . 细 心 的 读 者 自 己 算 算 看 .
(3)服 务 型 态 (Service Type): 8个 bit. 传 给 路 由 器 或 闸 道 器 , 我 们 所 希 望 的 传 输 类 型 . 共 分 叁 种 1. D-低 延 迟 2. T-高 吞 吐 率 3. R-高 可 靠 性
(4)总 长 度 (Total Length): 16个 bit. 所 允 许 的 最 大 长 度 为   2^16-1=65535 (表 头 加 上 资 料 总 长 ).
(5)识 别 字 (Identification): 16个 bit. 资 料 分 割 後 , 当 成 识 别 码 用 .
(6)旗 标 (Flag): 3个 bit. 指 示 是 否 可 分 割 .
(7)分 段 差 距 值 (Fragment): 13个 bit. 资 料 被 分 段 後 , 此 分 段 在 原 资 料 流 的 位 址 .
(8)存 活 时 间 (Time to live): 8个 bit. 以 秒 为 单 位 , 表 示 IP预 测 此 封 包 可 在 网 路 上 的 存 活 时 间 . 闸 道 器 会 把 此 资 料 传 输 的 时 间 减 去 存 活 时 间 , 若 小 於 零 , 则 放 弃 此 封 包 .
(9)协 定 (Protocol): 8个 bit. 表 示 IP上 层 的 协 定 内 容 . 这 里 告 诉 了 IP软 体 , 我 们 的 资 料 应 丢 那 一 层 软 体 去 处 理 . 以 下 在 WINSOCK中 的 Protocol file都 可 找 到 .


       ip      0    icmp     1   tcp     6     udp     17

(10)标 头 检 查 码 (Header Checksum): 16个 bit. 表 示 IP表 头 (HEADER)的 检 查 码 .
(11)来 源 IP地 址 (Source Address): 32 bit. 这 里 就 是 所 谓 的 IP ADDRESS

目 前 在 Internet中 , 网 路 共 分 五 级 . 如 下 表 图 四

A类 网 路 的 IP ADDRESS是 介 於 0.0.0.1至 128.0.0.0
B类 网 路 的 IP ADDRESS是 介 於 128.0.0.0至 192.0.0.0
C类 网 路 的 IP ADDRESS是 介 於 192.0.0.0至 224.0.0.0
D类 网 路 的 IP ADDRESS是 介 於 224.0.0.0至 240.0.0.0
E类 网 路 的 IP ADDRESS是 介 於 240.0.0.0至 255.255.255.254
#注 意 IP ADDRESS 255.255.255.255为 广 播 位 址 #

举 个 例 子 来 说 : 若 你 的 IP ADDRESS为 140.113.207.141的 话 , 那 在 就 是 B类 网 路 . 而 电 脑 即 以 2进 位 来 表 示 这 个 位 址 ,


  因    140=10001100  113=01110001   207=11001111   141=10001101

  所以 140.113.207.141 = 10001100011100011100111110001101

        就是 IP 和 IP 沟通的实际方式。

目 地 IP地 址 (Destination Address): 32 bits. 理 由 同 上 。
IP选 项 (Option): 可 有 可 无 . 这 里 大 多 是 用 在 资 料 段 的 除 错 或 测 试 。
补 足 长 度 (Padding): 长 度 不 定 . 它 会 填 充 IP表 头 (HEADER)使 得 表 头 能 被 32整 除 , 加 快 电 脑 处 理 。
资 料 (IP Data): 这 里 就 是 由 上 层 的 TCP / UDP资 料 填 充 , 或 同 层 的 ICMP。

IP所提供的服务

    看 样 子 多 了 这 些 栏 位 , IP层 比 较 聪 明 , 事 实 上 在 网 路 的 哲 学 里 的 确 是 这 样 , 越 上 层 的 协 定 , 功 能 越 强 也 越 好 用 , 硬 体 也 越 抽 象 化 , 当 然 对 使 用 者 而 言 也 越 好 用 . 但 聪 明 归 聪 明 , 它 还 是 有 缺 点 的 . 其 中 的 不 可 靠 性 (unreliable) 和 非 联 结 性 (connectionless)  的 传 输 就 是 它 最 大 的 致 命 伤 。

    所 谓 不 可 靠 性 即 是 , 发 送 端 或 接 收 端 对 於 分 封 可 能 遗 失 , 重 复 , 延 迟 或 失 序 都 无 法 侦 测 或 被 通 知 . 而 非 联 结 性 是 指 对 於 一 系 列 的 封 包 可 能 经 由 不 同 的 路 径 前 往 目 的 地 , 其 中 有   些 能 会 遗 失 . 而 这 就 是 给 上 层 网 路 表 现 的 机 会 了 . TCP (Transmission Comtrol Protocol)可 靠 资 料 传 输 服 务 , 就 因 此 诞 生 . 它 利 用 软 体 的 技 术 , 使 得 经 由 IP传 出 的   资 料 能 够 更 稳 定 , 更 有 效 率 的 到 达 对 方 . 但 IP的 非 联 结 服 务 并 非 是 不 好 的 , 因 为 IP  在 网 路 层 有 它 的 实 际 考 量 , 而 它 没 有 必 要 吃 力 不 讨 好 的 去 取 代 上 层 网 路 , 而 影 响 了 整 个 网 路 传 输 的 效 能 。

    另 外 由 IP表 头 中 的 总 长 度 栏 (Total Length)可 知 , 它 最 大 一 次 可 以 丢 65535 byte. 虽 然 如 此 , 真 正 要 传 输 时 的 大 小 还 是 得 决 定 於 下 层 网 路 (如 以 太 网 路 的 MTU=1500), 所 以 , IP会 把 上 层 来 的 大 块 资 料 分 割 (fragment), 利 用 识 别 字 , 旗 标 , 分 段 差 距 值 来 控 制 , 然 後 再 由 接 收 端 加 以 组 合 , 再 丢 还 给 上 层 . 如 此 一 来 IP就 可 以 圆 满 的 达 成 上 层 所 交 待 的 任 务 了 . 同 样 的 , 也 就 是 由 於 IP的 弹 性 大 , 它 可 以 架 在 各 种 不 同 的 网 路 实 体 之 上 如 ISDN或 SLIP等 。

    还 有 一 个 值 得 深 思 的 问 题 . 那 就 是 既 然 有 了 硬 体 实 体 位 址 , 那 干 嘛 又 多 生 出 一 个   IP ADDRESS. 这 是 因 为 要 绕 路 的 关 系 , 多 了 IP ADDRESS, 路 由 器 或 闸 道 器 可 由 学 习   知 道 整 个 网 路 的 架 构 , 进 而 快 速 地 把 封 包 送 至 正 确 的 地 点 , 加 速 网 际 间 资 料 的 传 递 。

    当 然 绕 路 功 能 也 是 IP必 备 的 功 能 之 一 . 这 部 份 大 多 由 路 由 器 (ROUTER)或 闸 道 器 (GETWAY)来 帮 忙 , 请 注 意 , IP中 的 来 源 地 址 (source address)和 目 的 地 址 (destination address)在 绕 路 的 过 程 之 中 是 不 会 被 改 变 的 ; 如 果 被 改 变 , 网 路 层 一 定 大 乱 . 唯 一 可 能 被 改 变 的 是 目 地 硬 体 地 址 (destination hardware address)或   来 源 硬 体 地 址 (source hardware address). 此 外 , 当 然 网 路 层 中 , 它 自 己 也 有 重 网 路 中 学 来 的 绕 路 表 , 只 是 功 能 没 有 路 由 器 或 闸 道 器 强 大 而 矣 。

    在 网 路 层 传 送 资 料 之 中 , IP  会 利 用 ICMP  和 其 夥 办 沟 通 有 无 . 当 然 这 是 为 了 达 到 网 路 的 稳 定 性 以 及 传 输 效 益 所 设 计 出 来 的 , 否 则 在 茫 茫 的 网 海 当 中 , 网 路 层 遇 到 错 误 一 直 重 送 资 料 , 整 个 网 路 一 定 会 死 得 很 难 看 , 那 更 惶 论 架 在 IP之 上 的 通 讯 协 定 。 ( 下 一 期 将 详 细 探 讨 ICMP, 请 读 者 视 目 以 待 )

    让 我 们 对 IP作 个 小 结 ; 它 是 点 对 点 的 联 结 , 从 TCP, UDP或 ICMP取 得 资 料 , 然 後 决 定 是 否 分 割 上 层 资 料 , 寻 找 IP ADDRESS, 以 及 实 体 位 址 , 然 後 选 择 路 径 , 制 作 封 包 , 最 後 利 用 以 太 网 路 的 驱 动 程 式 送 至 远 方 . 同 理 当 它 收 到 资 料 时 , 它 会 看 看 此 封 包 收 方 的 IP ADDRESS是 否 是 自 己 的 IP ADDRESS, 若 是 , 就 往 TCP UDP或 ICMP分 封 . 若 不 是 , 则 帮 这 封 包 绕 路 , 使 它 到 达 目 的 地 。

    以 下 列 出 一 小 部 份 LINUX IP实 作 的 原 始 程 式 , 希 望 读 者 更 能 体 会 出 它 的 道 理 。

第 一 个 例 子 是 IP它 如 何 建 立 封 包 标 头 。


  /*

   * This routine builds the appropriate hardware/IP headers for

   * the routine.  It assumes that if *dev != NULL then the

   * Protocol knows what it's doing, otherwise it uses the

   * routing/ARP tables to select a device struct.

   */

  int

  ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long daddr,

                  struct device **dev, int type, struct options *opt, int len, int tos, int ttl)

  {

    static struct options optmem;

    struct iphdr *iph;

    struct rtable *rt;

    unsigned char *buff;

    unsigned long raddr;

    static int count = 0;

    int tmp;



    if (saddr == 0)

          saddr = my_addr();



    DPRINTF((DBG_IP, "ip_build_header (skb=%X, saddr=%X, daddr=%X, *dev=%X,\n"

             "                 type=%d, opt=%X, len = %d)\n",

             skb, saddr, daddr, *dev, type, opt, len));



    buff = skb->data;



    /* See if we need to look up the device. */

    if (*dev == NULL) {

          rt = rt_route(daddr, &optmem);

          if (rt == NULL)

                  return(-ENETUNREACH);



          *dev = rt->rt_dev;

          if (saddr == 0x0100007FL && daddr != 0x0100007FL)

                  saddr = rt->rt_dev->pa_addr;

          raddr = rt->rt_gateway;



          DPRINTF((DBG_IP, "ip_build_header: saddr set to %s\n", in_ntoa(saddr)));

          opt = &optmem;

    } else {

          /* We still need the address of the first hop. */

          rt = rt_route(daddr, &optmem);

          raddr = (rt == NULL) ? 0 : rt->rt_gateway;

    }

    if (raddr == 0)

          raddr = daddr;



    /* Now build the MAC header. */

    tmp = ip_send(skb, raddr, len, *dev, saddr);

    buff += tmp;

    len -= tmp;



    skb->dev = *dev;

    skb->saddr = saddr;

    if (skb->sk) skb->sk->saddr = saddr;



    /* Now build the IP header. */



    /* If we are using IPPROTO_RAW, then we don't need an IP header, since

       one is being supplied to us by the user */



    if(type == IPPROTO_RAW) return (tmp);



    iph = (struct iphdr *)buff;

    iph->version  = 4;

    iph->tos      = tos;

    iph->frag_off = 0;

    iph->ttl      = ttl;

    iph->daddr    = daddr;

    iph->saddr    = saddr;

    iph->Protocol = type;

    iph->ihl      = 5;

    iph->id       = htons(count++);



    /* Setup the IP options. */

  #ifdef Not_Yet_Avail

    build_options(iph, opt);

  #endif



    return(20 + tmp);     /* IP header plus MAC header size */

  }

    零 零 总 总 的 讲 了 一 大 堆 , 我 想 各 位 读 者 对 其 应 有 更 深 一 层 的 体 会 和 实 务 . 其 实 学 网 路 并 不 难 , 资 料 就 是 这 样 一 层 又 一 层 的 往 下 丢 和 往 上 收 . 而 IP就 是 这 位 劳 苦 功 高 的 无 名 英 雄 。

    另 外 有 兴 趣 的 读 者 可 参 阅 RFC791, 1010, 815, 以 及 894可 获 得 更 详 细 的 技 术 资 料 ( 在 nctuccca或 nic.ddn.mil都 可 找 到 ) , 或 下 列 的 参 考 书 目 ( 原 文 书 均 有 中 译 本 ) 。 咱 们 下 期 见 !

参考书目:

1.Comer, Inetrnetworking With TCP/IP VOL I, PRENTICE HALL
2.Stevens, UNIX Network Programming, PRENTICE HALL
3.王 家 辉 , 透 视 TCP/IP, 和 硕 科 技 文 化 有 限 公 司

(作者任职 於Derek Ma, Software,E-mail为DEREK_M1@tpev1.verifone.com

图说:

    图一、Ethernet 框架。

    图二、IP 资料封包。

    图叁、OSI与Internet。

    图四、IP的五类型式。