简单使用
Twisted是用Python实现的基于事件驱动的网络引擎框架,Twisted支持许多常见的传输及应用层协议,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。就像Python一样,Twisted也具有“内置电池”(batteries-included)的特点。Twisted对于其支持的所有协议都带有客户端和服务器实现,同时附带有基于命令行的工具,使得配置和部署产品级的Twisted应用变得非常方便。
内部方法介绍
Transports
Transports代表网络中两个通信结点之间的连接。Transports负责描述连接的细节,比如连接是面向流式的还是面向数据报的,流控以及可靠性。TCP、UDP和Unix套接字可作为transports的例子。它们被设计为“满足最小功能单元,同时具有最大程度的可复用性”,而且从协议实现中分离出来,这让许多协议可以采用相同类型的传输。Transports实现了ITransports接口,它包含如下的方法:
write 以非阻塞的方式按顺序依次将数据写到物理连接上
writeSequence 将一个字符串列表写到物理连接上
loseConnection 将所有挂起的数据写入,然后关闭连接
getPeer 取得连接中对端的地址信息
getHost 取得连接中本端的地址信息
getPage 发送HTTP请求
将transports从协议中分离出来也使得对这两个层次的测试变得更加简单。可以通过简单地写入一个字符串来模拟传输,用这种方式来检查。
Protocols
Protocols描述了如何以异步的方式处理网络中的事件。HTTP、DNS以及IMAP是应用层协议中的例子。Protocols实现了IProtocol接口,它包含如下的方法:
makeConnection 在transport对象和服务器之间建立一条连接
connectionMade 连接建立起来后调用
dataReceived 接收数据时调用
connectionLost 关闭连接时调用
Reactor模式
Twisted实现了设计模式中的反应堆(reactor)模式,这种模式在单线程环境中调度多个事件源产生的事件到它们各自的事件处理例程中去。
Twisted的核心就是reactor事件循环。Reactor可以感知网络、文件系统以及定时器事件。它等待然后处理这些事件,从特定于平台的行为中抽象出来,并提供统一的接口,使得在网络协议栈的任何位置对事件做出响应都变得简单。
Deferreds
Deferred对象以抽象化的方式表达了一种思想,即结果还尚不存在。它同样能够帮助管理产生这个结果所需要的回调链。当从函数中返回时,Deferred对象承诺在某个时刻函数将产生一个结果。返回的Deferred对象中包含所有注册到事件上的回调引用,因此在函数间只需要传递这一个对象即可,跟踪这个对象比单独管理所有的回调要简单的多。
Deferred对象包含一对回调链,一个是针对操作成功的回调,一个是针对操作失败的回调。初始状态下Deferred对象的两条链都为空。在事件处理的过程中,每个阶段都为其添加处理成功的回调和处理失败的回调。当一个异步结果到来时,Deferred对象就被“激活”,那么处理成功的回调和处理失败的回调就可以以合适的方式按照它们添加进来的顺序依次得到调用。
简单的使用
一、服务器代码编写
# 1、需要引用的库
from twisted.internet import protocol, reactor
from twisted.internet.endpoints import TCP4ServerEndpoint
# TCP4ServerEndpoint 需要win32api
from time import ctime
# 2、定义服务器端协议类
class TSServerProtocol(protocol.Protocol):
"""
服务器端协议
每一个客户端连接对应一个实例。
"""
def __init__(self):
self.clientInfo = "" # clientInfo 将保存客户端连接信息。
def connectionMade(self):
self.clientInfo = self.transport.getPeer()
print("来自%s的连接" % (self.clientInfo))
def dataReceived(self, data):
recData = data.decode()
print("收到来自%s的数据:%s" % (self.clientInfo, recData))
rep = '[%s] %s' % (ctime(), recData)
self.transport.write(rep.encode())
# 3、定义服务器端工厂类
class TSServerFactory(protocol.Factory):
def buildProtocol(self, addr):
return TSServerProtocol()
# 4、使用reactor启动端口监听
endpoint = TCP4ServerEndpoint(reactor, PORT)
endpoint.listen(TSServerFactory())
print("等待客户端连接")
reactor.run()
二、客户端代码的编写
#1、引用的库
from twisted.internet import protocol, reactor
#2、定义客户端协议类
class TSClientProtocol(protocol.Protocol):
def sendData(self):
data = input("> ")
if data:
self.transport.write(data.encode())
else:
self.transport.loseConnection()
def connectionMade(self):
self.sendData()
def dataReceived(self, data):
recData = data.decode() # 将二进制数据转换为字符串数据。
print("从服务器上收到的数据:%s" % (recData))
self.sendData()
#3、定义客户端工厂类
class TSClientFactory(protocol.ClientFactory):
protocol = TSClientProtocol
clientConnectionLost = clientConnectionFailed = lambda self, connector, reason:reactor.stop()
#4、使用reactor启动连接
reactor.connectTCP(HOST, PORT, TSClientFactory())
reactor.run() # 启动循环
三、getPage的使用
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from twisted.internet import defer # 处理回调函数的方法
from twisted.web.client import getPage
from twisted.internet import reactor
def one_done(arg):
print(arg)
def all_done(arg):
print('done')
reactor.stop() # 停止循环
@defer.inlineCallbacks # 回调装饰器
def task(url):
res = getPage(bytes(url, encoding='utf8')) # 发送Http请求
res.addCallback(one_done) # 回调
yield res
url_list = [
'http://www.baidu.com',
'http://www.so.com',
'http://www.sogou.com',
]
defer_list = [] # [特殊,特殊,特殊(已经向url发送请求)]
for url in url_list:
v = task(url)
defer_list.append(v)
d = defer.DeferredList(defer_list)
d.addBoth(all_done)