课程:《Python程序设计》
班级: 1912
姓名: 斯廷响
学号:20191212
实验教师:王志强
实验日期:2021年5月25日
必修/选修: 公选课
1.实验内容
创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。
(1)创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
(2)要求包含文件的基本操作,例如打开和读写操作。
(3)要求发送方从文件读取内容,加密后并传输;接收方收到密文并解密,保存在文件中。
(4)程序代码托管到码云。
2. 实验过程及结果
实验的难点在于涉及到了以前我从来未涉及过的socket编程,通过计算机网络课程上学习过的一定知识以及在博客园和CSDN上学习到的一些有关该知识的讲解,我可以了解到Socket是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机的相关进程之间的数据交换。
实验的一个重点是涉及到了加密算法,不过这对我们密码系的同学来说是小意思(*•̀ᴗ•́*)و ,通过回忆袁征老师在密码学这堂课上讲解过的公钥加密以及对称加密有关知识,有了实现加密算法过程的理论基础。本次实验选择的是SM2公钥加密算法。SM2算法是一种新的国产非对称算法,相对于RSA算法,它更先进。基于国家商业密码安全等原因,国家密码管理部门正式全国范围内大力推广。
服务器
- 在网上以及书上查找公钥加密以及对称加密有关知识
- 通过了解有关知识,选择使用基于SM2的国产公钥算法进行加密
-
首先设置好 SM2 算法的相关环境,设置公钥和私钥
-
然后设置好服务器,等待客户端连接
-
接受 客户端的密文 ,进行解密
-
将解密后的明文 ,写入一个新建的文件里。
-
最后 ,输出新建文件中的内容,关闭服务器
源代码:
import socket
import base64
import binascii
from gmssl import sm2, func
#16进制的公钥和私钥
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key =
'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A
6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(
public_key=public_key, private_key=private_key)
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host = socket.gethostname()
port = 12345
s.bind((host,port))
s.listen(5)
new_s,addr = s.accept()
data = new_s.recv(1024)
#print(data)
dec_data =sm2_crypt.decrypt(data)
dec_data = dec_data.decode()
#print(dec_data)
name = input("请填写解密后明文的文件名称")
f = open(name,"w+")
f.write("
经服务器解密后的明文是:
")
f.write(dec_data)
f.close()
f = open(name,"r+")
f0 = f.readlines()
f0 = ''.join(f0)
print(f0)
f.close()
new_s.close()
运行程序,出现以下结果:
请填写解密后明文的文件名称 加密文件.txt
服务器解密后的明文是:
This is 20191212斯廷响
the file of client!!
可见,程序解密成功,再来设计客户端程序
客户端
- 先仿照上面的过程,了解此步骤SM2环境如何搭建
-
首先设置好 SM2 算法的相关环境,设置公钥和私钥
-
然后读取一个文件,对其内容进行加密,然后输出一下加密后结果给用户看一下
-
接下来,连接到服务器上,把密文发送给服务器
-
最后 ,关闭文件,关闭客户端
源代码:
import socket
import base64
import binascii
from gmssl import sm2, func
#16进制的公钥和私钥
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key =
'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF
331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(
public_key=public_key, private_key=private_key)
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host = socket.gethostname()
port = 12345
c.connect((host,port))
f = open(input("请输入文件名"),"r+")
f0 = f.readlines()
f0 = ''.join(f0)
data = f0
data = data.encode()
enc_data = sm2_crypt.encrypt(data)
print("加密后的密文是
{}".format(enc_data))
c.sendall(enc_data)
f.close()
c.close()
经过上述过程,完成了程序基本功能
3. 实验过程中遇到的问题和解决过程
- 问题1:编写完程序发现电脑上没有安装gmssl
- 问题1解决方案:通过查资料得知原来要更新pip,再用pip来安装对应的工具
- 问题2:SM2 算法怎么弄
- 问题2解决方案:在网上找了找资料
其他(感悟、思考等)
学习socket编程主要是编写网络程序,在很多的方面我们主要是针对于一个具体的网络协议来进行编程,首先必须分析这个网络协议的方方面面,然后使用socket来进行实现,无论这个网络协议是协议栈中已经存在的高层网络协议,还是自己在应用中设计出来的网络协议,都需要了解了网络协议在进行实现的。例如我们需要写一个邮件收发软件,只有了解了SMTP和POP协议才能使用socket或者winnet这些编程接口进行开发;写一个文件服务器或者客户端,也需要了解了计算机网络课程上的有关知识才能进行开发。
实际上,对于网络编程,在windows平台下,有几种网络编程接口,socket是一种,winnet也是一种,其是一个应用层的网络通信组件,它可以使你的应用程序很容易的实现http、ftp、gopher等协议而不需要你去深入的了解协议本身的规范。而之前,如果要想做类似的应用,我们必须了解socket编程并且要对协议本身非常熟悉,哪怕是一个非常非常简单的程序。当然了socket是比较灵活的,两种接口在用途上表现出来的优点也是不同的。
不同课堂上的知识在将来有可能在某些时候发生联动,在本次实验中,就使用了密码学课堂上学习过的公钥算法有关知识。这引起了我的思考,在将来的学习中,会不会有课程或者活动比赛也用的python课程上学习到底一些重要知识呢?所以,学好当前的每一门知识对于我们大学生将来的人生路都是有着十分积极的作用。
学会搜索很重要,我们现在遇到的很多问题,大多数都已经被别人解决过,并且答案已经被公开了。如果能学会搜索,那么多数问题都能得到解决,从而帮助我们
学习到更多的有关知识。学会使用百度等搜索引擎。
码云链接
https://gitee.com/besti2021python/stx20191212homework/blob/master/experiment3_1
https://gitee.com/besti2021python/stx20191212homework/blob/master/experiment3_2
参考资料
http://c.biancheng.net/socket/
https://blog.csdn.net/kimwu/article/details/14453569