deep think


CS144 (2025): Checkpoint0

Code Style

  • 使用 https://en.cppreference.com 作为C++参考手册
  • 杜绝使用 malloc() / free()new / delete
  • 杜绝使用C风格的类型转换,而使用C++ static_cast
  • 尽量使用智能指针而非C风格指针
  • 尽量使用 C++ std::string 而非C风格字符串及相关API函数
  • 尽量使用const reference类型的函数参数
  • 尽量使用const类型的变量或函数
  • 尽量不使用全局变量,并且赋予变量尽可能小的作用域
  • 使用clang-format对代码做格式化,使用clang-tidy对代码做静态检查

Abstract

了解 TCP writer 和 reader 之间的可靠字节流传输

Fetch a Web page

使用 telnet 手动构造 HTTP 报文,实现 HTTP 协议通信

cs144@cs144vm:~$ telnet cs144.keithw.org http
Trying 104.196.238.229...
Connected to cs144.keithw.org.
Escape character is '^]'.
GET /lab0/1234 HTTP/1.1
Host: cs144.keithw.org
Connection: close

HTTP/1.1 200 OK
Date: Thu, 30 Jan 2025 10:48:57 GMT
Server: Apache
X-You-Said-Your-SunetID-Was: 1234
X-Your-Code-Is: 222626
Content-length: 108
Vary: Accept-Encoding
Connection: close
Content-Type: text/plain

Hello! You told us that your SUNet ID was "1234". Please see the HTTP headers (above) for your secret code.
Connection closed by foreign host.

Send yourself a mail

使用 telnet 手动构造 SMTP 报文,实现 SMTP 协议通信

cs144@cs144vm:~$ telnet smtp.126.com smtp
Trying 117.135.214.14...
Connected to smtp.126.com.
Escape character is '^]'.
220 126.com Anti-spam GT for Coremail System (126com[20140526])
HELO hartvon
250 OK
AUTH LOGIN
334 dXNlcm5hbWU6
Zmh0enZsQDEyNi5jb20=
334 UGFzc3dvcmQ6
Qlhwdjk2SHl1clpjZlBNVQ==
235 Authentication successful
MAIL FROM: <fhtzvl@126.com>
250 Mail OK
RCPT TO: <fhtzvl@163.com>
250 Mail OK
DATA
354 End data with <CR><LF>.<CR><LF>
FROM: fhtzvl@126.com
TO: fhtzvl@163.com
Subject: Hello from CS144 Lab 0!

This is example text body.

.
250 Mail OK queued as gzsmtp3,PikvCgDnP+X3bZtns8SpAQ--.16071S2 1738239576

421 closing transmission channel
Connection closed by foreign host.

Listenning and connecting

使用 nc 进行 TCP 层 server 和 client 之间的通信

cs144@cs144vm:~/minnow$ nc -vlp 9090
Listening on 0.0.0.0 9090
Connection received on localhost 48480
hello, this is client

cs144@cs144vm:~/minnow$ nc localhost 9090
hello, this is client
^C

Writing webget

使用封装好的 TCPSocket 类手动构造 HTTP 报文,并与连接成功的服务端进行报文的写读

void get_URL( const string& host, const string& path )
{
  cerr << "Function called: get_URL(" << host << ", " << path << ")\n";

  try {
    TCPSocket tcp_socket;  // 3-way shakehands
    tcp_socket.connect( Address( host, "http" ) );

    tcp_socket.write(
      { "GET " + path + " HTTP/1.1\r\n", "Host: cs144.keithw.org\r\n", "Connection: close\r\n\r\n" } );   // client's P & server's F

    while ( !tcp_socket.eof() ) {  // check if reach elf
      std::string output;
      tcp_socket.read( output );   // may set elf status
      std::cout << output;
    }
        // client's F as tcp_socket's destruction
  } catch ( const std::exception& e ) {
    std::cerr << e.what() << "\n";
  }
}

An in-memory reliable byte stream

将内存 buffer 作为 TCP 的字节流 buffer,实现 TCP 字节流的 push 和 pop,通过 capacity_控制 writer 的写限速,超出容量的字节流将会被丢弃

注意:虽然这个内存buffer有最大容量(限制了一次从内存中写入或读取的最大字节长度),但它所承载的总字节流可以任意长,只要这些字节流一直被不断地被写入和读取

// bytes_stream.hh
class ByteStream
{
public:
  ...
protected:
  uint64_t capacity_;
  bool error_ {};
  bool is_closed_ {};

  std::string buffer_ {};
  uint64_t bytes_buffered_ {};
  uint64_t bytes_write_ {};
  uint64_t bytes_read_ {};
};
// bytes_stream.cc

#include "byte_stream.hh"
using namespace std;
ByteStream::ByteStream( uint64_t capacity ) : capacity_( capacity ) {}
void Writer::push( string data )
{
  if ( is_closed_ or has_error() )
    return;
  auto data_size = std::min( data.size(), available_capacity() );
  buffer_ += data.substr( 0, data_size );
  bytes_buffered_ += data_size;
  bytes_write_ += data_size;
}
void Writer::close()
{
  is_closed_ = true;
}
bool Writer::is_closed() const
{
  return is_closed_;
}
uint64_t Writer::available_capacity() const
{
  return capacity_ - bytes_buffered_;
}
uint64_t Writer::bytes_pushed() const
{
  return bytes_write_;
}
string_view Reader::peek() const
{
  return buffer_;
}
void Reader::pop( uint64_t len )
{
  buffer_.erase( 0, len );
  bytes_read_ += len;
  bytes_buffered_ -= len;
}
bool Reader::is_finished() const
{
  return is_closed_ and bytes_buffered_ == 0;
}
uint64_t Reader::bytes_buffered() const
{
  return bytes_buffered_;
}
uint64_t Reader::bytes_popped() const
{
  return bytes_read_;
}

Published by


Leave a Reply

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