下载
第1章 概 述
1.1 引言
本章介绍伯克利( B e r k e l e y ) 联网程序代码。开始我们先看一段源代码并介绍一些通篇要用
的印刷约定。对各种不同代码版本的简单历史回顾让我们可以看到本书中的源代码处于什么
位置。接下来介绍了两种主要的编程接口,它们在 U n i x 与非U n i x 系统中用于编写T C P / I P协议。
然后我们介绍一个简单的用户程序,它发送一个 U D P 数据报给一个位于另一主机上的日
期/时间服务器,服务器返回一个 U D P 数据报,其中包含服务器上日期和时间的 A S C I I 码字符
串。这个进程发送的数据报经过所有的协议栈到达设备驱动器,来自服务器的应答从下向上
经过所有协议栈到达这个进程。通过这个例子的这些细节介绍了很多核心数据结构和概念,
这些数据结构和概念在后面的章节中还要详细说明。
本章的最后介绍了在本书中各源代码的组织,并显示了联网代码在整个组织中的位置。
1.2 源代码表示
不考虑主题,列举 15 000行源代码本身就是一件难事。下面是所有源代码都使用的文本
格式:
1.2.1 将拥塞窗口设置为1
3 8 7 - 3 8 8 这是文件t c p _ s u b r . c中的函数t c p _ q u e n c h 。这些源文件名引用4 . 4 B S D - L i t e发
布的文件。4 . 4 B S D 在1 . 1 3节中讨论。每个非空白行都有编号。正文所描述的代码的起始和结
束位置的行号记于行开始处,如本段所示。有时在段前有一个简短的描述性题头,对所描述
的代码提供一个概述。
这些源代码同4 . 4 B S D - L i t e 发行版一样,偶尔也包含一些错误,在遇到时我们会提出来并
加以讨论,偶尔还包括一些原作者的编者评论。这些代码已通过了 G N U缩进程序的运行,使
它们从版面上看起来具有一致性。制表符的位置被设置成 4个栏的界线使得这些行在一个页面
中显示得很合适。在定义常量时,有些 # i f d e f 语句和它们的对应语句 # e n d i f 被删去(如:
G A T E W A Y 和M R O U T I N G,因为我们假设系统被作为一个路由器或多播路由器 )。所有r e g i s t e r说
明符被删去。有些地方加了一些注释,并且一些注释中的印刷错误被修改了,但代码的其他
部分被保留下来。
这些函数大小不一,从几行 (如前面的t c p _ q u e n c h )到最大11 0 0行(t c p _ i n p u t )。超过
大约4 0 行的函数一般被分成段,一段一段地显示。虽然尽量使代码和相应的描述文字放在同
一页或对开的两页上,但为了节约版面,不可能完全做到。
本书中有很多对其他函数的交叉引用。为了避免给每个引用都添加一个图号和页码,书
封底内页中有一个本书中描述的所有函数和宏的字母交叉引用表和描述的起始页码。因为本
书的源代码来自公开的 4 . 4 B S D _ L i t e 版,因此很容易获得它的一个拷贝:附录 B详细说明了各
种方法。当你阅读文章时,有时它会帮助你搜索一个在线拷贝 [例如U n i x 程序grep ( 1 )]。
描述一个源代码模块的各章通常以所讨论的源文件的列表开始,接着是全局变量、代码
维护的相关统计以及一个实际系统的一些例子统计,最后是与所描述协议相关的 S N M P 变量。
全局变量的定义通常跨越各种源文件和头文件,因此我们将它们集中到的一个表中以便于参
考。这样显示所有的统计,简化了后面当统计更新时对代码的讨论。卷 1的第 2 5 章提供了
S N M P 的所有细节。我们在本文中关心的是由内核中的 T C P / I P 例程维护的、支持在系统上运
行的S N M P 代理的信息。
1.2.2 印刷约定
通篇的图中,我们使用一个等宽字体表示变量名和结构成员名 (m _ n e x t),用斜体等宽字
体表示定义常量 ( N U L L ) 或常量的值 (5 1 2 ) 的名称,用带花括号的粗体等宽字体表示结构名称
(m b u f { } )。这里有一个例子:
在表中,我们使用等宽字体表示变量名称和结构成员名称,用斜体等宽字体表示定义的
常量。这里有一个例子:
m _ f l a g s 说 明
M _ B C A S T 以链路层广播发送/接收
通常用这种方式显示所有的 # d e f i n e符号。如果必要,我们显示符号的值 (M _ B C A S T 的
值无关紧要)并且所列符号按字母排序,除非对顺序有特殊要求。
通篇我们会使用像这样的缩进的附加说明来描述历史的观点或实现的细节。
我们用有一个数字在圆括号里的命令名称来表示 U n i x 命令,如g r e p ( 1 ) 。圆括号中的数字
是4 . 4 B S D 手册“manual page”中此命令的节号,在那里可以找到其他的信息。
1.3 历史
本书讨论在伯克利的加利福尼亚大学计算机系统研究组的 T C P / I P 实现的常用引用。历史
上,它曾以4.x BSD系统(伯克利软件发行)和“B S D 联网版本”发行。这个源代码是很多其他
实现的起点,不论是U n i x 或非U n i x 操作系统。
图1 - 1显示了各种B S D 版本的年表,包括重要的 T C P / I P 特征。显示在左边的版本是公开可
2计计TCP/IP详解 卷2:实现
下载
用源代码版,它包括所有联网代码:协议本身、联网接口的内核例程及很多应用和实用程序
(如Te l n e t和F T P )。
图1-1 带有重要T C P / I P特征的各种 B S D版本
虽然本文描述的软件的官方名称为 4 . 4 B S D - L i t e发行软件,但我们简单地称它为 N e t / 3 。
虽然源代码由U. C. Berkeley发行并被称为伯克利软件发行,但 T C P / I P 代码确实是各种研
究者的工作的融合,包括伯克利和其他地区的研究人员。
通篇我们会使用术语源于伯克利的实现来谈及各厂商的实现,如 SunOS 4.x、系统V版本
4 ( S V R 4 ) 和AIX 3.2,它们的T C P / I P代码最初都是从伯克利源代码发展而来的。这些实现有很
多共同之处,通常包括同样的错误!
在图1 - 1中没有显示的伯克利联网代码的第 1版实际上是1 9 8 2年的4 . 1 c B S D,但是
广泛发布的是1 9 8 3 年的版本4 . 2 B S D。
在4 . 1 c B S D 之前的 B S D 版本使用的一个 T C P / I P实现,是由 Bolt Beranek and
N e w m a n ( B B N )的Rob Gurwitz和Jack Haverty开发的。[Salus 1994]的第1 8章提供了另
外一些合并到4 . 2 B S D 中的B B N 代码细节。其他对伯克利 T C P / I P代码有影响的实现是
由B a l l i s t i c s研究室的Mike Muuss为P D P - 11开发的T C P / I P 实现。
描述联网代码从一个版本到下一个版本的变化的文档有限。 [Karels and
McKusick 1986]描述了从4 . 2 B S D 到4 . 3 B S D 的变化,并且 [Jacobson 1990d]描述了从
4.3BSD Ta h o e到4.3BSD Reno的变化。
1.4 应用编程接口
在互联网协议中两种常用的应用编程接口 ( A P I ) 是插口( s o c k e t ) 和T L I ( 运输层接口)。前者
第1章 概 述计计3
下载
BSD联网软件
版本1.0(1989):Net/1
BSD联网软件
版本2.0(1991):Net/2
4.4BSD-Lite(1994)
在正文中用Net/3表示
4.4BSD(1993)
多播,长肥管道的修改
4.3BSD Reno (1990)
快速恢复,T C P首部预
测,S L I P首部压缩,路
由表改变
4.3BSD Tahoe (1988)
慢启动,防拥塞,快速
重传
4.3BSD (1996)
改进了TCP性能
4.2BSD (1983)
第一次被广泛应用的
TCP/IP版本
有时称为伯克利插口(Berkeley socket),因为它被广泛地发布于4 . 2 B S D 系统中(见图1 - 1 )。但它
已被移植到很多非 BSD Unix系统和很多非U n i x 系统中。后者最初是由 AT & T 开发的,由于被
X / O p e n 承认,有时叫作 X T I ( X / O p e n 传输接口)。X / O p e n是一个计算机厂商的国际组织,它制
定自己的标准。X T I 是T L I的一个有效超集。
虽然本文不是一本程序设计书,但既然在 N e t / 3 ( 和所有 B S D 版本)中应用编程用插口来访
问T C P / I P ,我们还是说明一下插口。在各种非 U n i x系统中也实现了插口。插口和 T L I的编程细
节在[Stevens 1990]中可以找到。
系统Ⅴ版本4 ( S V R 4 ) 也为应用编程提供了一组插口 A P I,在实现上与本文中列举的有所不
同。在S V R 4 中的插口基于“流”子系统,在 [Rago 1993]中有所说明。
1.5 程序示例
在本章我们用一个简单的C程序(图1- 2 )来介绍一些B S D 网络实现的很多特点。
图1-2 程序示例:发送一个数据报给 U D P 日期/时间服务器并读取一个应答
4计计TCP/IP详解 卷2:实现
下载