优化基于tcp,socket的ftp文件传输程序
原始程序:
template_ftp_server_old.py:
import socket
import json
import struct
import os
import time
import pymysql.cursorssoc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '192.168.31.111'
PORT = 4101
soc.bind((HOST,PORT))
port_str = str(PORT)
slice_id = int(port_str[:2]) - 20
ueX_str = 'user'
ue_id = int(port_str[3])
ueX_delay = ueX_str + str(ue_id) + '_delay' #
ueX_v = ueX_str + str(ue_id) + '_v' #
ueX_loss = ueX_str + str(ue_id) + '_loss' #
soc.listen(5)
cnx = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='qt', charset='utf8mb4', connect_timeout=20)
cursor = cnx.cursor()# 上传函数
def uploading_file():ftp_dir = r'C:/Users/yinzhao/Desktop/ftp/ftpseverfile' # 将传送的name.txt保存在该文件夹当中if not os.path.isdir(ftp_dir):os.mkdir(ftp_dir)head_bytes_len = conn.recv(4) # 拿到struct后的头长度head_len = struct.unpack('i', head_bytes_len)[0] # 取出真正的头长度# 拿到真正的头部内容conn.send("1".encode('utf8'))head_bytes = conn.recv(head_len)conn.send("1".encode('utf8'))# 反序列化后取出头head = json.loads(head_bytes)file_name = head['file_name']print(file_name)file_path = os.path.join(ftp_dir, file_name)data_len = head['data_len']received_size = 0data=b''#****************************************************旧程序问题1:一次发送最大数据量,越大传输速率越快*************************************max_size=65536*4while received_size < data_len:#************************************************旧程序问题2:在接收文件的循环中有大量统计 计算 操作数据库的代码,占用时间**************8# ftp_v = open('E:\FTP_test\FTP_v.txt', 'w', encoding='utf-8')# ftp_delay = open('E:\FTP_test\FTP_delay.txt', 'w', encoding='utf-8')if data_len - received_size > max_size:size = max_sizeelse:size = data_len - received_sizereceive_data = conn.recv(size) # 接收文本内容#************************************************旧程序问题3:基于socket的tcp无需手动在服务端进行ack的操作,既若无需要服务端可以不手动回发消息**********# conn.send("1".encode('utf8'))# delay=conn.recv(1024).decode('utf8') # 接受时延# conn.send(str(size).encode('utf-8')) ## v = conn.recv(1024).decode('utf8') # 接受速率# conn.send("1".encode('utf-8')) ## loss = conn.recv(1024).decode('utf8') # 接受loss# conn.send("1".encode('utf-8'))# print("delay:",delay)# delay_float = float(delay)# v_float = float(v)# loss_float = float(loss)# formatted_delay = "{:.2f}".format(delay_float)# formatted_v = "{:.2f}".format(v_float)# formatted_loss = "{:.2f}".format(loss_float)# cursor.execute("UPDATE slice_v2 SET " + ueX_v + "= %s," + ueX_delay + "=%s, " + ueX_loss + " =%s WHERE slice_id = %s", [str(formatted_v), str(formatted_delay), str(formatted_loss), slice_id])# cnx.commit()data+=receive_datareceive_datalen = len(receive_data)received_size += receive_datalen# print(delay, file=ftp_delay)# print(v, file=ftp_v)#print(loss)# ftp_delay.close()#ftp_v.close()#***********************************************旧程序问题4:接收文件后进行组装,组装后统一写入,且在一个线程里,耗时*******************************with open(file_path, 'wb') as fw:fw.write(data)# print("上传文件 " + str(file_name) + " 成功")#uploading_file()while True:encoding = 'utf-8'print('等待客户端连接...')conn, addr = soc.accept()print('客户端已连接:', addr)uploading_file()conn.close()
client_renew_old.py
# coding: UTF-8
import socket
import os
import struct
import json
import hashlib
import time# lient_soc.connect(('192.168.1.101', 8025))# 上传函数
def uploading_file(filepath,filename):client_soc = socket.socket()client_soc.connect(('192.168.31.111', 4101))try:encoding = 'utf-8'with open(filepath+filename, 'rb') as fr:#发送固定文件data = fr.read()head = {'data_len': len(data), 'file_name': filename} # 自定义头head_bytes = json.dumps(head).encode('utf8')head_bytes_len = struct.pack('i', len(head_bytes))client_soc.send(head_bytes_len)client_soc.recv(20).decode('utf8')client_soc.send(head_bytes)client_soc.recv(20).decode('utf8')print(str(int(len(data))/1024)+'KB')# client_soc.send(data)max_size = 65536*4#max_size = 1024# 计算需要分成几个数据包发送num_packets = len(data) // max_sizeif len(data) % max_size > 0:num_packets += 1# 循环分批发送数据for i in range(num_packets):# 将延时、速率传到txt文件中start = i * max_sizeend = start + max_size# if(i==num_packets-1):# end=len(data)packet = data[start:end]#从这里开始计时start = time.perf_counter()client_soc.sendall(packet)# client_soc.recv(1024).decode('utf8')#计算时间段# delay=float(time.perf_counter() - start)# s#v=round(len(packet)/1048576/delay,2)#MB/S# delay=int(delay*1000)# print("延时:",delay)# print("传输速率:",v)#client_soc.send(str(delay).encode('utf8'))# rev_size=client_soc.recv(1024).decode('utf8')# loss=(len(packet)-int(rev_size))/len(packet)# client_soc.send(str(v).encode('utf8'))# client_soc.recv(1024).decode('utf8')# client_soc.send(str(loss).encode('utf8'))# client_soc.recv(1024).decode('utf8')# print("丢包率:",loss)print("发送完毕")#uploading_file()except socket.error as e:print("发生错误:", str(e))finally:# 关闭连接client_soc.close()if __name__ == '__main__':filepath='C:/Users/yinzhao/Desktop/ftp/'filename='test.7z'i = 0while i<2 :encoding = "utf8"uploading_file(filepath,filename)i = i+1print(i)
目前有如下支持:
- 传输任何文件,若成功传输到服务器,不会损坏
- 传输速率:
max_size =655364

max_size =655368

该代码经过测试,有如下问题与特性:
4. 一次发送最大数据量,越大传输速率越快。之前每次发送1024,现在修改为65536*4
5. 在接收文件的循环中有大量统计 计算 操作数据库的代码,占用时间
6. 基于socket的tcp无需手动在服务端进行ack的操作,既若无需要服务端可以不手动回发消息。原程序有大量手动进行确认的过程,占用大量时间
7. 完整接收文件后再进行组装,组装后统一写入,也可以改成接收一次包写入一次
8. 所有程序都在同一个线程里,可以将数据传输 统计 数据写入放在不同的程序里,提供程序执行速度
修改代码
import socket
import json
import struct
import os
import time
import pymysql.cursors
import datetime
import threadingsoc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '192.168.84.1'
PORT = 4101
soc.bind((HOST,PORT))
port_str = str(PORT)
slice_id = int(port_str[:2]) - 20
ueX_str = 'user'
ue_id = int(port_str[3])
ueX_delay = ueX_str + str(ue_id) + '_delay' #
ueX_v = ueX_str + str(ue_id) + '_v' #
ueX_loss = ueX_str + str(ue_id) + '_loss' #
soc.listen(5)
cnx = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='qt', charset='utf8mb4', connect_timeout=20)
cursor = cnx.cursor()def up_to_mysql(v,delay,loss):delay_float = float(delay)v_float = float(v)loss_float = float(loss)formatted_delay = "{:.2f}".format(delay_float)formatted_v = "{:.2f}".format(v_float)formatted_loss = "{:.2f}".format(loss_float)cursor.execute("UPDATE slice_v2 SET " + ueX_v + "= %s," + ueX_delay + "=%s, " + ueX_loss + " =%s WHERE slice_id = %s", [str(formatted_v), str(formatted_delay), str(formatted_loss), slice_id])cnx.commit()def write_file(file_path,data):with open(file_path, 'wb') as fw:fw.write(data)
# 上传函数
def uploading_file():ftp_dir = r'/home/lab/changeyaml/test' # 将传送的name.txt保存在该文件夹当中if not os.path.isdir(ftp_dir):os.mkdir(ftp_dir)head_bytes_len = conn.recv(4) # 拿到struct后的头长度head_len = struct.unpack('i', head_bytes_len)[0] # 取出真正的头长度# 拿到真正的头部内容conn.send("1".encode('utf8'))head_bytes = conn.recv(head_len)conn.send("1".encode('utf8'))# 反序列化后取出头head = json.loads(head_bytes)file_name = head['file_name']print(file_name)file_path = os.path.join(ftp_dir, file_name)data_len = head['data_len']received_size = 0data=b''max_size=65536*8time_begin = datetime.datetime.now()time_rev_begin=datetime.datetime.now()time_rev_end=datetime.datetime.now()datasize_rev_last=0while received_size < data_len:if data_len - received_size > max_size:size = max_sizeelse:size = data_len - received_sizereceive_data = conn.recv(size) # 接收文本内容 data+=receive_datareceive_datalen = len(receive_data)received_size += receive_datalentime_rev_end=datetime.datetime.now()time_gap=time_rev_end-time_rev_beginif time_gap.total_seconds()>=1 :time_rev_begin=time_rev_end# print((time_rev_end-time_rev_begin).total_seconds)data_rev_1s_KB=(received_size-datasize_rev_last)/1024# print("data:"+str(data_rev_1s_KB)+'KB')# print("speed:"+str(data_rev_1s_KB)+'KB/s')# print("speed:"+str(data_rev_1s_KB/1024)+'MB/s')delay= 1/(data_rev_1s_KB*1024/max_size)# print("delay:"+str(delay)+'s')delay_ms=delay*1000print("delay:"+str(delay)+'ms')datasize_rev_last=received_sizeup_mysql_thread = threading.Thread(target=up_to_mysql, args=(8*data_rev_1s_KB/1024, delay_ms,0))up_mysql_thread.start()time_end= datetime.datetime.now()time_transport=time_end-time_begintime_transport_s=time_transport.total_seconds()print("耗时:"+str(time_transport_s))data_len_KB=data_len/1024data_len_MB=data_len/(1024*1024)print("数据量:"+str(data_len_KB)+"KB")v_average=data_len_KB/time_transport_s# print("平均速度:"+str(v_average)+'KB/s')print("平均速度:"+str(data_len_MB/time_transport_s)+'MB/s')write_file_thread = threading.Thread(target=write_file, args=(file_path, data))write_file_thread.start()while True:encoding = 'utf-8'print('等待客户端连接...')conn, addr = soc.accept()print('客户端已连接:', addr)uploading_file()conn.close()
# coding: UTF-8
import socket
import os
import struct
import json
import hashlib
import time# 上传函数
def uploading_file(filepath,filename):client_soc = socket.socket()client_soc.connect(('192.168.1.21', 4101))try:encoding = 'utf-8'with open(filepath+filename, 'rb') as fr:#发送固定文件data = fr.read()head = {'data_len': len(data), 'file_name': filename} # 自定义头head_bytes = json.dumps(head).encode('utf8')head_bytes_len = struct.pack('i', len(head_bytes))client_soc.send(head_bytes_len)client_soc.recv(20).decode('utf8')client_soc.send(head_bytes)client_soc.recv(20).decode('utf8')print(str(int(len(data))/1024)+'KB')# client_soc.send(data)max_size = 65536*8#max_size = 1024# 计算需要分成几个数据包发送num_packets = len(data) // max_sizeif len(data) % max_size > 0:num_packets += 1# 循环分批发送数据for i in range(num_packets):start = i * max_sizeend = start + max_size# if(i==num_packets-1):# end=len(data)packet = data[start:end]#从这里开始计时start = time.perf_counter()client_soc.sendall(packet)print("发送完毕")#uploading_file()except socket.error as e:print("发生错误:", str(e))finally:# 关闭连接client_soc.close()if __name__ == '__main__':filepath='C:/Users/QD689/Desktop/ftp1.01/'filename='name.txt'i = 0while i<3 :encoding = "utf8"uploading_file(filepath,filename)uploading_file(filepath,filename)i = i+1print(i)
经过精简代码与多线程使用,以及合理配置每次发送数据量大小,ftp文件传输速率极大提高了,并且可以正确测算到速率与时延
相关文章:
优化基于tcp,socket的ftp文件传输程序
原始程序: template_ftp_server_old.py: import socket import json import struct import os import time import pymysql.cursorssoc socket.socket(socket.AF_INET, socket.SOCK_STREAM) HOST 192.168.31.111 PORT 4101 soc.bind((HOST,PORT)) p…...
MySQL 数据库 【增删查改(二)】
目录 一、表的设计 1、一对一 2、一对多 3、多对多 二、新增 三、查询 1、聚合查询 (1)聚合函数: (2) group by 子句 (3)having 2、联合查询 (1)内连接 (2)外连接 (3)自链接 (4)…...
力扣 -- 978. 最长湍流子数组
一、题目 二、解题步骤 下面是用动态规划的思想解决这道题的过程,相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 三、参考代码 class Solution { public:int maxTurbulenceSize(vector<int>& nums) {int nnums.size();vector<int> f(n);…...
甘特图 Dhtmlx Gantt
介绍 在一些任务计划、日程进度等场景中我们会使用到甘特图,Dhtmlx Gantt 对于甘特图的实现支持很友好,文档API介绍全面,虽然增强版的收费,但免费版的足以够用。 官网:https://docs.dhtmlx.com/gantt/ 安装dhtml gannt…...
iOS 应用上架流程详解
iOS 应用上架流程详解 欢迎来到我的博客,今天我将为大家分享 iOS 应用上架的详细流程。在这个数字化时代,移动应用已经成为了人们生活中不可或缺的一部分,而 iOS 平台的 App Store 则是开发者们发布应用的主要渠道之一。因此,了解…...
Python入门【LEGB规则、面向对象简介、面向过程和面向对象思想、面向对象是什么? 对象的进化 、类的定义、对象完整内存结构 】(十三)
👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白 📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 📧如果文章知识点有错误…...
【消息中间件】原生PHP对接Uni H5、APP、微信小程序实时通讯消息服务
文章目录 视频演示效果前言一、分析二、全局注入MQTT连接1.引入库2.写入全局连接代码 二、PHP环境建立总结 视频演示效果 【uniapp】实现买定离手小游戏 前言 Mqtt不同环境问题太多,新手可以看下 《【MQTT】Esp32数据上传采集:最新mqtt插件(支…...
【C语言初阶】指针篇—上
目录 1. 指针是什么?2. 指针和指针类型2.1 指针-整数2.2 指针的解引用 3. 野指针3.1 野指针成因1. 指针未初始化2. 指针越界访问3. 指针指向的空间释放 3.2 如何规避野指针 1. 指针是什么? 指针是什么? 指针理解的2个要点: > 1…...
基于FasterRCNN深度学习网络的车辆检测算法matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022A 3.部分核心程序 ....................................................................... % 训练Faster R-…...
机器学习深度学习——多层感知机
👨🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——感知机 📚订阅专栏:机器学习&&深度学习 希望文章对你们有所帮助 上一节…...
Django模型将模型注释同步到数据库
1、安装django-comment-migrate库 pip install django-comment-migrate 2、将库注册到settings.py文件中 INSTALLED_APPS [...django_comment_migrate, # 表注释... ] 3、加注释 3.1、给模型(表)加注释 在模型的class Meta中编辑 verbose_name&…...
STM32 Flash学习(二)
STM32F1的官方固件库操作FLASH的几个常用函数。这些函数和定义分布在源文件stm32f1xx_hal_flash.c/stm32f1xx_hal_flash_ex.c以及头文件stm32f1xx_hal_flash.h/stm32f1xx_hal_flash_ex.h中。 锁定解函数 对FLASH进行写操作前必须先解锁,解锁操作:在FLA…...
kotlin获取泛型集合的类型信息
通过 reified 关键字和内联函数来实现 inline fun <reified T> getClassFromList(list: List<T>): Class<T> {return T::class.java }fun main() {val list listOf("Hello", "World")val clazz getClassFromList(list)println(clazz)…...
AQS源码解析
关于 AQS,网上已经有无数的文章阐述 AQS 的使用及其源码,所以多这么一篇文章也没啥所谓,还能总结一下研究过的源码。源码解析和某某的使用,大概是互联网上 Java 文章中写得最多的主题了。 AQS AQS 是 AbstractQueuedSynchronize…...
关于在VS2017中编译Qt项目遇到的问题
关于在VS2017中编译Qt项目遇到的问题 【QT】VS打开QT项目运行不成功 error MSB6006 “cmd.exe”已退出,代码为 2。如何在VS2017里部署的Qt Designer上编辑槽函数 【QT】VS打开QT项目运行不成功 error MSB6006 “cmd.exe”已退出,代码为 2。 链接 如何在VS2017里部署的Qt Design…...
Python web实战 | 使用 Flask 实现 Web Socket 聊天室
概要 今天我们学习如何使用 Python 实现 Web Socket,并实现一个实时聊天室的功能。本文的技术栈包括 Python、Flask、Socket.IO 和 HTML/CSS/JavaScript。 什么是 Web Socket? Web Socket 是一种在单个 TCP 连接上进行全双工通信的协议。它是 HTML5 中的…...
Android10 Recovery系列(一)隐藏recovery菜单项
一 、背景 起因是遇到了一个隐藏删除recovery菜单项的需求。在寻找解决问题的时候,我经历了找到源码位置,调试修改,生效,思考是否可拓展,优化修改,符合要求的整个过程,下面简单分享一下。如果不想立即实现效果或者只想看解决方案,可以直接看总结那一个部分 二 、准备…...
选好NAS网络储存解决方案,是安全储存的关键
随着网络信息的发展,NAS也越来越受到企业的关注,NAS网络存储除了提供简单的存储服务外,还可以提供更好的数据安全性、更方便的文件共享方式。但市面上的产品种类繁多,我们该如何选择合适的产品,通过企业云盘࿰…...
AnimateDiff论文解读-基于Stable Diffusion文生图模型生成动画
文章目录 1. 摘要2. 引言3. 算法3.1 Preliminaries3.2. Personalized Animation3.3 Motion Modeling Module 4. 实验5.限制6. 结论 论文: 《AnimateDiff: Animate Your Personalized Text-to-Image Diffusion Models without Specific Tuning》 github: https://g…...
centos7安装tomcat
安装tomcat 必须依赖 JDK 环境,一定要提前装好JDK保证可以使用 一、下载安装包 到官网下载 上传到linux 服务器 二、安装tomcat 创建tomcat 文件夹 mkdir -p /usr/local/tomcat设置文件夹权限 chmod 757 tomcat将安装包上传至 新建文件夹 解压安装包 tar zx…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
