2.6 *Twisted框架介绍
Twisted是一个完整的事件驱动的网络框架,利用它既能使用也能开发完整的异步网络应用程序和协议。在编写本书时,因为它还不是Python标准库的一部分,所以必须单独下载并安装它(可以使用本章末尾的链接)。它提供了大量的支持来建立完整的系统,包括网络协议、线程、安全性和身份验证、聊天/ IM、DBM及RDBMS数据库集成、Web/因特网、电子邮件、命令行参数、GUI集成工具包等。
使用Twisted来实现简单的例子,有点小题大做,但是你必须开始使用它,并且该应用程序就相当于网络应用程序的“hello world”。
与SocketServer类似,Twisted的大部分功能都存在于它的类中。特别是对于该示例,我们将使用Twisted因特网组件中的reactor和protocol子包中的类。
2.6.1 创建Twisted Reactor TCP服务器
你会发现示例2-10中的代码类似于SocketServer例子中的代码。然而,相比于处理程序类,我们创建了一个协议类,并以与安装回调相同的方式重写了一些方法。另外,这个例子是异步的。现在就让我们看一下服务器代码。
示例2-10 Twisted Reactor时间戳TCP服务器(tsTservTW.py)
这是一个时间戳TCP服务器,它使用了Twisted Internet类。
逐行解释
第1~6行
设置行代码包括常用模块导入,尤其是twisted.internet的protocol和reactor子包以及常数端口号的设置。
第8~14行
我们获得protocol类并为时间戳服务器调用TSServProtocol。然后重写了connectionMade()和dataReceived()方法,当一个客户端连接到服务器时就会执行connectionMade()方法,而当服务器接收到客户端通过网络发送的一些数据时就会调用dataReceived()方法。reactor会作为该方法的一个参数在数据中传输,这样就能在无须自己提取它的情况下访问它。
此外,传输实例对象解决了如何与客户端通信的问题。你可以看到我们如何在connectionMade()中使用它来获取主机信息,这些是关于与我们进行连接的客户端的信息,以及如何在dataReceived()中将数据返回给客户端。
第16~20行
在服务器代码的最后部分中,创建了一个协议工厂。它之所以被称为工厂,是因为每次得到一个接入连接时,都能“制造”协议的一个实例。然后在reactor中安装一个TCP监听器,以此检查服务请求。当它接收到一个请求时,就会创建一个TSServProtocol实例来处理那个客户端的事务。
2.6.2 创建Twisted Reactor TCP客户端
与SocketServer TCP客户端不同,示例2-11看起来与其他客户端都不同,这个是明显的Twisted。
示例2-11 Twisted Reactor时间戳TCP客户端(tsTclntTW.py)
同样是我们熟悉的时间戳TCP客户端,只是从一个Twisted的角度来写的。
逐行解释
第1~6行
再一次,除了导入Twisted组件之外,并没有什么新内容。它与其他的客户端非常类似。
第8~22行
类似于服务器,我们通过重写connectionMade()和dataReceived()方法来扩展Protocol,并且这两者都会以与服务器相同的原因来执行。另外,还添加了自己的方法sendData(),当需要发送数据时就会调用它。
因为这次我们是客户端,所以我们是开启与服务器对话的一端。一旦建立了连接,就进行第一步,即发送一条消息。服务器回复之后,我们就将接收到的消息显示在屏幕上,并向服务器发送另一个消息。
以上行为会在一个循环中继续,直到当提示输入时我们不输入任何内容来关闭连接。此时,并非调用传输对象的write()方法发送另一个消息到服务器,而是执行loseConnection()来关闭套接字。当发生这种情况时,将调用工厂的clientConnectionLost()方法以及停止reactor,结束脚本执行。此外,如果因为某些其他的原因而导致系统调用了clientConnectionFailed(),那么也会停止reactor。
在脚本的最后部分创建了一个客户端工厂,创建了一个到服务器的连接并运行reactor。注意,这里实例化了客户端工厂,而不是将其传递给reactor,正如我们在服务器上所做的那样。这是因为我们不是服务器,需要等待客户端与我们通信,并且它的工厂为每一次连接都创建一个新的协议对象。因为我们是一个客户端,所以创建单个连接到服务器的协议对象,而服务器的工厂则创建一个来与我们通信。
2.6.3 执行TCP服务器和客户端
与其他客户端类似,Twisted客户端也展示了输出。
$ tsTclntTW.py
> Where is hope
...sending Where is hope...
[Tue Apr 18 23:53:09 2006] Where is hope
> When words fail
...sending When words fail...
[Tue Apr 18 23:53:14 2006] When words fail
>
$
服务器恢复到单个连接。Twisted会保持连接,在每条消息发送后不会关闭传输。
$ tsTservTW.py
waiting for connection...
...connected from: 127.0.0.1
“connection from”的输出并不包含其他信息,因为我们只从服务器传输对象的getPeer()方法请求了主机/地址。
需要记住的是,大多数基于Twisted的应用程序都比本节给出的例子更加复杂。因为这是一个功能丰富的库,但是它确实有一定的复杂度,所以你需要做好准备。