Python asynchat模块-异步套接字处理-服务器程序示例

2023-09-18 09:30:00

介绍

此模块在asyncore架构上建立,简化了异步客户端和服务器,并且使得处理元素为任意字符串结束或者为变长度的协议更加容易。asynchat定义了一个可以由使用者来子类化的抽象类async_chat,提供了collect_incoming_data()和found_terminator()等方法的实现。它使用与asyncore相同的异步循环,并且可以在通道映射中自由地混合asyncore.dispatcher和asynchat.aync_chat这两种类型地通道。一般来说asyncore.dispatcher服务器通道在接收到传入地连接请求时,会生成新地asynchat.async_chat通道对象。

class asynchat.async_chat

这个类是asyncore.dispatcher的抽象子类。对于实际使用的代码必须子类化async_chat,提供有意义的collect_incoming_data()和found_terminator()方法。asyncore.dispatcher的方法也可以被使用,但它们在消息/响应上下文中并不是全都有意义。

与asyncore.dispatcher类似,async_chat也定义了一组通过对select()调用之后的套接字进行分析所生成的事件。一旦启动轮询循环,async_chat对象的方法就会被事件处理框架调用而无需程序员方法做任何操作。

两个可被修改的类属性,用以提升性能,甚至也可能会节省内存。

1)ac_in_buffer_size:异步输入缓冲区大小(默认:4096)

2)ac_out_buffer_size:移除输出缓冲区大小。

与asyncore.dispatcher不同,async_chat允许你定义一个FIFO队列producer。其中的生产者只需要一个方法more(),该方法应当返回要在通道上传递的数据。生成者通过让其more()方法返回空字节串对象来表明其处于耗尽状态(它已不再包含数据)。此时,async_chat对象会将该生产者从队列中移除并开始使用下一个生产者,如果有下一个的话。当生产者队列为空时,handle_write()方法将不执行任何操作。你要使用通道对象的set_terminator()方法来描述如何识别来自远程端点的入站传输的结束或者重要的中断点。

要构建一个可用的async_chat子类,你的输入方法collect_incoming_data()和found_terminator()必须要处理通道异步接收的数据。

1)async_chat.close_when_done():将None推入生产者队列。当此生产者被弹出队列时,它将导致通道被关闭。

2)async_chat.collect_incoming_data(data):调用时附带data,其中包含任意数量的已接收数据。必须被重载的默认方法将引发一个NotImplementedError异常。

3)asyn_chat.discard_buffer():在紧急情况下,此方法将丢弃输入和/或输出缓冲区以及生产者队列中的任何数据。

4) asyn_chat.found_terminator():当输入数据流能匹配set_terminator()所设定的终结条件时被调用。必须被重载的默认方法将引发一个NotImplementedError异常。被缓存的输入数据应当可以通过实例属性来获取。

5)async_chat.get_terminator():返回通道的当前终止符。

6)async_chat.push(data):将数据推入通道的队列以确保其被传输。要让通道将数据写到网络中,只需要这样做就足够。

7)async_chat.push_with_producer(producer)

8)async_chat.set_terminator(term):设置可在通道上被识别的终结条件。term可以是三种类型值中的任何一种,对应于处理入站协议数据的三种不同方式。

术语        描述
string  当在输入流中发现这个字符串,将调用found_terminator()
integer在接收到指定数目字符时,将调用found_terminator()
None通道一直持续收集数据。

注意:在found_terminator()后,在终止符之后的任何数据将可用于由这个通道读取。

以下用一个示例展示使用 asynchat模块实现一个tcp服务:

服务器具有以下特性:

1) 识别一个以\r为终止符的字符串

2)它接收到字符串1返回One, 接收2返回Two,接收到3返回Three,接收到其它字符串时,返回Hello: + 接收到的字符串

3) 返回字符串以\r\n为终止符

源代码如下:

#!/usr/bin/env python3

import os

import sys
import asynchat
import asyncore
import socket

DEFAULT_PORT = 31337

class Echo:
    def parseCommand(self, num):
        if num == "1":
            return "One"
        elif num == "2":
            return "Two"
        elif num == "3":
            return "Three"
        else:
            return "Hello: " + num

class ConnectionDispatcher(asyncore.dispatcher):
        def __init__(self, port, echo):
                # 创建套接字,绑定IP地址和监听端口,开始监听
                asyncore.dispatcher.__init__(self)
                self.port = port
                self.device = echo
                self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
                self.set_reuse_addr()
                self.bind(("", port))
                self.listen(5)

        # 接受连接,调用服务处理方法
        def handle_accept(self):
                client_info = self.accept()
                print("client connected: ", client_info )
                ConnectionHandler(client_info[0], self.device)


class ConnectionHandler(asynchat.async_chat):
        # 设置输入终止符
        def __init__(self, sock, device):
                asynchat.async_chat.__init__(self, sock)
                self.set_terminator(b"\r")
                # 输出终止符格式
                self.outputTerminator = "\r\n"
                self.device = device
                self.buffer = ""
        # 收集数据
        def collect_incoming_data(self, data):
                self.buffer = self.buffer + data.decode()
        # 查找终止符,并把终止符之前的数据交给处理方法
        def found_terminator(self):
                data = self.buffer
                self.buffer = ""
                self.handleClientRequest(data)

        def handleClientRequest(self, request):
                request = request.strip()

                # 显示接收到的数据
                print(request)

                response = self.device.parseCommand(request)

                # 回应客户端
                if response != None:
                        self.sendClientResponse("{}".format(response))

                return

        def sendClientResponse(self, response=""):
                data = response + self.outputTerminator
                self.push(data.encode())


if __name__ == "__main__":
    if sys.version_info < (3,0,0) and sys.version_info < (3,12,0):
            sys.stderr.write("You need Python 3.0 or later (but less than 3.12) to run this script\n")
            input("Press enter to quit... ")
            sys.exit(1)

        # 尝试运行服务器
    try:
        echo = Echo()
        server = ConnectionDispatcher(DEFAULT_PORT, echo)
        asyncore.loop()
    except Exception as e:
        if isinstance(e, SystemExit):
            raise e
        else:
            print("Error: {}".format(e))
            sys.exit(1)

运行以上python代码。

以下是测试结果:

更多推荐

Zookeeper集群 + Kafka集群

ZookeeperZookeeper概述Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目Zookeeper工作机制Zookeeper从设计模式角度来理解:是一个,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zo

Vue路由与nodes的环境配置

一,Vue路由什么是Vue路由?Vue路由是Vue.js的一部分,是一个官方的Vue.js插件,用于管理单页面应用程序的路由。它允许您在应用程序中使用URL路径和参数来管理不同的页面视图,而无需刷新页面。使用Vue路由,您可以轻松地设置和管理客户端路由,包括嵌套和动态路由。它还提供了一些高级功能,例如路由守卫,用于在页

leetcode646. 最长数对链(java)

最长数对链题目描述贪心解法二动态规划dp题目描述难度-中等leetcode646.最长数对链(java)给你一个由n个数对组成的数对数组pairs,其中pairs[i]=[lefti,righti]且lefti<righti。现在,我们定义一种跟随关系,当且仅当b<c时,数对p2=[c,d]才可以跟在p1=[a,b]后

HTML 学习笔记(基础)

它是超文本标记语言,由一大堆约定俗成的标签组成,而其标签里一般又有一些属性值可以设置。W3C标准:网页主要三大部分结构:HTML表现:CSS行为:JavaScript<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewpor

配置 iSCSI 服务并实现客户端自动挂载块设备

文章目录前言1.iSCSI简介2.iSCSIServer端配置2.1.添加磁盘2.2.安装targetcli软件包2.3.创建块设备2.4.创建Target2.5.创建LUN2.6.创建ACL2.7.配置门户创建监听2.8.查看全部配置信息并保存退出2.9.启用Target服务3.iSCSIClient端配置3.1.安

C# 扫描并读取图片中的文字(.NET Core)

本文介绍如何通过C#程序来扫描并读取图片中的文字,这里以创建一个.NetCore程序为例。下面是具体步骤,供参考。程序测试环境:VisualStudio版本要求不低于2017图片扫描工具:Spire.OCRfor.NET图片格式:png(这里的图片格式支持JPG、PNG、GIF、BMP、TIFF等格式)扫描的图片文字:

HT for Web (Hightopo) 使用心得(2)- 2D 图纸、节点、连线 与基本动画

概括来说,用HTforWeb做可视化主要分为两部分,也就是2D和3D。这两部分需要单独创建。在它们被创建完成后,我们再把它们集成到一起。HTforWeb的2D部分主要是指ht.graph.GraphView(简称GraphView,也就是2D图纸)。所谓2D图纸其本质是一个canvas。我们可以在上面进行基本图形的绘制

MeterSphere v2.10.X-lts 双节点HA部署方案

一、MeterSphere高可用部署架构及服务器配置1.1服务器信息序号应用名称操作系统要求配置要求描述1负载均衡器CentOS7.X/RedHat7.X2C,4G,200GB部署Nginx,实现负载路由。部署NFS服务器。2MeterSphere应用节点1CentOS7.X/RedHat7.X8C,16GB,200G

数据可视化

一、Flask介绍#通过访问路径,获取用户的字符串参数@app.route('/user/<name>')defwelcome(name):return"你好,%s"%name@app.route('/user/<int:id>')defwelcome2(id):return"你好,%d号的会员"%id能够自动根据参数

Web 3.0 安全风险,您需要了解这些内容

随着技术的不断进步,我们正迎来一个全新的互联网时代,被称为Web3.0。Web3.0将带来许多令人兴奋的机会,但与之同时,也伴随着一系列新的安全风险。在这篇文章中,我们将探讨Web3.0的安全挑战,以帮助您更好地了解并准备迎接这个新时代。Web3.0简介Web3.0是互联网的下一代,将构建在区块链、分布式技术和智能合约

人工智能:人脸识别技术应用场景介绍

目录人脸识别介绍什么是人脸识别技术人脸识别的流程1、场景分类2、认证对比3、金融领保险应用3.1金融行业3.2保险行业4、安防交通领域4.1公园景点人脸识别闸机4.2高铁站进站人脸识别闸机5、警务领域5.1抓拍交通违法人脸识别介绍什么是人脸识别技术人脸识别技术是一种通过计算机技术和模式识别算法来识别和验证人脸的技术。它

热文推荐