通过一些问题来讨论 TCP 协议
- 什么是 TCP ?举几个应用了 TCP 协议的例子
- TCP协议如何保证可靠性?
- tcp如何保证不会接受重复的报文?
- Tcp粘包拆包问题了解吗?介绍一下,如何解决?
- TCP拥塞控制与流量控制区别?
- 现在我们视频面试用到哪些协议
1. 什么是 TCP ?举几个应用了 TCP 协议的例子
TCP 就是连接控制协议,是面向连接的,可靠的,基于字节流的传输层通信协议。
其中面向连接一定是一对一的连接。可靠性指无论网络链路中出现了什么状况,TCP 都会尽力保证一个报文能够无损坏,无冗余,按序到达。基于字节流是指用户消息通过 TCP 协议传输时,会被操作系统分组成多个 TCP 报文,并且这些报文之间是有序的
像我们平时用到的最多的网页中的 HTTP 协议,传输层协议就是 TCP。类似用到 TCP 的应用层还有 FTP 文件传输协议,SMTP 简单邮件传输协议和 SSH,它们的传输层都需要 TCP 来做可靠性保证
2. TCP协议如何保证可靠性?
首先 TCP 每次建立连接都需要三次握手,释放连接需要四次挥手来确保建立的传输通道是可靠的
其次,TCP 采用了连续 ARQ 协议来保证数据传输的正确性,同时还使用了滑动窗口机制来控制发送方的发送速率,保证接收方一定能接受到发送的数据,也就是流量控制机制
还有,TCP 利用序列号和校验和,来分别确保数据传输的有序性和完整性
最后在整个网络层面上,TCP 还使用慢启动,拥塞避免,快速重传和快速恢复来进行拥塞控制,避免网络阻塞带来的数据接好问题
3. tcp如何保证不会接受重复的报文?
这个是由 TCP 报文中的“序列号”字段保证的,TCP 在建立连接时,客户端和服务端都会将一个内核生成的随机数作为自己的初始序列号。在建立连接完成后,开始发送数据时,发送的一端会将“上次发送的序列号”加上“上次发送的数据长度”作为“本次报文的序列号”发送给对端。对端在收到数据包时,会根据序列号来确定接收到数据的顺序和是否重复,如果重复收到某个序列号的报文,则只会接收一次,其他的都丢弃
需要注意的是,在三次握手和四次挥手阶段,发送端序列号的值就不是“上次发送的序列号”加上“上次发送的数据长度”的值,而是“上次发送的序列号”加上 “1”
还有,序列号除了确保数据接收的“有序性”,还有用于 TCP 的流量控制中。具体的,TCP 连接的两端都会维护一个发送窗口和接受窗口。发送方根据 TCP 报文的序列号和发送窗口的大小来确定可以发送的数据量。接收方使用序列号和接收窗口大小来确定可以接收的数据量,并通知发送方来控制发送速率,以此来确保双方数据都能够被顺利接收。
4. Tcp粘包拆包问题了解吗?介绍一下,如何解决?
首先 TCP 是处在传输层的面向流的协议的协议,它本身不会按照应用开发者的期望,保持每次发送时都带有一个数据的边界,这可能导致接收端一次收到了多个应用层报文,需要应用开发者自己分开,也就是需要自己去实现“流”到“数据报”的功能。具体的解决,可以用“特殊字符作为边界”,也就是我们对于应用层的每个信息后面都加上一些特殊字符用来代表信息结束。当读到了这些特殊字符,就意味着已经读完了一个完整的消息。比如 HTTP 通过设置回车符和一个换行符来作为 HTTP 报文协议的边界。但需要注意的是,如果信息内容中刚好出现了这些字符,可能会导致信息提前结束和数据错乱,这时我们可以对这些个字符进行转义,避免这种情况。
其实还有一种“粘包”的含义:就是 TCP 在实现的时候,为了解决大量小报文场景下,包头比数据还大,导致传输的性价比太低的情况,采用了一种叫 Nagle 的算法。这个算法的效果就是将开发者多次发送的小数据,粘在同一个 TCP 报文中发出。这样可能就会导致先被发送的数据可能需要等待一段时间,才能跟后面才被发送的数据一起组成报文发送出去。但在实际中这种算法带来的延迟几乎可以忽略不计,绝大多数情况都是无感知的。只有在频繁进行超短信息的交互,比如只有几个字节的场景,禁用 Nagle 算法才能显著降低延迟。
5. TCP拥塞控制与流量控制区别?
两者诞生的原因就不同:
需要流量控制的原因是,端到端在通信时,发送方的速率与接收方的速率不一致,如果发送方发的速率太快,会导致接收方处理不过来;而如果发送方发送的太慢,数据就会有一定的延迟。那么此时就需要通过一种方法来控制发送方的速率,这个方法就叫“流量控制”
而拥塞控制不同于流量控制,它主要强调的是网络的拥塞,导致发送方发的数据包被堵在了半路,而接收方迟迟没收到数据包并返回接收到的最后一个包的确认报文,会让发送方误以为这个包丢了并重新发送,这不仅会浪费信道资源,还会使原来拥塞的网络雪上加霜。
6. 现在我们视频面试用到哪些协议
考虑到视频时对于延迟很敏感,所以应该具有 UDP 传输速度快的特性,但又能允许一定程度的丢包。但又不能丢包率太高,还应具备 TCP 有关数据传输可靠性的保证,确保不会视频着视频着突然画面就没有了的情况。所以我觉得应该是同时结合了 TCP 可靠性和 UDP 速度快的优点,这类协议我了解的是谷歌提出的 QUIC 协议。
QUIC 协议全称是“快速 UDP 互联网”连接,相比与当前应用多的 http2 + tcp + tls,它的优势主要在减少了 TCP 三次握手以及 TLS 握手的时间,拥有改进后的拥塞控制,以及拥有避免队头阻塞的多路复用。
首先由于 UDP 本身没有连接的概念,不需要三次握手,QUIC 在此基础上实现了 0 RTT 的安全握手,并且在大部分情况下也只需 0 RTT 就能实现数据发送。
为了保证可靠性传输,QUIC 在 TCP 关于拥塞控制方面的四个算法,包括慢启动,拥塞避免,快速重传,快速回复都做了相应的改进。比较突出的特点就是,QUIC 使用 packet number 代替了 TCP 的 sequence number,且每个 packet number 都严格递增。加上同样是 QUIC 提出的 Stream Offset,确保数据的顺序性和可靠性。
除此之外,QUIC 还在 Connection 和 Stream 两个级别都提供了流量控制。Stream 可以理解为一条 http 请求,Connection 可以类比一条 TCP 连接。QUIC 的多路复用就是指在一条 Connection 上同时存在多条 Stream,且多条 Stream 之间没有顺序依赖,也就消除了 TCP 中队头阻塞的问题。
大致只了解这么多。
诚恳欢迎大家提出意见
......(待续未完