标签:构造 pytho 监听 需要 ESS %s back client mac
Twisted 框架概况
Twisted 是一个有着10多年历史的开源事件驱动框架。Twisted 支持很多协议,包括传输层的TCP、UDP、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 引导程序员使用异步编程模型。Twisted 提供了丰富的 Defer、Threading等特性来支持异步编程。
在 Linux 与 macOS 中 安装 Twisted
Twisted在安装过程中需要先在设备上编译,因此在安装之前需要确保安装了Python编译开发包。该步骤在不同的操作系统略有不同,以Ubuntu Linux 举例:
# apt-get install python3-dev // 安装 Python3 开发包 # pip install twisted // 安装 Twisted
而在macOS系统的brew安装工具中自带了Python开发包,因此可以直接使用上述第二条命令(pip)安装。
安装完成后可以用如下命令查看Twisted版本:
# pip freeze | grep Twisted Twisted==19.2.1
举个例子: 开发TCP广播系统
该广播系统接受任意客户端的链接请求,并且将任意客户端发给服务器的消息转发给所有其他客户端。本系统是一个基本的实时通信模型。
使用 Twisted 进行基于传输层TCP的编程时,无须程序员操作Socket 的 bind、send、receive等基本原语;而是直接针对Twisted 的 Protocol、Factory 等类进行编程,定义它们的子类并重写connectionMade、dataReceived进行事件化的TCP编程风格。
1、开发 Protocol 子类
针对每个客户端连接,Twisted 框架建立了一个Protocol子类的实例管理该连接。开发者需要编写该子类,使其能够处理3个基本事件响应函数。
from twisted.internet.protocol import Protocol import random import string clients = [] class Spreader(Protocol): def __init__(self, factory): self.factory = factory def connectionMade(self): self.factory.numPortocols += 1 self.client_id = ‘‘.join(random.sample(string.ascii_letters + string.digits, 8)).lower() print("new connect: %d" % self.factory.numPortocols) self.transport.write( (u"欢迎来到 Twisted World, 您是第 %d 个客户端用户!\n" % self.factory.numPortocols).encode()) clients.append(self) def connectionLost(self, reason): clients.remove(self) print("lost connect: %s" % self.client_id) def dataReceived(self, data): if data == "close": self.transport.loseConnection() print("%s closed " % self.client_id) else: print("spreading message from %s % s" % (self.client_id, data)) for client in clients: if client != self: client.transport.write(data)
代码解析如下:
2、开发 Factory 子类
Twisted 中的 Factory 子类起到对 Protocol类的管理作用,当有新的客户端连接时,框架调用 Factory.buildProtocol(),使得程序员可以在这里创建 Protocol 子类的实例。Factory 子类及服务启动程序的代码如下:
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.internet import reactor
class SpreadFactory(Factory):
def __init__(self):
self.numPortocols = 0
def buildProtocol(self, addr):
return Spreader(self)
if __name__ == "__main__":
# 8006 是本服务器的监听端口, 建议选择大于1024 的端口
endpoint = TCP4ServerEndpoint(reactor, 8006)
endpoint.listen(SpreadFactory())
# 挂起运行
reactor.run()
建立 Factory 的子类 SpreadFactory,在其中只需要重写两个函数:在 __init__ 中将客户端计数器 self.numProtocols 置 0;在buildProtocol() 中建立 Protocol 子类 Spreader 的实例。
通过 TCP4ServerEndpoint() 定义服务器的监听端口,并用 listen() 函数指定该端口所绑定的 Factory 子类实例,运行 twisted.internet.reactor.run() 可启动服务器。
3、广播客户端
Twisted 同样提供了基于 Protocol 类的 TCP 客户端的编程方法。实现一个与服务器程序相匹配的 TCP 客户端程序。
from twisted.internet.protocol import Protocol, ClientFactory from twisted.internet import reactor import sys from datetime import datetime class Echo(Protocol): def connectionMade(self): print("Connected to the server!") def dataReceived(self, data): print("got messages: ", data.decode()) reactor.callLater(5, self.say_hello) def connectionLost(self, reason): print("Disconnected from the server!") def say_hello(self): if self.transport.connected: self.transport.write((u"hello, I‘m %s %s" % (sys.argv[1], datetime.now())).encode()) class EchoClientFactory(ClientFactory): def __init__(self): self.protocol = None def startedConnecting(self, connector): print("started to connect.") def buildProtocol(self, addr): self.protocol = Echo() return self.protocol def clientConnectionLost(self, connector, reason): print("Lost connection. Reason:", reason) def clientConnectionFailed(self, connector, reason): print("Connection failed. Reason:", reason) if __name__ == "__main__": host = "127.0.0.1" port = 8006 factory = EchoClientFactory() reactor.connectTCP(host, port, factory) reactor.run()
解析如下:
为了更好地观察本例中 Echo(Protocol 的子类)与 EchoClientFactory( ClientFactory 的子类) 两个类之间回调事件函数的执行顺序,现在打开三个命令行控制台,分别执行一个服务器程序和两个客户端程序,比如:
# python server.py // 服务器程序 # python client.py Alice // 客户端程序 # python client.py Bob // 客户端程序
运行若干秒后用 CTRL-C 终止服务器程序的执行。观察服务器程序:
new connect: 1 spreading message from zjqaohpd b"hello, I‘m Alice 2019-06-18 21:02:57.807600" new connect: 2 spreading message from v0f4fhl3 b"hello, I‘m Bob 2019-06-18 21:03:13.586417" spreading message from zjqaohpd b"hello, I‘m Alice 2019-06-18 21:03:18.593345" spreading message from v0f4fhl3 b"hello, I‘m Bob 2019-06-18 21:03:23.600063" spreading message from zjqaohpd b"hello, I‘m Alice 2019-06-18 21:03:28.604293" lost connect: v0f4fhl3 lost connect: zjqaohpd
观察 Alice 客户端:
started to connect. Connected to the server! got messages: 欢迎来到 Twisted World, 您是第 1 个客户端用户! got messages: hello, I‘m Bob 2019-06-18 21:03:13.586417 got messages: hello, I‘m Bob 2019-06-18 21:03:23.600063 Disconnected from the server! Lost connection. Reason: [Failure instance: Traceback (failure with no frames): <class ‘twisted.internet.error.ConnectionDone‘>: Connection was closed cleanly. ]
结合服务器程序、客户端程序中的代码,在连接建立与关闭时回调事件函数的执行顺序如下:
即 建立连接时先执行 ClientFactory 中的回调,然后执行 Protocol 中的回调,而连接断开时则正好相反。
标签:构造 pytho 监听 需要 ESS %s back client mac
原文地址:https://www.cnblogs.com/51try-again/p/11046115.html