import sys import socket import threading import requests import json import time import uuid from PyQt5.QtWidgets import QMainWindow, QVBoxLayout, QPushButton, \ QListWidget, QLabel, QWidget, QMessageBox, QTextEdit, \ QLineEdit, QHBoxLayout, QRadioButton, QButtonGroup, QGroupBox from PyQt5.QtCore import Qt, QThread, pyqtSignal, QObject, QTimer from PyQt5.QtNetwork import QNetworkInterface,QAbstractSocket from datetime import datetime from utils import Globals class TcpClient(object): def __init__(self): # 配置信息 self.udpPort = 54321 self.broadcastAddr = '' def discoverServers(self): # print("[*] 正在扫描局域网设备...") udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udpSock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) udpSock.settimeout(2) udpSock.sendto(b"DISCOVERY_REQUEST", (self.broadcastAddr, self.udpPort)) servers = [] seen = set() local_ips = self.getLocalIps() try: while True: data, addr = udpSock.recvfrom(1024) if data.startswith(b"DISCOVERY_RESPONSE"): _, hostname, tcpPort = data.decode('utf-8').split(':') serverIp = addr[0] # 跳过本机IP if serverIp in local_ips: continue key = (serverIp, int(tcpPort)) if key in seen: continue seen.add(key) servers.append({ 'ip': (serverIp,), 'port': int(tcpPort), 'hostname': hostname }) print(data.decode('utf-8')) except socket.timeout: pass finally: udpSock.close() return servers def connectToServer(self, ip, tcpPort): client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: # 显式转换类型确保安全 client.connect((str(ip), int(tcpPort))) # print(f"[+] 已连接到 {ip}:{tcpPort}") Globals.getValue('protocolManage').setServerMode() clientName = Globals.getValue('protocolManage').RpcServer.getNextClientName() client.send(clientName.encode('utf-8')) response = client.recv(1024) # print(f"服务端响应: {response.decode('utf-8')}") resClientName = response.decode('utf-8') Globals.getValue('protocolManage').addClient(clientName = resClientName) QMessageBox.information(None, '连接成功', f'已成功连接到从站 {ip}:{tcpPort}') return True except Exception as e: print(f"连接失败: {e}") return False finally: client.close() def getLocalIps(self): """获取本机所有IPv4地址""" ips = set() for interface in QNetworkInterface.allInterfaces(): if interface.flags() & QNetworkInterface.IsUp: for entry in interface.addressEntries(): ip = entry.ip() if ip.protocol() == QAbstractSocket.IPv4Protocol and not ip.isLoopback(): ips.add(ip.toString()) return ips class DiscoveryThread(QThread): """用于在后台执行设备发现的线程""" discoveryFinished = pyqtSignal(list) # 信号,携带发现的设备列表 def __init__(self, tcpClient): super().__init__() self.tcpClient = tcpClient def run(self): servers = self.tcpClient.discoverServers() self.discoveryFinished.emit(servers) class DeviceMasterWidget(QMainWindow): def __init__(self): super().__init__() self.tcpClient = TcpClient() self.servers = [] self.discoveryThread = None self.statusLabel = None self.infoLabel = None self.disconnectList = None self.publicServerInput = None self.publicClientList = None self.publicClients = [] self.autoRefreshEnabled = False self.initUI() # 定时器启动放到控件初始化后 self.statusTimer = QTimer(self) self.statusTimer.timeout.connect(self.updateStatusInfo) self.statusTimer.start(1000) # 公网客户端自动刷新定时器 self.publicRefreshTimer = QTimer(self) self.publicRefreshTimer.timeout.connect(self.autoRefreshPublicClients) def initUI(self): self.setWindowTitle('设备连接管理') # self.setGeometry(1000, 500, 400, 300) # 主窗口部件 centralWidget = QWidget() self.setCentralWidget(centralWidget) layout = QVBoxLayout() self.statusLabel = QLabel('服务器模式: 无') layout.addWidget(self.statusLabel) self.infoLabel = QLabel('连接信息: 无') layout.addWidget(self.infoLabel) # 新增:断开客户端区 self.disconnectList = QListWidget() self.disconnectList.setFixedHeight(60) layout.addWidget(QLabel('已连接客户端(点击可断开):')) layout.addWidget(self.disconnectList) self.disconnectList.itemClicked.connect(self.disconnectClient) # 公网服务端配置区域 publicGroup = QGroupBox('公网服务端配置') publicLayout = QVBoxLayout() # 服务器地址输入 serverLayout = QHBoxLayout() serverLayout.addWidget(QLabel('服务器地址:')) self.publicServerInput = QLineEdit('43.138.48.181') self.publicServerInput.setPlaceholderText('输入公网服务器IP地址') serverLayout.addWidget(self.publicServerInput) publicLayout.addLayout(serverLayout) # 公网服务端控制按钮 serverButtonLayout = QHBoxLayout() self.publicConnectButton = QPushButton('启动公网服务端') self.publicConnectButton.clicked.connect(self.startPublicServer) self.publicConnectButton.setObjectName('setButton') serverButtonLayout.addWidget(self.publicConnectButton) self.publicDisconnectButton = QPushButton('关闭公网服务端') self.publicDisconnectButton.clicked.connect(self.stopPublicServer) self.publicDisconnectButton.setObjectName('setButton') self.publicDisconnectButton.setEnabled(False) serverButtonLayout.addWidget(self.publicDisconnectButton) publicLayout.addLayout(serverButtonLayout) # 公网客户端扫描区域 publicLayout.addWidget(QLabel('公网服务器客户端列表:')) self.publicClientList = QListWidget() self.publicClientList.setFixedHeight(100) self.publicClientList.itemDoubleClicked.connect(self.connectToPublicClient) publicLayout.addWidget(self.publicClientList) # 扫描和连接按钮 publicButtonLayout = QHBoxLayout() self.scanPublicButton = QPushButton('扫描公网客户端') self.scanPublicButton.clicked.connect(self.scanPublicClients) self.scanPublicButton.setObjectName('setButton') publicButtonLayout.addWidget(self.scanPublicButton) self.connectPublicButton = QPushButton('连接选中客户端') self.connectPublicButton.clicked.connect(self.connectToPublicClient) self.connectPublicButton.setEnabled(False) self.connectPublicButton.setObjectName('setButton') publicButtonLayout.addWidget(self.connectPublicButton) publicLayout.addLayout(publicButtonLayout) # 自动刷新选项 from PyQt5.QtWidgets import QCheckBox self.autoRefreshCheckBox = QCheckBox('自动刷新客户端列表 (5秒)') self.autoRefreshCheckBox.stateChanged.connect(self.toggleAutoRefresh) publicLayout.addWidget(self.autoRefreshCheckBox) publicGroup.setLayout(publicLayout) layout.addWidget(publicGroup) self.ipAddresslabel = QLabel(self) self.ipAddresslabel.setObjectName("setlabel") self.ipAddresslabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) layout.addWidget(self.ipAddresslabel) # 局域网设备发现区域 lanGroup = QGroupBox('局域网设备发现') lanLayout = QVBoxLayout() # 标题标签 self.titleLabel = QLabel('点击"扫描设备"按钮发现局域网中的设备') lanLayout.addWidget(self.titleLabel) # 设备列表 self.deviceList = QListWidget() lanLayout.addWidget(self.deviceList) lanLayout2 = QHBoxLayout() self.scanButton = QPushButton('扫描设备') self.scanButton.clicked.connect(self.startDiscovery) self.scanButton.setObjectName('setButton') lanLayout2.addWidget(self.scanButton) self.connectButton = QPushButton('连接设备') self.connectButton.clicked.connect(self.connectToDevice) self.connectButton.setEnabled(False) self.connectButton.setObjectName('setButton') lanLayout2.addWidget(self.connectButton) lanLayout.addLayout(lanLayout2) lanGroup.setLayout(lanLayout) layout.addWidget(lanGroup) self.ipAddresslabel.setText('当前设备IP地址: ' + self.getLocalIp()) centralWidget.setLayout(layout) # self.show() def startDiscovery(self): """开始扫描设备""" self.scanButton.setEnabled(False) self.titleLabel.setText('正在扫描局域网设备...') self.deviceList.clear() # 创建并启动发现线程 self.discoveryThread = DiscoveryThread(self.tcpClient) self.discoveryThread.discoveryFinished.connect(self.onDiscoveryFinished) self.discoveryThread.start() def onDiscoveryFinished(self, servers): """设备扫描完成后的回调""" self.scanButton.setEnabled(True) self.servers = servers if not servers: self.titleLabel.setText('未发现任何设备') QMessageBox.information(self, '提示', '未发现任何设备') return self.titleLabel.setText(f'发现 {len(servers)} 个设备:') # 在列表中显示设备 for server in servers: itemText = f"{server['hostname']} ({server['ip'][0]})" self.deviceList.addItem(itemText) self.connectButton.setEnabled(True) def startPublicServer(self): """启动公网服务端模式""" serverIp = self.publicServerInput.text().strip() if not serverIp: QMessageBox.warning(self, '警告', '请输入服务器地址') return try: # 设置为服务端模式 Globals.getValue('protocolManage').closeClient() Globals.getValue('protocolManage').setServerMode(rabbitmqHost=serverIp) # 更新按钮状态 self.publicConnectButton.setEnabled(False) self.publicDisconnectButton.setEnabled(True) QMessageBox.information(self, '成功', f'已启动公网服务端模式\n服务器地址: {serverIp}') except Exception as e: QMessageBox.critical(self, '失败', f'启动公网服务端模式失败: {str(e)}') def stopPublicServer(self): """关闭公网服务端模式""" try: # 关闭服务端模式 Globals.getValue('protocolManage').closeServer() # 更新按钮状态 self.publicConnectButton.setEnabled(True) self.publicDisconnectButton.setEnabled(False) # 清空客户端列表 self.publicClientList.clear() self.publicClients = [] self.connectPublicButton.setEnabled(False) # 停止自动刷新 if self.autoRefreshEnabled: self.autoRefreshCheckBox.setChecked(False) self.toggleAutoRefresh(0) QMessageBox.information(self, '成功', '已关闭公网服务端模式') except Exception as e: QMessageBox.critical(self, '失败', f'关闭公网服务端模式失败: {str(e)}') def scanPublicClients(self): """扫描公网服务器上的客户端""" serverIp = self.publicServerInput.text().strip() if not serverIp: QMessageBox.warning(self, '警告', '请输入服务器地址') return try: # 通过RabbitMQ管理API获取所有RPC队列 url = f"http://{serverIp}:15672/api/queues" response = requests.get(url, auth=('dcs', '123456'), timeout=10) queues = response.json() # 筛选RPC客户端队列 rpc_queues = [] for queue in queues: queue_name = queue['name'] if queue_name.startswith('rpc_queue_client'): client_name = queue_name.replace('rpc_queue_', '') rpc_queues.append({ 'name': client_name, 'queue': queue_name, 'messages': queue.get('messages', 0), 'consumers': queue.get('consumers', 0), 'status': 'online' if queue.get('consumers', 0) > 0 else 'offline' }) # 更新客户端列表 self.publicClients = rpc_queues self.publicClientList.clear() if not rpc_queues: self.publicClientList.addItem('未发现任何客户端') self.connectPublicButton.setEnabled(False) else: for client in rpc_queues: status_text = "在线" if client['status'] == 'online' else "离线" item_text = f"{client['name']} ({status_text}) - 消息:{client['messages']}" self.publicClientList.addItem(item_text) self.connectPublicButton.setEnabled(True) QMessageBox.information(self, '扫描完成', f'发现 {len(rpc_queues)} 个客户端') except Exception as e: QMessageBox.critical(self, '扫描失败', f'扫描公网客户端失败: {str(e)}') self.publicClientList.clear() self.publicClientList.addItem('扫描失败') self.connectPublicButton.setEnabled(False) def connectToPublicClient(self): """连接到选中的公网客户端""" selectedIndex = self.publicClientList.currentRow() if selectedIndex == -1: QMessageBox.warning(self, '警告', '请先选择一个客户端') return if selectedIndex >= len(self.publicClients): QMessageBox.warning(self, '警告', '选择的客户端无效') return selectedClient = self.publicClients[selectedIndex] clientName = selectedClient['name'] # 检查客户端状态 # if selectedClient['status'] == 'offline': # reply = QMessageBox.question(self, '客户端离线', # f'客户端 {clientName} 当前离线,是否仍要尝试连接?', # QMessageBox.Yes | QMessageBox.No) # if reply == QMessageBox.No: # return try: # 检查是否已经连接 protocolManage = Globals.getValue('protocolManage') if protocolManage and hasattr(protocolManage, 'RpcServer') and protocolManage.RpcServer: existing_clients = protocolManage.RpcServer.getClientNames() if clientName in existing_clients: QMessageBox.information(self, '提示', f'客户端 {clientName} 已连接,无需重复连接') return # 尝试添加客户端 if protocolManage.RpcServer.addClient(clientName): QMessageBox.information(self, '连接成功', f'已成功连接到客户端 {clientName}') # 刷新状态信息 self.updateStatusInfo() else: QMessageBox.warning(self, '连接失败', f'无法连接到客户端 {clientName},客户端可能不在线') else: QMessageBox.warning(self, '错误', '请先启动公网服务端模式') except Exception as e: QMessageBox.critical(self, '连接失败', f'连接客户端失败: {str(e)}') def autoRefreshPublicClients(self): """自动刷新公网客户端列表(静默模式)""" if not self.autoRefreshEnabled: return serverIp = self.publicServerInput.text().strip() if not serverIp: return try: # 静默扫描,不显示消息框 url = f"http://{serverIp}:15672/api/queues" response = requests.get(url, auth=('dcs', '123456'), timeout=5) queues = response.json() # 筛选RPC客户端队列 rpc_queues = [] for queue in queues: queue_name = queue['name'] if queue_name.startswith('rpc_queue_client'): client_name = queue_name.replace('rpc_queue_', '') rpc_queues.append({ 'name': client_name, 'queue': queue_name, 'messages': queue.get('messages', 0), 'consumers': queue.get('consumers', 0), 'status': 'online' if queue.get('consumers', 0) > 0 else 'offline' }) # 更新客户端列表(保持选中状态) current_selection = self.publicClientList.currentRow() self.publicClients = rpc_queues self.publicClientList.clear() if not rpc_queues: self.publicClientList.addItem('未发现任何客户端') self.connectPublicButton.setEnabled(False) else: for client in rpc_queues: status_text = "在线" if client['status'] == 'online' else "离线" item_text = f"{client['name']} ({status_text}) - 消息:{client['messages']}" self.publicClientList.addItem(item_text) self.connectPublicButton.setEnabled(True) # 恢复选中状态 if 0 <= current_selection < len(rpc_queues): self.publicClientList.setCurrentRow(current_selection) except Exception as e: # 静默处理错误,不显示消息框 print(f"自动刷新公网客户端失败: {e}") def toggleAutoRefresh(self, state): """切换自动刷新状态""" self.autoRefreshEnabled = state == 2 # Qt.Checked = 2 if self.autoRefreshEnabled: self.publicRefreshTimer.start(5000) # 每5秒刷新一次 print("已启用公网客户端自动刷新") else: self.publicRefreshTimer.stop() print("已禁用公网客户端自动刷新") def connectToDevice(self): """连接选中的设备""" selectedIndex = self.deviceList.currentRow() if selectedIndex == -1: QMessageBox.warning(self, '警告', '请先选择一个设备') return selectedServer = self.servers[selectedIndex] from utils import Globals protocolManage = Globals.getValue('protocolManage') already_connected = False ip = selectedServer['ip'][0] if isinstance(selectedServer['ip'], (list, tuple)) else selectedServer['ip'] if protocolManage and hasattr(protocolManage, 'RpcServer') and protocolManage.RpcServer: clients = protocolManage.RpcServer.getClientNames() ipMap = protocolManage.RpcServer.getClientIpMap() if hasattr(protocolManage.RpcServer, 'getClientIpMap') else {} for c in clients: if ipMap.get(c, '') == ip: already_connected = True break if already_connected: QMessageBox.information(self, '提示', f'客户端 {ip} 已连接,无需重复连接') return self.tcpClient.connectToServer(ip, selectedServer['port']) def getLocalIp(self): for interface in QNetworkInterface.allInterfaces(): if interface.flags() & QNetworkInterface.IsUp: for entry in interface.addressEntries(): ip = entry.ip() # 修改为新的枚举访问方式 if ip.protocol() == QAbstractSocket.IPv4Protocol and not ip.isLoopback(): return ip.toString() return "192.168.1.1" # 默认回退值 def cleanup(self): # 释放后台线程 if self.discoveryThread and self.discoveryThread.isRunning(): self.discoveryThread.terminate() self.discoveryThread.wait() def closeEvent(self, event): self.cleanup() event.accept() def __del__(self): self.cleanup() def updateStatusInfo(self): protocolManage = Globals.getValue('protocolManage') mode = '无' info = '无' # 重置按钮状态 isServerMode = False isClientMode = False if protocolManage: if hasattr(protocolManage, 'RpcServer') and protocolManage.RpcServer: mode = '服务端模式' isServerMode = True try: clients = protocolManage.RpcServer.getClientNames() clientIpMap = protocolManage.RpcServer.getClientIpMap() if hasattr(protocolManage.RpcServer, 'getClientIpMap') else {} info = '已连接客户端: ' + (', '.join([f"{c} ({clientIpMap.get(c, '')})" for c in clients]) if clients else '无') self.disconnectList.clear() for c in clients: ip = clientIpMap.get(c, '') display = f"{c} ({ip})" if ip else c self.disconnectList.addItem(display) except: info = '已连接客户端: 无' self.disconnectList.clear() elif hasattr(protocolManage, 'RpcClient') and protocolManage.RpcClient: mode = '客户端模式' isClientMode = True try: clientName = protocolManage.RpcClient.clientName serverInfo = protocolManage.RpcClient.rabbitHost info = f'客户端名: {clientName} 服务器: {serverInfo}' self.disconnectList.clear() except: info = '客户端信息获取失败' self.disconnectList.clear() # 更新公网服务端按钮状态(主站模式) self.publicConnectButton.setEnabled(not isServerMode) self.publicDisconnectButton.setEnabled(isServerMode) self.statusLabel.setText(f'服务器模式: {mode}') self.infoLabel.setText(f'连接信息: {info}') def disconnectClient(self, item): # 支持“客户端名 (IP)”格式 text = item.text() clientName = text.split(' ')[0] from utils import Globals protocolManage = Globals.getValue('protocolManage') if protocolManage and hasattr(protocolManage, 'disconnectClient'): protocolManage.disconnectClient(clientName) QMessageBox.information(self, '断开连接', f'已断开客户端 {clientName}') # 立即刷新列表 self.updateStatusInfo() class TcpServer(QObject): updateSignal = pyqtSignal(str) def __init__(self): super().__init__() # 配置信息 self.tcpPort = 12345 # 服务端TCP监听端口 self.udpPort = 54321 # 设备发现UDP端口 self.broadcastAddr = '' # 广播地址 self.tcpRunning = False self.udpRunning = False self.tcpThread = None self.udpThread = None self.serverSocket = None self.udpSocket = None def log(self, message): currentTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") logMessage = f"[{currentTime}] {message}" self.updateSignal.emit(logMessage) def tcpServer(self): try: self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.serverSocket.settimeout(1) # 设置1秒超时 self.serverSocket.bind(('0.0.0.0', self.tcpPort)) self.serverSocket.listen(5) self.log(f"TCP服务端已启动,监听端口 {self.tcpPort}") while self.tcpRunning: try: clientSock, addr = self.serverSocket.accept() self.log(f"接收到来自 {addr} 的连接") clientThread = threading.Thread(target=self.handleClient, args=(clientSock,addr)) clientThread.start() except socket.timeout: continue # 超时后继续检查运行标志 except: break except Exception as e: self.log(f"TCP服务器错误: {e}") finally: if self.serverSocket: self.serverSocket.close() self.log("TCP服务端已停止") def handleClient(self, clientSock, addr): try: while True: data = clientSock.recv(1024) if not data: break Globals.getValue('protocolManage').closeServer() Globals.getValue('protocolManage').setClentMode(data.decode('utf-8'), rabbitmqHost = addr[0]) self.log(f"收到消息: {data.decode('utf-8')}") clientSock.send(data) # 返回确认 # 新增:弹窗提示本机已被连接 # QMessageBox.information(None, '连接提示', f'本机已被 {addr[0]} 连接') except Exception as e: self.log(f"客户端异常断开: {e}") finally: clientSock.close() def udpDiscoveryServer(self): try: self.udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.udpSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.udpSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) self.udpSocket.bind(('', self.udpPort)) self.log(f"UDP发现服务已启动,监听端口 {self.udpPort}") while self.udpRunning: try: data, addr = self.udpSocket.recvfrom(1024) if data.decode('utf-8') == "DISCOVERY_REQUEST": self.log(f"收到来自 {addr} 的发现请求") response = f"DISCOVERY_RESPONSE:{socket.gethostname()}:{self.tcpPort}" # print(response) self.udpSocket.sendto(response.encode('utf-8'), addr) except: break except Exception as e: self.log(f"UDP服务器错误: {e}") finally: if self.udpSocket: self.udpSocket.close() self.log("UDP发现服务已停止") def startTcpServer(self): if not self.tcpRunning: self.tcpRunning = True self.tcpThread = threading.Thread(target=self.tcpServer) self.tcpThread.start() def stopTcpServer(self): if self.tcpRunning: self.tcpRunning = False # 唤醒accept阻塞,安全关闭线程 if self.serverSocket: try: self.serverSocket.shutdown(socket.SHUT_RDWR) except: pass try: self.serverSocket.close() except: pass if self.tcpThread and self.tcpThread.is_alive(): self.tcpThread.join(timeout=1) def startUdpServer(self): if not self.udpRunning: self.udpRunning = True self.udpThread = threading.Thread(target=self.udpDiscoveryServer) self.udpThread.start() def stopUdpServer(self): if self.udpRunning: self.udpRunning = False # 唤醒recvfrom阻塞,安全关闭线程 if self.udpSocket: try: self.udpSocket.shutdown(socket.SHUT_RDWR) except: pass try: self.udpSocket.close() except: pass if self.udpThread and self.udpThread.is_alive(): self.udpThread.join(timeout=1) class DeviceSlaveWidget(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("设备从站控制") # self.setGeometry(100, 100, 600, 400) self.server = TcpServer() self.server.updateSignal.connect(self.updateLog) self.statusLabel = None self.infoLabel = None self.publicServerInput = None self.initUI() # 定时器启动放到控件初始化后 self.statusTimer = QTimer(self) self.statusTimer.timeout.connect(self.updateStatusInfo) self.statusTimer.start(1000) def initUI(self): # 主布局 mainLayout = QVBoxLayout() self.statusLabel = QLabel('服务器模式: 无') mainLayout.addWidget(self.statusLabel) self.infoLabel = QLabel('连接信息: 无') mainLayout.addWidget(self.infoLabel) # 公网客户端连接配置 publicGroup = QGroupBox('公网客户端连接') publicLayout = QVBoxLayout() # 服务器地址输入 serverLayout = QHBoxLayout() serverLayout.addWidget(QLabel('服务器地址:')) self.publicServerInput = QLineEdit('43.138.48.181') self.publicServerInput.setPlaceholderText('输入公网服务器IP地址') serverLayout.addWidget(self.publicServerInput) publicLayout.addLayout(serverLayout) # 公网客户端控制按钮 clientButtonLayout = QHBoxLayout() self.publicConnectButton = QPushButton('连接公网服务器') self.publicConnectButton.clicked.connect(self.connectToPublicServer) self.publicConnectButton.setObjectName('setButton') clientButtonLayout.addWidget(self.publicConnectButton) self.publicDisconnectButton = QPushButton('断开公网连接') self.publicDisconnectButton.clicked.connect(self.disconnectFromPublicServer) self.publicDisconnectButton.setObjectName('setButton') self.publicDisconnectButton.setEnabled(False) clientButtonLayout.addWidget(self.publicDisconnectButton) publicLayout.addLayout(clientButtonLayout) publicGroup.setLayout(publicLayout) mainLayout.addWidget(publicGroup) # 局域网模式控制 lanGroup = QGroupBox('局域网通讯模式') lanLayout = QVBoxLayout() self.udpButton = QPushButton("开启远程通讯模式") self.udpButton.clicked.connect(self.toggleUdpServer) self.udpButton.setObjectName('setButton') lanLayout.addWidget(self.udpButton) lanGroup.setLayout(lanLayout) mainLayout.addWidget(lanGroup) # 日志显示 self.logDisplay = QTextEdit() self.logDisplay.setReadOnly(True) mainLayout.addWidget(QLabel("服务器日志:")) mainLayout.addWidget(self.logDisplay) # 设置中心部件 container = QWidget() container.setLayout(mainLayout) self.setCentralWidget(container) def toggleTcpServer(self): if self.server.tcpRunning: self.server.stopTcpServer() # print("关闭 TCP 服务器") else: self.server.startTcpServer() # print("启动 TCP 服务器") def connectToPublicServer(self): """连接到公网服务器作为客户端""" serverIp = self.publicServerInput.text().strip() if not serverIp: QMessageBox.warning(self, '警告', '请输入服务器地址') return try: # 获取客户端名称 from protocol.RPC.RpcClient import RpcClient clientName = RpcClient.getNextClientNameFromRabbitMQ(serverIp) print(f"获取到客户端名称: {clientName}") # 设置为客户端模式 Globals.getValue('protocolManage').closeServer() Globals.getValue('protocolManage').setClentMode(clientName, rabbitmqHost=serverIp) # 更新按钮状态 self.publicConnectButton.setEnabled(False) self.publicDisconnectButton.setEnabled(True) QMessageBox.information(self, '连接成功', f'已成功连接到公网服务器 {serverIp}\n客户端名称: {clientName}') except Exception as e: QMessageBox.critical(self, '连接失败', f'连接公网服务器失败: {str(e)}') def disconnectFromPublicServer(self): """断开公网服务器连接""" try: # 关闭客户端模式 Globals.getValue('protocolManage').closeClient() # 更新按钮状态 self.publicConnectButton.setEnabled(True) self.publicDisconnectButton.setEnabled(False) QMessageBox.information(self, '成功', '已断开公网服务器连接') except Exception as e: QMessageBox.critical(self, '失败', f'断开公网连接失败: {str(e)}') def toggleUdpServer(self): if self.server.udpRunning: self.server.stopUdpServer() self.udpButton.setText("开启远程通讯模式") else: self.server.startUdpServer() self.udpButton.setText("关闭远程通讯模式") self.toggleTcpServer() def updateLog(self, message): self.logDisplay.append(message) def cleanup(self): if self.server.tcpRunning: self.server.stopTcpServer() if self.server.udpRunning: self.server.stopUdpServer() def closeEvent(self, event): self.cleanup() event.accept() def __del__(self): # print(111111111111111111) self.cleanup() def updateStatusInfo(self): protocolManage = Globals.getValue('protocolManage') mode = '无' info = '无' # 重置按钮状态 isClientMode = False if protocolManage: if hasattr(protocolManage, 'RpcClient') and protocolManage.RpcClient: mode = '客户端模式' isClientMode = True try: clientName = protocolManage.RpcClient.clientName serverInfo = protocolManage.RpcClient.rabbitHost info = f'客户端名: {clientName} 服务器: {serverInfo}' except: info = '客户端信息获取失败' else: # 没有RpcClient,显示无 mode = '无' info = '无' else: mode = '无' info = '无' # 更新公网客户端按钮状态(从站模式) self.publicConnectButton.setEnabled(not isClientMode) self.publicDisconnectButton.setEnabled(isClientMode) self.statusLabel.setText(f'服务器模式: {mode}') self.infoLabel.setText(f'连接信息: {info}')