5.8 sendto和recvfrom() ---和我说话,数据报

本文详细介绍了数据报套接字中sendto和recvfrom函数的使用方法,包括函数原型、参数含义及返回值等,并解释了如何通过这些函数进行无连接的数据报通信。

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

原文:https://beej.us/guide/bgnet/html/#sendtorecv

 

5.8 sendto和recvfrom() ---和我说话,数据报

       “这很不错啊”,你说,“但是你还没有讲无连接数据报套接字呢?” 没问题,现在我们开始这个内容。

既然数据报套接字不是连接到远程主机的,那么在我们发送一个包之前需要什么信息呢? 不错,是目标地址!

       sendto()函数原型:

int sendto(int sockfd, const void *msg, int len, unsigned int flags,

const struct sockaddr *to, socklen_t tolen);

       你已经看到了,除了另外的两个信息外,其余的和函数 send() 是一样的。

to 是个指向常量结构 struct sockaddr 的指针,它包含了目的地的IP 地址和端口信息。

tolen 可以简单地设置为sizeof(struct sockaddr)。

和函数 send() 类似,sendto()返回实际发送的字节数(它也可能小于你想要发送的字节数!),

或者在错误的时候返回-1。

       recvfrom()函数原型:

int recvfrom(int sockfd, void *buf, int len, unsigned int flags,

struct sockaddr *from, int *fromlen);

       又一次,除了两个增加的参数外,这个函数和 recv() 也是一样的。

from 是一个指向局部数据结构 struct sockaddr 的指针,它的内容是源机器的IP 地址和端口信息。

fromlen 是个 int 型的局部指针,它的初始值为 sizeof(struct sockaddr)。

函数调用返回后,fromlen保存着实际储存在 from 中的地址的长度。

recvfrom() 返回收到的字节长度,或者在发生错误后返回 -1。

 

import os import sys import io import socket import time import re import threading import tkinter as tk import ttkbootstrap as tb from ttkbootstrap.constants import * from PIL import Image, ImageTk, ImageDraw import psutil import math import random # ====================== 数据采集服务 ====================== class HardwareMonitorService: def __init__(self): self.config = self.read_config() if self.config is None: raise Exception("配置读取失败,无法启动服务") self.server_ip = self.config.get('SERVER_IP') self.server_port = int(self.config.get('SERVER_PORT')) self.client_ip = self.config.get('CLIENT_IP') self.client_port = int(self.config.get('CLIENT_PORT')) self.running = True self.sock = None self.send_count = 1 self.setup_socket() # 启动服务线程 self.service_thread = threading.Thread(target=self.run_service, daemon=True) self.service_thread.start() def read_config(self): config = {} try: with open('config.txt', 'r') as config_file: for line in config_file: if '=' in line: key, value = line.strip().split('=', 1) config[key] = value print("读取配置成功", flush=True) return config except FileNotFoundError: print("无法打开配置文件!", flush=True) return None def is_command_available(self, command): """检查命令是否可用""" if os.name == 'nt': # Windows 系统 result = os.system(f'where {command} >nul 2>&1') else: # Linux 系统 result = os.system(f'which {command} >/dev/null 2>&1') return result == 0 def get_hardware_info(self, send_count): # 执行 cnmon info -e 命令并捕获输出 with os.popen('cnmon info -e') as f: result_temp = f.read() temperature_lines = self.extract_info(result_temp, "Temperature", "QDD Status") # 执行 cnmon info -p 命令并捕获输出 with os.popen('cnmon info -p') as f: result_power = f.read() power_lines = self.extract_info(result_power, "Power", "QDD Status") # 执行 cnmon info -m 命令并捕获输出 with os.popen('cnmon info -m') as f: result_memory = f.read() memory_lines = self.extract_info(result_memory, "v4.9.5", "Virtual Memory Usage") # 执行 cnmon info -b 命令并捕获输出 with os.popen('cnmon info -b') as f: result_bandwidth = f.read() bandwidth_lines = self.extract_info(result_bandwidth, "QDD 7 : Invalid", " Chassis") # 执行 cnmon info -u 命令并捕获输出 with os.popen('cnmon info -u') as f: result_usage = f.read() usage_lines = self.extract_info(result_usage, "Utilization", "QDD Status") usage_str = '\n'.join(usage_lines) mlu_average = 0 mlu_0 = 0 mlu_1 = 0 mlu_2 = 0 mlu_3 = 0 cpu_chip = 0 cpu_core_0 = 0 cpu_core_1 = 0 cpu_core_2 = 0 cpu_core_3 = 0 # 提取 MLU 平均利用率 mlu_avg_match = re.search(r'MLU Average\s+:\s+(\d+) %', usage_str) if mlu_avg_match: mlu_average = float(mlu_avg_match.group(1)) # 提取 MLU 0 - 3 利用率 mlu_0_3_match = re.search(r'MLU 0-3\s+:\s+(\d+) %\s+(\d+) %\s+(\d+) %\s+(\d+) %', usage_str) if mlu_0_3_match: mlu_0 = float(mlu_0_3_match.group(1)) mlu_1 = float(mlu_0_3_match.group(2)) mlu_2 = float(mlu_0_3_match.group(3)) mlu_3 = float(mlu_0_3_match.group(4)) # 提取 CPU 芯片利用率 cpu_chip_match = re.search(r'Device CPU Chip\s+:\s+(\d+) %', usage_str) if cpu_chip_match: cpu_chip = float(cpu_chip_match.group(1)) # 提取 CPU 核心 0 - 3 利用率 cpu_core_0_3_match = re.search(r'Device CPU Core 0-3\s+:\s+(\d+) %\s+(\d+) %\s+(\d+) %\s+(\d+) %', usage_str) if cpu_core_0_3_match: cpu_core_0 = float(cpu_core_0_3_match.group(1)) cpu_core_1 = float(cpu_core_0_3_match.group(2)) cpu_core_2 = float(cpu_core_0_3_match.group(3)) cpu_core_3 = float(cpu_core_0_3_match.group(4)) # 添加分隔符发送次数 info_str = ( "温度信息:\n{}\n\n功率信息:\n{}\n\n内存信息:\n{}\n\n带宽信息:\n{}\n\nMLU信息:\nMLU Average: {}%\nMLU 0-3 利用率:\nMLU 0: {}%\nMLU 1: {}%\nMLU 2: {}%\nMLU 3: {}%\n\nCPU信息:\n" "Device CPU Chip: {}%\nCPU核心 0-3 利用率:\nDevice CPU Core 0: {}%\nDevice CPU Core 1: {}%\nDevice CPU Core 2: {}%\nDevice CPU Core 3: {}%\n发送次数:\nsend_count : {}次\n---------------END---------------" ).format( '\n'.join(temperature_lines), '\n'.join(power_lines), '\n'.join(memory_lines), '\n'.join(bandwidth_lines), mlu_average, mlu_0, mlu_1, mlu_2, mlu_3, cpu_chip, cpu_core_0, cpu_core_1, cpu_core_2, cpu_core_3, send_count ) return info_str def extract_info(self, result, start_keyword, end_keyword): """提取指定关键字之间的信息""" lines = result.splitlines() extracted = [] started = False for line in lines: if start_keyword in line: started = True elif started and line.strip(): if end_keyword in line: break extracted.append(line.strip()) return extracted def setup_socket(self): """设置UDP套接字""" try: # 创建 UDP 套接字 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 端口号快速重用 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定服务器 IP 端口 self.sock.bind((self.server_ip, self.server_port)) print(f"绑定到 {self.server_ip}:{self.server_port}", flush=True) except OSError as e: print(f"绑定错误: {e}", flush=True) self.running = False def run_service(self): """运行数据采集服务""" print("硬件监控服务已启动", flush=True) while self.running: try: if not self.is_command_available('cnmon'): info = ( "温度信息:\n" "Board : 34 C\n" "Cluster 0 : 36 C\n" "\n" "功率信息:\n" "Usage : 3.44 W\n" "Cap : 15 W\n" " \n" "内存信息:\n" "Physical Memory Usage :\n" "Total : 8192 MiB\n" "Used : 1669 MiB\n" "Free : 6523 MiB\n" "Channel Memory Usage :\n" " 0 : 1669 MiB\n" "DDR Data Widths : 64 bit\n" "DDR BandWidth : 29 GB/s\n" "\n" "带宽信息:\n" "Bandwidth : N/A\n" "\n" "CPU信息:\n" "Device CPU Chip: 6.0%\n" "CPU核心 0-3 利用率:\n" "Device CPU Core 0: 3.0%\n" "Device CPU Core 1: 20.0%\n" "Device CPU Core 2: 9.0%\n" "Device CPU Core 3: 3.0%\n" "\n" "---------------END---------------\n" ) else: info = self.get_hardware_info(self.send_count) # 发送数据到客户端 self.sock.sendto(info.encode(), (self.client_ip, self.client_port)) self.send_count += 1 time.sleep(0.5) except Exception as e: print(f"服务错误: {e}", flush=True) time.sleep(1) def stop_service(self): """停止数据采集服务""" self.running = False if self.sock: self.sock.close() print("硬件监控服务已停止", flush=True) # ====================== GUI 监控界面 ====================== class EnhancedCircularProgressBar: def __init__(self, parent, size=200, thickness=20, bg_color="#1a1a1a", fg_color="#4caf50", text_color="#ffffff", font_size=16, title="", unit="", max_value=100, glow_effect=True): self.parent = parent self.size = size self.thickness = thickness self.bg_color = bg_color self.fg_color = fg_color self.text_color = text_color self.font_size = font_size self.title = title self.unit = unit self.max_value = max_value self.glow_effect = glow_effect # 创建Canvas self.canvas = tk.Canvas( parent, width=size, height=size, bg="black", highlightthickness=0, bd=0 ) # 计算圆心半径 self.center_x = size / 2 self.center_y = size / 2 self.radius = (size - thickness) / 2 - 5 # 创建渐变效果 self.create_gradient() # 绘制背景圆环 self.draw_background() # 创建进度弧 self.arc_id = self.canvas.create_arc( self.center_x - self.radius, self.center_y - self.radius, self.center_x + self.radius, self.center_y + self.radius, start=90, extent=0, style=tk.ARC, outline="", width=thickness, tags="progress" ) # 创建发光效果 if self.glow_effect: self.glow_id = self.canvas.create_oval( self.center_x - self.radius - 5, self.center_y - self.radius - 5, self.center_x + self.radius + 5, self.center_y + self.radius + 5, outline="", fill="", tags="glow" ) # 创建文本元素 self.create_text_elements() # 动画控制变量 self.current_value = 0 self.target_value = 0 self.animation_running = False self.animation_id = None self.last_update_time = time.time() # 性能优化 self.canvas.tag_raise("progress") self.canvas.tag_raise("text") def create_gradient(self): """创建渐变背景效果""" self.gradient_img = Image.new("RGBA", (self.size, self.size), (0, 0, 0, 0)) draw = ImageDraw.Draw(self.gradient_img) for r in range(int(self.radius), 0, -1): alpha = int(150 * (1 - r/self.radius)) draw.ellipse([ self.center_x - r, self.center_y - r, self.center_x + r, self.center_y + r ], outline=(40, 40, 40, alpha)) self.gradient_photo = ImageTk.PhotoImage(self.gradient_img) self.canvas.create_image( self.center_x, self.center_y, image=self.gradient_photo, tags="background" ) def draw_background(self): """绘制背景圆环""" self.bg_arc_id = self.canvas.create_arc( self.center_x - self.radius, self.center_y - self.radius, self.center_x + self.radius, self.center_y + self.radius, start=0, extent=359.9, style=tk.ARC, outline=self.bg_color, width=self.thickness, tags="background" ) def create_text_elements(self): """创建所有文本元素""" # 标题文本 self.title_id = self.canvas.create_text( self.center_x, self.center_y - self.radius * 0.5, text=self.title, fill=self.text_color, font=("Arial", self.font_size, "bold"), tags="text" ) # 数值文本 self.value_id = self.canvas.create_text( self.center_x, self.center_y, text="0", fill=self.text_color, font=("Arial", int(self.font_size * 1.8), "bold"), tags="text" ) # 单位文本 self.unit_id = self.canvas.create_text( self.center_x, self.center_y + self.radius * 0.3, text=self.unit, fill=self.text_color, font=("Arial", self.font_size - 2), tags="text" ) def calculate_color(self, value): """根据数值计算动态颜色""" ratio = value / self.max_value # 温度特殊处理(红色表示高温) if "温度" in self.title: r = min(255, int(255 * ratio)) g = min(255, int(255 * (1 - ratio))) b = 50 return f"#{r:02x}{g:02x}{b:02x}" # 正常渐变:绿 -> 黄 -> 红 if ratio < 0.5: r = int(255 * ratio * 2) g = 255 else: r = 255 g = int(255 * (1 - (ratio - 0.5) * 2)) return f"#{r:02x}{g:02x}00" def set_value(self, value): """设置目标值""" self.target_value = max(0, min(self.max_value, value)) # 更新数值显示 self.canvas.itemconfig(self.value_id, text=f"{self.target_value:.1f}") # 启动动画 if not self.animation_running: self.animate() def animate(self): """平滑动画更新进度""" self.animation_running = True # 计算插值(使用缓动函数) delta = self.target_value - self.current_value speed_factor = 0.2 # 控制动画速度 if abs(delta) > 0.1: self.current_value += delta * speed_factor else: self.current_value = self.target_value # 计算弧的角度 angle = 360 * (self.current_value / self.max_value) # 更新弧 self.canvas.itemconfig(self.arc_id, extent=-angle) # 更新颜色 color = self.calculate_color(self.current_value) self.canvas.itemconfig(self.arc_id, outline=color) # 更新发光效果 if self.glow_effect and time.time() - self.last_update_time > 0.1: self.update_glow_effect(color) self.last_update_time = time.time() # 继续动画或停止 if abs(self.current_value - self.target_value) > 0.5: self.animation_id = self.canvas.after(16, self.animate) else: self.current_value = self.target_value self.animation_running = False self.animation_id = None def update_glow_effect(self, color): """更新发光效果""" if not self.glow_effect: return # 创建新的发光图像 glow_img = Image.new("RGBA", (self.size, self.size), (0, 0, 0, 0)) draw = ImageDraw.Draw(glow_img) # 解析颜色 r = int(color[1:3], 16) g = int(color[3:5], 16) b = int(color[5:7], 16) # 绘制发光效果 for i in range(1, 6): alpha = int(50 * (1 - i/6)) radius = self.radius + i draw.ellipse([ self.center_x - radius, self.center_y - radius, self.center_x + radius, self.center_y + radius ], outline=(r, g, b, alpha), width=1) self.glow_photo = ImageTk.PhotoImage(glow_img) self.canvas.itemconfig(self.glow_id, image=self.glow_photo) def reset(self): """重置进度条""" if self.animation_id: self.canvas.after_cancel(self.animation_id) self.current_value = 0 self.target_value = 0 self.canvas.itemconfig(self.arc_id, extent=0) self.canvas.itemconfig(self.value_id, text="0") color = self.calculate_color(0) self.canvas.itemconfig(self.arc_id, outline=color) class SystemMonitorApp: def __init__(self): # 启动数据采集服务 try: self.monitor_service = HardwareMonitorService() client_ip = self.monitor_service.client_ip client_port = self.monitor_service.client_port except Exception as e: print(f"无法启动数据采集服务: {e}") self.monitor_service = None client_ip = "127.0.0.1" client_port = 9999 # 创建主窗口 self.root = tb.Window(themename="darkly", title="系统资源监控", size=(1200, 800)) self.root.iconbitmap("") self.root.minsize(1000, 700) # 设置样式 style = tb.Style() style.configure("TFrame", background="#121212") style.configure("Title.TLabel", background="#121212", foreground="#e0e0e0", font=("Arial", 16, "bold")) # 创建UDP接收套接字 self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.udp_socket.bind((client_ip, client_port)) print(f"GUI绑定到 {client_ip}:{client_port} 接收数据") except Exception as e: print(f"GUI绑定错误: {e}") self.udp_socket.settimeout(0.1) # 设置超时避免阻塞 # 存储真实数据的变量 self.real_data = { "cpu_temp": 0.0, "power": 0.0, "memory": 0.0, "bandwidth": 0.0, "mlu_usage": 0.0, "cpu_usage": 0.0 } # 创建主框架 main_frame = tb.Frame(self.root, padding=20) main_frame.pack(fill=tk.BOTH, expand=True) # 标题 tb.Label( main_frame, text="系统资源实时监控", style="Title.TLabel" ).pack(pady=(0, 20)) # 创建进度条容器框架 progress_container = tb.Frame(main_frame) progress_container.pack(fill=tk.BOTH, expand=True, pady=10) # 创建监控指标配置 monitor_config = [ {"title": "CPU温度", "unit": "°C", "max_value": 100, "thickness": 18, "fg_color": "#ff5555"}, {"title": "功率", "unit": "W", "max_value": 200, "thickness": 18, "fg_color": "#ffaa00"}, {"title": "内存使用", "unit": "%", "max_value": 100, "thickness": 18, "fg_color": "#55aaff"}, {"title": "网络带宽", "unit": "Mbps", "max_value": 1000, "thickness": 18, "fg_color": "#aa55ff"}, {"title": "MLU利用率", "unit": "%", "max_value": 100, "thickness": 18, "fg_color": "#00cc99"}, {"title": "CPU利用率", "unit": "%", "max_value": 100, "thickness": 18, "fg_color": "#ff55ff"} ] # 使用网格布局排列进度条 self.progress_bars = [] for i, config in enumerate(monitor_config): frame = tb.Frame(progress_container) frame.grid(row=i//3, column=i%3, padx=20, pady=20, sticky="nsew") # 创建增强型进度条 progress_bar = EnhancedCircularProgressBar( frame, size=220, thickness=config["thickness"], title=config["title"], unit=config["unit"], max_value=config["max_value"], fg_color=config["fg_color"], glow_effect=True ) self.progress_bars.append(progress_bar) progress_bar.canvas.pack(fill=tk.BOTH, expand=True) # 设置网格列权重 for i in range(3): progress_container.columnconfigure(i, weight=1) for i in range(2): progress_container.rowconfigure(i, weight=1) # 控制面板 control_frame = tb.Frame(main_frame) control_frame.pack(pady=20, fill=tk.X) # 按钮框架 btn_frame = tb.Frame(control_frame) btn_frame.pack(pady=10) tb.Button( btn_frame, text="启动", bootstyle=SUCCESS, command=self.start_monitoring ).pack(side=tk.LEFT, padx=5) tb.Button( btn_frame, text="暂停", bootstyle=DANGER, command=self.stop_monitoring ).pack(side=tk.LEFT, padx=5) tb.Button( btn_frame, text="重置", bootstyle=WARNING, command=self.reset_all ).pack(side=tk.LEFT, padx=5) # 主题选择器 theme_frame = tb.Frame(control_frame) theme_frame.pack(fill=tk.X, pady=10) tb.Label(theme_frame, text="选择主题:", bootstyle=PRIMARY).pack(anchor=tk.W) self.theme_var = tk.StringVar(value="darkly") themes = ["darkly", "cyborg", "solar", "minty", "cosmo", "flatly"] for theme in themes: tb.Radiobutton( theme_frame, text=theme.capitalize(), variable=self.theme_var, value=theme, bootstyle=PRIMARY, command=self.change_theme ).pack(side=tk.LEFT, padx=5) # 状态栏 self.status = tb.Label( self.root, text="系统准备就绪", bootstyle=(SECONDARY, INVERSE), anchor=tk.CENTER ) self.status.pack(side=tk.BOTTOM, fill=tk.X) # 监控控制变量 self.monitoring_active = False self.monitoring_thread = None # 启动初始监控 self.start_monitoring() # 窗口关闭事件处理 self.root.protocol("WM_DELETE_WINDOW", self.on_close) self.root.mainloop() def start_monitoring(self): """启动资源监控""" if self.monitoring_active: return self.status.config(text="启动系统资源监控...") self.monitoring_active = True # 使用线程运行监控,避免阻塞UI self.monitoring_thread = threading.Thread(target=self.monitor_resources, daemon=True) self.monitoring_thread.start() def stop_monitoring(self): """停止资源监控""" self.monitoring_active = False self.status.config(text="监控已暂停") def reset_all(self): """重置所有监控指标""" for bar in self.progress_bars: bar.reset() self.status.config(text="所有监控指标已重置") def receive_real_data(self): """接收并解析真实硬件数据""" try: data, _ = self.udp_socket.recvfrom(4096) data_str = data.decode('utf-8') self.parse_hardware_info(data_str) except socket.timeout: pass # 没有数据是正常的 except Exception as e: print(f"接收数据错误: {e}") def parse_hardware_info(self, info_str): """解析硬件信息字符串""" try: # 解析CPU温度 temp_match = re.search(r"Board\s+:\s+(\d+\.?\d*)\s*C", info_str) if temp_match: self.real_data["cpu_temp"] = float(temp_match.group(1)) # 解析功率 power_match = re.search(r"Usage\s+:\s+(\d+\.?\d*)\s*W", info_str) if power_match: self.real_data["power"] = float(power_match.group(1)) # 解析内存使用率 mem_match = re.search(r"Used\s+:\s+(\d+)\s*MiB.*?Total\s+:\s+(\d+)\s*MiB", info_str, re.DOTALL) if mem_match: used = float(mem_match.group(1)) total = float(mem_match.group(2)) self.real_data["memory"] = (used / total) * 100 # 解析MLU利用率 mlu_match = re.search(r"MLU Average:\s*(\d+\.?\d*)%", info_str) if mlu_match: self.real_data["mlu_usage"] = float(mlu_match.group(1)) # 解析CPU利用率 cpu_match = re.search(r"Device CPU Chip:\s*(\d+\.?\d*)%", info_str) if cpu_match: self.real_data["cpu_usage"] = float(cpu_match.group(1)) # 更新状态栏显示 self.status.config(text=f"接收到真实数据: {time.strftime('%H:%M:%S')}") except Exception as e: print(f"解析硬件信息错误: {e}") def monitor_resources(self): """监控系统资源""" while self.monitoring_active: # 尝试接收真实数据 self.receive_real_data() # 优先使用真实数据,如果没有则使用模拟数据 cpu_temp = self.real_data["cpu_temp"] or self.get_cpu_temperature() power = self.real_data["power"] or self.get_power_usage() mem_usage = self.real_data["memory"] or self.get_memory_usage() network = self.real_data["bandwidth"] or self.get_network_usage() mlu_usage = self.real_data["mlu_usage"] or self.get_mlu_usage() cpu_usage = self.real_data["cpu_usage"] or psutil.cpu_percent() # 更新进度条 self.progress_bars[0].set_value(cpu_temp) # CPU温度 self.progress_bars[1].set_value(power) # 功率 self.progress_bars[2].set_value(mem_usage) # 内存使用 self.progress_bars[3].set_value(network) # 网络带宽 self.progress_bars[4].set_value(mlu_usage) # MLU利用率 self.progress_bars[5].set_value(cpu_usage) # CPU利用率 # 更新状态栏 status_text = ( f"CPU: {cpu_usage:.1f}% | " f"温度: {cpu_temp:.1f}°C | " f"内存: {mem_usage:.1f}% | " f"MLU: {mlu_usage:.1f}%" ) self.status.config(text=status_text) # 控制更新频率 time.sleep(1) def get_cpu_temperature(self): """获取CPU温度(模拟)""" base_temp = 40.0 fluctuation = random.uniform(-2, 8) load_factor = self.progress_bars[5].current_value / 100 * 10 return min(100, max(30, base_temp + fluctuation + load_factor)) def get_power_usage(self): """获取功率使用(模拟)""" base_power = 80.0 fluctuation = random.uniform(-10, 15) load_factor = (self.progress_bars[5].current_value + self.progress_bars[4].current_value) / 200 * 50 return min(200, max(50, base_power + fluctuation + load_factor)) def get_memory_usage(self): """获取内存使用率""" return psutil.virtual_memory().percent def get_network_usage(self): """获取网络带宽使用(模拟)""" base_usage = 300.0 fluctuation = random.uniform(-50, 100) return min(1000, max(0, base_usage + fluctuation)) def get_mlu_usage(self): """获取MLU利用率(模拟)""" base_usage = 30.0 fluctuation = random.uniform(-5, 15) load_factor = random.uniform(0, 40) return min(100, max(0, base_usage + fluctuation + load_factor)) def change_theme(self): """更改应用主题""" theme = self.theme_var.get() tb.Style(theme=theme) self.status.config(text=f"主题已切换为: {theme.capitalize()}") def on_close(self): """窗口关闭时清理资源""" self.monitoring_active = False if self.monitor_service: self.monitor_service.stop_service() self.udp_socket.close() self.root.destroy() if __name__ == "__main__": # 设置无缓冲输出 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', line_buffering=True) # 启动GUI应用 SystemMonitorApp()该代码不再使用虚拟测试而是使用MLU220的cnmon指令如;cnmon info -p来获取板卡功耗信息,cnmon info -e来获取板卡温度数据,cnmon info -m来获取板卡内存信息,cnmon info -b来获取板卡带宽信息,cnmon info -u来获取板卡利用率信息。将获取信息方式写入上述代码中
06-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值