|  |  |  |  | import sys | 
					
						
							|  |  |  |  | import socket | 
					
						
							|  |  |  |  | import threading | 
					
						
							|  |  |  |  | from PyQt5.QtWidgets import QMainWindow, QVBoxLayout, QPushButton, \ | 
					
						
							|  |  |  |  |                              QListWidget, QLabel, QWidget, QMessageBox, QTextEdit | 
					
						
							|  |  |  |  | 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 = '<broadcast>' | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     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.initUI() | 
					
						
							|  |  |  |  |         # 定时器启动放到控件初始化后 | 
					
						
							|  |  |  |  |         self.statusTimer = QTimer(self) | 
					
						
							|  |  |  |  |         self.statusTimer.timeout.connect(self.updateStatusInfo) | 
					
						
							|  |  |  |  |         self.statusTimer.start(1000) | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     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) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.ipAddresslabel = QLabel(self) | 
					
						
							|  |  |  |  |         self.ipAddresslabel.setObjectName("setlabel") | 
					
						
							|  |  |  |  |         self.ipAddresslabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) | 
					
						
							|  |  |  |  |         layout.addWidget(self.ipAddresslabel) | 
					
						
							|  |  |  |  |         # 标题标签 | 
					
						
							|  |  |  |  |         self.titleLabel = QLabel('点击"扫描设备"按钮发现局域网中的设备') | 
					
						
							|  |  |  |  |         layout.addWidget(self.titleLabel) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         # 设备列表 | 
					
						
							|  |  |  |  |         self.deviceList = QListWidget() | 
					
						
							|  |  |  |  |         layout.addWidget(self.deviceList) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |        | 
					
						
							|  |  |  |  |         self.scanButton = QPushButton('扫描设备') | 
					
						
							|  |  |  |  |         self.scanButton.clicked.connect(self.startDiscovery) | 
					
						
							|  |  |  |  |         layout.addWidget(self.scanButton) | 
					
						
							|  |  |  |  |         self.scanButton.setObjectName('setButton') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.connectButton = QPushButton('连接设备') | 
					
						
							|  |  |  |  |         self.connectButton.clicked.connect(self.connectToDevice) | 
					
						
							|  |  |  |  |         self.connectButton.setEnabled(False) | 
					
						
							|  |  |  |  |         self.connectButton.setObjectName('setButton') | 
					
						
							|  |  |  |  |         layout.addWidget(self.connectButton) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         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 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 = '无' | 
					
						
							|  |  |  |  |         if protocolManage: | 
					
						
							|  |  |  |  |             if hasattr(protocolManage, 'RpcServer') and protocolManage.RpcServer: | 
					
						
							|  |  |  |  |                 mode = '服务端模式' | 
					
						
							|  |  |  |  |                 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 = '客户端模式' | 
					
						
							|  |  |  |  |                 try: | 
					
						
							|  |  |  |  |                     clientName = protocolManage.RpcClient.clientName | 
					
						
							|  |  |  |  |                     serverInfo = protocolManage.RpcClient.rabbitHost | 
					
						
							|  |  |  |  |                     info = f'客户端名: {clientName}  服务器: {serverInfo}' | 
					
						
							|  |  |  |  |                     self.disconnectList.clear() | 
					
						
							|  |  |  |  |                 except: | 
					
						
							|  |  |  |  |                     info = '客户端信息获取失败' | 
					
						
							|  |  |  |  |                     self.disconnectList.clear() | 
					
						
							|  |  |  |  |         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 = '<broadcast>'  # 广播地址 | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         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("TCP/UDP 服务器控制") | 
					
						
							|  |  |  |  |         # self.setGeometry(100, 100, 600, 400) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         self.server = TcpServer() | 
					
						
							|  |  |  |  |         self.server.updateSignal.connect(self.updateLog) | 
					
						
							|  |  |  |  |         self.statusLabel = None | 
					
						
							|  |  |  |  |         self.infoLabel = 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) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         # 控制按钮 | 
					
						
							|  |  |  |  |         # self.tcpButton = QPushButton("启动 TCP 服务器") | 
					
						
							|  |  |  |  |         # self.tcpButton.clicked.connect(self.toggleTcpServer) | 
					
						
							|  |  |  |  |         # self.tcpButton.setObjectName('setButton') | 
					
						
							|  |  |  |  |         self.udpButton = QPushButton("开启远程通讯模式") | 
					
						
							|  |  |  |  |         self.udpButton.clicked.connect(self.toggleUdpServer) | 
					
						
							|  |  |  |  |         self.udpButton.setObjectName('setButton')    | 
					
						
							|  |  |  |  |         # 日志显示 | 
					
						
							|  |  |  |  |         self.logDisplay = QTextEdit() | 
					
						
							|  |  |  |  |         self.logDisplay.setReadOnly(True) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         # 添加到布局 | 
					
						
							|  |  |  |  |         # mainLayout.addWidget(self.tcpButton) | 
					
						
							|  |  |  |  |         mainLayout.addWidget(self.udpButton) | 
					
						
							|  |  |  |  |         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 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 = '无' | 
					
						
							|  |  |  |  |         if protocolManage: | 
					
						
							|  |  |  |  |             if hasattr(protocolManage, 'RpcClient') and protocolManage.RpcClient: | 
					
						
							|  |  |  |  |                 mode = '客户端模式' | 
					
						
							|  |  |  |  |                 try: | 
					
						
							|  |  |  |  |                     clientName = protocolManage.RpcClient.clientName | 
					
						
							|  |  |  |  |                     serverInfo = protocolManage.RpcClient.rabbitHost | 
					
						
							|  |  |  |  |                     info = f'客户端名: {clientName}  服务器: {serverInfo}' | 
					
						
							|  |  |  |  |                 except: | 
					
						
							|  |  |  |  |                     info = '客户端信息获取失败' | 
					
						
							|  |  |  |  |             else: | 
					
						
							|  |  |  |  |                 # 没有RpcClient,显示无 | 
					
						
							|  |  |  |  |                 mode = '无' | 
					
						
							|  |  |  |  |                 info = '无' | 
					
						
							|  |  |  |  |         else: | 
					
						
							|  |  |  |  |             mode = '无' | 
					
						
							|  |  |  |  |             info = '无' | 
					
						
							|  |  |  |  |         self.statusLabel.setText(f'服务器模式: {mode}') | 
					
						
							|  |  |  |  |         self.infoLabel.setText(f'连接信息: {info}') |