CS144學習(1)Lab 0: networking warmup


CS144的實驗就是要實現一個用戶態TCP協議,對於提升C++的水平以及更加深入學習計算機網絡還是有很大幫助的。

第一個Lab是環境配置和熱身,環境按照文檔里的配置就行了,前面兩個小實驗就是按照步驟來的,就不細講了。

Writing webget

這一個實驗是要用他封裝好的socket庫寫一個簡單的http客戶端。看看文檔里AddressTCPSocket類的介紹就行了。

void get_URL(const string &host, const string &path) {
    TCPSocket sock;
    sock.connect(Address(host, "http"));
    sock.write("GET " + path + " HTTP/1.1\r\n");
    sock.write("Host: " + host + "\r\n");
    sock.write("Connection: close \r\n");
    sock.write("\r\n");

    while(!sock.eof()){
        auto rsp = sock.read();
        cout << rsp;
    }
    sock.close();
}

注意就是輸出的時候要原封不動地輸出內容,也不能任何內容(包括回車),不然會通過不了檢查。

An in-memory reliable byte stream

這一個就是要實現一個循環緩沖區ByteStream,並實現一系列的函數實現對其的讀寫等操作。我這里底層是使用vector來實現。

class ByteStream {
  private:
    std::vector<char> buffer;
    size_t head = 0;
    size_t tail = 0;
    size_t length = 0;
    size_t cap = 0;
    size_t total_read = 0;
    size_t total_write = 0;
    bool end = false;

    bool _error{};  //!< Flag indicating that the stream suffered an error.
    ...
}

ByteStream::ByteStream(const size_t capacity) : buffer(capacity), cap(capacity) {}

size_t ByteStream::write(const string &data) {
    size_t wlen;
    if(data.length() > cap - length){
        wlen = cap - length;
    }else{
        wlen = data.length();
    }
    for(size_t i = 0; i < wlen; i++){
        buffer[tail] = data[i];
        tail = (tail + 1) % cap;
    }
    length += wlen;
    total_write += wlen;
    return wlen;
}

//! \param[in] len bytes will be copied from the output side of the buffer
string ByteStream::peek_output(const size_t len) const {
    size_t rlen;
    if(len > length){
        rlen = length;
    }else{
        rlen = len;
    }
    string res(rlen, 0);
    size_t p = head;
    for(size_t i = 0; i < rlen; i++){
        res[i] = buffer[p];
        p = (p + 1) % cap;
    }
    return res;
}

//! \param[in] len bytes will be removed from the output side of the buffer
void ByteStream::pop_output(const size_t len) {
    if(len > length){
        length = 0;
        head = this->tail;
        total_read += length;
    }else{
        length -= len;
        head = (head + len) % cap;
        total_read += len;
    }
}

//! Read (i.e., copy and then pop) the next "len" bytes of the stream
//! \param[in] len bytes will be popped and returned
//! \returns a string
std::string ByteStream::read(const size_t len) {
    string res = peek_output(len);
    pop_output(len);
    return res;
}

void ByteStream::end_input() {
    end = true;
}

bool ByteStream::input_ended() const {
    return end;
}

size_t ByteStream::buffer_size() const {
    return length;
}

bool ByteStream::buffer_empty() const {
    // cout << len << endl;
    return length == 0;
}

bool ByteStream::eof() const {
    return end && length == 0;
}

size_t ByteStream::bytes_written() const {
    return total_write;
}

size_t ByteStream::bytes_read() const {
    return total_read;
}

size_t ByteStream::remaining_capacity() const {
    return cap - length;
}

整個實現還是很簡單的,就是記得判斷一下輸入的len是否超出了限制就行了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM