Stanford CS144 lab4
-
总览
- 一个TCP endpoint(TCPConnection)是TCPSender与TCPReceiver的结合体
- TCPConnection的segment可以被放入UDP的数据包中或则IP的数据包中
- 这个lab最后会基于实现的TCPConnection,给出一个叫做CS144TCPSCocket类,并基于此修改之前写的webget
-
TCPConnection的接收发送策略
- 接受方
- 如果接受到的报文
RST置位,此时需要切断连接,把出入端(in/outbound)设置到错误状态 TCPReceiver检查收到的报文段这些字段:seqno,SYN,payload,FIN- 如果接受到的报文中
ACK置位(一般建立连接后,都是启用状态),那么接受方需要查看ackno与window_size字段 - 如果传来的报文占据了序列号,那么
TCPConnection需要确保至少有一个回应报文,并且其中设置好了正确的ackno和window size - 这一段表示需要用到之前的写好的
send_empty_segment()![]()
- 如果接受到的报文
- 发送方
- 对于发送出(outgoing)的报文,需要设置好相关字段
- 发送报文时,一并发送确认,设置好
ackno与window_size,并置位ACK,这应该是捎带确认(piggybacking)
- 时间处理
TCPConnection需要告诉调用tick函数的TCPSender距离上一次调用经过的时间- 当
consecutive retransmissions超过一个阈值TCPConfig::MAX RETX ATTEMPTS,终止连接,发送一个置位RST报文 - ?
![]()
- 接受方
-
TCP connection的结束, 涉及到一致性问题
- 有两种连接结束的方式,第一种是
unclean shutdown,也就发送或者接受置位了RST的报文,这种情况下in/outbound的ByteStream都应该被置为error状态,且active()立即返回false - 第二种是
clean shutdown,由于两军问题Two Generals Problem, TCP并不能完全实现一个clean shudown- 对于一个
clean shutdown有四个先置条件,1inbound字节流完全被push并被重组,2outbound字节流被完全出去了,也就是说fin包被发送出去了,3outbound字节已经被遥远的对等实体完全确认了,4本地的对等实体自信的认为遥远的对等实体满足条件3 - 另外关闭时有两种情况,一种是主动关闭,一种时被动关闭,当然这里的关闭
close是对于一端来说的,关闭后自己就可以不发数据了,主动关闭,需要lingering2MSL(lab里是10 × cfg.rt timeout),
,而被动关闭不需要,这里作为附加题,我认为是由于对方先把FIN包发送给过来了,并且作为被动关闭者只要接收到了对方的对于自己的FIN包的ack就能确保关闭
但是这段话意味着什么,应该是指对方过早的发送完字节流并且完全被上方应用接受了,那么就完全不需要对方的重传了,这时候就不需要lingering,但是这能够确保对方收到了己方对于对方FIN的ack吗?![]()
- 对于一个
- 有两种连接结束的方式,第一种是
-
实现
- 对于
segment_received函数,- 涉及到
_sender的ack确认与窗口的修改,也就输是TCPSender::ack_received,修改完对方窗口的大小,_sender需要相应的发送数据; - 另外还需要
_receiver把数据上传到inbound stream,也就是调用TCPReceiver::segment_received
- 涉及到
- 对于
-
实现中遇到的问题
-
面向测试编程,由于测试用例过多(162个),把输出重定向到
lab4.log中 -
对于置位
RST报文的发送,如果_sender中_segement_out容量为空,那么需要添加一个empty segment![]()
![]()
-
kills the connection permanently是指发送rst![]()
-
![]()
-
这个测试用例是双方
同时打开,也就是双方都作为主动发起方,并且这里与《TCP/IP 详解》中描述的不一致,这中情况下,对于第二次握手可以不需要置位SYN了![]()
-
关于如何测试单个用例
![]()
-
注意需要删除打印语句
![]()
-
吞吐量测试没过,开始排查
lab1中用了unorered_map,太慢,很多人都用set
对于std::__detail::_Map_base,减少map索引查找的时间,unordered_map由于是链表存储,最坏的取可以到达O(n)![]()
-
使用
scp命令将本地wsl2项目传递到云服务器上
![]()
-
在ubutun上无法用自己的TCP/IP实现通信,
![]()
-
好吧┭┮﹏┭┮没办法,
lab1 stream_reassembler只能够用set重写了 -
另外更好的优化是在
lab0中用BufferList来当作ByteStream的容器,把 ByteStream 类中字节流的容器由 Lab0 最初的 std::list_stream{}; 改为 BufferList _stream{},具体的优化 profile,参见这里 -
几张比较有用的图
![]()
![]()
![]()
-



,而被动关闭不需要,这里作为附加题,
但是这段话意味着什么,







lab1中用了







浙公网安备 33010602011771号