author: xiekch
- 写一个文件传输程序 A,通过 UPD 来传输一个文件及其管理元数据(文件名、大小和日期等),在应用层处理报文出错、重组和乱序等问题,保证文件传输正确无误。
可靠传输需要将文件按序无误的传输给对方,必须要解决三个问题:
- 出错
- 丢包
- 乱序
本程序仿照TCP传输协议,对这三个问题进行了处理。实现了连续ARQ(Automatic Repeat-reQuest)协议。此外,还实现了拥塞控制和自适应的超时重传时间算法。
发送方采用流水线传输。流水线传输就是发送方可以连续发送多个分组,不必每发完一个分组就停下来等待对方确认。如下图所示:
通过使用确认和超时这两个机制,就可以在不可靠UDP服务的基础上实现可靠的信息传输。
在UDP报文首部中,有2个字节长度的校验和,用来检测UDP用户数据报是否有错,有错就丢弃。而我们的数据包是以UDP为载体,故无需额外检测是否出错。
判断是否丢包有2个方法:
- 超时
- 3次对同一数据包的确认
处理算法:
- 采用累计确认算法,对按序到达的最后一个数据包发送确认
- 实现快速重传算法,只要有一个包确认达到三次,即立即重传。
- 选择重发。只重发发生丢包的数据包,节约网络带宽。
把没有按序到达的数据包先缓存下来,直到数据包有序排列,再交付给上层程序。
实现慢启动、AIMD算法,分三种情况处理:
- 超时重发
- 阈值设为原拥塞窗口的一半
- 拥塞窗口设为1
- 3次重复确认重发
- 阈值设为原拥塞窗口的一半
- 拥塞窗口减半
- 未重发
- 如果大于阈值,拥塞窗口加1
- 否则,拥塞窗口翻倍
相关代码
def updataCongWin(self, resend, timeout):
if resend == True:
self.threshold = math.ceil(0.5*self.congWin)
if timeout == True:
self.congWin = 1
else:
self.congWin = self.threshold
elif self.congWin < self.windowSize:
if self.congWin >= self.threshold:
self.congWin += 1
else:
self.congWin *= 2
采用自适应算法,分两种情况:
-
未重传
timeout = 0.8 * timeout + 0.2 * rtt + 0.2 * rtt
-
重传
timeout *= 2
相关代码
def updataTimeout(self, resend, rtt=1):
if resend == True:
if self.timeout < self.maxTimeout:
self.timeout *= 2
else:
self.timeout = 0.8*self.timeout+0.2*rtt+0.2*rtt
- 建立UDP socket
- 打开文件,读取数据
- 发送Syn=True数据包,建立连接
- 发送文件管理元数据
- 将在拥塞窗口内的文件数据发送出去
- 接收接收方确认
- 若发生丢包,重传数据包
- 更新拥塞窗口和超时重传时间
- 重复4直至文件发送完毕
- 发送Fin=True数据包,传输结束
- 建立UDP socket,绑定端口
- 接收Syn=True数据包,开始接收文件
- 接收文件管理元数据,输出并创建文件
- 接收文件数据
- 若按序到达,发送确认
- 否则,缓存,发送确认
- 将有序数据写入文件
- 重复4直接接收到Fin=True数据包,传输结束
在跨越4个路由的情况下:传输130MB的压缩包文件,稳定的有效文件传输速率为600KB/s左右,丢包率为0.1%左右:
传输结束,压缩包可正常解压。
First run UDPServer
.
python UDPServer.py [ServerIP] [ServerPort] [FileName]
python UDPClient.py [ServerIP] [ServerPort] [FileSavedDirectory]
- 滑动窗口协议