优化基于tcp,socket的ftp文件传输程序

原始程序:

template_ftp_server_old.py:

import socket
import json
import struct
import os
import time
import pymysql.cursors

soc = 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 = 0
    data=b''
    #****************************************************旧程序问题1:一次发送最大数据量,越大传输速率越快*************************************
    max_size=65536*4
    while 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_size
        else:
            size = data_len - received_size
        receive_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_data
        receive_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_size
        if len(data) % max_size > 0:
            num_packets += 1
        # 循环分批发送数据
        for i in range(num_packets):
             # 将延时、速率传到txt文件中
            start = i * max_size
            end = 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 = 0
    while i<2 :
        encoding = "utf8"
        uploading_file(filepath,filename)
        i = i+1
        print(i)

目前有如下支持:

  1. 传输任何文件,若成功传输到服务器,不会损坏
  2. 传输速率:
    max_size =655364
    在这里插入图片描述
    max_size =65536
    8
    在这里插入图片描述

该代码经过测试,有如下问题与特性:
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 threading

soc = 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 = 0
    data=b''
   
    max_size=65536*8
    time_begin = datetime.datetime.now()
    time_rev_begin=datetime.datetime.now()
    time_rev_end=datetime.datetime.now()
    datasize_rev_last=0
    while received_size < data_len:
        

        if data_len - received_size > max_size:
            size = max_size
        else:
            size = data_len - received_size
        receive_data = conn.recv(size)  # 接收文本内容  
        
        data+=receive_data
        receive_datalen = len(receive_data)
        received_size += receive_datalen
        time_rev_end=datetime.datetime.now()
        time_gap=time_rev_end-time_rev_begin
        if 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*1000
            print("delay:"+str(delay)+'ms')
            datasize_rev_last=received_size
            up_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_begin
    time_transport_s=time_transport.total_seconds()
    print("耗时:"+str(time_transport_s))
    data_len_KB=data_len/1024
    data_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_size
        if len(data) % max_size > 0:
            num_packets += 1
        # 循环分批发送数据
        for i in range(num_packets):


            start = i * max_size
            end = 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 = 0
    while i<3 :
        encoding = "utf8"
        uploading_file(filepath,filename)
        uploading_file(filepath,filename)
        i = i+1
        print(i)


经过精简代码与多线程使用,以及合理配置每次发送数据量大小,ftp文件传输速率极大提高了,并且可以正确测算到速率与时延

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MVC与MVVM模式的区别

一、MVC Model&#xff08;模型&#xff09;&#xff1a;用于处理应用程序数据逻辑&#xff0c;负责在数据库中存取数据。处理数据的crud View&#xff08;视图&#xff09;&#xff1a;处理数据显示的部分。通常视图是依据模型数据创建的。 Controller&#xff08;控制器&…

25.6 matlab里面的10中优化方法介绍—— 遗传算法(matlab程序)

1.简述 遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型&#xff0c;是一种通过模拟自然进化过程搜索最优解&#xff08;所找到的解是全局最优解&#xff09;的方法。 参数编码、初始群体的设定…

Generative Diffusion Prior for Unified Image Restoration and Enhancement 论文阅读笔记

这是CVPR2023的一篇用diffusion先验做图像修复和图像增强的论文 之前有一篇工作做了diffusion先验&#xff08;Bahjat Kawar, Michael Elad, Stefano Ermon, and Jiaming Song, “Denoising diffusion restoration models,” arXiv preprint arXiv:2201.11793, 2022. 2, 4, 6,…

【万字长文】SpringBoot整合SpringSecurity+JWT+Redis完整教程(提供Gitee源码)

前言&#xff1a;最近在学习SpringSecurity的过程中&#xff0c;参考了很多网上的教程&#xff0c;同时也参考了一些目前主流的开源框架&#xff0c;于是结合自己的思路写了一个SpringBoot整合SpringSecurityJWTRedis完整的项目&#xff0c;从0到1写完感觉还是收获到不少的&…

前端,js , Error in created hook: TypeError ,有bug了

怎么兄弟&#xff0c;遇到bug了&#xff1f;&#xff1f;&#xff1f;你开心吗&#xff0c;哈哈哈哈

论文笔记--Skip-Thought Vectors

论文笔记--Skip-Thought Vectors 1. 文章简介2. 文章概括3 文章重点技术3.1 Skip Thought Vectors3.2 词表拓展 4. 文章亮点5. 原文传送门6. References 1. 文章简介 标题&#xff1a;Skip-Thought Vectors作者&#xff1a;Ryan Kiros, Yukun Zhu, Ruslan Salakhutdinov, Rich…

7.28 作业 QT

手动完成服务器的实现&#xff0c;并具体程序要注释清楚: widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器类 #include <QTcpSocket> //客户端类 #include <QMessageBox> //对话框类 #include …

乐划锁屏充分发挥强创新能力,打造内容业新生态

乐划锁屏作为新型内容媒体,在这一市场有着众多独特的优势,不仅能够通过多场景的联动给内容创作者带来了更多可能性,还促进了更多优质作品的诞生,为用户带来更加丰富多彩的锁屏使用体验。 作为OPPO系统原生的OS应用,乐划锁屏一直致力于打造为用户提供至美内容的内容平台,吸引了全…

ETHERNET/IP转RS485/RS232网关什么是EtherNet/IP?

网络数据传输遇到的协议不同、数据互通麻烦等问题&#xff0c;一直困扰着大家。然而&#xff0c;现在有一种神器——捷米JM-EIP-RS485/232&#xff0c;它将ETHERNET/IP网络和RS485/RS232总线连接在一起&#xff0c;让数据传输更加便捷高效。 那么&#xff0c;它是如何实现这一功…

解决 tensorflow 出现的 ImportError: Could not find the DLL(s) ‘msvcp140_1.dll‘. 问题

在安装完tensorflow库后出现 问题详述&#xff1a; ImportError: Could not find the DLL(s) msvcp140_1.dll. TensorFlow requires that these DLLs be installed in a directory that is named in your %PATH% environment variable. You may install these DLLs by downlo…

FS32K144官方提供串口Bootloader对接Matlab串口烧写程序

​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 前言 Bootloader升级工具&#xff1a;可用TTL、232、485&#xff08;硬件收发模式&#xff09;,其中的一种&#x…

K8s-资源管理(二)

文章目录 2. 资源管理2.1 资源管理介绍2.2 YAML语言介绍2.3 资源管理方式2.3.1 命令式对象管理2.3.2 命令式对象配置2.3.3 声明式对象配置 2.4. 模拟使用普通用户来操作2.5 kubectl 一些基本命令2.6 使用个人的 docker 仓库的镜像 2. 资源管理 2.1 资源管理介绍 在kubernetes…

JMM是如何保证原子性呢?

3.3.1加锁 锁是一种通用技术&#xff0c;比如Java提供的Synchronized关键字就是锁的一种实现&#xff0c;Synchronized是排他锁/独占锁&#xff0c;就是有你没我的意思&#xff0c;只要其他线程到来访问&#xff0c;发现锁还未释放&#xff0c;就要在外面等待&#xff0c;因为S…

linux系统下(centos7.9)安装Jenkins全流程

一、卸载历史版本 # rpm卸载 rpm -e jenkins# 检查是否卸载成功 rpm -ql jenkins# 彻底删除残留文件 find / -iname jenkins | xargs -n 1000 rm -rf二、环境依赖安装 yum -y install epel-releaseyum -y install daemonize三、安装Jenkins Jenkins官网传送带&#xff1a; …

Nginx配置WebSocket反向代理

1、WebSocket协议 ​ WebSocket协议相比较于HTTP协议成功握手后可以多次进行通讯&#xff0c;直到连接被关闭。但是WebSocket中的握手和HTTP中的握手兼容&#xff0c;它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的…

微服务入门---SpringCloud(一)

微服务入门---SpringCloud&#xff08;一&#xff09; 1.认识微服务1.0.学习目标1.1.单体架构1.2.分布式架构1.3.微服务1.4.SpringCloud1.5.总结 2.服务拆分和远程调用2.1.服务拆分原则2.2.服务拆分示例2.2.1.导入Sql语句2.2.2.导入demo工程 2.3.实现远程调用案例2.3.1.案例需求…

【Koa】[NoSQL] Koa中相关介绍和使用Redis MongoDB增删改查

目录 NoSQL非关系型数据库关系型数据库&#xff08;RMDB&#xff09;介绍非关系型数据库&#xff08;NoSQL&#xff09;介绍Redis & MongoDB 在 Koa 中使用 Redis (了解)Redis 的安装和使用在 Koa 中连接 和 调用 Redis 在 Koa 中使用 MongoDBMongoDB 的安装MongoShell 操作…

【Spring框架】SpringBoot配置文件

目录 配置文件作用application.properties中午乱码问题&#xff1a;配置文件里面的配置类型分类SpringBoot热部署properties基本语法properties配置文件的优缺点&#xff1a;yml配置文件说明yml基本语法配置对象properties VS yml 配置文件作用 整个项⽬中所有重要的数据都是在…

SQL-每日一题【1068. 产品销售分析 I】

题目 销售表 Sales&#xff1a; 产品表 Product&#xff1a; 写一条SQL 查询语句获取 Sales 表中所有产品对应的 产品名称 product_name 以及该产品的所有 售卖年份 year 和 价格 price 。 查询结果中的顺序无特定要求。 查询结果格式示例如下&#xff1a; 解题思路 1.题目要…

ERROR 1064 - You have an error in your SQL syntax;

ERROR 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near (/, 少个逗号吧&#xff0c;以前开始写SQL&#xff0c;特别是修改SQL的时候容易出现这样错误。 而且自己也知道在附近…