文章目录
- 多线程对多客户端
- socketserver
- 分类(2种)
- 12个类的继承关系(原理)
- socketserver的实现效果
- 认证链接的合法性
-
socketserver本质是基于socket进行的一个封装,将多线程并发功能集成到一个新的模块里,就叫socketserver;
它用来解决TCP套接字无法并发的问题,也就是无法一个服务端不能同时服务多个客户端的问题(UDP没有此问题,因为它不需要链接)
多线程对多客户端
![多线程对多客户端](https://img-blog.csdnimg.cn/20200324183819456.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZpZXdpbmZpbml0ZWx5,size_16,color_FFFFFF,t_70)
socketserver
分类(2种)
1、server类:处理链接
BaseServer 处理链接必须
TCPServer 处理流式(TCP)链接
UDPServer 处理数据报式(UDP)链接
2、request类:处理通信必须
BaseRequestHandler 处理通信
StreamRequestHandler 处理流式通信,即TCP
DatagramRequestHandler 处理数据报式通信,即UDP
12个类的继承关系(原理)
socketserver模块的源码里面,主要只有12个类,这12个类实现了socketserver的所有功能,下面是这12个类的继承关系:
![12个类的继承关系](https://img-blog.csdnimg.cn/20200324183842619.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZpZXdpbmZpbml0ZWx5,size_16,color_FFFFFF,t_70)
socketserver的实现效果
1、服务端测试代码:
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
print('conn is ',self.request)
print('addr is ',self.client_address)
while True:
try:
data = self.request.recv(1024)
if not data:continue
if data == 'quit':break
print('客户端发来的消息是:',data.decode('utf-8'),'\n')
self.request.sendall(data.upper())
except Exception as e:
print(e)
break
if __name__ == '__main__':
s = socketserver.ThreadingTCPServer(('192.168.43.247',8080),MyServer)
s.serve_forever()
2、客户端测试代码:
from socket import *
ip_port = ('192.168.43.247',8080)
back_log = 5
buffer_size = 1024
tcp_client = socket(AF_INET,SOCK_STREAM)
tcp_client.connect(ip_port)
while True:
msg = input('请输入>>>')
tcp_client.send(msg.encode('utf-8'))
print('客户端已发送出消息!')
data = tcp_client.recv(buffer_size)
print('服务端发回的消息是:',data.decode('utf-8'))
tcp_client.close()
3、多个相同的客户端
当然我们需要准备多个相同的客户端才能看到效果
![多个客户端](https://img-blog.csdnimg.cn/20200324184303732.png)
4、测试结果:
![测试结果](https://img-blog.csdnimg.cn/20200324184332473.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZpZXdpbmZpbml0ZWx5,size_16,color_FFFFFF,t_70)
![断开并发](https://img-blog.csdnimg.cn/20200324191210123.png)
可以看到,成功实现了tcp套接字的并发效果,只有一个客户端,可以同时服务多个客户端,并且,四个客户端可以分别断开,不影响其他客户端的使用
认证链接的合法性
所谓认证客户端合法性,就是通过一条或多条规则,让服务端和客户端做一个接口验证;
如果验证成功就表明链接的合法的,就让对方的链接接入进来;错了当然就不允许接入
说白了就像对暗号一样,如果对了,就说明是自己人,就允许你进入;错了,就不准进
加盐(hmac)
我们通过哈希算法,可以验证一段数据是否有效,方法就是对比该数据的哈希值,来判断用户的暗号是否正确;
为了防止黑客通过彩虹表根据哈希值反推我们的暗号,在计算哈希的时候,不能只通过对原始数据进行比较,还需要增加一些salt来使得相同的输入也能得到不同的哈希,这样,就可以让我们的数据更安全;
一般都是我们随机生成一个salt(一段随机码),然后与我们自定义的一个暗号进行混合运算,这个就是hmac算法,它通过一个标准算法,在计算哈希的过程中,把key混入计算过程中;
hmac算法练习代码:
import hmac
message = b'ViewIn is strongest'
secret_key = b'Very'
h = hmac.new(secret_key, message, digestmod='MD5')
print(h.hexdigest())
练习结果:
![hmac算法](https://img-blog.csdnimg.cn/20200324185843637.png)
可见使用hmac和普通hash算法都非常类似,hmac输出的长度和原始哈希算法的长度一样长。不过传入的key和message都必须是bytes类型,str类型需要首先编码为bytes;
所以上文练习代码里在字符串前加了一个b,表示是二进制形式的变量
对暗号
1、我们要完成验证链接合法性,就必须先用hmac对生成我们的暗号
def conn_auth(conn):
print('开始验证新链接的合法性')
msg=os.urandom(32)
conn.sendall(msg)
h=hmac.new(secret_key,msg)
digest=h.digest()
respone=conn.recv(len(digest))
return hmac.compare_digest(respone,digest)
2、暗号生成完了,自然就是要开始对暗号了
def data_handler(conn,bufsize=1024):
if not conn_auth(conn):
print('该链接不合法,关闭!!!')
conn.close()
return
print('链接合法,开始通信!')
while True:
data=conn.recv(bufsize)
if not data:continue
if data == 'quit':break
conn.sendall(data.upper())
经过这两步操作我们就可以对任何传来的链接进行验证了,客户端发来正确的暗号就让其连接上服务端;如果暗号错误或者压根就不知道有暗号,那肯定就连接不上服务端
3、实现效果:
链接是合法的,暗号对上了:
![链接合法](https://img-blog.csdnimg.cn/2020032419123281.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZpZXdpbmZpbml0ZWx5,size_16,color_FFFFFF,t_70)
知道有暗号,但是暗号没对上:
![非法1](https://img-blog.csdnimg.cn/20200324191311714.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZpZXdpbmZpbml0ZWx5,size_16,color_FFFFFF,t_70)
压根就不知道有暗号:
![不知道有暗号](https://img-blog.csdnimg.cn/20200324191434429.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZpZXdpbmZpbml0ZWx5,size_16,color_FFFFFF,t_70)
这样就成功完成了对链接的认证,合法就接入,不合法就断开。
需要测试代码的Python学习伙伴们请私聊或评论
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)