20252436实验三《Python程序设计》实验报告

课程:《Python程序设计》
班级: 20252436
姓名: 赵明山
学号:20252436
实验教师:王志强
实验日期:2026年5月9日
必修/选修: 公选课

1.实验内容

本次实验基于Python Socket套接字,分别实现TCP服务端与客户端控制台通信程序LLM生成带图形界面GUI通信程序两大模块,具体内容如下:

  1. 搭建TCP服务端,固定端口监听客户端连接,实现本机与队友跨主机互相通信,每人分别充当一次服务端、一次客户端。
  2. 实现消息自定义加密传输,发送方输入明文、加密后发送;接收方接收密文、解密还原明文,通信双方控制台同时输出明文+密文
  3. 增加文件日志操作加分项,自动记录所有聊天通信记录到本地文件。
  4. 利用LLM生成基于tkinter的图形界面聊天程序,分析关键代码功能、程序优缺点,完成运行测试并截图留存。
  5. 分别在Windows物理机、华为ECS OpenOuler服务器上,使用PyCharm、IDLE、VIM等工具完成代码编写、调试与运行,所有代码上传托管至码云平台。

2. 实验过程及结果

2.1 基础控制台TCP加密通信(普通版本)

2.1.1 加密解密公共函数

采用异或对称加密,收发双方共用同一密钥,实现文本加密与解密:

# 异或对称加密解密函数
def encrypt_decrypt(text, key=0x1F):
    return ''.join([chr(ord(c) ^ key) for c in text])

2.1.2 服务端完整代码 SocketServer.py

import socket

# 加密解密函数
def encrypt_decrypt(text, key=0x1F):
    return ''.join([chr(ord(c) ^ key) for c in text])

# 加分项:文件日志记录
def log_message(sender, msg):
    with open("chat_log.txt", "a", encoding="utf-8") as f:
        f.write(f"{sender}: {msg}\n")

# 配置
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 端口复用,防止占用报错
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
HOST = "10.174.210.27"
PORT = 4444

try:
    server.bind((HOST, PORT))
    server.listen(1)
    print("服务端已启动,等待客户端连接......")
    conn, addr = server.accept()
    print(f"成功连接客户端:{addr}")
    log_message("系统", f"客户端 {addr} 已接入通信")

    while True:
        # 接收客户端密文
        data = conn.recv(1024).decode("utf-8")
        if not data or data == encrypt_decrypt("exit"):
            print("通信结束,连接断开")
            log_message("系统", "双方退出通信")
            break
        # 解密得到明文
        plain_text = encrypt_decrypt(data)
        print(f"\n【接收】密文:{data}")
        print(f"【接收】明文:{plain_text}")
        log_message("客户端", plain_text)

        # 服务端输入回复
        send_text = input("请输入回复消息:")
        log_message("服务端", send_text)
        if send_text.lower() == "exit":
            conn.send(encrypt_decrypt("exit").encode("utf-8"))
            break
        # 加密发送
        cipher_text = encrypt_decrypt(send_text)
        print(f"【发送】明文:{send_text}")
        print(f"【发送】密文:{cipher_text}")
        conn.send(cipher_text.encode("utf-8"))

except Exception as e:
    print(f"服务端异常:{e}")
finally:
    conn.close()
    server.close()
    print("服务端已关闭")

2.1.3 客户端完整代码 SocketClient.py

import socket

# 加密解密函数
def encrypt_decrypt(text, key=0x1F):
    return ''.join([chr(ord(c) ^ key) for c in text])

# 加分项:文件日志记录
def log_message(sender, msg):
    with open("chat_log.txt", "a", encoding="utf-8") as f:
        f.write(f"{sender}: {msg}\n")

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 填写服务端实际IP和端口
HOST = "10.174.210.36"
PORT = 4444

try:
    client.connect((HOST, PORT))
    print("已成功连接服务端,输入exit可退出")

    while True:
        # 客户端输入消息
        send_text = input("请输入发送消息:")
        log_message("客户端", send_text)
        if send_text.lower() == "exit":
            client.send(encrypt_decrypt("exit").encode("utf-8"))
            break
        # 加密并发送
        cipher_text = encrypt_decrypt(send_text)
        print(f"【发送】明文:{send_text}")
        print(f"【发送】密文:{cipher_text}")
        client.send(cipher_text.encode("utf-8"))

        # 接收服务端回复
        data = client.recv(1024).decode("utf-8")
        if not data or data == encrypt_decrypt("exit"):
            print("通信结束")
            break
        plain_text = encrypt_decrypt(data)
        print(f"\n【接收】密文:{data}")
        print(f"【接收】明文:{plain_text}")
        log_message("服务端", plain_text)

except ConnectionRefusedError:
    print("连接失败:请先启动服务端,核对IP和端口")
except Exception as e:
    print(f"客户端异常:{e}")
finally:
    client.close()
    print("客户端已关闭")

IPV4更改image

2.1.4 普通版本程序运行结果截图

20252436赵明山,20252427李昌鸿

image

image

运行说明:

  1. 先运行SocketServer.py启动服务端,监听4444端口;
  2. 再运行SocketClient.py客户端,输入服务端IP完成连接;
  3. 双方互相输入文字,控制台同时打印明文和加密后的密文
  4. 程序自动生成chat_log.txt日志文件,记录全部聊天内容;
  5. 与队友互换服务端、客户端身份,完成跨主机互相通信,功能正常。

2.2 LLM生成带图形界面GUI通信程序

2.2.1 GUI客户端完整代码 ChatGUI.py

import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, Entry, Button, END

# 加密解密函数
def encrypt_decrypt(text, key=0x1F):
    return ''.join([chr(ord(c) ^ key) for c in text])

class ChatGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("TCP加密聊天客户端(LLM生成GUI版)")
        self.host = tk.StringVar(value="10.174.210.27")
        self.port = tk.IntVar(value=4444)
        self.client_socket = None
        self.is_connect = False
        self.setup_ui()

    def setup_ui(self):
        # 连接配置区域
        frame1 = tk.Frame(self.root)
        frame1.pack(pady=5)
        tk.Label(frame1,text="IP:").pack(side=tk.LEFT)
        tk.Entry(frame1,textvariable=self.host,width=15).pack(side=tk.LEFT,padx=5)
        tk.Label(frame1,text="端口:").pack(side=tk.LEFT)
        tk.Entry(frame1,textvariable=self.port,width=6).pack(side=tk.LEFT,padx=5)
        Button(frame1,text="连接",command=self.connect).pack(side=tk.LEFT,padx=5)

        # 聊天显示区域
        self.chat_text = scrolledtext.ScrolledText(self.root,width=70,height=20,state=tk.DISABLED)
        self.chat_text.pack(pady=10,padx=10)

        # 消息输入区域
        frame2 = tk.Frame(self.root)
        frame2.pack(fill=tk.X,padx=10)
        self.msg_entry = Entry(frame2,width=60)
        self.msg_entry.pack(side=tk.LEFT,fill=tk.X,expand=True)
        self.msg_entry.bind("<Return>",self.send_msg)
        Button(frame2,text="发送",command=self.send_msg).pack(side=tk.LEFT,padx=5)

    def connect(self):
        try:
            self.client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            self.client_socket.connect((self.host.get(),self.port.get()))
            self.is_connect = True
            self.add_log("系统","已成功连接服务端!")
            # 开启子线程接收消息
            threading.Thread(target=self.recv_thread,daemon=True).start()
        except:
            self.add_log("系统","连接失败,请检查服务端和端口!")

    def recv_thread(self):
        while self.is_connect:
            try:
                data = self.client_socket.recv(1024).decode("utf-8")
                if not data or data == encrypt_decrypt("exit"):
                    self.add_log("系统","服务端已断开连接")
                    self.is_connect = False
                    break
                plain = encrypt_decrypt(data)
                self.add_log(f"服务端","明文:{plain}\n密文:{data}")
            except:
                self.add_log("系统","连接异常断开")
                self.is_connect = False
                break

    def send_msg(self,event=None):
        if not self.is_connect:
            return
        msg = self.msg_entry.get().strip()
        if not msg:
            return
        self.msg_entry.delete(0,END)
        if msg.lower() == "exit":
            self.client_socket.send(encrypt_decrypt("exit").encode("utf-8"))
            self.add_log("我","已退出通信")
            self.is_connect = False
            self.client_socket.close()
            return
        cipher = encrypt_decrypt(msg)
        self.client_socket.send(cipher.encode("utf-8"))
        self.add_log("我",f"明文:{msg}\n密文:{cipher}")

    def add_log(self,sender,content):
        self.chat_text.config(state=tk.NORMAL)
        self.chat_text.insert(END,f"【{sender}】{content}\n"+"-"*50+"\n")
        self.chat_text.config(state=tk.DISABLED)
        self.chat_text.yview(END)

if __name__ == "__main__":
    root = tk.Tk()
    app = ChatGUI(root)
    root.mainloop()

服务端仍沿用前面SocketServer.py即可,无需修改。

2.2.2 关键代码功能和使用方法分析

  1. 多线程接收消息
threading.Thread(target=self.recv_thread,daemon=True).start()

功能:GUI主线程负责界面渲染,单独开启子线程循环接收服务端消息;
作用:避免socket.recv()阻塞界面,实现聊天实时收发、界面不卡顿。

  1. ScrolledText滚动文本框
    用于展示聊天记录,设置为只读不可编辑,仅程序自动写入明文和密文,自带滚动条可查看历史记录。

  2. 回车键绑定发送事件

self.msg_entry.bind("<Return>",self.send_msg)

功能:支持输入完消息按回车直接发送,搭配按钮发送,提升操作体验。

  1. 加密解密复用
    和控制台版共用同一异或加密函数,保证前后加密规则一致,兼容普通版服务端。

2.2.3 LLM生成GUI程序的优点

  1. 可视化图形界面,相比黑框控制台更直观美观,无需修改代码即可随时更改IP和端口;
  2. 明文、密文统一展示在聊天窗口,条理清晰,不用翻看控制台滚动信息;
  3. 多线程架构,收发消息互不阻塞,支持实时双向聊天;
  4. 封装性好,代码结构清晰,易扩展添加文件传输、表情包、多用户聊天等功能;
  5. 适配Windows、Linux系统,可在华为ECS服务器和本地物理机上正常运行。

2.2.4 GUI版本程序运行结果截图

20252436赵明山,20252427李昌鸿

image
image

运行说明:

  1. 后台运行原有SocketServer.py服务端;
  2. 运行ChatGUI.py图形客户端,填写IP和端口点击连接;
  3. 在输入框发送消息,窗口自动展示自身发送的明文、密文;
  4. 接收服务端回复后,自动解密并展示对方明文与密文;
  5. 输入exit可正常断开连接,整体通信加密功能完好。

3. 实验过程中遇到的问题和解决过程

  • 问题2:传输中文出现乱码、解密失败

  • 问题2解决方案:所有编码解码统一添加encoding="utf-8",加密解密在字符串层面处理,避免字节流破坏加密规则。

  • 问题3:控制台程序只能发完消息才能接收回复,无法实时聊天

  • 问题3解决方案:改用LLM生成GUI程序,引入多线程,单独子线程负责接收消息,主线程负责界面交互。

  • 问题4:程序异常退出后端口被占用,重启服务端报错

  • 问题4解决方案:添加端口复用设置setsockopt,同时用try-finally保证程序退出时自动关闭套接字。

  • 问题5:GUI界面卡顿、无响应

  • 问题5解决方案:将阻塞的recv接收逻辑放到后台守护线程,不占用tkinter主线程事件循环。

其他(感悟、思考等)

本次实验完成了Python Socket TCP服务端与客户端的控制台通信、LLM图形界面通信两套程序,掌握了网络套接字编程、对称加密传输、多线程并发、tkinter图形界面开发等知识点。

通过搭建服务端监听、客户端连接、加密收发消息,理解了TCP三次握手、字节流传输、编码转换的底层原理。控制台程序简单易用但交互简陋,而LLM生成的GUI程序结构规范、交互友好,体现了大模型在代码开发、界面快速搭建上的优势。

posted @ 2026-05-10 13:16  mountank  阅读(9)  评论(1)    收藏  举报