20213306 实验三《Python程序设计》实验报告
2022/4/27 1:17:17
本文主要是介绍20213306 实验三《Python程序设计》实验报告,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
20213306《Python程序设计》实验三报告
课程:《Python程序设计》
班级:2133
姓名:李鹏宇
学号:20213306
实验教师:王志强
实验日期:2022年4月21日
必修/选修: 公选课
1.实验内容
创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。
2.实验要求
- 创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
- 要求包含文件的基本操作,例如打开和读写操作。
- 要求发送方从文件读取内容,加密后并传输;接收方收到密文并解密,保存在文件中。
- 程序代码托管到码云。
3. 实验过程及结果
3.1 代码
客户端
import socket import datetime#以当前日期加密 from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex class AesCrypto():#支持中文的AES def __init__(self, key, IV): self.key = key #需为16位倍数 self.iv = IV #必须为16位 self.mode = AES.MODE_CBC def encrypt(self, text): cryptor = AES.new(self.key, self.mode, self.iv) length = 16 count = len(text) if(count%length != 0): add = length-(count%length) else: add=0 text = text+("\0".encode()*add)#因为中文位数原因,这里需要.encode self.ciphertext = cryptor.encrypt(text) return (self.ciphertext) def decrypt(self, text): cryptor = AES.new(self.key, self.mode, self.iv) plain_text = cryptor.decrypt((text)).decode() return plain_text s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) print("欢迎来到客户端") port = input("请输入连接端口号") s.connect(('localhost',int(port))) #暂时本地传输本地 mo = input("请选择模式\n1.文字2.传输文件") if mo == '1': s.sendall(mo.encode()) str1 = input("请输入传输内容") k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo1 = AesCrypto(key=key1, IV=key1) str1 = mo1.encrypt(str1.encode()) s.sendall(str1) data = s.recv(1024) print(data.decode()) elif mo == '2':#文件传输 s.sendall(mo.encode()) mo2mo = input("新建文件请输入1,传输已有文件请输入2") addre = input("请输入文件路径") k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo2 = AesCrypto(key=key1, IV=key1) addre1 = mo2.encrypt(addre.encode()) s.sendall(addre1) if mo2mo == "1": file1 = open(addre,"w+",encoding="utf-8")#新建文件 neirong = input("请输入内容") file1.write(neirong) file1.close() file1 = open(addre,"r",encoding="utf-8") elif mo2mo == "2": file1 = open(addre,"r",encoding="utf-8")#只读 file1.seek(0) str1 = file1.readlines() file1.close() lenfile = len(str1)#获取文件有几行 lenfile = str(lenfile) k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo2 = AesCrypto(key=key1, IV=key1) lenfile = mo2.encrypt(lenfile.encode())#将文件行数发出去 s.sendall(lenfile) for i in str1:#对于文件的每一行顺序发送 k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo2 = AesCrypto(key=key1, IV=key1) i = mo2.encrypt(i.encode()) s.sendall(i) data = s.recv(1024)#接收“已收到”信息 print(data.decode()) s.close
服务端
import socket import datetime from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex class AesCrypto(): def __init__(self, key, IV): self.key = key self.iv = IV self.mode = AES.MODE_CBC def encrypt(self, text): cryptor = AES.new(self.key, self.mode, self.iv) length = 16 count = len(text) if(count%length != 0): add = length-(count%length) else: add=0 text = text+("\0".encode()*add) self.ciphertext = cryptor.encrypt(text) return (self.ciphertext) def decrypt(self, text): cryptor = AES.new(self.key, self.mode, self.iv) plain_text = cryptor.decrypt((text)).decode('utf8','ignore') return plain_text#加密解密同理 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = input("欢迎使用服务端\n请输入开放连接端口号") s.bind(("localhost", int(port)))#这里只写端口号没问题 s.listen() con,addr= s.accept() mo = con.recv(1024) if mo.decode()== '1': print("已收到文字传输请求,对方正在输入...") data = con.recv(1024) k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo1 = AesCrypto(key=key1, IV=key1) data = mo1.decrypt(data) print(data) right = "信息已收到"#类似状态码,就没有加密 con.sendall(right.encode()) elif mo.decode()=='2': print("已收到文件传输请求,对方正在输入...") addre = con.recv(1024) k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo2 = AesCrypto(key=key1, IV=key1) addre = mo2.decrypt(addre) addre = addre.encode() addre = addre.split(b"\x00")[0].decode("utf-8")#防‘\’导致打开文件不存在的问题 file1 = open(addre+"1.txt","w+",encoding="utf-8")#为测试方便多加了后缀 lenfile1 = con.recv(1024) k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo2 = AesCrypto(key=key1, IV=key1) lenfile1 = mo2.decrypt(lenfile1) lenfile1 = lenfile1.encode() lenfile1 = lenfile1.split(b"\x00")[0].decode("utf-8") lenfile1 = int(lenfile1)#解码文件行数 for temp in range(1,lenfile1+1): temp = con.recv(1024) k = datetime.date.today() key1 = k.__format__('%Y&%m&%d%j%U%w').encode() mo2 = AesCrypto(key=key1, IV=key1) temp = mo2.decrypt(temp) temp = temp.encode() temp = temp.split(b"\x00")[0].decode("utf-8")#防字符串解密问题 print(temp)#显示一下内容 file1.write(temp)#写入文件 file1.close() right = "文件传输完成" con.sendall(right.encode()) print("文件已接收") s.close
测试截图
上传gitee截图
4. 实验过程中遇到的问题和解决过程
- 问题1:AES加密方式无法加密中文
- 问题1解决方案:借用了csdn上一篇文章的的方案
- 问题2:错误“ValueError:数据必须与 ECB 模式下的块边界对齐”
- 问题2解决方案:补齐时中文需要encode
- 问题3:错误“UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xca in position 0: invalid continuation byte”
- 问题3解决方案:转码错误,应严格按照utf-8方式
- 问题4:路径传输时无法打开对应路径
- 问题4解决方案:将接收到的多余‘/’删除
其他(感悟、思考等)
这次实验中,我在aes加解密和bytes与str类型转换上耗费了大量的时间,这次实验让我意识到了尽管python的变量开始时是自适应的,但每个函数要求的变量不是能够通过简单的强制转换就能满足的,有时即使用正确的方式也会得到错误的结果。应该善用调试,灵活的去判断传输时每个变量的具体情况。同时,对于file方法掌握仍然不熟练,尤其是常常分不清某时指针的位置,是否创建了新文件等等,在以后会更加深入的去了解。
参考资料
- AES加密算法的python版本(实现了中文加密,且解密之后无乱码),基于pycrypto库
- Python File(文件) 方法 - 菜鸟教程
- Python 网络编程 - 菜鸟教程
- python字符编码问题汇总(str、byte转换,乱码处理,ASCII、Unicode、UTF-8)
这篇关于20213306 实验三《Python程序设计》实验报告的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-03用FastAPI掌握Python异步IO:轻松实现高并发网络请求处理
- 2025-01-02封装学习:Python面向对象编程基础教程
- 2024-12-28Python编程基础教程
- 2024-12-27Python编程入门指南
- 2024-12-27Python编程基础
- 2024-12-27Python编程基础教程
- 2024-12-27Python编程基础指南
- 2024-12-24Python编程入门指南
- 2024-12-24Python编程基础入门
- 2024-12-24Python编程基础:变量与数据类型