我们在前面讨论 OSI 和 TCP/IP 分层协定概念的时候﹐已经指出﹕不管协定设计者如何定义层级﹐各层级协定大致分成两类﹕网路群组﹑和使用者群组。前面介绍的 ARP ﹑IP﹑RIP 等协定﹐可以算是网路群组的范围﹐假如您对前述概念都有一定认识﹐已经知道了一个封包如何从一个节点传递到另一个节点。然而﹐这仅是 TCP/IP 协定的一半而已﹐要完全了解 TCP/IP 的精髓﹐在 IP 协定的更上一个层级﹐属于使用者群组协定之一﹕TCP 协定﹐是不可不知道的。只有当我们同时把 IP 协定和 TCP 协定理解进来﹐才能完整的描述电脑与电脑之间的资料传送过程﹔也只有如此﹐我们才有把握进行日常的 TCP/IP 网路管理。TCP 与 IP 这对孪生兄弟﹐是每一个网路管理人员必须混熟的朋友。下面﹐我们将一起探讨在 TCP/IP 协定中举足轻重的传送层﹐是如何影响我们日常的网路资料传输的。
传送层的功能
在前面讨论网际网路层的时候﹐我们知道﹕网际网路层协定只提供路由资讯的判断﹐以确定封包的传送路径。但事实上 IP 协定只确保封包交换设备之间的传输﹐并没有提供一套机制来确保数据的传输。在低层的通讯里﹐封包可能在传送过程中发生错误﹐诸如网路硬体的损坏﹑网路负荷过重等等﹐导致封包被丢弃或损坏。由于封包路由的多样性和复杂性﹐以及影响路由因素众多及其不可预测性﹐封包之抵达常是不依序的﹐或是会发生重复传送的情形。因此﹐我们必须提供一套网路技术﹐以达成更可靠和有效的传送。
再者﹐ IP 封包的体积是有限的﹐然而﹐网路程式之间交换的数据往往会超过这个体积限制﹔那么﹐我们必须有另一套机制将程式送来的资料进行规划﹐以符合 IP 封包的传送要求。在高层的程式里﹐除非利用非可靠和非连线型(connectionless)的资料传送方式﹐否则,程式设计者必须对每一个一个应用程式处理侦错和修复的动作﹐这无疑增加了程式设计和修改的难度﹐而且也做成许多重复的处理动作。因此﹐我们也有必要找出一个可靠的资料流传送方法﹐以建立单独且适用于所有应用程式的资料传送协定。这样就可以将应用程式与网路内部协定隔离﹐同时提供一致的资料流传送界面。
传送层的设计可以说是应上述要求而生的﹐它的主要功能有﹕
· 接管由上层协定传来的资料﹐并以 IP 封包可以接受的格式进行“封装”工作。
· 进行资料传送和回应的确认﹐以及处理资料流的检测和控制。
· 对不同的连线进行追踪及转换。
在 TCP/IP 协定组中,关于传送层的协定就是 TCP 和 UDP 了﹐我们将在下面详细讨论。简而言之﹐TCP 提供的是一个可靠的资料流传送服务﹔相对而言﹐UDP 提供的是一个非可靠的非连线型(connectionless)的资料流传送服务。
可靠性传送服务的特性
在应用程式对 TCP 的可靠性传送服务之主要要求有五个﹕
· 资料流导向。处理程式之间的大量资料传送﹐确保双方的位元资料流之统一性。
· 虚拟电路连接。建立和回应资料流传送的连线请求﹐并验证传送期间的资料﹐同时对通讯进行侦错。
· 缓冲处理。如果程式送出的资料太小﹐协定将等到收集到一定大小的资料包之后才进行传送﹐然而协定允许“push”机制强行送出。
· 非结构化资料流。应用程式在建立连线之前﹐要先了解资料流动内容与格式﹐方能使用资料流服务。
· 全双工连线。允许双向性的资料传送﹐各自被视为互不相关的独立资料流。然而﹐它提供了返回资料流中携带传送控制资讯的机制。
TCP 协定在进行传输的时侯,必须依靠 IP 协定传送封包。相对于 TCP , IP 协定属于不可靠协定﹐因为两个协定必需同时困绑工作,因此只要其一能做到可靠传输就可以了。要详细的描述 TCP 如何提供可靠性传送是非常复杂的﹐但大部分可靠性协定都采用一定的确认机制来保证传送之可靠性。这种技术需要接收端以确认信息(Acknowledgement) 回应发送端﹐肯定资料无误的到达﹐同时双方保留传送的封包记录﹐以作下一笔资料的确认依据。此外﹐还利用定时器的机制﹐以在传送逾时后重新发送封包,以确保资料的完整性。我们可以从下图中看到确认机制的简单模式﹕
发送端在送出封包之后﹐会起始一个专门针对该封包的计时器﹐当下层网路延迟过久导致封包不能按预估时间获得接收端的确认信息﹐那么发送端会认为该封包可能在传送过程中丢失﹐然后会重新发送该封包、并同时重设计时器﹔如果封包的确认信息在逾时前被接收到﹐则取消该封包的计时器﹐以进行下一封包的传送。
计时器虽然解决了封包丢失的问题﹐但如果封包的抵达只是因为网路延迟的关系没有在预定时间完成﹐但却在发送端重发后抵达﹐那么﹐接收端就有可能接收到重复的封包。为解决这个困绕﹐传送协定会为每一个封包分配一个序号﹐并要求接收端按封包序号传回确认信息。这样﹐当接收端收到封包的时候﹐则可以依据序号判断封包是否被重复传送,同时也能正确的重组资料顺序﹔而发送端也能根据确认封包的序号来判断封包是否被正确接收。
滑动视窗(Sliding Window)
从刚才介绍的可靠性传送知识作一个推断:假如每一个单一封包都需要需要等待前面的封包确认之后才进行传送的话﹐将会导致整个连线过程时间的增加﹐同时也会造成频宽的浪费。假如在低速的网路上面﹐或设备延迟﹐甚至还会造成网路处于空闲状态。有鉴于此﹐聪明的传送层协定设计者们引入了一个滑动视窗的概念。
我们可以将滑动视窗理解为多重发送和多重确认的技术。它允许发送端在接收到确认信息之前同时传送多个封包﹐因而能够更充份的利用网路频宽和加速资料传送速度。滑动视窗的操作可以想象为下图﹕
我们利用 Sliding Window 在收发两端各划分出一个缓冲范围(buffer)﹐定义了多大的资料量可被打包传送。在连线建立起来之初﹐两端都会将 window 的设定值还原到初始值﹐比方说﹕ 3 个封包。发送端一次过发送三个封包出去﹐如果接收端够顺利﹐也能一次处理接收下来的三个封包的话﹐就会向发送端确认全部三个封包,并告知接收端之 window 值为 3 。然后,发送端视窗则会往后移动三个封包﹐填补发送出去之封包的空缺。但如果接收端太忙﹐或是其它因素影响﹐暂时只能处理两个封包﹐那么﹐在视窗里面就剩下一个封包﹐然后就会告诉发送端 window 值为 2。这个时候﹐发送端就只送出两个封包﹐而视窗就会往后移动两个封包﹐填补发送出去的空缺。因此,视窗的大小是不固定的,这就是为什么我们会在视窗前面加上“滑动”字眼的原因了。(注意:这里使用封包数目作 window size 是不正确的,仅作例子参考而已。实际上的单位应是位元组,视不同的作业系统而各有不同,一般为 4096 bytes,但也有扩展至 16384 bytes 的。而且视窗的 size 是每个确认封包都不同的,端视当前的缓冲区状况,其机制比前述复杂许多。)