百度站長(zhǎng)平臺(tái)診斷百度app推廣
一、實(shí)驗(yàn)?zāi)康?/strong>
1.初步了解計(jì)算機(jī)網(wǎng)絡(luò),準(zhǔn)備實(shí)驗(yàn)所需的材料和環(huán)境;
2.掌握基礎(chǔ)實(shí)驗(yàn)方法;
3.動(dòng)手實(shí)現(xiàn)網(wǎng)絡(luò)功能。
二、實(shí)驗(yàn)內(nèi)容
1.下載實(shí)驗(yàn)所需的資料,安裝虛擬機(jī),配置環(huán)境;
2.獲取一個(gè)網(wǎng)頁(yè);
3.監(jiān)聽(tīng)和鏈接:嘗試讓自己的電腦變成一個(gè)簡(jiǎn)單的服務(wù)器,等待其他客戶端連接;
4.使用套接字編寫(xiě)網(wǎng)絡(luò)程序。
三、實(shí)驗(yàn)過(guò)程
(一)獲取實(shí)驗(yàn)材料
電腦上已經(jīng)安裝過(guò)VMware虛擬機(jī)軟件,無(wú)需再次下載;
在Ubuntu官網(wǎng)下載最新鏡像。
(二)安裝虛擬機(jī)
打開(kāi)VMware,新建虛擬機(jī)
選擇ubuntu64位
設(shè)置安裝位置
為避免后期空間不足,適當(dāng)加大磁盤(pán)大小
設(shè)置處理器
選擇ISO鏡像文件
安裝
進(jìn)行簡(jiǎn)單設(shè)置
稍作等待后安裝成功
設(shè)置ubuntu管理員密碼
安裝vim
修改阿里云鏡像
修改失敗 使用圖形化界面尋找最佳服務(wù)器
點(diǎn)擊選擇最佳服務(wù)器,進(jìn)行測(cè)試
測(cè)試結(jié)束,選擇該服務(wù)器
選擇重新載入
安裝cmake
安裝g++
打開(kāi)瀏覽器,訪問(wèn)http://cs144.keithw.org/hello
在終端中依次輸入四條命令
telnet cs144.keithw.org http
GET /hello HTTP/1.1
Host: cs144.keithw.org
Connection: close
輸入http://cs144.keithw.org/lab0/20212734
再次手動(dòng)獲取
監(jiān)聽(tīng)和連接
按下crtl+c斷開(kāi)連接
安裝git軟件包
獲取實(shí)驗(yàn)材料
進(jìn)入目錄
新建“build”目錄
編譯代碼
在 build 目錄中,使用編輯器打開(kāi) …/apps/webget.cc,將get_URL函數(shù)進(jìn)行替換
測(cè)試程序
編寫(xiě) …/src/byte_steam.cc 和 …/src/byte_steam.hh。在 .cc 文件中編寫(xiě)你的代碼,在 .hh 文件中定義你的私有成員變量。(此處以.hh為例)
測(cè)試代碼
實(shí)驗(yàn)結(jié)束。
四、實(shí)驗(yàn)體會(huì)
1.在本實(shí)驗(yàn)中,我通過(guò)獲取一個(gè)網(wǎng)頁(yè),嘗試讓自己的電腦變成一個(gè)簡(jiǎn)單的服務(wù)器,等待其他客戶端連接,我使用套接字編寫(xiě)了網(wǎng)絡(luò)程序這些實(shí)驗(yàn)初步了解了計(jì)算機(jī)網(wǎng)絡(luò)的實(shí)驗(yàn)實(shí)現(xiàn),對(duì)計(jì)算機(jī)網(wǎng)絡(luò)有了更加深入的了解;
2.在本實(shí)驗(yàn)中,我遇到的問(wèn)題主要是在獲取網(wǎng)頁(yè)連續(xù)鍵入四條命令時(shí)總是超時(shí),因?yàn)榇颂幍姆?wù)器會(huì)因請(qǐng)求超時(shí)而關(guān)閉連接,只能通過(guò)粘貼方式輸入。但我的虛擬機(jī)反復(fù)粘貼失敗,最后查證是因?yàn)閂Mware Tools出現(xiàn)問(wèn)題,重新安裝后即可解決。
五、代碼附錄
byte_stream.cc
#include <stdexcept>#include "byte_stream.hh"using namespace std;ByteStream::ByteStream( uint64_t capacity ) : capacity_( capacity ) {}void Writer::push( string data ) noexcept
{auto len = min( data.size(), available_capacity() ); // 確定可寫(xiě)入的數(shù)據(jù)長(zhǎng)度if ( len == 0 ) { // 如果可寫(xiě)入的數(shù)據(jù)長(zhǎng)度為0,說(shuō)明已經(jīng)寫(xiě)滿了,返回return;} else if ( len < data.size() ) { // 如果可寫(xiě)入的數(shù)據(jù)長(zhǎng)度小于 data 的長(zhǎng)度,說(shuō)明只能寫(xiě)入部分?jǐn)?shù)據(jù)data.resize( len ); // 將 data 的長(zhǎng)度截?cái)酁榭蓪?xiě)入的長(zhǎng)度}// 將 data 寫(xiě)入到 buffer 中buffer_data.push( move( data ) );if ( buffer_data.size() == 1) // 寫(xiě)入前為空時(shí)需要更新 buffer_viewbuffer_view = buffer_data.front();// 更新已寫(xiě)入的數(shù)據(jù)長(zhǎng)度bytes_pushed_ += len;
}void Writer::close() noexcept
{flag |= ( 1 << CLOSED );
}void Writer::set_error() noexcept
{flag |= ( 1 << ERROR );
}bool Writer::is_closed() const noexcept
{return flag & ( 1 << CLOSED );
}uint64_t Writer::available_capacity() const noexcept
{return capacity_ - reader().bytes_buffered();
}uint64_t Writer::bytes_pushed() const noexcept
{return bytes_pushed_;
}string_view Reader::peek() const noexcept
{return buffer_view;
}bool Reader::is_finished() const noexcept
{return writer().is_closed() && ( bytes_buffered() == 0 );
}bool Reader::has_error() const noexcept
{return flag & ( 1 << ERROR );
}void Reader::pop( uint64_t len ) noexcept
{if ( len > bytes_buffered() ) {return;}// 更新已彈出的數(shù)據(jù)長(zhǎng)度bytes_popped_ += len;// 將 buffer 中的數(shù)據(jù)彈出while ( len > 0 ) {if ( len >= buffer_view.size() ) {len -= buffer_view.size();buffer_data.pop();buffer_view = buffer_data.front(); // 最開(kāi)始就保證了 buffer_data 不為空} else {buffer_view.remove_prefix( len );len = 0;}}
}uint64_t Reader::bytes_buffered() const noexcept
{return writer().bytes_pushed() - bytes_popped();
}uint64_t Reader::bytes_popped() const noexcept
{return bytes_popped_;
}
Byte_stream.hh
// byte_stream.hh
#pragma once
#include <cstdint>
#include <queue>
#include <stdexcept>
#include <string>
#include <string_view>using std::uint64_t;class Reader;
class Writer;class ByteStream
{
protected:enum State { CLOSED, ERROR };uint64_t capacity_;uint64_t bytes_pushed_ {}; // 已寫(xiě)入的字節(jié)數(shù)uint64_t bytes_popped_ {}; // 已彈出的字節(jié)數(shù)unsigned char flag {}; // 0: normal, 1: closed, 2: errorstd::queue<std::string> buffer_data {};std::string_view buffer_view {};public:explicit ByteStream( uint64_t capacity );// 提供ByteStream的 reader 和 writer 接口的輔助函數(shù)Reader& reader();const Reader& reader() const;Writer& writer();const Writer& writer() const;
};class Writer : public ByteStream
{
public:void push( std::string data ) noexcept; // 在可用容量允許的范圍內(nèi)向流中寫(xiě)入數(shù)據(jù)void close() noexcept; // 關(guān)閉流,不允許再向流中寫(xiě)入數(shù)據(jù)void set_error() noexcept; // 流中出現(xiàn)錯(cuò)誤,置位錯(cuò)誤標(biāo)志bool is_closed() const noexcept; // 判斷流是否已關(guān)閉uint64_t available_capacity() const noexcept; // 計(jì)算流中剩余可用容量uint64_t bytes_pushed() const noexcept; // 計(jì)算流中已寫(xiě)入的字節(jié)數(shù)
};class Reader : public ByteStream
{
public:std::string_view peek() const noexcept; // 返回流中下一個(gè)數(shù)據(jù)塊的只讀視圖void pop( uint64_t len ) noexcept; // 從流中彈出指定長(zhǎng)度的數(shù)據(jù)塊bool is_finished() const noexcept; // 判斷流是否已關(guān)閉且所有數(shù)據(jù)塊都已彈出bool has_error() const noexcept; // 判斷流是否出現(xiàn)錯(cuò)誤uint64_t bytes_buffered() const noexcept; // 計(jì)算當(dāng)前流中剩余的字節(jié)數(shù)uint64_t bytes_popped() const noexcept; // 計(jì)算流中已彈出的字節(jié)數(shù)
};/** read: A (provided) helper function thats peeks and pops up to `len` bytes* from a ByteStream Reader into a string;*/
void read( Reader& reader, uint64_t len, std::string& out );