CS144 lab4 计算机网络实验 笔记

CS144 lab4 计算机网络实验 笔记

介绍

本实验中,我们将组合TCP senderTCP receiver实现一个完整的TCP connection

image-20220201233626933

image-20220201234117101

TCP是全双工连接,所以两方可以同时接收/发送信息,一端随时都有可能接收.发送信息

img

主要根据上图实现

tcp_connection.cc

#include "tcp_connection.hh"#include <iostream>using namespace std;size_t TCPConnection::remaining_outbound_capacity() const { return _sender.stream_in().remaining_capacity(); }size_t TCPConnection::bytes_in_flight() const { return _sender.bytes_in_flight(); }size_t TCPConnection::unassembled_bytes() const { return _receiver.unassembled_bytes(); }size_t TCPConnection::time_since_last_segment_received() const { return _time_since_last_segment_received; }bool TCPConnection::active() const { return _active; }void TCPConnection::segment_received(const TCPSegment &seg) {if (!_active)return;_time_since_last_segment_received = 0;// State: closedif (!_receiver.ackno().has_value() && _sender.next_seqno_absolute() == 0) {if (!seg.header().syn)return;_receiver.segment_received(seg);connect();return;}// State: syn sentif (_sender.next_seqno_absolute() > 0 && _sender.bytes_in_flight() == _sender.next_seqno_absolute() &&!_receiver.ackno().has_value()) {if (seg.payload().size())return;if (!seg.header().ack) {if (seg.header().syn) {// simultaneous open_receiver.segment_received(seg);_sender.send_empty_segment();}return;}if (seg.header().rst) {_receiver.stream_out().set_error();_sender.stream_in().set_error();_active = false;return;}}_receiver.segment_received(seg);_sender.ack_received(seg.header().ackno, seg.header().win);// Lab3 behavior: fill_window() will directly return without sending any segment.// See tcp_sender.cc line 42if (_sender.stream_in().buffer_empty() && seg.length_in_sequence_space())_sender.send_empty_segment();if (seg.header().rst) {_sender.send_empty_segment();unclean_shutdown();return;}send_sender_segments();
}size_t TCPConnection::write(const string &data) {if (!data.size())return 0;size_t write_size = _sender.stream_in().write(data);_sender.fill_window();send_sender_segments();return write_size;
}//! \param[in] ms_since_last_tick number of milliseconds since the last call to this method
void TCPConnection::tick(const size_t ms_since_last_tick) {if (!_active)return;_time_since_last_segment_received += ms_since_last_tick;_sender.tick(ms_since_last_tick);if (_sender.consecutive_retransmissions() > TCPConfig::MAX_RETX_ATTEMPTS)unclean_shutdown();send_sender_segments();
}void TCPConnection::end_input_stream() {_sender.stream_in().end_input();_sender.fill_window();send_sender_segments();
}void TCPConnection::connect() {_sender.fill_window();send_sender_segments();
}TCPConnection::~TCPConnection() {try {if (active()) {cerr << "Warning: Unclean shutdown of TCPConnection\n";_sender.send_empty_segment();unclean_shutdown();}} catch (const exception &e) {std::cerr << "Exception destructing TCP FSM: " << e.what() << std::endl;}
}void TCPConnection::send_sender_segments() {TCPSegment seg;while (!_sender.segments_out().empty()) {seg = _sender.segments_out().front();_sender.segments_out().pop();if (_receiver.ackno().has_value()) {seg.header().ack = true;seg.header().ackno = _receiver.ackno().value();seg.header().win = _receiver.window_size();}_segments_out.push(seg);}clean_shutdown();
}void TCPConnection::unclean_shutdown() {// When this being called, _sender.stream_out() should not be empty._receiver.stream_out().set_error();_sender.stream_in().set_error();_active = false;TCPSegment seg = _sender.segments_out().front();_sender.segments_out().pop();seg.header().ack = true;if (_receiver.ackno().has_value())seg.header().ackno = _receiver.ackno().value();seg.header().win = _receiver.window_size();seg.header().rst = true;_segments_out.push(seg);
}void TCPConnection::clean_shutdown() {if (_receiver.stream_out().input_ended()) {if (!_sender.stream_in().eof())_linger_after_streams_finish = false;else if (_sender.bytes_in_flight() == 0) {if (!_linger_after_streams_finish || time_since_last_segment_received() >= 10 * _cfg.rt_timeout) {_active = false;}}}
}

tcp_connection.hh

#ifndef SPONGE_LIBSPONGE_TCP_FACTORED_HH
#define SPONGE_LIBSPONGE_TCP_FACTORED_HH#include "tcp_config.hh"
#include "tcp_receiver.hh"
#include "tcp_sender.hh"
#include "tcp_state.hh"//! \brief A complete endpoint of a TCP connection
class TCPConnection {private:size_t _time_since_last_segment_received{0};bool _active{true};void send_sender_segments();void clean_shutdown();void unclean_shutdown();TCPConfig _cfg;TCPReceiver _receiver{_cfg.recv_capacity};TCPSender _sender{_cfg.send_capacity, _cfg.rt_timeout, _cfg.fixed_isn};//! outbound queue of segments that the TCPConnection wants sentstd::queue<TCPSegment> _segments_out{};//! Should the TCPConnection stay active (and keep ACKing)//! for 10 * _cfg.rt_timeout milliseconds after both streams have ended,//! in case the remote TCPConnection doesn't know we've received its whole stream?bool _linger_after_streams_finish{true};public://! \name "Input" interface for the writer//!@{//! \brief Initiate a connection by sending a SYN segmentvoid connect();//! \brief Write data to the outbound byte stream, and send it over TCP if possible//! \returns the number of bytes from `data` that were actually written.size_t write(const std::string &data);//! \returns the number of `bytes` that can be written right now.size_t remaining_outbound_capacity() const;//! \brief Shut down the outbound byte stream (still allows reading incoming data)void end_input_stream();//!@}//! \name "Output" interface for the reader//!@{//! \brief The inbound byte stream received from the peerByteStream &inbound_stream() { return _receiver.stream_out(); }//!@}//! \name Accessors used for testing//!@{//! \brief number of bytes sent and not yet acknowledged, counting SYN/FIN each as one bytesize_t bytes_in_flight() const;//! \brief number of bytes not yet reassembledsize_t unassembled_bytes() const;//! \brief Number of milliseconds since the last segment was receivedsize_t time_since_last_segment_received() const;//!< \brief summarize the state of the sender, receiver, and the connectionTCPState state() const { return {_sender, _receiver, active(), _linger_after_streams_finish}; };//!@}//! \name Methods for the owner or operating system to call//!@{//! Called when a new segment has been received from the networkvoid segment_received(const TCPSegment &seg);//! Called periodically when time elapsesvoid tick(const size_t ms_since_last_tick);//! \brief TCPSegments that the TCPConnection has enqueued for transmission.//! \note The owner or operating system will dequeue these and//! put each one into the payload of a lower-layer datagram (usually Internet datagrams (IP),//! but could also be user datagrams (UDP) or any other kind).std::queue<TCPSegment> &segments_out() { return _segments_out; }//! \brief Is the connection still alive in any way?//! \returns `true` if either stream is still running or if the TCPConnection is lingering//! after both streams have finished (e.g. to ACK retransmissions from the peer)bool active() const;//!@}//! Construct a new connection from a configurationexplicit TCPConnection(const TCPConfig &cfg) : _cfg{cfg} {}//! \name construction and destruction//! moving is allowed; copying is disallowed; default construction not possible//!@{~TCPConnection();  //!< destructor sends a RST if the connection is still openTCPConnection() = delete;TCPConnection(TCPConnection &&other) = default;TCPConnection &operator=(TCPConnection &&other) = default;TCPConnection(const TCPConnection &other) = delete;TCPConnection &operator=(const TCPConnection &other) = delete;//!@}
};#endif  // SPONGE_LIBSPONGE_TCP_FACTORED_HH

致此,完成TCP实验

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/408007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# GDI+ 实现图片分隔

1. 概述 有时候我们需要在web页面上显示一张图&#xff0c;比如说一张地图&#xff0c;而这张地图会比较大。这时候如果我们把一张大图分隔成一组小图&#xff0c;那么客户端的显示速度会明显地感觉块。希望阅读本文对你有所帮助。 2. 实现思路 .NET Framework GDI 为我们提…

c/c++面试试题(一)

1.求下面函数的返回值&#xff08;微软&#xff09;int func(x) { int countx 0; while(x) { countx ; x x&(x-1); } return countx; } 假定x 9999。 答案&#xff1a;8思路&#xff1a;将x转化为2进制&#xff0c;看含有的1…

2. Get the codes from GIT

Clone the code from git. Click the “GitEx Clone”. Paste the url into the “Repository to clone”. You can get the route from git repository from it: https://msstash.companydomainname.com/ .Find the project which you want to download and then click the “…

The Ranges Library (2) --- C++20

The Ranges Library (2) — C20 比较std与std::ranges算法 比较一下std::sort和std::ranges::sort std::sort template< class RandomIt > constexpr void sort( RandomIt first, RandomIt last );template< class ExecutionPolicy, class RandomIt > void sor…

WPF中的动画

WPF中的动画 周银辉动画无疑是WPF中最吸引人的特色之一&#xff0c;其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互。这里我们讨论一下故事板。在WPF中我们采用Storyboard&#xf…

[访问系统] Api_Win32_Mac类工具包 (转载)

点击下载 Api_Win32_Mac.zip using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices;namespace BaseFunction {class API{[DllImport("kernel32")]//内存public static extern void GlobalM…

constexpr 函数

constexpr 函数 — C 20 constexpr double pi 3.14;constexpr允许你在编译时使用典型的C函数语法进行编程,但这并不意味之constexpr只和编译期有关 constexpr函数可以在编译期运行,也可以在运行时运行 但在以下情况constexpr函数必须在编译期运行: constexpr函数在编译的上…

constexpr和consteval --- C++ 20

constexpr和consteval — C 20 标准库容器和算法库对constexpr 的应用 C20 中大量的算法和容器可以使用constexpr,这意味着你甚至可以再编译期vector<int>进行排序 Algorithms library - cppreference.com 如下: #include <iostream> #include <ranges>…

函数模板(参考《C++ Templates 英文版第二版》)

函数编程(参考《C Templates 英文版第二版》) Chapter 1 函数模板 1.1 一窥函数模板 template<class T> T max(T a, T b) {return b < a ? a : b; }#include "max1.hpp" #include <iostream> #include <string> #include <format>int…

Curiously Recurring Template Pattern奇怪的模板递归 --- C++20

Curiously Recurring Template Pattern 奇怪的模板递归 — C20 我们都知道C有静态多态和动态多态,动态多态通过虚函数表实现,他的缺点就是对效率产生一点点影响 可以用CRTP解决这个问题 我们先举一个动态多态的例子: #include <iostream> using namespace std;class …

PROJECT #0 - C++ PRIMER [CMU 15-445645]笔记

PROJECT #0 - C PRIMER [CMU 15-445/645]笔记 这是数据库领域的一门课程, 由卡内基梅隆大学副教授Andy Pavlo授课, 目前在网上有授课视频资料、实验以及配套的在线测评环境 (限时开放至2021年12月31日) 环境: wsl2 Clion Project #0 - C Primer 还是很简单的,主要目的是让…

简单JS实现对表的行的增删

这段代码非常的简单&#xff0c;仅仅作为自己的一个小小的记录&#xff01; ok&#xff0c;先上一个简单的图例&#xff0c;效果如下&#xff08;注意&#xff1a;这只是一个简单的例子&#xff0c;不过可以根据这个简单的例子&#xff0c;变化出更为复杂的效果&#xff09;&am…