没有合适的资源?快使用搜索试试~ 我知道了~
TCP-IP详解卷二:实现 总共三卷,这是卷二
资源推荐
资源详情
资源评论
下载
第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:实现
下载
1. 创建一个数据报插口
1 9 - 2 0 s o c k e t函数创建了一个UDP 插口,并且给进程返回一个保存在变量 s o c k f d中的描
述符。差错处理函数 e r r _ s y s 在[Stevens 1992]的附录 B . 2中给出。它接收任意数量的参数,
并用v s p r i n t f对它们格式化,将系统调用产生的 e r r n o 值对应的U n i x 错误信息打印出来,
并中断进程。
我们在不同的地方使用术语插口: ( 1 )为4 . 2 B S D 开发的程序用来访问网络协议的
A P I 通常叫插口A P I或者就叫插口接口; (2) socket是插口A P I 中的一个函数的名字;
( 3 )我们把调用s o c k e t创建的端点叫做一个插口,如评注“创建一个数据报插口”。
但是这里还有一些地方也使用术语插口: (4) socket函数的返回值叫一个插口描
述符或者就叫一个插口; ( 5 ) 在内核中的伯克利联网协议实现叫插口实现,相比较其
他系统如:系统V的流实现。( 6 )一个I P 地址和一个端口号的组合叫一个插口, I P 地址
和端口号对叫一个插口对。所幸的是引用哪一种术语是很明显的。
2. 将服务器地址放到结构 s o c k a d d r _ i n 中
2 1 - 2 4 在一个互联网插口地址结构中存放日期 /时间服务器的I P地址( 1 4 0 . 2 5 2 . 1 . 3 2 ) 和端口号
( 1 3 ) 。大多数T C P / I P 实现都提供标准的日期 /时间服务器,它的端口号为 13 [Stevens 1994,图
1- 9 ] 。我们对服务器主机的选择是随意的
—
直接选择了提供此服务的本地主机 (图1- 1 7 ) 。
函数i n e t _ a d d r 将一个点分十进制表示的 I P地址的A S C I I字符串转换成网络字节序的 3 2
b i t 二进制整数。( I n t e r n e t 协议族的网络字节序是高字节在后 )。函数h t o n s把一个主机字节序
的短整数(可能是低字节在后)转换成网络字节序(高字节在后)。在S p a r c 这种系统中,整数是高
字节在后的格式, h t o n s典型地是一个什么也不做的宏。但是在低字节在后的 8 0 3 8 6 上的
B S D / 3 8 6 系统中, h t o n s可能是一个宏或者是一个函数,来完成一个 16 bit整数中的两个字节
的交换。
3. 发送数据报给服务器
2 5 - 2 7 程序调用s e n d t o 发送一个1 5 0 字节的数据报给服务器。因为是运行时栈中分配的未初
始化数组,1 5 0字节的缓存内容是不确定的。但没有关系,因为服务器根本就不看它收到的报
文的内容。当服务器收到一个报文时,就发送一个应答给客户端。应答中包含服务器以可读
格式表示的当前时间和日期。
我们选择的1 5 0 字节的客户数据报是随意的。我们有意选择一个报文长度在 1 0 0 ~ 2 0 8 之间
的值,来说明在本章的后面要提到的 m b u f 链表的使用。为了避免拥塞,在以太网中,我们希
望长度要小于1 4 7 2 。
4. 读取从服务器返回的数据报
2 8 - 3 2 程序通过调用r e c v f r o m 来读取从服务器发回的数据报。 U n i x 服务器典型地发回一
个如下格式的2 6 字节字符串
Sat Dec 11 11:28:05 1993\r\n
\ r
是一个A S C I I 回车符,\ n 是A S C I I 换行符。我们的程序将回车符替换成一个空字节,然后
调用p r i n t f输出结果。
在本章和下一章我们在分析函数 s o c k e t 、s e n d t o 和r e c v f r o m 的实现时,要进入这个
例子的一些细节部分。
第1章 概 述计计5
下载
剩余871页未读,继续阅读
资源评论
xixiangchui
- 粉丝: 2
- 资源: 9
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功