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,一经查实,立即删除!

相关文章

unity2D技术学习与整理

目前有关unity2D的教程以及原理几乎都是国外的。我在这方面也是新手&#xff0c;看了一些例子有很多不懂的地方。 这个网站提供的教程很有参考价值 http://brackeys.com/ 还有这个 http://pixelnest.io/tutorials/2d-game-unity/table-of-contents/转载于:https://www.cnblogs.…

C# GDI+ 实现图片分隔

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

让人吐血的文章,要被气死了

来源&#xff1a;[url]http://dx.3800hk.com/news/w21/124454.html[/url]请注意文中这两部分新世纪&#xff1a;为什么在李俊落网之前&#xff0c;很多人都怀疑这是杀毒软件公司的人干的&#xff0c;目的是为了多卖几套杀毒软件&#xff1f;李铁军&#xff1a;人们一直都有这种…

共享锁和排它锁---C++17 多线程

共享锁和排它锁—C17 多线程 读写锁把对共享资源的访问者划分成读者和写者&#xff0c;读者只对共享资源进行读访问&#xff0c;写者则需要对共享资源进行写操作。C17开始&#xff0c;标准库提供了shared_mutex类&#xff08;在这之前&#xff0c;可以使用boost的shared_mutex…

将人民币的数字表示转化成大写表示(C#版)

using System; namespace Test.Com{ /// <summary> /// 功能&#xff1a;字符串处理函数集 /// </summary> public class DealString { #region 私有成员 /// <summary> /// 输入字符串 /// </summary> private string inputStringnull; /// <…

C#图片切割

图片切割就是把一幅大图片按用户要求切割成多幅小图片。dotnet环境下系统提供了GDI类库&#xff0c;为图像操作处理提供了方便的接口。 下面是图像切割小程序&#xff1a; public class ImageManager { /// <summary> /// 图像切割 /// </s…

条件变量 ---C++17 多线程

条件变量 —C17 多线程 C标准库提供了条件变量的两种实现&#xff1a;std::condition_variable 和std::condition_variable_any。它们都在标准库的头文件<condition_variable>内声明。两者都需配合互斥&#xff0c;方能提供妥当的同步操作。std::condition_variable仅限…

关于在asp.net中textbox文本输入框中的汉语标点符号显示位置的问题

在asp.net中的服务器控件textbox中输入中文标点符号&#xff0c;位置处于输入框中间&#xff0c;而不是靠在左下角&#xff0c;解决办法&#xff1a;把字体样式设置为其它&#xff0c;比如&#xff1a;微软雅黑。这个问题&#xff0c;仅在宋体的时候出现过。 转载于:https://ww…

考验

如果不做网站&#xff0c;可以做着不错的工作&#xff0c;过着安逸的生活&#xff0c;可是&#xff0c;我不想年老的时候后悔&#xff1a;这一生竟然没有为自己的理想拼搏过!仅这一个理由&#xff0c;足以让我坚强地面对任何考验!博客园的发展需要付出更多努力&#xff0c;开始…

汇编常用命令、指令一览

MOV&#xff08;MOVe&#xff09; 传送指令P28 PUSH 入栈指令P32 POP 出栈指令P33 XCHG&#xff08;eXCHanG&#xff09; 交换指令P34 XLAT&#xff08;TRANSLATE&#xff09; 换码指令P34 LEA &#xff08;Load Effective Address&#xff09; 有效地址送…

std::future ---C++17 多线程

std::future —C17 多线程 std::future C标准程序库使用future来模拟这类一次性事件&#xff1a;若线程需等待某个特定的一次性事件发生&#xff0c;则会以恰当的方式取得一个future&#xff0c;它代表目标事件&#xff1b;接着&#xff0c;该线程就能一边执行其他任务&#…

VNCserver在Fedora上配置过程

前言&#xff1a;一直想写一下vncserver在redhat下详细配置过程&#xff0c;以帮助一些向我有同样需求却有懒得去读man page的朋友&#xff0c;后来在www.fedoranews.org上发现已经有人写了一个教程&#xff0c;并且还不错。干脆翻译算了。大家可以直接去阅原文&#xff0c;我这…

学好英语的42个经典要诀(完整版)

第一要诀&#xff1a;收听英语气象报告 有些教学录音带为配合初学者的学习&#xff0c;故意放慢语速&#xff0c;这对英语听力的训练是不够的。如果听语速正常的英语&#xff0c;初学者又会感到力不从心。英语气象报告的速度虽快&#xff0c;但词汇简单固定&#xff0c;内容单纯…

std::packaged_task() ---C++17 并发编程

std::packaged_task() —C17 并发编程 std::packaged_task<>连结了future对象与函数&#xff08;或可调用对象&#xff09;。 std::packaged_task<>对象在执行任务时&#xff0c;会调用关联的函数&#xff08;或可调用对象&#xff09;&#xff0c;把返回值保存为…

js分页--存储数据并进行分页

//分页方法var page function(){this.v {o:null,//ul父级层home:null,previous:null,next:null,last:null, list:[],pageSize:10,pageIndex:0,pageCount:0,rowCount:0};this.init function(){var _this this;_this.v.o.find("li").each(function(i,o){_this.v.…

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…