#cnblogs_post_body .video{ height: 0; padding-bottom: 56.25%; /* 16:9 */ position: relative; width: 100%; } #cnblogs_post_body .video iframe{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; }

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向家沣为客户端:

1612413513c0214185f422cd424b58af

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

bdbfb2b76b865135bae4ab4b2ceb26e0

(3)程序代码托管到码云。

markdown链接:SeverClent

ae80021ba7d426c20b2eb983dfb42ba3

(4)添加文件操作,有加分。

本程序通过添加文件操作实现了聊天记录持久化存储功能:

1.使用 Python 文件操作函数 open() 以追加模式 a 保存聊天记录。

2.每次收发消息都会将明文和密文写入 chat_log.txt。

3.文件编码使用 UTF-8,保证中文正常显示。

4.程序关闭后聊天记录不会丢失,实现日志持久化。

image

image

要求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)分析关键代码的功能和使用方法

服务端:

  1. XOR+Base64加密:实现消息异或加密与Base64编解码,传输密文,自动加解密并展示明文、密文。

  2. TCP多线程服务:独立线程监听连接,每接入一个客户端开启接收子线程,支持多客户端同时在线。

  3. GUI图形界面:基于tkinter实现端口配置、启停服务、在线客户端列表、聊天记录查看和点对点单发消息。

  4. 线程安全与异常处理:通过after机制异步刷新界面,客户端掉线、发送异常自动清理连接资源,程序稳定运行。

客户端:

  1. XOR+Base64加密:与服务端共用加密算法,自动加解密,日志显示明文与密文。

  2. TCP客户端连接:可配置IP和端口,支持连接、断开服务端。

  3. 后台接收线程:独立线程接收消息,不卡顿GUI,自动解密显示。

  4. GUI界面操作:可视化聊天窗口,线程安全刷新日志,异常自动重连。

使用方法:

首先在服务端界面生成密钥并复制,随后启动服务端监听端口,再到客户端界面粘贴密钥,填写服务端IP与端口后点击连接建立通信;客户端输入文字点击发送,服务端日志可同

步展示传输密文与解密明文,切换回服务端输入消息并点击广播发送,所有在线客户端均可接收密文并自动解密显示明文内容。

(2)分析生成程序的优点

  1. 通信安全可控:采用XOR对称加密+Base64编码,传输全程无明文泄露;密钥独立生成、手动分发,避免非法接入,保障数据传输保密性。

  2. 图形化界面易操作:基于GUI设计,服务端/客户端分标签页布局,密钥生成复制、IP端口配置、消息收发均为按钮化操作,无需命令行,上手零门槛。

  3. 多线程并发稳定:服务端采用多线程架构,可同时接入多个客户端,收发异步不阻塞;异常断开自动清理资源,运行稳定、兼容性强。

  4. 功能全面且可追溯:支持客户端单发、服务端广播双向通信,服务端日志同步显示密文与明文,消息可查、问题可追溯。

(3)给出运行过程和结果截图

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

85f62e99f2e51d703edef7b4bd56dcd8

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

6852ecb62bcc6e3d43138c9e39247796

(4)程序代码托管到码云。

markdown链接:abc

image

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

  • 问题1:两个人无法通信。

  • 问题1解决方案:两个人需要连接同一个热点,要输入对方已经修改好的IP地址,一定要先开服务端,再开客户端。

  • 问题2:我们两个人用ios系统和鸿蒙系统,怎么操作都不行。

  • 问题2解决方案:换成安卓系统就可以了。

  • 问题3:不知道怎么修改IP地址.

  • 问题3解决方案:首先打开控制面板,选择网络和Internet,然后点击更改适配器设置,右键WLAN,选择属性,然后双击Internet协议版本4,选择“使用下面的IP地址”,进行更改

4.其他(感悟、思考等)

通过这次实验,我学到了如何从电脑中查询自己的IP地址以及如何修改IP地址,但同时我也意识到ios系统和鸿蒙系统的局限性,因为我和同伴手机系统的问题导致一直失败,因

此我知道了实验不只有代码,其他的细节也很重要。加密传输让我认识到网络安全的重要性,今后我会更加努力,提升实践能力。

5.参考资料

posted @ 2026-05-01 13:17  张新政  阅读(14)  评论(1)    收藏  举报
#cnblogs_post_body .video{ height: 0; padding-bottom: 56.25%; /* 16:9 */ position: relative; width: 100%; } #cnblogs_post_body .video iframe{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; }