这个py文件实现了以滑动窗口来发送文件。
发送原理:二进制读取文件并储存在本地,分组读取的文件,以序列号为标志发送这些分好的包。
测试:本机对本机发送文件,以及本机对局域网内的另外一台机器发送文件。发送的文件:一个1.6MB的JPG文件,一个3.5MB的 MP3文件。
测试结果:文件均完整和正确。传送速度大概 15KB/S。
应对特殊情况:
1.丢包&重复的包。如果发给receiver的包丢掉了,那么根据receiver的机制,返回ACK号将为最小的丢失的包。如果继续发送包,这个ACK号会重复。
当某个包丢失时,返回的重复ACK号不会让窗口继续向下滑动,在接受循环内会根据超时来重发包。通常情况下,丢失的包被补上,ACK更新,窗口继续向下滑动。
如果无论如何发包都返回同一个ACK(比如一直发3号包,对面一直回ACK3),连接将于10秒后断开:窗口超过10秒未滑动。
2.超时。发送某个包超过0.5秒窗口依然没有更新,那么判断为超时。
500ms的自动重发在实际测试中很糟。在一个局域网内,0.5秒的超时重发会带来大量的重发包,让滑动窗口更新极其缓慢。
推测可能的原因:测试时:receiver 会wb文件,可以看成是应用层的调用,如果写文件稍有迟缓,receiver就会拒绝发过来的包。写文件的速度是有差别的,mp3的最后一点数据就特别慢。
最后,为了保证测试的低重发率,timeout被设为1.5s.
3.错误的包或者空包。
Receiver 如果没有任何可以返回的ACK,会给sender一个None值,如果对这个值使用checksum会直接报错,因为空值没法分割。对于空包,判断之后不理会,抛弃掉。
对于错误的包,receiver会在checksum后抛弃掉,并不在receiver中跟新序号的值,就好像它没有收到这个包一样。返回后,receiver会按丢包处理。
4.100%丢包。
由于窗口没有更新,超过10s会断开。
如果小于10s,会被超时函数判断出来,重发。这个超时函数写了5个,最大窗口就是5个,会100%覆盖,不会漏掉某一个超时的包。
5.误差分析。
这个程序的误差还是稍大的,为了保证低重发率,response = self.receive(1)被写在了0.1秒的接收循环(循环2)内,如果receive()中的参数改低,实际测试时就有大量的空包被返回。这也影响了超时函数,最坏的情况是超时了过后1秒才重新发送包。我认为保证了低重发率,这个1秒的最坏延时还是可以接受的。
其他:
发送过程:Sender内。初始化发送序列号,窗口号,关键的计时。分别设为0,当前时间。
1.发送内是一个while循环, 序列号<窗口号+5 ,就直接发包,发送packet[序列号]。Message type什么的不多说,每发一个包,序列号+1。
2.等到出了上面的第一个循环,sender连续发送了5个包,分别是01234号,每发一个包,都会记录时间。这些包被receiver接受。在receiver内,首先分割开发送数据的结构,得到发送地址,端口,消息文本,checksum。并把它们输出在receiver上。
3.接着,检测到第一个包数据头是 start ,于是进入start数据头的方法,把receiver的连接地址初始化。接着,创建connection对象,这时后面的包到达,进入的是data,他们和第一个包调用的都是ack,这个函数将可能失序的包按升序排序,并返回调用自己的对象两个东西:可能调换过顺序的数据包,下一个希望得到的包号(ACK号)。
4.receiver包装一下ack数据包,向sender发回ack消息。
5.Sender 一次性发了5个包,开始进入下一个循环,给1秒来收receiver的ack信息。同时超时判断,超时的包将会重发。
6.假设某一次循环内获得了receiver的几个ack包(本机测试一般是3~5个),每获得一个,就会更新窗口号的值,刚刚的包的回应来了,显示ack 1,ack 2.ack 3,那么窗口号会更新3次,即1,2,3.更新完后跳出接受循环(循环2)。看看这一次循环花了多久,如果特别快,只有0.2秒就接受到ACK信息并出来了,那么还可以再进循环一次看看有没有新的可能的ACK发来。如果这次循环花了超过0.5s的时间,那么还是先返回到第一个循环发包了再说。我们假设这次比较快,于是再次循环了一次,收到了ACK4,ACK5。这次还是很快,0.1秒就搞定了。按照条件,再次进入循环,receiver表示所有的ACK都发完了,就给了一个None 回来,判断检测到了这个None,循环就跳出。开始进入第一个循环(发送循环)。
7.这时第一个循环,4<5+5,循环再次可以进入,这时候5个窗口全部可用,于是发送 5,6,7,8,9.接下来就不多说了。
使用说明。
把要发送的文件名赋值给filename。
不要去我的资源,那里什么都没有,也没有这次的程序。