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

20242118 2024-2025-2 《Python程序设计》实验三报告
课程:《Python程序设计》
班级:2421
姓名:符馨琰
学号:20242118
实验教师:王志强
实验日期:2025年4月16日
必修/选修:公选课

一、实验内容
创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。
具体要求如下:
1.创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
2.要求包含文件的基本操作,例如打开和读写操作;
3.要求发送方从文件读取内容,加密后并传输;接收方收到密文并解密,保存在文件中;
4.程序代码托管到码云。

二、实验过程及结果
(注:使用“添加代码”后代码显示不正常,故报告中四个代码均折叠)

1.创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
(1)打开终端,输入ipconfig获取自己的ipv4地址;

(2)分别编写服务端与客户端的代码兵运行;
服务端:

点击查看代码
import socket
import threading
import os
import time


def clear_screen():
    """清屏功能"""
    os.system('cls' if os.name == 'nt' else 'clear')


def handle_client(client_socket, client_address):
    print(f"收到来自 {client_address} 的连接")

    try:
        # 创建一个线程来处理服务器输入并发送给客户端
        input_thread = threading.Thread(
            target=server_input,
            args=(client_socket,)
        )
        input_thread.daemon = True
        input_thread.start()

        while True:
            # 接收客户端消息
            data = client_socket.recv(1024).decode('utf-8')
            if not data:
                break

            print(f"\r\n客户端说: {data}")
            print("服务端说: ", end='', flush=True)  # 重新显示输入提示
    except Exception as e:
        print(f"\n发生错误: {e}")
    finally:
        client_socket.close()
        print("\n客户端连接已关闭")


def server_input(client_socket):
    """处理服务器输入并发送到客户端"""
    try:
        while True:
            message = input("服务端说: ")
            if message.lower() == 'exit':
                break
            elif message.lower() == 'clear':
                clear_screen()
                print("聊天已清屏")
                continue
            client_socket.send(message.encode('utf-8'))
    except Exception as e:
        print(f"\n发送消息时出错: {e}")


def start_server():
    # 创建服务器套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 设置端口复用,这样服务器意外断开后可以立即重用端口
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # 绑定地址和端口
    host = 'localhost'
    port = 12345
    server_socket.bind((host, port))

    # 开始监听
    server_socket.listen(1)
    clear_screen()
    print(f"服务器正在监听 {host}:{port}")
    print("输入 'exit' 退出聊天")
    print("=" * 50)

    while True:
        # 接受客户端连接
        client_socket, client_address = server_socket.accept()
        # 创建一个新线程来处理客户端连接
        client_thread = threading.Thread(
            target=handle_client,
            args=(client_socket, client_address)
        )
        client_thread.daemon = True
        client_thread.start()


if __name__ == "__main__":
    start_server()
客户端:
点击查看代码
import socket
import threading
import os
import time


def clear_screen():
    """清屏功能"""
    os.system('cls' if os.name == 'nt' else 'clear')


def receive_messages(client_socket):
    """接收来自服务器的消息"""
    try:
        while True:
            data = client_socket.recv(1024).decode('utf-8')
            if not data:
                print("\n服务器已断开连接")
                break
            print(f"\r\n服务端说: {data}")
            print("客户端说: ", end='', flush=True)  # 重新显示输入提示
    except Exception as e:
        print(f"\n接收消息时出错: {e}")
    finally:
        client_socket.close()


def start_client():
    # 创建客户端套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 连接服务器
    host = 'localhost'
    port = 12345

    try:
        client_socket.connect((host, port))
        clear_screen()
        print(f"已连接到服务器 {host}:{port}")
        print("输入 'exit' 退出聊天")
        print("=" * 50)

        # 创建接收消息的线程
        receive_thread = threading.Thread(
            target=receive_messages,
            args=(client_socket,)
        )
        receive_thread.daemon = True
        receive_thread.start()

        # 主线程负责发送消息
        while True:
            message = input("客户端说: ")
            if message.lower() == 'exit':
                break
            elif message.lower() == 'clear':
                clear_screen()
                print("聊天已清屏")
                continue
            client_socket.send(message.encode('utf-8'))

    except Exception as e:
        print(f"连接或发送消息时出错: {e}")
    finally:
        client_socket.close()
        print("已断开与服务器的连接")


if __name__ == "__main__":
    start_client()
测试结果 与另一主机进行交流

2.加入包含文件的基本操作,例如打开和读写操作。
服务端:

点击查看代码
import socket
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad


# 密钥和IV
FIXED_KEY = b"MySecretKey12345"
FIXED_IV = b"InitVector123456"


# 解密函数
def decrypt_data(data):
    cipher = AES.new(FIXED_KEY, AES.MODE_CBC, FIXED_IV)
    decrypted_data = unpad(cipher.decrypt(data), AES.block_size)
    return decrypted_data


# 主函数
def start_server():
    # 创建服务器套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    # 服务器设置
    host = 'localhost'
    port = 9999
    server_socket.bind((host, port))
    server_socket.listen(1)
    print(f"服务器已启动,监听地址: {host}:{port}")

    # 主循环
    while True:
        # 等待连接
        client_socket, client_address = server_socket.accept()
        print(f"客户端已连接: {client_address}")

        # 接收文件名
        filename = client_socket.recv(1024).decode('utf-8')
        print(f"接收文件: {filename}")

        # 接收文件大小
        file_size = int(client_socket.recv(1024).decode('utf-8'))

        # 接收加密数据
        encrypted_data = b''
        remaining = file_size

        while remaining > 0:
            chunk = client_socket.recv(min(4096, remaining))
            if not chunk:
                break
            encrypted_data += chunk
            remaining -= len(chunk)

        # 解密并保存
        print("正在解密...")
        decrypted_data = decrypt_data(encrypted_data)

        # 保存文件
        os.makedirs("接收文件", exist_ok=True)
        save_path = os.path.join("接收文件", filename)

        with open(save_path, 'wb') as f:
            f.write(decrypted_data)

        print(f"文件已保存: {save_path}")
        client_socket.send("完成".encode('utf-8'))
        client_socket.close()
        print("连接已关闭")


# 程序入口
if __name__ == "__main__":
    start_server()
客户端
点击查看代码
import socket
import os
import sys
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad


# 密钥和IV
FIXED_KEY = b"MySecretKey12345"
FIXED_IV = b"InitVector123456"


# 加密函数
def encrypt_data(data):
    cipher = AES.new(FIXED_KEY, AES.MODE_CBC, FIXED_IV)
    padded_data = pad(data, AES.block_size)
    encrypted_data = cipher.encrypt(padded_data)
    return encrypted_data


# 发送文件函数
def send_file(file_path):
    # 检查文件是否存在
    if not os.path.exists(file_path):
        print(f"错误: 文件不存在: {file_path}")
        return

    # 创建套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 连接服务器
    host = 'localhost'
    port = 9999
    client_socket.connect((host, port))
    print(f"已连接到服务器: {host}:{port}")

    # 发送文件名
    filename = os.path.basename(file_path)
    client_socket.send(filename.encode('utf-8'))

    # 读取文件
    with open(file_path, 'rb') as f:
        file_data = f.read()

    # 加密文件
    print("正在加密...")
    encrypted_data = encrypt_data(file_data)

    # 发送文件大小
    client_socket.send(str(len(encrypted_data)).encode('utf-8'))

    # 发送加密数据
    client_socket.sendall(encrypted_data)
    print("文件发送完成")

    # 接收服务器响应
    response = client_socket.recv(1024).decode('utf-8')
    print(f"服务器回复: {response}")

    # 关闭连接
    client_socket.close()
    print("连接已关闭")


# 程序入口
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("用法: python simple_aes_client.py <文件路径>")
    else:
        file_path = sys.argv[1]
        send_file(file_path)
传输

接收文件

源代码上传gitee

三. 实验过程中遇到的问题和解决过程
问题1:网络不同无法连接
问题1解决方案:主机连接同一热点
问题2:代码正确但一直无法监听客户端
问题3解决方案:关闭电脑防火墙
四.其他(感悟、思考等)
1.实验三将理论知识转化为实际应用,提高了我的实践能力;
2.了解了如何对数据进行加密操作,进行加密通讯。
五、参考资料
《零基础学Python》

posted @ 2025-06-06 19:54  pilot0622  阅读(23)  评论(0)    收藏  举报