from queue import Full import socket import threading import time from typing import Dict, Optional from loguru import logger import telnetlib #2026/6/2 # 全局:TCP客户端管理(每个UART一个实例) tcp_clients: Dict[str, "TCPUARTClient"] = {} # HEAD = b"\xeb\x90" #地测帧头 # TAIL = b"\x57\x16" #地测帧尾 # MIN_FRAME = 23 ##地测长度最小值 # MAX_FRAME = 1000 ##地测帧长度最大值 class TCPUARTClient: def __init__(self, dev_name: str, local_port: int, remote_port: int, remote_ip="127.0.0.1"): self.dev_name = dev_name self.local_port = local_port self.remote_port = remote_port self.remote_ip = remote_ip self.socket = None self.running = False self.thread = None self.HEAD = b"\xeb\x90" #地测帧头 self.TAIL = b"\x57\x16" #地测帧尾 self.MIN_LEN = 23 ##地测长度最小值 self.MAX_LEN = 1000 ##地测帧长度最大值 self.tcp_buf = b'' #self.tn = None def connect(self): try: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 关键点:禁止Nagle算法,模仿网络调试助手,强制使用纯raw socket连接,但是导致TCP收不到数据 2026/6/2 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #停用 #self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) #telnet self.socket.bind(("127.0.0.1", self.local_port)) self.socket.connect((self.remote_ip, self.remote_port)) self.socket.setblocking(False) self.running = True print(f"[TCP-UART] {self.dev_name} 连接成功: local={self.local_port} remote={self.remote_port}") #telnet #self.tn = telnetlib.Telnet("127.0.0.1",{self.remote_port},timeout=5) return True except Exception as e: print(f"[TCP-UART] {self.dev_name} 连接失败: {e}") return False ''' # 去除转义FF的函数 2026/6/2,可能有安全问题 def unescape_ff(raw:bytes)->bytes: buf = bytearray() i = 0 n = len(raw) while ibytes: out = bytearray() idx=0 length = len(raw) while idx8192 2026/5/15 if not data: time.sleep(0.001) continue self.tcp_buf += data #新数据追加到缓存尾部2026/6/2 dev_name = None protocol = None for name, cfg in DEVICE_CONFIG_DICT.items(): if cfg.get("tcp_bus_port") == self.remote_port: dev_name = name protocol = cfg.get("protocol") break if not dev_name or not protocol: continue #循环拆包,大多数情况是只跑0~1次循环 2026/6/2 while True: if len(self.tcp_buf)>self.MAX_LEN * 2: self.tcp_buf = self.tcp_buf[-1000:] h_pos = self.tcp_buf.find(self.HEAD) if h_pos ==-1: break #截断帧头前面垃圾 if h_pos>0: self.tcp_buf = self.tcp_buf[h_pos:] #缓存不足最小帧,直接退出 if(len(self.tcp_buf)