twisted系列教程十二–为server 增加一个service
One More Server
在第九部分和第十部分我们介绍了关于诗歌的变形引擎的想法,最后我们实现了cummingsifier,我们还让它抛出随机的异常来模拟错误.但是假如这个变形的引擎在另外一台服务器上,提供一种网络的”poetry transformation service”, 那么现在又多出来一种出错的方式:变形引擎挂掉了.
所以在第十二部分我们将要实现一个poetry transformation server,并在下一部分,我们让我们的client 使用一个外部的transformation service,并从中学到Deferred 的一些东西.
Designing the Protocol
到现在为止client 和server 端的交互都是单向的,server 端向client端发送一首诗,而client 什么也向server 发送.但是一个transformation service 是双向的– client 端向server发送一首诗然后服务端发送给client 一首变形后的诗.所以我们需要一个新的protocol来处理这种交互.
在我们实现这个的时候,我们让server 支持多种的变形方式,并让client 可以选择使用哪一种.所以client 需要发送给server两个数据:变形的方式和这首诗的内容.我们的server 会返回变化后的诗.所以呢,我们已经完成了一个简单的Remote Procedure Call.
twisted 包含了几个实现这个问题的几种protocol,包括XML-RPC, Perspective Broker, 和 AMP.
但是呢,用这些已经实现了的protocol 会让我们走的太远了,所以最好我们还是自己实现一个.让我们的client 发送一个如下的字符串:
.
也就是一个变形引擎的名字和这首诗歌的内容中间用一个点连接.我们还会把这个字符串编码成netstring 的形式.server 端会返回已经变形过的诗,也是netstring 的方式.因为netstring 使用了带长度的编码,client 可以检测到是否server端发送了一个完整版本的诗.如果你回想一下的话,我们原来的protocol 很难检测到中途停止发送的情况.
有关protocol 的设计先介绍这些,对于我们来说已经够用了.
The Code
让我们来看一下我们的ransformation server,在 twisted-server-1/transformedpoetry.py,首先,我们定义了一个TransformService 类:
class TransformService(object):
def cummingsify(self, poem):
return poem.lower()
这个transform service 目前只支持一种变形–cummingsify.通过一个同名方法.我们还可以增加其他的算法.我们需要注意的是:transformation service 是完全独立于我们之前所说的protocol 的.把protocol 的逻辑和 service 的逻辑分开在twisted 编程中是一个经常用的模式.这样做的话可以通过不同的protocol 来提供相同的transformation service而不用修改太多的代码.
下面让我们看一下protocol 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 提供了一个变形的方法,一个protocol 可以用它来得到一个poetry transformation.如果没有这个方法相对应的transformation或这个transformation失败了,这个方法会返回None.就像TransformService 一样,这个protocol factory 和protocol 也是相互独立的,但是factory 中的方法protocol 都是可以调用的.
你需要注意的是我们是怎样保护带有xform_前缀地 方法.这是一种在twisted 源码中经常用的模式.这是一种防止客户端的代码直接调用service 对象方法的方法,因为客户端可能传递过来任何的 transform name.
下面我们来看一下protocol 的实现:
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()
在protocol 的实现中我们利用了Twsited 已经实现的NetstringReceiver protocol.这个基类会负责netstring 的编码和解码,我们所要去做的就是实现stringReceived 方法.换句话说,stringReceived会被传递进从client 那边接收过来的诗的内容.这个基类也会负责缓冲传进来的数据直到我们有足够的数据去解码出来一首完整的诗.
假如一切都正常的话我们会通过NetstringReceiver 提供的sendString方法发送变过形的诗到客户端.这就是全部要做的工作.main 函数由于没有什么变化,我们在这里就不讲了.
注意我们是怎样通过定义xformRequestReceived 方法利用twisted 模式将传进来的字节流变化成更高级的抽象,最后xformRequestReceived 被传递进两个参数–一个是变形的名字另一个是诗的内容.
A Simple Client
在第十三部分我们会实现一个利用ransformation service 的twisted client.但现在我们仅仅用一段脚本来测试我们的server,代码在twisted-server-1/transform-test.它用netcat程序向server 发送一首诗歌的内容并打印出返回的结果.让我们先开启我们的server:
python twisted-server-1/transformedpoetry.py --port 11000
然后运行我们的测试脚本:
./twisted-server-1/transform-test 11000
你看看到下面的额输出:
15:here is my poem,
Discussion
在这一部分我们介绍了一些新的想法:
双向的通信
在twisted 已经提供的protocol 实现上进行编程
使用一个service 对象来分开功能逻辑和protocol 逻辑
双向通信的结构是非常简单的,读数据和写数据中我们都使用了同样的技术,与之前的server 和client 不同的是我们同时使用了它们两个.当然,一个更复杂的protocol会需要更复杂的代码来处理字节流,这也是我们为什么使用了一个已经存在的protocol 实现.
一但你熟悉了一些基本的protocol 的实现,建议你去看看twisted 自带的一些复杂的协议.你可以从twisted.protocols.basic 模块读起.写一些简单的protocol 是你熟悉twisted 编程的很好的方式.在一些真正twisted 程序中,更有可能去使用一个已经被实现的protocol.
使用一个service对象来把功能逻辑和protocol逻辑分开在twisted 编程中是一个很重要的设计模式,尽管我们今天将的这个变形的service 不是特别重要,你可以想象在一个大型的应用中一个service可能会非常复杂.通过让service 和 protocol 分离,我们可以快速的在不同的protocol上提供相同的service.
图片二十七描述了一个transformation server通过两种不同的protocol 的来进行服务:
图片二十七
尽管我们需要两个protocol factory,它们可能也就protocol 不同.这个两个protocol factory共用一个service 对象,剩下的就是protocol 需要分开实现.这样我们就实现了数据复用.
Looking Ahead
有关我们的transformation server 暂时就讲这么多,在第十三部分,我们会继续改进我们的client,让它可以直接利用我们的service.
twisted系列教程十二–为server 增加一个service相关推荐
- twisted系列教程十六–twisted守护进程
Introduction 到目前为止我们写的server 还运行在一个终端里面,通过print 语句向外输出内容.开发的时候这样做是很有好处的,但是当你部署一个产品的时候这样就不好了.一个生产环境中的 ...
- twisted系列教程十四— pre-fireed deferred
Introduction 在这一部分我们将要学习deferred 类的另外的一个方面.为了促进讨论,我们要为我们的poetry service增加一个server.假设我们有大量的内部的client ...
- twisted系列教程十九–cancel deferred
Introduction twisted 是一个正在发展的项目,twisted 的开发者们会添加一些新的特色或者扩展旧的.随着twisted 10.1.0 的发布,开发者们增加了一个新的功能–取消,这 ...
- twisted系列教程十五–测试twisted代码
Introduction 在这个系列中我们也已经写了很多twisted 代码了,但目前为止我们忽略了一个很重要的事情-测试.你可能也一直在想我们怎样用一个同步的测试框架unitest来测试我们的异步的 ...
- twisted系列教程十–可以变化的诗
Client 5.0 现在我们将要想我们的client中加入一些变形逻辑.但是首先我不得不说:我不知道怎样写一个Byronification 引擎,它超出我的能力范围了.做为替代,我会实现一个相对简单 ...
- twisted系列教程十八–异步操作的并行运行
Introduction 在上一部分我们学习了一种新的用生成器来组织一系列异步callbacks 的方法.加上deferred,我们已经有两种组织异步操作的方法了. 有时候,我们想让一组异步操作并行的 ...
- (爱加密系列教程十二) 如何防止jd-gui查看代码
使用jd-gui查看class文件的时候,经常会发现有一些方法或类,无法正常的显示出来. 我们可以利用这个bug,来阻止jd-gui反编译我们的class文件. 首先反编译一个有源码的项目,用 jd- ...
- twisted系列教程十三–deferred 中的deferred
Introduction 回想一下第十部分的poetry client 5.1,client 用一个deferred 来管理一个callback 链,这个callback 链中调用了一个transfo ...
- SQL Server2000系列教程(二)---企业管理器
[转帖]SQL Server2000系列教程(二)---企业管理器 昨天我们学习了如何安装SQL Server 2000,今天我们就来学一些简单的应用.首先来看看企业管理器. 从"开始&qu ...
最新文章
- 英国政府发布5G政策文件
- java 去除干扰_【Selenium-WebDriver实战篇】Java丨验证码图片去除干扰像素,方便验证码的识别(转)...
- 在spring boot中集成Swagger
- 2015 多校第三场
- C++ 有参构造 无参构造 拷贝构造 以及参数化列表 成员对象之间的执行关系
- Scrum之 Sprint计划会议
- container_of宏
- LeetCode 2206. 将数组划分成相等数对
- Hive导入csv文件
- BZOJ 1606: [Usaco2008 Dec]Hay For Sale 购买干草(动态规划)
- 国内外各大免费搜索引擎、导航网址提交入口(转载)
- ASP.NET Web Forms 自学篇:(一)简介
- php限制选择图片数量,ImagePicker组件,限制选择图片数量上限(selectable={images.length 3} )失败...
- lempel ziv matlab,精讲Lempel-Ziv压缩算法
- 跟我学Linux系统管理 第三讲 磁盘管理
- 【WORD技巧合集】
- 中国科学技术大学 先进技术研究院
- Highcharts 江湖就这样
- php 无限极分类(两种方式)
- 历数金融危机 摘自http://www.ftchinese.com/sc/index.jsp
热门文章
- 那个一年发4篇cell的研究生后来怎样了?
- 感到压力时,你秃的是头,而TA秃的是屁股
- 用python计算准确率_分词结果准确率、召回率计算-python(示例代码)
- WebSocket之仿QQWeb即时聊天系统(上)
- 无悔入华夏怎么一直显示服务器,无悔入华夏新手开局玩法 无悔入华夏新手攻略开局带的...
- qt android文件读写文件,qt android 开发之写入xml配置文件篇
- uniapp ios时间戳获取不到_2折甩卖、货架被抢空…青岛这家大超市要关门,开业不到两年!停业时间戳...
- Qt文档阅读笔记-Q_INVOKABLE官方解析及Qt中反射的使用
- Web前后端笔记-通过对称加密算法和信息摘要算法防止数据重放
- OpenCV如何修改Mat中某像素(某通道的数值)