热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Twisted网络编程必备(1)注:测试版本Twisted10.1.0.winxp32py2.6,对于原代码略有修改

转自:http:www.yybug.comread-htm-tid-15324.html为什么使用Twisted? 如果你并不准备使用Twisted,你可能有很多异议。为什么使用T





转自:http://www.yybug.com/read-htm-tid-15324.html


为什么使用Twisted?


 


如果你并不准备使用Twisted,你可能有很多异议。为什么使用Twisted而不是其他网络函数库或框架?如下是一些充分的理由:


·基于Python


Twisted是使用Python编写的,强壮的、面向对象的解释性语言。Python使它的爱好者充满热情。使用Python编程是一种乐趣,易于编写、易于阅读、易于运行。因为Python是跨平台的,所以可以运行Twisted程序在Linux、Windows、Unix和MAC等等系统上。


·异步和事件驱动的


同步网络编程函数库留给开发者一个痛苦的抉择:要么允许程序在网络通信时失去响应,或者引入非常复杂的线程。Twisted是基于事件的,异步网络通信框架允许编写的程序在处理事件时保持相应,却不需要使用线程。


·多功能


Twisted包括大量的功能。Email、WEB、news、chat、DNS、SSH、Telnet、RPC、数据库存取或者更多。所有的都为你准备好了。


·灵活


Twisted提供了高层类允许快速开始。而且并没有感到受限。如果需要高级功能,或者需要自定义网络协议,也是可以的。你可以实现自己的网络协议,控制每一个字节。


·开放源代码


Twisted是免费的。它包含源代码,按照函数库协议发行。并且欢迎在你的程序中使用Twisted,不必支付任何费用和担心法律问题。如果希望知道一个对象的运行原理也可以直接看源码。如果你开发出了自己的新功能和扩展,欢迎与我们共享。


·社区支持


Twisted有一个活跃的社区包含开发者和用户。如果你发现了问题,也可以在邮件列表上找到很多开发者来帮助你。查看第一章的寻找FAQ一节。或者进入#twisted这个IRC频道,来与开发者进行在线交流。


·易于整合的平台


一个Twisted程序可以在多种服务之间共享数据,可以整合很多工作。比如可以编写SMTP到XMLRPC的代理,一个通过SSH来更新网站的服务,或者一个包含NNTP接口的WEB讨论组。如果需要在平台之间交换数据,Twisted是个很好的选择。


 


启动Twisted的事件循环


Twisted是事件驱动的框架。这意味着不再使用特定序列来处理程序逻辑,而是通过被动调用一些函数来实现。例如,GUI程序里面使用的"button pressed"事件。设计者不需要事先确定事件何时发生,只需要编写事件的响应函数即可。这就是所谓的事件处理器(event handler)。


 


每个事件驱动的框架都包含了一个特殊的函数叫做事件循环(event loop)。每次启动,事件循环都会立即运行。这个函数运行时等待事件的发生。当事件发生时,事件循环函数会自动触发相关的事件处理函数。


使用事件循环需要改变一些顺序编程的习惯。一旦开始了事件循环,你将无法控制程序的执行顺序,只会自动响应事件。所以,你需要为程序设计事件处理器。也就是事件发生时的响应。


在Twisted中,有一种特殊的对象用于实现事件循环。这个对象叫做reactor。可以把反应器(reactor)想象为Twisted程序的中枢神经。除了分发事件循环之外,反应器还做很多重要的工作:定时任务、线程、建立网络连接、监听连接。为了让反应器可以正常工作,需要启动事件循环


 


启动反应器


 


启动反应器是很简单的,从twisted.internet模块导入reactor对象。然后调用reactor.run()来启动反应器的事件循环。下例展示了代码:




from twisted.internet.selectreactor import SelectReactor
print 'Running the reactor ...'
reactor = SelectReactor()
reactor.run()
print 'Reactor stopped.'


 


反应器将会一直运行,直到接到停止的通知,可以按下Ctrl+C来退出事件循环,并终止程序:




$ python runreactor.py
Running the reactor ...
<ctrl-c>
^CReactor stopped.


 


这是一个简洁的例子。尽管反应器运行着,但是没有做任何事情。下面的例子提供了更多有趣的事情,介绍了反应器的callLater方法。reactor.callLater方法用于设置定时事件。这个方法在用于定时在未来执行。比如一个函数已经是一个事件处理器了,这种事件会在一定时间之后启动。下面的例子,函数调用了一定时间之后被调用:


 



代码


from twisted.internet.selectreactor import SelectReactor
import time
reactor = SelectReactor()
def printTime():
print 'Current time is',time.strftime("%H:%M:%S")
def stopReactor():
print "Stopping reactor"
reactor.stop()
reactor.callLater(
1,printTime)
reactor.callLater(
2,printTime)
reactor.callLater(
3,printTime)
reactor.callLater(
4,printTime)
reactor.callLater(
5,stopReactor)
print 'Running the reactor ...'
reactor.run()
print 'Reactor stopped.'



 


运行这个程序,可以看到如下结果:


$ python calllater.py


Running the reactor ...


Current time is 10:33:44


Current time is 10:33:45


Current time is 10:33:46


Current time is 10:33:47


Stopping reactor


Reactor stopped.


 


它是如何工作的


 


第一个例子简介了导入与执行reactor.run()来启动事件循环。反应器将会一直保持执行直到按下Ctrl-C,尽管这一段时间什么都不做。在这时,反应器停止了,程序执行到代码的最后一行,并打印出反应器已经停止的消息。


第二个例子使用reactor.callLater函数定时执行函数。reactor.callLater函数包含两个必须参数,等待的秒数,和需要调用的函数。在设置了定时函数调用之后,控制就回到了反应器的事件循环reactor.run()中了。


Tip:你可以传递附加的参数和键值对到reactor.callLater中,这些用于调用指定的函数。例如,reactor.callLater(1,func,True,x="Hello"),将会最终调用func(True,x="Hello"),在一秒钟之后。


第一个定时函数是printTime(),简单显示了当前时间。第五个定时函数是stopReactor(),其中调用了reactor.stop(),导致了反应器退出了事件循环。这也是为什么不需要按下Ctrl-C而自动退出了事件循环的原因。


Tip:在这种情况下仍然可以按下Ctrl-C来手动停止事件循环。


注意事件的发生顺序,反应器按照给定的时间来调用指定的函数。一旦反应器开始运行,反应器就会控制事件循环,并在指定时间调用函数。反应器在被告知停止之前会一直运行,直到reactor.stop()调用。一旦反应器停止了,程序将继续处理最后一行,显示反应器停止的消息。


Tip:在实际应用中,reactor.callLater是常用于超时处理和定时事件。可以设置函数按照指定的时间间隔来执行关闭非活动连接或者保存内存数据到硬盘。


 


建立(establishing)一个TCP连接


 


所有的网络应用程序都必须做一个简单的步骤,开启一个连接。接着可以发送邮件、传递文件、看电影等等,但是在所有这些之前,必须在电脑之间建立一个连接。本节讲解了如何使用reactor开启TCP连接。


 


调用reactor.connectTCP()方法打开一个TCP连接,传递一个ClientFactory对象作为第三个参数。ClientFactory对象等待连接被建立,然后创建一个Protocol对象来管理连接中的数据流。下面的例子展示了如何在电脑和Internet之间建立一个连接(www.google.com):





代码


from twisted.internet.selectreactor import SelectReactor
from twisted.internet.protocol import Protocol,ClientFactory
reactor
= SelectReactor()
protocol
= Protocol()
class QuickDisconnectedProtocol(Protocol):
def connectionMade(self):
print "Connected to %s."%self.transport.getPeer().host
self.transport.loseConnection()
class BasicClientFactory(ClientFactory):
protocol
=QuickDisconnectedProtocol
def clientConnectionLost(self,connector,reason):
print 'Lost connection: %s'%reason.getErrorMessage()
reactor.stop()
def clientConnectionFailed(self,connector,reason):
print 'Connection failed: %s'%reason.getErrorMessage()
reactor.stop()
reactor.connectTCP(
'www.google.com',80,BasicClientFactory())
reactor.run()




 



 


当运行这个例子的时候,可以看到如下输出:


$ python connection.py


Connected to 66.249.89.104.
Lost connection: Connection was closed cleanly.


除非你的电脑没有在线。在这种情况下,会看到如下错误信息:


$ python connection.py


Connection failed: DNS lookup failed: address 'www.google.com' not found.


 


它是如何工作的


 


这里有两个主要的类用于作为客户端工作,ClientFactory和Protocol。这些类被设计成处理连接中所有可能运到的事件:成功建立连接、连接失败、连接断开、数据传送等等。


ClientFactory和Protocol有严格的不同。ClientFactory的工作是管理连接事件并且创建Protocol对象处理每一个成功的连接。一旦连接建立,Protocol对象就接管下面的工作了,包括收发数据和决定是否关闭连接。


Tip:名字"Factory"在ClientFactory是来自于Protocol的请求,响应每一个成功的连接。


例子定义了自定义的Protocol叫做QuickDisconnectProtocol,继承自protocol.Protocol。它重载了一个方法connectMade。这个方法连接成功时运行,在reactor刚刚成功建立了连接,然后ClientFactory创建了QuickDisconnectProtocol的实例时。有如他的名字,QuickDisconnectProtocol对象在打印信息之后就马上关闭了。


Tip:Protocol对象有一个属性叫做transport,包含了当前活动连接对象。


BasicClientFactory是继承自protocol.ClientFactory的类。它首先设置了类变量protocol为QuickDisconnectProtocol。这个类的实例被创建用于管理成功的连接。


BasicClientFactory重载了ClientFactory的两个方法,clientConnectionLost和clientConnectionFailed。这两个方法是事件处理器。clientConnectionFailed在反应器无法建立连接时被调用。clientConnectionLost在建立的连接被关闭或断开时调用。


告知反应器建立TCP连接,按照例子2-3的方法是调用reactor.connectTCP:


reactor.connectTCP('www.google.com',80,BasicClientFactory())


这一行告知反应器建立一个TCP连接到服务器www.google.com的80端口,通过BasicClientFactory来管理连接。







推荐阅读
  • Python库在GIS与三维可视化中的应用
    Python库极大地扩展了GIS的能力,使其能够执行复杂的数据科学任务。本文探讨了几个关键的Python库,这些库不仅增强了GIS的核心功能,还推动了地理信息系统向更高层次的应用发展。 ... [详细]
  • List & Label 19现已发布,此版本引入了报表参数、集合变量、扩展区域以及交互式排序等功能,并增加了对OData和REST数据提供器的支持,同时推出了包括组合图、堆叠图、漏斗图等在内的新型图表。 ... [详细]
  • 如何打造属于自己程序的菜单栏,以上代码清晰的展示了swing是如何创建菜单栏的。只要理清楚javaswing的容器和面板的逻辑顺序就能掌握swing ... [详细]
  • Java面向对象编程深入解析
    本文详细探讨了Java中的关键字static、单例模式、main()方法、代码块、final关键字、抽象类与方法、模板方法设计模式、接口、内部类等内容,旨在帮助读者深入理解和掌握Java面向对象编程的核心概念。 ... [详细]
  • 本文详细介绍了如何配置Apache Flume与Spark Streaming,实现高效的数据传输。文中提供了两种集成方案,旨在帮助用户根据具体需求选择最合适的配置方法。 ... [详细]
  • 在 Linux 系统中,除了基本的读取、写入和执行权限外,还存在三种特殊权限:Set User ID (SUID)、Set Group ID (SGID) 和 Sticky Bit。这些特殊权限用于增强系统的安全性和功能性。 ... [详细]
  • JSP服务器概述及搭建指南
    本文详细介绍了JSP服务器的概念、主流服务器软件及其搭建步骤,旨在帮助开发者更好地理解和使用JSP技术。 ... [详细]
  • JS的类型和值
    1.类型ECMAScript语言中所有的值都有一个对应的语言类型。ECMAScript语言类型包括Undefined、Null、Boolean、String、Number和Obje ... [详细]
  • 本文详细介绍了MooseFS中的副本管理(Goal)以及文件回收机制。副本管理允许用户设定文件的复制份数,确保数据的安全性和可用性;而文件回收机制则提供了在误删除文件后的恢复途径,通过设置合理的隔离时间,保护重要数据。 ... [详细]
  • 本文深入探讨了Redis中的两种主要持久化方式——RDB(Redis Database)和AOF(Append Only File),并详细解析了两者的实现机制、优缺点以及在实际应用中的选择策略。 ... [详细]
  • 原作者:小甲鱼(注:最左边是文件头的偏移量。)IMAGE_DOS_HEADERSTRUCT{+0hWORDe_magicMagi ... [详细]
  • 在尝试重新激活已过期的 Visual Studio 2008 试用版时遇到了困难,特别是找不到输入序列号的位置。经过一番探索,最终找到了有效的解决方法,包括未安装和已安装过期后的处理方式。 ... [详细]
  • 开发笔记:精通 CSS 第 10 章 变换过渡与动画 学习笔记
    开发笔记:精通 CSS 第 10 章 变换过渡与动画 学习笔记 ... [详细]
  • 本文探讨了在支付项目开发中使用SS5 Socket Server实现内部网络访问外部网络的技术方案。详细介绍了SS5的安装、配置及性能测试过程,旨在为面临相同需求的技术人员提供参考。 ... [详细]
  • 解决Ant编译时出现的非法字符错误
    在进行Java项目的Ant构建过程中,有时会遇到由平台差异引发的编译错误。本文将详细探讨一种常见的错误——'error: illegal character'及其解决方案。 ... [详细]
author-avatar
Victoria625_176
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有