Python Twisted 学习系列12(转载stulife最棒的Twisted入门教程)

第十二部分 改进诗歌下载服务器

作者:[email protected]http://krondo.com/?p=2101译者:杨晓伟(采用意译)

第十二部分 改进诗歌下载服务器

你可以从这里从头阅读这个系列。

新的服务器实现

这里我们要新写一个Twisted版的服务器。然后,再来讨论一些Deferred的新功能。

在第九、十部分,我们提出了诗歌转换引擎这个概念。由于其实现太过简单,因此我们用随机选择来模拟了可能会出现转换失败的情景。但如果转换引擎位于服务器端,那么当服务器宕机就会出现真实的转换失败的情景了。

因此,在这部分我们要实现一个诗歌样式转换服务器,然后在一个部分,我们会重写我们的诗歌下载客户端来使用这一服务并且学习Deferred的新功能。

设计协议

到目前为止,服务器端与客户端之间的交互都是单向的。但样式转换服务需要两者进行双向交互-客户端将原始式样的诗歌发送给乳服务器,然后服务器将转换格式并将其发送给对应的客户端。因此,我们需要使用、或自己实现一个协议来实现这种交互。

我们设计服务器端可以提供若干种转换服务,而让客户端来进行选择。因此客户端需要向服务器端发送两部分信息:转换方式名与诗歌原始内容。服务器只是将转换格式之后的诗歌发送给客户端。这里使用到了简单的运程调用

Twisted支持需要种协议来解决这个问题:XML-RPC,Perspective Broker,AMP。

但介绍使用其中任何一种都需要大量的时间,因此我们使用自己实现的协议。我们约定客户端发送内容格式如下:

转换名称.诗歌内容

我们将其以netstring格式编码,当然服务器回发的信息也是以netstring格式编码。由于netstring使用了length-encoding,因此客户端能够识别出服务器没有将完整诗歌回发的情况。如果你尝试一下前面的协议,其无法检测到中途中断传输的情况。

代码

新的服务器实现代码在twisted-server-1/transformedpoetry.py中。首先,我们定义了一个TransformService类:

class TransformService(object):

def cummingsify(self, poem):

return poem.lower()

这里我们仅仅实现了一种转换方法,我们可以不回新格式转换方法。有一个重要的地方需要注意:格式转换服务与具体协议的实现是完全分分离的。将协议逻辑与服务逻辑分开是Twisted编程中常见的模式。这样做可以通过多种协议实现同一种服务,以增加了代码的重用性。

下面看看factory的实现代码:

class TransformFactory(ServerFactory):

protocol = TransformProtocol

def __init__(self, service):

self.service = service

def transform(self, xform_name, poem):

thunk = getattr(self, ‘xform_%s‘ % (xform_name,), None)

if thunk is None: # no such transform

return None

try:

return thunk(poem)

except:

return None # transform failed

def xform_cummingsify(self, poem):

return self.service.cummingsify(poem)

factory提供了一个transform的函数,protocol就是用它来代表客户端连接请求进行诗歌格式转换。

如果发现没有客户端请求的转换方法或转换失败,那么返回None。和TransformService一样,factory与具体的协议逻辑实现也是相互独立的。

有一个地方需要引起注意:我们通过xfomr_前缀式方法来获取服务方法。这种方法在Twisted中很常见,尽管前缀经常发生变化,并且他们经常是依赖于独立于factory的一个对象(如此处的 TransformService)这是一种防止客户端使用蓄意恶性代码来让服务器端执行的方法。这种方法也提供了实现由服务提供具体协议代理的机制。

下面是协议实现代码:

class TransformProtocol(NetstringReceiver):

def stringReceived(self, request):

if ‘.‘ not in request: # bad request

self.transport.loseConnection()

return

xform_name, poem = request.split(‘.‘, 1)

self.xformRequestReceived(xform_name, poem)

def xformRequestReceived(self, xform_name, poem):

new_poem = self.factory.transform(xform_name, poem)

if new_poem is not None:

self.sendString(new_poem)

self.transport.loseConnection()

在这个协议的实现中,我们通过继承NetstringReceiver来利用了Twisted对netstrings的实现。基类很好的处理了编码与解码功能,我们需要做的就是实现stringReceived方法。换句话说,stringReceived接收的参数是客户端编码之后的诗歌,而无需我们再去添加额外的编码信息。而且基类同样管理着缓冲区,即当一首诗歌完整接收完再进行解码。

如果一切进展正常的话,我们会使用NetstringReceiver的 sendString方法来将格式转换成功后的诗歌发送给客户端。

注意我们是如何通过定义xformRequestReceived方法将收到的信息一步步推向更高的抽象层而实现了Twisted的模式。

一个简单的客户端

我们会在下一个部分来实现相应的客户端,这里使用一个简单的脚本来实现客户端,代码位于twisted-server-1/transform-test中。如果你运行服务器端于11000端口:

python twisted-server-1/transformedpoetry.py --port 11000

相应的运行脚本为:

./twisted-server-1/transform-test 11000

那么你会看到如下输出(经过netstring编码):

15:here is my poem,

讨论

在这个部分介绍了如下几个方面内容:

1.双向通信

2.基于Twisted已有的协议实现新协议

3.将协议实现与服务功能实现独立分开

双向通信的基本机制是很简单的。我们使用前面服务器端与客户端使用的相同的技术来写与读数据,唯一不同的是我们这次两者都使用了(读与写)。当然,一个复杂的协议需要复杂的代码来处理接收到的数据流与格式化输出的信息。这也是为什么使用已经存在的协议的原因。

如果你开始觉得写简单的协议已经很上手了,那么最好就开始看看Twisted对不同协议的实现。尽管写一些简单的协议有助理解Twisted的编程风格,但在一个真实的程序中,最好是复用那些已经实现并证明性能良好的协议。

最后一点是将协议解析逻辑与服务实现逻辑分开,这是Twisted编程中非常重要的一个模式。我们这个服务器程序只是一个演示,你可以想象一下真实的网络服务是相当复杂的。通过将服务与协议逻辑分开,你可以通过复用已有的服务代码来运行于其它的协议实现上。

图27展示了一个格式转换服务器通过两种协议提供格式转换服务(当然,我们的服务器只提供了一种协议):

图27 提供两种协议支持的格式转换服务器

虽然在图27中使用了两种协议,但他们也许是只有几个协议属性不同。factory共享相同的服务。这样实现了代码的复用。

时间: 2024-12-10 21:13:06

Python Twisted 学习系列12(转载stulife最棒的Twisted入门教程)的相关文章

Python Twisted 学习系列3(转载stulife最棒的Twisted入门教程)

第三部分:初步认识Twisted 作者:[email protected]http://krondo.com/?p=1333译者:杨晓伟(采用意译) 第三部分:开始认识Twisted 可以从这里从头开始阅读这个系列. 用twisted的方式实现前面的内容 最终我们将使用twisted的方式来重新实现我们前面的异步模式客户端.不过,首先我们先稍微写点简单的twisted程序来认识一下twisted. 最最简单的twisted程序就是下面的代码,其在twisted-intro目录中的basic-tw

Python Twisted 学习系列1(转载stulife最棒的Twisted入门教程)

第一部分:Twisted理论基础 作者:[email protected]http://krondo.com/?p=1209译者:杨晓伟(采用意译) 前言: 最近有人在Twisted邮件列表中提出诸如”为任务紧急的人提供一份Twisted介绍”的的需求.值得提前透露的是,这个序列并不会如他们所愿.尤其是介绍Twisted框架和基于Python 的异步编程而言,可能短时间无法讲清楚.因此,如果你时间紧急,这恐怕不是你想找的资料. 我相信如果对异步编程模型一无所知,快速的介绍同样无法让你对其有所理解

Python Twisted 学习系列4(转载stulife最棒的Twisted入门教程)

第四部分:由Twisted支持的诗歌客户端 作者:[email protected]://krondo.com/?p=1445译者:杨晓伟(采用意译) 第四部分:由Twisted支持的诗歌客户端 你可以在这里从头开始阅读这个系列. 第一个twisted支持的诗歌服务器 尽管Twisted大多数情况下用来写服务器代码,为了一开始尽量从简单处着手,我们首先从简单的客户端讲起. 让我们来试试使用Twisted的客户端.源码在twisted-client-1/get-poetry.py.首先像前面一样要

Python Twisted 学习系列20(转载stulife最棒的Twisted入门教程)

第二十部分 轮子中的轮子: Twisted和Erlang 简介 在这个系列中,有一个事实我们还没有介绍,即混合同步的"普通Python"代码与异步Twisted代码不是一个简单的任务,因为在Twisted程序中阻滞不定时间将使异步模型的优势丧失殆尽. 如果你是初次接触异步编程,那么你得到的知识看起来有一些局限.你可以在Twisted框架内使用这些新技术,而不是在更广阔的一般Python代 码世界中.同时,当用Twisted工作时,你仅仅局限于那些专门为作为Twisted程序一部分所写的

Python Twisted 学习系列19(转载stulife最棒的Twisted入门教程)

第十九部分 改变之前的想法 简介 Twisted是一个正在进展的项目,它的开发者会定期添加新的特性并且扩展旧的特性. 随着Twisted 10.1.0发布,开发者向 Deferred 类添加了一个新的特性—— cancellation ——这正是我们今天要研究的. 异步编程将请求和响应解耦了,如此又带来一个新的可能性:在请求结果和返回结果之间,你可能决定不再需要这个结果了.考虑一下 :doc:`p14` 中的诗歌代理服务器.下面是这个如何工作的,至少对于诗歌的第一次请求: 一个对诗歌的请求来了.

Python Twisted 学习系列11(转载stulife最棒的Twisted入门教程)

第十一部分:改进诗歌下载服务器 作者:[email protected]http://krondo.com/?p=2048译者:杨晓伟(采用意译) 第十一部分:改进诗歌下载服务器 你可以从这里从头阅读这个系列. 诗歌下载服务器 到目前为止,我们已经学习了大量关于诗歌下载客户端的Twisted的知识,接下来,我们使用Twisted重新实现我们的服务器端.利益于Twisted的抽象机制,接下来你会发现我们前面已经几乎全部学习到这部分知识了.其实现源码在twisted-server-1/fastpoe

Python Twisted 学习系列22(转载stulife最棒的Twisted入门教程)

第二十二部分 结束 全部完成 呼呼! 感谢你一路支持. 在我开始时完全没有想到这个系列会这样长,会花这么多时间完成,但是创建这个系列的过程使我非常享受,也希望你喜欢它. 既然我已经完成了,我会进一步考虑将其转化为PDF格式.然而,不保证. 最后,我想总结一些帮助你继续学习Twisted的建议. 进一步阅读 首先,我建议阅读Twisted的 在线文档. 虽然它备受指责,但我觉得这总比饱受赞誉要好. 如果你希望使用Twisted进行网络编程, 那么 Jean-Paul Calderone 的广受关注

Python Twisted 学习系列21(转载stulife最棒的Twisted入门教程)

第二十一部分 惰性不是迟缓: Twisted和Haskell 简介 在上一个部分我们对比了Twisted与 Erlang,并将注意力集中在它们共有的一些思想上.结果表明使用Erlang也是非常简便的,因为异步I/O和反应式编程是Erlang运行时和进程模型的关键元素. 今天我们想走得更远一点,去看一看 Haskell —— 另一种功能性语言,然而与Erlang有很大不同(当然与Python也不同).这里面没有太多的平行概念,但我们仍然会发现藏在下面的异步I/O概念. F —— 功能性 虽然Erl

Python Twisted 学习系列5(转载stulife最棒的Twisted入门教程)

第五部分:由Twisted支持的诗歌客户端 作者:[email protected] http://krondo.com/?p=1522译者:杨晓伟(采用意译) 第五部分:由Twited支持的诗歌下载服务客户端 你可以从这里从头开始阅读这个系列 抽象地构建客户端 在第四部分中,我们构建了第一个使用Twisted的客户端.它确实能很好地工作,但仍有提高的空间. 首先是,这个客户端竟然有创建网络端口并接收端口处的数据这样枯燥的代码.Twisted理应为我们实现这些例程性功能,省得我们每次写一个新的程