学号:20241227曹鹏泰 2024-2025-3《Python程序设计》实验三报告

课程:《Python程序设计》
班级: 2412
姓名: 曹鹏泰
学号:20241227
实验教师:王志强
实验日期:2025年4月22日
必修/选修:公选课

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

注:在华为ECS服务器(OpenOuler系统)和物理机(Windows/Linux系统)上使用VIM、PDB、IDLE、Pycharm等工具编程实现。

二.实验过程及结果:https://gitee.com/uchiha-p/xiao-organization.git;)
1.实现连接和通信功能:(这段代码实现了一个简单的基于 TCP 协议的服务器端程序,能够与客户端建立连接并进行简单的双向文本通信。)
实验代码:
服务端

# -*- coding: utf-8 -*-
#该 Python 脚本的编码格式为 UTF-8,这样脚本中就可以正确处理包含中文字符等Unicode字符的内容。

import os
# 文件名: Server2025
# 描  述:
# 作  者: besti
# 日  期: 2025/4/15
#  Have you ever seen Los Angeles at 4 a.m?
import socket

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

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

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

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

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

    # 发送消息给客户端
    message = input('请输入要发送给客户端的消息: ')
    client_socket.send(message.encode('utf-8'))
    if input("是否要继续?Y/N")=="N":
        break

# 关闭连接
client_socket.close()
server_socket.close()

参数“1” 表示允许的最大未完成连接数,即同时可以等待处理的客户端连接请求数量。然后打印出服务器正在监听的地址和端口信息。

客户端

# -*- coding: utf-8 -*-

# 文件名: Client2025
# 描  述:
# 作  者: 20241227曹鹏泰
# 日  期: 2025/4/22
#  Have you ever seen Los Angeles at 4 a.m?
import socket

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

# 连接到服务器
server_address = ('192.168.43.78', 9999) 
# 绑定了服务器的IP地址和端口
client_socket.connect(server_address)

while True:
    # 发送消息给服务器
    message = input('请输入要发送给服务器的消息: ')
    client_socket.send(message.encode('utf-8'))

    # 接收服务器消息
    data = client_socket.recv(1024).decode('utf-8')
    if not data:
        break
    print('服务器说: {}'.format(data))
    # if (input("是否继续Y/N?")=="N"):
    #     break

# 关闭连接
client_socket.close()

实验结果:


2.文件的打开和传送:
实验代码:
服务端

# -*- coding: utf-8 -*-

import os
# 文件名: Server2025
# 描  述:
# 作  者: besti
# 日  期: 2025/4/15
#  Have you ever seen Los Angeles at 4 a.m?
import socket

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

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

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

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

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

    # 将客户端消息写入文件
    try:
        with open('client_messages.txt', 'a', encoding='utf-8') as file:
            file.write(data + '\n')
    except Exception as e:
        print(f'写入文件时出错: {e}')

    # 发送消息给客户端
    message = input('请输入要发送给客户端的消息: ')
    client_socket.send(message.encode('utf-8'))
    if input("是否要继续?Y/N") == "N":
        break

# 关闭连接
client_socket.close()
server_socket.close()

客户端

# -*- coding: utf-8 -*-

# 文件名: Client2025
# 描  述:
# 作  者: besti
# 日  期: 2025/4/15
#  Have you ever seen Los Angeles at 4 a.m?
import socket

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

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

while True:
    choice = input('请选择操作:1. 发送消息;2. 发送文件内容;3. 退出:')
    if choice == '1':
        # 发送消息给服务器
        message = input('请输入要发送给服务器的消息: ')
        client_socket.send(message.encode('utf-8'))
    elif choice == '2':
        file_path = input('请输入要发送的文件路径: ')
        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                file_content = file.read()
                client_socket.send(file_content.encode('utf-8'))
        except FileNotFoundError:
            print('文件未找到,请检查文件路径。')
    elif choice == '3':
        break
    else:
        print('无效的选择,请重新输入。')

    # 接收服务器消息
    data = client_socket.recv(1024).decode('utf-8')
    if not data:
        break
    print('服务器说: {}'.format(data))

# 关闭连接
client_socket.close()

在上述的 Python 代码中,当客户端选择发送文件内容时,输入的文件路径可以是绝对路径,也可以是相对路径(相对于运行客户端程序时的当前工作目录)。
例如,文件 “test.txt” 在 “C:\Users\username\Documents” 文件夹下,其完整路径就是 “C:\Users\username\Documents\test.txt”。

实验结果:


3.文件的加密
实验代码:
服务端:

# -*- coding: utf-8 -*-

import os
# 文件名: Server2025
# 描  述:
# 作  者: besti
# 日  期: 2025/4/15
#  Have you ever seen Los Angeles at 4 a.m?
import socket

# 定义异或加密函数,定义了与客户端相同的加密密钥key。
def xor_encrypt_decrypt(data, key):
    key_length = len(key)
    encrypted = bytearray()
    for i in range(len(data)):
        encrypted.append(data[i] ^ key[i % key_length])
    return bytes(encrypted)

# 加密密钥,要与客户端保持一致
key = b'secretkey'

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

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

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

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

while True:
    # 接收客户端消息,在接收客户端消息时,调用 xor_encrypt_decrypt 函数对加密数据进行解密,然后打印并写入文件。
    encrypted_data = client_socket.recv(1024)
    if not encrypted_data:
        break
    data = xor_encrypt_decrypt(encrypted_data, key).decode('utf-8')
    print('客户端说: {}'.format(data))

    # 将客户端消息写入文件
    try:
        with open('client_messages.txt', 'a', encoding='utf-8') as file:
            file.write(data + '\n')
    except Exception as e:
        print(f'写入文件时出错: {e}')

    # 发送消息给客户端,在发送消息给客户端时,调用 xor_encrypt_decrypt 函数对消息进行加密,然后发送加密后的消息。
    message = input('请输入要发送给客户端的消息: ')
    encrypted_message = xor_encrypt_decrypt(message.encode('utf-8'), key)
    client_socket.send(encrypted_message)
    if input("是否要继续?Y/N") == "N":
        break

# 关闭连接
client_socket.close()
server_socket.close()

客户端:

# -*- coding: utf-8 -*-

# 文件名: Client2025
# 描  述:
# 作  者: besti
# 日  期: 2025/4/15
#  Have you ever seen Los Angeles at 4 a.m?
import socket

# 定义异或加密函数
def xor_encrypt_decrypt(data, key):
    key_length = len(key)
    encrypted = bytearray()
    for i in range(len(data)):
        encrypted.append(data[i] ^ key[i % key_length])
    return bytes(encrypted)

# 加密密钥
key = b'secretkey'

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

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

while True:
    choice = input('请选择操作:1. 发送消息;2. 发送文件内容;3. 退出:')
    if choice == '1':
        # 发送消息给服务器,在发送消息或文件内容时,调用 xor_encrypt_decrypt 函数对数据进行加密,然后发送加密后的数据。
        message = input('请输入要发送给服务器的消息: ')
        encrypted_message = xor_encrypt_decrypt(message.encode('utf-8'), key)
        client_socket.send(encrypted_message)
    elif choice == '2':
        file_path = input('请输入要发送的文件路径: ')
        try:
            with open(file_path, 'rb') as file:
                file_content = file.read()
                encrypted_content = xor_encrypt_decrypt(file_content, key)
                client_socket.send(encrypted_content)
        except FileNotFoundError:
            print('文件未找到,请检查文件路径。')
    elif choice == '3':
        break
    else:
        print('无效的选择,请重新输入。')

    # 接收服务器消息,在接收服务器消息时,同样调用 xor_encrypt_decrypt 函数对加密数据进行解密,然后打印解密后的消息。
    encrypted_data = client_socket.recv(1024)
    if not encrypted_data:
        break
    data = xor_encrypt_decrypt(encrypted_data, key).decode('utf-8')
    print('服务器说: {}'.format(data))

# 关闭连接
client_socket.close()

实验结果:

“xor_encrypt_decrypt” 函数实现了异或加密和解密的功能。
由于异或运算的特性,加密和解密使用的是同一个函数。

三.实验过程中遇到的问题和解决过程:
问题1:指定文件的路径错误
输入了D:\projects\练习一,显示错误。
解决方法:D:\projects\练习一是一个路径,但它可能是一个文件夹路径。如果要读取这个文件夹下的文件,还需要在这个路径基础上加上文件名和文件扩展名。
完整路径应该是D:\projects\练习一\test.txt。(同时要注意去掉双引号)
问题2:加密算法错误

未安装相关的pycharm插件。
解决方法:终端运行pip install pycryptodome,或者采用异或加密的方法,只是安全性不高。

四.其他(感悟、思考等)
对Socket 套接字在 TCP 协议下的通信机制有了直观且深入的认识。服务端监听端口、等待连接,客户端发起连接请求,这种交互模式看似简单,
实则在实际代码编写时,需要仔细处理诸如连接建立、数据收发、异常处理等多个环节。

五.参考资料:深入理解Python密码学:使用PyCrypto库进行加密和解密 ;python 对文件进行异或运算

posted @ 2025-04-23 18:43  20241227曹鹏泰  阅读(26)  评论(0)    收藏  举报