python-41-初识hmac与socketserver模块

Posted 广深-小龙 --扬帆起航!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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:\\Users\\Administrator\\Desktop\'
    print(\'上传成功,总共字节:\',client(sk,FlieName,FliePath))

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

以上是关于python-41-初识hmac与socketserver模块的主要内容,如果未能解决你的问题,请参考以下文章

SocketServer模块,hmac模块验证client合法性

HMAC 256 与 HMAC 512 JWT 签名加密

信息摘要算法之五:HMAC算法分析与实现

HMAC与CMAC

python实现HMAC算法与应用

验证链接合法性(hmac)