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


    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端就会立即中止连接(这里我只是完成了打印)

    talk is cheap,show me the code
  • 相关阅读:
    B树和B+树的区别
    宏(腾讯)
    数组作为函数参数传递时退化为指针(腾讯)
    求已知表达式的后缀形式(腾讯)
    JAVA笔记12-接口interface
    JAVA笔记11-Final关键字
    JAVA笔记10-抽象类
    JAVA笔记9-多态(动态绑定、池绑定)
    JAVA笔记8-对象转型casting
    JAVA笔记7-Object类之toString方法和equals方法
  • 原文地址:https://www.cnblogs.com/xuanxuanlove/p/9750877.html
Copyright © 2020-2023  润新知