1. 前言
TCP启的socket server端是不能同时跟多个client进行通信的,但是现在我们可以使用一个模块socketserver模块来帮助我们完成这个功能:
2. socketserver实现server和多个client同时通信
# server.py import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): while True: ret=self.request.recv(1024).decode("utf-8") print(ret) info=input(">>>") self.request.send(bytes(info.encode("utf-8"))) if __name__=="__main__": server=socketserver.ThreadingTCPServer(("127.0.0.1",8080),Myserver) server.serve_forever()
# client.py import socket sk=socket.socket() sk.connect(("127.0.0.1",8080)) while True: info=input(">>>") sk.send(bytes(("来自璇璇的消息:"+info).encode("utf-8"))) ret=sk.recv(1024).decode("utf-8") print(ret) sk.close()
# client2.py import socket sk=socket.socket() sk.connect(("127.0.0.1",8080)) while True: info=input(">>>") sk.send(bytes(('来自嘻嘻的消息:'+info).encode("utf-8"))) ret=sk.recv(1024).decode("utf-8") print(ret) sk.close()
3. 使用socketserver 使得server与多个client 交互之前 使用hmac对客户端进行验证
# server.py import os import socketserver # 由于TCP起的server同一时间不能跟多个客户端通信,socketserver模块刚好解决了该问题 import hmac # server端和合法的客户端有相同的密钥,server端给客户端发送要加密的bytes类型 # 客户端也使用hmac进行加密,将结果返回给server端,server端比较两个加密的结果 secret_key=b"xuanxuan" # server和合法的客户端之间的密钥(约定好的,双方都已知的) class MyServer(socketserver.BaseRequestHandler): # 自己定义的类Myserver必须要继承BaseRequestHandler def handle(self): # 该类中必须要定义的方法 msg=os.urandom(32) # 随机生成一个32位的字节,用于发送给client端,进行验证(配合密钥) self.request.send(msg) # self.request相当于socket中的conn表示一个连接 h=hmac.new(secret_key,msg) # 获得需要加密的对象 一个是双方约定好的密钥 ,另一个是随机生成的bytes类型的需要加密的信息 digest=h.digest() # 加密 client_digest=self.request.recv(1024) ret=hmac.compare_digest(digest,client_digest) if ret: while True: ret=self.request.recv(1024).decode("utf-8") print(ret) info=input(">>>") self.request.send(bytes(info.encode("utf-8"))) else: print("不合法的客户端,我要断开连接") if __name__=="__main__": server=socketserver.ThreadingTCPServer(("127.0.0.1",8080),MyServer) # 必须要传两个参数 IP地址 端口号,还有上面定义的类名 server.serve_forever() # 永久起一个服务
# client.py import socket import hmac secret_key=b"xuanxuan" # 跟server端的密钥一样,是合法的客户端 sk=socket.socket() sk.connect(("127.0.0.1",8080)) msg=sk.recv(1024) # hmac.new()操作的对象都是bytes类型的,所以先不解码啦 h=hmac.new(secret_key,msg) client_digest=h.digest() sk.send(client_digest) # 把加密后的给server端发过去 while True: info=input(">>>") sk.send(bytes(("来自客户端1的消息:"+info).encode("utf-8"))) ret=sk.recv(1024).decode("utf-8") print(ret) sk.close()
# client2.py import socket import hmac secret_key=b"xuan" # 跟server端的密钥不一样,不是合法的客户端 sk=socket.socket() sk.connect(("127.0.0.1",8080)) msg=sk.recv(1024) # hmac.new()操作的对象都是bytes类型的,所以先不解码啦 h=hmac.new(secret_key,msg) client_digest=h.digest() sk.send(client_digest) # 把加密后的给server端发过去 while True: info=input(">>>") sk.send(bytes(("来自客户端2的消息:"+info).encode("utf-8"))) ret=sk.recv(1024).decode("utf-8") print(ret) sk.close()
我们先启动server 和 client1:
server和client可以正常建立连接,但是当启动client2时(不合法的客户端,因为密钥不一样)server端就会立即中止连接(这里我只是完成了打印)