收藏 分享(赏)

TCP-IP详解卷2:实现.pdf

上传人:wenkunet 文档编号:6997 上传时间:2018-05-21 格式:PDF 页数:872 大小:44.66MB
下载 相关 举报
TCP-IP详解卷2:实现.pdf_第1页
第1页 / 共872页
TCP-IP详解卷2:实现.pdf_第2页
第2页 / 共872页
TCP-IP详解卷2:实现.pdf_第3页
第3页 / 共872页
TCP-IP详解卷2:实现.pdf_第4页
第4页 / 共872页
TCP-IP详解卷2:实现.pdf_第5页
第5页 / 共872页
点击查看更多>>
资源描述

1、下载第 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码字符串。这个进程发送的数据报经过所有的协议栈到达设备驱动器,来自服务器

2、的应答从下向上经过所有协议栈到达这个进程。通过这个例子的这些细节介绍了很多核心数据结构和概念,这些数据结构和概念在后面的章节中还要详细说明。本章的最后介绍了在本书中各源代码的组织,并显示了联网代码在整个组织中的位置。1.2 源代码表示不考虑主题,列举 15 000行源代码本身就是一件难事。下面是所有源代码都使用的文本格式:1.2.1 将拥塞窗口设置为 13 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节中

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

4、 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行的函数一般被分成段,一段一段地显示。虽然尽量使代码和相应的描述文字放在同一页或对开的两页上,但为了节约版面,不可能完全做到。本书中有很多对其他函数的交叉引用。为了避免给每个引用都添加一个图号和页码,书封底内页中有一个本书中描述的所有函数和宏的

5、字母交叉引用表和描述的起始页码。因为本书的源代码来自公开的 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

6、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 以链路层广播发送 /接收通常用这种方式显示所有的

7、# 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联

8、网版本”发行。这个源代码是很多其他实现的起点,不论是 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.

9、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

10、 S D版本使用的一个 T C P / I P实现,是由 Bolt Beranek andN 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 andMcKusick 1986描述了从 4

11、. 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/1BSD联网软件版本 2.0(1991): Net/24.4BSD-Lite(1994)在正文中用 Net/3表示4.4BSD(1993)多播,长肥管道的修改4.3BSD Reno (1990)快速恢复, T

12、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 用库函数实现 s e n d的好处是仅调用 s e n d t o,减少了系统调用的个数和内核代码的长度。缺点是由于多调用了一个函数,增加了进程调用 s e

13、 n d的开销。因为本书是说明 T C P / I P的伯克利实现的,大多数进程调用的函数 (s o c k e t、 b i n d、c o n n e c t等 )是直接由内核系统调用来实现。1.7 网络实现概述N e t / 3通过同时对多种通信协议的支持来提供通用的底层基础服务。的确, 4 . 4 B S D支持四种不同的通信协议族:1) TCP/IP(互联网协议族 ),本书的主题。2) XNS(Xerox网络系统 ),一个与 T C P / I P相似的协议族;在 8 0年代中期它被广泛应用于连6计计 TCP/IP详解 卷 2:实现 下载接 X e r o x设备 (如打印机和文件服

14、务器 ),通常使用的是以太网。虽然 N e t / 3仍然发布它的代码,但今天已很少使用这个协议了,并且很多使用伯克利 T C P / I P代码的厂商把 X N S代码删去了 (这样他们就不需要支持它了 )。3) OSI协议 Rose 1990; Piscitello and Chapin 1993。这些协议是在 8 0年代作为开放系统技术的最终目标而设计的,来代替所有其他通信协议。在 9 0年代初它没有什么吸引力,以致于在真正的网络中很少被使用。它的历史地位有待进一步确定。4) Unix域协议。从通信协议是用来在不同的系统之间交换信息的意义上来说,它还不算是一套真正的协议,但它提供了一种进

15、程间通信 ( I P C )的形式。相对于其他 I P C,例如系统 V消息队列,在同一主机上两个进程间的 I P C使用 U n i x域协议的好处是 U n i x域协议用与其他三种协议同样的 A P I (插口 )访问。另一方面,消息队列和大多数其他形式 I P C的 A P I与插口和 T L I完全不同。在同一主机上的两进程间的 I P C使用网络 A P I,更容易将一个客户 /服务器应用程序从一台主机移植到多台主机上。在 U n i x域中提供两个不同的协议 一个是可靠的,面向连接的,与 T C P相似的字节流协议;一个是不可靠的,无连接的,与 U D P相似的数据报协议。虽然

16、U n i x域协议可以作为一种同一主机上两进程间的 I P C,但也可以用 T C P / I P来完成它们之间的通信。进程间通信并不要求使用在不同的主机上的互联网协议。内核中的联网代码组织成三层,如图1- 3所示。在图的右侧我们注明了 O S I参考模型 P i s c i t e l l o和 Chapin 1994的七层分别对应到 B S D组织的哪里。1) 插口层是一个到下面协议相关层的协议无关接口。所有系统调用从协议无关的插口层开始。例如:在插口层中的 b i n d系统调用的协议无关代码包含几十行代码,它们验证的第一个参数是一个有效的插口描述符,并且第二个参数是一个进程中的有效指

17、针。然后调用下层的协议相关代码,协议相关代码可能包含几百行代码。2) 协议层包括我们前面提到的四种协议族 ( T C P / I P, X N S, O S I和 U n i x域 )的实现。每个协议族可能包含自己的内部结构,在图 1 - 3中我们没有显示出来。例如,在 I n t e r n e t协议族中, I P (网络层 )是最低层, T C P和 U D P两运输层在 I P的上面。3) 接口层包括同网络设备通信的设备驱动程序。1.8 描述符图 1 - 2中,一开始调用 s o c k e t,这要求定义插口类型。 I n t e r n e t协议族 (P F _ I N E T)

18、和数据报插口 (S O C K _ D G R A M)组合成一个 U D P协议插口。s o c k e t的返回值是一个描述符,它具有其他 U n i x描述符的所有特性:可以用这个描述符调用 r e a d和 w r i t e;可以用 d u p复制它,在调用了 f o r k后,父进程和子进程可以共享第 1章 概 述 计计 7下载进 程7. 应用6. 表示5. 会话4. 运输3. 网络2. 数据链路1. 物理插口层系统调用 (socket, bind, connect, etc.)媒体协议层(TCP/IP, XNS, OSI, Unix)接口层(以太网、 SLIP、环回等等 )图 1

19、-3 Net/3联网代码的大概组织它;可以调用 f c n t l来改变它的属性,可以调用 c o l s e来关闭它,等等。在我们的例子中可以看到插口描述符是函数 s e n d t o和 r e c v f r o m的第一个参数。当程序终止时 (通过调用e x i t ),所有打开的描述符,包括插口描述符都会被内核关闭。我们现在介绍在进程调用 s o c k e t时被内核创建的数据结构。在后面的几章中会更详细地描述这些数据结构。首先从进程的进程表表项开始。在每个进程的生存期内都会有一个对应的进程表表项存在。一个描述符是进程的进程表表项中的一个数组的下标。这个数组项指向一个打开文件表的结

20、构,这个结构又指向一个描述此文件的 i - n o d e或 v - n o d e结构。图 1 - 4说明了这种关系。图 1-4 从一个描述符开始的内核数据结构的基本关系在这个图中,我们还显示了一个涉及插口的描述符,它是本书的焦点。由于进程表表项是由以下 C语言定义的,我们把记号 p r o c 放在进程表项的上面。并且在本书所有的图中都用它来标注这个结构。struct proc .Stevens 1992, 3 . 1 0节 显示了当进程调用 d u p和 f o r k时,描述符、文件表结构和 i - n o d e或 v - n o d e之间的关系是如何改变的。这三种数据结构的关系存

21、在于所有版本的 U n i x中,但不同的实现细节有所变化。在本书中我们感兴趣的是 s o c k e t结构和它所指向的 I n t e r n e t专用数据结构。但是既然插口系统调用以一个描述符开始,我们就需要理解如何从一个描述符导出一个 s o c k e t结构。如果程序如此执行a.out不重定向标准输入 (描述符 0 )、标准输出 (描述符 1 )和标准错误处理 (描述符 2 ),图 1 - 5显示了程序示例中的 N e t / 3数据结构的更多细节。在这个例子中,描述符 0、 1和 2连接到我们的终端,并且当 s o c k e t被调用时未用描述符的最小编号是 3。当进程执行了

22、一个系统调用,如 s o c k e t,内核就访问进程表结构。在这个结构中的项p _ f d指向进程的 f i l e d e s c结构。在这个结构中有两个我们现在关心的成员:一个是8计计 TCP/IP详解 卷 2:实现 下载f d _ o f i l e f l a g s,它是一个字符数组指针 (每个描述符有一个描述符标志 );一个是f d _ o f i l e s,它是一个指向文件表结构的指针数组的指针。描述符标志有 8 bit,只有两位可为任何描述符设置: c l o s e - o n - e x e c标志和 m a p p e d - f r o m - d e v i c

23、 e标志。在这里我们显示的所有标志都是 0。由于 U n i x描述符与很多东西有关,除了文件外,还有:插口、管道、目录、设第 1章 概 述 计计 9下载所有 UDP Internet协议控制块的双向循环链表图 1-5 在程序示例中调用 s o c k e t后的内核数据结构备等等,因此,我们有意把本节叫做“描述符”而不是“文件描述符” 。但是很多U n i x文献在谈到描述符时总是加上“文件”这个修饰词,其实没有必要。虽然我们要说明的是插口描述符,但这个内核数据结构叫 f i l e d e s c 。我们尽可能地使用描述符这个未加修饰的术语。项 f d _ o f i l e s指向的数据

24、结构用 * f i l e 来表示。它是一个指向 f i l e结构的指针数组。这个数组及描述符标志数组的下标就是描述符本身: 0、 1、 2等等,是非负整数。在图 1 -5中我们可以看到描述符 0、 1、 2对应的项指向图底部的同一个 f i l e结构 (由于这三个描述符都对应终端设备 )。描述符 3对应的项指向另外一个 f i l e结构。结构 f i l e的成员 f _ t y p e指示描述符的类型是 D T Y P E _ S O C K E T和 D T Y P E _ V N O D E。 v -n o d e是一个通用机制,允许内核支持不同类型的文件系统 磁盘文件系统、网络

25、文件系统(如 N F S )、 C D - R O M文件系统、基于存储器的文件系统等等。在本书中关心的不是 v - n o d e,因为 T C P / I P插口的类型总是 D T Y P E _ S O C K E T。结构 f i l e的成员 f _ d a t a指向一个 s o c k e t结构或者一个 v n o d e结构,根据描述符类型而定。成员 f _ o p s指向一个有 5个函数指针的向量。这些函数指针用在 r e a d、 r e a d v、w r i t e、 w r i t e v、 i o c t l、 s e l e c t和 c l o s e系统调用

26、中,这些系统调用需要一个插口描述符或非插口描述符。这些系统调用每次被调用时都要查看 f _ t y p e的值, 然后做出相应的跳转,实现者选择了直接通过 f i l e o p s结构的相应项来跳转的方式。我们用一个等宽字体 ( f o _ r e a d )来醒目地表示一个结构成员的名称,用斜体等宽字体(s o o _ r e a d)来表示一个结构成员的内容。注意,有时我们用一个箭头指向一个结构的左上角(如结构 f i l e d e s c),有时用一个箭头指向右上角 (如结构 f i l e和 f i l e o p s)。我们用这些方法来简化图例。下面我们来查看结构 s o c k

27、 e t,当描述符的类型是 D T Y P E _ S O C K E T时,结构 f i l e指向结构 s o c k e t。在我们的例子中, s o c k e t的类型 (数据报插口的类型是 S O C K _ D G R A M )保存在成员 s o _ t y p e中。还分配了一个 I n t e r n e t协议控制块 ( P C B ):一个 i n p c b结构。结构 s o c k e t的成员 s o _ p c b指向 i n p c b,并且结构 i n p c b的成员 i n p _ s o c k e t指向结构 s o c k e t。对于一个给定插口

28、的操作可能来自两个方向: “上”或“下” ,因此需要有指针来互相指向。1) 当进程执行一个系统调用时,如 s e n d t o,内核从描述符值开始,使用 f d _ o f i l e s索引到 f i l e结构指针向量,直到描述符所对应的 f i l e结构。结构 f i l e指向 s o c k e t结构,结构 s o c k e t带有指向结构 i n p c b的指针。2) 当一个 U D P数据报到达一个网络接口时,内核搜索所有 U D P协议控制块,寻找一个合适的,至少要根据目标 U D P端口号,可能还要根据目标 I P地址、源 I P地址和源端口号。一旦定位所找的 i

29、n p c b,内核就能通过 i n p _ s o c k e t指针来找到相应的 s o c k e t结构。成员 i n p _ f a d d r和 i n p _ l a d d r包含远地和本地 I P地址,而成员 i n p _ f p o r t和i n p _ l p o r t包含远地和本地端口号。 I P地址和端口号的组合经常叫做一个插口。在图 1 - 5的左边,我们用名称 u d b来标注另一个 i n p c b结构。这是一个全局结构,它是所有 UDP PCB组成的链表表头。我们可以看到两个成员 i n p _ n e x t和 i n p _ p r e v把所有的 U D PP C B组成了一个双向环型链表。为了简化此图,我们用两条平行的水平箭头来表示两条链,而不是用箭头指向 P C B的顶角。右边的 i n p c b结构的成员 i n p _ p r e v指向结构 u d b,而不是它的成员 i n p _ p r e v。来自 u d b . i n p _ p r e v和另一个 P C B成员 in p _ n e x t的虚线箭头表示这里10计计 TCP/IP详解 卷 2:实现 下载

展开阅读全文
相关资源
相关搜索
资源标签

当前位置:首页 > 网络技术 > 后端技术

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:文库网官方知乎号:文库网

经营许可证编号: 粤ICP备2021046453号世界地图

文库网官网©版权所有2025营业执照举报