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

20241417 2024-2025-2 《Python程序设计》实验三报告

课程:《Python程序设计》
班级: 2414
姓名: 罗若元
学号:20241417
实验教师:王志强
实验日期:2025年4月16日
必修/选修: 公选课

一.实验内容

  • 创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信

二. 实验过程及结果

  1. 根据实验要求编写代码如下:
    服务端代码:
# coding: utf-8
# Project:PythonProject4
# File:server.py
# Author:罗若元
# Date :2025/4/18 22:50
# IDE:PyCharm
import socket
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import os

# 加密密钥和初始化向量
key = os.urandom(16)
iv = os.urandom(16)


def encrypt_message(message):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(pad(message.encode('utf-8'), AES.block_size))
    return iv + encrypted


def decrypt_message(encrypted_message):
    iv = encrypted_message[:AES.block_size]
    encrypted = encrypted_message[AES.block_size:]
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted = unpad(cipher.decrypt(encrypted), AES.block_size)
    return decrypted.decode('utf-8')


# 创建 socket 对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定地址和端口
server_address = ('localhost',8888)
server_socket.bind(server_address)

# 监听连接
server_socket.listen(1)
print('服务器正在监听 {}:{}'.format(*server_address))

# 接受客户端连接
client_socket, client_address = server_socket.accept()
print('接受来自 {} 的连接'.format(client_address))

try:
    # 先发送密钥和IV给客户端
    client_socket.send(key + iv)

    conversation = []
    while True:
        # 接收客户端加密消息
        encrypted_data = client_socket.recv(1024)
        if not encrypted_data:
            break
        # 解密消息
        decrypted_message = decrypt_message(encrypted_data)
        conversation.append(f"客户端: {decrypted_message}")
        print('客户端加密消息解密后: {}'.format(decrypted_message))

        # 发送消息给客户端
        plaintext_message = input('请输入要发送给客户端的消息: ')
        encrypted_message = encrypt_message(plaintext_message)
        client_socket.send(encrypted_message)
        conversation.append(f"服务端: {plaintext_message}")

        if input("是否要继续对话?Y/N").upper() == "N":
            break

    # 后续操作可以继续添加,这里仅打印对话记录
    print("对话记录:")
    for line in conversation:
        print(line)

except Exception as e:
    print(f'发生错误: {e}')
finally:
    # 关闭连接
    client_socket.close()
    server_socket.close()

客户端代码:

# coding: utf-8
# Project:PythonProject4
# File:client.py
# Author:罗若元
# Date :2025/4/18 22:49
# IDE:PyCharm
import socket
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import os

# 创建 socket 对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器
server_address = ('localhost',8888)
client_socket.connect(server_address)

# 接收服务器发送的密钥和IV
key_iv = client_socket.recv(32)
key = key_iv[:16]
iv = key_iv[16:]


def encrypt_message(message):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(pad(message.encode('utf-8'), AES.block_size))
    return iv + encrypted


def decrypt_message(encrypted_message):
    iv = encrypted_message[:AES.block_size]
    encrypted = encrypted_message[AES.block_size:]
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted = unpad(cipher.decrypt(encrypted), AES.block_size)
    return decrypted.decode('utf-8')


try:
    conversation = []
    while True:
        # 发送消息给服务器
        plaintext_message = input('请输入要发送给服务器的消息: ')
        encrypted_message = encrypt_message(plaintext_message)
        client_socket.send(encrypted_message)
        conversation.append(f"客户端: {plaintext_message}")

        # 接收服务器加密消息
        encrypted_data = client_socket.recv(1024)
        if not encrypted_data:
            break
        # 解密消息
        decrypted_message = decrypt_message(encrypted_data)
        conversation.append(f"服务端: {decrypted_message}")
        print('服务器加密消息解密后: {}'.format(decrypted_message))

        if input("是否继续对话?Y/N").upper() == "N":
            break

    # 将对话保存为加密文件
    conversation_text = '\n'.join(conversation)
    encrypted_conversation = encrypt_message(conversation_text)
    with open('encrypted_conversation.bin', 'wb') as file:
        file.write(encrypted_conversation)
    print("对话已保存为加密文件 encrypted_conversation.bin")

    # 后续操作可以继续添加,这里仅打印对话记录
    print("对话记录:")
    for line in conversation:
        print(line)

except Exception as e:
    print(f'发生错误: {e}')
finally:
    # 关闭连接
    client_socket.close()

2.实验步骤
(1)创建服务端和客户端,选择一个通信端口,用 Python 语言编程实现通信演示程序:
服务端(首先创建了一个 TCP 套接字对象server_socket,并将其绑定到本地地址localhost的端口8888上):

import socket
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import os

# 创建 socket 对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定地址和端口
server_address = ('localhost',8888)
server_socket.bind(server_address)

# 监听连接
server_socket.listen(1)
print('服务器正在监听 {}:{}'.format(*server_address))

# 接受客户端连接
client_socket, client_address = server_socket.accept()
print('接受来自 {} 的连接'.format(client_address))

try:
    # 先发送密钥和IV给客户端
    client_socket.send(key + iv)

    while True:
        # 接收客户端加密消息
        encrypted_data = client_socket.recv(1024)
        if not encrypted_data:
            break
        # 解密消息
        decrypted_message = decrypt_message(encrypted_data)
        print('客户端加密消息解密后: {}'.format(decrypted_message))

        # 发送消息给客户端
        plaintext_message = input('请输入要发送给客户端的消息: ')
        encrypted_message = encrypt_message(plaintext_message)
        client_socket.send(encrypted_message)

        if input("是否要继续对话?Y/N").upper() == "N":
            break

except Exception as e:
    print(f'发生错误: {e}')
finally:
    # 关闭连接
    client_socket.close()
    server_socket.close()

客户端(创建一个 TCP 套接字对象client_socket,并使用connect()方法连接到服务器的地址和端口):

import socket
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import os

# 创建 socket 对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器
server_address = ('localhost',8888)
client_socket.connect(server_address)

# 接收服务器发送的密钥和IV
key_iv = client_socket.recv(32)
key = key_iv[:16]
iv = key_iv[16:]

try:
    while True:
        # 发送消息给服务器
        plaintext_message = input('请输入要发送给服务器的消息: ')
        encrypted_message = encrypt_message(plaintext_message)
        client_socket.send(encrypted_message)

        # 接收服务器加密消息
        encrypted_data = client_socket.recv(1024)
        if not encrypted_data:
            break
        # 解密消息
        decrypted_message = decrypt_message(encrypted_data)
        print('服务器加密消息解密后: {}'.format(decrypted_message))

        if input("是否继续对话?Y/N").upper() == "N":
            break

except Exception as e:
    print(f'发生错误: {e}')
finally:
    # 关闭连接
    client_socket.close()

(2)文件的打开和读写操作:
客户端(首先将对话列表conversation中的每一项用换行符连接成一个字符串conversation_text,对该字符串进行加密,得到加密后的对话encrypted_conversation,使用with open()语句以二进制写入模式打开文件encrypted_conversation.bin,并将加密后的对话写入文件。最后打印提示信息,表示对话已保存为加密文件。):

# 将对话保存为加密文件
conversation_text = '\n'.join(conversation)
encrypted_conversation = encrypt_message(conversation_text)
with open('encrypted_conversation.bin', 'wb') as file:
    file.write(encrypted_conversation)
print("对话已保存为加密文件 encrypted_conversation.bin")

(3)客户端从文件读取内容,加密后并传输;服务端收到密文并解密,保存在文件中:
客户端(使用with open()语句以文本读取模式打开文件message.txt,读取文件内容并存储在plaintext_message中,对读取的内容进行加密,得到加密后的消息encrypted_message,并发送给服务器。如果文件不存在,捕获FileNotFoundError异常并打印错误信息):

# 从文件读取内容
try:
    with open('message.txt', 'r', encoding='utf-8') as file:
        plaintext_message = file.read()
    encrypted_message = encrypt_message(plaintext_message)
    client_socket.send(encrypted_message)
except FileNotFoundError:
    print("文件 message.txt 未找到,请检查文件路径。")

服务端(接收客户端发送的加密消息encrypted_data。
如果接收到的消息不为空,对其进行解密,得到解密后的消息decrypted_message,使用with open()语句以文本写入模式打开文件received_message.txt,将解密后的消息写入文件。最后打印提示信息,表示解密后的消息已保存到文件中):

# 接收客户端加密消息
encrypted_data = client_socket.recv(1024)
if encrypted_data:
    # 解密消息
    decrypted_message = decrypt_message(encrypted_data)
    # 保存到文件
    with open('received_message.txt', 'w', encoding='utf-8') as file:
        file.write(decrypted_message)
    print("解密后的消息已保存到 received_message.txt")
  1. 代码编译运行,测试是否运行成功,并得到结果

  2. 将代码上传至码云

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

  • 问题1:客户端无法连接到服务端
  • 问题1解决方案:询问AI后发现是没有打开服务端而打开了客户端
  • 问题2:保存为文件后无法打开,显示文件不存在
  • 问题2解决方案:询问AI豆包后得知是文件路径问题,上下设置的文件路径不一致
  • ...

其他(感悟、思考等)

  • 接触到了py的函数,和C一样能让主函数变得更加简洁,非常方便
  • 两次实验下来深刻感受到了py代码的方便快捷,与C相比简洁明了不少

参考资料

  • 群里的代码
  • AI大模型
  • CSDN网站
  • 学习通里有关socket编程技术的介绍
posted @ 2025-04-23 20:20  20241417罗若元  阅读(40)  评论(0)    收藏  举报