【面经】飞书后端开发一面

一  TCP和UDP区别?

二 TCP头部和UDP头部区别?

TCP 头部:TCP 头部较复杂,包含了许多字段来支持面向连接的可靠性、流量控制和拥塞控制等功能。

字段大小描述
源端口16 位发送端的端口号
目的端口16 位接收端的端口号
序列号32 位用于数据流的排序和重组
确认号32 位确认已收到的数据的序列号
数据偏移4 位TCP 头部长度 (以 32 位字为单位)
保留6 位预留位,通常为 0
控制位6 位例如 SYN、ACK、FIN 等标志
窗口大小16 位用于流量控制
校验和16 位用于检测数据在传输过程中是否损坏
紧急指针16 位如果 URG 标志位被设置,该字段有效
选项可变包含额外的控制信息和选项
填充可变确保头部长度是 32 位字的倍数
数据可变实际的数据

UDP 头部:UDP 头部较简单,主要提供基本的端到端数据传输功能。UDP 头部的结构如下:

字段大小描述
源端口16 位发送端的端口号
目的端口16 位接收端的端口号
长度16 位UDP 数据包的总长度 (头部+数据)
校验和16 位用于检测数据在传输过程中是否损坏
数据可变实际的数据

三 TCP如何保证数据传输安全?

        TCP主要提供了检验和、序列号/确认应答、超时重传、滑动窗口、拥塞控制和 流量控制等方法实现了可靠性传输。

        检验和:通过检验和的方式,接收端可以检测出来数据是否有差错和异常,假如有差错就会直接丢弃TCP段,重新发送。

        序列号/确认应答:序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。

        TCP传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送ACK报文,这个ACK报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。

        滑动窗口:滑动窗口既提高了报文传输的效率,也避免了发送方发送过多的数据而导致接收方无法正常处理的异常。

        超时重传:超时重传是指发送出去的数据包到接收到确认包之间的时间,如果超过了这个时间会被认为是丢包了,需要重传。最大超时时间是动态计算的。

        拥塞控制:在数据传输过程中,可能由于网络状态的问题,造成网络拥堵,此时引入拥塞控制机制,在保证TCP可靠性的同时,提高性能。

        流量控制:如果主机A 一直向主机B发送数据,不考虑主机B的接受能力,则可能导致主机B的接受缓冲区满了而无法再接受数据,从而会导致大量的数据丢包,引发重传机制。而在重传的过程中,若主机B的接收缓冲区情况仍未好转,则会将大量的时间浪费在重传数据上,降低传送数据的效率。所以引入流量控制机制,主机B通过告诉主机A自己接收缓冲区的大小,来使主机A控制发送的数据量。流量控制与TCP协议报头中的窗口大小有关。

四 TCP的序列号除了保证数据有序还有什么作用?

1. 数据重组

        TCP 的序列号用于数据重组。在接收方,TCP 会根据序列号将接收到的分段数据重新组合成原始数据流。这对于处理可能乱序到达的分段数据非常重要,因为数据包可能会经过不同的路径到达接收方。

2. 数据重传

        序列号在数据重传中起到关键作用。如果一个数据包在传输过程中丢失或出现错误,接收方不会收到这个数据包,并会要求发送方重新发送该数据包。接收方通过确认号(ACK)通知发送方未接收到的数据包的序列号,从而触发重传。

3. 流量控制

        TCP 使用序列号来实现流量控制。通过序列号,发送方可以知道已被接收方确认的数据的范围,从而限制新数据的发送量。TCP 的滑动窗口机制利用序列号来控制数据的发送速率,确保接收方能够处理接收到的数据而不会被压垮。

4. 确认和拥塞控制

        确认(ACK):接收方使用确认号来指示到达的数据的序列号。发送方收到确认后,可以确定数据已经成功接收,并可以移动发送窗口,从而发送新的数据。

        拥塞控制:序列号在拥塞控制中也起到作用。TCP 协议通过监控序列号和确认号来动态调整数据的发送速率,以避免网络拥塞。通过控制发送窗口的大小,TCP 能够在网络拥塞的情况下减少发送的数据量。

5. 防止重复数据

        序列号帮助防止数据的重复接收。在 TCP 连接中,每个数据包都有一个唯一的序列号。接收方可以通过检查序列号来识别并丢弃重复的数据包,确保每个数据包只被处理一次。

五 如何设计一个限流器?

        令牌桶算法通过一个桶来存储令牌,每秒生成一定数量的令牌。每个请求需要消耗一个令牌。如果桶为空,则请求被拒绝。令牌桶允许突发流量,但限制了平均速率。

实现步骤:

  1. 初始化令牌桶,设置令牌生成速率和桶的容量。
  2. 每秒生成一定数量的令牌,并加入桶中(如果桶未满)。
  3. 每次请求时,从桶中取走一个令牌。
  4. 如果桶为空,拒绝请求;如果有令牌,允许请求。
import java.util.concurrent.TimeUnit;

public class TokenBucket {
    private final long capacity; // 桶的容量
    private final long rate;     // 令牌生成速率(每秒生成的令牌数)
    private long tokens;         // 当前令牌数
    private long lastRefillTime; // 上次令牌生成时间

    public TokenBucket(long capacity, long rate) {
        this.capacity = capacity;
        this.rate = rate;
        this.tokens = capacity;
        this.lastRefillTime = System.nanoTime();
    }

    public synchronized boolean tryAcquire() {
        refill();
        if (tokens > 0) {
            tokens--;
            return true;
        }
        return false;
    }

    private void refill() {
        long now = System.nanoTime();
        long elapsed = now - lastRefillTime;
        long newTokens = TimeUnit.NANOSECONDS.toSeconds(elapsed) * rate;
        tokens = Math.min(capacity, tokens + newTokens);
        lastRefillTime = now;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值