• python-41-初识hmac与socketserver模块


    前言

    hmac:用来检验合法性,比如客户端后面发送一些请求,服务端要进行检验是否合法。

    基本逻辑:客户端生成一串密文发送给客户端接收,后面客户端发送请求的时候要先校验是否与客户端密文一致

    socketserver:是Python标准库中的一个高级模块,能实现多并发服务端。

    一、hmac 模块

    ①服务端:

    import socket,os,hmac
    sk=socket.socket()
    sk.bind(('127.0.0.1',9999))
    sk.listen()
    conn,addr=sk.accept()
    
    def exp():
        msg=os.urandom(32)              # 随机生成字节
        conn.send(msg)                  # 发送随机生成的字节
        digest=hmac.new(msg).digest()   # 生成密文给下面对比
        res_digest=conn.recv(1024)      # 接收客户端的密文
        res=hmac.compare_digest(digest,res_digest)   # 对比服务端与客户端的密文是否相等,返回bool
        return res
    res=exp()
    if res:
        print('合法请求')
        sk.close()
    else:
        print('不合法请求')
        sk.close()

    ②客户端:

    import socket,hmac
    sk=socket.socket()
    sk.connect(('127.0.0.1',9999))
    msg=sk.recv(1024)
    h=hmac.new(msg)
    digest=h.digest()
    sk.send(digest)
    sk.close()

    合法与不合法打印结果:

     二、socketserver 模块

    ①服务端:

    import socketserver
    class Mysevrer(socketserver.BaseRequestHandler):
        def handle(self):
            while 1:
                msg=self.request.recv(1024).decode('utf-8')
                if msg=='8':break
                print(msg)
                info=input('info send:')
                self.request.send(info.encode('utf-8'))
    
    if __name__ == '__main__':
        server=socketserver.ThreadingTCPServer(('127.0.0.1',9999),Mysevrer)
        server.serve_forever()

    ②客户端:

    import socket
    sk=socket.socket()
    sk.connect(('127.0.0.1',9999))
    while 1:
        msg=input('send:')
        if msg=='8':break
        sk.send(msg.encode('utf-8'))
        ret=sk.recv(1024).decode('utf-8')
        print(ret)
    sk.close()

     三、简单实现文件上传功能

    基于前一篇:struct模块定制报头ftp实战,注释有解析。

    基本逻辑:客户端获取文件大小,处理报头后告诉服务端,服务端每次接收一定字节数。

    ①服务端,接收:

    def sevrer(sk,ip,port,buffer=10240):
        sk.bind((ip, port))
        sk.listen()
        conn,addr=sk.accept()
    
        head_pack=conn.recv(4)                           # 先接收pack的4个字节
        head_len=struct.unpack('i',head_pack)[0]         # unpack解字节后得到一个元组,取第[0]个即可
        head=conn.recv(head_len).decode('utf-8')         # bytes报头内容
        head_loads=json.loads(head)                      # json报头内容
        FlieSize=head_loads['FlieSize']                  # 取json报头内容中FlieSize对应的值
        with open(head_loads['FlieName'],'wb')as f:      # 创建文件,名称=json报头内容中FlieName对应的名称
            while FlieSize:                              # 如果FlieSize有数值
                if FlieSize>=buffer:                     # 大于等于buffer,给下面直接写入buffer个字节
                    f.write(conn.recv(buffer))           # 写入buffer个字节
                    FlieSize-=buffer                     # FlieSize每次减少buffer个字节
                else:                                    # 如果小于buffer个字节,直接读完
                    f.write(conn.recv(buffer))           # 读取完毕,退出循环
                    break
        conn.close()
        sk.close()                                       # 结束,关闭连接
    
    if __name__ == '__main__':
        import socket, struct, json
        sk = socket.socket()
        sevrer(sk,ip='127.0.0.1',port=8888)

    ②客户端,上传:

    def client(sk,FlieName,FliePath,buffer=10240):
    
        head={
            'FlieName': FlieName,                                     # 文件名
            'FliePath': FliePath,                                     # 文件目录
            'FlieSize': None,}                                        # 文件大小为空
        cur_path=os.path.join(head['FliePath'],head['FlieName'])      # 拼接文件路径
        FlieSize=os.path.getsize(cur_path)                            # 获取文件字节大小
        head['FlieSize']=FlieSize                                     # 将文件大小传入head字典
        head_bytes=json.dumps(head).encode('utf-8')                   # 序列化
        head_len=len(head_bytes)                                      # 报头的长度
        head_pack=struct.pack('i',head_len)                           # pack为4个字节长度
        sk.send(head_pack)                                            # 发送pack的4个字节
        sk.send(head_bytes)                                           # 发送bytes类型报头
        with open(cur_path,'rb')as f:                                 # 打开拼接路径的文件
            while FlieSize:                                           # 如果FlieSize有数值
                if FlieSize>=buffer:                                  # 大于等于buffer,给下面直接写入buffer个字节
                    sk.send(f.read(buffer))                           # 写入buffer个字节
                    FlieSize-=buffer                                  # FlieSize每次减少buffer个字节
                else:
                    sk.send(f.read(buffer))                           # 如果小于buffer个字节,直接读完
                    break                                             # 读取完毕,退出循环
        sk.close()                                                    # 关闭连接
        return FlieSize
    
    if __name__ == '__main__':
        import socket, struct, os, json
        sk = socket.socket()
        sk.connect(('127.0.0.1',8888))
    
        FlieName=r'bash教程.pdf'
        FliePath=r'C:UsersAdministratorDesktop'
        print('上传成功,总共字节:',client(sk,FlieName,FliePath))

     欢迎来大家QQ交流群一起学习:482713805

  • 相关阅读:
    python 进程
    python 网络编程
    Tensorflow学习教程------参数保存和提取重利用
    Tensorflow学习教程------利用卷积神经网络对mnist数据集进行分类_利用训练好的模型进行分类
    Tensorflow学习教程------利用卷积神经网络对mnist数据集进行分类_训练模型
    Tensorflow学习教程------tensorboard网络运行和可视化
    Tensorflow学习教程------过拟合
    Spring的@Value注解为静态变量赋值
    Linux使用scp远程拷贝使用ssh免密登录
    Mysql升级5.7.10后GROUP BY语句出错解决方法
  • 原文地址:https://www.cnblogs.com/gsxl/p/12577021.html
Copyright © 2020-2023  润新知