python学习笔记 day33 socketserver模块--解决TCP不能同时跟多个client同时通信的问题

时间:2022-12-24 23:57:04

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:
python学习笔记 day33 socketserver模块--解决TCP不能同时跟多个client同时通信的问题

 

 python学习笔记 day33 socketserver模块--解决TCP不能同时跟多个client同时通信的问题

 

 server和client可以正常建立连接,但是当启动client2时(不合法的客户端,因为密钥不一样)server端就会立即中止连接(这里我只是完成了打印)
python学习笔记 day33 socketserver模块--解决TCP不能同时跟多个client同时通信的问题