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

news2024/11/17 21:27:20

原始程序:

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文件传输速率极大提高了,并且可以正确测算到速率与时延

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

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

相关文章

03-树1 树的同构(c++)

03-树1 树的同构 给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2&#xff0c;则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的&#xff0c;因为我们把其中一棵树的结点A、B、G的左右孩子互换后&#xff0c;就得到另外一棵树。而图2就不是同构的。 现…

[Linux]线程基本知识

概念 进程 一个正在执行的程序&#xff0c;它是资源分配的最小单位 进程中的事情需要按照一定的顺序逐个进行 进程出现了很多弊端: 一是由于进程是资源拥有者&#xff0c;创建、撤消与切换存在较大的时空开销&#xff0c;因此需要引入轻型进程&#xff1b; 二是由于对称多…

USB3.0之设备检测

1 USB超速SerDes原理介绍 1.1 SerDes Rx.Detect SerDes Rx.Detect的原理比较简单&#xff0c;就是通过一个逻辑电路比较RC时间常数的大小。 当Rx不存在时&#xff0c;RC时间常数较小。当Rx存在时&#xff0c;RC时间常数较大。 下面将详细描述其原理。 Figure 1-1 USB 3.0电缆 …

App 测试工具大全,收藏这篇就够了

随着移动互联网的高速发展&#xff0c;App应用非常火&#xff0c;测试工程师也会接触到各种app应用。除了人工测试之外&#xff0c;也可以通过一些测试工具来提高我们的测试效率&#xff0c;以下对于我用过或听过的app测试工具做了一个统一整理&#xff0c;欢迎补充。 一、APP自…

vue的事件绑定和修饰符

&#x1f600;前言 本片文章是vue系列第3篇整理了vue的事件绑定和修饰符以及注意事项和代码演示 &#x1f3e0;个人主页&#xff1a;尘觉主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是尘觉&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的…

Java | 继承、多态、抽象类与接口

目录 一、类的继承 二、Object类 2.1 getClass()方法 2.2 toString()方法 2.3 equals()方法 三 、对象类型的转换 3.1 向上转换 3.2 向下转型 四、使用instanceof关键字判断对象类型 五、方法的重载 六、final关键字 6.1 final变量 6.2 final方法 6.3 final类 七…

分冶算法 剑指 07 重建二叉树 排序算法:剑指45 把数组排成最小的数 10-I 斐波那契数列

来记录几个注意事项 1.vector容器里利用find&#xff08;&#xff09;函数 不同于map&#xff08;map有find方法&#xff09;&#xff0c;vector本身是没有find这一方法&#xff0c;其find是依靠algorithm来实现的。 所以要包含头文件 #include <iostream> #include <…

线程字符串传递方式

//扩展作业--参数传递 //思路: 当子线程退出的时候,pthread_exit((void *)88)--->传递给主线程 pthread_join(tid,(void *)&ret1) //函数---参数 #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include …

Y型结构,Y-shape PEG SCM,Y型聚乙二醇琥珀酰亚胺乙酸酯,具有独特的空间结构

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 规格单位&#xff1a;g |货期&#xff1a;按照具体的库存进行提供 | 纯度&#xff1a;95% PART1----​试剂描述&#xff1a; Y-shape PEG-SCM&#xff0c;Y型结构&#xff0c;具有2个PEG链和一个琥珀酰亚胺乙酸酯基因…

三用表校准仪TD1850多用表校准系统

直流电压标准源 ( DCV ) 输出范围&#xff1a;20 mV&#xff5e;1100 V 直流电流标准源 ( DCI ) 输出范围&#xff1a;2 μA&#xff5e;22 A或33 A 交流电压标准源 ( ACV ) 输出范围&#xff1a;20 mV&#xff5e;1100 V、45 Hz&#xff5e;1100 Hz 交流电流标准源 ( ACI )…

搜索与图论(一)

一、DFS与BFS 1.1深度优先搜索(DFS) DFS不具有最短性 //排列数字问题 #include<iostream> using namespace std;const int N 10; int n; int path[N]; bool st[N];void dfs(int u) {if(u n){for(int i 0;i < n;i) printf("%d",path[i]);puts("&qu…

抖音seo源代码开发搭建--开发者概述

抖音SEO源代码开发搭建需要有一定的开发技术和经验&#xff0c;一般需要掌握以下技能&#xff1a; 掌握HTML、CSS、JavaScript等前端技术&#xff0c;能够编写静态页面和交互效果&#xff1b;了解服务器端语言如PHP、Python等&#xff0c;并能够开发后端逻辑&#xff1b;熟悉数…

Android 中 app freezer 原理详解(一):S 版本

基于版本&#xff1a;Android S 0. 前言 在之前的两篇博文《Android 中app内存回收优化(一)》和 《Android 中app内存回收优化(二)》中详细剖析了 Android 中 app 内存优化的流程。这个机制的管理通过 CachedAppOptimizer 类管理&#xff0c;为什么叫这个名字&#xff0c;而不…

【AHK】通过唤醒窗口快捷菜单调节窗口位置/打开窗口控制菜单的其他方法

需求&#xff1a;触控板使用AHK传统控制窗口位置和大小的方式不方便&#xff0c;故打算通过快捷方式唤醒窗口移动图标的方式来调节。但本人有使用utools的习惯&#xff0c;altspace打开快捷方式菜单/窗口控制菜单会冲突&#xff0c;所以一直尝试新的打开该菜单的方式——先点击…

[语义分割] DeepLab v3(Cascaded model、ASPP model、两种ASPP对比、Multi-grid、训练细节)

Rethinking Atrous Convolution for Semantic Image Segmentation 论文地址&#xff1a;Rethinking Atrous Convolution for Semantic Image SegmentationPytorch 实现代码&#xff1a;pytorch_segmentation/deeplab_v3 这是一篇 2017 年发表在CVPR上的文章。相比 DeepLab V2 有…

一、前端高德地图注册、项目中引入、渲染标记(Marker)and覆盖物(Circle)

首先说明一下&#xff0c;下面的流程只是个人摸索and看文档梳理出来的&#xff0c;并不作为完全正确的流程。 首先&#xff0c;注册 高德开放平台 没有注册的可以点击右上角点击注册&#xff1b; 我们点个人的就ok&#xff1b; 信息完善之后我们到控制台&#xff0c;点击 应…

6个高清图片素材网站,免费下载,值得推荐~

关于图片素材网站&#xff0c;我一直都在推荐这几个&#xff0c;免费下载&#xff0c;可商用&#xff0c;建议收藏起来~ 菜鸟图库 https://www.sucai999.com/pic.html?vNTYwNDUx 网站主要是为新手设计师提供免费素材的&#xff0c;素材的质量都很高&#xff0c;类别也很多&a…

手机word怎么转换成pdf?这几个转换方法推荐给你

手机word怎么转换成pdf&#xff1f;将Word转换为PDF的主要原因是PDF格式具有更好的文件保护性和稳定性。PDF文件是一种可靠的文件格式&#xff0c;可以保护文件免受恶意软件和病毒的攻击&#xff0c;同时保持文件的格式和布局不变。此外&#xff0c;PDF文件可以在不同的操作系统…

【1】-Locust性能测试工具介绍与安装

Locust介绍 locust是一个开源的压测工具&#xff0c;其官网地址是Locust - A modern load testing framework&#xff0c;通过编写Python代码&#xff0c;可以轻松实现百万级的并发&#xff0c;相对于我们熟悉的Jmeter来说&#xff0c;其对压测机的要求更低&#xff0c;而且使…

MicroPython for ESP32

MicroPython for ESP32 开发板引脚图 环境搭建 参考资料 https://zhuanlan.zhihu.com/p/587027345 官方资料 https://docs.micropython.org/en/latest/ http://vcc-gnd.com/rtd/html/esp32/quickref.html#i2c 创建一个虚拟环境&#xff0c; conda create -n esp32 pytho…