20243429 2025-2026-2 《Python程序设计》实验三报告

课程:《Python程序设计》
班级: 2434
姓名: 付家祺
学号:20243429
实验教师:王志强老师
实验日期:2026年4月27日
必修/选修: 公选课

一.实验内容
创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。
要求1:
(1)创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
(2)要求发送方输入内容,加密后并传输;接收方收到密文并解密和显示(需要发方和收方同时输出明文和明文);
(3)程序代码托管到码云;
(4)添加文件操作。
要求2:
使用LLM生成一个带图形界面的程序
(1)分析关键代码的功能和使用方法;
(2)分析生成程序的优点;
(3)给出运行过程和结果截图;
(4)程序代码托管到码云。

二. 实验过程及结果
实验代码:
服务端的代码如下:

点击查看代码
import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

HOST = "192.168.31.29"
PORT = 4444
server.bind((HOST, PORT))

server.listen(1)
print("服务端已启动,等待客户端连接")

conn, addr = server.accept()
print("已连接客户端:", addr)

f = open("server_chat.txt", "w", encoding="utf-8")

try:
    while True:
        cipher = conn.recv(1024).decode("utf-8")
        if not cipher:
            print("聊天结束")
            break

        plain = ''.join([chr(ord(c) - 8) for c in cipher])

        if plain == "exit":
            print("聊天结束")
            break

        print("\n【收到】密文:" + cipher)
        print("【解密】明文:" + plain)

        f.write("【收到】密文:" + cipher + "\n")
        f.write("【解密】明文:" + plain + "\n")

        send_plain = input("我:")
        send_cipher = ''.join([chr(ord(c) + 8) for c in send_plain])
        conn.send(send_cipher.encode("utf-8"))

        if send_plain == "exit":
            print("聊天结束")
            break

        print("【发送】明文:" + send_plain)
        print("【发送】密文:" + send_cipher + "\n")

        f.write("【发送】明文:" + send_plain + "\n")
        f.write("【发送】密文:" + send_cipher + "\n\n")

finally:
    f.close()
    conn.close()
    server.close()
    print("进程已结束,退出代码为 0")
其中服务端的IP末尾改为.29(服务端由20243429的同学提供)

服务端代码分析
创建 TCP socket,绑定到 192.168.31.29:4444 并开始监听。
等待客户端连接,连接成功后获取客户端连接对象与地址。
打开 server_chat.txt 文件用于记录聊天日志。
进入循环:接收客户端发来的密文,若为空则结束聊天。
对密文进行解密(每个字符 ASCII 码减 8)。
若解密后明文为 exit,结束聊天。打印收到的密文与解密后的明文,并写入文件。用户输入回复消息(明文)。
加密后发送给客户端,同时打印明文和密文并记录到文件。
若发送 exit,跳出循环关闭连接。
循环结束后关闭文件、客户端连接与服务端 socket。

客户端的代码如下:

点击查看代码
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

HOST = "192.168.31.10"
PORT = 4444

client.connect((HOST, PORT))
print("已连接服务端!输入exit退出聊天!")

f = open("client_chat.txt", "w", encoding="utf-8")

try:
    while True:
        send_plain = input("我:")
        send_cipher = ''.join([chr(ord(c) + 8) for c in send_plain])
        client.send(send_cipher.encode("utf-8"))

        if send_plain == "exit":
            print("聊天结束")
            break

        print("【发送】明文:" + send_plain)
        print("【发送】密文:" + send_cipher + "\n")

        f.write("【发送】明文:" + send_plain + "\n")
        f.write("【发送】密文:" + send_cipher + "\n\n")

        cipher = client.recv(1024).decode("utf-8")
        if not cipher:
            print("聊天结束")
            break

        plain = ''.join([chr(ord(c) - 8) for c in cipher])

        if plain == "exit":
            print("聊天结束")
            break

        print("【收到】密文:" + cipher)
        print("【解密】明文:" + plain + "\n")

        f.write("【收到】密文:" + cipher + "\n")
        f.write("【解密】明文:" + plain + "\n\n")

finally:
    f.close()
    client.close()
    print("进程已结束,退出代码为 0")
其中客户端的IP末尾改为.10(服务端由20243410的同学提供)

客户端代码分析:
创建 TCP socket,连接到 192.168.31.10:4444。
连接成功后,打开 client_chat.txt 文件记录聊天日志。
进入循环:用户输入消息(明文)。加密后发送给服务端,同时打印明文和密文并写入文件。
若发送 exit,跳出循环关闭连接。
否则,接收服务端回复的密文,若为空则结束聊天。
对密文解密,若明文为 exit 则结束聊天。
打印收到的密文与解密后的明文,并写入文件。
循环结束后关闭文件与客户端 socket。

实验结果如下:
启动服务端时,密文(采用凯撒密码,利用ASCII+8)和明文一同显示:
6bdbc7ebe43842411a8604f396e1c319

启动客户端时,密文(采用凯撒密码,利用ASCII+8)和明文一同显示:
b2d8f7d38d39f8d26e148306fa1888df

将服务端与客户端的传输记录添加至文件中:
b629496049566ccd51a365e83f6aa61a
613c8203b775a3ebe4f8e90fe80c89e1

利用LLM生成一个带图形界面的程序:
服务端代码如下:

点击查看代码
import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, messagebox

# 加密解密函数
def encrypt(text):
    return ''.join([chr(ord(c) + 8) for c in text])

def decrypt(text):
    return ''.join([chr(ord(c) - 8) for c in text])

class ServerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("TCP 加密聊天 - 服务端")
        self.root.geometry("650x550")

        # IP 和端口
        self.HOST = "172.16.221.47"  # 监听所有网卡
        self.PORT = 4444

        # 组件
        tk.Label(root, text="聊天记录(明文+密文)", font=("微软雅黑", 12)).pack(pady=5)
        self.chat_area = scrolledtext.ScrolledText(root, width=75, height=25, state=tk.DISABLED)
        self.chat_area.pack(pady=5)

        self.entry_msg = tk.Entry(root, width=50, font=("微软雅黑", 12))
        self.entry_msg.pack(pady=5)
        self.entry_msg.bind("<Return>", self.send_msg)

        tk.Button(root, text="发送", command=self.send_msg, width=10).pack()

        # 套接字
        self.server_socket = None
        self.client_conn = None
        self.f = None

        # 启动服务端线程
        threading.Thread(target=self.start_server, daemon=True).start()

    def start_server(self):
        try:
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.bind((self.HOST, self.PORT))
            self.server_socket.listen(5)
            self.show_msg(f"服务端已启动,端口:{self.PORT}\n等待客户端连接...")

            # 打开记录文件
            self.f = open("server_chat_gui.txt", "w", encoding="utf-8")

            # 等待客户端连接
            self.client_conn, addr = self.server_socket.accept()
            self.show_msg(f"客户端已连接:{addr}\n")

            # 接收消息循环
            while True:
                cipher = self.client_conn.recv(1024).decode("utf-8")
                if not cipher:
                    break
                plain = decrypt(cipher)

                if plain == "exit":
                    self.show_msg("\n【对方退出聊天】")
                    break

                self.show_msg(f"\n【收到】密文:{cipher}")
                self.show_msg(f"【解密】明文:{plain}")
                self.save_log(f"【收到】密文:{cipher}\n【解密】明文:{plain}\n")

        except Exception as e:
            messagebox.showerror("错误", str(e))

    def send_msg(self, event=None):
        if not self.client_conn:
            messagebox.showwarning("提示", "未连接客户端")
            return

        plain = self.entry_msg.get().strip()
        if not plain:
            return

        cipher = encrypt(plain)
        self.client_conn.send(cipher.encode("utf-8"))

        self.show_msg(f"\n【发送】明文:{plain}")
        self.show_msg(f"【发送】密文:{cipher}")
        self.save_log(f"【发送】明文:{plain}\n【发送】密文:{cipher}\n\n")

        self.entry_msg.delete(0, tk.END)

        if plain == "exit":
            self.client_conn.close()
            self.server_socket.close()
            self.root.quit()

    def show_msg(self, msg):
        self.chat_area.config(state=tk.NORMAL)
        self.chat_area.insert(tk.END, msg + "\n")
        self.chat_area.config(state=tk.DISABLED)
        self.chat_area.see(tk.END)

    def save_log(self, text):
        if self.f:
            self.f.write(text)
            self.f.flush()

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

LLM客户端代码如下:

点击查看代码
import socket
import threading
import tkinter as tk
from tkinter import scrolledtext, messagebox

# 加密解密
def encrypt(text):
    return ''.join([chr(ord(c) + 8) for c in text])

def decrypt(text):
    return ''.join([chr(ord(c) - 8) for c in text])

class ClientGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("TCP 加密聊天 - 客户端")
        self.root.geometry("650x550")

        # 服务端IP(改成你自己的服务端IP)
        self.HOST = "127.0.0.1"
        self.PORT = 4444

        # 界面
        tk.Label(root, text="聊天记录(明文+密文)", font=("微软雅黑", 12)).pack(pady=5)
        self.chat_area = scrolledtext.ScrolledText(root, width=75, height=25, state=tk.DISABLED)
        self.chat_area.pack(pady=5)

        self.entry_msg = tk.Entry(root, width=50, font=("微软雅黑", 12))
        self.entry_msg.pack(pady=5)
        self.entry_msg.bind("<Return>", self.send_msg)

        tk.Button(root, text="发送", command=self.send_msg, width=10).pack()

        # 套接字
        self.client_socket = None
        self.f = None

        # 连接服务端
        threading.Thread(target=self.connect_server, daemon=True).start()

    def connect_server(self):
        try:
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client_socket.connect((self.HOST, self.PORT))
            self.show_msg("已成功连接服务端!\n")

            self.f = open("client_chat_gui.txt", "w", encoding="utf-8")

            # 接收消息
            while True:
                cipher = self.client_socket.recv(1024).decode("utf-8")
                if not cipher:
                    break
                plain = decrypt(cipher)

                if plain == "exit":
                    self.show_msg("\n【对方退出聊天】")
                    break

                self.show_msg(f"\n【收到】密文:{cipher}")
                self.show_msg(f"【解密】明文:{plain}")
                self.save_log(f"【收到】密文:{cipher}\n【解密】明文:{plain}\n")

        except Exception as e:
            messagebox.showerror("连接失败", "请检查服务端是否启动")
            print(e)

    def send_msg(self, event=None):
        if not self.client_socket:
            messagebox.showwarning("提示", "未连接服务端")
            return

        plain = self.entry_msg.get().strip()
        if not plain:
            return

        cipher = encrypt(plain)
        self.client_socket.send(cipher.encode("utf-8"))

        self.show_msg(f"\n【发送】明文:{plain}")
        self.show_msg(f"【发送】密文:{cipher}")
        self.save_log(f"【发送】明文:{plain}\n【发送】密文:{cipher}\n\n")

        self.entry_msg.delete(0, tk.END)

        if plain == "exit":
            self.client_socket.close()
            self.root.quit()

    def show_msg(self, msg):
        self.chat_area.config(state=tk.NORMAL)
        self.chat_area.insert(tk.END, msg + "\n")
        self.chat_area.config(state=tk.DISABLED)
        self.chat_area.see(tk.END)

    def save_log(self, text):
        if self.f:
            self.f.write(text)
            self.f.flush()

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

关键代码解析:
3c32c79b4ec5bb4d60cbc6efe185dc8c
功能:把每个字符的 ASCII 码 +8 加密,-8 解密
作用:简单对称加密,保证传输内容不直接显示明文

c2bd095d938f62edbf1a04317c7c1baf
作用:让界面不卡死,后台持续监听网络消息

66ad48bd6ab24fc7fb7d434d7387be84
功能:安全地往聊天框追加内容
特点:自动滚动到最新消息

LLM代码的结果图片
b918088b9d43e5f21d664dd0607ecd04

LLM生成代码的优点:
1.在同时开启服务端和客户端时,在关闭服务端时,客户端会弹出“连接失败”提示并退出程序,同时,服务器未连接时禁止发送,不会报错崩溃,给用户增强了使用体验;
2.LLM生成的代码容错和异常处理更加完善,鲁棒性大大增强;
3.生成的代码结构清晰,代码趋于模块化;
4.LLM生成的代码引入多线程,收发互不干扰,实现双工实时通信,不会卡死界面。

上传代码云
实验3代码
实验3LLM生成代码
4435f154eae8c9cc960dfe3cea2e7827
a40c3fe164b86906712fb0de33052af7

三. 实验过程中遇到的问题和解决过程
问题1.与同学Ping通时,无法正常连接上。
问题1解决方案:防火墙拦截了Ping通的请求,将防火墙关闭即可连接。
问题2.与同学连接进行正常的ip更改后,在进行测试时,却无法连接。
问题2解决方案:在大家连接同一个学校的网络时,有不同同学的学号的末尾时相同的,这样会导致另一个同学在连接时会导致报错,解决方法时连接另一个同学的网络热点进行操作。
问题3.在查询ipconfig时会提示“"ipconfig"不是内部或外部命令,也不是可运行的程序或批处理文件”
问题3解决方案:可能误删其文件等,需要在命令提示符中输入完整路径,如:C:\Windows\System32\ipconfig

四.其他(感悟、思考等)
在本次 Socket 网络通信实验中,我了解 TCP 套接字的通信原理,利用 Python 实现了带加密与日志记录的双人通信程序。同时,通过不断学习和同学帮助,我也学会了 IP 地址查询与配置。学习LLM生成后的代码后,也进一步理解了单线程通信与多线程通信的原理。

参考资料

posted @ 2026-04-30 17:14  -+7  阅读(13)  评论(0)    收藏  举报