
3.4 TCP/IP参考模型
前面提到,TCP/IP参考模型出现在OSI参考模型之前,是Internet的前身ARPANET所使用的参考模型,其目标是当子网硬件故障时计算机网络不受影响并且已建立的会话不会被取消,所以整个体系结构相当灵活。TCP/IP是基于网间互联的构造模型,如图3-22所示。由于Internet的影响力日益增强,TCP/IP网络体系结构已经成为计算机网络结构的事实标准并得到全世界计算机网络公司的支持。

图3-22 TCP/IP参考模型及各层协议
TCP/IP的目标决定了TCP/IP是一种基于无连接的IP包交换网络。TCP/IP参考模型分为4层,即网络接口层(IP子网层)、IP层(网络层)、TCP层(传输层)和应用层。TCP/IP协议栈由一系列协议所组成,包括TCP、IP、UDP、ARP、ICMP及其他一些协议,下面详细描述。
3.4.1 TCP/IP协议与OSI七层协议的对应关系
TCP/IP是一个协议栈,既包括底层协议,也包括应用层协议。它大致分为4个层次:应用层、传输层、网络层和网络接口层,它与OSI参考模型的对应关系如图3-23所示。

图3-23 TCP/IP协议与OSI参考模型的对应关系
从图3-23可以看出,应用层对应于OSI参考模型中的应用层和表示层,应用程序通过FTP、HTTP、TFPT、SMTP、DHCP等应用层协议或者应用程序接口(API)在网络上传输数据;传输层对应于OSI参考模型中的会话层和传输层,包括TCP和UDP传输协议用于提供流控制、排序及错误校验功能,其中TCP是面向连接的,UDP是无连接的;网络层对应于OSI参考模型中的网络层,除了IP协议外,这一层还包括ICMP、IGMP、ARP等协议,都是用来处理数据包的路由信息及地址的解析。网络接口层对应于OSI参考模型中的数据链路层和物理层,处理数据帧的格式并将数据传送至网络。TCP/IP协议族中的核心协议是TCP(传输控制协议)和IP(网际互连协议)。
3.4.2 网络接口层
网络接口层又称为IP子网层,用于定义各种物理网络的接口,负责数据帧的发送和接收。TCP/IP参考模型并没有真正描述网络接口层,只是指出主机与网络相连需要使用的某种协议。
3.4.3 IP层
IP层用于提供无连接的、不可靠的、“尽力而为”(best-effort)式的数据包传送服务,使一个主机可以把数据包独立地(可能经过不同的网络)发送到任何网络中的目的主机。由于数据包可以独立传输,因此为了使数据按顺序到达接收方,高层协议需要对数据包进行排序。
在TCP/IP协议栈的IP层中实际上有多个协议,构成了IP协议族,包括IP协议、ICMP协议、IGMP协议、RAP/RARP协议等。IP协议定义了数据包的格式和处理过程、ICMP协议(网间控制报文协议)用于控制数据包传输、IGMP协议(互联网组管理协议)用于支持主机和路由器进行多播(multicast)、RAP/RARP协议用于转换IP地址和MAC地址。IP层主要功能就是把数据包发送到正确的目的地,需要解决的问题主要是路由选择和拥塞控制。
使用IP协议可以使多个小型网络(子网)通过路由器连成一个大型网络。下面对IP层协议涉及的内容做具体介绍。
1.IP数据包(datagram)
数据帧中与IP层有关的部分叫做IP数据包,其中包含了路由器转发数据帧时所需要的信息,包括包头和数据,长度不超过65535字节,如表3-1所示。
表3-1 IP数据包的结构

其中各数据项的含义是:
(1)版本:表示IP协议的版本号。目前主要的TCP/IP网络都使用IPv4版本的协议,大多数计算机也都支持IPv6协议,但是IPv6还没有大量使用。接收到数据包的网络设备会首先检查版本以便知道它是否能处理该数据包。
(2)包头长度:这个32位的域用来指明IP协议包头的长度,接收设备可以根据这个长度判断数据帧的开始位置。
(3)服务类型:包括数据优先级、可靠性和延迟等,表明应该怎样处理输入数据包的信息。
(4)总长度:包头和数据的总长度。
(5)标志号:用于表示消息是否分段,如果消息分段则表明是否最后一段。
(6)标识符:表明一个数据包的消息使接收设备可以重组分段消息。
(7)段偏移量:表明数据段处于输入段集合中的哪一段。
(8)生存期:表明一个数据包在网络中最多经过几个路由器,每经过一个路由器,生存期减1,当生存期减为0时就不能再向下一个路由器传输了。
(9)协议:表明该数据包的传输层协议。
(10)包头校验和:用于检验IP包头是否出错。
(11)源地址:表示数据源的IP地址(有关IP地址的知识在下文中介绍)。
(12)目标地址:表示目标的IP地址。
(13)可选项:可选的路由信息等相关信息,用于规定附加服务。
(14)填充位:填充位的作用是保证IP数据包头的长度是32位的倍数。
(15)数据:从传输层获取的数据包内容(原始数据加TCP或UDP包头)。
从IP数据包的格式可以看出,除了路由选择外,IP层协议还要负责数据的分段、重组和校验控制,以保证路由信息的完整性。
路由选择的简单过程是,每个收到数据包的路由器从包头获取目标地址,查找路由器自身的路由表得到通向目的地的下一跳(next hop)路由器的地址,然后把数据转发给下一跳地址,直到数据包到达目标地址的主机。其中,路由表的基本内容包括目的网络地址、目的网络地址的掩码和通向目的网络的下一跳地址。关于路由选择和路由表的详细内容将在下文中介绍。
2.IP地址
TCP/IP网络中每个网络设备都具有一个单独的IP地址,作为与网上其他设备区别的标志,其作用类似于电话网中的电话号码和邮政网络中的门牌号码。
完整的IP地址有32位(四字节)二进制数字,其表示方式是所谓的“点分二进制”,即每8位(一个字节)组成一段(segment),段之间用“.”号隔开,如10100010.1101001.10100011. 1110100。点分二进制的表示方法方便计算机读取,但不便于人的记忆,因此人们在实际使用时可以用十进制数表示IP地址,上面的IP地址例子转换为点分十进制,就是162.105. 163.116。实际上即使十进制的IP地址对人而言也不易记忆,所以可以为每个主机分配一个主机名,操作系统负责进行IP地址和主机名的转换。
32位IP地址实际上被分为两个部分,即网络ID和主机ID。网络ID用于确定所在的网络,而主机ID用于确定该网络中特定的主机。网络ID和主机ID的关系类似于电话网络中的区号和市内电话号码。因此,处于同一网段的所有主机具有相同的网络ID,例如北京大学校园网内的主机都具有相同的网络ID“162.105”,而在同一个网络内,所有的主机具有唯一的主机ID,否则就会发生地址冲突。根据网络ID的长度可以把常用的IP地址分为A、B、C三类, A类地址具有8位网络ID, B类地址具有16位网络ID, C类地址具有24位网络ID,相应的主机ID长度就分别是24位、16位、8位,具体如图3-24所示。实际上,IP地址中还有一个类别是D类地址,D类地址用于表示多播(multicast)中的组,这里不再详述。

图3-24 IP地址分类
用A类地址可以建立一个超大规模网络,由于A类地址具有24位主机ID,因此可以在网络内容纳224-2=16777214台主机(全0和全1的主机ID被保留)。在上表中可以看到,A类地址的最高位总是0,接下来的7位是网络ID,且第一个字节只能取1—126之间的数字(网络ID127被保留用于回路及诊断,另外,全为0和全为1的网络ID也不可用,分别作为本地网络地址和广播地址),因此使用A类地址的网络最多只有126个。目前A类地址主要被美国的企业和单位占用,例如IBM、斯坦福大学等。
B类地址用于相对来说中等规模的网络。B类地址的前两个字节是网络ID,后两个字节是主机ID,并且第一个字节必须以10开头,也就是说第一个字节取128—191之间的数。可以计算B类地址的网络最多有216-2=65534个,每个B类地址网络中最多容纳216-2=65534个主机。
C类地址用于小型网络。前三个字节是网络ID,第四个字节是主机ID,且第一个字节以110开头,因此第1个字节取192—223之间的数,所以C类地址的网络最多有224-2=16777214个,每个网络中最多可容纳28-2=254个主机。
划分网络IP地址时还保留了一部分地址用于网络内部的特殊的用途,当局域网使用保留IP地址时,不会与其他局域网的保留地址冲突。保留IP地址的范围如表3-2所示。
表3-2 保留IP地址

有时为了将一个大的网络划分成若干小的子网,需要用到子网掩码。子网掩码也是一个32位的点分二进制数,与IP地址结合使用就可以确定IP地址中的网络ID和主机ID,还可以把一个网络划分成若干子网。当不需要划分子网时的默认子网掩码如表3-3所示。
表3-3 系统默认子网掩码

掩码中前面一段为全1的字节,后面一段为全0的字节,全1的部分定位网络ID,全0的部分定位主机ID。具体地,当需要划分子网时,只需要按照需要调整掩码中1和0所占的bit数就可以了,例如在一个A类网络中,使用B类子网掩码255.255.0.0或C类子网掩码255. 255.255.0就可以将网络分成多个B类子网或者多个C类子网,从而增加网络数量,减少每个网络中的主机数量,在B类网络中使用C类掩码也一样。反过来,在C类网络中使用B类子网掩码就可以把多个小规模的C类网络再合并为一个B类网络以满足大型企业机构的需求。除此之外,子网掩码中网络ID部分的位数可以任意选择,比如11111111.11100000. 00000000.00000000(255.224.0.0)是一个A类子网掩码,子网中的主机数是2097150个。
每个网络可以选择不同的协议进行通信,但这对异种网络之间的通信带来困难,网关(gateway)就是用来解决异种网络间通信的设备,运行不同协议的两种网络可以通过网关相互访问,而两个TCP/IP网络之间通信可以简单地使用“默认网关”(default gateway)。由于网关要承担不同网络的连接工作,因此必须在每个所连接的子网中拥有一个IP地址。
3.IP数据传输
这里简单介绍一下IP层与网络接口层的数据交换。
在网络接口层,数据包被封装在物理帧的特定数据区内。网络接口层通过帧的形式传输数据,其中帧头部的目的地址是目的地址的下一跳的物理地址。发送方对数据包进行封装后把物理帧发送给下一跳,下一跳的物理设备从接收到的物理帧的数据区中提取数据包,去掉帧头部,再用下一个物理网络的帧格式进行数据包封装,再传给下一跳,依次类推直至目的地址。
特定的网络所允许的物理帧的最大数据量被称为MTU(maximum transmission unit),当路由器收到一个大于其要转发的网络的MTU的数据包时,会把数据包分成可以通过该网络的数据片,每一片封装成同样的数据包格式,并保留原数据包中的标识符。每个数据片都独立传输,可以通过不同的路由选择路径达到目的主机,在目的主机对数据片重组恢复原始数据包。重组的依据就是数据包首部的标志号、标识符和偏移量。关于路由选择的内容将在后文中介绍。
4.IP层协议族
IP层实际上包含多个协议,分别完成不同的工作,包括IP协议、ICMP协议、IGMP协议、ARP/RARP协议等。
(1)IP(Internet Protocol)协议。IP协议是IP层中最重要的协议。
在IP层传输数据时,如果目标IP地址在本地,则将数据包直接传输到该主机,而如果目标地址是其他网络中的远程地址,则需要在本地路由表中获取远程主机的路由,并按照路由路径发送数据包到下一跳路由器,如果没找到路由,就直接发送到源主机的默认路由器。
路由器在收到数据包之后,IP层软件读取IP包头的信息,并进行如下处理:若线路拥塞,路由器会对数据拥塞控制使数据包暂时停止传输;若数据包超过下一个网络的允许的最大数据量的话,把数据包切分为若干小的数据包,给每个新数据包添加一个新的包头,并计算一个新的检验和;获取下一个路由的目标硬件地址,并转发数据包;每个路由器重复该过程直到数据包被送至目的主机,在目的主机组装被切分的小数据包,并上传至传输层的TCP或UDP。
需要注意的是,IP数据包是不可靠的,不能保证数据包按顺序、完整、准确地发送到目的主机或没有被破坏。IP协议假定包头中的源地址是有效的,但修改源地址可以被用来欺骗系统以便进行被禁止的连接,依靠IP源地址确认的网络服务可能会被用于非法入侵。
(2)ARP/RARP协议。IP数据包在网络接口层中通常是通过以太网发送的。但以太网设备并不能直接识别32位网络IP地址,而是使用48位的以太网地址(硬件地址)。因此需要把IP地址转换为硬件地址。地址解析协议(address resolution protocol, ARP)就是进行这种地址转换的协议,它可以获得在同一物理网络中的主机的物理地址。而RARP(反向地址解析协议)则用于无盘工作站寻找其IP地址。
ARP协议包含ARP请求和ARP回应两种消息类型。其数据包的内容如图3-25所示。其中,阴影部分是以太网数据帧的头部。

图3-25 ARP包结构
使用ARP解析本地的目标IP地址时,ARP协议生成一个包含源主机IP地址和硬件地址的ARP请求,并广播到本地所有主机;每个本地主机收到广播后在本机寻找与目标IP地址相符的IP地址;如果某个主机确定ARP请求中的目的IP地址与自己相符就发送一个ARP回应,把自己的硬件地址发送给源主机,并以源主机IP地址和硬件地址更新其ARP缓存;源主机收到ARP回应后就可以建立通信。
当目的主机在远程网络时,源主机在本地路由表中查不到目标IP,因此源主机会把默认网关IP地址作为目标IP地址,然后在ARP缓存中查找符合的硬件地址;如果没找到,ARP协议将广播一个获取默认网关(路由器)硬件地址的ARP请求,这时路由器会用自己的硬件地址回应该ARP请求,因此源主机把数据包发送到路由器;最终由路由器把数据发送到目的主机。
ARP协议在缓存中保存一个地址映射表。为了节省缓存,被解析过的ARP条目如果在一段时间内没有被参考过,则条目被自动删除。ARP缓存中也可以有静态项,静态项不会被自动删除直到重启计算机。需要注意的是本地子网的硬件广播地址总是作为一个永久项,这使得主机能够接受ARP广播。
(3)网际控制报文协议(Internet control message protocol, ICMP)。ICMP协议用于传输IP层的控制消息,以便报告错误并对消息进行控制。ICMP主要用于提供通向目的主机的路径信息。其中,“redirect”消息可以通知主机通向其他主机的准确路径;“unreachable”消息表示路径有问题;source quench(源抑制)消息表示速度达到路由器的饱和状态;如果路径不可用,ICMP可以使TCP连接终止。另外,ping是最常见的ICMP服务。
ICMP数据包的结构包括:一个8位类型字段,表示ICMP数据包类型;一个8位代码域,表示指定类型的一个功能;数据包中ICMP部分的一个16位校验和。
(4)网际组管理协议(Internet group management protocol, IGMP)。IGMP用于管理多播通信。IGMP消息可以使路由器获取目标主机组和目标网络信息,其结构包括版本、类型(0x1h类型为主机成员请求,0x2h类型为主机成员报告)、校验和与组地址(D类地址)。
5.IP路由
前面提到,当数据需要传输到远程网络时,必须通过源主机和目的主机之间的路由器进行转发,称为IP路由。所谓路由就是要选择一条数据的传输路径。路由选择的主要依据是路由器内存中的路由表,其大致过程如下:
当主机试图与另一个主机通信时,IP层软件判断目的主机是否处于一个远程网络;
如果目的主机在远程网络,查询路由表来选择一个路由;
若未找到明确的路由,用默认网关的地址将数据传输到另一个路由器;
依次类推,直到数据被发送到目的主机,在这个路径中经过的每个路由器称为-“跳”(hop)。
路由器工作在网络层协议上,是用于把各种网络连接在一起的中介系统。路由功能可以用硬件设备完成,也可以用软件实现。用硬件设备实现路由功能的路由器称为硬件路由器,用软件方式实现路由功能的路由器称为软件路由器。目前主流的操作系统都集成了软件路由功能。图3-26就是一个完整的可路由网络的示意图。

图3-26 可路由网络示意图
一个主机在发送数据包时所激发的路由称为主机路由,这时主机根据目的主机的地址决定把数据包直接发送到目的主机还是先发送到路由器。路由器收到数据包后激发的路由称为路由器路由,路由器也需要根据目的主机是否与自身直接相连决定把数据发送给目的主机还是下一个路由器,以此类推直到目的主机接收到数据。图3-27简单显示了直接发送数据和通过路由器把数据发送到另一个子网的两种过程。

图3-27 直接发送和间接发送
6.IP路由算法
前面提到,跨子网的数据传输需要路由器进行路由选择,以便一跳接一跳地把数据传输到最终的目的主机。每个路由器对于下一跳路由器的选择由路由算法来决定,路由算法可以看作是一个由所有路由器和网络主机共同执行的一个分布式算法,这一小节简单介绍主要的路由选择算法。
(1)最短路径算法。最短路径法是最简单的路由选择算法,其主要目标是找出两个给定网络节点(路由器)之间的最短路径。计算最短路径的方法很多,最著名的最短路径算法是Dijkstra算法。
假设一个网络中共有N个节点,网络连接和连接的距离已知,现在要计算源节点到其他所有节点的最短路径,那么Dijkstra算法的大致过程是:
维护一个通向其他所有节点的最短路径表,初始时刻,在表中记录所有与源节点直接相连的连接的长度,把所有与源节点不直接相连的连接的长度设为无穷大(或者一个足够大的数);
然后,挑选出表中N-1个距离的最小值,也就是与源节点距离最短的直接相连的节点,并用与该节点直接相连的连接的长度来更新最短路径表,也就是说,如果源节点通过该节点到达某个节点的距离比表中对应的距离短,就更新这个距离;
接下来,在表中剩余N-2个距离中选择最小值,重复上面的过程更新表项,直到最后一个节点。
当这个计算过程结束后就得到了源节点到其他所有节点的最短路径,稍微改造这个算法还可以得到一个列表,记录源节点到其他所有节点的最短路径上所需要通过的下一个节点是哪个,这个列表称为路由表,保存在源节点的内存中。每个节点上都会保存这样一个路由表以记录自己到其他节点的最短路径需要通过的下一个节点。
有了路由表之后,路由器就可以在转发数据时根据目标IP地址找到下一跳的地址了。
(2)扩散法。扩散法中,当某个节点收到一个需要转发的数据包时,把数据包发送给除了数据包进入的连接以外的所有连接,这样也可以保证数据最终到达目的地,但是显然会在网络中产生大量的重复数据包。有两个办法可以抑制这种重复数据包,一种是使用TTL(time to live)值,数据包每经过一个节点,TTL值就减1,当TTL值减为0时就不再转发了。另一个办法是为每个数据包设置一个序列号,每个节点记录它已经扩散过那些数据包,当再次接收到相同的数据包时就丢弃它。
扩散法并不实用,但在一些特殊场合下(比如战争可能使大量路由器损坏)需要使用。由于扩散法总可以找到最短路径,所以还可以作为衡量其他路由算法的尺度。
(3)距离向量路由算法。前两种路由选择算法都是静态路由算法,距离向量算法和下面的链接状态算法是动态路由算法。距离向量算法是现在的网络中常用的一种路由选择算法。
距离向量算法中每个路由器维护一个路由表,用来记录到达每个目的节点的已知最短路径和经过的路径,相邻的节点之间会周期性地交换各自的路由表信息以便更新路由信息。
路由器向邻居节点发送ECHO消息,并在接收到回应时计算出与邻居节点的距离。每隔一段时间,路由器就向邻居节点发送自己的路由表,当一个路由器收到邻居节点的路由表后,根据表中记录的到达每个节点的延迟,结合它到邻居节点的延迟,来判断是否需要修改自己的路由表中到达每个节点的延迟,如果根据计算发现通过邻居节点到达某个节点会更快,就更新自己的路由表中相应的项。
(4)链接状态路由算法。距离向量算法在选择最佳路径时只考虑延迟而没有考虑通信带宽的差异,在高带宽的通信线路上常用的路由选择算法是链接状态算法。
链接状态算法的大致步骤如下:
① 发现邻居并获取其网络地址;
② 测量到达每个邻居节点的代价;
③ 把所有需要交换的信息组成链接状态包;
④ 将链接状态包发送到所有其他路由器。
当路由器收到所有的链接状态包后就可以计算出完整的通信子网图,进而在本地运行Dijkstra算法得到最短路径。
3.4.4 传输层
TCP/IP协议栈中传输层位于网络层上面,主要为网络上的对等实体提供会话功能,包括面向连接的TCP和无连接的用户数据包协议(user datagram protocol, UDP)两种协议。下面介绍几个传输层需要用到的术语。
端口(port):是一个软件数据结构,一个端口对应一个16bits的数字(0—65535),被客户程序或服务进程用来发送和接收信息。例如,SMTP使用25端口,HTTP使用80端口。Telnet使用23端口等。为使传输层的数据让目的主机接收,除使用IP地址表明目的主机之外,还需要使用约定好的端口号才能通信。
套接字(socket):套接字由三个部分产生,主机IP地址、服务类型(TCP、UDP)和端口号。套接字进程间通信的接口,也可以看作支持多种网络操作形式的接口。
TCP建立起两个主机之间的可靠传输信道,使得可以从源主机发出的字节流无差错地到达目的主机。TCP还要进行流量控制,避免发送过快地把数据包发送到速度较低的接收方导致接收方无法处理。
1.TCP协议
表3-4是TCP数据帧的结构。
表3-4 TCP数据帧的结构

其中,序列号用来表示该数据段在整个数据块中的位置;应答号表示数据已经被接收;代码表示某些特殊条件,例如请求一个连接或者结束一个连接;滑动窗口尺寸表示接收节点可接收的数据块的数量;校验和用于判断数据帧在传输过程中是否遭到破坏;紧急段指针表示紧急数据在数据块中的位置;可选项表示一些特殊选项;数据包含源节点发送的原始数据。其中在数据域中还存在一个填充位,用来保证TCP包头的长度是32位的整数倍。
TCP传输必须先建立TCP连接,数据传输分段进行。TCP协议为每个数据字段指定一个序列号,以便接收方按照数据字段的顺序获得可靠的数据。根据序列号接收主机会知道是否所有数据字段都已收到并发送应答;如果发送方在一个预定的时间段内未收到确认,则重发数据;如果收到的数据被损坏,接收主机丢弃该数据,不发送确认信息,因此发送方会重新发送分段。
2.UDP协议
UDP是一个不可靠的(尽力而为的,best-effort)数据传输协议,用于不需要TCP排序和流量控制能力的场合,例如流媒体的传输等。
UDP协议不能保证数据帧以正确的顺序被接收,也不提供任何错误帧校验及数据帧的序列,但在需要实时高速传输而并不在意少量的传输错误时(例如电视的实况转播), UDP协议不需要像TCP协议那样添加许多额外的信息保证完全的正确性,这样就提高了数据处理速度,满足实时传输的要求。因此UDP包头只有4个域:源端口、目标端口、包头的长度和校验和。
具体来说,UDP主要用于“查询-应答”式的服务,例如NFS、NTP(网络时间协议)和DNS (DNS也使用TCP)。表3-5是一些常用的UDP端口及其服务。
表3-5 UDP端口及服务

3.4.5 应用层
应用层处于TCP/IP模型的最上层,包含所有高层协议,例如虚拟终端协议Telnet、文件传输协议(file transfer protocol, FTP)、电子邮件传输协议(simple message transfer protocol, SMTP)、域名系统服务(domain name service, DNS)、网络新闻传输协议NNTP和(hypertext transfer protocol, HTTP)协议等。
(1)Telnet:允许用户登录到远程机器上并且获得一个shell进程。
(2)FTP:提供有效的远程文件传输服务。
(3)SMTP:起初仅仅是一种文件传输,后来为它提出了专门的协议。
(4)DNS:把主机名映射到网络地址。
(5)HTTP:在Web上获取网页等。
这部分内容不属于本书的范围,关于这些协议的具体内容请参考相关专著,这里不再详述。