欢迎来到JIA的博客

我的python学习之路-tup/udp/hashlib/hmac

本节内容:

  一.网络基本概念

    1.1.网络的开发的两大结构

      1. 2.网段

    1.3.端口

    1.4.osi网络七层模型

    1.5.交换机 和 路由器

      1.6.TCP / UDP 协议

  二、TCP 和 UDP 用法

    2.1 TCP的基本用法

    2.2 TCP循坏发送消息

    2.3 UDP的基本用法

    2.4 UDP循环发送消息

    2.5 黏包

  三、socketserver 使用

    3.1 基本用法

    3.2 循环发送消息

  四、 加密模块的使用

    4.1 hashlib模块使用

    4.2 hmac 模块使用

    4.3 文件校验

    4.4 服务器校验的合法性

 

 

 

 

一、网络基本概念

1、网络开发的两个架构                   

1.C/S架构

                     

    

2.B/S 架构

               

一台主机有两个重要标识:
(1)mac地址:标记一台机器的物理地址 (不可变)
(2)ip 地址:#标记一台机器的逻辑地址 (可变)

2、网段

网段

主要用来划分同一区域里的某些机器是否能够互相通信。

在一个网段里可以不同过因特网,直接对话

子网掩码:
区分网段和主机

判别的依据:
如果IP地址和子网掩码相与得到的值相同就是同一网段

3.端口   

通过ip+端口号 : 可以找到世界上任何一个主机下的一个应用(软件) => 192.168.33.81:80
0~65535 : 自定义端口时,不要使用知名厂商已经用过的端口号, 起8000以上端口号,避免冲突

20  FTP=>文件传输协议(默认数据口)
21  FTP=>文件传输协议(控制)
22  SSH远程登录协议 (xshell , putty)
25  SMTP服务器所开放的端口,用于发送邮件
80  http,用于网页浏览,木马Executor开放此端口
443 https , 基于http,对数据进行加密传输
3306 MySQL开放此端口

 

4. osi 网络七层模型

 

应用层:(应用层,表示层,会话层)
  封装数据:
    根据不同的协议,封装不同个数的数据
    http (超文本传输协议)
    https (加密传输的超文本传输协议)
    FTP (文件传输协议)
    SMTP (邮件传输协议)

传输层:
  封装端口:
    指定传输协议(TCP协议/UDP协议)

网络层:
  封装ip:
    ipv4 / ipv6

数据链路层:
  封装mac地址:
    指定mac地址(arp协议[ip->mac] rarp协议[mac->ip])

物理层:
  打成数据包,变成二进制字节流,通过网络进行传输

 

5.交换机 和 路由器

交换机:对同一网段的不同机器之间进行数据转发的设备 [每一台机器和交换机相连,形成通信]
路由器:对不同网段的不同机器之间进行数据转发的设备 [每一个局域网和路由器相连,形成通信]

交换机 : 从下到上拆2层,拆到数据链路层 (转发内网数据)
路由器 : 从下到上拆3层,拆到网络层 (转发外网数据)

arp协议:每台主机都有arp缓存表 ,主要作用通过ip找mac的一个协议规则
           【实现方式:通过交换机一次广播,一次单播找到的】

arp协议: 通过ip->mac
rarp协议: 通过mac->ip

arp协议完整过程:
电脑a发现目标主机没有mac,标记全F广播地址,发送arp广播包,给了交换机
交换机接受arp广播包,从下到上拆2层,拆到数据链路层,发现是全F的广播地址,此时开始广播,给所有连接在这个交换机的设备发一份arp广播包
每台主机在接收到arp广播包后,开始拆包,如果不归属于自己,该数据包自动舍弃
路由器得到arp广播包后,从下到上拆包,拆三层到网络层,获取到ip,解析出对应的网段信息;打开路由器信息表找对应的网关(路由器层面)
把arp广播包发送给对应网关的交换机
交换机拿到数据之后,从下到上拆2层,发现全F广播地址,在广播.
数据库得到广播包之后,从下到上进行拆包,发现要找的这个主机,就是自己.
此时,把对应ip->mac的数据返回给交换机,
交换机拿到该数据之后,进行单播,返回给数据的原发送方
原数据发送发拿到数据后,更新自己的arp解析表,方便下次使用

 

6.TCP / UDP 协议

TCP(Transmission Control Protocol)一种面向连接的、可靠的、传输层通信协议(比如:打电话)
优点:可靠,稳定,传输完整稳定,不限制数据大小
缺点:慢,效率低,占用系统资源高,一发一收都需要对方确认
应用:Web浏览器,电子邮件,文件传输,大量数据传输的场景

UDP(User Datagram Protocol)一种无连接的,不可靠的传输层通信协议(比如:发短信)
优点:速度快,可以多人同时聊天,耗费资源少,不需要建立连接
缺点:不稳定,不能保证每次数据都能接收到(大数据不稳定)
应用:IP电话,实时视频会议,聊天软件,少量数据传输的场景

客户端和服务端在建立连接时: 三次握手
客户端和服务端在断开连接时: 四次挥手
SYN 创建连接
ACK 确认响应
FIN 断开连接

 

TCP 三次握手:

特点: 先建立连接 , 在发送数据

建立连接 (三次握手)

客户端发送一个请求消息,与服务端建立连接
服务端接受请求,发出响应,回复客户端,与客户端建立连接的一个请求;
客户端接受服务端的响应消息后,发送回复消息(表达同意)
到此,客户端和服务端真正的建立了连接,接下来开始发送数据.

 

 

 

发送数据 特点:有回执消息
每发送一个数据,都会对应有回执消息.如果没有回执消息,会把该数据在发送一次(保证数据的稳定,可靠,不丢包)

断开连接 (四次挥手)
等双方都没有数据要互发,断开连接,所以是4次挥手; 特点:最大等待2msl 大概1分钟;
客户端向服务端发送一个断开连接的请求(代表客户端已经没有数据发送给服务端)
服务端接受请求,发出响应 (回复好的)
等到服务端彻底把数据发送完毕之后,
服务端向客户端发送一个断开连接的请求,
客户端接受请求,发出响应 (回复好的)
双方彻底断开连接.

 

 

二、TCP 和 UDP 用法

1、TCP的基本用法

(1)客户端

# ### 客户端
import socket
# 1.创建一个socket对象
sk = socket.socket()
# 2.与服务端建立连接
sk.connect( ("127.0.0.1",8001) )
# 3.发送数据(二进制的字节流)
sk.send("地狱空荡荡,魔鬼在人间,但行好事,莫问前程".encode("utf-8"))
# 4.关闭连接
sk.close()

(2)服务器端

 1 # ### 服务端
 2 """必须注意:一发一收需要成对,否则出现数据异常"""
 3 import socket
 4 # 1.创建socket对象
 5 sk = socket.socket()
 6 # 2.绑定对应的ip和端口号(注册网络,让其他电脑可以访问到该主机)
 7 # 127.0.0.1 默认本地ip , 参数为一个元组
 8 sk.bind( ("127.0.0.1",8001) )
 9 # 3.开启监听
10 sk.listen()
11 
12 # 4.建立三次握手
13 conn,addr = sk.accept()
14 
15 print("<======1=====>")
16 print(conn)
17 print(addr)
18 """
19 conn : <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8001), raddr=('127.0.0.1', 45466)>
20 addr : ('127.0.0.1', 45466)
21 """
22 print("<======2=====>")
23 
24 # 5.处理收发数据的逻辑
25 res = conn.recv(1024) # 最多一次接受1024个字节
26 print(res.decode("utf-8"))
27 
28 # 6.四次挥手
29 conn.close()
30 # 7.退还端口
31 sk.close()
View Code

 

2、TCP循环发送消息

 1 # ### 客户端
 2 import socket
 3 # 1.创建socket对象
 4 sk = socket.socket()
 5 # 2.连接服务端
 6 sk.connect( ("127.0.0.1",8001) )
 7 # 3.处理收发数据的逻辑
 8 
 9 while True:
10     # 发送数据
11     strvar = input("请输出您要发送的数据[客户端]>>>")
12     sk.send(strvar.encode())
13 
14     # 接受数据
15     res = sk.recv(1024)
16     
17     if res == b'q' or  res == b"Q":
18         break
19     
20     print(res.decode())
21 
22 # 4.关闭连接
23 sk.close()
客户端
 1 # ### 服务端
 2 import socket
 3 # 1.创建socket对象
 4 sk = socket.socket()
 5 
 6 # 让一个端口重复绑定多个程序(仅限在测试环节)
 7 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 8 
 9 
10 # 2.绑定ip端口号(在网络中注册该主机)
11 sk.bind( ("127.0.0.1",8001) )
12 # 3.开启监听
13 sk.listen()
14 
15 while True:
16 
17     # 4.建立三次握手
18     conn,addr = sk.accept()
19     # 5.处理收发数据的逻辑
20 
21     while True:
22         # 接受数据
23         res = conn.recv(1024)
24         print(res,type(res))
25         print(res.decode())
26 
27         # 发送数据
28         strvar = input("请输出您要发送的数据[服务端]>>>")
29         conn.send(strvar.encode())
30         
31         if strvar.upper() == "Q":
32             break
33 
34     # 6.四次挥手
35     conn.close()
36     
37     
38 # 7.退还端口
39 sk.close()
服务器端

3、UDP的基本用法

 1 # ### 客户端
 2 import socket
 3 # 1.创建udp对象
 4 sk = socket.socket(type=socket.SOCK_DGRAM)
 5 # 2.收发数据的逻辑
 6 
 7 # 发送数据
 8 msg = "你好么老婶~"
 9 # sendto( 数据[二进制字节流]  ,  (ip,端口号)  )
10 sk.sendto(   msg.encode() ,  ("127.0.0.1",8005)    )
11 
12 # 接受数据
13 msg,ser_addr = sk.recvfrom(1024)
14 print(msg.decode())
15 print(ser_addr)
16 
17 # 3.关闭连接
18 sk.close()
客户端
 1 # ### 服务端
 2 import socket
 3 # 1.创建udp对象
 4 sk = socket.socket(type=socket.SOCK_DGRAM)
 5 # 2.绑定ip端口号
 6 sk.bind( ("127.0.0.1",8005) )
 7 # 3.针对于udp服务器,第一次只能接受数据
 8 
 9 # 接受数据
10 msg,cli_addr = sk.recvfrom(1024)
11 print(msg.decode()) # 你好么老婶~
12 print(cli_addr)     # ('127.0.0.1', 46190)
13 
14 
15 # 发送数据
16 msg = "我是你妈妈"
17 sk.sendto(   msg.encode() ,  cli_addr    )
18 
19 # 4.关闭连接
20 sk.close()
服务器端

4、UDP循环发送消息

 1 # ### 客户端
 2 import socket
 3 # 1.创建udp对象
 4 sk = socket.socket(type=socket.SOCK_DGRAM)
 5 
 6 # 2.处理收发数据的流程
 7 while True:
 8     # 发送数据
 9     message = input("请输入要发送的内容[客户端]")
10     sk.sendto(  message.encode()  ,  ("127.0.0.1",8005)   )
11     
12     # 接受数据
13     msg , ser_addr = sk.recvfrom(1024)
14     print(msg.decode())
15 
16 # 3.关闭连接
17 sk.close()
客户端
 1 # ### 服务端
 2 import socket
 3 # 1.创建udp对象
 4 sk = socket.socket(type=socket.SOCK_DGRAM)
 5 # 2.绑定ip端口号
 6 sk.bind( ("127.0.0.1",8005) )
 7 
 8 # 3.针对于udp服务器,第一次只能接受数据 ,处理收发数据的流程
 9 while True:
10     # 接受数据
11     msg,cli_addr = sk.recvfrom(1024)
12     print(msg.decode())
13     print(cli_addr)
14     
15     # 发送数据
16     message = input("请输入要发送的内容[服务端]")
17     sk.sendto(message.encode() , cli_addr)
18     
19 
20 # 4.关闭连接
21 sk.close()
22 
23 
24 """
25 tcp : 默认是1对1, 默认必须等待连接断开之后,下个客户端才能连接
26 udp : 默认1对多,不需要建立连接,即可发送或者接受数据
27 """
服务器端

 

 5、黏包

(1)造成原因

 1 # ### 客户端
 2 import socket
 3 import time
 4 sk = socket.socket()
 5 sk.connect( ("127.0.0.1",8001) )
 6 
 7 
 8 # [接收端]出现黏包: 接受数据太慢了
 9 # 处理收发数据的逻辑
10 # 1024 最多接受1024个字节
11 time.sleep(3)
12 res1 = sk.recv(1024)
13 print(res1.decode(),"1111")
14 res2 = sk.recv(1024)
15 print(res2.decode(),"2222")
16 
17 sk.close()
客户端
 1 # ### 服务端
 2 import socket
 3 import time
 4 sk = socket.socket()
 5 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 6 sk.bind( ("127.0.0.1",8001) )
 7 sk.listen()
 8 conn,addr = sk.accept()
 9 
10 
11 # [发送端]出现黏包: 1.数据太小, 2.数据之间时间间隔太短了;
12 # 处理收发数据的逻辑
13 conn.send("feifei".encode())
14 time.sleep(1)
15 conn.send("你站起来".encode())
16 
17 
18 conn.close()
19 sk.close()
服务器端

(2)解决方法

 1 # ### 客户端
 2 import socket
 3 sk = socket.socket()
 4 sk.connect( ("127.0.0.1",8001) )
 5 
 6 # 处理收发数据的逻辑
 7 # 1024 最多接受1024个字节
 8 
 9 # 第一步,先接受接下来要发送的数据
10 res = sk.recv(1)
11 num = int(res.decode()) # 6
12 
13 # 第二步,接受真实的数据[feifei]
14 res1 = sk.recv(num)
15 print(res1.decode(),"1111")
16 
17 # 第三步,接受真实的数据[你站起来]
18 res2 = sk.recv(1024)
19 print(res2.decode(),"2222")
20 
21 sk.close()
客户端
 1 # ### 服务端
 2 import socket
 3 import time
 4 sk = socket.socket()
 5 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 6 sk.bind( ("127.0.0.1",8001) )
 7 sk.listen()
 8 conn,addr = sk.accept()
 9 
10 # 处理收发数据的逻辑
11 # 第一步,先把接下来要发送的数据的字节大小传过去
12 conn.send("6".encode())
13 
14 # 第二步,发送真实的数据[feifei]
15 conn.send("feifei".encode())
16 
17 # 第三步,发送真实的数据[你站起来]
18 conn.send("你站起来".encode())
19 
20 
21 
22 conn.close()
23 sk.close()
服务端

(3)struct 模块

pack 打包
把任意长度数字转换成具有固定4个字节长度的字节流
unpack 解包
把4个字节长度的值恢复成原来的数字,返回是元组

 1 import struct
 2 # pack
 3 # i => int 要转换的当前类型是整型
 4 res = struct.pack("i" , 191992131)
 5 print( res  ,  len(res))
 6 
 7 res = struct.pack("i" , 1)
 8 print( res  ,  len(res))
 9 
10 res = struct.pack("i" , 233241)
11 print( res  ,  len(res))
12 
13 # -2147483648 <= number <= 2147483647 长度在-21个亿 ~ 21个亿左右 大概不到1.9g的数据
14 res = struct.pack("i" , 9999999999)
15 print( res  ,  len(res))
16 
17 
18 # unpack
19 # i => 把对应的数据转换成整型
20 tup = struct.unpack("i",res)
21 res = tup[0]
22 print(res , type(res))
23 print(tup , type(tup))
View Code

(4)优化方法

 1 # ### 客户端
 2 import socket
 3 import struct
 4 sk = socket.socket()
 5 sk.connect( ("127.0.0.1",8001) )
 6 
 7 # 处理收发数据的逻辑
 8 # 第一次接受数据的大小
 9 num = sk.recv(4)
10 print(num)
11 tup = struct.unpack("i",num)
12 num = tup[0]
13 
14 # 第二次接受真实的数据,按照num这么大截取
15 res = sk.recv(num)
16 print(res.decode())
17 
18 # 第三次接受真实的数据
19 res = sk.recv(1024)
20 print(res.decode())
21 
22 
23 sk.close()
客户端
 1 # ### 服务端
 2 import socket
 3 import time
 4 import struct
 5 sk = socket.socket()
 6 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
 7 sk.bind( ("127.0.0.1",8001) )
 8 sk.listen()
 9 conn,addr = sk.accept()
10 
11 # 处理收发数据的逻辑
12 strvar = input("请输入您想要发送的数据:[服务端]")
13 # 先发送这个数据的大小
14 msg = strvar.encode()
15 res = len(msg)
16 print(res)
17 
18 res_bytes = struct.pack("i",res)
19 
20 # 第一次发送数据的大小
21 conn.send(res_bytes)
22 
23 # 第二次发送真实的数据
24 conn.send(msg)
25 
26 # 第三次发送真实的数据
27 conn.send("飞飞,旁边的自豪你也站起来吧~".encode())
28 
29 conn.close()
30 sk.close()
服务器端

 

 三、socketserver 使用

 1、基本用法

# ### 客户端
import socket
sk = socket.socket()
sk.connect( ("127.0.0.1",8005) )
# 写处理收发数据的逻辑
sk.close()
# ### 服务端
import socketserver

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        print("handler这个方法触发了 ... ")
        
# ThreadingTCPServer( (ip,端口号) , 自定义类 )
server = socketserver.ThreadingTCPServer( ("127.0.0.1",8005) , MyServer )
server.serve_forever()

2、循环发送消息

 1 # ### 客户端
 2 import socket
 3 sk = socket.socket()
 4 sk.connect( ("127.0.0.1",8005) )
 5 
 6 # 写处理收发数据的逻辑
 7 while True:
 8     # 发送数据
 9     sk.send(b"i love you")
10     # 接受数据
11     res = sk.recv(1024)
12     print(res.decode())
13 sk.close()
客户端
 1 # ### 服务端
 2 """支持TCP协议下的多线程并发,一个服务端同时连接多个客户端"""
 3 import socketserver
 4 
 5 class MyServer(socketserver.BaseRequestHandler):
 6     def handle(self):
 7         print("handler这个方法触发了 ... ")
 8         """
 9         print(self.request)
10         print(self.client_address)
11         conn: <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8005), raddr=('127.0.0.1', 54606)>
12         add : ('127.0.0.1', 54606)
13         """
14         conn = self.request
15         while True:
16             # 接受数据
17             res = conn.recv(1024)
18             res2 = res.decode()
19             print(res2)
20             # 发送数据
21             conn.send(res2.upper().encode())
22 
23         
24 # ThreadingTCPServer( (ip,端口号) , 自定义类 )
25 server = socketserver.ThreadingTCPServer( ("127.0.0.1",8005) , MyServer )
26 server.serve_forever()
服务器端

四、加密模块的使用

1 、hashlib模块使用

(1)md5算法

md5算法 : 可以把字符串变成具有固定长度的32位十六进制字符串
加密之后,不能反解

 1 import hashlib
 2 import random
 3 # 一.md5算法
 4 # 1.创建md5对象
 5 hs = hashlib.md5()
 6 # 2.把要加密的数据放到新的对象里,update(参数:二进制字节流)
 7 hs.update("111".encode("utf-8"))
 8 # 3.获取十六进制 32为长度字符串
 9 res = hs.hexdigest()
10 print(res , len(res))
11 
12 # 加盐 (加key,加关键字)
13 hs = hashlib.md5("XboyWW".encode())
14 hs.update("111".encode())
15 res = hs.hexdigest()
16 # 848ace59d5c61fc6b202db5301fbafa1 32
17 print(res , len(res))
18 
19 # 动态加盐 (动态加盐)
20 res = str(random.randrange(300,500000))
21 hs = hashlib.md5(res.encode())
22 hs.update("xboyaa".encode())
23 res = hs.hexdigest()
24 print(res , len(res))
View Code

(2) sha系列算法

# 二.sha系列算法
hs = hashlib.sha256() # 64位长度
hs = hashlib.sha512() # 128位长度
hs.update("111222".encode()) 
res = hs.hexdigest()
print(res , len(res)) 

2、hmac加密算法 (推荐)

1、基本语法

import hmac
key = b"aa"
msg = b"111222"
# 语法: new(盐(二进制字节流) ,密码(二进制字节流) )
hm = hmac.new(key,msg)
# 返回32位长度的十六进制字符串
res = hm.hexdigest()
print(res , len(res))

2、动态加盐

# 随机二进制字节流
import os
# os.urandom(位数) 返回随机的二进制字节流,长度由位数决定
res = os.urandom(32)
print(res , len(res))

# hmac动态加盐效果
key = os.urandom(32)
msg = b"123"
hm = hmac.new(key,msg)
res = hm.hexdigest()
print(res , len(res))

3 文件校验

(1) 针对于小文件的内容,进行校验

def check_md5(filename):
    hs = hashlib.md5()
    with open(filename , mode="rb") as fp:
        hs.update(fp.read())
    return hs.hexdigest()
    
res1 = check_md5("ceshi1.py")
res2 = check_md5("ceshi2.py")
print(res1 , res2)

(2) 针对于大文件的内容,进行校验

结论:update方法,可以把一个字符串拆解成多分

进行分开加密,得出的结果和作为一个整体加密的值是一致的;

1 # 写法一
2 hs = hashlib.md5()
3 strvar = "全球疫情肆虐,我们出门要带口罩"
4 hs.update(strvar.encode())
5 print(hs.hexdigest()) # 98bf8735876269b1750c997f330017c9
1 # 写法二
2 hs = hashlib.md5()
3 strvar1 = "全球疫情肆虐,"
4 hs.update(strvar1.encode())
5 strvar2 = "我们出门要带口罩"
6 hs.update(strvar2.encode())
7 print(hs.hexdigest()) # 98bf8735876269b1750c997f330017c9
 1 def check_md5(filename):
 2     hs = hashlib.md5()
 3     with open(filename , mode="rb") as fp:
 4         while True:
 5             # 一次最多读取10个字节
 6             content = fp.read(10)
 7             if content:
 8                 hs.update(content)
 9             else:
10                 break
11                 
12         return hs.hexdigest()
13     
14 res1 = check_md5("ceshi1.py")
15 res2 = check_md5("ceshi2.py")
16 print(res1 == res2)
大文件校验方法一
 1 import os 
 2 def check_md5(filename):
 3     hs = hashlib.md5()
 4     filesize = os.path.getsize(filename)
 5     print(filesize)
 6     with open(filename , mode="rb") as fp:
 7         # 一次减去最多10个字节,直到filesize = 0的时,循环终止了;
 8         while filesize:
 9             # 一次最多读取10个字节 3
10             content = fp.read(10)
11             hs.update(content)
12             filesize -= len(content)
13         return hs.hexdigest()
14     
15 res1 = check_md5("ceshi1.py")
16 res2 = check_md5("ceshi2.py")
17 print(res1 == res2)
大文件校验方法二

4、服务器校验的合法性

 1 # ### 服务端1
 2 import socket
 3 import hmac
 4 
 5 sk = socket.socket()
 6 sk.connect( ("127.0.0.1" , 8003) )
 7 
 8 
 9 # 处理收发数据的逻辑
10 def auth(secret_key):
11     msg = sk.recv(32)
12     # hmac.new(key(盐),msg(密码))
13     hm = hmac.new( secret_key.encode() , msg )
14     # 获取加密后的字符串[32为长度的十六进制字符串]
15     cli_res = hm.hexdigest()
16     # 把加密后的字符串转换成字节流发送给服务端做校验.
17     sk.send(cli_res.encode())
18     
19     # 接受服务端最后的校验结果
20     res = sk.recv(1024).decode()
21     return res
22         
23 
24 secret_key = "芝麻开门吧小怪怪"
25 res = auth(secret_key)
26 print(res , type(res))
27 
28 """"""
29 if res == "True" :
30     print("服务端校验成功~")
31 else:
32     print("服务端校验失败~")
33 
34 
35 sk.close()
客户端
 1 import socketserver
 2 import os
 3 import hmac
 4 
 5 class MyServer(socketserver.BaseRequestHandler):
 6     secret_key = "芝麻开门吧小怪怪"
 7     
 8     def auth(self):
 9         conn = self.request
10         # 创建一个随机的32位字节流
11         msg = os.urandom(32)
12         # 把字节流发送给客户端
13         conn.send(msg)
14         # 服务端接受客户端发送过来的结果
15         cli_res = conn.recv(1024).decode()
16         
17         # 服务端进行数据加密
18         hm = hmac.new(self.secret_key.encode() , msg)
19         # 获取服务端校验的数据结果
20         ser_res = hm.hexdigest()
21         
22         # 让客户端和服务端的结果做校验
23         return "True" if cli_res == ser_res else "False"
24 
25     def handle(self):
26         # 获取校验结果
27         res = self.auth()
28         # 把结果发送给对应的客户端
29         self.request.send(res.encode())
30         
31         
32         
33 server = socketserver.ThreadingTCPServer( ("127.0.0.1" , 8003) , MyServer )
34 server.serve_forever()
服务端

 

posted @ 2021-01-02 21:00  讷言敏行~  阅读(247)  评论(0编辑  收藏  举报