设计思路
说明
该项目实现了TCP协议的一个简单版本(不包括流量控制和)。它使用了由Fishnet提供的链接层API和网络拓扑仿真。
实现TCP协议的核心代码在TCPSock.java和TCPManager.java中
打印原理
- Node初始化的时候就会同时初始化一个TCPManage。当一个包到达node后,manage就会调用node的onReceive,当识别到是传输数据的数据包后就会调用
TCPManage的onReceive,并传参包括源地址,目的地址和数据段。 - TCPManage起到一个总管的作用。这时候onReceive就会从报文段中获得源和目的的端口,看一下已经存在的TCPSock里面有没有已经有相同的地址和端口的TCP连接,没有的话就查找是否有相同端口和本地地址的正在监听。到最后有找到的话就调用TCPSock的onRecieve,没有就给出错误提示。
- TCPSock的onRecieve就是进行分辨传输数据段的类型,并根据不同的数据段类型给出不同的函数跳转,不同的函数就会打印对应的字符
字符打印思路
1.发送方打印。发送方发送请求同步时打印一个"S",发送结束连接请求时打印一个“F”,发送数据时打印“.”。计时器超时后重发数据时打印“!”。因为timeout为静态固定值,所以基本会重发数据,所以发送方的打印字符通常会“.”和“!”相连。发送方接收到接收方的ACK也会打印一个“:”。
2.接收方打印。接收方接收到SYN同步请求时也会打印一个“S”,接收到结束连接请求时也会打印一个“F”,接收到数据时会先打印一个“.”表示收到数据,然后紧接着打印一个“:”表示发送对该序列号的数据的确认,所以接收方通常会“.”和“:”相连。当收到的数据不等于recv_next时将会打印一个“!”。而问号则是其他未说明的情况。
打印如图

发送数据思路
这里send需要封装一个Transport通过TCPManage来发送数据。
停等协议思路
- 因为这里主要先测试打印以及序列号的初步使用,所以这里先使用最简单的停等协议。等到后面拥塞和流量控制再使用更长的滑动窗口
- 为了使后续转化更为方便,停等协议将设计成滑动窗口协议的简化版。
- 使用send_begin和send_next分别代表单个滑动窗口的发送未确认和下一个准备发送的序列号。在receiveACK中,当收到接收方的确认字号后就会将send_begin等于ack_num,这里的ack_num就等于send_begin+1,在之后的sendData里又会将send_begin和send_next进行一个同步。
- 停等协议中的超时重发主要有两个,一个是请求同步的重发,当超过一定时间没收到对于SYN的ACK后,就会重发一个SYN。另一个是重发数据,发送方发送每个序列号后都会开启该序列号的计时器,当计时器结束后还未收到该序列号就会进入resendData,将会重新更新send_begin和send_next等于未收到确认的序列号。
TCPManage思路
TCPManage主要实现的是创建TCPSock并进行管理。所以实现了socket的创建,相应事件,发送数据和添加定时器等功能。在接受的相应方法里,TCPManage先检测是否存在对应的TCPSock,存在的话就抛给TCPSock来处理,没有的话将打印错误信息。
其他补充
- 新增状态。为了区分已经结束或者还没初始化过的CLOSED和刚初始化未进行操作CLOSED和已经绑定了端口的CLISED故引入BIND来区分
- 未实现拥塞控制。因为最后的项目才会有拥塞控制,所以在作业四中并未实现,所以数据的timeout为静态可能与实际情况不符导致超时情况未接受较多。同时由于是使用较为简单的停等协议,故信道使用率较低,传输速度较慢。在最后一个项目将改用滑动窗口协议解决上述问题。
- 新增initial实现初始化。新增clean实现关闭后数据的刷新。
函数说明
/*
* 创造一个新的TCPSock
*/
Socket TCPSock()
Socket TCPSock(TCPManager manager)
讨论问题
1a
在选择初始序列号时,最好使用随机值。
- 使用随机初始序列号可以增加协议的安全性,降低遭受网络攻击的风险。如果初始序列号是固定的,攻击者更容易进行序列号的预测和攻击。随机选择初始序列号使得攻击者更难以猜测下一个序列号,提高了连接的安全性。
- 同时,使用随机序列号也能让接收方区别该数据包应该是新的套接字还是以前关闭的。因为这个序列号刚好等于随机的序列号的概率是极低的。
1b
如果受到SYN洪泛攻击,将可能导致我的TCPSock队列处于满的状态,无法接收新的SYN请求。为了更好地抵御这种攻击,可以考虑采取以下措施:
- 使用SYN cookie,在连接还未确立之前不分配资源来响应连接请求以免占用资源
- 使用连接请求限制,限制每个IP地址的连接请求数量,以防止过多的连接请求。
- 增加backlog,增加可以接受的挂起数量,但是这个并不能从根本上解决问题
- 使用三次握手机制而不是简单的连接。
1c
如果发送方传输数据但从未关闭连接,可能导致连接数据泄露以及持续占用空间。为了更好的解决,我想到以下办法
- 使用超时计时器。每次传输数据时都开启一个新的计时器,在一段时间内未检测到数据传输时,可以来自动关闭连接,释放相关资源。
- 使用心跳机制。定期检测连接的活跃性,及时发现未关闭的连接。
2
因为本项目未涉及流量控制,所以本问题将在最后一个项目中回答。(最后一个项目将会同时附上1的三个问题的回答)
输出捕获
图片
图片如下,上方为发送方transfer 0 21 40 100
下方为接收方server 21 2

发送方
$perl fishnet.pl emulate localhost 8888 10001
Node 1: started
transfer 0 21 40 100
bind localPort 40 successfully!
Socket (1:40) connecting to (0:21)
S:Node 1: time = 1705462679441 msec
Node 1: started
Node 1: bytes to send = 100
Node 1: amount=100
.!.!.!.!.:.!.!.!.!.:.!.Node 1: amount=0
Node 1: time = 1705462680450
Node 1: sending completed
Node 1: closing connection...
.!.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.!.!.!.!.:.FFFFFNode 1: time = 1705462720473 msec
Node 1: connection closed
Node 1: total bytes sent = 100
Node 1: time elapsed = 41032 msec
Node 1: Bps = 2.437122246051862
接收方
$perl fishnet.pl emulate localhost 8888 10000
Node 0: started
server 21 2
bind localPort 21 successfully!
Node 0: server started, port = 21
SNode 0: time = 1705462679339 msec
Node 0: connection accepted
.:!!!!.:!!!!.:!!!!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:!!!!.:F.FFFFFFFFFNode 0: time = 1705462721373 msec
Node 0: connection closed
Node 0: total bytes received = 50
1万+

被折叠的 条评论
为什么被折叠?



