deep think


CS144 (2025): Checkpoint2

Abstact

前面两次实验分别实现了一个字节流抽象和一个字节流重装器,本次实验将开始深入TCP细节之中:实现一个 TCPReceiver,从对端Sender中接收字节流并发给Reassembler进行重组,以及将ackno和 window size发回给对端的Sender

Translating between 64-bit indexes and 32-bit seqnos

基于初始序列化(ISN/zero_point)将uint64_t类型的绝对序列号转为uint32_t类型的(相对)序列号

Wrap32 Wrap32::wrap( uint64_t n, Wrap32 zero_point )
{
    // uint64_t -> uint32_t  <==>  val_u64 % 2^32
  return zero_point + static_cast<uint32_t>(n);
}

基于初始序列化(ISN/zero_point)和checkpoint(接近绝对序列号的一个参考值),将uint32_t类型的相对序列号转为 uint64_t类型的绝对序列号

uint64_t Wrap32::unwrap( Wrap32 zero_point, uint64_t checkpoint ) const
{
  Wrap32 cp = wrap( checkpoint, zero_point );
  int32_t offset = raw_value_ - cp.raw_value_;
  int64_t res = checkpoint + offset;
  return res >= 0 ? res : res + ( 1ul << 32 );
}

Implementing the TCP receiver

TCP receiver 包含void receive( TCPSenderMessage message );TCPReceiverMessage send() const;两个需要实现的接口

receive(): 从对端的TCPSender中接收Message(包括seqno、SYN flag、payload、FIN flag和RST flag),计算绝对序列号(stream_index),并将payload插入到Reassembler中

void TCPReceiver::receive( TCPSenderMessage message )
{
  if (writer().has_error() || message.RST) {
    if (message.RST) {
      reader().set_error();
    }
    return;
  }
  if ( not isn_.has_value() ) {
    if (not message.SYN) {
      return;
    }
    isn_ = message.seqno;
  }
  uint64_t checkpoint = writer().bytes_pushed() + 1; // added SYN
  uint64_t abs_seqno = message.seqno.unwrap( isn_.value(), checkpoint );
  // 为什么要 + message.SYN?
  // 考虑 SYN + FIN 的字节流,FIN 标记应该在字节流的末尾,确保了即使没有数据 FIN 也能正确标记流的结束
  uint64_t stream_index = abs_seqno + static_cast<uint64_t>( message.SYN ) - 1;
  reassembler_.insert( stream_index, message.payload, message.FIN );
}

send(): 根据abs_seqno计算ackno,根据available_capacity()计算window_size,从而构造一个 TCPReceiverMessage

TCPReceiverMessage TCPReceiver::send() const
{
  TCPReceiverMessage msg;
  if ( isn_.has_value() ) {
    uint64_t abs_seqno = writer().bytes_pushed();
    if ( writer().is_closed() ) {
      abs_seqno += 2; // 1 byte for FIN
    } else {
      abs_seqno += 1;
    }
    msg.ackno = Wrap32::wrap( abs_seqno, isn_.value() );
  }
  msg.window_size = writer().available_capacity() <= UINT16_MAX ?
                    writer().available_capacity() : UINT16_MAX;
  msg.RST = writer().has_error();
  return msg;
}
,

Published by


Leave a Reply

Your email address will not be published. Required fields are marked *