文档章节

(转) Twisted : 第十二部分 改进诗歌下载服务器

水果糖
 水果糖
发布于 2016/01/27 13:23
字数 1809
阅读 13
收藏 0
点赞 1
评论 0

新的服务器实现

这里我们要新写一个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来利用了Twistednetstrings的实现。基类很好的处理了编码与解码功能,我们需要做的就是实现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展示了一个格式转换服务器通过两种协议提供格式转换服务(当然,我们的服务器只提供了一种协议):

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

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

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


本文转载自:http://blog.sina.com.cn/s/blog_704b6af70100py9n.html

共有 人打赏支持
水果糖
粉丝 15
博文 125
码字总数 51701
作品 0
深圳
程序员
(转) Twisted :第十一部分 改进诗歌下载服务器

诗歌下载服务器 到目前为止,我们已经学习了大量关于诗歌下载客户端的Twisted的知识,接下来,我们使用Twisted重新实现我们的服务器端。利益于Twisted的抽象机制,接下来你会发现我们前面已经...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted :第六部分 抽象地利用Twisted

打造可以复用的诗歌下载客户端 我们在实现客户端上已经花了大量的工作。最新版本的(2.0)客户端使用了Transports,Protocols和Protocol Factories,即整个Twisted的网络框架。但仍有大的改进...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted : 第十四部分 Deferred用于同步环境

介绍 这部分我们要介绍Deferred的另外一个功能。便于讨论,我们设定如下情景:假设由于众多的内部网请求一个外部诗歌下载服务器,但由于这个外部下载服务器性能太差或请求负荷太重。因此,我...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted :第五部分 Twisted支持的诗歌客户端

抽象地构建客户端 在第四部分中,我们构建了第一个使用Twisted的客户端。它确实能很好地工作,但仍有提高的空间。 首先是,这个客户端竟然有创建网络端口并接收端口处的数据这样枯燥的代码。...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted :第二十部分 轮子中的轮子: Twisted和Erlang

简介 在这个系列中,有一个事实我们还没有介绍,即混合同步的"普通Python"代码与异步Twisted代码不是一个简单的任务,因为在Twisted程序中阻滞不定时间将使异步模型的优势丧失殆尽. 如果你是初次...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted : 第二部分 异步编程初探与reactor模式

第二部分:低效的诗歌服务器来启发对Twisted机制的理解 这个系列是从这里开始的,欢迎你再次来到这里来。现在我们可能要写一些代码。在开始之前,我们都做出一些必要的假设。 关于对你的假设 ...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted :第十部分 增强defer功能的客户端

现在我们将要向诗歌下载客户端添加一些新的处理逻辑,包括在第九部分提到要添加的功能。不过,首先我要说明一点:我并不知道如何实现Byronification引擎。那超出了我的编程能力范围。取而代之...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted :第十六部分 Twisted 进程守护

简介 目前我们所写的服务器仅仅运行在终端窗口,结果通过 语句输出到屏幕.这对于开发来说已经足够,但对于产品级的部署还远远不够. 健壮的产品级服务器应该: 运行一个 daemon 进程,这个进程...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted :第二十一部分 惰性不是迟缓: Twisted和Haskell

简介 在上一个部分我们对比了Twisted与 Erlang,并将注意力集中在它们共有的一些思想上.结果表明使用Erlang也是非常简便的,因为异步I/O和反应式编程是Erlang运行时和进程模型的关键元素. 今天...

水果糖 ⋅ 2016/01/27 ⋅ 0

(转) Twisted :第十九部分 改变之前的想法

简介 Twisted是一个正在进展的项目,它的开发者会定期添加新的特性并且扩展旧的特性. 随着Twisted 10.1.0发布,开发者向 类添加了一个新的特性—— ——这正是我们今天要研究的. 异步编程将请求...

水果糖 ⋅ 2016/01/27 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

一篇文章学懂Shell脚本

Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合。 Shell可以直接使用在win/Unix/Linux上面,并且可以调用...

Jake_xun ⋅ 25分钟前 ⋅ 0

大数据工程师需要精通算法吗,要达到一个什么程度呢?

机器学习是人工智能的一个重要分支,而机器学习下最重要的就是算法,本文讲述归纳了入门级的几个机器学习算法,加大数据学习群:716581014一起加入AI技术大本营。 1、监督学习算法 这个算法由...

董黎明 ⋅ 57分钟前 ⋅ 0

Kylin 对维度表的的要求

1.要具有数据一致性,主键值必须是唯一的;Kylin 会进行检查,如果有两行的主键值相同则会报错。 2.维度表越小越好,因为 Kylin 会将维度表加载到内存中供查询;过大的表不适合作为维度表,默...

无精疯 ⋅ 今天 ⋅ 0

58到家数据库30条军规解读

军规适用场景:并发量大、数据量大的互联网业务 军规:介绍内容 解读:讲解原因,解读比军规更重要 一、基础规范 (1)必须使用InnoDB存储引擎 解读:支持事务、行级锁、并发性能更好、CPU及...

kim_o ⋅ 今天 ⋅ 0

代码注释中顺序更改 文件读写换行

`package ssh; import com.xxx.common.log.LogFactory; import com.xxx.common.log.LoggerUtil; import org.apache.commons.lang3.StringUtils; import java.io.*; public class DirErgodic ......

林伟琨 ⋅ 今天 ⋅ 0

linux实用操作命令

参考 http://blog.csdn.net/qwe6112071/article/details/50806734 ls [选项] [目录名 | 列出相关目录下的所有目录和文件 -a 列出包括.a开头的隐藏文件的所有文件-A 同-a,但不列出"."和"...

简心 ⋅ 今天 ⋅ 0

preg_match处理中文符号 url编码方法

之前想过直接用符号来替换,但失败了,或者用其他方式,但有有些复杂,这个是一个新的思路,亲测可用 <?php$str='637朗逸·超速新风王(300)(白光)'; $str=iconv("UTF-8","GBK",$s...

大灰狼wow ⋅ 今天 ⋅ 0

DevOps 资讯 | PostgreSQL 的时代到来了吗 ?

PostgreSQL是对象-关系型数据库,BSD 许可证。拼读为"post-gress-Q-L"。 作者: Tony Baer 原文: Has the time finally come for PostgreSQL?(有删节) 近30年来 PostgreSQL 无疑是您从未听...

RiboseYim ⋅ 今天 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 今天 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部