CS144-lab0

2023/02/01 Blog CS144 计算机网络 共 16767 字,约 48 分钟

环境准备

  1. 实验资料,包括实验手册以及PPT

  2. 环境配置

    2.1申请EC2

    ​ 在lab0的实验手册中有不同的实验环境配置方案,这里我选择使用更方便的AWS的EC2。AWS为新用户提供为期一年的免费使用,需要使用Visa等信用卡注册,在国内也可以使用银联信用卡注册。注册以后申请EC2实例,选择Ubuntu version 18.04 LTS系统,登陆方式可以选择秘钥登陆或者密码登陆,如果未创建过秘钥对,选择创建秘钥对后会将私钥下载到本地。在安全组配置处开放SSH、SMTP、POP3、HTTP、HTTPS、ICMP等服务端口,当然也可以在实例启动以后再修改安全组规则。如果未开放SSH端口,则无法通过SHELL远程连接服务器,所以最好在申请实例时候一次性将所有需要端口配置好。

    2.2连接EC2

    ​ 使用SHELL连接服务器,WindTerm)是一款颜值高,且支持类似tmux和cmder分屏的工具。选择会话,新建会话,主机处输入IP地址,其余可根据个人喜好选择是否填写,然后弹出输入用户,用户名为ubuntu,EC2默认不允许远程使用root登陆,确认后选择秘钥路径然后登陆。

    image-20230124115551210

    在连接处AWS默认用户名为ubuntu,出于方便可配置用root用户登陆,也可以使用su -i或su root切换到root。

    2.3配置EC2

    ​ 2.3.1开启root用户登陆 ​ sudo passwd root可直接设置root用户的密码。 ​ su root输入设置的密码切换至root. ​ 2.3.2编辑 sshd 服务配置文件: ​ vi /etc/ssh/sshd_config ​ 将PermitRootLogin 设置为yes, ​ 确保passwordAuthenticationyes. ​ 保存后重启sshd服务service sshd restart或者/bin/systemctl restart sshd.service即可。

    ​ 2.3.3配置实验依赖工具

    ​ 首先执行apt-get update更新apt-get版本和软件源。

    ​ 实验手册中给出了没有使用prepared image的安装说明,使用EC2服务器只需安装依赖的工具,官方已经给出了安装脚本

    wget https://web.stanford.edu/class/cs144/vm_howto/setup_dev_env.sh

    bash ./setup_dev_env.sh

    2.4构建Sponge项目Sponge quickstart

    git clone https://github.com/cs144/sponge
    cd sponge
    mkdir build
    cd build
       
    cmake ..
    make -j$(nproc)
    

构建项目中可能会出现以下报错

/home/ubuntu/cs144/sponge/libsponge/util/parser.cc:36:13: error: shift count >= width of type [-Werror,-Wshift-count-overflow]
        ret <<= 8;
            ^   ~
将 ret <<=8; 换成 ret = ret << 8 即可正常运行

任务一:获取一个网页

我在EC2上安装了nginx,其默认自带静态首页,使用http协议通过浏览器访问我的EC2站点,结果如下,如果没有域名也可以直接使用http://ip来访问站点

image-20230124152502482

通过telnet获取网页

root@ip-172-31-12-241:~# telnet 127.0.0.1 http
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
GET /index.html HTTP/1.1
Host: localhost
Connection: close

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Tue, 24 Jan 2023 07:34:02 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 17 Apr 2018 15:22:36 GMT
Connection: close
ETag: "5ad6113c-264"
Accept-Ranges: bytes

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Connection closed by foreign host.

Assignment: Now that you know how to fetch a Web page by hand, show us you can! Use the above technique to fetch the URL http://cs144.keithw.org/lab0/sunetid, replacing sunetid with your own primary SUNet ID. You will receive a secret code in the X-Your-Code-Is: header. Save your SUNet ID and the code for inclusion in your writeup.

root@ip-172-31-12-241:~# telnet cs144.keithw.org http
Trying 104.196.238.229...
Connected to cs144.keithw.org.
Escape character is '^]'.
GET /lab0/gaozhiyuan HTTP/1.1
Host: cs144.keithw.org
Connection: close

HTTP/1.1 200 OK
Date: Tue, 24 Jan 2023 07:44:34 GMT
Server: Apache
X-You-Said-Your-SunetID-Was: gaozhiyuan
X-Your-Code-Is: 375453
Content-length: 114
Vary: Accept-Encoding
Connection: close
Content-Type: text/plain

Hello! You told us that your SUNet ID was "gaozhiyuan". Please see the HTTP headers (above) for your secret code.
Connection closed by foreign host.

任务二:发送邮件

邮件由三部分组成,用户代理、邮件传输代理、邮件分发代理

1.环境准备,选择使用postfix作为邮件传输代理,安全规则放行SMTP 25端口,POP3 110端口,IMAP 143端口

2.域名解析,在域名解析服务商处添加A记录,MX记录,CNAME记录

3.使用nslookup -type=MX mydomain.com或者dig mx mydomain.com查看解析是否生效

4.安装postfix

apt-get install postfix

在安装过程中会提示postfix配置

  • No configuration:表示不要做任何配置;

  • Internet Site:表示直接使用本地SMTP服务器发送和接收邮件;

  • Internet with smarthos: 表示使用本地SMTP服务器接收邮件,但发送邮件时不直接使用本地SMTP服务器,而是使用第三方smart host来转发邮件;

  • Satellite system:表示邮件的发送和接收都是由第三方smarthost来完成。

  • Local only:表示邮件只能在本机用户之间发送和接收。

然后会提示域名配置,输入mydomain.com

安装完成后查看端口监听情况:

root@ip-172-31-12-241:~# netstat -anptl | grep 25
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      2267/master         
tcp6       0      0 :::25                   :::*                    LISTEN      2267/master     

可以看到SMTP 25端口正常监听

5.使用telnet测试收发邮件

#新建用户并设置密码
useradd -m -s /bin/bash gaozhiyuan
passwd gaozhiyuan
#输入密码

#测试SMTP25端口是否打开
telnet localhost 25
#输出如下说明正常
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 ip-172-31-12-241.ap-northeast-1.compute.internal ESMTP Postfix (Ubuntu)

#测试收发邮件
telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 ip-172-31-12-241.ap-northeast-1.compute.internal ESMTP Postfix (Ubuntu)

ehlo localhost
250-ip-172-31-12-241.ap-northeast-1.compute.internal
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8

mail from: root@csmasterpath.top
250 2.1.0 Ok

rcpt to: gaozhiyuan@csmasterpath.top
250 2.1.5 Ok

data
354 End data with <CR><LF>.<CR><LF>
Subject: Test Mail
Hi, gaozhiyuan! This is a test e-mail. I'm your e-mail server manager!
.
250 2.0.0 Ok: queued as DDDB1824FD

quit
221 2.0.0 Bye
Connection closed by foreign host
#到此邮件已经发送到gaozhiyuan@csmasterpath.top,切换到gaozhiyuan查看
su gaozhiyuan
#查看收件箱
mail
"/var/mail/gaozhiyuan": 1 message 1 new
>N   1 root@csmasterway.t Tue Jan 24 08:26  12/585   Test Mail
? 

#输入数字查看收到的邮件
? 1
Return-Path: <root@csmasterpath.top>
X-Original-To: gaozhiyuan@csmasterpath.top
Delivered-To: gaozhiyuan@csmasterpath.top
Received: from localhost (localhost [127.0.0.1])
        by ip-172-31-12-241.ap-northeast-1.compute.internal (Postfix) with ESMTP id DDDB1824FD
        for <gaozhiyuan@csmasterpath.top>; Tue, 24 Jan 2023 08:24:21 +0000 (UTC)
Subject: Test Mail
Message-Id: <20230124082442.DDDB1824FD@ip-172-31-12-241.ap-northeast-1.compute.internal>
Date: Tue, 24 Jan 2023 08:24:21 +0000 (UTC)
From: root@csmasterpath.top

Hi, gaozhiyuan! This is a test e-mail. I'm your e-mail server manager!

#退出
?quit
Saved 1 message in /home/gaozhiyuan/mbox
Held 0 messages in /var/mail/gaozhiyuan

062785  3  307

测试用qq邮箱发送邮件到gaozhiyuan@csmasterpath.top

image-20230124180347554

查看结果

#当前在gaozhiyuan用户
mail
gaozhiyuan@ip-172-31-12-241:~$ mail
"/var/mail/gaozhiyuan": 1 message 1 new
>N   1 1428272985@qq.com  Tue Jan 24 08:35  69/3426  Test Mail
? 

#查看邮件
?1
Return-Path: <1428272985@qq.com>
X-Original-To: gaozhiyuan@csmasterpath.top
Delivered-To: gaozhiyuan@csmasterpath.top
Received: from out162-62-57-49.mail.qq.com (out162-62-57-49.mail.qq.com [162.62.57.49])
        by ip-172-31-12-241.ap-northeast-1.compute.internal (Postfix) with ESMTPS id 0A0D9824FD;
        Tue, 24 Jan 2023 08:35:56 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512;
        t=1674549353; bh=/fqKGf5ndjblJ8iuoR8ElmrgZ0YeFP5GJs10BbhET0o=;
        h=Date:From:To:Cc:Subject;
        b=tDPxc3JALzwyKAHCIgaENZR9Yy4i8sy/gShsnoDvVxv/vOtPxMU2L62BS0A301pux
         cZ/+jCl0yvmLz+JgaQ1a+lAtlyVDD2fQ2jdTD6mHmIQJPSQr2tZFVoV3387+d0eGGi
         h/j5Jt9zQHzQDhKDdP5/10tuoKnu0ngkt6qxSfTM=
Received: from DESKTOP-656JFJI ([111.52.51.180])
        by newxmesmtplogicsvrszc2-0.qq.com (NewEsmtp) with SMTP
        id 8F4140A3; Tue, 24 Jan 2023 16:35:52 +0800
X-QQ-mid: xmsmtpt1674549352t5k9frlac
Message-ID: <tencent_C3384D71D826E1EF6BE9C6857F9E08BDE205@qq.com>
X-QQ-XMAILINFO: MTmSu602bpi083hmynJjDf/cBFEEZKBOJXknSaJBHM2KlL3s7quN1B80By2/11
         7oWeO2T4A/qTl2l3s6bFJWof/dPMFFm3T4+fdl3r5qaaMVy35QnCfPL3aUUzp6gGmwWzVz1wfjzb
         iGKrJuZUeJBldmUZmiHE/bR1HFT/q8mtGt6q8c7p6/wk8Iv0FoPsRm2wJSTEvRZ7DVWgMTT1i47j
         QTOe2VB2PYoA5akbhnEeg8+5zLgI/IJNRCUShxaTZ9xKps0GNjVCHuhUfH+VNSv2wvhEAIMys0Ny
         EvSoi1irr4GmaCjdJDd5E7CP6dV0VP7mIrs0nodieneW4mzdZ9P1sUxSWTfEgFrAPfP2SCVWGE8L
         Jyczlp7YCHRXHB/03MQeziuDT6JStIdFpfUqFfo0vpyUKn5Mcc6FZkYbg2bOdUbaccJWQlNOgCSg
         uCt+VyMNt9/qWHcfuzv8zrMvKBOwNGKBA974mWiX2X9sDwYzlao8TIpYbhjyJS6kG4MotmwK2kyY
         DNpSziqhEY84ulLELSlKGUdwwG5/8kf/F8qg+q1bhZ7grPyKfCfaIEr1mXei0HUirV6LnCs2CI9L
         u1ffA5FI4IoTTdgA5/c2UIOOiWVPe7tJ5w7WTV+XkppbZ9t+1WivevUGsSt2EpBiQaNYtVv24aOS
         eHOIrD2a2jKg057T6nfXqXVP933yj16/lQQd7rQBnyoNyPtjYkhF7Pfl5mX8sSTOC8JZlyEvYKcT
         Od4PW7EEmgJwAyJDUdC5uHFLx+R7ZLuW6LxBYfC6r06grwL+SK6YEgYmC5yNLVFcsVgIX2wP6Vam
         IXB2cOub5FrSKEF1aknFtq5YZ3R88oZ+SobJDPn0qAJDHDcblWuacq+scx6uSXZxWCf6uev9x36E
         O+vBLYNQhDJHHe3PgZXeBB5QIPi3uMvpmUXiAUkWGNgnf0ufiVWuOqqZYYDkJ02hLmk+GTCya9
Date: Tue, 24 Jan 2023 16:35:54 +0800
From: "1428272985@qq.com" <1428272985@qq.com>
To: gaozhiyuan <gaozhiyuan@csmasterpath.top>
Cc: root <root@csmasterpath.top>
Subject: Test Mail
X-Priority: 3
X-GUID: EDA9983B-B8AF-4C07-B414-4545E99D0F80
X-Has-Attach: no
X-Mailer: Foxmail 7.2.25.178[cn]
Mime-Version: 1.0
X-OQ-MSGID: <202301241635540061581@qq.com>
Content-Type: multipart/alternative;
        boundary="----=_001_NextPart522038763015_=----"

This is a multi-part message in MIME format.

------=_001_NextPart522038763015_=----
Content-Type: text/plain;
        charset="us-ascii"
Content-Transfer-Encoding: base64

DQpTZW5kIGEgdGVzdCBlLW1haWwgZnJvbSBxcS5jb20gdG8gY3NtYXN0ZXJ3YXkudGVjaA0KDQoN
CjE0MjgyNzI5ODVAcXEuY29tDQo=

------=_001_NextPart522038763015_=----
Content-Type: text/html;
        charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html><head><meta http-equiv=3D"content-type" content=3D"text/html; charse=
t=3Dus-ascii"><style>body { line-height: 1.5; }body { font-size: 14px; fon=
t-family: "Microsoft YaHei UI"; color: rgb(0, 0, 0); line-height: 1.5; }</=
style></head><body>=0A<div><span></span><br></div>=0A<div>Send a test e-ma=
il from qq.com to csmasterpath.top</div><hr style=3D"WIDTH: 210px; HEIGHT:=
 1px" color=3D"#b5c4df" size=3D"1" align=3D"left">=0A<div><span><div style=
=3D"MARGIN: 10px; FONT-FAMILY: verdana; FONT-SIZE: 10pt"><div>1428272985@q=
q.com</div></div></span></div>=0A</body></html>
------=_001_NextPart522038763015_=------

#查看抄送到root的邮件
root@ip-172-31-12-241:~# mail
"/var/mail/root": 1 message 1 new
>N   1 1428272985@qq.com  Tue Jan 24 08:35  69/3414  Test Mail
? 1
Return-Path: <1428272985@qq.com>
X-Original-To: root@csmasterpath.top
Delivered-To: root@csmasterpath.top
Received: from out162-62-57-49.mail.qq.com (out162-62-57-49.mail.qq.com [162.62.57.49])
        by ip-172-31-12-241.ap-northeast-1.compute.internal (Postfix) with ESMTPS id 0A0D9824FD;
        Tue, 24 Jan 2023 08:35:56 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512;
        t=1674549353; bh=/fqKGf5ndjblJ8iuoR8ElmrgZ0YeFP5GJs10BbhET0o=;
        h=Date:From:To:Cc:Subject;
        b=tDPxc3JALzwyKAHCIgaENZR9Yy4i8sy/gShsnoDvVxv/vOtPxMU2L62BS0A301pux
         cZ/+jCl0yvmLz+JgaQ1a+lAtlyVDD2fQ2jdTD6mHmIQJPSQr2tZFVoV3387+d0eGGi
         h/j5Jt9zQHzQDhKDdP5/10tuoKnu0ngkt6qxSfTM=
Received: from DESKTOP-656JFJI ([111.52.51.180])
        by newxmesmtplogicsvrszc2-0.qq.com (NewEsmtp) with SMTP
        id 8F4140A3; Tue, 24 Jan 2023 16:35:52 +0800
X-QQ-mid: xmsmtpt1674549352t5k9frlac
Message-ID: <tencent_C3384D71D826E1EF6BE9C6857F9E08BDE205@qq.com>
X-QQ-XMAILINFO: MTmSu602bpi083hmynJjDf/cBFEEZKBOJXknSaJBHM2KlL3s7quN1B80By2/11
         7oWeO2T4A/qTl2l3s6bFJWof/dPMFFm3T4+fdl3r5qaaMVy35QnCfPL3aUUzp6gGmwWzVz1wfjzb
         iGKrJuZUeJBldmUZmiHE/bR1HFT/q8mtGt6q8c7p6/wk8Iv0FoPsRm2wJSTEvRZ7DVWgMTT1i47j
         QTOe2VB2PYoA5akbhnEeg8+5zLgI/IJNRCUShxaTZ9xKps0GNjVCHuhUfH+VNSv2wvhEAIMys0Ny
         EvSoi1irr4GmaCjdJDd5E7CP6dV0VP7mIrs0nodieneW4mzdZ9P1sUxSWTfEgFrAPfP2SCVWGE8L
         Jyczlp7YCHRXHB/03MQeziuDT6JStIdFpfUqFfo0vpyUKn5Mcc6FZkYbg2bOdUbaccJWQlNOgCSg
         uCt+VyMNt9/qWHcfuzv8zrMvKBOwNGKBA974mWiX2X9sDwYzlao8TIpYbhjyJS6kG4MotmwK2kyY
         DNpSziqhEY84ulLELSlKGUdwwG5/8kf/F8qg+q1bhZ7grPyKfCfaIEr1mXei0HUirV6LnCs2CI9L
         u1ffA5FI4IoTTdgA5/c2UIOOiWVPe7tJ5w7WTV+XkppbZ9t+1WivevUGsSt2EpBiQaNYtVv24aOS
         eHOIrD2a2jKg057T6nfXqXVP933yj16/lQQd7rQBnyoNyPtjYkhF7Pfl5mX8sSTOC8JZlyEvYKcT
         Od4PW7EEmgJwAyJDUdC5uHFLx+R7ZLuW6LxBYfC6r06grwL+SK6YEgYmC5yNLVFcsVgIX2wP6Vam
         IXB2cOub5FrSKEF1aknFtq5YZ3R88oZ+SobJDPn0qAJDHDcblWuacq+scx6uSXZxWCf6uev9x36E
         O+vBLYNQhDJHHe3PgZXeBB5QIPi3uMvpmUXiAUkWGNgnf0ufiVWuOqqZYYDkJ02hLmk+GTCya9
Date: Tue, 24 Jan 2023 16:35:54 +0800
From: "1428272985@qq.com" <1428272985@qq.com>
To: gaozhiyuan <gaozhiyuan@csmasterpath.top>
Cc: root <root@csmasterpath.top>
Subject: Test Mail
X-Priority: 3
X-GUID: EDA9983B-B8AF-4C07-B414-4545E99D0F80
X-Has-Attach: no
X-Mailer: Foxmail 7.2.25.178[cn]
Mime-Version: 1.0
X-OQ-MSGID: <202301241635540061581@qq.com>
Content-Type: multipart/alternative;
        boundary="----=_001_NextPart522038763015_=----"

This is a multi-part message in MIME format.

------=_001_NextPart522038763015_=----
Content-Type: text/plain;
        charset="us-ascii"
Content-Transfer-Encoding: base64

DQpTZW5kIGEgdGVzdCBlLW1haWwgZnJvbSBxcS5jb20gdG8gY3NtYXN0ZXJ3YXkudGVjaA0KDQoN
CjE0MjgyNzI5ODVAcXEuY29tDQo=

------=_001_NextPart522038763015_=----
Content-Type: text/html;
        charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html><head><meta http-equiv=3D"content-type" content=3D"text/html; charse=
t=3Dus-ascii"><style>body { line-height: 1.5; }body { font-size: 14px; fon=
t-family: "Microsoft YaHei UI"; color: rgb(0, 0, 0); line-height: 1.5; }</=
style></head><body>=0A<div><span></span><br></div>=0A<div>Send a test e-ma=
il from qq.com to csmasterpath.top</div><hr style=3D"WIDTH: 210px; HEIGHT:=
 1px" color=3D"#b5c4df" size=3D"1" align=3D"left">=0A<div><span><div style=
=3D"MARGIN: 10px; FONT-FAMILY: verdana; FONT-SIZE: 10pt"><div>1428272985@q=
q.com</div></div></span></div>=0A</body></html>
------=_001_NextPart522038763015_=------

测试使用gaozhiyuan@csmasterpath.top发送邮件给1428272985@qq.com

gaozhiyuan@ip-172-31-12-241:/root$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 ip-172-31-12-241.ap-northeast-1.compute.internal ESMTP Postfix (Ubuntu)
ehlo localhost
250-ip-172-31-12-241.ap-northeast-1.compute.internal
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8
mail from: gaozhiyuan@csmasterpath.top
250 2.1.0 Ok
rcpt to:1428272985@qq.com
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
Subject:Test Mail
This is a test e-mail from gaozhiyuan@csmasterpath.top
.
250 2.0.0 Ok: queued as 611C4824FD
quit
221 2.0.0 Bye
Connection closed by foreign host.

此时已经显示发送成功但是在QQ邮箱中并未收到邮件,原因EC2默认封禁了SMTP 25端口出方向流量,需要根据AWS官方的说明申请解封25端口。

2.2:使用telnet建立通信

image-20230124202239693

任务三:使用OS stream socket实现一个网络程序

这里和上述通过telnet客户端获取网页是一样的流程。

TCPSocket socket{};
socket.connect(Address(host,"http"));
socket.write("GET " + path + " HTTP/1.1\r\nHost: " + host + "\r\n\r\n");
socket.shutdown(SHUT_WR);
while(!socket.eof())
{
    cout << socket.read();
}
socket.close();

任务四:实现内存中的支持读写的可靠字节流

​ 根据实验手册,此测试只有单台主机。字节流可以从输入方写入,从输出方读出,当读取到“EOF”(end of file)时候,表示当前已经没有可以被读取的字节流。首先想到的就是先入先出的队列,如果将数组封装成循环队列,这样不仅能够提高效率,内存也能够充分利用。但是实验手册要求使用“Modern C++”,尽量避免使用普通指针,同时为使用对象的方法从而方便输入和读取操作,选用deque。

byte_stream.hh

class ByteStream {
  private:
    // Your code here -- add private members as necessary.
    // Init reading and writing memory that will be used to communicate.
    std::deque<char> _buffer{};
    // The memory capacity.
    size_t _capacity{0};
    // The bytes num that writer has written into the memory.
    size_t _written_bytes{0};
    // The bytes num that reader has read from the memory.
    size_t _read_bytes{0};
    //!< Flag indicating that the input byte stream is finished.
    bool _input_ended{false};
    bool _error{false};  //!< Flag indicating that the stream suffered an error.
}

byte_stram.cc

//Init he memory capacity
ByteStream::ByteStream(const size_t capacity) :_capacity{capacity}{}

size_t ByteStream::write(const string &data) {
    if(_input_ended){
        return 0;
    }
    // Only the minimum between remaining capacity and the data size can be written into the buffer.
    size_t written_len = 0;
    data.size() >= remaining_capacity() ? written_len = remaining_capacity() : written_len = data.size();
    _buffer.insert(_buffer.end(),data.begin(),data.begin() + written_len);
    _written_bytes += written_len;
    return written_len;
}

//! \param[in] len bytes will be copied from the output side of the buffer
string ByteStream::peek_output(const size_t len) const {
   // Only the maximum between the parameter len and the maximum amount that can currently be peeked/read can be peeked.
   size_t peeked_len = 0;
   len >= _buffer.size() ? peeked_len = _buffer.size() : peeked_len = len;
   return string(_buffer.begin(),_buffer.begin() + peeked_len);
}

//! \param[in] len bytes will be removed from the output side of the buffer
void ByteStream::pop_output(const size_t len) {
     //Only the maximum between the parameter len and the maximum amount that can currently be peeked/read can be popped.
    size_t popped_len = 0;
    len >= buffer_size() ? popped_len = buffer_size() : popped_len = len;
    _buffer.erase(_buffer.begin(),_buffer.begin() + popped_len);
    _read_bytes += popped_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(res.size());
    return res;
}
// Signal that the byte stream has reached its ending
void ByteStream::end_input() {_input_ended = true;}
// `true` if the stream input has ended
bool ByteStream::input_ended() const { return _input_ended; }
// the maximum amount that can currently be peeked/read
size_t ByteStream::buffer_size() const { return _buffer.size(); }
// `true` if the buffer is empty
bool ByteStream::buffer_empty() const { return _buffer.empty(); }
// `true` if the output has reached the ending
bool ByteStream::eof() const { return input_ended() && buffer_empty();}
// Total number of bytes written
size_t ByteStream::bytes_written() const { return _written_bytes; }
// Total number of bytes popped
size_t ByteStream::bytes_read() const { return _read_bytes; }
// Returns the number of additional bytes that the stream has space for
size_t ByteStream::remaining_capacity() const { return _capacity - _buffer.size();}

参考链接:

文档信息

Search

    Table of Contents