- 为什么TCP是可靠传输,UDP不可靠?
- 简单的说,TCP是面向连接的协议,而且建立连接时三次握手;UDP不关心数据是否传输正确,不面向连接的协议
- 为什么面向连接就可靠呢? 搞清楚“连接”的意义
- 当提到连接,我们本能的会把它想成一根水管或者绳子,建立连接就是把这个水管或者绳子接起来。在通信的时候,我们会把连接想象成一个独立的通道,建立连接后所有的数据都顺着这个通道传输出去,对方就能收到有序完整的数据。但是实际上,因为各种各样的问题(硬件故障、网络阻塞、攻击等)的存在,网络传输通道本身就不可靠。所以,TCP里的所谓连接不是一个通道,它只是通信双方建立的一个一对一的逻辑关系,让双方都明确对方是自己的通信目标。
- 既然双方只存在逻辑约定,数据仍然可能在传输过程中会出现错误、丢失等各种状况。那建立连接的意义是什么呢?
- 就是为了保证数据传输的 完整 和 正确
- TCP建立连接是三次握手过程:
- 连接开始时,连接建立方(Client)发送SYN包,并包含了自己的初始序号a;
- 连接接受方(Server)收到SYN包以后会回复一个SYN包,其中包含了对上一个a包的回应信息ACK,回应的序号为下一个希望收到包的序号,即a+1,然后还包含了自己的初始序号b;
- 连接建立方(Client)收到回应的SYN包以后,回复一个ACK包做响应,其中包含了下一个希望收到包的序号即b+1。
- TCP终止连接是四次握手过程:
- 首先进行关闭的一方(即发送第一个FIN)将执行主动关闭,而另一方(收到这个FIN)执行被动关闭。
- 当服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
- 同时TCP服务器还向应用程序(即丢弃服务器)传送一个文件结束符。接着这个服务器程序就关闭它的连接,导致它的TCP端发送一个FIN。
- 客户必须发回一个确认,并将确认序号设置为收到序号加1。
- 三次握手和四次握手中的ACK机制:
- 由于通信过程的不可靠性,传输的数据不可避免的会出现丢失、延迟、错误、重复等各种状况,TCP协议为解决这些问题设计了一系列机制。ACK机制的核心,就是发送方向接收方发送数据后,接收方要向发送方发送ACK(回执)。如果发送方没接收到正确的ACK,就会重新发送数据直到接收到ACK为止。比如:发送方发送的数据序号是seq,那么接收方会发送seq + 1作为ACK,这样发送方就知道接下来要发送序号为seq + 1的数据给接收方了。
- 在不同的异常情况下,ACK机制是怎么工作的:
- 数据丢失或延迟。发送方发送数据seq时会起一个定时器,如果在指定时间内没有接收到ACK seq + 1,就把数据seq再发一次。
- 数据乱序。接收方上一个收到的正确数据是seq + 4,它返回seq + 5作为ACK。这时候它收到了seq + 7,因为顺序错了,所以接收方会再次返回seq + 5给发送方。
- 数据错误。每一个TCP数据都会带着数据的校验和。接收方收到数据seq + 3以后会先对校验和进行验证。如果结果不对,则发送ACK seq + 3,让发送方重新发送数据。
- 数据重复。接收方直接丢弃重复的数据即可ACK的优化
- 按照ACK机制,只要整个数据传输顺利结束,接收方就能收到完整有序的数据了。但是,如果我们针对每一个数据包都发送ACK,就会有大量的网络资源消耗在ACK的发送上,这不太划算的。于是,TCP设计了延迟ACK的机制。这个机制其实很简单。客户端一次给服务器发送多个数据包,当服务器收到客户端的数据包时,不马上发送ACK,而是稍微等一小段时间。在这个过程中服务器可能能收到后续几个数据包,服务器就可以直接按照最后一个正确的数据发送ACK,减少发送ACK的总数。
- 为什么偏偏是三次连接?知乎有答案:https://www.zhihu.com/question/24853633
- 既要保证数据可靠传输,又要提高传输的效率,而用三次恰恰可以满足以上两方面的需求!
- 总结一下,是一种权衡的结果
- TCP连接到底是什么? https://blog.csdn.net/zdavb/article/details/47790229
- 先给结论,什么是TCP连接?连接实际上是操作系统内核的一种数据结构,称为TCP控制块(TCB),对于linux而言是tcp_sock结构。不光连接,连数据包也是由一个数据结构来控制,linux里面称为sk_buff结构。