在Windows和Ubuntu中, 如何通用建立服务来传输"流"数据


1. 在 Ubuntu 端接收命令 (配合 Python 方案):
    因为 Python 发送的是 tar.gz 流,Ubuntu 端的接收命令保持不变:


sudo nc -l -p 9999 | sudo tar -xz -C /data/mysql

    (此时终端会卡住等待连接)



2. 在windwos端, 在python环境里面, 创建py文件, 并执行
    给脚本加上“进度条”和“流量统计”

    请使用以下增强版脚本覆盖原来的 send.py


import socket
import tarfile
import gzip
import os
import sys
import time

# ================= 配置区域 =================
TARGET_IP = '192.168.99.150'
TARGET_PORT = 9999
SOURCE_DIR_NAME = 'Data'
BASE_PATH = r'G:\\'
# ===========================================

class SocketWrapper:
    def __init__(self, sock):
        self.sock = sock
        self.bytes_sent = 0
        self.start_time = time.time()
    
    def write(self, data):
        self.sock.sendall(data)
        self.bytes_sent += len(data)
        
        # 每发送 500MB 打印一次进度 (500 * 1024 * 1024)
        if self.bytes_sent % (500 * 1024 * 1024) < len(data):
            elapsed = time.time() - self.start_time
            speed = self.bytes_sent / elapsed / (1024 * 1024) if elapsed > 0 else 0
            print(f"已发送: {self.bytes_sent / (1024*1024*1024):.2f} GB | 速度: {speed:.2f} MB/s | 耗时: {elapsed:.0f}s")
    
    def flush(self):
        pass
    
    def close(self):
        self.sock.close()

def get_dir_size(path):
    total = 0
    try:
        for entry in os.scandir(path):
            if entry.is_file():
                total += entry.stat().st_size
            elif entry.is_dir():
                total += get_dir_size(entry.path)
    except Exception:
        pass
    return total

def main():
    full_source_path = os.path.join(BASE_PATH, SOURCE_DIR_NAME)
    
    if not os.path.exists(full_source_path):
        print(f"错误: 找不到路径 {full_source_path}")
        return

    # 估算大小
    print("正在计算源数据大小 (可能需要几秒)...")
    total_size = get_dir_size(full_source_path)
    print(f"源数据总大小约为: {total_size / (1024*1024*1024):.2f} GB")
    print(f"正在连接 {TARGET_IP}:{TARGET_PORT} ...")

    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置超时,防止卡死无响应
        s.settimeout(30) 
        s.connect((TARGET_IP, TARGET_PORT))
        s.settimeout(None) # 连接成功后取消超时,防止大文件传输中断
        print("连接成功!开始压缩并传输数据...")
        print("提示:如果长时间没有新的进度输出,可能是网络拥堵或磁盘IO瓶颈,请耐心等待。")

        wrapped_socket = SocketWrapper(s)

        # 核心传输逻辑
        with gzip.GzipFile(fileobj=wrapped_socket, mode='wb', compresslevel=1) as gzip_file: 
            # compresslevel=1 最快,虽然压缩率低一点,但能极大减少 CPU 瓶颈,加快整体传输
            with tarfile.open(fileobj=gzip_file, mode='w') as tar:
                tar.add(full_source_path, arcname=SOURCE_DIR_NAME)
        
        s.close()
        print("传输完成!")

    except ConnectionRefusedError:
        print("连接被拒绝。请检查 Ubuntu 是否运行了 nc 命令,以及防火墙设置。")
    except Exception as e:
        print(f"发生错误: {e}")
        import traceback
        traceback.print_exc()

if __name__ == '__main__':
    main()


3. 检查 Ubuntu (接收端) 的状态,  打开另一个终端,实时监控 /data/mysql 的大小变化:


watch -n 2 'du -sh /data/mysql'

    

    如果数字在不断增加,说明解压和写入正常。 
    如果数字一直是 0 或者很小,说明数据堵在内存里没写进去,或者 tar 命令参数有误。


    或者安装相应的工具来实时检查网络流量

# 安装 iftop (如果没有)
sudo apt install iftop -y
# 监控 9999 端口的流量
sudo iftop -P -n -p -f "port 9999"

    如果你看到带宽在跑(例如 50Mbps, 100Mbps),说明传输正常,只是数据量大,需要时间。 
    如果带宽为 0,说明连接建立了但数据没发过来(可能是 Windows 端读取磁盘慢,或者压缩慢)。

白俊遥博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论