《传输层 - TCP》
一:概述
- 面向连接的,可靠的流协议。
- 提供可靠交付,无差错/不重复/无丢失/按需到达。
二:什么是面向连接?
- 是为了在客户端和服务端维持连接,而建立一定的数据结构来维护双方交互状态,用这样的数据保证了所谓的面向连接。
三:什么是流协议?
- 首先,TCP(传输层) 是建立在 IP(传输层) 基础上,IP只有一个包一个包的概念。
- 所以,TCP 在传输大数据的时候,会以MSS切割数据段,发送多个数据包(IP包)
- 所以,接收到的数据,看起来就像是 "流" 一样。
四: TCP 段最大消息长度 MSS(Maximum Segment Size)
- TCP 是流协议,在处理数据时,会将数据段以MSS为单位切分成多个数据包进行传输。
- UDP 是面向报文的,所以是一次性传输数据。(超过65535的数据包会在IP层进行分包)
- 工作原理
- 在建立连接时候,两端计算自己所能适应的MSS大小。
- 选择较小值作为 MSS。
五:TCP基础(数据结构)
-
六:TCP 是通过什么机制实现可靠传输的?
- TCP 通过确认应答ACK(Positive Acknowled-gement)实现可靠的数据传输。
- 如果有确认应答,说明数据已经成功到达对端。反之,则丢失的可能性很大。
七:TCP如何保证数据的顺序?
- 发送端,数据的每一个字节标明编号。(序列号)
- 接收端,根据首部的序列号和长度,将下一步应该接受的序列号返回。
- 这样,通过序列号和确认应答号,TCP 可以实现可靠传输及数据顺序。
八:TCP三次握手(建立连接)
-
九:为什么需要三次握手建立连接?
- 角度一
-《计算机网络》:防止已失效的连接请求又传送到服务器端,因而产生错误。
- 例如只有两次 A->B, B没响应(网路问题),A断开连接,(过一会)B收到了连接,认为是建立连接,所以建立了无效的连接。
- 角度二
- 为了实现可靠数据传输,TCP 协议的通信双方,必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。
- 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。
- 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认.
十:提升数据传输的速度-窗口控制
- TCP传输的问题
- TCP是根据确认应答来保证数据的正确传输。
- "一问一答" 的机制。大大影响的整体TCP的传输速率,
- 所以TCP采取类似 "批处理" 的方式,来提升整体发送数据。
- TCP 窗口控制
- 窗口大小即为无序应答即可发送的最大值。(类似批处理)
- 当客户端接收繁忙时,根据TCP首部改变窗口大小,降低传输速率。
- 核心
- 客户端不在纠结于单个报文的确认应答。
十一:窗口控制是快了,但是应答/报文丢失怎么办?
- 确认应答(ACK)丢失
- 应答丢失表明了服务端已经接受到了数据报文,但是客户端还没有收到此报文段的确认应答。
- 当确认应答丢失时候,TCP不会数据重发,可以通过下一个确认应答进行确认。
-
- 报文丢失
- 报文丢失表明服务端没有收到数据。
- TCP这时会进行3次的重复应答,超过3次后,既重新发送,也叫 高速重发机制。
-
十二:我怎么知道我一次发多少(拥塞控制)?
- 拥塞控制主要用于限制服务端的发送,在刚开始建立连接时候,不能直接一次发送大量数据,会导致网络的堵塞。
- 所以,TCP在发送过程中,采用慢启动,既 发送比较少的数据(窗口少),逐渐加大传输速率。(窗口变大后稳定)
- 核心
- 服务端可以控制传输速率,避免堵塞网络。
十三:TCP 的其他优化
- Nagle 算法
- 如果发送端还有数据,但是数据量很小的话,会延迟发送。(提高网络使用率)
十四:TCP四次挥手(断开连接)
-
十五:为什么断开连接需要四次挥手?
- 在建立连接时候
- 当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。
- 因为之前压根没通信过,所以没有历史包袱。
- 但是关闭连接时
- 当Server端收到FIN报文时,很可能并不会立即关闭SOCKET。因为他可能还有未发送的数据。
- 所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。
- 最终只有等到Server端所有的报文都发送完了,才能发送FIN报文。
- 因为(SYN+ACK)不能一起发送。故需要四步挥手。
十六: 四次挥手为什么最后要等待 2MSL?
- MSL(Maximum Segment Life) 最大报文生存时间
- 这是TCP 对TCP Segment 生存时间的限制(参考默认60s)
- 根本原因
- 最后一次的ACK的确认应答,只有一方会收到,而发送方则不会收到。
- 原因一
- 保证客户端发送的最后一个ACK报文段能够到达服务端
- A并不知道B是否接到自己的ACK
- A是这么想的:
- 如果B没有收到自己的ACK,会超时重传FiN那么A再次接到重传的FIN,会再次发送ACK2)
- 如果B收到自己的ACK,也不会再发任何消息,包括ACK无论是1还是2,A都需要等待,要取这两种情况等待时间的最大值,以应对最坏的情况发生,
- 这个最坏情况是:去向ACK消息最大存活时间(MSL) + 来向FIN消息的最大存活时间(MSL)。
- 这恰恰就是2MSL( Maximum Segment Life)。
- 原因二
- 防止“已失效的连接请求报文段”出现在本连接中。
- 客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
十七:TCP 状态位
- ACK 应答信号
- FIN 结束信号
- RST 重新连接
- PSH 数据推送