使用繁體中文,在linux mint21.3下,使用python語言,使用UI界面,要設計區網中電腦,client端程式啟動後,自動到伺服端電腦報到,,伺服端用UI界面呈現,clinet端報到後,要回報ip位址、MAC位址、電腦名稱、連線速度,伺服端使用者要能選擇不同的clinet端電腦,UI界面上有一個按鈕,名稱是"重新開機",功能是讓被選到的clinet端電腦(可以選擇多台電腦),重新開機,要如何處理,請給完整範例,謝謝
讓本機電腦重新啟動,要如何處理,請給完整範例,謝謝
要實現這個功能,我們需要設計一個簡單的伺服器(Server)和客戶端(Client)架構。伺服器將顯示所有連接的客戶端資訊,而客戶端在啟動時會自動向伺服器報到。伺服器還需要能夠選擇不同的客戶端並對其發送重啟指令。
以下是完整的範例,包括伺服器和客戶端的實作。
伺服端
import socket
import threading
import tkinter as tk
from tkinter import messagebox, simpledialog
clients = {}
def handle_client(conn, addr):
while True:
try:
data = conn.recv(1024).decode()
if not data:
break
ip, mac, hostname, speed = data.split(',')
clients[addr] = (ip, mac, hostname, speed)
update_client_list()
except Exception as e:
break
conn.close()
del clients[addr]
update_client_list()
def update_client_list():
client_list.delete(0, tk.END)
for addr, info in clients.items():
client_list.insert(tk.END, f"{info[2]} - {info[0]} - {info[1]} - {info[3]}")
def reboot_selected_clients():
selected_clients = client_list.curselection()
for i in selected_clients:
client_addr = list(clients.keys())[i]
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(b'reboot', client_addr)
messagebox.showinfo("通知", "已發送重啟指令給選中的客戶端。")
def start_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 9999))
server_socket.listen(5)
while True:
conn, addr = server_socket.accept()
threading.Thread(target=handle_client, args=(conn, addr)).start()
root = tk.Tk()
root.title("伺服器端")
client_list = tk.Listbox(root, width=50)
client_list.pack(pady=10)
reboot_button = tk.Button(root, text="重新開機", command=reboot_selected_clients)
reboot_button.pack(pady=10)
threading.Thread(target=start_server, daemon=True).start()
root.mainloop()
client端
import socket
import uuid
import platform
import speedtest
import time
SERVER_IP = '伺服器的IP位址' # 請替換為伺服器的實際IP
SERVER_PORT = 9999
def get_system_info():
ip_address = socket.gethostbyname(socket.gethostname())
mac_address = ':'.join(['{:02x}'.format((uuid.getnode() >> elements) & 0xff) for elements in range(0,2*6,2)][::-1])
hostname = platform.node()
speed = str(speedtest.Speedtest().download() / 1_000_000) + ' Mbps'
return ip_address, mac_address, hostname, speed
def report_to_server():
ip, mac, hostname, speed = get_system_info()
message = f"{ip},{mac},{hostname},{speed}"
while True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((SERVER_IP, SERVER_PORT))
sock.sendall(message.encode())
sock.close()
break
except:
time.sleep(5) # 連接失敗時,等待再試
def listen_for_commands():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 9998))
while True:
data, addr = sock.recvfrom(1024)
if data.decode() == 'reboot':
print("收到重啟指令,正在重新啟動...")
# 可以在這裡執行系統重啟命令
# 例如在Linux上: os.system('sudo reboot')
break
report_to_server()
listen_for_commands()
以下是一個完整的範例程式,實現了使用 UDP multicast 傳送和接收檔案的功能,並包含了簡單的 Tkinter UI 界面。
import socket
import os
import threading
import tkinter as tk
from tkinter import filedialog, messagebox
MULTICAST_GROUP = '224.0.0.1'
PORT = 5004
def send_file(file_path):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
with open(file_path, 'rb') as f:
data = f.read(1024)
while data:
sock.sendto(data, (MULTICAST_GROUP, PORT))
data = f.read(1024)
sock.sendto(b'', (MULTICAST_GROUP, PORT)) # Send empty message to indicate end
sock.close()
def receive_files():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', PORT))
mreq = socket.inet_aton(MULTICAST_GROUP) + socket.inet_aton('0.0.0.0')
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
data, addr = sock.recvfrom(1024)
if not data:
break
# 將接收到的數據寫入檔案
with open('received_file', 'ab') as f:
f.write(data)
sock.close()
messagebox.showinfo("通知", "檔案接收完成!")
def choose_file():
file_path = filedialog.askopenfilename()
if file_path:
file_label.config(text=file_path)
send_button.config(state=tk.NORMAL)
def start_sending():
file_path = file_label.cget("text")
if file_path:
threading.Thread(target=send_file, args=(file_path,)).start()
def start_receiving():
threading.Thread(target=receive_files, daemon=True).start()
receive_button.config(state=tk.DISABLED)
# 設計界面
root = tk.Tk()
root.title("UDP Multicast File Transfer")
file_label = tk.Label(root, text="尚未選擇檔案")
file_label.pack(pady=10)
file_button = tk.Button(root, text="選擇檔案", command=choose_file)
file_button.pack(pady=5)
send_button = tk.Button(root, text="傳送檔案", command=start_sending, state=tk.DISABLED)
send_button.pack(pady=5)
receive_button = tk.Button(root, text="接收檔案", command=start_receiving)
receive_button.pack(pady=5)
root.mainloop()
執行程式:將上述程式碼保存為 file_transfer.py,並在終端中運行:
bash
python3 file_transfer.py
選擇檔案:點擊「選擇檔案」按鈕選擇要傳送的檔案。
開始傳送:選擇檔案後,點擊「傳送檔案」按鈕開始傳送。
開始接收:在另一個終端中運行相同的程式,然後點擊「接收檔案」按鈕以接收傳送的檔案。接收到的檔案將保存為 received_file。
確保在同一個局域網中運行傳送和接收程式。
檔案接收後會顯示通知。
這個範例簡單處理接收的檔案,實際應用中可能需要更完善的檔案管理和錯誤處理邏輯。