实验四 增强型可靠文件传输系统

一、实验目的和任务

  1. 掌握基于队列的多文件传输机制
  2. 理解断点续传的实现原理
  3. 学习文件传输完整性保障方法

二、实验内容

基础功能验证

  1. 单文件传输功能测试
  2. 服务器状态监控测试
  3. 传输日志记录验证

新增功能实现

  1. 多文件队列传输功能
  2. 断点续传支持

三、实验步骤

4.1 客户端功能扩展

参考代码:

关键代码修改点:

文件队列管理:
# 新增队列和状态变量
self.file_queue = queue.Queue()
self.is_transferring = False
# 修改后的文件选择方法
def select_file(self):filepaths = filedialog.askopenfilenames()if filepaths:for filepath in filepaths:self.file_queue.put(filepath)self.log.insert(END, f"已添加: {os.path.basename(filepath)}\n")if not self.is_transferring:threading.Thread(target=self.process_queue).start()
新增队列处理线程:
def process_queue(self):self.is_transferring = Truewhile not self.file_queue.empty():filepath = self.file_queue.get()self.upload_file(filepath)
self.is_transferring = False
断点续传功能:
上传文件方法修改def upload_file(self, filepath):try:client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(('localhost', 12345))# 发送文件元数据filename = os.path.basename(filepath)filesize = os.path.getsize(filepath)client.send(f"{filename} |{filesize}".encode())# 等待服务器确认ack = client.recv(1024).decode()if ack.startswith('RESUME'):recieved = int(ack.split('|')[1])mode = 'rb+'  #从断点处继续读else:recieved = 0mode = 'rb'# 分块传输文件with open(filepath, mode) as f:f.seek(recieved)while recieved <filesize:chunk = f.read(1024)if chunk:client.send(chunk)recieved += len(chunk)self.log.insert(END, f"{filename} 传输成功\n")except Exception as e:self.log.insert(END, f"错误: {e}\n")finally:client.close()

完整python脚本如下:

import socket
import os
import threading
import queue
from tkinter import *
from tkinter import filedialog
from tkinter import messagebox
class FileTransferClient:def __init__(self, root):self.root = rootself.root.title("文件传输客户端")# 文件队列和状态self.file_queue = queue.Queue()self.is_transferring = False# 创建界面组件self.create_widgets()def create_widgets(self):# 文件选择按钮self.select_btn = Button(self.root, text="选择文件", command=self.select_file)self.select_btn.pack(pady=10)# 传输日志self.log = Text(self.root, height=15, width=60)self.log.pack(pady=10)def select_file(self):filepaths = filedialog.askopenfilenames()if filepaths:for filepath in filepaths:self.file_queue.put(filepath)self.log.insert(END, f"已添加: {os.path.basename(filepath)}\n")if not self.is_transferring:threading.Thread(target=self.process_queue).start()def process_queue(self):self.is_transferring = Truewhile not self.file_queue.empty():filepath = self.file_queue.get()self.upload_file(filepath)self.is_transferring = Falsedef upload_file(self, filepath):try:client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(('localhost', 12345))# 发送文件元数据filename = os.path.basename(filepath)filesize = os.path.getsize(filepath)client.send(f"{filename}|{filesize}".encode())# 等待服务器确认ack = client.recv(1024).decode()if ack.startswith('RESUME'):received = int(ack.split('|')[1])mode = 'rb+'else:received = 0mode = 'rb'# 分块传输文件with open(filepath, mode) as f:f.seek(received)while received < filesize:data = f.read(1024)if not data:breakclient.send(data)received += len(data)self.log.insert(END, f"{filename} 传输成功\n")except Exception as e:self.log.insert(END, f"错误: {e}\n")finally:client.close()
if __name__ == "__main__":root = Tk()app = FileTransferClient(root)root.mainloop()

4.2 服务器功能扩展

参考代码:

关键代码修改点:

断点续传支持:
def handle_client(self, client_socket):# 检查文件是否存在if os.path.exists(filename):received = os.path.getsize(filename)client_socket.send(f"RESUME|{received}".encode())mode = 'ab'  # 追加模式else:client_socket.send(b"ACK")mode = 'wb'received = 0

完整python脚本如下:  


import socket
import os
import threading
from datetime import datetime
class FileTransferServer:def __init__(self, host='localhost', port=12345):self.host = hostself.port = portself.server_socket = Noneself.running = Falsedef start(self):self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.server_socket.bind((self.host, self.port))self.server_socket.listen(5)self.running = Trueprint(f"服务器启动,监听 {self.host}:{self.port}")while self.running:try:client_socket, addr = self.server_socket.accept()print(f"新连接来自: {addr}")# 为每个客户端创建新线程client_thread = threading.Thread(target=self.handle_client,args=(client_socket,))client_thread.start()except Exception as e:print(f"服务器错误: {e}")breakdef stop(self):self.running = Falseif self.server_socket:self.server_socket.close()print("服务器已停止")def handle_client(self, client_socket):try:# 接收文件元数据metadata = client_socket.recv(1024).decode()filename, filesize = metadata.split('|')filesize = int(filesize)# 检查文件是否存在if os.path.exists(filename):received = os.path.getsize(filename)client_socket.send(f"RESUME|{received}".encode())mode = 'ab'  # 追加模式else:client_socket.send(b"ACK")mode = 'wb'received = 0# 接收文件数据with open(filename, mode) as f:while received < filesize:data = client_socket.recv(1024)if not data:breakf.write(data)received += len(data)print(f"文件 {filename} 接收完成 ({received}/{filesize} bytes)")except Exception as e:print(f"处理客户端时出错: {e}")finally:client_socket.close()
if __name__ == "__main__":server = FileTransferServer()try:server.start()except KeyboardInterrupt:server.stop()

4.3 实验验证步骤

  1. 基础传输测试:
  1. 启动Server.py
  2. 运行Client.py
  3. 选择单个文件传输
  4. 观察服务器接收情况
  1. 多文件队列测试:
  1. 启动Server2.py
  2. 运行Client2.py
  3. 同时选择多个文件(建议3-5个)
  4. 观察队列传输顺序和日志记录
  1. 断点续传测试:
  1. 传输大文件(>50MB)
  2. 在传输过程中强制关闭客户端
  3. 重新启动传输同一文件
  4. 验证文件完整性(通过文件大小比对)

四、测试结果

五、思考题

1.MD5校验是否能完全保证文件正确性?为什么?

        MD5校验不能完全保证文件的正确性。虽然MD5可以用来检测文件完整性,因为它通过生成一个固定长度的哈希值来唯一标识文件内容,但如果两个不同的文件生成了相同的MD5哈希值(这种情况称为哈希碰撞),那么MD5校验就无法区分这两个文件了。此外,MD5已经被证明不够安全,存在被恶意攻击者故意构造碰撞的情况。因此,对于需要更高安全性的场景,通常推荐使用更安全的哈希算法,如SHA-256。

2.进度条更新为什么要用after()方法?

        在GUI编程中,after()方法常用于非阻塞地执行某些任务,比如定时更新进度条。这是因为after()方法可以在指定的时间间隔后执行一个函数或方法调用,而不需要阻塞主线程。这样可以保持用户界面的响应性,防止因为长时间的计算或网络操作导致界面卡顿。

3.如何实现服务端的多客户端并发处理?

        实现服务端的多客户端并发处理通常可以采用多线程或多进程的方式。例如,在Python中可以使用socket库结合threadingmultiprocessing库来为每个客户端创建一个独立的线程或进程,从而实现并发。另一种方法是使用异步编程,如asyncio库,通过事件循环管理多个客户端的请求,这种方式在处理大量并发连接时效率更高。

4.传输过程中突然关闭窗口会导致什么问题?如何解决?

        传输过程中突然关闭窗口可能会导致数据传输不完整,文件损坏,或者服务端和客户端之间的连接异常中断。为了解决这个问题,通常可以采用以下措施:

  • 实现数据包的确认机制,确保每个数据包都被正确接收。

  • 使用断点续传功能,使得在传输中断后可以从上次中断的位置继续传输。

  • 设计良好的错误处理机制,能够在检测到连接中断时尝试恢复连接或通知用户重新传输文件。

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

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

相关文章

网络Tips20-003

1.E1载波的控制开销占2/32*100%6.25%&#xff0c;E1载波的基本帧传送时间是125uS。 2.计算机在一个指令周期的过程中&#xff0c;为从内存读取指令操作码&#xff0c;首先要将.程序计数器(PC)的内容送到地址总线上 3.3DES算法:密码学中&#xff0c;3DES是三重数据加密算法通称…

【MySQL】索引(重要)

目录 一、索引本质&#xff1a; 索引的核心作用 索引的优缺点 二、预备知识&#xff1a; 硬件理解&#xff1a; 软件理解&#xff1a; MySQL与磁盘交互基本单位&#xff1a; 三、索引的理解&#xff1a; 理解page&#xff1a; 单个page&#xff1a; 多个page&#x…

【深入浅出MySQL】之数据类型介绍

【深入浅出MySQL】之数据类型介绍 MySQL中常见的数据类型一览为什么需要如此多的数据类型数值类型BIT&#xff08;M&#xff09;类型INT类型TINYINT类型BIGINT类型浮点数类型float类型DECIMAL(M,D)类型区别总结 字符串类型CHAR类型VARCHAR(M)类型 日期和时间类型enum和set类型 …

数字化时代下,软件测试中的渗透测试是如何保障安全的?

在如今数字化与信息化的时代&#xff0c;软件测试中存在渗透测试&#xff0c;其位置十分重要&#xff0c;它借助模拟恶意攻击的方式&#xff0c;去发现软件系统所存在的漏洞以及安全问题&#xff0c;这是保障软件安全的关键环节&#xff0c;接下来我会对它的各个方面进行详细介…

Pytorch - Developer Notes 1/2

文章目录 自动混合精度示例典型的混合精度训练处理未缩放梯度梯度裁剪 处理缩放梯度梯度累积梯度惩罚 处理多个模型、损失函数和优化器多 GPU 工作环境下的注意事项单进程中的DataParallel分布式数据并行&#xff1a;每个进程对应一个GPU每个进程使用多块GPU的DistributedDataP…

RuntimeError: CUDA error: __global__ function call is not configured

表明在 CUDA 设备上调用的核函数 没有正确配置线程块和网格维度。 一般体现在&#xff1a; 直接调用 kernel 函数&#xff0c;而不是通过 launch 函数 指定 kernel 函数调用 解决方法&#xff08;示例&#xff09;&#xff1a; // kernel function __global__ void Idtest_k…

cloudfare+gmail 配置 smtp 邮箱

这里介绍有一个域名后&#xff0c;不需要服务器&#xff0c;就可以实现 cloudfare gmail 的 邮箱收发。 为什么还需要 gmail 的 smtp 功能&#xff0c;因为 cloudfare 默认只是对 email 进行转发&#xff0c;就是只能收邮件而不能发送邮件&#xff0c;故使用 gmail 的功能来进…

如何在 CentOS 7 命令行连接 Wi-Fi?如何在 Linux 命令行连接 Wi-Fi?

如何在 CentOS 7 命令行连接 Wi-Fi&#xff1f;如何在 Linux 命令行连接 Wi-Fi&#xff1f; 摘要 本教程覆盖如何在多种 Linux 发行版下通过命令行连接 Wi-Fi&#xff0c;包括&#xff1a; CentOS 7、Ubuntu、Debian、Arch Linux、Fedora、Alpine Linux、Kali Linux、OpenSU…

基于PHP的在线编程课程学习系统

有需要请加文章底部Q哦 可远程调试 基于PHP在线编程课程学习系统 一 介绍 在线编程课程学习系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端jquery.js。系统角色分为学生&#xff0c;教师和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqljquery.jsphps…

PyTorch_张量形状操作

搭建模型时&#xff0c;数据都是基于张量形式的表示&#xff0c;网络层与层之间很多都是以不同的shape的方式进行表现和运算。 对张量形状的操作&#xff0c;以便能够更好处理网络各层之间的数据连接。 reshape 函数的用法 reshape 函数可以再保证张量数据不变的前提下改变数…

大模型实践:图文解锁Ollama在个人笔记本上部署llm

使用在线模型服务时&#xff0c;我们常常需要支付API调用费用&#xff0c;这对于个人开发者或小型组织来说可能是一笔不小的开支。那么&#xff0c;有没有方法可以在本地免费使用这些强大的模型呢&#xff1f;答案是肯定的——Ollama就是这样一个工具。 当然如果是比较大的组织…

Python基本语法(lambda表达式)

lambda表达式 lambda的一般形式是在关键字lambda后面跟一个或多个参数&#xff0c;之后再紧跟一个 冒号&#xff0c;接下来是一个表达式。lambda是一个表达式&#xff0c;而不是一个语句&#xff0c;它能够出现 在Python语法不允许def出现的地方。作为表达式&#xff0c;lambd…

【MySQL数据库】用户管理

目录 1&#xff0c;用户信息 2&#xff0c;创建/删除/修改用户 3&#xff0c;数据库的权限 MySQL数据库安装完之后&#xff0c;我们最开始时使用的都是 root 用户&#xff0c;其它用户通常无法进行操作。因此&#xff0c;MySQL数据库需要对用户进行管理。 1&#xff0c;用户…

Python的ArcPy基于Excel表格对大量遥感影像批量重分类

本文介绍基于Python中的ArcPy模块&#xff0c;以Excel表格内的信息&#xff0c;对遥感影像加以重分类的方法。 首先&#xff0c;明确一下本文的需求。现有按照文章ArcPy批量将栅格文件的属性表导出为Excel表格的方法&#xff08;https://blog.csdn.net/zhebushibiaoshifu/artic…

LabVIEW 中VI Server导出 VI 配置

该 LabVIEW VI 展示了在 VI Server 中配置和执行 Exported VIs 的过程&#xff0c;实现对服务器端导出 VI 的远程调用与操作。 ​ 具体过程及模块说明 前期配置&#xff1a;需确保在 LabVIEW 的 “Tools> Options > VI Server > Protocols” 路径下&#xff0c;启用 …

论文阅读:2024 ACM SIGSAC Membership inference attacks against in-context learning

总目录 大模型安全相关研究&#xff1a;https://blog.csdn.net/WhiffeYF/article/details/142132328 Membership inference attacks against in-context learning https://arxiv.org/pdf/2409.01380 https://www.doubao.com/chat/4030440311895554 速览 这篇论文主要研究了…

从 Python 基础到 Django 实战 —— 数据类型驱动的 Web 开发之旅

主题简介&#xff1a; 本主题以 Python 基础数据类型为核心&#xff0c;结合 Django 框架的开发流程&#xff0c;系统讲解如何通过掌握数字、字符串、列表、元组、字典等基础类型&#xff0c;快速构建功能完善的 Web 应用。通过理论与实践结合&#xff0c;帮助学员从零基础 Py…

软考 系统架构设计师系列知识点之杂项集萃(53)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;52&#xff09; 第85题 在静态测试中&#xff0c;主要是对程序代码进行静态分析。“数据初始化、赋值或引用过程中的异常”属于静态分析中的&#xff08;&#xff09;。 A. 控制流分析 B. 数据…

Raycaster光线投射

Raycaster光线投射 3D虚拟工厂在线体验 描述 光线投射Raycaster&#xff0c;用于进行raycasting&#xff08;光线投射&#xff09;。 光线投射用于进行鼠标拾取&#xff08;在三维空间中计算出鼠标移过了什么物体&#xff09;。 构造器 Raycaster( origin : Vector3, dire…

初识Linux —— git三板斧

版本控制器git 为了我们方便管理不同版本的文件&#xff0c;就有了版本控制器&#xff1b; 所谓的版本控制器&#xff0c;就是能够了解到一个文件的历史记录&#xff08;修改记录&#xff09;&#xff1b;简单来说就是记录每一次的改动和版本迭代的一个管理系统&#xff0c;同…