解决 NET FTP Response error: (503) .

本文介绍了解决在使用.NET访问FTP时遇到的503错误(Bad Sequence of Commands)。通过设置FTPWebRequest对象的KeepAlive属性为False,可以避免在同一IP地址上重复使用会话导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1. 在应用。NET 访问FTP的Response来返回时,出现了如下错误。

 

 

2. 参考如下MSDN 和一些网络资源,尝试后解决了此问题.

   > Ftp GetFileSize randomly throws FTP error 503 (Bad Sequence of Commands)

   >FtpWebRequest re-sending USER and PASS commands half way through download loop

3. 问题是在此处应用此个FTP Request 之前曾经使用些地址创建了一个登录Session, 所以在后面同一地址会话建立时会有这个异常报告。

The remote server returned an error: (503) Bad sequence of commands.

 解决办法就是将 request 对象的 KeepAlive 设为 False,其后基于同一IP创建的Session将不会抛出异常了。

 

 

代码
FtpWebRequest reqFTP;
                    reqFTP 
=  (FtpWebRequest)FtpWebRequest.Create( new  Uri(sUnixURL)); // "ftp: // " + "10.2.159.69" + "/" + fileInf.Name));
                    reqFTP.Credentials  =   new  NetworkCredential( " dwei " " Admin98 " );
                    reqFTP.Method 
=  WebRequestMethods.Ftp.DownloadFile;
                    reqFTP.UseBinary 
=   true ;
                    reqFTP.KeepAlive 
=   false ;    //  If keepalive is true will make the same IP request response lead to failed !
                    FileStream outputStream  =   new  FileStream(FILE_NAME, FileMode.Create);
                    
//  Create the writer for data.
                    BinaryWriter w  =   new  BinaryWriter(outputStream);
                    FtpWebResponse response 
=  (FtpWebResponse)reqFTP.GetResponse();

 

 

 

[17:22:04.292] Log Level: 2 [17:22:04.294] remote-ssh@0.76.1 [17:22:04.294] win32 x64 [17:22:04.300] SSH Resolver called for "ssh-remote+112.74.167.19", attempt 1 [17:22:04.301] "remote.SSH.useLocalServer": false [17:22:04.301] "remote.SSH.showLoginTerminal": false [17:22:04.301] "remote.SSH.remotePlatform": {} [17:22:04.301] "remote.SSH.path": [17:22:04.301] "remote.SSH.configFile": [17:22:04.301] "remote.SSH.useFlock": true [17:22:04.301] "remote.SSH.lockfilesInTmp": false [17:22:04.302] "remote.SSH.localServerDownload": auto [17:22:04.302] "remote.SSH.remoteServerListenOnSocket": false [17:22:04.302] "remote.SSH.showLoginTerminal": false [17:22:04.302] "remote.SSH.defaultExtensions": [] [17:22:04.302] "remote.SSH.loglevel": 2 [17:22:04.302] "remote.SSH.enableDynamicForwarding": true [17:22:04.302] "remote.SSH.enableRemoteCommand": false [17:22:04.302] "remote.SSH.serverPickPortsFromRange": {} [17:22:04.303] "remote.SSH.serverInstallPath": {} [17:22:04.315] SSH Resolver called for host: 112.74.167.19 [17:22:04.315] Setting up SSH remote "112.74.167.19" [17:22:04.336] Using commit id "488a1f239235055e34e673291fb8d8c810886f81" and quality "stable" for server [17:22:04.338] Install and start server if needed [17:22:06.289] Checking ssh with "ssh -V" [17:22:06.380] > OpenSSH_for_Windows_9.5p1, LibreSSL 3.8.2 [17:22:06.383] Running script with connection command: ssh -T -D 49840 "112.74.167.19" bash [17:22:06.386] Terminal shell path: C:\WINDOWS\System32\cmd.exe [17:22:06.595] > [?9001h[?1004h [17:22:06.596] Got some output, clearing connection timeout [17:22:06.922] > root@112.74.167.19&#39;s password:]0;C:\WINDOWS\System32\cmd.exe [17:22:06.922] Showing password prompt [17:22:11.143] Got password response [17:22:11.143] "install" wrote data to terminal: "*********" [17:22:11.168] > [17:22:11.354] > 5e76bec89c36: running [17:22:11.401] > Acquiring lock on /root/.vscode-server/bin/488a1f239235055e34e673291fb8d8c810886f81/vscode-remote-lock.root.488a1f239235055e34e673291fb8d8c810886f81 [17:22:11.417] > Found existing installation at /root/.vscode-server/bin/488a1f239235055e34e673291fb8d8c810886f81... > Checking /root/.vscode-server/.488a1f239235055e34e673291fb8d8c810886f81.log and /root/.vscode-server/.488a1f239235055e34e673291fb8d8c810886f81.pid for a running server > Looking for server with pid: 10601 [17:22:11.426] > Starting server with command... /root/.vscode-server/bin/488a1f239235055e34e673291fb8d8c810886f81/bin/code-server --start-server --host=127.0.0.1 --accept-server-license-terms --enable-remote-auto-shutdown --port=0 --telemetry-level all &> "/root/.vscode-server/.488a1f239235055e34e673291fb8d8c810886f81.log" < /dev/null > printenv: > XDG_SESSION_ID=17942 > SHELL=/bin/bash > SSH_CLIENT=117.140.106.46 30413 22 > USER=root > LD_LIBRARY_PATH=:/root/.VimForCpp/vim/bundle/YCM.so/el7.x86_64 > VSCODE_AGENT_FOLDER=/root/.vscode-server > PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin > MAIL=/var/mail/root > PWD=/root > LANG=en_US.UTF-8 > HOME=/root > SHLVL=2 > LOGNAME=root > SSH_CONNECTION=117.140.106.46 30413 172.17.17.112 22 > LESSOPEN=||/usr/bin/lesspipe.sh %s > XDG_RUNTIME_DIR=/run/user/0 > _=/usr/bin/printenv > Removing old logfile at /root/.vscode-server/.488a1f239235055e34e673291fb8d8c810 > 0886f81.log [17:22:11.432] > > Spawned remote server: 13938 [17:22:11.447] > Waiting for server log... [17:22:11.462] > [17:22:11.478] > Waiting for server log... [17:22:11.524] > Waiting for server log... [17:22:11.557] > Waiting for server log... [17:22:11.602] > Waiting for server log... [17:22:11.634] > Waiting for server log... [17:22:11.664] > Waiting for server log... [17:22:11.712] > Waiting for server log... [17:22:11.743] > Waiting for server log... [17:22:11.790] > Waiting for server log... [17:22:11.823] > Waiting for server log... [17:22:11.854] > Waiting for server log... [17:22:11.900] > Waiting for server log... [17:22:11.948] > Waiting for server log... [17:22:11.978] > Waiting for server log... [17:22:12.009] > Waiting for server log... [17:22:12.041] > Waiting for server log... [17:22:12.090] > Waiting for server log... [17:22:12.121] > Waiting for server log... [17:22:12.153] > Waiting for server log... [17:22:12.199] > Waiting for server log... [17:22:12.246] > Waiting for server log... [17:22:12.262] > Waiting for server log... [17:22:12.278] > [17:22:12.292] > Waiting for server log... [17:22:12.340] > Waiting for server log... [17:22:12.371] > Waiting for server log... [17:22:12.417] > Waiting for server log... [17:22:12.448] > Waiting for server log... [17:22:12.478] > Waiting for server log... [17:22:12.524] > Waiting for server log... [17:22:12.557] > Waiting for server log... [17:22:12.587] > Waiting for server log... [17:22:12.634] > Waiting for server log... [17:22:12.664] > Waiting for server log... [17:22:12.696] > Waiting for server log... [17:22:12.744] > Waiting for server log... [17:22:12.775] > Waiting for server log... [17:22:12.820] > Waiting for server log... [17:22:12.851] > Waiting for server log... [17:22:12.898] > Waiting for server log... [17:22:12.929] > Waiting for server log... [17:22:12.960] > Waiting for server log... [17:22:13.007] > Waiting for server log... [17:22:13.056] > Waiting for server log... [17:22:13.085] > Waiting for server log... [17:22:13.117] > Waiting for server log... [17:22:13.146] > Waiting for server log... [17:22:13.210] > Waiting for server log... [17:22:13.225] > Waiting for server log... [17:22:13.258] > Waiting for server log... [17:22:13.304] > Waiting for server log... [17:22:13.336] > Waiting for server log... [17:22:13.367] > Waiting for server log... [17:22:13.412] > Waiting for server log... [17:22:13.445] > Waiting for server log... [17:22:13.491] > Waiting for server log... [17:22:13.523] > Waiting for server log... [17:22:13.552] > Waiting for server log... [17:22:13.584] > Waiting for server log... [17:22:13.646] > Waiting for server log... [17:22:13.661] > Waiting for server log... [17:22:13.708] > Waiting for server log... [17:22:13.741] > Waiting for server log... [17:22:13.801] > Waiting for server log... > Waiting for server log... [17:22:13.819] > [17:22:13.849] > Waiting for server log... [17:22:13.895] > Waiting for server log... [17:22:13.926] > Waiting for server log... [17:22:13.956] > Waiting for server log... [17:22:14.004] > Waiting for server log... [17:22:14.035] > Waiting for server log... [17:22:14.079] > Waiting for server log... [17:22:14.111] > Waiting for server log... [17:22:14.141] > Waiting for server log... [17:22:14.187] > Waiting for server log... [17:22:14.219] > Waiting for server log... [17:22:14.251] > Waiting for server log... [17:22:14.298] > Waiting for server log... [17:22:14.328] > Waiting for server log... [17:22:14.358] > Waiting for server log... [17:22:14.406] > Waiting for server log... [17:22:14.435] > Waiting for server log... [17:22:14.467] > Waiting for server log... [17:22:14.515] > Waiting for server log... [17:22:14.545] > Waiting for server log... [17:22:14.590] > Waiting for server log... [17:22:14.622] > Waiting for server log... [17:22:14.652] > Waiting for server log... [17:22:14.698] > Waiting for server log... [17:22:14.729] > Waiting for server log... [17:22:14.775] > Waiting for server log... [17:22:14.806] > Waiting for server log... [17:22:14.853] > Waiting for server log... [17:22:14.884] > Waiting for server log... [17:22:14.929] > Waiting for server log... [17:22:14.959] > Waiting for server log... [17:22:15.007] > Waiting for server log... [17:22:15.039] > Waiting for server log... [17:22:15.070] > Waiting for server log... [17:22:15.117] > Waiting for server log... [17:22:15.148] > Waiting for server log... [17:22:15.180] > Waiting for server log... [17:22:15.211] > Waiting for server log... [17:22:15.258] > Waiting for server log... [17:22:15.289] > Waiting for server log... [17:22:15.321] > Waiting for server log... [17:22:15.366] > Waiting for server log... [17:22:15.398] > Waiting for server log... [17:22:15.461] > Waiting for server log... [17:22:15.476] > Waiting for server log... [17:22:15.492] > [17:22:15.507] > Waiting for server log... [17:22:15.554] > Waiting for server log... [17:22:15.586] > Waiting for server log... [17:22:15.617] > Waiting for server log... [17:22:15.664] > Waiting for server log... [17:22:15.695] > Waiting for server log... [17:22:15.741] > Waiting for server log... [17:22:15.772] > Waiting for server log... [17:22:15.803] > Waiting for server log... [17:22:15.849] > Waiting for server log... [17:22:15.881] > Waiting for server log... [17:22:15.928] > Waiting for server log... [17:22:15.960] > Waiting for server log... [17:22:15.991] > Waiting for server log... [17:22:16.039] > Waiting for server log... [17:22:16.070] > Waiting for server log... [17:22:16.101] > Waiting for server log... [17:22:16.148] > Waiting for server log... [17:22:16.179] > Waiting for server log... [17:22:16.211] > Waiting for server log... [17:22:16.257] > Waiting for server log... [17:22:16.288] > Waiting for server log... [17:22:16.320] > Waiting for server log... [17:22:16.365] > Waiting for server log... [17:22:16.396] > Waiting for server log... [17:22:16.428] > Waiting for server log... [17:22:16.476] > Waiting for server log... [17:22:16.506] > Waiting for server log... [17:22:16.537] > Waiting for server log... [17:22:16.583] > Waiting for server log... [17:22:16.614] > Waiting for server log... [17:22:16.660] > Waiting for server log... [17:22:16.691] > Waiting for server log... [17:22:16.724] > Waiting for server log... [17:22:16.769] > Waiting for server log... [17:22:16.800] > Waiting for server log... [17:22:16.847] > Waiting for server log... [17:22:16.879] > Waiting for server log... [17:22:16.924] > Waiting for server log... [17:22:16.955] > Waiting for server log... [17:22:16.986] > Waiting for server log... [17:22:17.033] > Waiting for server log... [17:22:17.064] > Waiting for server log... [17:22:17.096] > Waiting for server log... [17:22:17.141] > Waiting for server log... [17:22:17.173] > Waiting for server log... [17:22:17.203] > Waiting for server log... [17:22:17.250] > Waiting for server log... [17:22:17.280] > Waiting for server log... [17:22:17.312] > Waiting for server log... [17:22:17.358] > Waiting for server log... [17:22:17.390] > Waiting for server log... [17:22:17.421] > Waiting for server log... [17:22:17.467] > Waiting for server log... [17:22:17.498] > Waiting for server log... [17:22:17.546] > Waiting for server log... [17:22:17.577] > Waiting for server log... [17:22:17.607] > Waiting for server log... [17:22:17.654] > Waiting for server log... [17:22:17.686] > Waiting for server log... [17:22:17.717] > Waiting for server log... [17:22:17.763] > Waiting for server log... [17:22:17.797] > Waiting for server log... [17:22:17.827] > Waiting for server log... [17:22:17.874] > Waiting for server log... [17:22:17.906] > Waiting for server log... [17:22:17.952] > Waiting for server log... [17:22:17.998] > Waiting for server log... [17:22:18.015] > Waiting for server log... [17:22:18.060] > Waiting for server log... [17:22:18.093] > Waiting for server log... [17:22:18.123] > Waiting for server log... [17:22:18.170] > Waiting for server log... [17:22:18.202] > Waiting for server log... [17:22:18.232] > Waiting for server log... [17:22:18.280] > Waiting for server log... [17:22:18.311] > Waiting for server log... [17:22:18.341] > Waiting for server log... [17:22:18.388] > Waiting for server log... [17:22:18.420] > Waiting for server log... [17:22:18.451] > Waiting for server log... [17:22:18.499] > Waiting for server log... [17:22:18.528] > Waiting for server log... [17:22:18.559] > Waiting for server log... [17:22:18.607] > Waiting for server log... [17:22:18.639] > Waiting for server log... [17:22:18.684] > Waiting for server log... [17:22:18.715] > Waiting for server log... [17:22:18.746] > Waiting for server log... [17:22:18.793] > Waiting for server log... [17:22:18.840] > Waiting for server log... [17:22:18.855] > Waiting for server log... [17:22:18.903] > Waiting for server log... [17:22:18.934] > Waiting for server log... [17:22:18.979] > Waiting for server log... [17:22:19.010] > Waiting for server log... [17:22:19.041] > Waiting for server log... [17:22:19.090] > Waiting for server log... [17:22:19.120] > Waiting for server log... [17:22:19.166] > Waiting for server log... [17:22:19.197] > Waiting for server log... [17:22:19.228] > Waiting for server log... [17:22:19.277] > Waiting for server log... [17:22:19.308] > Waiting for server log... [17:22:19.339] > Waiting for server log... [17:22:19.376] > > * > * Reminder: You may only use this software with Visual Studio family products, > * as described in the license (https://go.microsoft.com/fwlink/?linkid=2077057) > * > > Server did not start successfully. Full server log at /root/.vscode-server/.488a > a1f239235055e34e673291fb8d8c810886f81.log >>> [17:22:19.386] > > /root/.vscode-server/bin/488a1f239235055e34e673291fb8d8c810886f81/node: /lib64/l > libm.so.6: version `GLIBC_2.27&#39; not found (required by /root/.vscode-server/bin/4 > 488a1f239235055e34e673291fb8d8c810886f81/node) > /root/.vscode-server/bin/488a1f239235055e34e673291fb8d8c810886f81/node: /lib64/l > libc.so.6: version `GLIBC_2.27&#39; not found (required by /root/.vscode-server/bin/4 > 488a1f239235055e34e673291fb8d8c810886f81/node) > /root/.vscode-server/bin/488a1f239235055e34e673291fb8d8c810886f81/node: /lib64/l > libc.so.6: version `GLIBC_2.28&#39; not found (required by /root/.vscode-server/bin/4 > 488a1f239235055e34e673291fb8d8c810886f81/node) > /root/.vscode-server/bin/488a1f239235055e34e673291fb8d8c810886f81/node: /lib64/l > libc.so.6: version `GLIBC_2.25&#39; not found (required by /root/.vscode-server/bin/4 > 488a1f239235055e34e673291fb8d8c810886f81/node) > <<< End of server log > 5e76bec89c36: start > exitCode==32== > listeningOn==== > osReleaseId==centos== > arch==x86_64== > tmpDir==/run/user/0== > platform==linux== > unpackResult==== [17:22:19.397] > > didLocalDownload==0== > downloadTime==== > installTime==== > extInstallTime==== > serverStartTime==7944== > 5e76bec89c36: end [17:22:19.397] Received install output: exitCode==32== listeningOn==== osReleaseId==centos== arch==x86_64== tmpDir==/run/user/0== platform==linux== unpackResult==== didLocalDownload==0== downloadTime==== installTime==== extInstallTime==== serverStartTime==7944== [17:22:19.398] Resolver error: Error: The VS Code Server failed to start at f.ServerInstallError (c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:585913) at p (c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:579762) at t.handleInstallOutput (c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:583047) at t.tryInstall (c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:681784) at async c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:644424 at async t.withShowDetailsEvent (c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:647769) at async t.resolve (c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:645503) at async c:\Users\forest\.vscode\extensions\ms-vscode-remote.remote-ssh-0.76.1\out\extension.js:1:722810 [17:22:19.402] ------ [17:22:19.665] > [17:22:20.752] "install" terminal command done [17:22:20.752] Install terminal quit with output:
最新发布
08-06
import json import os import threading import PySimpleGUI as sg import telnetlib import time import queue import logging from datetime import datetime # ============== 全局配置 ============== DATA_FILE = &#39;pyremote_config.json&#39; PROJECTS_FILE = &#39;projects_config.json&#39; END_STR = "ROUTER_MPU /home\x1b[m # " LOG_FORMAT = &#39;%(asctime)s - %(levelname)s - %(message)s&#39; ENCODING = &#39;utf-8&#39; BUFFER_SIZE = 4096 CHUNK_SIZE = 10 # 每10个字符发送一次 CHUNK_DELAY = 0.15 # 每个分块之间的延迟(秒) COMMAND_DELAY = 0.5 # 命令之间的延迟(秒) # ============== 日志配置 ============== def setup_logger(): """配置日志系统""" logger = logging.getLogger(&#39;RemoteControl&#39;) logger.setLevel(logging.DEBUG) # 文件处理器 file_handler = logging.FileHandler(&#39;remote_control.log&#39;) file_handler.setFormatter(logging.Formatter(LOG_FORMAT)) # 控制台处理器 console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter(LOG_FORMAT)) logger.addHandler(file_handler) logger.addHandler(console_handler) return logger logger = setup_logger() # ============== 项目管理类 ============== class ProjectManager: def __init__(self): self.projects = self.load_projects() def load_projects(self): """加载项目配置""" if os.path.exists(PROJECTS_FILE): try: with open(PROJECTS_FILE, &#39;r&#39;) as f: return json.load(f) except Exception as e: logger.error(f"加载项目配置失败: {e}") return {"projects": []} return {"projects": []} def save_projects(self): """保存项目配置""" try: with open(PROJECTS_FILE, &#39;w&#39;) as f: json.dump(self.projects, f, indent=4) return True except Exception as e: logger.error(f"保存项目配置失败: {e}") return False def add_project(self, name, commands): """添加新项目""" project = { "name": name, "commands": commands, "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } self.projects["projects"].append(project) if self.save_projects(): return project return None def update_project(self, index, name, commands): """更新项目""" if 0 <= index < len(self.projects["projects"]): self.projects["projects"][index]["name"] = name self.projects["projects"][index]["commands"] = commands if self.save_projects(): return True return False def delete_project(self, index): """删除项目""" if 0 <= index < len(self.projects["projects"]): del self.projects["projects"][index] return self.save_projects() return False def import_projects(self, file_path): """导入项目配置""" try: with open(file_path, &#39;r&#39;) as f: imported = json.load(f) # 验证导入格式 if "projects" in imported and isinstance(imported["projects"], list): self.projects = imported return self.save_projects() except Exception as e: logger.error(f"导入项目失败: {e}") return False def export_projects(self, file_path): """导出项目配置""" try: with open(file_path, &#39;w&#39;) as f: json.dump(self.projects, f, indent=4) return True except Exception as e: logger.error(f"导出项目失败: {e}") return False def get_project_commands(self, index): """获取项目的命令列表""" if 0 <= index < len(self.projects["projects"]): return self.projects["projects"][index]["commands"] return [] # ============== 指令执行类(增强版) ============== class CommandExecutor: def __init__(self): self.tn = None self.is_connected = False self.response = "" self.prev_cmd = "" self.log_queue = queue.Queue() self.lock = threading.Lock() self.stop_event = threading.Event() self.pause_event = threading.Event() # 暂停事件 self.last_response = "" self.expected_prompt = END_STR self.current_command_index = -1 # 当前执行命令索引 self.current_command = "" # 当前执行的命令 self.total_commands = 0 # 总命令数 def connect(self, host, port): """连接设备""" try: with self.lock: self.tn = telnetlib.Telnet(host, port, timeout=10) self.is_connected = True self.log_queue.put(f"已连接到 {host}:{port}") # 初始读取以清除欢迎信息 self.read_until_prompt(timeout=3) return True except Exception as e: self.log_queue.put(f"连接失败: {str(e)}") return False def disconnect(self): """断开连接""" with self.lock: if self.tn: try: self.tn.close() except: pass self.is_connected = False self.log_queue.put("连接已断开") def send(self, content): """发送命令(分块发送)""" if not self.is_connected: self.log_queue.put("错误:未连接到设备") return False try: with self.lock: # 保存当前命令 self.current_command = content # 使用正确的编码发送 encoded_content = content.encode(ENCODING) # 分块发送(每10个字符) chunks = [encoded_content[i:i+CHUNK_SIZE] for i in range(0, len(encoded_content), CHUNK_SIZE)] for chunk in chunks: # 检查停止信号 if self.stop_event.is_set(): self.log_queue.put("发送已中止") return False # 检查暂停信号 while self.pause_event.is_set(): time.sleep(0.1) if self.stop_event.is_set(): return False # 发送分块 self.tn.write(chunk) self.log_queue.put(f"发送分块: {chunk.decode(ENCODING, errors=&#39;replace&#39;)}") # 添加分块之间的延迟 time.sleep(CHUNK_DELAY) # 发送回车符(模拟敲回车) self.tn.write(b"\r\n") self.log_queue.put("发送回车符") self.log_queue.put(f"完整发送: {content.strip()}") self.prev_cmd = content return True except Exception as e: self.log_queue.put(f"发送命令失败: {str(e)}") return False def read_until_prompt(self, timeout=5): """读取直到遇到提示符""" if not self.is_connected: return "" try: # 使用正确的编码读取 response = self.tn.read_until(self.expected_prompt.encode(ENCODING), timeout=timeout) decoded_response = response.decode(ENCODING, errors=&#39;replace&#39;) # 移除命令回显 if self.prev_cmd and decoded_response.startswith(self.prev_cmd.strip()): decoded_response = decoded_response[len(self.prev_cmd.strip()):].lstrip() # 移除尾部的提示符 if decoded_response.endswith(self.expected_prompt): decoded_response = decoded_response[:-len(self.expected_prompt)].rstrip() self.last_response = decoded_response self.log_queue.put(decoded_response) return decoded_response except Exception as e: self.log_queue.put(f"接收响应失败: {str(e)}") return "" def execute_commands(self, commands): """执行命令序列(增强版)""" if not self.is_connected: self.log_queue.put("错误:未连接到设备") return False self.stop_event.clear() self.pause_event.clear() self.total_commands = len(commands) self.log_queue.put(f"开始执行 {self.total_commands} 条命令") try: for idx, cmd in enumerate(commands): if self.stop_event.is_set(): self.log_queue.put("命令执行已中止") return False # 设置当前命令索引 self.current_command_index = idx # 检查暂停状态 while self.pause_event.is_set(): time.sleep(0.1) if self.stop_event.is_set(): return False if cmd.strip(): # 跳过空行 # 发送命令 if not self.send(cmd): return False # 等待命令完成 self.read_until_prompt(timeout=10) # 命令间延迟 delay_remaining = COMMAND_DELAY while delay_remaining > 0: if self.stop_event.is_set(): return False if self.pause_event.is_set(): time.sleep(0.1) continue time.sleep(0.1) delay_remaining -= 0.1 self.log_queue.put("命令执行完成") self.current_command_index = -1 return True except Exception as e: self.log_queue.put(f"命令执行失败: {str(e)}") return False def stop_execution(self): """停止当前执行""" self.stop_event.set() self.log_queue.put("正在停止执行...") def pause_execution(self): """暂停当前执行""" if not self.pause_event.is_set(): self.pause_event.set() self.log_queue.put("执行已暂停") return True return False def resume_execution(self): """继续执行""" if self.pause_event.is_set(): self.pause_event.clear() self.log_queue.put("执行已继续") return True return False def get_execution_status(self): """获取执行状态""" return { "is_running": not self.stop_event.is_set() and not self.pause_event.is_set(), "is_paused": self.pause_event.is_set(), "is_stopped": self.stop_event.is_set(), "current_command": self.current_command.strip(), "current_index": self.current_command_index, "total_commands": self.total_commands } # ============== GUI 界面类(增强版) ============== class RemoteControlApp: def __init__(self): self.project_manager = ProjectManager() self.executor = CommandExecutor() self.default_data = self.load_default_data() self.window = None self.setup_gui() self.log_thread = None self.status_update_thread = None self.running = True def load_default_data(self): """加载默认配置""" default_data = { "IP": "71.19.0.120", "port": "1001", "FTP_IP": "71.19.0.120", "芯片名称": "Hi1260SV100", &#39;发送信息&#39;: "", "board_local_ip": "71.19.0.53", &#39;interval&#39;: "1", "start_addr": "", "end_addr": "", "文件FTP路径": "", } if os.path.exists(DATA_FILE): try: with open(DATA_FILE, &#39;r&#39;) as f: data = json.load(f) default_data.update({k: data[k] for k in default_data if k in data}) except Exception as e: logger.error(f"加载默认配置失败: {e}") with open(DATA_FILE, &#39;w&#39;) as f: json.dump(default_data, f) else: with open(DATA_FILE, &#39;w&#39;) as f: json.dump(default_data, f) return default_data def save_config(self): """保存配置""" try: values = self.window.read()[1] if self.window else {} with open(DATA_FILE, &#39;w&#39;) as f: json.dump({ "IP": values.get("IP", self.default_data["IP"]), "port": values.get("port", self.default_data["port"]), "FTP_IP": values.get("FTP_IP", self.default_data["FTP_IP"]), "芯片名称": values.get("芯片名称", self.default_data["芯片名称"]), &#39;发送信息&#39;: values.get("发送信息", self.default_data["发送信息"]), "board_local_ip": values.get("board_local_ip", self.default_data["board_local_ip"]), &#39;interval&#39;: values.get("interval", self.default_data["interval"]), "start_addr": values.get("start_addr", self.default_data["start_addr"]), "end_addr": values.get("end_addr", self.default_data["end_addr"]), "文件FTP路径": values.get("文件FTP路径", self.default_data["文件FTP路径"]), }, f) return True except Exception as e: logger.error(f"保存配置失败: {e}") return False def create_project_buttons(self): """创建项目按钮区域""" layout = [] projects = self.project_manager.projects["projects"] if not projects: layout.append([sg.Text("没有项目,请添加新项目", text_color=&#39;red&#39;)]) for i, project in enumerate(projects): row = [ sg.Button(project["name"], key=f&#39;-PROJECT-{i}-&#39;, size=(15,1), tooltip=f"创建于: {project[&#39;created_at&#39;]}\n命令数: {len(project[&#39;commands&#39;])}"), sg.Button("一键升级", key=f&#39;-UPGRADE-{i}-&#39;, button_color=(&#39;white&#39;, &#39;green&#39;)), sg.Button("编辑", key=f&#39;-EDIT-{i}-&#39;, button_color=(&#39;white&#39;, &#39;blue&#39;)), sg.Button("删除", key=f&#39;-DELETE-{i}-&#39;, button_color=(&#39;white&#39;, &#39;red&#39;)) ] layout.append(row) # 添加项目管理按钮 layout.append([ sg.Button("添加新项目", key=&#39;-ADD-PROJECT-&#39;, button_color=(&#39;white&#39;, &#39;purple&#39;)), sg.Button("导入项目", key=&#39;-IMPORT-PROJECTS-&#39;), sg.Button("导出项目", key=&#39;-EXPORT-PROJECTS-&#39;), sg.Button("生成模板", key=&#39;-CREATE-TEMPLATE-&#39;) ]) return layout def edit_project_window(self, index=None): """项目编辑窗口""" project = None if index is not None and 0 <= index < len(self.project_manager.projects["projects"]): project = self.project_manager.projects["projects"][index] layout = [ [sg.Text("项目名称:"), sg.Input(key=&#39;-PROJECT-NAME-&#39;, default_text=project["name"] if project else "")], [sg.Text("升级指令:")], [sg.Multiline(key=&#39;-PROJECT-COMMANDS-&#39;, size=(60, 10), default_text=&#39;\n&#39;.join(project["commands"]) if project else "", tooltip="每行一个命令,命令将按顺序执行")], [sg.Button("保存", key=&#39;-SAVE-PROJECT-&#39;), sg.Button("取消", key=&#39;-CANCEL-PROJECT-&#39;)] ] window = sg.Window("项目编辑", layout, modal=True) while True: event, values = window.read() if event in (sg.WINDOW_CLOSED, &#39;-CANCEL-PROJECT-&#39;): break elif event == &#39;-SAVE-PROJECT-&#39;: name = values[&#39;-PROJECT-NAME-&#39;].strip() commands = [cmd.strip() for cmd in values[&#39;-PROJECT-COMMANDS-&#39;].split(&#39;\n&#39;) if cmd.strip()] if not name: sg.popup("项目名称不能为空") continue if index is None: new_project = self.project_manager.add_project(name, commands) if new_project: sg.popup(f"项目 &#39;{name}&#39; 添加成功") break else: if self.project_manager.update_project(index, name, commands): sg.popup(f"项目 &#39;{name}&#39; 更新成功") break sg.popup("操作失败,请查看日志") window.close() return True def setup_gui(self): """设置GUI界面(增强版)""" # 创建主布局 sg.theme(&#39;LightBlue1&#39;) # 输出区域 output = sg.Multiline( size=(80, 20), key=&#39;-OUTPUT-&#39;, autoscroll=True, background_color=&#39;#f0f0f0&#39;, text_color=&#39;black&#39; ) # 状态信息区域 status_info = [ sg.Text("当前命令: ", size=(10,1)), sg.Text("无", key=&#39;-CURRENT-COMMAND-&#39;, size=(40,1), text_color=&#39;blue&#39;), sg.Text("进度: ", size=(5,1)), sg.Text("0/0", key=&#39;-COMMAND-PROGRESS-&#39;, size=(10,1)) ] # 项目列表区域 projects_frame = sg.Frame("项目列表", [ [sg.Column( self.create_project_buttons(), scrollable=True, vertical_scroll_only=True, size=(700, 300), key=&#39;-PROJECTS-COLUMN-&#39; )] ], key=&#39;-PROJECTS-FRAME-&#39;) # 执行控制区域 control_buttons = [ sg.Button(&#39;暂停执行&#39;, key=&#39;-PAUSE-EXECUTION-&#39;, button_color=(&#39;white&#39;, &#39;orange&#39;), size=(10,1)), sg.Button(&#39;继续执行&#39;, key=&#39;-RESUME-EXECUTION-&#39;, button_color=(&#39;white&#39;, &#39;green&#39;), size=(10,1)), sg.Button(&#39;停止执行&#39;, key=&#39;-STOP-EXECUTION-&#39;, button_color=(&#39;white&#39;, &#39;red&#39;), size=(10,1)) ] # 连接状态区域 status_bar = [ sg.Text(&#39;●&#39;, key=&#39;-STATUS-LIGHT-&#39;, text_color=&#39;red&#39;, font=(&#39;Arial&#39;, 12)), sg.Text("未连接", key=&#39;-CONNECTION-STATUS-&#39;), sg.StatusBar("就绪", key=&#39;-STATUS-&#39;, size=(50, 1)) ] # 主布局 layout = [ [sg.Text(&#39;IP:&#39;, size=(6,1)), sg.Input(key="IP", default_text=self.default_data["IP"], size=(15,1)), sg.Text(&#39;Port:&#39;, size=(5,1)), sg.Input(key="port", default_text=self.default_data["port"], size=(8,1)), sg.Button(&#39;连接&#39;, button_color=(&#39;white&#39;, &#39;green&#39;)), sg.Button(&#39;断开连接&#39;, button_color=(&#39;white&#39;, &#39;red&#39;))], [projects_frame], status_info, # 执行控制按钮 [sg.Frame("执行控制", [control_buttons], key=&#39;-CONTROL-FRAME-&#39;)], [sg.Text("发送信息:", size=(8,1)), sg.Input(key=&#39;发送信息&#39;, size=(50, 1), default_text=self.default_data["发送信息"])], [sg.Button(&#39;ROUTER_MPU下发送&#39;), sg.Button(&#39;Shell下发送&#39;), sg.Text(&#39;每隔&#39;, size=(3,1)), sg.Input(key=&#39;interval&#39;, default_text=self.default_data["interval"], size=(5,1)), sg.Text("秒", size=(2,1)), sg.Button(&#39;定时发送&#39;), sg.Button("停止定时发送")], [sg.Button(&#39;接收1s&#39;)], [sg.Text(&#39;芯片名称:&#39;, size=(8,1)), sg.Input(key="芯片名称", default_text=self.default_data["芯片名称"], size=(15,1)), sg.Text(&#39;文件FTP路径:&#39;, size=(10,1)), sg.Input(key="文件FTP路径", default_text=self.default_data["文件FTP路径"], size=(30,1))], [sg.Text(&#39;FTP_IP:&#39;, size=(6,1)), sg.Input(key="FTP_IP", default_text=self.default_data["FTP_IP"], size=(15,1)), sg.Text(&#39;单板IP:&#39;, size=(6,1)), sg.Input(key="board_local_ip", default_text=self.default_data["board_local_ip"], size=(15,1))], [sg.Text("SLT测试用"), sg.Button(&#39;重新获取sdk.out&#39;), sg.Button("一键升级MT1"), sg.Button("一键升级MT2")], [sg.Button("使用说明", button_color=(&#39;white&#39;, &#39;blue&#39;))], [sg.Text(&#39;起始地址:&#39;, size=(8,1)), sg.Input(key=&#39;start_addr&#39;, default_text=self.default_data["start_addr"], size=(12,1)), sg.Text(&#39;结束地址:&#39;, size=(8,1)), sg.Input(key=&#39;end_addr&#39;, default_text=self.default_data["end_addr"], size=(12,1)), sg.Button(&#39;dump寄存器&#39;)], [output], status_bar ] self.window = sg.Window(&#39;远程单板连接工具&#39;, layout, finalize=True, resizable=True) self.update_status_light() self.start_log_thread() self.start_status_update_thread() def update_status_light(self): """更新状态指示灯""" color = &#39;green&#39; if self.executor.is_connected else &#39;red&#39; status = "已连接" if self.executor.is_connected else "未连接" self.window[&#39;-STATUS-LIGHT-&#39;].update(text_color=color) self.window[&#39;-CONNECTION-STATUS-&#39;].update(status) def update_output(self): """更新输出区域""" while not self.executor.log_queue.empty(): try: message = self.executor.log_queue.get_nowait() current_text = self.window[&#39;-OUTPUT-&#39;].get() self.window[&#39;-OUTPUT-&#39;].update(current_text + message + &#39;\n&#39;) except queue.Empty: break def start_log_thread(self): """启动日志更新线程""" self.log_thread = threading.Thread(target=self.log_update_loop, daemon=True) self.log_thread.start() def log_update_loop(self): """日志更新循环""" while self.running: self.update_output() time.sleep(0.1) def start_status_update_thread(self): """启动状态更新线程""" self.status_update_thread = threading.Thread(target=self.status_update_loop, daemon=True) self.status_update_thread.start() def status_update_loop(self): """状态更新循环""" while self.running: # 更新执行状态 status = self.executor.get_execution_status() # 更新当前命令显示 if status["current_command"]: self.window[&#39;-CURRENT-COMMAND-&#39;].update(status["current_command"]) # 更新进度显示 if status["current_index"] >= 0 and status["total_commands"] > 0: progress_text = f"{status[&#39;current_index&#39;] + 1}/{status[&#39;total_commands&#39;]}" self.window[&#39;-COMMAND-PROGRESS-&#39;].update(progress_text) # 更新按钮状态 if status["is_running"]: self.window[&#39;-PAUSE-EXECUTION-&#39;].update(disabled=False) self.window[&#39;-RESUME-EXECUTION-&#39;].update(disabled=True) self.window[&#39;-STOP-EXECUTION-&#39;].update(disabled=False) elif status["is_paused"]: self.window[&#39;-PAUSE-EXECUTION-&#39;].update(disabled=True) self.window[&#39;-RESUME-EXECUTION-&#39;].update(disabled=False) self.window[&#39;-STOP-EXECUTION-&#39;].update(disabled=False) else: self.window[&#39;-PAUSE-EXECUTION-&#39;].update(disabled=True) self.window[&#39;-RESUME-EXECUTION-&#39;].update(disabled=True) self.window[&#39;-STOP-EXECUTION-&#39;].update(disabled=True) time.sleep(0.2) def refresh_project_list(self): """刷新项目列表""" self.window[&#39;-PROJECTS-COLUMN-&#39;].update(visible=False) self.window[&#39;-PROJECTS-COLUMN-&#39;].update(self.create_project_buttons()) self.window[&#39;-PROJECTS-COLUMN-&#39;].update(visible=True) def run(self): """运行主循环(增强版)""" stop_loop = 0 interval = 10000 loop_msg = "" while True: event, values = self.window.read(timeout=100) if event == sg.WINDOW_CLOSED: break # 更新输出区域 self.update_output() # 连接管理 if event == &#39;连接&#39;: if values["IP"] and values["port"]: if self.executor.connect(values["IP"], int(values["port"])): self.window[&#39;-STATUS-&#39;].update("已连接") self.update_status_light() else: sg.popup("请输入IP和端口") elif event == &#39;断开连接&#39;: self.executor.disconnect() self.window[&#39;-STATUS-&#39;].update("已断开") self.update_status_light() # 项目管理 elif event == &#39;-ADD-PROJECT-&#39;: self.edit_project_window() self.refresh_project_list() elif event.startswith(&#39;-EDIT-&#39;): index = int(event.split(&#39;-&#39;)[2]) self.edit_project_window(index) self.refresh_project_list() elif event.startswith(&#39;-DELETE-&#39;): index = int(event.split(&#39;-&#39;)[2]) if self.project_manager.delete_project(index): sg.popup("项目删除成功") self.refresh_project_list() else: sg.popup("项目删除失败") elif event == &#39;-IMPORT-PROJECTS-&#39;: file_path = sg.popup_get_file("选择项目配置文件", file_types=(("JSON Files", "*.json"),)) if file_path and self.project_manager.import_projects(file_path): sg.popup("项目导入成功") self.refresh_project_list() else: sg.popup("项目导入失败") elif event == &#39;-EXPORT-PROJECTS-&#39;: file_path = sg.popup_get_file("保存项目配置文件", save_as=True, file_types=(("JSON Files", "*.json"),)) if file_path and self.project_manager.export_projects(file_path): sg.popup("项目导出成功") else: sg.popup("项目导出失败") elif event == &#39;-CREATE-TEMPLATE-&#39;: self.create_template_file() sg.popup("模板文件已生成: projects_template.json") # 一键升级 elif event.startswith(&#39;-UPGRADE-&#39;): index = int(event.split(&#39;-&#39;)[2]) if index < len(self.project_manager.projects["projects"]): project = self.project_manager.projects["projects"][index] self.window[&#39;-STATUS-&#39;].update(f"执行 {project[&#39;name&#39;]} 升级...") # 在新线程中执行升级 threading.Thread( target=self.execute_project_upgrade, args=(index,), daemon=True ).start() # 执行控制 elif event == &#39;-PAUSE-EXECUTION-&#39;: if self.executor.pause_execution(): self.window[&#39;-STATUS-&#39;].update("执行已暂停") elif event == &#39;-RESUME-EXECUTION-&#39;: if self.executor.resume_execution(): self.window[&#39;-STATUS-&#39;].update("执行已继续") elif event == &#39;-STOP-EXECUTION-&#39;: self.executor.stop_execution() self.window[&#39;-STATUS-&#39;].update("执行已停止") # 其他原有功能... elif event == &#39;ROUTER_MPU下发送&#39;: if self.save_config() and values["发送信息"]: self.executor.send(values["发送信息"]) # 等待响应 self.executor.read_until_prompt() elif event == &#39;Shell下发送&#39;: if self.save_config() and values["发送信息"]: self.executor.send(values["发送信息"]) # 等待响应 self.executor.read_until_prompt() elif event == &#39;定时发送&#39;: if self.save_config() and values["发送信息"] and values["interval"]: try: interval = float(values["interval"]) if interval <= 0: raise ValueError("间隔必须大于0") loop_msg = values["发送信息"] threading.Thread( target=self.periodic_send, args=(loop_msg, interval), daemon=True ).start() except Exception as e: sg.popup(f"无效的间隔: {str(e)}") else: sg.popup("请输入发送信息和有效间隔") elif event == "停止定时发送": self.executor.stop_execution() # 其他事件处理 elif event == &#39;接收1s&#39;: self.executor.read_until_prompt(timeout=1) elif event == &#39;dump寄存器&#39;: if values["start_addr"] and values["end_addr"]: self.executor.send(f"dump {values[&#39;start_addr&#39;]} {values[&#39;end_addr&#39;]}") self.executor.read_until_prompt() elif event == &#39;重新获取sdk.out&#39;: self.executor.send("get_sdk.out") self.executor.read_until_prompt() elif event == &#39;一键升级MT1&#39;: self.executor.send("upgrade_mt1") self.executor.read_until_prompt() elif event == &#39;一键升级MT2&#39;: self.executor.send("upgrade_mt2") self.executor.read_until_prompt() elif event == &#39;使用说明&#39;: self.show_help() self.running = False self.executor.disconnect() if self.log_thread: self.log_thread.join(timeout=1.0) if self.status_update_thread: self.status_update_thread.join(timeout=1.0) self.window.close() def execute_project_upgrade(self, index): """执行项目升级(增强版)""" commands = self.project_manager.get_project_commands(index) if commands: # 重置进度显示 self.window[&#39;-CURRENT-COMMAND-&#39;].update("") self.window[&#39;-COMMAND-PROGRESS-&#39;].update("0/0") success = self.executor.execute_commands(commands) self.window[&#39;-STATUS-&#39;].update("升级完成" if success else "升级失败") else: self.executor.log_queue.put("错误:项目没有配置命令") def periodic_send(self, message, interval): """周期性发送消息(优化版)""" while not self.executor.stop_event.is_set(): self.executor.send(message) # 等待响应 self.executor.read_until_prompt() # 等待指定间隔 time.sleep(interval) def show_help(self): """显示使用说明(增强版)""" help_text = """ === 远程单板连接工具使用说明 === 1. 连接管理: - 输入IP和端口后点击"连接"按钮 - 状态指示灯显示连接状态(红:未连接, 绿:已连接) 2. 项目管理: - 添加项目:点击"添加新项目"按钮 - 编辑项目:点击项目右侧的"编辑"按钮 - 删除项目:点击项目右侧的"删除"按钮 - 一键升级:点击项目右侧的"一键升级"按钮 - 导入/导出:支持JSON格式配置导入导出 3. 命令执行控制: - 暂停执行:点击"暂停执行"按钮 - 继续执行:点击"继续执行"按钮 - 停止执行:点击"停止执行"按钮 - 进度显示:显示当前执行的命令和进度 4. 发送机制: - 分块发送:每条命令按10字符分块发送 - 回车发送:每条命令发送后自动发送回车符 - 命令间延迟:每条命令之间有0.5秒延迟 - 命令同步:每条命令发送后等待响应完成 5. 特殊功能: - dump寄存器:输入起始和结束地址 - SLT测试:提供快速测试按钮 6. 优化说明: - 使用UTF-8编码避免乱码 - 命令发送后自动等待响应完成 - 自动过滤命令回显和提示符 - 实时显示执行状态和进度 """ sg.popup(help_text, title="使用说明", font=("Arial", 11)) def create_template_file(self): """创建项目配置模板""" try: template = { "projects": [ { "name": "项目A", "commands": [ "ifconfig eth0 192.168.0.100", "ftpget -u user -p pass 192.168.0.1 /home/firmware.bin firmware.bin", "flash -w 0 0x0000000 0xa000000 0x2000000" ], "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") }, { "name": "项目B", "commands": [ "ifconfig eth0 192.168.0.101", "ping 192.168.0.1", "reboot" ], "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } ] } with open("projects_template.json", &#39;w&#39;) as f: json.dump(template, f, indent=4) return True except Exception as e: logger.error(f"创建模板文件失败: {e}") return False # ============== 主程序入口 ============== if __name__ == "__main__": # 启动应用 try: app = RemoteControlApp() app.run() except Exception as e: logger.exception("应用程序崩溃") sg.popup_error(f"应用程序发生致命错误: {str(e)}")
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值