110
社区成员
发帖
与我相关
我的任务
分享课程:《Python程序设计》
班级: 2322
姓名: 刘天择
学号:20232210
实验教师:王志强
实验日期:2024年4月20日
必修/选修: 公选课
创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。
socket模块允许程序在网络上进行通信,它提供了一种统一的接口,用于在不同平台上的计算机之间传递数据。
流式套接字(SOCK_STREAM):用于提供面向连接、可靠的数据传输服务。(TCP)
数据报套接字(SOCK_DGRAM):提供了一种无连接的服务。(UDP)
在Python中,socket模块封装了底层的操作系统接口,提供了简单而强大的套接字(socket)接口。
一般的创建TCP服务流程:
ss = socket() # 创建服务器套接字
ss.bind(ADDR) # 套接字与地址绑定
ss.listen() # 监听连接
while True: # 服务器无限循环
cs = ss.accept() # 接受客户端连接
comm_loop: # 通信循环
cs.recv()/cs.send() # 对话(接收 / 发送)
cs.close() # 关闭客户端套接字
ss.close() # 关闭服务器套接字
一般的创建TCP客户端流程:
cs = socket() # 创建客户端套接字
cs.connect() # 尝试连接服务器
comm_loop: # 通信循环
cs.send()/cs.recv() # 对话(发送 / 接收)
cs.close() # 关闭客户端套接字
借用了室友的电脑,模拟客户端与服务端的通信
启动并初始化服务端
# 默认的最大等待数量为5
# 默认使用本机的ip地址和8080端口
def __init__(self, backlog=5, addr=('localhost', 8080)):
# 默认使用AF_INET协议族,即ipv4地址和端口号的组合以及tcp协议
self.serverSocket = socket.socket()
# 绑定监听的ip地址和端口号
self.serverSocket.bind(addr)
# 开始等待
self.serverSocket.listen(backlog)
# 该函数需要并行处理
def link_one_client(self):
# 获取客户端对象和客户端地址
clientSocket, addr = self.serverSocket.accept()
# 客户端数量加1
Server.number = Server.number + 1
# 标记当前客户端编号
now_number = Server.number
# 打印
print("和客户端{0}建立连接\n目标主机地址为:{1}".format(now_number, addr))
# 接受客户端传递的公钥
# 这里可以加一个哈希函数检验公钥的正确性!
# 运用pickle进行反序列化
publicKeyPK, pubKeySha256 = pickle.loads(clientSocket.recv(1024))
if hashlib.sha256(publicKeyPK).hexdigest() != pubKeySha256:
raise AuthenticationError("密钥被篡改!")
else:
publicKey = pickle.loads(publicKeyPK)
print("已接受公钥")
# 下面是用公钥加密对称密钥并传递的过程
# 产生用于对称加密的密钥
sym_key = Fernet.generate_key()
# 用pickle进行序列化用来进行网络传输
# 对密钥进行hash保证其准确性
en_sym_key = rsa.encrypt(pickle.dumps(sym_key), publicKey)
en_sym_key_sha256 = hashlib.sha256(en_sym_key).hexdigest()
print("正在加密传送密钥")
clientSocket.send(pickle.dumps((en_sym_key,en_sym_key_sha256)))
# 这里可以添加密钥交换成功的函数
# 初始化加密对象
f = Fernet(sym_key)
# 下面使用对称密钥进行加密对话的过程
while True:
time.sleep(0.3)
# 接收到的加密消息
en_recvData = clientSocket.recv(1024)
recvData = f.decrypt(en_recvData).decode()
print("接受到客户端{0}传来的消息:{1}".format(now_number, recvData))
# 调用图灵机器人
sendData = get_reply(recvData)
# 对消息进行加密
en_sendData = f.encrypt(sendData.encode())
clientSocket.send(en_sendData)
启用并初始化客户端
class Client:
def __init__(self):
# 产生非对称密钥
self.asyKey = rsa.newkeys(2048)
# 公钥和私钥
self.publicKey = self.asyKey[0]
self.privateKey = self.asyKey[1]
def link_server(self, addr=('localhost', 8080)):
# 创建socket通信对象
# 默认使用AF_INET协议族,即ipv4地址和端口号的组合以及tcp协议
clientSocket = socket.socket()
# 默认连接服务器地址为本机ip和8080端口
clientSocket.connect(addr)
# 向服务器传递公钥,和该公钥字符串化后的sha256值
print("正在向服务器传送公钥")
sendKey = pickle.dumps(self.publicKey)
sendKeySha256 = hashlib.sha256(sendKey).hexdigest()
clientSocket.send(pickle.dumps((sendKey, sendKeySha256)))
# 接受服务器传递的密钥并进行解密
symKey, symKeySha256 = pickle.loads(clientSocket.recv(1024))
if hashlib.sha256(symKey).hexdigest() != symKeySha256:
raise AuthenticationError("密钥被篡改!")
else:
self.symKey = pickle.loads(rsa.decrypt(symKey, self.privateKey))
print("密钥交换完成")
# 初始化加密对象
f = Fernet(self.symKey)
while True:
sendData = input("输入你要发送的消息:")
en_sendData = f.encrypt(sendData.encode())
clientSocket.send(en_sendData)
en_recvData = clientSocket.recv(1024)
recvData = f.decrypt(en_recvData).decode()
print("接受到服务器传来的消息:{0}".format(recvData))
首先客户端和服务器端建立连接,客户端产生非对称密钥,将公钥传送给服务器端,服务器端检查后通过公钥将对称密钥进行加密并传送给客户端
客户端接收到密钥并进行解密,双方开始通信
王老师代码真的好难看也看不懂TAT