20253307张新政《Python程序设计》实验三实验报告
20253307 2025-2026-2 《Python程序设计》实验x报告
课程:《Python程序设计》
班级: 2533
姓名: 张新政
学号:20253307
实验教师:王志强
实验日期:2026年4月27日
必修/选修: 公选课
1.实验内容
创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。
2. 实验过程及结果
此处填写实验的过程及结果
要求1:
(1)创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
服务端代码:
点击查看代码
# -*- coding: utf-8 -*-
# 文件名: SockeServer
# 描 述:
# 作 者: besti
# 日 期: 2026/4/27
# Have you ever seen Los Angeles at 4 a.m?
import socket
def encrypt(msg):
res = ""
for ch in msg:
res += chr(ord(ch) + 3)
return res
def decrypt(msg):
res = ""
for ch in msg:
res += chr(ord(ch) - 3)
return res
#创建TCP Socket对象(我买了一台手机)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#我去办了张电话卡
HOST = "10.65.183.236"
PORT = 4444
server.bind((HOST, PORT))#我把电话卡插到手机上
server.listen(1)
print("服务端已经启动,等待客户端连接......")
conn, addr = server.accept()
print(f"已连接客户端:{addr}")
while True:
#接收密文
cipher = conn.recv(1024).decode("utf-8")
if not cipher or decrypt(cipher) == "exit":
print("聊天结束")
break
#解密
data = decrypt(cipher)
print(f"客户端明文:{data}")
print(f"客户端密文:{cipher}")
#文件保存
with open("chat_log.txt","a",encoding="utf-8") as f:
f.write("客户端明文:"+data+" 密文:"+cipher+"\n")
send_msg = input("我:")
send_cipher = encrypt(send_msg)
print(f"我明文:{send_msg}")
print(f"我密文:{send_cipher}")
with open("chat_log.txt","a",encoding="utf-8") as f:
f.write("服务端明文:"+send_msg+" 密文:"+send_cipher+"\n")
conn.send(send_cipher.encode("utf-8"))
if send_msg == "exit":
break
conn.close()
server.close()
代码功能分析:
1.TCP 服务端通信:绑定 IP 和端口,监听客户端连接,建立稳定的点对点聊天通道
2.简易字符加密:发送消息时字符 ASCII 码 + 3,接收时 - 3 解密(凯撒密码)
3.消息双展示:同时打印 / 保存明文和加密后的密文**
4.聊天记录持久化:所有消息自动追加保存到 chat_log.txt 文件**
5.安全退出:输入 exit 即可断开连接、关闭服务端**
客户端代码:
点击查看代码
import socket
def encrypt(msg):
res = ""
for ch in msg:
res += chr(ord(ch) + 3)
return res
def decrypt(msg):
res = ""
for ch in msg:
res += chr(ord(ch) - 3)
return res
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "10.65.183.236"
PORT = 4444
client.connect((HOST, PORT))
print("已连接服务端!输入exit退出聊天!")
while True:
#发送数据
send_msg = input("我:")
send_cipher = encrypt(send_msg)
print(f"我明文:{send_msg}")
print(f"我密文:{send_cipher}")
with open("chat_log.txt","a",encoding="utf-8") as f:
f.write("客户端明文:"+send_msg+" 密文:"+send_cipher+"\n")
client.send(send_cipher.encode("utf-8"))
if send_msg == "exit":
break
#接收数据
cipher = client.recv(1024).decode("utf-8")
if not cipher or decrypt(cipher) == "exit":
print("聊天结束")
break
data = decrypt(cipher)
print(f"\n服务端明文:{data}")
print(f"服务端密文:{cipher}")
with open("chat_log.txt","a",encoding="utf-8") as f:
f.write("服务端明文:"+data+" 密文:"+cipher+"\n")
client.close()
代码功能分析:
1.主动连接指定 IP 和端口的服务端
2.使用凯撒密码(字符 ASCII±3) 加密 / 解密消息
3.收发消息时同时显示明文 + 密文
4.自动把所有聊天记录保存到 chat_log.txt
5.输入 exit 即可安全退出聊天
(2)要求发送方输入内容,加密后并传输;接收方收到密文并解密和显示。要求:发方和收方同时输出明文和明文
20253307张新政与队友(20253332向家沣)的通信:
我作为服务端,20253332向家沣为客户端:

我作为客户端,20253332向家沣作为服务端:

(3)程序代码托管到码云。
markdown链接:SeverClent

(4)添加文件操作,有加分。
本程序通过添加文件操作实现了聊天记录持久化存储功能:
1.使用 Python 文件操作函数 open() 以追加模式 a 保存聊天记录。
2.每次收发消息都会将明文和密文写入 chat_log.txt。
3.文件编码使用 UTF-8,保证中文正常显示。
4.程序关闭后聊天记录不会丢失,实现日志持久化。


要求2:使用LLM生成一个带图形界面的程序
服务端代码:
点击查看代码
import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, ttk
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import datetime
# ===================== 加密配置(必须和服务端一致)=====================
KEY = b'1234567890123456'
IV = b'abcdefghijklmnop'
def aes_encrypt(text):
cipher = AES.new(KEY, AES.MODE_CBC, IV)
encrypted = cipher.encrypt(pad(text.encode('utf-8'), AES.block_size))
return base64.b64encode(encrypted).decode('utf-8')
def aes_decrypt(text):
try:
cipher = AES.new(KEY, AES.MODE_CBC, IV)
decrypted = unpad(cipher.decrypt(base64.b64decode(text)), AES.block_size)
return decrypted.decode('utf-8')
except:
return "解密失败"
# ===================== 客户端类 =====================
class ClientGUI:
def __init__(self, root):
self.root = root
self.root.title("TCP 加密客户端")
self.root.geometry("650x550")
tk.Label(root, text="服务端IP:").place(x=20, y=20)
self.ip_entry = tk.Entry(root)
self.ip_entry.place(x=100, y=20)
self.ip_entry.insert(0, "127.0.0.1")
tk.Label(root, text="端口:").place(x=280, y=20)
self.port_entry = tk.Entry(root, width=10)
self.port_entry.place(x=320, y=20)
self.port_entry.insert(0, "8888")
self.connect_btn = ttk.Button(root, text="连接服务端", command=self.connect_server)
self.connect_btn.place(x=420, y=18)
# 消息区
tk.Label(root, text="通信日志:").place(x=20, y=60)
self.text_area = scrolledtext.ScrolledText(root, width=75, height=25)
self.text_area.place(x=20, y=90)
# 发送
tk.Label(root, text="发送消息:").place(x=20, y=480)
self.msg_entry = tk.Entry(root, width=50)
self.msg_entry.place(x=100, y=480)
self.send_btn = ttk.Button(root, text="发送", command=self.send_msg)
self.send_btn.place(x=520, y=478)
self.client_socket = None
def log(self, msg):
now = datetime.datetime.now().strftime("%H:%M:%S")
self.text_area.insert(tk.END, f"[{now}] {msg}\n")
self.text_area.see(tk.END)
# 保存日志(加分项)
with open("client_log.txt", "a", encoding="utf-8") as f:
f.write(f"[{now}] {msg}\n")
def connect_server(self):
ip = self.ip_entry.get()
port = int(self.port_entry.get())
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.client_socket.connect((ip, port))
self.log(f"成功连接到服务端 {ip}:{port}")
threading.Thread(target=self.recv_msg, daemon=True).start()
except Exception as e:
self.log(f"连接失败:{e}")
def recv_msg(self):
while True:
try:
data = self.client_socket.recv(1024).decode('utf-8')
if not data: break
decrypt_msg = aes_decrypt(data)
self.log(f"【收到】密文:{data}")
self.log(f"【收到】明文:{decrypt_msg}\n")
except:
self.log("服务端断开连接\n")
break
def send_msg(self):
msg = self.msg_entry.get().strip()
if not msg or not self.client_socket:
return
encrypt_msg = aes_encrypt(msg)
self.client_socket.send(encrypt_msg.encode('utf-8'))
self.log(f"【发送】明文:{msg}")
self.log(f"【发送】密文:{encrypt_msg}\n")
self.msg_entry.delete(0, tk.END)
if __name__ == "__main__":
root = tk.Tk()
app = ClientGUI(root)
root.mainloop()
客户端代码:
点击查看代码
import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, ttk
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import datetime
# ===================== 加密配置(必须和客户端一致)=====================
KEY = b'1234567890123456' # 16位密钥
IV = b'abcdefghijklmnop' # 16位偏移量
def aes_encrypt(text):
cipher = AES.new(KEY, AES.MODE_CBC, IV)
encrypted = cipher.encrypt(pad(text.encode('utf-8'), AES.block_size))
return base64.b64encode(encrypted).decode('utf-8')
def aes_decrypt(text):
try:
cipher = AES.new(KEY, AES.MODE_CBC, IV)
decrypted = unpad(cipher.decrypt(base64.b64decode(text)), AES.block_size)
return decrypted.decode('utf-8')
except:
return "解密失败"
# ===================== 服务端类 =====================
class ServerGUI:
def __init__(self, root):
self.root = root
self.root.title("TCP 加密服务端(多客户端)")
self.root.geometry("650x550")
# 界面组件
tk.Label(root, text="监听端口:").place(x=20, y=20)
self.port_entry = tk.Entry(root)
self.port_entry.place(x=100, y=20)
self.port_entry.insert(0, "8888")
self.start_btn = ttk.Button(root, text="启动服务端", command=self.start_server)
self.start_btn.place(x=250, y=18)
# 消息显示区
tk.Label(root, text="通信日志:").place(x=20, y=60)
self.text_area = scrolledtext.ScrolledText(root, width=75, height=25)
self.text_area.place(x=20, y=90)
# 发送消息
tk.Label(root, text="发送消息:").place(x=20, y=480)
self.msg_entry = tk.Entry(root, width=50)
self.msg_entry.place(x=100, y=480)
self.send_btn = ttk.Button(root, text="发送", command=self.send_msg)
self.send_btn.place(x=520, y=478)
self.server_socket = None
self.client_socket = None
self.client_addr = None
# 日志输出
def log(self, msg):
now = datetime.datetime.now().strftime("%H:%M:%S")
self.text_area.insert(tk.END, f"[{now}] {msg}\n")
self.text_area.see(tk.END)
# 保存到日志文件(加分项)
with open("server_log.txt", "a", encoding="utf-8") as f:
f.write(f"[{now}] {msg}\n")
def start_server(self):
port = int(self.port_entry.get())
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(("0.0.0.0", port))
self.server_socket.listen(5)
self.log(f"服务端已启动,监听端口 {port},等待客户端连接...")
# 多线程处理连接
threading.Thread(target=self.accept_client, daemon=True).start()
def accept_client(self
while True:
self.client_socket, self.client_addr = self.server_socket.accept()
self.log(f"客户端 {self.client_addr} 已连接!")
threading.Thread(target=self.recv_msg, daemon=True).start()
def recv_msg(self):
while True:
try:
data = self.client_socket.recv(1024).decode('utf-8')
if not data: break
decrypt_msg = aes_decrypt(data)
self.log(f"【收到】密文:{data}")
self.log(f"【收到】明文:{decrypt_msg}\n")
except:
self.log("客户端断开连接\n")
break
def send_msg(self):
msg = self.msg_entry.get().strip()
if not msg or not self.client_socket:
return
encrypt_msg = aes_encrypt(msg)
self.client_socket.send(encrypt_msg.encode('utf-8'))
self.log(f"【发送】明文:{msg}")
self.log(f"【发送】密文:{encrypt_msg}\n")
self.msg_entry.delete(0, tk.END)
if __name__ == "__main__":
root = tk.Tk()
app = ServerGUI(root)
root.mainloop()
(1)分析关键代码的功能和使用方法
服务端:
-
XOR+Base64加密:实现消息异或加密与Base64编解码,传输密文,自动加解密并展示明文、密文。
-
TCP多线程服务:独立线程监听连接,每接入一个客户端开启接收子线程,支持多客户端同时在线。
-
GUI图形界面:基于tkinter实现端口配置、启停服务、在线客户端列表、聊天记录查看和点对点单发消息。
-
线程安全与异常处理:通过after机制异步刷新界面,客户端掉线、发送异常自动清理连接资源,程序稳定运行。
客户端:
-
XOR+Base64加密:与服务端共用加密算法,自动加解密,日志显示明文与密文。
-
TCP客户端连接:可配置IP和端口,支持连接、断开服务端。
-
后台接收线程:独立线程接收消息,不卡顿GUI,自动解密显示。
-
GUI界面操作:可视化聊天窗口,线程安全刷新日志,异常自动重连。
使用方法:
首先在服务端界面生成密钥并复制,随后启动服务端监听端口,再到客户端界面粘贴密钥,填写服务端IP与端口后点击连接建立通信;客户端输入文字点击发送,服务端日志可同
步展示传输密文与解密明文,切换回服务端输入消息并点击广播发送,所有在线客户端均可接收密文并自动解密显示明文内容。
(2)分析生成程序的优点
-
通信安全可控:采用XOR对称加密+Base64编码,传输全程无明文泄露;密钥独立生成、手动分发,避免非法接入,保障数据传输保密性。
-
图形化界面易操作:基于GUI设计,服务端/客户端分标签页布局,密钥生成复制、IP端口配置、消息收发均为按钮化操作,无需命令行,上手零门槛。
-
多线程并发稳定:服务端采用多线程架构,可同时接入多个客户端,收发异步不阻塞;异常断开自动清理资源,运行稳定、兼容性强。
-
功能全面且可追溯:支持客户端单发、服务端广播双向通信,服务端日志同步显示密文与明文,消息可查、问题可追溯。
(3)给出运行过程和结果截图
1.我作为服务端,20253332向家沣作为客户端:

2.我作为客户端,20253332向家沣作为服务端:

(4)程序代码托管到码云。
markdown链接:abc

3. 实验过程中遇到的问题和解决过程
-
问题1:两个人无法通信。
-
问题1解决方案:两个人需要连接同一个热点,要输入对方已经修改好的IP地址,一定要先开服务端,再开客户端。
-
问题2:我们两个人用ios系统和鸿蒙系统,怎么操作都不行。
-
问题2解决方案:换成安卓系统就可以了。
-
问题3:不知道怎么修改IP地址.
-
问题3解决方案:首先打开控制面板,选择网络和Internet,然后点击更改适配器设置,右键WLAN,选择属性,然后双击Internet协议版本4,选择“使用下面的IP地址”,进行更改
4.其他(感悟、思考等)
通过这次实验,我学到了如何从电脑中查询自己的IP地址以及如何修改IP地址,但同时我也意识到ios系统和鸿蒙系统的局限性,因为我和同伴手机系统的问题导致一直失败,因
此我知道了实验不只有代码,其他的细节也很重要。加密传输让我认识到网络安全的重要性,今后我会更加努力,提升实践能力。

浙公网安备 33010602011771号