TCP是一个可靠的协议。有时人们会说:"TCP能够保证它所发送数据的可靠传输。"这种说法尽管很常见,但却非常不恰当。

首先,只要稍微想一下就会知道这不可能是对的。比如,假设在数据传输的过程中将一台主机从网络上断开,TCP这侧不管做出何种努力,都无法获取其余 的数据。网络确实会中断,主机确实会崩溃,用户确实会在TCP连接仍然活跃的时候关机。这些事件或其他类似的事件都使得TCP无法将它从应用程序收到的数 据传送出去。

但更重要的是,TCP"确保可靠传输"这种说法会对不够谨慎的网络程序员产生微妙的影响。当然,没人真的会相信TCP有某种魔法总是可以将数据安全 地传送到其目的地。但是,相信TCP能够保证可靠传输会让人觉得没必要进行防御性编程,也没必要考虑对故障模式的处理,还是那句话,毕竟TCP可以确保可 靠传输。

可靠性--是什么,不是什么

在考虑TCP中可能出现的各种故障模式之前,要弄清楚TCP的可靠性意味着什么。如果TCP不能保证将提交给它的所有数据都传送出去,它又能保证什 么呢?第一个问题是向谁保证?图2-41显示,数据流从应用程序A通过它所在主机的TCP/IP栈向下传输,经过几台中间路由器,通过应用程序B所在主机 的TCP/IP栈向上传输,最后抵达应用程序B。一个TCP段离开应用程序A所在主机的TCP层时,会被封装到一个IP数据报中,传送给其对等实体主机。 它所走的路由可能要经过很多路由器,但如图2-41所示,这些路由器都没有TCP层,它们只是转发了IP数据报。

 

实际上,有些"路由器"可能是拥有完整TCP/IP协议栈的通用计算机,但在这种情况下,它们的路由功能也不涉及TCP或应用层。

我们知道IP是个不可靠的协议,那就应该很清楚,在数据传输路径上,第一个可以讨论确保可靠传输问题的地方就是应用程序B所在主机的TCP层。当一 个段抵达应用程序B所在主机的TCP层时,唯一可以确定的就是这个段已经到达了,但它可能损坏了,可能是重复的数据,可能是错序的,或者是由于其他一些原 因无法接受的。注意,发送端TCP无法对这些抵达接收端TCP的段做出任何保证。

但接收端TCP要向发送端TCP确认,也就是说它ACK的数据以及在此数据之前到达的所有数据在TCP层都已经正确收到了,发送端TCP可以安全地 删除这些数据的副本了。这并不意味着已经将数据传送,或者总是可以将数据传送给应用程序。比如,接收端主机可能在刚刚对数据进行了ACK,但应用程序还没 有将其读走之前,就崩溃了。这个问题值得进一步讨论:TCP向发送端提供的唯一一个数据接收通知就是这个ACK。发送端应用程序无法从TCP自身判断对等 实体应用程序是否真的收到数据了。稍后我们会说明,这是应用程序编写者要弄清楚的一种TCP故障模式。

另一个可以讨论确保可靠传输问题的地方是应用程序B。我们知道,无法保证应用程序A发送的所有数据都会到达。TCP能够向应用程序B保证的是所有到达的数据都是按序且未受损的。

前面已经提到过一种TCP故障模式了:TCP已经ACK了的数据实际上可能不会抵达目的应用程序。这是相当罕见的事情,即使发生这种事情,影响也不会太严重。重要的是网络程序员要知道这种可能性的存在,要对这种或其他所有故障模式可能带来的不良后果有所预防。要避免这样一种看法:TCP会做好一切准备,我们不需要为应用程序协议的健壮性操心。

前面讨论的故障模式有很明确的解决方案。对应用程序来说,明确地知道对等实体收到了某个特定的报文是非常重要的,其对等实体就必须将收到报文的信息通知发送端。通常,这种确认信息都是隐式的。比如,如果客户端向服务器请求一些数据,服务器进行了响应,那么,这个响应就隐式地确认收到了原始请求。

一个更难解决的问题是如果服务器没有对收到的报文进行确认,客户端会怎么做?当然,这与特定的应用程序有很大的关系,很可能没有一个统一的解决方 案。但我们应该注意到,仅仅重发请求很可能无法解决问题:我们不想请求银行进行两次转账。数据库系统使用三阶段提交协议来处理这种类型的问 题,某些应用程序可能会使用类似的策略来确保操作"最多执行一次"。

TCP是一个端对端协议,也就是说它自己要在对等实体之间提供可靠的传输机制。但是,认识到"端点"位于对等的TCP层,而不是对等的应用程序中是非常重要的要求进行端到端确认的应用程序必须自身提供此项功能(比如WCF实现的WS-RM)

看看其他一些"常见的"故障模式。只要两个对等实体仍然连着,TCP就能保证将数据按序、无损坏地传送。只有连接中断时才会出现故障。什么类型的事件会造成这种中断呢?有三种情况可能引发这类问题:

(1) 永久或临时的网络中断;

(2) 对等的应用程序崩溃;

(3) 运行对等应用程序的主机崩溃。

我们会看到,在发送端应用程序中,这些事件会以不同的方式显现出来。

posted on 2011-07-03 22:55  一路转圈的雪人  阅读(9090)  评论(3编辑  收藏  举报