当前位置: 首页 > news >正文

关于TCP的可靠性

关于TCP的可靠性

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) 运行对等应用程序的主机崩溃。

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

相关文章:

  • 如何成长为技术合伙人?
  • 发现一个超酷的FireFox2.0插件,纪念一下
  • UPYUN 用到的技术
  • 祝贺三八节日 “IT女杰风云榜”专题
  • 如何快速成长
  • 我的新浪博客地址升级了
  • 服务器开发
  • 清朝最后一次科举试题 看看你能考中状元吗
  • 说说Linux线程的栈空间
  • linux中使用pthread_kill函数测试线程是否存活的例子
  • 在SharePoint中对文档库(列表)进行的一些操作
  • Linux下TCP keepalive心跳设置
  • 利用SQL存储过程创建交叉表
  • Program received signal SIGUSR1, User defined signal 1.解决方法
  • 在Linux中创建静态库.a和动态库.so
  • @angular/forms 源码解析之双向绑定
  • 30天自制操作系统-2
  • If…else
  • input实现文字超出省略号功能
  • javascript数组去重/查找/插入/删除
  • Java教程_软件开发基础
  • orm2 中文文档 3.1 模型属性
  • python大佬养成计划----difflib模块
  • Quartz初级教程
  • vue-cli3搭建项目
  • 大整数乘法-表格法
  • 解析带emoji和链接的聊天系统消息
  • 那些被忽略的 JavaScript 数组方法细节
  • 详解移动APP与web APP的区别
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​linux启动进程的方式
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (四)JPA - JQPL 实现增删改查
  • (一)kafka实战——kafka源码编译启动
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @RestControllerAdvice异常统一处理类失效原因
  • @Transaction注解失效的几种场景(附有示例代码)
  • [2021]Zookeeper getAcl命令未授权访问漏洞概述与解决
  • [Android Pro] Notification的使用
  • [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作
  • [BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务
  • [C/C++] C/C++中数字与字符串之间的转换
  • [C++] sqlite3_get_table 的使用
  • [CC-FNCS]Chef and Churu
  • [Electron] 将应用打包成供Ubuntu、Debian平台下安装的deb包
  • [Firefly-Linux] RK3568修改控制台DEBUG为普通串口UART