【python】Twisted网络编程

news2024/9/22 19:43:12

Twisted

    • 什么是Twisted?
    • 为什么使用twisted?
    • Twisted 写TCP通信基本实例
      • - TCP服务端
      • - TCP客户端
    • Twisted的Deferred机制
      • Why Deferred?
      • Deferred TCP-ECHO客户端实现
        • - TCP client为例,

什么是Twisted?

Twisted是一种非阻塞的网络服务器技术,通过事件循环处理、回调机制来触发相应操作。
【相比socket通信,当有多个事件时,如果有一个事件阻塞,就都阻塞的情况。】

  • 异步处理:

类似小学数学题中的给定时间任务的合理安排,比如烧水和做饭两个任务,不用等烧完水再做饭,而是烧水中去做饭,一开始烧水,中间去做饭烧开时再管热水。

  • 异步处理的示意:
  • 📕twisted原理
    • reactor中心
    • 多任务轮询
    • 暂停循环回调执行操作
      在这里插入图片描述

为什么使用twisted?

网络编程中,最基本的对协议的包装为socket库。socket通信方式如下:
请添加图片描述
Tcp协议中,服务端等待客户端发送数据rece()才能收到,否则就在阻塞等待。客户端也一样要等待服务端发送。这就是阻塞IO,浪费了很多性能。
Twisted 进行改进,提出非阻塞IO,不等待回复,而是不断轮询看是否收到。并根据情况进行状态切换操作,这就是异步处理.

  • 因此有多个客户端时,不用多线程实现,twisted内部单线程回调都能实现[^1]

Twisted 写TCP通信基本实例

  • 📕Twisted使用方式
    • protocol中定义事件回调操作(根据需要找已有的方法即可)
    • 在factory中注册
    • 开启监听、轮询run

- TCP服务端

# TCP服务端
import twisted
import twisted.internet.protocol
import twisted.internet.reactor

SERVER_PORT = 8080 # 监听端口

class Server(protocol.Protocol): # 定义好事件的回调操作程序,twisted定义的事件,根据需要找到
	def connectionMade(self): # 客户端连接的时候触发
		print("客户端地址: %s" % self.transport.getPeer().host)
	
	def dataReceived(self. data): # 接收客户端数据
		print("[服务端]接收到数据 : %s" % data.decode("UTF-8")) # 输出接收到的数据
		self.transport.write(("[ECHO] %s" % data.decode("UTF-8")).encode("UTF-8")) # 回应

class DefaultServerFactory(protocol.Factory): # 定义处理工厂类,注册
	protocol = Server

def main():
	reactor.listenTCP(SERVER_PORT, DefaultServerFactory())  # 服务监听
	print("服务启动完毕,等待客户端连接。。。")
	reactor.run()  # 事件轮询

if __name__ == "__main__":
	main() 

- TCP客户端

import twisted
import twisted.internet.protocol
import twisted.internet.reactor
SERVER_HOST = "localhost"  # server 主机
SERVER_PORT = 8080  # server端口号

class Client(protocol.Protocol): # 定义客户端回调处理
	def connectionMade(self):
		print("服务器连接成功,可以进行数据交互,如果要结束通讯,则直接回车")
		self.send()
		
	def send(self):  # 自定义的数据发送方法
		input_data = input("请输入要发送的数据")
		if input_data: # 有数据输入
			self.transport.write(input_data.encode("UTF-8"))
		else:
			self.transport.loseConnection() # 关闭连接

class DefaultClientFactory(protocol.ClientFactory):
	protocol = Client
	clientConnectionLost = clientConnectionFailed = lambda self, connector, reason:reactor.stop()  # 只要连接失败 就关闭reactor

def main():
	reactor.connectTCP(SERVER_HOST, SERVER_PORT, DefaultClientFactory()) 
	reactor.run()

if __name__ == "__main__":
	main() 
connectionMade()等有的函数是Twisted定义好的方法,根据需要调用即可。

从代码中可以看出Twisted优势:在运行多个客户端时,相比socket,这里不需要进行并发(多线程)开发,全部执行流程都是单线程的运行模式(Python中的多线程有GIL全局锁问题)。Twisted内部会进行单线程回调实现,只需要找到对应的事件(方法)即可

Twisted的Deferred机制

Why Deferred?

在这里插入图片描述
线程不被长时间占用,而是另外开启线程执行这个长时任务,执行完告诉。

Deferred TCP-ECHO客户端实现

- TCP client为例,

import twisted
import twisted.internet.protocol
import twisted.internet.defer
import twisted.internet.reactor
import twisted.internet.threads
import time
SERVER_HOST = "localhost"  # server 主机
SERVER_PORT = 8080  # server端口号

class DeferClient(protocol.Protocol):  # 设置一个回调处理类
	def connectionMade(self):
		print("服务器连接成功,可以进行数据交互,如果要结束通讯,则直接回车")
		self.send()
	
	def send(self):  # 自定义的数据发送方法
		input_data = input("请输入要发送的数据")
		if input_data: # 有数据输入
			self.transport.write(input_data.encode("UTF-8"))
		else:
			self.transport.loseConnection() # 关闭连接
	
	def dataReceived(self, data): # 接收服务端发送的数据
		content = data.decode("utf-8")
		threads.deferToThread(self.handle_request, content).addCallback(self.handle_success) # 开启另一线程并用回调提示完成
	def handle_request(self, content): # 数据处理过程
		print("客户端对服务端的数据 %s 进行处理,此处会产生1s延迟..." % content) # 处理完毕后的信息输出
		time.sleep(1) # 模拟延迟
		return content # 返回处理结果
	def handle_success(self, result):
		print(处理完成,进行参数接收 %s" % result) # 处理完毕后的信息输出
	
	def handle_error(self, exp):
		print("程序出错,%s" % exp)

class DefaultClientFactory(protocol.ClientFactory):
	protocol = DeferClient
	clientConnectionLost = clientConnectionFailed = lambda self, connector, reason:reactor.stop()  # 只要连接失败 就关闭reactor
	
def main():
	reactor.connectTCP(SERVER_HOST, SERVER_PORT, DefaultClientFactory()) 
	reactor.run()

if __name__ == "__main__":
	main() 

解释
对数据的处理需要时间,想不只等待而是先去做别的:

def handle_request(self, content): # 数据处理过程
		print("客户端对服务端的数据 %s 进行处理,此处会产生1s延迟..." % content) # 处理完毕后的信息输出
		time.sleep(1) # 模拟延迟
		return content # 返回处理结果

因此把数据放到另一线程中进行处理,并用defer回调提示完成

import twisted.internet.threads
threads.deferToThread(self.handle_request, content).addCallback(self.handle_success) # 开启另一线程并用回调提示完成

注:以上总结自b站这个视频

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/188368.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

useEffect 依赖项为对象或数组时,引发不断重渲染问题的原因及解法

转载自 https://www.izhaoo.com/2021/11/01/useEffect-object-dependent/背景今天封了个轮子,对组件传入参数生成对应的动画实例,当入参变化时重新渲染新实例。自然而然想到的就是 useEffect 监听 props 依赖了,如:useEffect(() &…

ESD器件(TVS)选型考虑

参考:TOSHIBA《Basics of ESD Protection (TVS) Diodes》①VRWM: Working peak reverse voltage工作峰值反向电压:ESD保护二极管显示非常高的阻抗。高于这个电压,会通过指定大小漏电流。设计的时候,信号的最大出现电压要在这个电压…

Java基础漏洞(六)

巩固Java基础,基于韩顺平老师的课程,Java的封装、继承、多态、super()、this()、重载与重写的区别......,下面我们一点点来巩固练习。 (1)继承 继承细节1:子类无法继承父类的私有 图1 我们定义一个父类f…

Ansys Zemax | 利用 TrueFreeForm 面进行网格自由曲面的优化

在这篇文章中,我们将演示如何使用 OpticStudio 的 TrueFreeForm 面,设计AR/VR设备中的人眼追迹系统(eye-tracking subsystem),这个系统通常位于装置的楔形透镜结构中。此外,为了完成子孔径(sub-…

JSBridge:混合开发中的双向通信[Android、iOSJavaScript]

什么是WebView WebView 是移动端中的一个控件,它为 JS 运行提供了一个沙箱环境。WebView 能够加载指定的 url,拦截页面发出的各种请求等各种页面控制功能,JSB 的实现就依赖于 WebView 暴露的各种接口。 由于历史原因,IOS以8为分界…

【Java AWT 图形界面编程】事件处理机制 ② ( Frame 窗口事件监听器 WindowListener | 代码示例 )

文章目录一、Frame 窗口事件监听器 WindowListener二、Frame 窗口事件监听器 WindowListener 代码示例一、Frame 窗口事件监听器 WindowListener 在 AWT 中 , 为 Frame 窗口 添加 窗口事件监听器 WindowListener , 可以监听窗口的操作 , 如 : 窗口显示 WindowListener#windowO…

leetcode 1626. Best Team With No Conflicts(最佳无冲突团队)

scores数组中是每个队员的得分,ages数组中为对应队员的年龄, 现在要从这个队里挑选出一些队员,使总得分最高, 挑选时年龄大的要比年龄小的score更高(严格大于),才不会产生冲突。 返回最高的得分…

【nestjs+VueJs全栈】- 后端搭建和数据库抽离

先补充一些nestjs的前置知识 控制器 控制器负责处理传入的请求和向客户端返回响应。 控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。 为了创建一个基本的控制器…

React 组件基础

文章目录1. React 组件的两种创建方式1 使用函数创建组件2 使用类创建组件3 抽离为独立 JS 文件2. React 事件处理1.事件绑定2 事件对象3. 有状态组件和无状态组件4. 组件中的 state 和 setState1 state的基本使用2 setState()修改状态从 JSX 中抽离事件处理程序5.事件绑定 thi…

Python初学如何逆袭高手?22个万能公式汇总大全

嗨害大家好鸭!我是小熊猫~ 本篇文章共22个万能公式~ 初学者友好~ 源码资料电子书:点击此处跳转文末名片获取 1、一次性进行多个数值的输入 对于数值的输入问题, 是很多笔试题目中经常遇到的问题, 一次性输入多个参数值 , 可以节…

AppiumDesktop学习总结

Appium学习总结 文章目录Appium学习总结一、简介二、环境准备1.下载并配置安卓SDK环境变量2.下载及安装AppiumDesktop3.安装AppiumDesktop4. 启动AppiumDesktop5.安装Python3.x环境6.安装Appium的Python客户端7.安装安卓模拟器8.安装被测APP:9.连接安卓设备三、运行…

NCRE二级 《MS Office高级应用》备考之路

文章目录一、WORD一、易考点二、解题思路二、EXCEL一、易考点二、解题思路三、PPT一、易考点二、解题思路四、其他一、WORD 一、易考点 1.设置页边距、纸张方向、纸张大小、装订线位置,分栏。 2.设置主题、页面边框、添加水印。 3.设置段间距、行间距、特殊格式&…

MySQL从入门到精通(第一篇):MySQL的基本语法及其设计,结合多篇文章

MySQL目录一、数据库入门1. 数据管理技术的三个阶段2. 关系型数据库与非关系型数据库3. 四大非关系型数据库a. 基于列的数据库(column-oriented)b. 键值对存储(Key-Value Stores)c. 文档存储(Document Stores&#xff…

【日志首次上报积分最多】

题目描述 【日志首次上报最多积分】 日志采集是运维系统的的核心组件。日志是按行生成,每行记做一条,由采集系统分批上报。 如果上报太频繁,会对服务端造成压力;如果上报太晚,会降低用户的体验; 如果一次上报的条数…

【flyway入门及使用】解决生产环境sql更新遗漏

flyway入门及使用 一、简单介绍 flyway开源的数据库版本管理工具 二、为什么要使用flyway 1.自己写的sql没有在全部环境执行 2.别人写的sql没有在全部环境执行 3.有人修改了已经执行过的SQL,期望再次执行 4.需要新增环境做数据迁移 三、flyway是如何工作 1…

雷达流量计的安装方法与应用方向介绍

1、设备介绍 雷达流量计是一种采用微波技术的水位流速探测仪器,结合了成熟的雷达水位计和雷达流速仪的测量技术,主要应用于江河、水库闸口、地下水道管网、灌溉渠道等明渠水位流速测量。该产品可有效地监控水位流速流量变化状态,为监测单位提…

【ThreeJs 初学习】随机三角形的实现方案

随机三角形的实现方案 根据官网的文档整理出一份API文档, 地址是:ThreeJs 官网文档,其目的还是为了方便查阅 下列代码源码地址 上述的截图 就是大致的实现效果。 实现内容 首先我们需要对法向量 以及如何完成一个面有一定的了解,具体了解的内…

Opencv-DNN模块之官方指导:利用DNN模块实现深度学习应用:分类、分割、检测、跟踪等

本文根据 Deep Learning with OpenCV DNN Module: A Definitive Guide 中相关内容进行翻译整理而得,用于今后的学习和工程。 00 前  言 ---   机器视觉研究领域从上个世纪六十年后期就已创立。图像分类和物体检测是计算机视觉领域中的一些最古老的的问题&#x…

CSS - 实现Loading加载动画

Loading加载动画 用CSS都用实现一个loading的加载动画 通过控制 item-loader-container 来实现显示及隐藏 <div class"item-loader-container" id"item-loader-container"><div class"la-ball-running-dots la-2x"><div></…

TVS二极管6.6SMDJ58A/6.6SMDJ58CA参数,有什么区别?

提及6600W高功率TVS二极管&#xff0c;电子工程师们更多想到的可能是DO-218AB封装SM8S系列汽车级瞬态抑制TVS二极管&#xff0c;关于SM8S系列TVS管这方面的知识&#xff0c;之前科普过好多次了。接下来&#xff0c;TVS保护管厂家东沃电子要科普的是另一款6600W的二极管6.6SMDJ系…