Python之网络编程(socketserver模块详解、链接认证)

2023-05-16

文章目录

      • 多线程对多客户端
      • socketserver
        • 分类(2种)
        • 12个类的继承关系(原理)
        • socketserver的实现效果
      • 认证链接的合法性
        • 加盐(hmac)
        • 对暗号

socketserver本质是基于socket进行的一个封装,将多线程并发功能集成到一个新的模块里,就叫socketserver;
它用来解决TCP套接字无法并发的问题,也就是无法一个服务端不能同时服务多个客户端的问题(UDP没有此问题,因为它不需要链接)

多线程对多客户端

多线程对多客户端

socketserver

分类(2种)

1、server类:处理链接
BaseServer 处理链接必须
TCPServer 处理流式(TCP)链接
UDPServer 处理数据报式(UDP)链接

2、request类:处理通信必须
BaseRequestHandler 处理通信
StreamRequestHandler 处理流式通信,即TCP
DatagramRequestHandler 处理数据报式通信,即UDP

12个类的继承关系(原理)

socketserver模块的源码里面,主要只有12个类,这12个类实现了socketserver的所有功能,下面是这12个类的继承关系:
12个类的继承关系

socketserver的实现效果

1、服务端测试代码:

#导入socketserver模块
import socketserver

#定义一个类,该类必须继承socketserver下的BaseRequestHandler类
class MyServer(socketserver.BaseRequestHandler):
    def handle(self):  #必须定义一个handle方法
        print('conn is ',self.request)  #self.request是获取的链接,相当于conn
        print('addr is ',self.client_address)  #self.client_address则是获取的地址,相当于addr

        #循环收发消息
        while True:
            try:  #异常处理
                #收消息
                data = self.request.recv(1024)  #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__':
    #多线程的TCP服务端,即可以同时开启多个链接运行,也就是多客户端并发效果;
    #再将这样的功能实例化成一个对象s
    s = socketserver.ThreadingTCPServer(('192.168.43.247',8080),MyServer)
    #第一个参数为服务端的ip地址,用元组传进;第二个参数是刚刚定义的那个类
    
    s.serve_forever()  #永远,就是通信循环(链接循环)

2、客户端测试代码:

#客户端就不需要socketserver模块了,用socket模块收发消息就可以了
from socket import *

ip_port = ('192.168.43.247',8080)  #记录ip地址
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)  #buffer_size=1024默认参数,表示字节格式
    print('服务端发回的消息是:',data.decode('utf-8'))

tcp_client.close()  #关闭socket对象

3、多个相同的客户端
当然我们需要准备多个相同的客户端才能看到效果
多个客户端
4、测试结果:
测试结果
断开并发
可以看到,成功实现了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')  #将前两段文字用hmac算法混个,模式为MD5
#如果文字很长,可以多次使用h.update(msg)操作

print(h.hexdigest())  #以十六进制形式输出h

练习结果:
hmac算法
可见使用hmac和普通hash算法都非常类似,hmac输出的长度和原始哈希算法的长度一样长。不过传入的key和message都必须是bytes类型,str类型需要首先编码为bytes;
所以上文练习代码里在字符串前加了一个b,表示是二进制形式的变量

对暗号

1、我们要完成验证链接合法性,就必须先用hmac对生成我们的暗号

#验证链接的合法性
def conn_auth(conn):
    print('开始验证新链接的合法性')
    msg=os.urandom(32)  #生成一个32位随机码
    conn.sendall(msg)  #发送随机码给想接入的链接
    h=hmac.new(secret_key,msg)  #将随机码与我们自定义的暗号混合(加盐操作)
    digest=h.digest()  #再将混合后的内容转化成二进制
    respone=conn.recv(len(digest))  #接收对方发来的加盐结果
    return hmac.compare_digest(respone,digest)
    #再返回digest与想接入链接发来的消息做比较的结果,是一个布尔值
    #该布尔值作为对暗号的结果

2、暗号生成完了,自然就是要开始对暗号了

#开始对暗号
def data_handler(conn,bufsize=1024):  #传入链接、可接收内容的大小
    #验证链接合法性
    if not conn_auth(conn):  #传入需要验证的链接到conn_auth
        print('该链接不合法,关闭!!!')
        conn.close()
        return
    
    #暗号对了,通信
    print('链接合法,开始通信!')
    while True:  #通信就是循环收发消息
        data=conn.recv(bufsize)  #收消息
        if not data:continue
        if data == 'quit':break
        conn.sendall(data.upper())  #发消息

经过这两步操作我们就可以对任何传来的链接进行验证了,客户端发来正确的暗号就让其连接上服务端;如果暗号错误或者压根就不知道有暗号,那肯定就连接不上服务端

3、实现效果:
链接是合法的,暗号对上了:
链接合法
知道有暗号,但是暗号没对上:
非法1
压根就不知道有暗号:
不知道有暗号
这样就成功完成了对链接的认证,合法就接入,不合法就断开。
需要测试代码的Python学习伙伴们请私聊或评论

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python之网络编程(socketserver模块详解、链接认证) 的相关文章

  • 使用Python开发Web应用程序

    我一直在用 python 做一些工作 但这都是针对独立应用程序的 我很想知道 python 的任何分支是否支持 Web 开发 有人还会建议一个好的教程或网站吗 我可以从中学习一些使用 python 进行 Web 开发的基础知识 既然大家都说
  • 如何在android上的python kivy中关闭应用程序后使服务继续工作

    我希望我的服务在关闭应用程序后继续工作 但我做不到 我听说我应该使用startForeground 但如何在Python中做到这一点呢 应用程序代码 from kivy app import App from kivy uix floatl
  • 如何在 Sublime Text 2 的 OSX 终端中显示构建结果

    我刚刚从 TextMate 切换到 Sublime Text 2 我非常喜欢它 让我困扰的一件事是默认的构建结果显示在 ST2 的底部 我的程序产生一些很长的结果 显示它的理想方式 如在 TM2 中 是并排查看它们 如何在 Mac 操作系统
  • 如何等到 Excel 计算公式后再继续 win32com

    我有一个 win32com Python 脚本 它将多个 Excel 文件合并到电子表格中并将其另存为 PDF 现在的工作原理是输出几乎都是 NAME 因为文件是在计算 Excel 文件内容之前输出的 这可能需要一分钟 如何强制工作簿计算值
  • SQL Alchemy 中的 NULL 安全不等式比较?

    目前 我知道如何表达 NULL 安全的唯一方法 SQL Alchemy 中的比较 其中与 NULL 条目的比较计算结果为 True 而不是 NULL 是 or field None field value 有没有办法在 SQL Alchem
  • 为 pandas 数据透视表中的每个值列定义 aggfunc

    试图生成具有多个 值 列的数据透视表 我知道我可以使用 aggfunc 按照我想要的方式聚合值 但是如果我不想对两列求和或求平均值 而是想要一列的总和 同时求另一列的平均值 该怎么办 那么使用 pandas 可以做到这一点吗 df pd D
  • Python tcl 未正确安装

    我刚刚为 python 安装了graphics py 但是当我尝试运行以下代码时 from graphics import def main win GraphWin My Circle 100 100 c Circle Point 50
  • 如何使用装饰器禁用某些功能的中间件?

    我想模仿的行为csrf exempt see here https docs djangoproject com en 1 11 ref csrf django views decorators csrf csrf exempt and h
  • IRichBolt 在storm-1.0.0 和 pyleus-0.3.0 上运行拓扑时出错

    我正在运行风暴拓扑 pyleus verbose local xyz topology jar using storm 1 0 0 pyleus 0 3 0 centos 6 6并得到错误 线程 main java lang NoClass
  • Geopandas 设置几何图形:MultiPolygon“等于 len 键和值”的 ValueError

    我有 2 个带有几何列的地理数据框 我将一些几何图形从 1 个复制到另一个 这对于多边形效果很好 但对于任何 有效 多多边形都会返回 ValueError 请指教如何解决这个问题 我不知道是否 如何 为什么应该更改 MultiPolygon
  • HTTPS 代理不适用于 Python 的 requests 模块

    我对 Python 还很陌生 我一直在使用他们的 requests 模块作为 PHP 的 cURL 库的替代品 我的代码如下 import requests import json import os import urllib impor
  • 循环中断打破tqdm

    下面的简单代码使用tqdm https github com tqdm tqdm在循环迭代时显示进度条 import tqdm for f in tqdm tqdm range 100000000 if f gt 100000000 4 b
  • Python - 按月对日期进行分组

    这是一个简单的问题 起初我认为很简单而忽略了它 一个小时过去了 我不太确定 所以 我有一个Python列表datetime对象 我想用图表来表示它们 x 值是年份和月份 y 值是此列表中本月发生的日期对象的数量 也许一个例子可以更好地证明这
  • Numpy 优化

    我有一个根据条件分配值的函数 我的数据集大小通常在 30 50k 范围内 我不确定这是否是使用 numpy 的正确方法 但是当数字超过 5k 时 它会变得非常慢 有没有更好的方法让它更快 import numpy as np N 5000
  • Python 3 中“map”类型的对象没有 len()

    我在使用 Python 3 时遇到问题 我得到了 Python 2 7 代码 目前我正在尝试更新它 我收到错误 类型错误 map 类型的对象没有 len 在这部分 str len seed candidates 在我像这样初始化它之前 se
  • 如何将 PIL 图像转换为 NumPy 数组?

    如何转换 PILImage来回转换为 NumPy 数组 这样我就可以比 PIL 进行更快的像素级转换PixelAccess允许 我可以通过以下方式将其转换为 NumPy 数组 pic Image open foo jpg pix numpy
  • 检查所有值是否作为字典中的键存在

    我有一个值列表和一本字典 我想确保列表中的每个值都作为字典中的键存在 目前我正在使用两组来确定字典中是否存在任何值 unmapped set foo set bar keys 有没有更Pythonic的方法来测试这个 感觉有点像黑客 您的方
  • 在 Pandas DataFrame Python 中添加新列[重复]

    这个问题在这里已经有答案了 例如 我在 Pandas 中有数据框 Col1 Col2 A 1 B 2 C 3 现在 如果我想再添加一个名为 Col3 的列 并且该值基于 Col2 式中 如果Col2 gt 1 则Col3为0 否则为1 所以
  • 在python中,如何仅搜索所选子字符串之前的一个单词

    给定文本文件中的长行列表 我只想返回紧邻其前面的子字符串 例如单词狗 描述狗的单词 例如 假设有这些行包含狗 hotdog big dog is dogged dog spy with my dog brown dogs 在这种情况下 期望
  • Python 分析:“‘select.poll’对象的‘poll’方法”是什么?

    我已经使用 python 分析了我的 python 代码cProfile模块并得到以下结果 ncalls tottime percall cumtime percall filename lineno function 13937860 9

随机推荐