TCP是在不可靠的网络层上提供可靠的传输服务。如何理解?假设你拥有一个快递公司,但是快递小哥不是很靠谱,
送货偶尔会出问题,所以你经常收到投诉电话,处理一些复杂的问题。比如有些快递压舱了,有些丢失了,有些损坏了等等。为了解决这个问题,你雇佣了一个经理人,全权负责这些琐事。这个经理就相当于TCP的功能。而快递小哥就是不靠谱的网络层。网络层的不可靠是指数据不一定会在规定的时间内按照规定的顺序到达。比如快递丢了,这就是直接没送到,或者快递在中间某一个站点滞留了很久很久,最终可能会送到,但是很不幸你包裹是水果,送到都烂掉了。而我们通常所说的TCP是可靠的,指的是TCP通过了一些手段,使得传输看起来可靠。这个与
视觉暂留的效果类似,都是对上层提供的一种假象。那么哪些手段可以用来保证可靠?

重传

重传是TCP保证可靠的唯一方式。这个道理没法在解释了。一个数据在网络中丢了也好,蒸发了也好,想要对面收到,恐怕除了重新发一个一模一样的数据没有其他的方法。但这里的问题是,发送方在什么情况下重传。

我们把问题简化,假设现在没有TCP(假设现在是1975年),网络中只有发送方A和接收方B,A和B一生只通信一次,一次只发送一个数据包,只能A发送数据,B接收数据,在一个不可靠的信道上,A如何确定B收到了数据?

应答

应答(ACK)是判断是否重传的指标。现在我们允许B发送数据,不过只能发送ACK。当发送方收到ACK则认为数据可靠抵达,在一段时间内没有收到就可以重新发送。这样,拥有了重传和应答两项技能,我们就保证了通信双方在只发送一个数据包的情况下的可靠通信。强调一下,这里的可靠是指,只要收到了ACK则数据一定被B收到,但是并不保证一定会收到ACK,而且没有收到ACK数据也未必没有到达。说以A收到ACK是B收到数据包的充分条件,而不是必要条件。

我们现在再提一些需求。假设现在没有TCP(假设现在是1975年),网络中只有发送方A和接收方B,A和B一生只通信一次,一次发送多个数据包,只能A发送数据,B接收数据(可发送ACK),在一个不可靠的信道上,A如何确定B收到了所有的数据?假设B知道A到底发送了几个数据包,那么B可以在收到所有数据包后给一个ACK。但是,实际情况是B并不能知道A到底发送了几个数据包,所以只能收到一个确认一个。如此一来,A即使收到了ACK,也不知道到底B确认的是哪个数据包。

序号

如果能使得ACK能标明确认的到底是哪个数据包,那问题看 大专栏  TCP与三次握手起来就解决了。所以我们就在A发送数据包时给数据包一个编号。这样A发送了n个数据包,就等着接收n个对应ACK。而B也不需要知道A到底发送了多少数据包,只需要确认当前收到的数据包就可以。我们暂定这个标号从0开始。

我们现在再提一些需求。假设现在没有TCP(假设现在是1975年),网络中只有发送方A和接收方B,A和B可以通信多次,一次发送多个数据包,只能A发送数据,B接收数据(可发送ACK),在一个不可靠的信道上,A如何确定B收到了所有的数据?在拥有重传,应答,序号等功能后,我们实现了在不可靠信道上单方向通信一次多包的可靠传输。在通信多次的情况下,多次通信的数据包的确认信息会出现相互干扰,在某一时刻信道中可能存在多个编号为x的包。即使我们在一次通信结束之后再开始第二次通信,由于网络的堵塞和发送方的重传机制,在某一时刻信道中可能还是会有若干编号相同的包。

kh
However, there is a practicalsnag for using it for establishing connections. Since we do not normally remember sequence numbers across connections at the destination, we still have no way of knowing if a CONNECTION REQUEST segment containing an initial sequence number is a duplicate of a recent connection.

-->

我们假设包的编号可以无穷大。如果每次通信能使用不同的编号区间,貌似就解决了这个问题。要做到这样,在每次通信过程真正开始之前,发送方与接收方需要协商一个起始编号。

二次握手-四次握手-三次握手

协商编号的过程,就是让接收方B知晓发送方A发送的数据包的起始标号。所以还是一个数据包的可靠传输问题,我们之前已经解释过,拥有重传,应答两项技能就可以保证一个包传输的可靠性。所以这个协商过程就是指的双方一问一答(看上去是一问一答,实际上由于信道的不可靠,可能尝试多次才完成一问一答),也可以称为二次握手。

我们之前一直假设只有A向B发送数据,B只能响应ACK。如果双方都可以向对方发送数据,那么不仅A要让B知道自己的起始编号,B也要让A知道自己的起始编号。于是需要四次握手。在这个过程中,B的应答和请求可以合并到一起,于是变成了三次握手。

结论

TCP保证可靠的方式是重传。三次握手建立可靠链接的说法其实是不恰当的。在实际情况中,数据包的编号不可能无穷大,也会出现重复的问题,不过这又是另外一个单独的问题,RFC1323中定义的PAWS对这个问题有更详细的描述,感兴趣的可以参考。

TCP与三次握手的更多相关文章

  1. 简析TCP的三次握手与四次分手

    TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续.它只是一个超级麻烦的协议,而它又是互联网的基础,也 ...

  2. TCP的三次握手(建立连接)和四次挥手(关闭连接)

    参照: http://course.ccniit.com/CSTD/Linux/reference/files/018.PDF http://hi.baidu.com/raycomer/item/94 ...

  3. TCP协议三次握手和四次挥手

    http://www.cnblogs.com/rootq/articles/1377355.html TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对 ...

  4. HTTP协议中TCP的三次握手,四次挥手总结

    建立TCP需要三次握手才能建立,而断开连接则需要四次挥手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资 ...

  5. TCP协议三次握手

    TCP协议三次握手过程分析 TCP(Transmission Control Protocol) 传输控制协议 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: ...

  6. 简析TCP的三次握手与四次挥手

    TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续.它只是一个超级麻烦的协议,而它又是互联网的基础,也 ...

  7. 简析TCP的三次握手与四次分手【转】

    转自 简析TCP的三次握手与四次分手 | 果冻想http://www.jellythink.com/archives/705 TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文 ...

  8. 【转载】简析TCP的三次握手与四次分手

    最近在补习HTTP协议相关知识点,看到这篇讲得不错,所以转载收藏一下,同时也分享给大家.原文地址:http://www.jellythink.com/archives/705,版权归原作者所有. TC ...

  9. TCP协议—三次握手四次挥手的原理<转>

    三次握手四次挥手的原理   TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接.在TCP/IP协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的.三 ...

  10. TCP的三次握手与四次挥手

    TCP的三次握手与四次挥手 一.TCP(Transmission Control Protocol 传输控制协议) TCP是面向对连接,可靠的进程到进程通信的协议 TCP是提供全双工服务,即数据可在同 ...

随机推荐

  1. PANIC: ANDROID_SDK_HOME is defined but could not find Nexus_5_API_23.ini file in $ANDROID_SDK_HOME\

    运行模拟器总是出现这个错误 后来把系统环境变量中的ANDROID_SDK_HOME 删掉就好了 我去,好神奇的操作

  2. crf多表与基表系列化-自定义序列化深度表查询-断关联表关系-多表反序列化

    学习表关系的序列化和反序列表查询之前,新建项目的准备工作及环境搭建的配置. 配置:settings.py INSTALLED_APPS = [ # ... 'rest_framework', ] DA ...

  3. vue路由的跳转-路由传参-cookies插件-axios插件-跨域问题-element-ui插件

    ---恢复内容开始--- 项目初始化 创建一个纯净的vue环境项目,手动书写全局的样式配置,全局的main,js配置 (1)如果vue项目在重构或者出错的时候,手动安装node_modules. 如果 ...

  4. Opencv笔记(二十一)——傅里叶变换

    参考 Numpy 中的傅里叶变换 首先我们看看如何使用 Numpy 进行傅里叶变换.Numpy 中的 FFT 包可以帮助我们实现快速傅里叶变换.函数 np.fft.fft2() 可以对信号进行频率转换 ...

  5. The website is API(4)

    1.淘宝商品信息定向爬虫 目标:获取淘宝搜索页面信息,提取其中的商品名称和价格 理解:淘宝的搜索接口 翻页的处理 技术路线:requests+re https://s.taobao.com/searc ...

  6. 系统学习Javaweb7----JavaScript3

    学习内容: 1.JavaScript语法规则----全局函数 2.JavaScript语法规则----自定义函数 3.BOM对象 3.1BOM对象--消息框 3.2BOM对象--循环定时器 3.3BO ...

  7. mysql按表字段内容长度排序

    今天遇到个需求如下: 查询一下新的业务是否正常入库,遇到的问题是新旧业务用的是同一个字段标识,唯一不同的是字段里内容的长度不同 查询方式如下,mysql按表字段内容长度排序 SELECT * FROM ...

  8. python学习笔记(17)urllib.parse模块使用

    url.parse :定义了url的标准接口,实现url的各种抽取 parse模块的使用:url的解析,合并,编码,解码 使用时需导入 from urllib import parse urlpars ...

  9. LeetCode No.73,74,75

    No.73 SetZeroes 矩阵置零 题目 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0.请使用原地算法. 示例 输入: [   [1,1,1],   [ ...

  10. OpenCV 使用FLANN进行特征点匹配

    #include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #inclu ...