为什么要由TCP协议负责数据传输的可靠性?
Posted 车小胖谈网络
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么要由TCP协议负责数据传输的可靠性?相关的知识,希望对你有一定的参考价值。
如果TCP不负责数据传输的可靠性,让谁来负责呢?
这不是抬杠,真理是不怕辩论的,从某种角度来说,真理是越辩越明朗!
按照TCP/IP模型五层模型,从上层到下层一个个看过来,看谁最帅,最适合做数据传输的可靠性!
应用层
应用程序,直接和用户的数据打交道,做数据传输的可靠性毫无压力。不就是TCP那个套路吗?咱应用程序也学得会,不就是那个确认机制吗?
我方发数据,你方确认收到数据;你方发数据,我方确认收到数据!
多么朴素无华的道理!
还有如果丢包,超时重传。如果超时重传多次没有成功,Reset双方的通信会话。
还有,为了不把接收方的接收缓冲区(仓库)占满并溢出,需要对方实时通告对方仓库的剩余空间,这个就是“Window”。
如果每次发数据,对方能及时确认,那就越发越快,直到占满对方仓库为止。
如果发数据,对方不能及时确认,那就悠着点发,咱别给互联网添堵。
实现完以上代码,对照TCP代码一看,我去,这不就是TCP代码吗?
通过上文的讨论,得出第一个观点:
第一个观点:无论哪层来实现数据的可靠传输,实现代码和TCP代码应该是高度相似的!
假设这段伪TCP代码10K 行,有100K字节大小。如果用户开N个浏览器窗口,同时有N个伪TCP代码在运行,占用的内存空间是N*100 K字节。其它的应用程序,也还是要实现自己的伪TCP代码。
读者会说,直接把浏览器的伪TCP代码拿来用就好了吗?其它程序为什么还要从无到有实现伪TCP代码?
浏览器的伪TCP代码为何要给你用?哦,你也是Microsoft操作系统旗下的产品,Okay,拿去用吧,不谢!
当新的应用程序每运行一个实例,内存空间就会多一块100K字节的伪TCP代码。
如果这段“伪TCP代码”有什么bug需要修复,所有使用“伪TCP代码”应用程序都要修改,这是多么的悲惨的场景啊!一大批程序员撅着屁股在那儿狂改bug。。。
那些独立开发应用程序的小公司,和人家Microsoft又不认识,人家的伪TCP代码也不会给你用,那只有硬着头皮写自己的伪TCP代码。限于开发水平,一大群程序员花了三个月的时间写是写出来了,但是错误百出,需要经常修Bug。。。
统计表明,每100行代码平均会有1个bug出现,10000行代码里至少埋藏着100个Bug!
小公司的老总硬着头皮联系Microsoft技术支持,能否把贵司的伪TCP代码通过接口函数开放出来?
很快,Microsoft 将伪TCP代码,用接口函数开放了出来,包括但不限于:
CreateSocket()
Connect()
Send()
Receive()
Close()
Shutdown()
用户看不到这些函数的内部实现,但是只要在应用程序里使用这些接口函数,如同使用伪TCP代码。
为了最大限度降低伪TCP代码的数量,操作系统将伪TCP代码从浏览器里剥离,伪TCP代码被集成到操作系统内核,所有应用程序调用接口函数,就如同使用伪TCP代码本身!
这样,整个操作系统就有且仅有一个伪TCP代码在运行,即使有N多个程序在同时运行。
当前操作系统就是这么来实现的,TCP代码,可以供所有的应用程序共享使用,提高代码的重用,避免代码的无谓重复!
这段神奇的代码名字是“TCP代码”,用于完全实现TCP/IP协议栈的TCP协议!
第二个论点:TCP的存在,是为了避免相同的代码出现不同的地方,从而提高代码的使用效率!
网络层
一个IP报文从源主机到达目的主机的路径上,会经过N多个路由器。为了让IP层来实现可靠传输,需要和相邻的路由器建立可靠传输,问题是IP协议头也没有什么字段可以保证可靠传输的,比如如何建立连接?如何字节流编号?如何确认?这些还不是致命的!
好吧,还需要扩展IP头协议字段以实现可靠传输!等扩展完才发现,扩展出来的协议字段和TCP没有什么两样!
问题又来了,核心路由器一秒钟高达几千万、甚至上亿次IP报文的转发,这些完全依靠硬件转发。
一旦要IP层建立可靠连接,维护连接状态、以及处理IP报文,就不能依靠硬件了,硬件处理不了那么复杂的逻辑。而是需要软件(CPU)来实现,而软件压根完成不了一秒几千万次的转发!这样就会严重影响路由器的转发速率!
至于数据链路层,就更不提了,数据链路层越简单越好,数据的转发效率才会高!
通过以上论述,才发现操作系统选择TCP来实现可靠传输是多么天经地义!TCP是纯软件,可以处理复杂的逻辑判断。客户端电脑不会有太多进程在运行,所以即使纯软件运行,也不会有太大压力!
服务器端会有一些压力,每秒要处理几十万次、甚至千万次的连接,这可以通过服务器集群、CDN加速来实现流量负载的分摊!
当然,用户对自己实现数据传输的可靠性有足够的自信,完全可以在应用程序里实现可靠性传输代码,只需要调用基于UDP的Socket接口函数即可!
以上是关于为什么要由TCP协议负责数据传输的可靠性?的主要内容,如果未能解决你的问题,请参考以下文章