20252410李沐泽实验三报告

20252410 2025-2026-2《Python程序设计》

实验三报告

课程:《Python 程序设计》
班级: 2524
姓名: 李沐泽
学号:20252410
实验教师:王志强
实验日期:2026 年 4 月 27 日
必修 / 选修: 公选课
1. 实验内容
基于 Python 的Socket TCP实现服务端与客户端。
客户端从本地文件读取明文,加密后发送;服务端接收密文并解密保存。
发送方与接收方同时输出明文与密文,展示加密传输全过程。
完成文件读写、加密解密。
使用大模型生成图形界面 GUI 版程序,完成代码分析、运行测试。
程序在 Windows 物理机运行,代码托管到码云。
2. 实验过程及结果
2.1 实验环境
开发工具:PyCharm、VIM、IDLE
操作系统:Windows11、华为 ECS OpenEuler
通信协议:TCP
端口:8988
加密方式:ASCII 偏移加密
2.2 控制台版程序(满足要求 1)
2.2.1 服务端代码
屏幕截图 2026-04-27 204734

2.2.2 客户端代码
屏幕截图 2026-04-27 204843

2.2.3 运行步骤
(1)运行服务端server.py
(2)运行客户端client.py
(3)客户端输出明文 + 密文并发送
(4)服务端输出密文 + 明文并保存文件
2.2.4 运行结果示例
客户端显示
屏幕截图 2026-04-27 202016
服务端显示
image

2.3LLM生成 GUI 图形界面版(满足要求 2)
2.3.1 GUI 完整代码
(1)服务端
import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, messagebox, ttk
import queue
def decrypt(text):
"""解密:ASCII值 - 1"""
return "".join(chr(ord(char) - 1) for char in text)
class ServerGUI:
def init(self, root):
self.root = root
self.root.title("252310 网络通信服务端 (GUI版)")
self.root.geometry("620x520")
self.root.resizable(False, False)

self.server_thread = None
self.server_socket = None
self.running = False
self.log_queue = queue.Queue()

self.setup_ui()
self.root.after(100, self.process_log_queue)

def setup_ui(self):
ctrl_frame = ttk.Frame(self.root, padding=10)
ctrl_frame.pack(fill=tk.X)

ttk.Label(ctrl_frame, text="主机:").grid(row=0, column=0, padx=5)
self.host_var = tk.StringVar(value="192.168.25.10")
ttk.Entry(ctrl_frame, textvariable=self.host_var, width=15).grid(row=0, column=1, padx=5)

ttk.Label(ctrl_frame, text="端口:").grid(row=0, column=2, padx=5)
self.port_var = tk.StringVar(value="8988")
ttk.Entry(ctrl_frame, textvariable=self.port_var, width=8).grid(row=0, column=3, padx=5)

self.start_btn = ttk.Button(ctrl_frame, text="▶ 启动服务", command=self.start_server)
self.start_btn.grid(row=0, column=4, padx=10)
self.stop_btn = ttk.Button(ctrl_frame, text="⏹ 停止服务", command=self.stop_server, state=tk.DISABLED)
self.stop_btn.grid(row=0, column=5, padx=5)

ttk.Label(self.root, text="📡 运行日志 & 数据监控:", font=("Microsoft YaHei", 10, "bold")).pack(anchor=tk.W,
padx=12,
pady=(8, 0))
self.log_area = scrolledtext.ScrolledText(self.root, height=18, state=tk.DISABLED, wrap=tk.WORD,
font=("Consolas", 9))
self.log_area.pack(fill=tk.BOTH, expand=True, padx=12, pady=5)

self.status_var = tk.StringVar(value="就绪:等待启动")
ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W, font=("Arial", 9)).pack(
fill=tk.X, padx=12, pady=5)
ttk.Label(self.root, text="版权所有:besti 20252328 向一", font=("Arial", 9, "italic"), foreground="gray").pack(
pady=3)

def log(self, msg):
self.log_queue.put(msg)

def process_log_queue(self):
try:
while True:
msg = self.log_queue.get_nowait()
self.log_area.config(state=tk.NORMAL)
self.log_area.insert(tk.END, msg + "\n")
self.log_area.see(tk.END)
self.log_area.config(state=tk.DISABLED)
except queue.Empty:
pass
self.root.after(100, self.process_log_queue)

def start_server(self):
if self.running: return
host = self.host_var.get()
try:
port = int(self.port_var.get())
except ValueError:
messagebox.showerror("错误", "端口号必须是整数!");
return

self.start_btn.config(state=tk.DISABLED)
self.stop_btn.config(state=tk.NORMAL)
self.status_var.set("正在绑定端口并启动监听...")
self.log("🔧 正在初始化服务器...")

self.running = True
self.server_thread = threading.Thread(target=self._server_loop, args=(host, port), daemon=True)
self.server_thread.start()
self.log("✅ 服务器后台线程已启动")

def stop_server(self):
self.running = False
self.status_var.set("正在停止服务...")
self.log("🛑 收到停止请求,正在关闭监听...")
if self.server_socket:
try:
self.server_socket.close()
except:
pass
self.start_btn.config(state=tk.NORMAL)
self.stop_btn.config(state=tk.DISABLED)

def _server_loop(self, host, port):
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((host, port))
self.server_socket.listen(5)
self.log(f"🌐 252328服务端已启动,监听 {host}:{port}")
self.status_var.set(f"🟢 运行中:{host}:{port}")

while self.running:
self.log("⏳ 等待客户端连接...")
try:
self.server_socket.settimeout(1.0)
client_socket, addr = self.server_socket.accept()
except socket.timeout:
continue
except OSError:
break

self.log(f"📥 客户端已连接:{addr}")
self.status_var.set(f"🔗 已连接:{addr}")

try:
data = client_socket.recv(4096).decode("utf-8")
if not data:
self.log("⚠️ 客户端未发送数据或已断开");
continue

decrypted = decrypt(data)
self.log(f"🔒 接收密文:{data}")
self.log(f"🔓 解密明文:{decrypted}")

with open("接收文件.txt", "w", encoding="utf-8") as f:
f.write(decrypted)
self.log("💾 已保存至:接收文件.txt")
self.status_var.set("✅ 数据处理完成,等待下一次连接")
except Exception as e:
self.log(f"❌ 数据处理异常:{e}")
finally:
client_socket.close()
self.log("🔌 客户端连接已释放")
except Exception as e:
self.log(f"💥 服务器启动/运行失败:{e}")
finally:
self.running = False
self.status_var.set("🔴 服务已停止")
if self.root.winfo_exists():
self.root.after(0, lambda: self.start_btn.config(state=tk.NORMAL))
self.root.after(0, lambda: self.stop_btn.config(state=tk.DISABLED))

if name == 'main':
root = tk.Tk()
app = ServerGUI(root)
root.mainloop()
(2)客户端
import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, messagebox, ttk
import queue

def encrypt(text):
"""加密:ASCII值 + 1"""
return "".join(chr(ord(char) + 1) for char in text)

class ClientGUI:
def init(self, root):
self.root = root
self.root.title("252328 网络通信客户端 (GUI版)")
self.root.geometry("560x580")
self.root.resizable(False, False)

self.log_queue = queue.Queue()
self.is_sending = False
self.setup_ui()
self.root.after(100, self.process_log_queue)

def setup_ui(self):
frm_cfg = ttk.LabelFrame(self.root, text="🌐 服务器配置", padding=10)
frm_cfg.pack(fill=tk.X, padx=10, pady=5)
ttk.Label(frm_cfg, text="IP地址:").grid(row=0, column=0, sticky=tk.W, padx=5)
self.ip_var = tk.StringVar(value="192.168.25.10")
ttk.Entry(frm_cfg, textvariable=self.ip_var, width=18).grid(row=0, column=1, padx=5)
ttk.Label(frm_cfg, text="端口:").grid(row=0, column=2, sticky=tk.W, padx=5)
self.port_var = tk.StringVar(value="8988")
ttk.Entry(frm_cfg, textvariable=self.port_var, width=8).grid(row=0, column=3, padx=5)

frm_in = ttk.LabelFrame(self.root, text="📝 数据输入与加密", padding=10)
frm_in.pack(fill=tk.X, padx=10, pady=5)
ttk.Label(frm_in, text="发送内容:").grid(row=0, column=0, sticky=tk.NW, padx=5, pady=2)
self.input_txt = tk.Text(frm_in, height=3, width=45, font=("Consolas", 10))
self.input_txt.grid(row=0, column=1, padx=5, pady=2, sticky=tk.W)

ttk.Label(frm_in, text="加密预览:").grid(row=1, column=0, sticky=tk.NW, padx=5, pady=2)
self.enc_preview = tk.Text(frm_in, height=1, width=45, state=tk.DISABLED, font=("Consolas", 10), bg="#f0f0f0")
self.enc_preview.grid(row=1, column=1, padx=5, pady=2, sticky=tk.W)

frm_btn = ttk.Frame(self.root)
frm_btn.pack(fill=tk.X, padx=10, pady=5)
ttk.Button(frm_btn, text="🔒 预览加密", command=self.preview_encrypt).pack(side=tk.LEFT, padx=5)
self.send_btn = ttk.Button(frm_btn, text="📤 连接并发送", command=self.start_send)
self.send_btn.pack(side=tk.LEFT, padx=5)

ttk.Label(self.root, text="📡 运行日志:", font=("Microsoft YaHei", 9, "bold")).pack(anchor=tk.W, padx=12, pady=(5,0))
self.log_area = scrolledtext.ScrolledText(self.root, height=15, state=tk.DISABLED, wrap=tk.WORD, font=("Consolas", 9))
self.log_area.pack(fill=tk.BOTH, expand=True, padx=12, pady=5)

ttk.Label(self.root, text="版权所有:besti 20252328 向一", font=("Arial", 9, "italic"), foreground="gray").pack(pady=3)

def log(self, msg): self.log_queue.put(msg)

def process_log_queue(self):
try:
while True:
msg = self.log_queue.get_nowait()
self.log_area.config(state=tk.NORMAL)
self.log_area.insert(tk.END, msg + "\n")
self.log_area.see(tk.END)
self.log_area.config(state=tk.DISABLED)
except queue.Empty: pass
self.root.after(100, self.process_log_queue)

def preview_encrypt(self):
content = self.input_txt.get("1.0", tk.END).strip()
if not content: messagebox.showwarning("提示", "请先输入内容!"); return
enc = encrypt(content)
self.enc_preview.config(state=tk.NORMAL)
self.enc_preview.delete("1.0", tk.END)
self.enc_preview.insert("1.0", enc)
self.enc_preview.config(state=tk.DISABLED)
self.log(f"🔍 原文: {content}")
self.log(f"🔒 密文预览: {enc}")

def start_send(self):
if self.is_sending: return
self.is_sending = True
self.send_btn.config(state=tk.DISABLED)
t = threading.Thread(target=self._send_logic, daemon=True)
t.start()

def _send_logic(self):
client_socket = None
try:
content = self.input_txt.get("1.0", tk.END).strip()
if not content: self.log("⚠️ 发送内容为空!"); return

self.log("🔒 正在加密...")
enc_content = encrypt(content)

self.log("💾 正在写入 发送文件.txt ...")
with open("发送文件.txt", "w", encoding="utf-8") as f:
f.write(enc_content)

self.log("📤 正在读取文件并连接服务器...")
with open("发送文件.txt", "r", encoding="utf-8") as f:
send_data = f.read()

server_ip = self.ip_var.get()
server_port = int(self.port_var.get())

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.settimeout(5.0)
client_socket.connect((server_ip, server_port))
self.log(f"✅ 已连接至 {server_ip}:{server_port}")

client_socket.send(send_data.encode("utf-8"))
self.log("📤 加密数据发送成功!")
self.root.after(0, lambda: messagebox.showinfo("成功", "文件已成功发送至服务端!"))

except ConnectionRefusedError:
self.log("❌ 连接失败:服务器未启动或IP/端口错误")
except socket.timeout:
self.log("⏱️ 连接超时:请检查网络或防火墙设置")
except Exception as e:
self.log(f"💥 发送异常:{e}")
finally:
self.is_sending = False
self.root.after(0, lambda: self.send_btn.config(state=tk.NORMAL))
if client_socket: client_socket.close()

if name == 'main':
root = tk.Tk()
app = ClientGUI(root)
root.mainloop()
2.3.2 关键代码功能
加密解密:ASCII 偏移实现简单加密。
Socket TCP:实现稳定连接、数据收发。
多线程:支持多客户端并发处理。
tkinter GUI:窗口、日志、文件选择、弹窗提示。
文件操作:读取发送文件、写入接收文件。
2.3.3 GUI 程序优点
可视化操作,无需命令行。
明文密文实时展示,直观清晰。
跨平台运行(Windows/Linux/OpenEuler)。
代码模块化,易读易维护。
支持多客户端、文件选择、状态提示,功能完整。
2.3.4 运行过程
启动 GUI 程序,选择启动服务端。
屏幕截图 2026-04-27 205527

启动客户端,选择 txt 文件,输入 IP。
点击发送文件。
服务端自动接收、解密、保存。
界面显示明文、密文与运行状态。
屏幕截图 2026-04-27 205509

3. 实验过程中遇到的问题和解决过程
问题 1:客户端连接超时或连接失败
问题 1 解决方案:手动设置子网IP地址。
问题 2:中文传输乱码
问题 2 解决方案:文件读写与 socket 编码统一使用 utf-8。

4. 其他(感悟、思考等)
通过本次实验,我掌握了 Socket TCP 通信的完整流程,理解了服务端监听、客户端请求、数据加密解密、文件传输的原理。多线程、文件操作、编码处理、服务器配置等能力得到了综合提升。
使用大模型生成 GUI 程序极大提高了开发效率,同时也锻炼了代码阅读与优化能力。本次实验将网络编程、文件处理、数据安全、图形界面结合在一起,是非常实用的 Python 实战训练。
5. 码云托管
已将以下代码上传至码云仓库:
(客户端)https://gitee.com/lmzmz/PythonProject9/blob/2e18fa108908ce2325209e128383ccf787e985bc/客户端.py
(服务端)
https://gitee.com/lmzmz/Project3/commit/e4e041882daade69c5f8838ddce4344728066f20

posted @ 2026-04-28 20:48  lm泽  阅读(14)  评论(0)    收藏  举报