CS144 lab2 笔记
CS144 lab2 筆記
介紹
在lab0中,我們實現了一個ByteStream。
在lab1中,實現了一個重組字符片段的StreamReassembler,重組收到的字符片段,并且將排序好的字符串退送到ByteStream
在lab2中,j將實現一個TCPReceiver,它將在TCP segments和byte stream之間進行轉換
通過這個圖片
-
ackno就是第一個未排序片段的索引,是期望下一個收到的片段索引
-
第一個未排序片段與流末端索引之間的距離就是window size(TCP窗口)
the distance between the “first unassembled” index and the “first unacceptable” index.
This is called the “window size”
Translating between 64-bit indexes and 32-bit seqnos
通過TCP報頭我們可以知道,傳輸過程中的seq是32位的,但我們本地的seq是64位系統(tǒng)下的,所以我們需要將seq(64bit)--->seq(32bit),32位最大值為 232-1,超過這個數字就從0開始
TCP seq 以一個32為隨機值初始化:這個目的是為了防止被猜到,以及網絡中較早的數據報造成干擾,一端連接中第一個seq就以一個32位的數字初始化,叫做Initial Sequence Number(ISN),之后每個seq/mod 232
連接開始和結束每個占用一個序列號:除了確保收到所有字節(jié)的數據,TCP確保流的開始和結束同樣是是可靠的。因此,在TCP中,SYN(流開始)和FIN(流終端)控制標志被分配序列號。都占據一個序列號。 (SYN標志占用的序列號就是ISN。)流中的每個數據字節(jié)還占用一個序列號。請記住,SYN和FIN不是流本身的一部分,而不是“字節(jié)” —它們代表字節(jié)流本身的開始和結束。
這些seq在每個TCP段的頭中發(fā)送。**絕對序列號:**始終以零開始并且不包裝(就是64位),流索引:StreamReassEmbler流中的每個字節(jié)的索引,從零開始,64bit,具體見下圖:
思路
-
很顯然這種轉換不是唯一的——seqno每次增加2322^{32}232值都不變,但是absolute seqno變化。為了確定唯一的結果,我們需要checkpoint,即將可能的結果中距離checkpoint最近的作為最終結果。
-
checkpoint表示最近一次轉換求得的absolute seqno,而本次轉換出的absolute seqno應該選擇與上次值最為接近的那一個。原理是雖然segment不一定按序到達,但幾乎不可能出現相鄰到達的兩個segment序號差值超過INT32_MAX的情況
-
如果想不出來,就在紙上畫一畫就能想出來了
實現
//! Transform an "absolute" 64-bit sequence number (zero-indexed) into a WrappingInt32 //! \param n The input absolute 64-bit sequence number //! \param isn The initial sequence number WrappingInt32 wrap(uint64_t n, WrappingInt32 isn) { return WrappingInt32(static_cast<uint32_t>(n) + isn.raw_value()); }//! Transform a WrappingInt32 into an "absolute" 64-bit sequence number (zero-indexed) //! \param n The relative sequence number //! \param isn The initial sequence number //! \param checkpoint A recent absolute 64-bit sequence number //! \returns the 64-bit sequence number that wraps to `n` and is closest to `checkpoint` //! //! \note Each of the two streams of the TCP connection has its own ISN. One stream //! runs from the local TCPSender to the remote TCPReceiver and has one ISN, //! and the other stream runs from the remote TCPSender to the local TCPReceiver and //! has a different ISN. uint64_t unwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint) {int32_t interval = n - wrap(checkpoint, isn);int64_t result = checkpoint + interval;if (result >= 0)return result;elsereturn result + (1ul << 32); }Implementing the TCP receiver
對于接收端,在這個實驗中只需要處理示意圖中彩色部分:
在做實驗之前最好看一下TCPSegment的相關實現
思路
主要就是參考下圖中TCP的過程,將其分為圖中三種情況,一一實現即可,錯誤不需要考慮,將在之后的實驗進行處理
segment received()
- 請設置初始序列號。設置ISN,并且不要忘記使用 。請注意,SYN標志只是標題中的一個標志。相同的段也可以攜帶數據,甚至可以設置FIN標志。所以,即使受到syn也不能拋棄他的片段以及fin
- 將任何數據或流終端標記推向StreamReasseMbler。如果FIN標志設置在TCPSegment的標題中,這意味著有效載荷的最后一個字節(jié)是整個流的最后一個字節(jié)。
ackno()
- 返回包含接收器尚未知道的第一個字節(jié)的序列號的wraxingInt32。這是Window的左邊緣。如果尚未設置ISN,則返回一個空可選
window size()
- 見代碼
實現
tcp_receiver.hh
class TCPReceiver {//! Our data structure for re-assembling bytes.StreamReassembler _reassembler;//! The maximum number of bytes we'll store.size_t _capacity;bool _syn {false};WrappingInt32 _isn{0};tcp_receiver.cc
void TCPReceiver::segment_received(const TCPSegment &seg) {const TCPHeader &_tcp_header = seg.header();/** 不需要考慮很多,直接按照tcp接收端狀態(tài)轉換圖寫就行,其他情況都可以交給reassembler處理*/if (!_syn) // 如果未收到過syn{if (!_tcp_header.syn)// 如果包中含有syn就繼續(xù),沒有就直接返回,拋棄包return;_syn = true;_isn = _tcp_header.seqno;}// ack 期望下一個收到的片段索引uint64_t _ackno = _reassembler.stream_out().bytes_written() + 1;// 計算 sequint64_t _seqno = unwrap(_tcp_header.seqno, _isn, _ackno);// 注意syn也占用seqno,所以別忘了uint64_t _index = _seqno - 1 + static_cast<uint64_t>(_tcp_header.syn);_reassembler.push_substring(seg.payload().copy(), _index, _tcp_header.fin); }optional<WrappingInt32> TCPReceiver::ackno() const {if (!_syn) // 如果未建立連接,直接返回空return nullopt;uint64_t _ackno = _reassembler.stream_out().bytes_written() + 1;if (_reassembler.stream_out().input_ended())// 如果結束連接,返回的ack要算上sender發(fā)來的fin_ackno++;return WrappingInt32(_isn) + _ackno; } // 如下 size_t TCPReceiver::window_size() const { return _capacity - _reassembler.stream_out().buffer_size(); }總結
以上是生活随笔為你收集整理的CS144 lab2 笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VB与数据库连接
- 下一篇: easyui dialog的一个小坑