当前位置:Linux教程 - Linux - TCP/IP 协议概貌

TCP/IP 协议概貌



        
    作者:Charles L. Hedrick

    翻译:waterbird[AKA]


    Copyright (C) 1987, Charles L. Hedrick. Anyone may reproduce this document, in whole or in part, provided that: (1) any copy or republication of the entire document must show Rutgers University as the source, and must include this notice; and (2) any other use of this material must reference this manual and Rutgers University, and the fact that the material is copyright by Charles Hedrick and is used by permission.

    TCP/IP 是一个协议的分层集合。为理解此含义,让我们看一个例子,MAIL。首先,有一个MAIL的协议。它定义了一个从一台机器向另一台机器发送的命令集合,即那些指定谁是信息的发送者、谁是接受者以及信息的内容。该协议假定已经存在一条在两台计算机之间通讯的可靠通道。和其他应用协议一样,MAIL简单定义了一个命令集以及要发送的内容。它被设计为和TCP、IP一起使用。TCP保证命令被发送到另外一端,它跟踪要发送的东西,并在发送失败时重发信息。如果信息的内容(邮件长度)太长了,大于一个数据报的长度,TCP会把他们拆成几个数据报分别发送,并保证它们能够正确到达。因为这些函数在许多应用中都能用到,它们被打包成一个单独的协议,而不是作为MAIL协议的一部分。从编程的角度看,你可以认为TCP协议是一个函数库,调用它们可以和另一台计算机进行可靠的网络通讯。与此类似,TCP又要调用IP提供的服务。尽管很多应用都使用TCP提供的服务,也有一些应用不需要它。可是,存在一些每个应用都需要的服务。它们就被一起放进IP协议之中。象TCP一样,你可以认为IP是一个TCP要调用的函数库,当然,其他未用到TCP的协议也可以直接调用它。这种构造几个不同层次的协议的策略被成为“分层”。 我们把MAIL、TCP、 IP这样的应用程序看作是各个相互独立的“层”,它们都调用位于自己“下面”的那个层提供的服务。通常,TCP/IP应用使用4个层:

    * 应用协议如MAIL

    * 一个为其他应用提供服务的协议,如TCP

    * IP, 提供最基本的服务,把数据报送到目的地

    * 一个需要处理特定物理传输介质的协议,如以太网或点到点连接

    TCP/IP是基于“catenet”模型的。(详见IEN 48) 该模型假设许多个相互独立的网络通过网关连接在一起。用户可以从网络的任何地方访问其上的计算机和资源。数据报在到达目的地之前通常要经过许多不同的网络。完成此任务的路由工作对用户应该是完全不可见的。对用户而言,所有他需要知道的只是另一个系统的“Internet 地址”。这是一个类似 128.6.4.194 这样的地址。它实际上是一个32位数字。但是,它经常被写为4个10进制数字,每个数字代表地址的8 位。(Internet 文档 用\"octet\"一词表示这样的8位数据块,而不用\"字节\",因为TCP/IP也被其他一些非8位字节的计算机所支持。注:指在那些计算机中,1个字节并非是通常的8位)通常,该地址本身就向你透漏了些如何到达它们的信息。例如, 128.6 是由有关负责机构分配给 Rutgers 大学的网络号。Rutgers 大学使用下一个octet 来表示哪个校园的以太网。 128.6.4刚好是计算机系所使的以太网。最后那个octet可以用来表示该以太网上254个不同的系统。(因为0和255被禁用,原因稍后详述。) 注意 128.6.4.194和128.6.5.194将分属不同的系统。稍后我们再详细讨论Internet地址的结构。

    通常我们用名称而不是Internet地址来表示一个系统。当我们指定一个名称,网络软件就去查找数据库,返回它对应的Internet地址。 (见RFC 882)

    TCP/IP基于无连接技术。信息作为一个“数据报”序列传递。“数据报”是数据集,它作为一个单独的信息发送。这些“数据报”各自独立通过网络。有一些关于建立连接的条文。(即开始一个可持续的会话)然而在某些层,这些连接下的信息被拆分成数据报,这些数据报被网络单独传送。例如,设想你要传一个15000字节的文件。很多网络无法处理这么大的数据报。因此,协议会把它分成30个500字节大小的数据报,分别传送到另一端,然后再重新组装回一个15000字节大小的文件。网络在传输这些数据报时,并不知道它们之间的联系。包14很可能先于包13到达目的地。也可能由于网络的故障,某个数据报没能通过网络,这时它将被重发。

    注意,数据报和“包”一词常常可以互换。技术上,数据报是正确用语。数据报是协议处理的数据单元。包是在以太网或网线上出现的一个物理实体。多数情况下,一个包仅仅包含一个数据报,因此二者差别甚微。但他们仍有不同。当在X.25协议上使用TCP/IP时,X.25接口把数据报拆分成128字节的包。这对IP是不可见的,因为在另一端TCP/IP处理它之前各个包又被重新组装回原来的数据报格式了。这里,一个IP数据报有多个包来负载。但是对于绝大多数介质,采取一个包一个数据报的方式最为有效,因此它们之间就没什么差别了。

    ---- TCP层

    处理TCP/IP数据报用到两个协议。 其中 TCP(传输控制协议)负责把信息分割成一个个数据报、在另一端将他们重组、丢失时重新发送以及保证他们的正确顺序。 IP(Internet协议)则负责各个数据报的路由、寻径(routing) 。看起来好象TCP作了所有工作。而事实上对小型网络也正是如此。可是在Internet中,单单传一个数据报到目的地就是件非常复杂的工作。连接可能要求数据报经过Rutgers的几个网络、再经过通往冯.诺依曼超级计算中心的一根串行线、再经过那里的以太网、再经过到另一个NSFnet的一根56K电话线,以及另一个校园的以太网。实际表明,跟踪到所有这些地方的路由,以及处理不同传输介质之间的兼容性,是一件很复杂的工作。请注意TCP和IP之间的接口非常之简单。 TCP只是传给IP一个带目的地址的数据报。IP并不知道此数据报同它之前或之后的数据报有什么关系。

    你会觉得这里少了点什么。我们已经谈到了Internet地址,但并无涉及你怎样追踪到一个系统的多条连接。很明显它不足以使一个数据报到达正确的目的地。TCP必须知道该数据报属于哪个连接。这个任务被称为“解析(?)”。事实上,在TCP/IP中存在多个层次的\"解析\"。解析所需的信息位于一系列“包头”中。包头是协议加在数据报头部的一些附加8位字节,用来对该数据报进行追踪。这很象是你把一封信装入信封,再在外面写上地址。在现代网络中,该过程发生多次。类似以下过程:你把信件放入一个小信封,你的秘书再把它放进一个大信封,学校邮局又把它放入一个更大的信封。 下面是一个典型的TCP/IP网络如何给一个要传输的信息添加包头的:

    以一个简单数据流为例,如你要传递如下文件到其他计算机去:

    ......................................................

    TCP先把它分割成若干个可处理的数据块。(为此,TCP必须知道你的网络的最大可传输数据报的大小。实际上,两端的TCP先交流一下它们各自的最大可传输数据报大小,然后选择最小的那个。)

    .... .... .... .... .... .... .... ....

    TCP给每个数据报都添加一个“报头(header)”。此报头至少包含20个8位字节,其中最为重要的部分是源端口号、目的数据端口和序列号。端口号被用来追踪不同的对话。假设有3个不同的人要传送文件。你的TCP应该为他们分别分配3个端口:1000,1001和1002,这就是源端口号,因为你是该数据报的发送源。当然另一端的TCP也为会话分配了一个它自己的端口号。你的TCP必须知道另一端的那个端口号。(它用来判断何时开始连接。)它将其写入目的端口地址域。显然,如果是另一端向你发数据,源端口和目的端口应该倒过来,它是源而你却成了目的所在。每个数据报都有一个序列号。目的端据此来判断它以正确的顺序接受数据报,以及是否丢失数据报。TCP并不以数据报为单位计数,而是以8位字节数来计数。因此如果在每个数据报中有500个8位字节,那么第一个数据报的序号为0,第二个就为500,下一个就为1000,如此类推。 最后来谈谈校验和(Checksum)。它是将数据报中所有的字节相加所得之和。结果被放入报头中。另一端的TCP接受到数据报后,重新再算一遍校验和。如果二者不一致,该包就被认为有错而被抛弃。现在,数据报的格式就是这样子了:


    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Source Port | Destination Port |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Sequence Number |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Acknowledgment Number |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Data
    | |U|A|P|R|S|F| |
    | Offset|
    Reserved |R|C|S|S|Y|I| Window |
    | |
    |G|K|H|T|N|N| |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |
    Checksum | Urgent Pointer |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |
    your data ... next 500 octets |
    | ......
    |


    如果我们将TCP“报头”缩写为\"T\",则整个文件现在就是这样子了:

    T.... T.... T.... T.... T.... T.... T....

    你会注意到报头中有些东西我还未描述到。通常它们是用来管理连接的。为了确保数据报已经到达了目的地,接收方必须送回一个“确认”。这是一个填充了“确认号码”的数据报。例如,送回一个确认号为1500的数据报表明你已经收到了所有1500号以前的数据报。如果发送方在一段合理长的时间内未收到确认,它将再次发送数据。窗口是用来控制一次可以发送多少数据。如果每次都等到收到前一个数据报的确认后才发送下一个数据报,传输效率就太低了。 另一方面,你也不能马不停蹄地只管发送。因为那样一个快速的计算机的发送速度会超过一个慢速接收方的接受能力而导致溢出。 因此每个接收端在自己的“窗口域”中显示一个数字来表示自己当前准备接收的新的数据量。当计算机接收数据时,窗口中的数据逐步减少,减到0时,发送方将停止发送数据。当接收方处理数据时,窗口中的数据逐步增加,表明它可以接受更多的数据了。通常,负责发确认信号的哪个数据报也负责通知发送方可以继续发送新的数据了。(通过一个更新了的窗口) “紧急域”(Urgent)允许一端通知另一端跳过一个特定的字节而不加处理。这常常用于处理异步事件,例如在你敲入一个控制字符或其他命令中断输出时。其它域超出了本文档的讨论范围。

    3 IP层

    TCP把每个数据报都送给IP。当然它必须告诉IP另一端计算机的Internet地址。注意这才是IP要关心的。它并不在乎数据报的内容,甚至也不在乎TCP头的内容。IP只是为数据报找到路由,将其送到另一端。为了让网关及其他中间系统传送数据报,IP为数据报加上自己的报头。报头中主要包含源端IP地址(32位地址,如128.6.4.194)、目的端IP地址、协议号和一个校验和。源端IP地址就是你的机器的地址。(必须,另一端靠它获知数据报的来源)目的端IP地址是另一台机器的地址。(必须,中间的网关靠它获知数据报的目的地)协议号告诉另一端的IP将数据报送给TCP协议进行处理而非其它。尽管很多IP传输都使用TCP,但也能使用IP的其它协议,因此你必须告诉IP究竟把数据报送给哪个协议。最后,校验和允许另一端的IP验证数据报头是否在传输中被损坏。注意,TCP和IP都有各自的校验和。IP需要验证数据报头是否在传输中被损坏,否则就会将消息送到错误的目的地。但是,使用TCP协议对TCP的报头和数据单独计算一个校验和更加有效、也更加安全(原因篇幅所限,恕不在此详述)。一旦IP准备好了报头,格式将如下所示:


    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |Version| IHL |Type of Service| Total Length |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Identification |Flags| Fragment Offset |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Time to Live | Protocol | Header Checksum |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Source Address |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Destination Address |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | TCP header, then your data ...... |
    | |

    如果我们将IP的报头用\"I\"来表示,我们要传输的数据将如下所示, 其中T代表TCP的报头:


    IT.... IT.... IT.... IT.... IT.... IT.... IT....

    同样,报头中也有一些未被讨论的域。它们大多超出了本文档的范围。标志位(flags)和段偏移量 (fragmentoffset)被用于当一个数据报不得不被拆分时追踪数据碎片。对于某些最大传输数据包尺寸较小的网络,当大数 据 报经过时,就需要将它拆开成合适大小的数据报。存活时间(time to live)是一个随着数据报的传输而不断变小的数字。当它减为零时,这个数据报就被丢弃。这可以防止系统中传输环路的 影响。当然这应当是很少发生的,但是设计良好的网络必须也能够处理这些“意外”情况。

    到现在,我们不再需要报头了。如果你的计算机跟目的计算机刚好有一个直接的电话线连接,或通过网关相连,它可以简单地把数据发送出去。(尽管可能还会用到一个同步协议如HDLC,但它只是在开始和结束加上几个8进制数)

    4 以太网(Ethernet)层

    然而今天多数网络都使用以太网。所以我们现在必须描述一下以太网的报头。不幸的是,以太网有自己的地址。设计以太网的人希望确保世界上所有计算机都有一个唯一的以太网地址。而且,它们不想让用户去担心如何分配以太网地址的问题,因而每个以太网控制器(网卡)出厂时就自带了一个唯一的地址。为确保不会重复,设计者为以太网地址留出了48位空间。制造以太网设备的厂家必须到一个权威机构进行登记,以确保他们使用的以太网地址不会跟其他厂家的重复。以太网是以“广播方式”工作的。它象是那种老式的会议电话。当你往以太网上发送一个数据报后,网络上所有的计算机都能看到它。因此必须有种机制来保证正确的机器才能接收它。如你所猜,这涉及到以太网报头。每个以太网数据包都有一14个八进制数长的报头,它包括源以太网地址、目的以太网地址和一个类型码。每台机器都被假定只对发给自己的数据报 ----目的以太网地址和自己地址相等的数据报----即感兴趣。(当然,进行欺骗是绝对可行的,这就是以太网通讯是绝对不安全的一个原因)注意,在以太网地址和因特网地址(即IP地址)之间并无必然联系。每台机器都有一个以太网地址和IP地址的对照表。 (稍后我们将对此进行进一步讨论)除了地址,报头还包含一个类型码。这个类型码允许多种不同的协议族在同一个网络上运行。 因此你可以同时使用TCP/IP, DECnet, Xerox NS,等等,它们每个都往报头的类型域中填入不同的数值。最后,也有一个校验和。由以太网控制器负责计算所有数据包的校验和。当另一端收到数据报后,它重新计算校验和,扔掉与原先校验和不一致的数据包。 这个校验和被放在数据包的尾部,而非头部。最后,你的数据变成了下面这个样子:



    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Ethernet destination address (first 32 bits) |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Ethernet dest (last 16 bits) |Ethernet source (first 16 bits)|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Ethernet source address (last 32 bits) |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Type code |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | IP header, then TCP header, then your data |
    | |
    ...
    | |
    | end of your data |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    | Ethernet Checksum |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    如果我们用\"E\"来代替以太网数据报头,用\"C\"来代替以太网校验和,你的文件看起来将是这个样子:

    EIT....C EIT....C EIT....C EIT....C EIT....C

    当这些数据包被另一端收到后,所有的报头都会被移走: 以太网接口会移走以太网数据报头和以太网校验和。它看一看类型码。因为这里类型码是IP,所以以太网设备驱动器将数据包向上送给IP; IP移走IP报头。它看一看IP的协议域,发现协议类型是TCP,于是将包送给TCP; TCP检查一下序列号,它使用序列号以及其他信息将各个数据包合起来形成原来的文件。

    TCP/IP 协议概貌介绍到此结束。当然还有很多重要的概念没有得到详细的论述。(详细描述请参考RFC 793 for TCP, RFC 791 for IP, and RFC\s 894 and 826 for sending IP over Ethernet.)
    发布人:netbull 来自:AKA主页