基于Python实现(控制台)UDP传输协议的可靠文件传输工具

LFTP Design

简介

LFTP是一个采用python3实现的基于UDP传输协议的可靠文件传输工具

特点

  • 基于UDP
    • 采用python3编程语言,socket的类型均为socket(AF_INET,SOCK_DGRAM)实现
  • 实现100%可靠性传输
    • 使用SR(选择重传)协议保证所有报文都正确接收
  • 实现流量控制
    • 使用接收者通知发送者接收缓存大小来反馈发送窗口大小
  • 实现拥塞控制
    • 根据网络情况动态调整发送窗口大小。
  • 实现并发传输
    • 使用多个服务线程,满足多个用户同时上传或者下载的需求
  • 支持大文件传输且不需要过多内存
    • 切块传输

具体设计

项目结构:

项目树:

.
├── docs
│ ├── Design-doc.md
│ └── Test-doc.md
├── README.md
└── src├── Client│ └── client.py   # 客户端├── Helper│ ├── __init__.py│ ├── LFTPMessage.py    # 封装传递的包│ ├── LFTPRecvWindow.py # 接收窗口│ └── LFTPSendWindow.py # 发送端口├── Server│ └── server.py   # 服务端└── Utils└── Log.py      # 记录日志

基本流程

流程参考FTP被动模式,首先客户端会获取一个随机端口(python的socket指定),然后向我们指定定的服务端端口发送请求命令,然后服务端主控制线程会新开一个数据线程,分配一个数据传输端口,并且把端口号发送给客户端,然后客户端向这个数据传输端口获取文件数据或者发送文件数据。这种方式保证了多个客户端可以同时连接服务器进行数据传输。

客户端上传文件到服务端

具体工作过程:

  • 客户端向服务端请求发送文件,获取服务端的数据端口
  • 服务端接收到发送文件请求,从空闲的地址池中选择一个端口,新开一个数据线程,在这个端口上监听接收的数据
  • 客户端接收到服务端传来的数据端口,向该数据端口发起连接
  • 若连接成功,客户端向服务端开始发送文件分组信息
  • 服务端接收到相应的分组,发回相应的ACK确认(采用累积确认)
  • 客户端接收到相应的ACK,做出调整
  • 客户端接收到所有分组的ACK,结束进程
  • 服务端超时5s(有可能需要ACK相应的信息,即使收到了全部的包)之后同样关闭端口
客户端从服务器下载文件

下载的过程和上传的过程类似,只是在建立连接之后,由数据方,也就是服务端开始发数据分组

  • 客户端向服务端请求发送文件,获取服务端的数据端口
  • 服务端接收到发送文件请求,从空闲的地址池中选择一个端口,新开一个数据线程,在这个端口上监听接收的数据
  • 客户端接收到服务端传来的数据端口,向该数据端口发起连接
  • 若连接成功,服务端向客户端开始发送文件分组信息
  • 客户端接收到相应的分组,发回相应的ACK确认(采用累积确认)
  • 服务端接收到相应的ACK,做出调整(cwnd和rwnd)
  • 服务端接收到所有分组的ACK,结束该服务线程,关闭端口
  • 客户端超时5s(有可能需要ACK相应的信息,即使收到了全部的包)之后结束进程

相关细节实现

文件相关信息的接收和发送

这里的文件相关信息指示的是文件名称或文件大小等信息,原先打算在每个包的首部加上该字段,存储文件相关信息,后来发现可以在三次握手期间将文件信息发与服务端(或者从服务端获取该相关信息)

可靠性的实现

这里参考TCP的重传和确认,采用SR(选择重传)和累积确认的结合方式,当收取到相应的数据包,接收方会发送ACK包,与SR不同的是,这里ACK包中的确认号ACKnum是选择最小的未接收序列号。

拥塞控制实现

在接收到ACK的时候:

  • 正确的ACK,增加窗口大小:
    • 慢启动阶段:cwnd <= ssthresh: cwnd = cwnd + 1
    • 拥塞避免阶段:cwnd > ssthresh: cwnd = cwnd + 1/cwnd
  • 冗余的ACK,三次冗余将重传 + 减少窗口大小
    • ssthresh = cwnd / 2
    • cwnd = cwnd/2 + 3
  • 超时,重传 + 减少窗口大小
    • ssthresh = cwnd / 2
    • cwnd = 1
流量控制实现

在ACK确认分组信息头部加上接收窗口空余数(可用数),发送方接收到该确认分组之后将根据该字段,动态调整发送窗口的长度

并发多客户上传或下载的实现

服务端会有一个主控制线程,每受到新的客户端的请求(UPLOAD/DOWNLOAD),它都会从空闲端口池中取出空闲端口,新建一个数据线程去监听该端口,然后主控制线程会告诉客户端去跟新的数据线程连接并传递信息。

大文件读写的实现

python3读取文件的函数file.read(size),已经自动帮我们做了缓存机制,所以我们可以直接进行读写而不必进行数据分块处理,但需要注意的是,不能一次性read()整个文件,不然会将整个文件读入内存中,大文件会直接将内存撑爆,而要使用read(size),通过大小为size的缓存,实现对文件的分块读取(每次只读取size)。

测试

局域网下进行测试

服务端

命令行开启服务(默认跑在123456端口)

$ python3 server.py

客户端

命令错误会有相应的提示信息

发送数据
使用指令LFTP lsend 127.0.0.1 filepath 进行上传相应的文件

这里我上传了一个几十MB的pdf文件:

上传结束:

对比服务端和客户端的文件大小:

可以发现客户端和服务端的文件子节数相同,上传成功

接收数据
使用指令LFTP lget 127.0.0.1 filename 进行下载相应的文件

这里我删除刚才上传的了的pdf文件,再进行下载:

下载结束:

对比服务端和客户端的文件大小:

可以发现客户端和服务端的文件子节数相同,下载成功

测试并行下载

上图可以看出服务端支持两个客户端同时进行文件的下载

互联网下进行测试

测试环境

服务器:腾讯云

配置:2核2G

带宽:上行1Mbps,下行8Mbps

系统:ubuntu 16.04 64位

运行环境:Python3

公网IP:119.29.204.118 (广州)

服务端

命令行开启服务(默认跑在123456端口)

$ python3 server.py

客户端

发送数据
使用指令LFTP lsend 119.29.204.118 filepath 进行上传相应的文件

跟在局域网下相似,这里我上传了一个几十MB的pdf文件:

上传结束

对比一下接收到的文件和源文件

可以发现客户端和服务端的文件子节数相同,上传成功

接收数据
使用指令LFTP lget 119。29.204.118 filename 进行下载相应的文件

这里我删除刚才上传的了的pdf文件,再进行下载:

下载结束:

对比服务端和客户端的文件大小:

可以发现客户端和服务端的文件子节数相同,下载成功

测试并行下载
在局域网下测试:

上图可以看出服务端成功支持两个客户端同时进行文件的下载

拥塞控制测试

因为局域网内的带宽过大,难以看出拥塞控制测试的效果,因此这里使用互联网环境,在云服务器上1Mbps的带宽下同时下载文件

首先让一个客户端先开启下载,可以达到300KB/s的速度:

然后,再连接一个客户端,可以看到,此时速度都降低到150KB/s的速度。约为原来的1/2:

流量控制测试

因为文件写入的速度远快于数据在网络中的传输数度,流量控制并没有很明显的表现,所以此处并没有流量控制测试的相关截图。

大文件下载测试

这里在局域网下进行了大文件测试


可以看出,即使上传超过4GB,内存并没有过多占有,这里只是占用了 0.1% 的内存.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86674.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86674.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Go-7】面向对象编程

7. 面向对象编程 面向对象编程&#xff08;Object-Oriented Programming&#xff0c;简称OOP&#xff09;是一种编程范式&#xff0c;通过将数据和行为封装在对象中&#xff0c;以提高代码的可重用性、可维护性和扩展性。虽然Go语言不像传统的OOP语言&#xff08;如Java、C&am…

PHP语法基础篇(六):数组

PHP 中的数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。此类型针对多种不同用途进行了优化&#xff1b;它可以被视为数组、列表&#xff08;向量&#xff09;、哈希表&#xff08;映射的实现&#xff09;、字典、集合、堆栈、队列等等。本篇文章将记录数…

GitHub Actions 的深度解析与概念介绍

GitHub Actions 核心定义 Git Actions 是 GitHub 原生提供的 自动化工作流引擎&#xff0c;允许开发者在代码仓库中直接创建、测试、部署代码。其本质是通过事件驱动&#xff08;Event-Driven&#xff09;的自动化管道&#xff0c;将软件开发中的重复任务抽象为可编排的流程。…

TestCafe 全解析:免费开源的 E2E 测试解决方案实战指南

在2025年的数字化浪潮中&#xff0c;Web应用的稳定性和用户体验成为企业竞争的关键&#xff0c;而端到端&#xff08;E2E&#xff09;测试则是确保质量的“守护者”&#xff01;想象一下&#xff0c;您的电商平台因表单错误导致用户流失&#xff0c;或者支付流程因浏览器兼容性…

[CVPR 2025] 高效无监督Prompt与偏好对齐驱动的半监督医学分割

CVPR 2025 | 优化SAM&#xff1a;高效无监督Prompt与偏好对齐驱动的半监督医学分割 论文信息 标题&#xff1a;Enhancing SAM with Efficient Prompting and Preference Optimization for Semi-supervised Medical Image Segmentation作者&#xff1a;Aishik Konwer, Zhijian…

【C++】责任链模式

目录 一、模式核心概念与结构二、C++ 实现示例:员工请假审批系统三、责任链模式的关键特性四、应用场景五、责任链模式与其他设计模式的关系六、C++ 标准库中的责任链模式应用七、优缺点分析八、实战案例:Web 请求过滤器链九、实现注意事项如果这篇文章对你有所帮助,渴望获得…

dp进阶,树形背包(dfs+01)

顾名思义&#xff0c;就是在对树进行搜索的时候&#xff0c;由于限制了子节点选根节点必选和节点数限制&#xff0c;所以需要额外利用背包来维护最大值 假设根节点就是0&#xff0c;我们很容易 发现&#xff0c;这就是一个正常的树求和&#xff0c;但是限制了节点数量&#xf…

微信小程序安卓手机输入框文字飘出输入框

最近在开发微信小程序遇到一个问题&#xff0c;安卓手机输入框文字飘出输入框&#xff0c;但是ios系统的手机则正常。 使用情景&#xff1a;做了一个弹窗&#xff0c;弹窗内是表单&#xff0c;需要填写一些信息&#xff0c;但是在填写信息时光标不显示&#xff0c;输入的内容飘…

3 大语言模型预训练数据-3.2 数据处理-3.2.2 冗余去除——3.后缀数组(Suffix Array)在大模型数据去重中的原理与实战

后缀数组&#xff08;Suffix Array&#xff09;在大模型数据去重中的原理与实战 一、后缀数组的核心原理与数据结构二、后缀数组去重的核心流程1. **文档预处理与合并**2. **构建后缀数组**3. **计算最长公共前缀&#xff08;LCP&#xff09;数组**4. **基于LCP检测重复文档** …

数据库外连接详解:方式、差异与关键注意事项

&#x1f504; 数据库外连接详解&#xff1a;方式、差异与关键注意事项 外连接用于保留至少一个表的全部行&#xff0c;即使另一表无匹配记录。以下是三种外连接方式的深度解析&#xff1a; &#x1f50d; 一、外连接的三种类型 1. 左外连接 (LEFT OUTER JOIN) 作用&#xf…

vscode把less文件生成css文件配置,设置生成自定义文件名称和路径

1.下载less插件 在插件市场搜索 less 2.设置生成配置 3.修改out属性 "less.compile": {"compress": false, // 是否删除多余空白字符 一行显示[压缩]"sourceMap": false, // 是否创建文件目录树&#xff0c;true的话会自动生成一个 .css.map …

探索相机成像的奥秘 - 齐次坐标、径向失真和图像传感器倾斜

引言 大家好&#xff01;今天我们将一起探索相机成像背后的一些关键技术概念&#xff1a;齐次坐标、径向失真和图像传感器倾斜。这些概念对于理解相机如何捕捉和处理图像至关重要。我们将通过简单易懂的语言和严谨的公式来详细解释这些概念。 齐次坐标&#xff08;Homogeneou…

校企协同育人,智慧养老实训基地助力人才就业无忧

随着我国人口老龄化程度不断加深&#xff0c;智慧养老产业蓬勃发展&#xff0c;对专业人才的需求日益迫切。校企协同打造智慧养老实训基地&#xff0c;成为解决人才供需矛盾、提升人才培养质量的重要途径。通过科学的建设方案&#xff0c;智慧养老实训基地能够为学生提供实践平…

从需求到落地:一个AI训练平台的售前全流程复盘

目录 一、项目背景:客户要建自己的AI训练平台 二、需求梳理三板斧:并发量、存储带宽、模型种类 1. 并发训练量 2. 存储带宽需求 3. 模型类型与参数规模 三、解决方案设计:GPU选型 + 高速网络 + 存储架构 ✅ GPU服务器选型 ✅ 网络与通信架构 ✅ 存储与数据缓存 四…

织梦DedeCMS转WordPress

最近&#xff0c;有个用户找模板兔迁移网站&#xff0c;源站用的dede&#xff0c;需要转成wp&#xff0c;文章数量大概7000-8000篇&#xff0c;其中有个需求是保证旧文章的链接有效&#xff0c;在wp上的新文章与旧文章的链接类型不一样&#xff0c;所以这涉及到伪静态来处理跳转…

installGo.sh

#!/bin/bash # 检查是否以root用户运行 if [ "$(id -u)" -ne 0 ]; then echo "请使用root权限运行此脚本" exit 1 fi # 检查是否安装了必要的工具 for cmd in curl wget tar; do if ! command -v $cmd &> /dev/null; then echo…

【技术难题】el-table的全局数据排序实现示例,不受分页影响,以及异步请求带来的页面渲染问题

参考链接:https://blog.csdn.net/qq_35770559/article/details/131183121 问题代码 编辑页面detail.vue <el-form title="列表信息" name="detail"><el-form><el-form-item><el-buttontype="cyan"icon="el-icon-p…

非功能测试

非功能测试范畴&#xff1a;界面测试&#xff0c;易用性测试&#xff0c;兼容性测试&#xff0c;文档测试&#xff0c;安装/卸载测试等等 界面测试 1.窗体界面测试 1.窗体定义&#xff1a;指整个软件窗口&#xff0c;也可称为窗口&#xff0c;是界面测试的基本单位 2.控件分…

一起endpoint迷路的问题排查总结

今天上班&#xff0c;一到工位上&#xff0c;就有同事和我说有客户反映自己的容器的一些指标在监控平台不上报了&#xff0c;我当时一看机器所在的监控&#xff0c;发现确实是这样 确实存在某个点开始数据就没了&#xff0c;主要这个点当时也没有任何的操作变更&#xff0c;于…

官方 Linker Scripts 语法和规则解析(2)

系列文章目录 官方 Linker Scripts 语法和规则解析&#xff08;1&#xff09; 官方 Linker Scripts 语法和规则解析&#xff08;2&#xff09; 官方 Linker Scripts 语法和规则解析&#xff08;3&#xff09; 链接脚本(Linker Scripts)语法和规则解析(自官方手册) 7.9. 链接脚…