【计算机网络 - 基础问题】每日 3 题(二十三)
✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/fYaBd
📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
📝推荐参考地址:https://www.xiaolincoding.com/(这个大佬的专栏非常有用!)
67. TCP 如何保证可靠性连接?
- 校验和:TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
- 序列号:TCP 传输时将每个字节的数据都进行了编号,这就是序列号。(为了应对延时抵达和排序混乱)。每个连接都会选择一个初始序列号,初始序列号(视为一个 32 位计数器),会随时间而改变(每 4 微秒加 1)。因此,每一个连接都拥有不同的序列号。序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。这也是 TCP 传输可靠性的保证之一。
- 确认应答:TCP 传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送 ACK 报文。这个 ACK 报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。
- 超时重传:超时重传机制。简单理解就是发送方在发送完数据后等待一个时间,时间到达没有接收到 ACK 报文,那么对刚才发送的数据进行重新发送。如果是刚才第一个原因,接收方收到二次重发的数据后,便进行 ACK 应答。如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以上面说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送 ACK 应答。那么发送方发送完毕后等待的时间是多少呢?如果这个等待的时间过长,那么会影响 TCP 传输的整体效率,如果等待时间过短,又会导致频繁的发送重复的包。如何权衡?由于 TCP 传输时保证能够在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。
- 连接管理:说白了就是三次握手四次挥手。
- 流量控制:当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。
- 拥塞控制:拥塞控制是 TCP 在传输时尽可能快的将数据传输,并且避免拥塞造成的一系列问题。是可靠性的保证,同时也是维护了传输的高效性。
68. 能不能说说 TCP 报文中时间戳的作用?
timestamp 是 TCP 报文首部的一个可选项,一共占 10 个字节,格式如下:
kind(1 字节) + length(1 字节) + info(8 个字节)
其中 kind = 8, length = 10, info 有两部分构成:timestamp 和 timestamp echo,各占 4 个字节。
TCP 的时间戳主要解决两大问题:
- 计算往返时延 RTT (Round-Trip Time)
- 防止序列号的回绕问题
69. 能不能说说 Nagle 算法和延迟确认?
- Nagle 算法
试想一个场景,发送端不停地给接收端发很小的包,一次只发 1 个字节,那么发 1 千个字节需要发 1000 次。这种频繁的发送是存在问题的,不光是传输的时延消耗,发送和确认本身也是需要耗时的,频繁的发送接收带来了巨大的时延。
而避免小包的频繁发送,这就是 Nagle 算法要做的事情。
具体来说,Nagle 算法的规则如下:
- 第一次发送数据时不用等待,就算是 1 byte 的小包也立即发送
- 后面发送满足下面条件之一就可以发了:
- 数据包大小达到最大段大小 (Max Segment Size,即 MSS)
- 之前所有包的 ACK 都已接收到
- 延迟确认
试想这样一个场景,当我收到了发送端的一个包,然后在极短的时间内又接收到了第二个包,那我是一个个地回复,还是稍微等一下,把两个包的 ACK 合并后一起回复呢?
延迟确认 (delayed ack) 所做的事情,就是后者,稍稍延迟,然后合并 ACK,最后才回复给发送端。TCP 要求这个延迟的时延必须小于 500ms,一般操作系统实现都不会超过 200ms。
不过需要主要的是,有一些场景是不能延迟确认的,收到了就要马上回复:
- 接收到了大于一个 frame 的报文,且需要调整窗口大小
- TCP 处于 quickack 模式(通过 tcp_in_quickack_mode 设置)
- 发现了乱序包
- 两者一起使用会怎样?
前者意味着延迟发,后者意味着延迟接收,会造成更大的延迟,产生性能问题。