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

课程:《Python程序设计》
班级: 2413
姓名: 梅良谦
学号:20241309
实验教师:王志强
实验日期:2025年4月16日
必修/选修: 公选课

一、实验内容

1.创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
2.要求包含文件的基本操作,例如打开和读写操作。
3.要求发送方从文件读取内容,加密后并传输;接收方收到密文并解密,保存在文件中。
4.程序代码托管到码云。

二、 实验过程及结果

实验前的准备

在终端查询电脑的ip地址,用于服务端和客户端之间的连接。

1.服务端核心代码:

(1)首先,导入socket库,创建套接字serve_socket,两个参数表明该socke使用的协议;
(2)然后绑定ip地址和端口,server_socket.listen(5)表示使socket处于监听转播台,5表示最多接受五个等待连接的客户端;
(3)运行accept方法使服务端接受客户端连接,打印出IP地址和端口;
(4)当成功连接客户端后,用data存储客户端传输的数据,client_socket.recv(1024)中1024表示最多读取的字节数;
(5)判断监听是否结束:如果客户端关闭连接,返回空字节,则服务端也关闭服务,如果客户端返回不是空字节,decode将传来的数据解码并打印出来,同时输入服务端回应的内容,因为发送的数据类型为字节,所以需要使用encode编码后发送。
(6)最后可以调用close()关闭socket。

import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('192.168.13.248', 9999)
server_socket.bind(address)
server_socket.listen(5)
print("开始监听", address)
client_socket, address = server_socket.accept()
print("我们收到了{}的连接".format(address))
while True:
    data = client_socket.recv(1024)
    if not data: 
        break
    print("客户端说:{}".format(data.decode()))  # 解码收到的数据
    response = input("服务端回应:")
    client_socket.send(response.encode())  # 发送回应时需要编码
client_socket.close()
server_socket.close()  # 记得关闭服务

2.作为服务端的运行结果

3.客户端核心代码

(1)首先,同样需要导入scoket模板并创立客户端的套接字client_socket;
(2)然后,运用connect方法,借助服务端的ip地址和端口,连接服务端;
(3)用message存储用户端输入的数据并添加退出条件,如果客户端输入的说exit,则关闭连接,如果不是,则将数据进行编码后发送到服务器端同时将服务端的数据进行解码并打印,其中message.lower的作用是使用户输入exit无需考虑大小写;
(4)close()关闭连接。

import socket  # 确保导入 socket 模块

# 创建一个新的套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器
client_socket.connect(('192.168.13.200', 9999))

while True:
    # 发送消息到服务器
    message = input("客户端说:")
    if message.lower() == 'exit':  # 添加退出条件
        break
    client_socket.send(message.encode())  # 发送消息时需要编码

    # 接收服务器端的回复
    data = client_socket.recv(1024).decode()  # 解码接收到的数据
    print("服务端回答:", data)

# 关闭连接
client_socket.close()

4.作为客户端的运行结果

5.学习异或加密、解密算法、,文件的基本操作

(1)异或加密、解密算法
定义加密、解密函数,例如encode(data,key)参数data表示要加密或者解密的字符串数据,参数key表示密钥,运用for循环遍历字符串,ord(char)获取字符的Unicode码,^异或运算符号,chr()将异或操作后的整数值转化回字符。
(2)文件的基本操作
打开文件:open(file,mode=‘r’,encoding),mode包括r(只读模式),w(写入模式)a(追加模式)等,with open(),可在代码块结束时自动关闭文件
读取文件:read(),一次性读取全部内容;readline()逐行读取,一次一行;readlines()读取所有行
写入文件:write()
关闭文件:close(),推荐使用with open()
文件定位:seek()用于改变指针位置

6.修改代码,给予详细注释

服务端代码:

import socket
# 异或加密函数
def encrypt_decrypt(data, key):#data:要加密或解密的字符串数据,key: 异或操作的密钥,是一个整数
    result = ""#将一个空字符赋值给result,用于后续返回加密或者解密后的字符串
    for char in data:# ord(char) 获取字符的Unicode码点(整数值),^ 是异或运算符, chr() 将异或操作后的整数值转换回字符
        result += chr(ord(char) ^ key)#字符拼接
    return result#返回加密或者解密后的字符串
# 创建一个新的套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 设置地址和端口
address = ('192.168.5.3', 9999)

# 绑定
server_socket.bind(address)

# 开始监听
server_socket.listen(5)
print("开始监听", address)

# 接收连接
client_socket, address = server_socket.accept()
print("我们收到了{}的连接".format(address))

while True:
    # 接收数据
    data1 = client_socket.recv(1024)
    if not data1:  # 更改这里的 adta 为 data
        break
        # 解码收到的数据
    decoded_data = data1.decode()
    print("客户端说:{}".format(decoded_data))
    # 使用密钥666对接收到的密文进行解密
    data2 = encrypt_decrypt(decoded_data, 666)
    print(data2)
    # 打开文件'fuwuduanjieshou' 以写入模式,将解密后的数据保存到文件中
    file_path = r'D:\999\fuwuduanjieshou.txt'
    with open(file_path, 'w') as file:
        file.write(data2)
        print(data2)
# 关闭连接
client_socket.close()
server_socket.close()  # 记得关闭服务

客户端代码:

import socket  # 确保导入 socket 模块
# 异或加密函数
def encrypt_decrypt(data, key):#data:要加密或解密的字符串数据,key: 异或操作的密钥,是一个整数
    result = ""#将一个空字符赋值给result,用于后续返回加密或者解密后的字符串
    for char in data:# ord(char) 获取字符的Unicode码点(整数值),^ 是异或运算符, chr() 将异或操作后的整数值转换回字符
        result += chr(ord(char) ^ key)#字符拼接
    return result#返回加密或者解密后的字符串
#创建一个文件test.txt
file_path = r'D:\999\text.txt'
with open(file_path, 'w') as file:
    file.write('Hello, World!')


# 创建一个新的套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器
client_socket.connect(('192.168.5.3', 9999))

while True:
    message = input("如果想要退出输入exit,如果不,输入no:")
    if message.lower() == 'exit':  # 添加退出条件
        break
            # 打开文件 'test.txt' 以读取模式,读取文件内容
    with open(file_path , 'r') as file:
              data2 = file.read()
             # 使用密钥123对读取到的数据进行加密
    encrypted_data = encrypt_decrypt(data2, 666)
    # 将加密后的数据编码为字节流并发送给服务端
    client_socket.send(encrypted_data.encode())
# 关闭连接
client_socket.close()

7实验结果

如下图,服务器和客户端相继运行完成后,创建了一个text.txt和fuwuqijieshou.txt的文件,两个文件的内容都为Hello,World!

8上传代码到码云

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

  • 问题1:,在代码正确的情况下,作为服务端一直无法监听客户端
  • 问题1解决方案:通过询问老师,发现是因为电脑的防火墙没有关闭。
  • 问题2:对服务端和客户端的部分代码存在不理解的地方
  • 问题2解决方案:询问豆包,网上观看哔哩哔哩相关视频。
  • 问题3:起初编写的服务端部分代码如下,运行时会出现下面的错误提示:

  • 问题3解决方案:知晓是因为ord()函数要求里面的参数应该是字符串类型,通过向老师请教对代码进行了如下修改:

  • 问题4:在完成上述代码的修改后,运行时发现解码失败,如下图:

  • 问题4解决方案:猜测可能是因为直接使用 str(data1) 导致出现了问题,询问ai后明白当对字节类型的数据使用 str() 函数时,Python 会把字节对象转换为一种字符串形式,而非把字节数据解码成对应的字符串,要是直接把字节对象转换为字符串,传递给 encrypt_decrypt 函数,就会导致加密和解密操作处理的是字节对象的字符串表示形式,而不是实际的文本内容,这样加密和解密的结果就会出错。如下方的事例:

byte_data = b'hello'
str_data = str(byte_data)
print(str_data)

运行上述代码,输出结果为:

b'hello'

为想要的结果因为hello,所以先对 data1 进行解码,得到字符串后再进行异或解密操作,修改成如下图所示的代码:

其他(感悟、思考等)

感悟:实验中遇到的编码问题、数据同步问题等,促使我不断查阅资料、优化代码,极大地提升了问题解决能力。这次实验将理论知识转化为实际应用,让我明白只有通过不断实践,才能真正掌握编程技术的精髓。

参考资料

posted @ 2025-04-24 21:26  灯火忽已晚  阅读(71)  评论(0)    收藏  举报