Author: 酱橙
参考资料:
《Python高效开发实战——Django、Tornado、Flask、Twisted(第2版)_刘长龙(著) 电子工业出版社_2018-12-01》密码:9j57
Twisted初识
1. Twisted是个啥?
Twisted
是一个历史悠久的开源事件驱动框架。支持很多协议,包括传输层的UDP、TCP、TLS,以及应用层的HTTP、FTP 等。对于这些所有的协议,Twisted 提供了客户端和服务器方面的开发工具。
Twisted是一个高性能的编程框架。在不同的操作系统平台上,Twisted
利用不同的底层技
术实现了高效能通信。在Windows中,Twisted 的实现基于I/O完成端口( IOCP,Input/
Output Completion Port)技术,它保证了底层高效地将I/O事件通知给框架及应用程序。在Linux中,Twisted的实现基于**epoll **技术,epoll 是Linux下多路复用I/O接口select/**poll **的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。
- twisted网络框架的三个基础模块:
Protocol
,ProtocolFactory
,Transport
.这三个模块是构成twisted服务器端与客户端程序的基本。
class | explain |
---|---|
Protocol | 实现协议内容,即通信的内容协议 |
ProtocolFactory | 工厂模式的体现,在这里面生成协议 |
Transport | 用来收发数据, 服务器端与客户端的数据收发与处理都是基于这个模块 |
2. 准备工作
- 笔者时windows环境中进行的开发,因此这里有个小网站,可以下载
pip
需要的轮子包:
这里 cp 的数字表示的是对应可以使用的Python版本。
但是书中使用的版本是 18.7.0(我是下载链接)
- 然后用mkvirtualenv 新建一个虚拟环境
- 我这里直接pip安装的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vngMdePy-1605262287940)(img\image-20201112154540366.png)]
- 如果使用轮子包的话,就这样写(下载到当前目录的.whl文件,注意对应的Python版本):
pip install Twisted‑20.3.0‑cp37‑cp37m‑win_amd64.whl
- 检查一下:
- 发现版本和书上对不上,所以卸了重新装18.7.0版本 🙂
3. 实战: 开发TCP广播系统
基于的网络协议:TCP
流程:接收任意客户端的链接请求,并将任意客户端发送给服务器的消息转发给其它客户端。
特点:类似于一个基本的实时通信模型。
使用Twisted进行基于传输层TCP的编程时,无需操作 Socket的bind
、send
、receive
等语句(我也觉得,写这玩意儿 ,很艹蛋),而是使用Twisted的 Protocol
、Factory
这些封装好了的类进行编程,定义他们的子类并且重写connectionMade
、dataReceived
进行事件的TCP编程风格。当然,这也是Twisted作者Glyph编写这个框架的原因之一。
Server
- 项目结构:
|——>server
|————>/app
| |————> echo_factory.py
| |————> settings.py
|————>run_client.py
1. 开发Protocol 子类
针对每个客户端的连接,Twisted框架建立了一个
Protocol子类
的实例管理该连接。开发者需要编写该子类,使其能够处理 3 个基本事件响应函数。
- connectionMade():
Called when a connection is made.
在实际应用中, 本函数的主要作用是常常在系统的注册该连接, 方便后来调用.
- dataReceived():
Called whenever data is received.
- connectionLost
Called whenever data is received.
在实际应用中,用来清理连接占用的资源。
- Protocol 代码:
server_protocol.py
from twisted.internet.protocol import Protocol, connectionDone
# 用全局变量clients保存所有的客户端的连接(即 Protocol 子类 Speaker 的实例)
clients = []
# 定义Protocol的子类, 实现需要重载的方法
class Spreader(Protocol):
def __init__(self, factory):
self.factory = factory
# 对客户端连接进行计数, 并且将 self 保存到 clients 列表中。
def connectionMade(self):
"""
Called when a connection is made.
在实际应用中, 本函数的主要作用是常常在系统的注册该连接, 方便后来调用.
:return: None
"""
self.factory.numProtocols = self.factory.numProtocols + 1
self.transport.write(
(u"欢迎来到Spread Site,您是第 %d 个客户端用户!\n" %
(self.factory.numProtocols,).encode('utf-8')))
print(