当我们说"TCP是可靠协议"时,我们真正表达的是什么

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                     

很明确地说,从通信意义上推敲,TCP一点都不可靠。一个抽象的协议,怎么可能左右介质来保证可靠,不存在的。但凡是经由某种介质的通信行为均不可能是绝对可靠的!

正好比我们现实生活中的保险,其实它什么都不能阻止,什么风险也保证不了它的不发生,它保证不了飞机不会掉下来,也无法阻止人生病…事实上,TCP就是通信中的保险业。

TCP是如何设计出来的?推而广之这类通信协议是如何设计出来的?如果说让你在一个不可靠的介质上运行一个可靠的协议,你该怎么做?本文将介绍内中的些许因果。

可靠的通信协议如何构建

这要从经典的两军问题说起。

首先介绍一下两军问题,来自Wiki的解说是最好的:
Two Generals’ Problemhttps://en.wikipedia.org/wiki/Two_Generals%27_Problem
两军问题本质上一个一致性确认问题,也就是说通信双方而不是一方(这对理解TCP非常重要)都要确保信息的一致性。即假设通信双方为A和B,那么A发送一则消息M给B,所谓的可靠性则是要同时满足下面的条件:

  • 信道是不可靠的,任何消息均可能以任何概率丢失
  • 如果A A重新这么来一遍即可!于是我们观察到,两军问题如果超时重传的前提下将双向的消息传递和确认分解成两个单向的消息传递和确认,事情就会简单得多。

    原始的两军问题解法:
    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    转换后的解法:
    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    嗯,转换后的解法,即我们熟悉的协议,TCP协议的最基本形式。现在进入TCP时间!


    TCP握手,挥手,一致性的问题

    经常有人问,TCP为什么是3次握手,而不是2次,也不是4次,5次。知乎上经常会有这种问题,但是答案几乎是千篇一律的错误或者答非所问,最常见的答案只是描述一下TCP握手的细节,然后导出这么做是OK的,其实不这么做也是OK的这一点没人提。

    最常见的错误答案:
    1. 这是一种权衡,因为无数次握手也不可能完全可靠;
    2. 描述握手的协议细节;
    3. …

    看过了我上面的论述,这个问题应该非常好答了,所谓的TCP建立连接的握手,实质上就是建立一个双向的可靠通信连接,一边一个来回,每一边都自带超时重传来确保可靠性(而不是靠握手的次数)。TCP的3次握手是优化的结果,其实它应该是4次握手,由于是从零开始的建立连接,因此将SYN的ACK以及被动打开的SYN合并成了一个SYN-ACK,仅此而已。

    握手的作用,旨在确定两个双向的初始***,TCP用***来编址传输的字节,由于是两个方向的连接,所以需要两个***,握手过程不传输任何字节,仅仅确定初始***
    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    说完了3次握手,那么,其姊妹问题,为什么TCP的断链是4次挥手而不是3次?

    换句话说,即是在问为什么针对主动断开方的FIN的ACK以及本端的FIN不能合并?

    非常简单,因为TCP是在一个单向可靠通信系统基础上构建而成的双向传输控制协议,握手期间可以合并ACK和SYN,是因为在握手之前两端没有任何连接上的包袱,而在断链挥手时,一端认为可以断开了,另一端却不一定,可能另一端还有数据要传输,所以便不能合并,被动关闭的一方只能单独处理针对FIN的ACK以及自己的FIN,仅此而已。

    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    再来一个问题,TCP能确保一致性吗?换句话说,TCP协议是两军问题的一个解吗?

    远远不是!TCP并不确保一致性。

    任何时间点,TCP都不能完全确认当前时刻连接双方的状态,此处所谓的状态包括两端传输的数据。一致性是基于消息的,而不是基于连接的!也就是说,TCP只有收到下一个数据包时,才知道上一个数据包的接收情况,而无法实现隔空打人!TCP的好处仅在于,它在一个信息流上实现了一个一致性确认的流水线方式

    我们在理解这个流水线方式的时候,不应该考虑滑动窗口,那样会比较难以理解,我们应该仅仅考虑单字节停等机制。事实上也确实是这样,滑动窗口机制只是为流量控制而引入的,单字节停等效率又太低,所以说这并无伤大雅,你把字节换成窗口即可,即单窗口停等。

    如果我们把一致性推广到连接的层面,在连接层面,一致性就是靠4次挥手保证的。

    我们可以看到,4次挥手那里的状态机非常之复杂,这是有原因的,即便是引入了TIMEWAIT状态,也还是没有办法保证彻底的一致性,这是两军问题本质上不可解的一个结论,仅此而已。


    1974年的TCP

    现在你应该大致知道TCP如何保证可靠性了,进一步,如果你想知道TCP协议的头部为什么是那个样子,这一切是如何安排的,你就不得不去读一下一篇陈年的论文:
    《A Protocol for Packet Network Intercommunication》https://www.cs.princeton.edu/courses/archive/fall08/cos561/papers/cerf74.pdf
    我来大致介绍一下这篇划时代的论文。

    毫不夸张地说,该论文奠定了以TCP/IP为核心的互联网的基础,我们今天能刷抖音,用微信聊天,能在线看片…这一切要不是这篇论文,不会是现在这个样子。

    该论文的重点不是TCP协议,而是TCP/IP作为一个整体如何发挥作用,早在1974年,分层模型还不算太成熟,所以当我们提起TCP/IP的时候,要明白,最初的时候,这两个协议是牢牢切合在一起的,到了后来为了兼容纯IP转发,才加入了UDP,这个时候,人们意识到分层模型的必要性。于是抽象而成的ISO/OSI模型。

    该论文主要有两个论题:

    • 网关的概念和意义–最终的IP协议
    • 进程间通信的传输控制–最终的TCP协议

    注意,我们看看TCP最初的形式,没错,它是作为一种进程间通信的手段被提出的,当初TCP作为进程间通信手段,侧重于不同主机的进程间通信,因此,我们可以清晰看到它的API和文件IO的API是多么相似,这也是socket可以作为文件描述符的原因。

    此外,还有值得注意的是,TCP的ACK号被定义为下一个索要字节的***,这在当时实现了一种简易且完备的字节流水线,节省了协议头空间,看到这个设计,简直太帅!虽然它也带来了很多问题,比如无法精确测准RTT,比如无法进行选择确认,进而无法进行良好的拥塞控制,但不得不说,在空间重于时间的1970年代,这绝对是创举,毕竟,拥塞控制在当时是没有意义的,1988年才被引入。


    1974年的互联网

    在1974年那篇论文之后,同样的作者归纳总结出了RFC675:
    《RFC675:SPECIFICATION OF INTERNET TRANSMISSION CONTROL PROGRAM》https://tools.ietf.org/html/rfc675
    这篇划时代的RFC正式提出了互联网这个概念,我们常说的Internet就是Internetworking的缩写。

    TCP/IP协议确实不是一个协议栈,最初它们只是一个协议,仅此而已,不多说。


    那么,接下来?

    接下来,skinshoe wu来了,携带着他的高级皮鞋,还有高级西装。

               

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

当我们说"TCP是可靠协议"时,我们真正表达的是什么
                     

很明确地说,从通信意义上推敲,TCP一点都不可靠。一个抽象的协议,怎么可能左右介质来保证可靠,不存在的。但凡是经由某种介质的通信行为均不可能是绝对可靠的!

正好比我们现实生活中的保险,其实它什么都不能阻止,什么风险也保证不了它的不发生,它保证不了飞机不会掉下来,也无法阻止人生病…事实上,TCP就是通信中的保险业。

TCP是如何设计出来的?推而广之这类通信协议是如何设计出来的?如果说让你在一个不可靠的介质上运行一个可靠的协议,你该怎么做?本文将介绍内中的些许因果。

可靠的通信协议如何构建

这要从经典的两军问题说起。

首先介绍一下两军问题,来自Wiki的解说是最好的:
Two Generals’ Problemhttps://en.wikipedia.org/wiki/Two_Generals%27_Problem
两军问题本质上一个一致性确认问题,也就是说通信双方而不是一方(这对理解TCP非常重要)都要确保信息的一致性。即假设通信双方为A和B,那么A发送一则消息M给B,所谓的可靠性则是要同时满足下面的条件:

  • 信道是不可靠的,任何消息均可能以任何概率丢失
  • 如果A A重新这么来一遍即可!于是我们观察到,两军问题如果超时重传的前提下将双向的消息传递和确认分解成两个单向的消息传递和确认,事情就会简单得多。

    原始的两军问题解法:
    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    转换后的解法:
    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    嗯,转换后的解法,即我们熟悉的协议,TCP协议的最基本形式。现在进入TCP时间!


    TCP握手,挥手,一致性的问题

    经常有人问,TCP为什么是3次握手,而不是2次,也不是4次,5次。知乎上经常会有这种问题,但是答案几乎是千篇一律的错误或者答非所问,最常见的答案只是描述一下TCP握手的细节,然后导出这么做是OK的,其实不这么做也是OK的这一点没人提。

    最常见的错误答案:
    1. 这是一种权衡,因为无数次握手也不可能完全可靠;
    2. 描述握手的协议细节;
    3. …

    看过了我上面的论述,这个问题应该非常好答了,所谓的TCP建立连接的握手,实质上就是建立一个双向的可靠通信连接,一边一个来回,每一边都自带超时重传来确保可靠性(而不是靠握手的次数)。TCP的3次握手是优化的结果,其实它应该是4次握手,由于是从零开始的建立连接,因此将SYN的ACK以及被动打开的SYN合并成了一个SYN-ACK,仅此而已。

    握手的作用,旨在确定两个双向的初始***,TCP用***来编址传输的字节,由于是两个方向的连接,所以需要两个***,握手过程不传输任何字节,仅仅确定初始***
    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    说完了3次握手,那么,其姊妹问题,为什么TCP的断链是4次挥手而不是3次?

    换句话说,即是在问为什么针对主动断开方的FIN的ACK以及本端的FIN不能合并?

    非常简单,因为TCP是在一个单向可靠通信系统基础上构建而成的双向传输控制协议,握手期间可以合并ACK和SYN,是因为在握手之前两端没有任何连接上的包袱,而在断链挥手时,一端认为可以断开了,另一端却不一定,可能另一端还有数据要传输,所以便不能合并,被动关闭的一方只能单独处理针对FIN的ACK以及自己的FIN,仅此而已。

    当我们说"TCP是可靠协议"时,我们真正表达的是什么

    再来一个问题,TCP能确保一致性吗?换句话说,TCP协议是两军问题的一个解吗?

    远远不是!TCP并不确保一致性。

    任何时间点,TCP都不能完全确认当前时刻连接双方的状态,此处所谓的状态包括两端传输的数据。一致性是基于消息的,而不是基于连接的!也就是说,TCP只有收到下一个数据包时,才知道上一个数据包的接收情况,而无法实现隔空打人!TCP的好处仅在于,它在一个信息流上实现了一个一致性确认的流水线方式

    我们在理解这个流水线方式的时候,不应该考虑滑动窗口,那样会比较难以理解,我们应该仅仅考虑单字节停等机制。事实上也确实是这样,滑动窗口机制只是为流量控制而引入的,单字节停等效率又太低,所以说这并无伤大雅,你把字节换成窗口即可,即单窗口停等。

    如果我们把一致性推广到连接的层面,在连接层面,一致性就是靠4次挥手保证的。

    我们可以看到,4次挥手那里的状态机非常之复杂,这是有原因的,即便是引入了TIMEWAIT状态,也还是没有办法保证彻底的一致性,这是两军问题本质上不可解的一个结论,仅此而已。


    1974年的TCP

    现在你应该大致知道TCP如何保证可靠性了,进一步,如果你想知道TCP协议的头部为什么是那个样子,这一切是如何安排的,你就不得不去读一下一篇陈年的论文:
    《A Protocol for Packet Network Intercommunication》https://www.cs.princeton.edu/courses/archive/fall08/cos561/papers/cerf74.pdf
    我来大致介绍一下这篇划时代的论文。

    毫不夸张地说,该论文奠定了以TCP/IP为核心的互联网的基础,我们今天能刷抖音,用微信聊天,能在线看片…这一切要不是这篇论文,不会是现在这个样子。

    该论文的重点不是TCP协议,而是TCP/IP作为一个整体如何发挥作用,早在1974年,分层模型还不算太成熟,所以当我们提起TCP/IP的时候,要明白,最初的时候,这两个协议是牢牢切合在一起的,到了后来为了兼容纯IP转发,才加入了UDP,这个时候,人们意识到分层模型的必要性。于是抽象而成的ISO/OSI模型。

    该论文主要有两个论题:

    • 网关的概念和意义–最终的IP协议
    • 进程间通信的传输控制–最终的TCP协议

    注意,我们看看TCP最初的形式,没错,它是作为一种进程间通信的手段被提出的,当初TCP作为进程间通信手段,侧重于不同主机的进程间通信,因此,我们可以清晰看到它的API和文件IO的API是多么相似,这也是socket可以作为文件描述符的原因。

    此外,还有值得注意的是,TCP的ACK号被定义为下一个索要字节的***,这在当时实现了一种简易且完备的字节流水线,节省了协议头空间,看到这个设计,简直太帅!虽然它也带来了很多问题,比如无法精确测准RTT,比如无法进行选择确认,进而无法进行良好的拥塞控制,但不得不说,在空间重于时间的1970年代,这绝对是创举,毕竟,拥塞控制在当时是没有意义的,1988年才被引入。


    1974年的互联网

    在1974年那篇论文之后,同样的作者归纳总结出了RFC675:
    《RFC675:SPECIFICATION OF INTERNET TRANSMISSION CONTROL PROGRAM》https://tools.ietf.org/html/rfc675
    这篇划时代的RFC正式提出了互联网这个概念,我们常说的Internet就是Internetworking的缩写。

    TCP/IP协议确实不是一个协议栈,最初它们只是一个协议,仅此而已,不多说。


    那么,接下来?

    接下来,skinshoe wu来了,携带着他的高级皮鞋,还有高级西装。