20252419 2025-2026-2 《Python程序设计》实验3报告
课程:《Python程序设计》
班级: 2523
姓名: 陈冠宇
学号:20252320
实验教师:王志强
实验日期:2026年5月11日
必修/选修: 公选课
1.实验内容
注意事项:
每人必须做一次客户端和一次服务端,且要和队友(标注学号姓名)互相通信。
要求1:
(1)创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
(2)要求发送方输入内容,加密后并传输;接收方收到密文并解密和显示。要求:发方和收方同时输出明文和明文。
(3)程序代码托管到码云。
(4)添加文件操作,有加分。(可选项)
要求2:使用LLM生成一个带图形界面的程序
(1)分析关键代码的功能和使用方法
(2)分析生成程序的优点
(3)给出运行过程和结果截图
(4)程序代码托管到码云。
注:在华为ECS服务器(OpenOuler系统)和物理机(Windows/Linux系统)上使用VIM、PDB、IDLE、Pycharm等工具编程实现。
- 实验过程及结果
1.作为服务端接收消息
代码:`import socket
def decrypt(text):
res = ""
for c in text:
if c.isalpha():
if c.islower():
res += chr((ord(c)-ord('a')-3)%26 + ord('a'))
else:
res += chr((ord(c)-ord('A')-3)%26 + ord('A'))
else:
res += c
return res
HOST = '192.168.31.236'
PORT = 8890
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
print("服务端已启动,等待你连接...")
conn, addr = s.accept()
print(f"已和你建立连接:{addr}")
cipher = conn.recv(1024).decode("utf-8")
plain = decrypt(cipher)
print(f"【服务端-密文】{cipher}")
print(f"【服务端-明文】{plain}")
conn.close()
s.close()结果  2.作为客户端发送消息 代码:import socket
def encrypt(text):
res = ""
for c in text:
if c.isalpha():
if c.islower():
res += chr((ord(c)-ord('a')+3)%26 + ord('a'))
else:
res += chr((ord(c)-ord('A')+3)%26 + ord('A'))
else:
res += c
return res
HOST = '192.168.31.157'
PORT = 8891
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
plain = input("请输入发给同学的消息:")
cipher = encrypt(plain)
print(f"【客户端-明文】{plain}")
print(f"【客户端-密文】{cipher}")
s.send(cipher.encode("utf-8"))
s.close()`
结果:

GUI生成的可视界面代码
`import tkinter as tk
from tkinter import ttk, scrolledtext, filedialog, messagebox
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import os
from datetime import datetime
class EncryptionApp:
def init(self, root):
self.root = root
self.root.title("安全加解密系统 - AES-256-CBC")
self.root.geometry("900x700")
self.root.resizable(True, True)
设置密钥(16/24/32字节对应AES-128/192/256)
self.key = b'0123456789abcdef0123456789abcdef' # 32字节,AES-256
self.create_widgets()
def create_widgets(self):
# 样式配置
style = ttk.Style()
style.theme_use('clam')
主框架
main_frame = ttk.Frame(self.root, padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
发送方区域
sender_frame = ttk.LabelFrame(main_frame, text="发送方(加密端)", padding="10")
sender_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=5)
ttk.Label(sender_frame, text="明文输入:").grid(row=0, column=0, sticky=tk.W)
self.sender_plaintext = scrolledtext.ScrolledText(sender_frame, height=8, width=50)
self.sender_plaintext.grid(row=1, column=0, columnspan=2, pady=5)
发送方按钮
btn_frame1 = ttk.Frame(sender_frame)
btn_frame1.grid(row=2, column=0, columnspan=2, pady=10)
ttk.Button(btn_frame1, text="加密并传输", command=self.encrypt_and_transmit).pack(side=tk.LEFT, padx=5)
ttk.Button(btn_frame1, text="从文件加载明文", command=self.load_plaintext_file).pack(side=tk.LEFT, padx=5)
ttk.Label(sender_frame, text="密文(Base64编码):").grid(row=3, column=0, sticky=tk.W, pady=(10, 0))
self.ciphertext_display = scrolledtext.ScrolledText(sender_frame, height=4, width=50, bg="#f0f0f0")
self.ciphertext_display.grid(row=4, column=0, columnspan=2, pady=5)
发送方输出明文
ttk.Label(sender_frame, text="发送方明文输出:").grid(row=5, column=0, sticky=tk.W, pady=(10, 0))
self.sender_output = scrolledtext.ScrolledText(sender_frame, height=4, width=50, bg="#e8f4e8")
self.sender_output.grid(row=6, column=0, columnspan=2, pady=5)
接收方区域
receiver_frame = ttk.LabelFrame(main_frame, text="接收方(解密端)", padding="10")
receiver_frame.grid(row=0, column=1, sticky=(tk.W, tk.E, tk.N, tk.S), pady=5, padx=(10, 0))
ttk.Label(receiver_frame, text="接收到的密文:").grid(row=0, column=0, sticky=tk.W)
self.receiver_ciphertext = scrolledtext.ScrolledText(receiver_frame, height=8, width=50)
self.receiver_ciphertext.grid(row=1, column=0, columnspan=2, pady=5)
接收方按钮
btn_frame2 = ttk.Frame(receiver_frame)
btn_frame2.grid(row=2, column=0, columnspan=2, pady=10)
ttk.Button(btn_frame2, text="解密并显示", command=self.decrypt_and_display).pack(side=tk.LEFT, padx=5)
ttk.Button(btn_frame2, text="保存解密结果到文件", command=self.save_decrypted_file).pack(side=tk.LEFT, padx=5)
ttk.Label(receiver_frame, text="解密后的明文:").grid(row=3, column=0, sticky=tk.W, pady=(10, 0))
self.receiver_plaintext = scrolledtext.ScrolledText(receiver_frame, height=4, width=50, bg="#e8f4e8")
self.receiver_plaintext.grid(row=4, column=0, columnspan=2, pady=5)
接收方输出明文
ttk.Label(receiver_frame, text="接收方明文输出:").grid(row=5, column=0, sticky=tk.W, pady=(10, 0))
self.receiver_output = scrolledtext.ScrolledText(receiver_frame, height=4, width=50, bg="#e8f4e8")
self.receiver_output.grid(row=6, column=0, columnspan=2, pady=5)
日志区域
log_frame = ttk.LabelFrame(main_frame, text="操作日志", padding="10")
log_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=10)
self.log_text = scrolledtext.ScrolledText(log_frame, height=8, width=100, bg="#fef9e6")
self.log_text.grid(row=0, column=0, sticky=(tk.W, tk.E))
配置网格权重
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
main_frame.columnconfigure(0, weight=1)
main_frame.columnconfigure(1, weight=1)
log_frame.columnconfigure(0, weight=1)
def log(self, message):
"""记录日志"""
timestamp = datetime.now().strftime("%H:%M:%S")
self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
self.log_text.see(tk.END)
def encrypt_data(self, plaintext):
"""AES加密数据"""
try:
# 生成随机IV
iv = os.urandom(16)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
# 填充并加密
padded_data = pad(plaintext.encode('utf-8'), AES.block_size)
ciphertext = cipher.encrypt(padded_data)
# 组合IV和密文,并进行Base64编码
encrypted_data = base64.b64encode(iv + ciphertext).decode('utf-8')
return encrypted_data
except Exception as e:
messagebox.showerror("错误", f"读取文件失败: {str(e)}")
def save_decrypted_file(self):
"""保存解密结果到文件"""
plaintext = self.receiver_plaintext.get("1.0", tk.END).strip()
if not plaintext:
messagebox.showwarning("警告", "没有解密的明文可保存!")
return
filepath = filedialog.asksaveasfilename(
title="保存解密结果",
defaultextension=".txt",
filetypes=[("文本文件", ".txt"), ("所有文件", ".*")]
)
if filepath:
try:
with open(filepath, 'w', encoding='utf-8') as f:
f.write(plaintext)
self.log(f"解密结果已保存到: {os.path.basename(filepath)}")
messagebox.showinfo("成功", "文件保存成功!")
except Exception as e:
messagebox.showerror("错误", f"保存文件失败: {str(e)}")
def main():
root = tk.Tk()
app = EncryptionApp(root)
root.mainloop()
if name == "main":
main()
`
结果:
- 实验过程中遇到的问题和解决过程
问题1:链接服务端时提示超时,发现可能是不在同一局域网或端口不一导致
问题1解决方案:连接到同一局域网后重新启动
问题2:服务端无法启动,发现为没及时更改IP地址
问题2解决方案:在命令提示符中再次查询IPV4地址并修改代码
浙公网安备 33010602011771号