diff --git a/README.txt b/README.txt index e599064..c443651 100644 --- a/README.txt +++ b/README.txt @@ -1,24 +1,23 @@ -windows 开启xftp(目前版本: frp_0.53.2_windows_amd64 ) -在./P2PfilePython文件夹下右击打开终端 +操作说明: +本软件不需要安装为免安装绿色软件。 +需在系统 windows环境上运行主程序SnailSend.exe,选下面密钥一个密钥才可以发送和接收文件。(注意:发送和接收密钥必须一致,必须为同一个) +发送文件可以开多个程序同时发送,但接收文件只能要开一个。(注意:接收文件开多个会将影响原先接收程序) +密钥可以重复使用,如遇到密钥已经被占用的情况请换一个密钥。 +请关闭你的网络开启UDP防护,避免接收不到文件。 -#发送命令 (windows) +误杀说明: +有些杀毒软件会将本软件视为病毒,可以关闭杀毒软件。 -python.exe .\p2pfile.py --mode send --host 127.0.0.1 --port 7001 --path D:\navidrome-data.zip --psk 123456@@ +密钥: +1. ENbOUMvXJGWuA623@@@|MyvKorrmGv3Xn8FTARkiTy3mvRwTJGrE|2zxJDn9LzF4CFjHspBTmdRHuh6ew11C5|Q6XThKq457kLuwERbUPPMEnxjYUzVKGk -#接收命令 (windows) +2. ENbOUMvXJGWuA623@@@|2E8UaE0qQm8bVtAFqzUhXJWMbPjBh8Gq|0AqiomQgKGpzea89ZbhWeRVNJ7crXZt6|JjTTRBiq89o9Lm4Zg6bgjpeXc9NBU5tz -python.exe .\p2pfile.py --mode recv --host 47.97.6.201 --port 6000 --outdir ./ --psk 123456@@ +3. ENbOUMvXJGWuA623@@@|7tKyGbtCcwiWb8ZvDjLMDCUDgunsE9x7|5ToF67sH35W64Pf6sPz1BTCPfB5sNcuF|vZ9McB85fHfvumBjxUzRrb416TATE8EP -python3 ./p2pfile.py --mode recv --host 127.0.0.1 --port 6000 --outdir ./ --psk 123456 +4. ENbOUMvXJGWuA623@@@|E6egfQoUog2rpGRhr2VhtrZE3V4WTBij|b3v6XxVPvcWuuau2uKPqHhTV4KZ74kZi|MW1Bm9NPy4fdqTcE3N9RxijP8U319V2s +5. ENbOUMvXJGWuA623@@@|aw1fohFnPcZEjRcRogENJzBbgPsNqjV3|Lcaa6hmVU7nXKoHmZDYp3EnaUbTfARnh|M0BUnkgzPxR0Ebdp9NQ4VUtm4EpTDvPR -参数说明: - --mode", choices=["send", "recv"], required=True) - --host", help="接收端IP (send模式必需)") - --port", type=int, required=True) - --path", help="要发送的文件/目录 (send模式必需)") - --outdir", help="接收保存目录 (recv模式必需)") - --rate", help="限速,例: 500K, 5M(每连接)") - --psk", required=True, help="预共享密钥,用于保证不被串口,可自定义") - --conn", type=int, default=4, help="并行连接数,默认 4") - --part-size", type=int, default=64, help="分片大小(MB),默认 64") \ No newline at end of file +作者:蜗牛 +邮件:mvcers@gmail.com \ No newline at end of file diff --git a/main.py.bak b/main.py.bak deleted file mode 100644 index f57600d..0000000 --- a/main.py.bak +++ /dev/null @@ -1,877 +0,0 @@ -import tkinter as tk -from tkinter import ttk, messagebox, scrolledtext, filedialog -import threading -import subprocess -import os -import sys -import time -import random -import subprocess -from subprocess import CREATE_NO_WINDOW, STARTUPINFO, STARTF_USESHOWWINDOW - -class FileTransferApp: - def __init__(self, root): - self.root = root - self.root.title("蜗牛创造的高速文件传输") - self.root.geometry("900x700") - self.root.configure(bg='white') # 设置窗口背景为白色 - - # 设置样式 - self.setup_styles() - - # 创建主框架容器 - self.main_frame = tk.Frame(self.root, bg='white') - self.main_frame.pack(fill='both', expand=True, padx=20, pady=20) - - # 显示欢迎界面 - self.show_welcome_screen() - - def setup_styles(self): - """设置界面样式""" - style = ttk.Style() - style.configure('TButton', font=('Microsoft YaHei', 10)) - style.configure('Primary.TButton', background='#3498db', foreground='white') - style.configure('Success.TButton', background='#2ecc71', foreground='white') - style.configure('Danger.TButton', background='#e74c3c', foreground='white') - style.configure('Secondary.TButton', background='#95a5a6', foreground='white') - - def clear_frame(self): - """清除当前框架中的所有控件""" - for widget in self.main_frame.winfo_children(): - widget.destroy() - - def show_welcome_screen(self): - """显示欢迎界面""" - self.clear_frame() - - # 顶部logo区域 - logo_frame = tk.Frame(self.main_frame, bg='white') - logo_frame.pack(pady=(30, 20)) - - # 欢迎标签 - welcome_label = tk.Label( - logo_frame, - text="🐌 欢迎来到蜗牛创造的高速世界", - font=("Microsoft YaHei", 20, "bold"), - fg="#2c3e50", - bg='white' - ) - welcome_label.pack() - - # 副标题 - subtitle_label = tk.Label( - logo_frame, - text="安全、高速的文件传输解决方案", - font=("Microsoft YaHei", 12), - fg="#7f8c8d", - bg='white' - ) - subtitle_label.pack(pady=(5, 30)) - - # 功能卡片框架 - card_frame = tk.Frame(self.main_frame, bg='white') - card_frame.pack(pady=20) - - # 发送卡片 - send_card = tk.Frame(card_frame, bg='#f8f9fa', relief='raised', bd=1, padx=20, pady=20) - send_card.pack(side='left', padx=15) - - send_icon = tk.Label(send_card, text="📤", font=("Arial", 24), bg='#f8f9fa') - send_icon.pack() - - send_title = tk.Label(send_card, text="发送文件", font=("Microsoft YaHei", 14, "bold"), fg="#2c3e50", bg='#f8f9fa') - send_title.pack(pady=(10, 5)) - - send_desc = tk.Label(send_card, text="快速安全地发送文件", font=("Microsoft YaHei", 9), fg="#7f8c8d", bg='#f8f9fa') - send_desc.pack(pady=(0, 15)) - - send_button = tk.Button( - send_card, - text="开始发送", - command=self.show_send_screen, - font=("Microsoft YaHei", 11, "bold"), - bg="#3498db", - fg="white", - width=12, - height=2, - relief='flat', - cursor='hand2' - ) - send_button.pack() - - # 接收卡片 - receive_card = tk.Frame(card_frame, bg='#f8f9fa', relief='raised', bd=1, padx=20, pady=20) - receive_card.pack(side='left', padx=15) - - receive_icon = tk.Label(receive_card, text="📥", font=("Arial", 24), bg='#f8f9fa') - receive_icon.pack() - - receive_title = tk.Label(receive_card, text="接收文件", font=("Microsoft YaHei", 14, "bold"), fg="#2c3e50", bg='#f8f9fa') - receive_title.pack(pady=(10, 5)) - - receive_desc = tk.Label(receive_card, text="安全可靠地接收文件", font=("Microsoft YaHei", 9), fg="#7f8c8d", bg='#f8f9fa') - receive_desc.pack(pady=(0, 15)) - - receive_button = tk.Button( - receive_card, - text="开始接收", - command=self.show_receive_screen, - font=("Microsoft YaHei", 11, "bold"), - bg="#2ecc71", - fg="white", - width=12, - height=2, - relief='flat', - cursor='hand2' - ) - receive_button.pack() - - # 底部信息 - footer_frame = tk.Frame(self.main_frame, bg='white') - footer_frame.pack(side='bottom', pady=20) - - footer_label = tk.Label( - footer_frame, - text="© 2024 蜗牛创造 - 让文件传输更简单", - font=("Microsoft YaHei", 9), - fg="#bdc3c7", - bg='white' - ) - footer_label.pack() - - def create_styled_button(self, parent, text, command, bg_color, width=10): - """创建样式统一的按钮""" - return tk.Button( - parent, - text=text, - command=command, - font=("Microsoft YaHei", 10, "bold"), - bg=bg_color, - fg="white", - width=width, - relief='flat', - cursor='hand2', - padx=10, - pady=5 - ) - - def show_send_screen(self): - """显示发送界面""" - self.clear_frame() - - # 标题栏 - title_frame = tk.Frame(self.main_frame, bg='white') - title_frame.pack(fill='x', pady=(10, 20)) - - back_button = self.create_styled_button(title_frame, "← 返回", self.show_welcome_screen, "#95a5a6", 8) - back_button.pack(side='left') - - title_label = tk.Label( - title_frame, - text="📤 文件发送", - font=("Microsoft YaHei", 16, "bold"), - fg="#2c3e50", - bg='white' - ) - title_label.pack(side='left', padx=10) - - # 输入卡片 - input_card = tk.Frame(self.main_frame, bg='#f8f9fa', relief='raised', bd=1, padx=20, pady=20) - input_card.pack(fill='x', pady=(0, 15)) - - # 密钥输入 - key_frame = tk.Frame(input_card, bg='#f8f9fa') - key_frame.pack(fill='x', pady=5) - - tk.Label(key_frame, text="🔑 密钥:", font=("Microsoft YaHei", 10), bg='#f8f9fa').pack(side='left') - self.send_key_entry = tk.Entry(key_frame, font=("Microsoft YaHei", 10), width=40, relief='solid', bd=1) - self.send_key_entry.pack(side='left', padx=10) - - # 文件选择 - file_frame = tk.Frame(input_card, bg='#f8f9fa') - file_frame.pack(fill='x', pady=10) - - tk.Label(file_frame, text="📁 文件路径:", font=("Microsoft YaHei", 10), bg='#f8f9fa').pack(side='left') - self.file_path_var = tk.StringVar() - file_entry = tk.Entry(file_frame, textvariable=self.file_path_var, font=("Microsoft YaHei", 10), - width=30, state='readonly', relief='solid', bd=1) - file_entry.pack(side='left', padx=10) - - browse_button = self.create_styled_button(file_frame, "浏览文件", self.browse_file, "#8e44ad", 10) - browse_button.pack(side='left') - - # 按钮组 - button_frame = tk.Frame(self.main_frame, bg='white') - button_frame.pack(pady=15) - - self.send_connect_button = self.create_styled_button(button_frame, "🔄 连接", self.start_send_connection, "#27ae60") - self.send_connect_button.pack(side='left', padx=5) - - self.send_file_button = self.create_styled_button(button_frame, "🚀 发送文件", self.start_file_send, "#e74c3c") - self.send_file_button.pack(side='left', padx=5) - self.send_file_button.config(state='disabled') - - self.send_stop_button = self.create_styled_button(button_frame, "⏹️ 停止", self.stop_send_connection, "#95a5a6") - self.send_stop_button.pack(side='left', padx=5) - self.send_stop_button.config(state='disabled') - - # 状态显示 - status_frame = tk.Frame(self.main_frame, bg='white') - status_frame.pack(fill='x', pady=5) - - self.send_status_label = tk.Label( - status_frame, - text="📊 状态: 等待连接", - font=("Microsoft YaHei", 10), - fg="#7f8c8d", - bg='white' - ) - self.send_status_label.pack() - - # 输出区域 - output_card = tk.Frame(self.main_frame, bg='#f8f9fa', relief='raised', bd=1, padx=15, pady=15) - output_card.pack(fill='both', expand=True, pady=(10, 0)) - - output_label = tk.Label(output_card, text="📋 发送日志:", font=("Microsoft YaHei", 10), bg='#f8f9fa') - output_label.pack(anchor='w') - - self.send_output = scrolledtext.ScrolledText( - output_card, - height=12, - width=80, - font=("Consolas", 9), - state='disabled', - relief='solid', - bd=1, - bg='#ffffff' - ) - self.send_output.pack(fill='both', expand=True, pady=(5, 0)) - - # 初始信息 - self.append_send_output("等待输入密钥并选择文件...\n") - self.append_send_output("密钥格式应为: token|sk|psk|sern\n") - - # 进程引用 - self.send_frpc_process = None - self.send_p2p_process = None - self.is_send_running = False - - - def show_receive_screen(self): - """显示接收界面""" - self.clear_frame() - - # 标题栏 - title_frame = tk.Frame(self.main_frame, bg='white') - title_frame.pack(fill='x', pady=(10, 20)) - - back_button = self.create_styled_button(title_frame, "← 返回", self.show_welcome_screen, "#95a5a6", 8) - back_button.pack(side='left') - - title_label = tk.Label( - title_frame, - text="📥 文件接收", - font=("Microsoft YaHei", 16, "bold"), - fg="#2c3e50", - bg='white' - ) - title_label.pack(side='left', padx=10) - - # 输入卡片 - input_card = tk.Frame(self.main_frame, bg='#f8f9fa', relief='raised', bd=1, padx=20, pady=20) - input_card.pack(fill='x', pady=(0, 15)) - - # 密钥输入 - key_frame = tk.Frame(input_card, bg='#f8f9fa') - key_frame.pack(fill='x', pady=5) - - tk.Label(key_frame, text="🔑 密钥:", font=("Microsoft YaHei", 10), bg='#f8f9fa').pack(side='left') - self.receive_key_entry = tk.Entry(key_frame, font=("Microsoft YaHei", 10), width=40, relief='solid', bd=1) - self.receive_key_entry.pack(side='left', padx=10) - - # 保存路径选择 - path_frame = tk.Frame(input_card, bg='#f8f9fa') - path_frame.pack(fill='x', pady=10) - - tk.Label(path_frame, text="💾 保存路径:", font=("Microsoft YaHei", 10), bg='#f8f9fa').pack(side='left') - self.receive_path_var = tk.StringVar() - self.receive_path_var.set(".\\received_files") # 默认路径 - path_entry = tk.Entry(path_frame, textvariable=self.receive_path_var, font=("Microsoft YaHei", 10), - width=30, relief='solid', bd=1) - path_entry.pack(side='left', padx=10) - - browse_path_button = self.create_styled_button(path_frame, "浏览文件夹", self.browse_receive_path, "#8e44ad", 12) - browse_path_button.pack(side='left') - - # 按钮组 - button_frame = tk.Frame(self.main_frame, bg='white') - button_frame.pack(pady=15) - - self.connect_button = self.create_styled_button(button_frame, "🔄 连接", self.start_frpc_connection, "#27ae60") - self.connect_button.pack(side='left', padx=5) - - self.stop_button = self.create_styled_button(button_frame, "⏹️ 停止", self.stop_frpc_connection, "#e74c3c") - self.stop_button.pack(side='left', padx=5) - self.stop_button.config(state='disabled') - - # 状态显示 - status_frame = tk.Frame(self.main_frame, bg='white') - status_frame.pack(fill='x', pady=5) - - self.status_label = tk.Label( - status_frame, - text="📊 状态: 等待连接", - font=("Microsoft YaHei", 10), - fg="#7f8c8d", - bg='white' - ) - self.status_label.pack() - - # 输出区域 - output_card = tk.Frame(self.main_frame, bg='#f8f9fa', relief='raised', bd=1, padx=15, pady=15) - output_card.pack(fill='both', expand=True, pady=(10, 0)) - - output_label = tk.Label(output_card, text="📋 接收日志:", font=("Microsoft YaHei", 10), bg='#f8f9fa') - output_label.pack(anchor='w') - - self.receive_output = scrolledtext.ScrolledText( - output_card, - height=12, - width=80, - font=("Consolas", 9), - state='disabled', - relief='solid', - bd=1, - bg='#ffffff' - ) - self.receive_output.pack(fill='both', expand=True, pady=(5, 0)) - - # 初始信息 - self.append_output("等待输入密钥并连接...\n") - self.append_output("密钥格式应为: token|sk|psk|sern\n") - self.append_output(f"文件将保存到: {self.receive_path_var.get()}\n") - - # 进程引用 - self.frpc_process = None - self.p2p_process = None - self.is_running = False - self.current_stage = "idle" - - def browse_receive_path(self): - """浏览选择接收文件保存路径""" - folder_path = filedialog.askdirectory( - title="选择文件保存目录", - initialdir="." - ) - if folder_path: - self.receive_path_var.set(folder_path) - self.append_output(f"✅ 文件将保存到: {folder_path}\n") - - def browse_file(self): - """浏览选择要发送的文件""" - file_path = filedialog.askopenfilename( - title="选择要发送的文件", - filetypes=[ - ("所有文件", "*.*"), - ("文本文件", "*.txt"), - ("图片文件", "*.jpg *.png *.gif"), - ("视频文件", "*.mp4 *.avi *.mov"), - ("文档文件", "*.pdf *.doc *.docx") - ] - ) - if file_path: - self.file_path_var.set(file_path) - self.append_send_output(f"✅ 已选择文件: {file_path}\n") - - def create_send_ini(self, token, sk, sern, bport): - """创建send.ini配置文件""" - ini_content = f"""[common] -local_ip = 0.0.0.0 -server_addr = 47.97.6.201 -server_port = 7100 -token = {token} - - -[xtcp_visitor] -type = xtcp -role = visitor -server_name = {sern} -sk = {sk} -bind_ip = 127.0.0.1 -bind_port = 7001 -""" - try: - with open('./send.ini', 'w', encoding='utf-8') as f: - f.write(ini_content) - self.append_send_output(f"配置文件 send.ini 创建成功\n") - return True - except Exception as e: - self.append_send_output(f"创建配置文件失败: {e}\n") - return False - - def monitor_send_frpc_output(self): - """监控发送NATCC输出""" - try: - for line in iter(self.send_frpc_process.stdout.readline, ''): - if not self.is_send_running: - break - if line: - self.append_send_output(f"[NATC] {line}") - except: - pass - - def monitor_send_p2p_output(self): - """监控发送P2P输出""" - try: - for line in iter(self.send_p2p_process.stdout.readline, ''): - if not self.is_send_running: - break - if line.strip(): - self.append_send_output(f"[P2P] {line}") - - # 进程结束后检查退出码 - return_code = self.send_p2p_process.wait() - if self.is_send_running: - self.append_send_output(f"[P2P] 文件发送完成,退出码: {return_code}\n") - self.send_file_button.config(state='normal') - - except Exception as e: - self.append_send_output(f"[P2P] 输出监控错误: {e}\n") - - def execute_send_frpc(self): - """执行发送NATCC命令""" - try: - self.update_send_status("正在启动NATC客户端...") - - self.send_frpc_process = subprocess.Popen( - ['.\\gc.exe', '-c', '.\\send.ini'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - encoding='utf-8', - errors='replace', - bufsize=1, - universal_newlines=True, - creationflags=subprocess.CREATE_NO_WINDOW # 不创建窗口 - ) - - # 启动输出监控线程 - output_thread = threading.Thread(target=self.monitor_send_frpc_output, daemon=True) - output_thread.start() - - # 等待一段时间让NATCC建立连接 - self.append_send_output("[NATC] 等待NATC连接建立...\n") - time.sleep(3) - - # 检查NATCC进程是否还在运行 - if self.send_frpc_process.poll() is not None: - self.append_send_output("[NATC] NATC客户端意外退出\n") - return - - # 如果还在运行,启用发送文件按钮 - if self.is_send_running: - self.append_send_output("[NATC] NATC连接已建立,可以发送文件\n") - self.send_file_button.config(state='normal') - self.update_send_status("就绪,可以发送文件") - - except Exception as e: - self.append_send_output(f"[NATC] 执行错误: {e}\n") - - def execute_send_file(self): - """执行文件发送""" - try: - self.update_send_status("正在发送文件...") - - file_path = self.file_path_var.get() - if not file_path or not os.path.exists(file_path): - self.append_send_output("[错误] 文件路径无效或文件不存在\n") - return - - self.send_p2p_process = subprocess.Popen( - [ - '.\\python.exe', - '.\\p2pfile.py', - '--mode', 'send', - '--path', file_path, - '--psk', self.send_psk - '--port', self.bport - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - encoding='gbk', - errors='replace', - bufsize=1, - universal_newlines=True, - creationflags=subprocess.CREATE_NO_WINDOW # 不创建窗口 - ) - - self.append_send_output(f"[P2P] 开始发送文件: {os.path.basename(file_path)}\n") - - # 启动输出监控线程 - output_thread = threading.Thread(target=self.monitor_send_p2p_output, daemon=True) - output_thread.start() - - except Exception as e: - self.append_send_output(f"[P2P] 执行错误: {e}\n") - - def start_send_connection(self): - """开始发送连接""" - key = self.send_key_entry.get().strip() - if not key: - messagebox.showwarning("输入错误", "请输入密钥") - return - - # 解析密钥 - if '|' not in key: - messagebox.showwarning("格式错误", "密钥格式应为: token|sk|psk|sern|bport") - return - - parts = key.split('|') - if len(parts) < 4: - messagebox.showwarning("格式错误", "密钥格式应为: token|sk|psk|sern|bport") - return - - token = parts[0].strip() - sk = parts[1].strip() - psk = parts[2].strip() - sern = parts[3].strip() - bport = parts[4].strip() - - self.send_token = token - self.send_sk = sk - self.send_psk = psk - self.send_sern = sern - self.bport = bport - - # 创建配置文件 - if not self.create_send_ini(token, sk, sern, bport): - return - - # 清空输出框 - self.send_output.config(state='normal') - self.send_output.delete(1.0, tk.END) - self.send_output.config(state='disabled') - - self.append_send_output(f"开始连接流程...\n") - self.append_send_output(f"Token: {token}\n") - self.append_send_output(f"SK: {sk}\n") - self.append_send_output(f"PSK: {psk}\n") - self.append_send_output(f"SERN: {sern}\n") - self.append_send_output(f"BPORT: {bport}\n") - self.append_send_output("-" * 50 + "\n") - - # 禁用连接按钮,启用停止按钮 - self.send_connect_button.config(state='disabled') - self.send_stop_button.config(state='normal') - - # 设置运行标志 - self.is_send_running = True - self.update_send_status("启动中...") - - # 在新线程中执行NATCC - self.send_process_thread = threading.Thread(target=self.execute_send_frpc, daemon=True) - self.send_process_thread.start() - - def start_file_send(self): - """开始发送文件""" - if not self.file_path_var.get(): - messagebox.showwarning("选择错误", "请先选择要发送的文件") - return - - # 禁用发送按钮,避免重复点击 - self.send_file_button.config(state='disabled') - - # 在新线程中执行文件发送 - send_thread = threading.Thread(target=self.execute_send_file, daemon=True) - send_thread.start() - - def stop_send_connection(self): - """停止发送连接""" - self.is_send_running = False - self.update_send_status("正在停止...") - - # 停止NATCC进程 - if self.send_frpc_process and self.send_frpc_process.poll() is None: - try: - self.send_frpc_process.terminate() - self.append_send_output("[NATC] 正在停止NATC客户端...\n") - except: - pass - - # 停止P2P进程 - if self.send_p2p_process and self.send_p2p_process.poll() is None: - try: - self.send_p2p_process.terminate() - self.append_send_output("[P2P] 正在停止文件发送...\n") - except: - pass - - time.sleep(1) - - self.send_connect_button.config(state='normal') - self.send_file_button.config(state='disabled') - self.send_stop_button.config(state='disabled') - self.update_send_status("已停止") - self.append_send_output("所有进程已停止\n") - - def update_send_status(self, status): - """更新发送状态标签""" - self.send_status_label.config(text=f"状态: {status}") - - def append_send_output(self, message): - """向发送输出框添加消息""" - self.send_output.config(state='normal') - self.send_output.insert(tk.END, message) - self.send_output.see(tk.END) - self.send_output.config(state='disabled') - - - - def create_service_ini(self, token, sk, sern, bport): - """创建service.ini配置文件""" - ini_content = f"""[common] -server_addr = 47.97.6.201 -server_port = 7100 -token = {token} - -[{sern}] -type = xtcp -sk = {sk} -local_ip = 127.0.0.1 -local_port = {bport} -""" - try: - with open('./service.ini', 'w', encoding='utf-8') as f: - f.write(ini_content) - self.append_output(f"配置文件 service.ini 创建成功\n") - return True - except Exception as e: - self.append_output(f"创建配置文件失败: {e}\n") - return False - - def execute_frpc(self): - """执行frpc命令""" - try: - self.current_stage = "frpc" - self.update_status("正在启动NATC客户端...") - - self.frpc_process = subprocess.Popen( - ['.\\gc.exe', '-c', '.\\service.ini'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - encoding='utf-8', - errors='replace', - bufsize=1, - universal_newlines=True, - creationflags=subprocess.CREATE_NO_WINDOW # 不创建窗口 - ) - - # 启动输出监控线程 - output_thread = threading.Thread(target=self.monitor_frpc_output, daemon=True) - output_thread.start() - - # 等待一段时间让NATCC建立连接 - self.append_output("[NATC] 等待NATC连接建立...\n") - time.sleep(3) # 等待3秒让NATCC建立连接 - - # 检查NATCC进程是否还在运行 - if self.frpc_process.poll() is not None: - self.append_output("[NATC] NATC客户端意外退出\n") - return - - # 如果还在运行,启动P2P - if self.is_running: - self.append_output("[NATC] NATC连接已建立,启动P2P接收器...\n") - self.execute_p2p_receiver() - - except Exception as e: - self.append_output(f"[NATC] 执行错误: {e}\n") - - def monitor_frpc_output(self): - """监控NATCC输出""" - try: - for line in iter(self.frpc_process.stdout.readline, ''): - if not self.is_running: - break - if line: - self.append_output(f"[NATC] {line}") - except: - pass - - def monitor_p2p_output(self): - """监控P2P输出并检测进程结束""" - try: - for line in iter(self.p2p_process.stdout.readline, ''): - if not self.is_running: - break - if line.strip(): - self.append_output(f"[P2P] {line}") - - # 进程结束后检查退出码 - return_code = self.p2p_process.wait() - if self.is_running: - self.append_output(f"[P2P] P2P接收器已停止,退出码: {return_code}\n") - - except Exception as e: - self.append_output(f"[P2P] 输出监控错误: {e}\n") - - def execute_p2p_receiver(self): - """执行P2P文件接收器""" - try: - self.current_stage = "p2p" - self.update_status("正在启动P2P文件接收...") - - # 获取用户选择的保存路径 - save_path = self.receive_path_var.get().strip() - if not save_path: - save_path = ".\\received_files" # 默认路径 - - # 创建目录(如果不存在) - os.makedirs(save_path, exist_ok=True) - - self.p2p_process = subprocess.Popen( - [ - '.\\python.exe', - '.\\p2pfile.py', - '--mode', 'recv', - '--psk', self.current_psk, - '--outdir', save_path, - '--port', self.bport - ], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - encoding='gbk', - errors='replace', - bufsize=1, - universal_newlines=True, - creationflags=subprocess.CREATE_NO_WINDOW # 不创建窗口 - ) - - self.append_output("[P2P] 启动P2P文件接收器...\n") - self.append_output(f"[P2P] 使用PSK: {self.current_psk}\n") - self.append_output(f"[P2P] 文件保存路径: {save_path}\n") - - # 启动输出监控线程 - output_thread = threading.Thread(target=self.monitor_p2p_output, daemon=True) - output_thread.start() - - # 检查进程是否立即失败 - time.sleep(1) - if self.p2p_process.poll() is not None: - self.append_output("[P2P] P2P接收器启动失败\n") - - except Exception as e: - self.append_output(f"[P2P] 执行错误: {e}\n") - - def start_frpc_connection(self): - """开始NATC连接和P2P接收""" - key = self.receive_key_entry.get().strip() - if not key: - messagebox.showwarning("输入错误", "请输入密钥") - return - - # 解析密钥 - if '|' not in key: - messagebox.showwarning("格式错误", "密钥格式应为: token|sk|psk|sern") - return - - parts = key.split('|') - if len(parts) < 4: - messagebox.showwarning("格式错误", "密钥格式应为: token|sk|psk|sern") - return - - token = parts[0].strip() - sk = parts[1].strip() - psk = parts[2].strip() - sern = parts[3].strip() - bport = parts[4].strip() - - self.current_token = token - self.current_sk = sk - self.current_psk = psk - self.current_sern = sern - self.bport = bport - - # 获取保存路径并显示 - save_path = self.receive_path_var.get() - self.append_output(f"📁 保存路径: {save_path}\n") - - - # 创建配置文件 - if not self.create_service_ini(token, sk, sern, bport): - return - - # 清空输出框 - self.receive_output.config(state='normal') - self.receive_output.delete(1.0, tk.END) - self.receive_output.config(state='disabled') - - self.append_output(f"开始连接流程...\n") - self.append_output(f"Token: {token}\n") - self.append_output(f"SK: {sk}\n") - self.append_output(f"PSK: {psk}\n") - self.append_output(f"SERN: {sern}\n") - self.append_output(f"保存路径: {save_path}\n") - self.append_output(f"port: {bport}\n") - self.append_output("-" * 50 + "\n") - - # 禁用连接按钮,启用停止按钮 - self.connect_button.config(state='disabled') - self.stop_button.config(state='normal') - - # 设置运行标志 - self.is_running = True - self.update_status("启动中...") - - # 在新线程中执行 - self.process_thread = threading.Thread(target=self.execute_frpc, daemon=True) - self.process_thread.start() - - - def stop_frpc_connection(self): - """停止所有进程""" - self.is_running = False - self.update_status("正在停止...") - - # 停止NATCC进程 - if self.frpc_process and self.frpc_process.poll() is None: - try: - self.frpc_process.terminate() - self.append_output("[NATC] 正在停止NATC客户端...\n") - except: - pass - - # 停止P2P进程 - if self.p2p_process and self.p2p_process.poll() is None: - try: - self.p2p_process.terminate() - self.append_output("[P2P] 正在停止P2P接收器...\n") - except: - pass - - time.sleep(1) # 给进程一些时间结束 - - self.connect_button.config(state='normal') - self.stop_button.config(state='disabled') - self.update_status("已停止") - self.append_output("所有进程已停止\n") - - def update_status(self, status): - """更新状态标签""" - self.status_label.config(text=f"状态: {status}") - - def append_output(self, message): - """向输出框添加消息""" - self.receive_output.config(state='normal') - self.receive_output.insert(tk.END, message) - self.receive_output.see(tk.END) # 自动滚动到底部 - self.receive_output.config(state='disabled') - -# 创建主窗口并运行程序 -if __name__ == "__main__": - root = tk.Tk() - app = FileTransferApp(root) - root.mainloop() \ No newline at end of file