学号 2019-2020-2 《Python程序设计》实验x报告
课程:《Python程序设计》
班级: 2012
姓名: 王馨瑶
学号:20201215
实验教师:王志强
实验日期:2020年5月24日
必修/选修: 公选课
1.实验内容
创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。
(1)创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
(2)要求包含文件的基本操作,例如打开和读写操作。
(3)要求发送方从文件读取内容,加密后并传输;接收方收到密文并解密,保存在文件中。
(4)程序代码托管到码云。
2. 实验过程及结果
a.服务端监听多个客户端
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 8001))
s.listen(5)
socks = [] # 存放每个客户端的socket
b.客户端进行连接
amanda = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
amanda.connect(('127.0.0.1', 8001)) # 建立连接,参数必须是元组的形式
print(amanda.recv(1024)) # 接收welcome!
c.客户端实现循环互动
while True:
fun = input("Input your choice:")
amanda.sendall(fun.encode())
if fun == 'end':
print("Ok,Bye!")
break
elif fun == 'encrypt file':
filename = input("Please Input the file name which you want to encrypt:")
with open(filename, 'w')as file:
content = input("please input the content of " + filename + ':')
try:
file.writelines(content)
finally:
file.close()
af_filename = 'encrypted.txt'
amanda.sendall(af_filename.encode())
# amanda.sendall('amanda'.encode())
encrypt(filename, af_filename)
send_out(af_filename)
d.加密文件
第一次正儿八经接触密码学。查阅资料后决定用Python实现AES中相对简单的ECB模式加密。
需要了解补位知识、base64编码、utf-8编码等等
加密函数:
def encrypt(filename,af_filename):
key = input("Please set a key:")
data = str(open(filename, 'rb').read())
open(filename, 'rb').close()
key = key.encode('utf8')
data = pad(data)
cipher = AES.new(key, AES.MODE_ECB)
# 加密后得到的是bytes类型的数据,使用Base64进行编码,返回byte字符串
result = cipher.encrypt(data.encode())
encodestrs = base64.b64encode(result)
enctext = encodestrs.decode('utf8')
txt(af_filename, enctext)
time.sleep(1)
print('... File encrypted successfully ...')
return enctext
e.发送加密后的文件
def send_out(af_filename):
with open(af_filename, 'rb') as file:
i = file.read()
amanda.send(i)
# amanda.send('end'.encode())
time.sleep(1) # 推迟执行
print("... File sent successfully ...")
f.收到加密后的函数后,在服务器解密
def decrypt(af_filename):
key = input('Please enter the corresponding key:')
key = key.encode('utf8')
text = str(open(af_filename, 'r').read())
open(af_filename, 'r').close()
text = base64.b64decode(text)
cipher = AES.new(key, AES.MODE_ECB)
msg = cipher.encrypt(pad(text, BLOCK_SIZE))
decipher = AES.new(key, AES.MODE_ECB)
msg_dec = decipher.decrypt(msg)
print("Successfully decrypted, the contents of the file are:")
print(unpad(msg_dec, BLOCK_SIZE))
解密函数这里卡了不知道有多久,有补码的问题、有忘了转换base64的问题,还有函数参数引用错误的问题、总之对于python实现AES加密解密的知识还不够了解扎实。所以不要急于求成,要基础打好。
g.上传gitee
完整代码链接:
[client.py](client1.py · 2021bestipython/python_20201215 - 码云 - 开源中国 (gitee.com))
[server.py](server.py · 2021bestipython/python_20201215 - 码云 - 开源中国 (gitee.com))
运行结果
3. 实验过程中遇到的问题和解决过程
- 问题1:报错:a bytes-like object is required, not 'str'
问题出在该语句:
c.send("欢迎进入聊天系统!")
- 查阅资料发现问题所在:
原因是 Python3 和 Python2 在套接字返回值解码上有区别
解决办法:
1、str 通过 encode() 函数编码为 bytes
2、bytes 通过 decode() 函数编码为 str。(当我们从网络或磁盘上读取了字节流,则读到的数据就是 bytes)
- 问题2:报错:bind() takes exactly one argument (2 given)
- 解决方案:bind()括号中再加一个括号,应该传入元组。用元组表示地址
- 问题3:不明白实验要求中“监听多个客户请求”的意思
-解决方案:查阅资料,了解多线编程的概念,学习Python中threading模块
但是运用还不熟练,于是采取了另一种理解方式,即在客户端加上输入ip地址和端口数字的操作,进行主动连接,这样即可以在多个端口和服务器进行连接。运行结果如下图
- 问题4:报错:ValueError: Data must be aligned to block boundary in ECB mode
这个问题卡了好久好久,从网上找了三种方法,应用之后都不能解决。越来越烦躁。最终我决定从头再系统地理解一下AES加密解密方法。在自顶而下地耐心寻找代码错误。
[Python 实现 AES 加密/解密](Python 实现 AES 加密/解密)
-问题5:显示无CRYPTO文件
解决:查阅资料找到以下安装方式
-问题6:秘钥设置少于16位时报错
解决办法:加一个if语句判断key的位数,如果不足即补全
其他(感悟、思考等)
在了解学习一个新的领域和新知识时,要善于利用网络上存在的作品。一边抄一边学。但也不能只通过这样。应该和完整的基础知识相辅相成。基础知识扎实后才能真正理解代码