Twsited异步网络框架

Twsited

Twsited是一个事件驱动的网络架构,其中包含了很多功能,例如:网络协议,线程,数据库管理,网络操作,电子邮件等。

 

事件驱动

简单来说,事件驱动分为两个部分,第一注册事件,第二触发事件

例子:

event_list = []
 
 
def run():
    for event in event_list:
        obj = event()
        obj.execute()
 
 
class BaseHandler(object):
    """
    用户必须继承该类,从而规范所有类的方法(类似于接口的功能)
    """
    def execute(self):
        raise Exception('you must overwrite execute')

程序使用这个架构

from source import event_drive
 
 
class MyHandler(event_drive.BaseHandler):
 
    def execute(self):
        print 'event-drive execute MyHandler'
 
 
event_drive.event_list.append(MyHandler)
event_drive.run()

# 简单理解就是别人写好的框架,你在使用的时候必需遵守它们的约定。

 

Protocols

Protocols描述了如何以异步的方式处理网络中的事件。HTTP,DNS以及IMAP是应用层协议中的列子

Protocols的方法:

makeConnection                                     在transport对象中服务器之间建立一条连接

connectionMade                                      连接建立起来后调用

dataReceived                                          接收数据时调用

connectionLost                                        关闭连接时调用

 

Transports

Transports代表网络中两个通信节点之间的连接,Transports负责描述连接的细节,比如连接是面向流式的还是面向数据包的,流控以及可靠。TCP,UDP和Unix套接字可作为Transports的例子。它们被设计为“满足最小功能单元,同时具有最大控制的可复用性”,而且从协议实现中分离出来,这让许多协议可以采用相同类型的传输。

所包含的方法:

write                                         以非阻塞的方式按顺序依次将数据写到物理连接上

writeSequence                         将一个字符串列表写到物理连接上

loseConnecton                         将所有挂起的数据写入,然后关闭连接

getPeer                                     取得连接中对端的地址信息

getHost                                     取得连接中本端的地址信息

将Transports从协议中分离出来也使得对这两个层次的测试变的更加简单。可以通过简单的写入一个字符串来模拟传输,用这种方式检查。

 

EchoServer

from twisted.internet import protocol
from twisted.internet import reactor
 
class Echo(protocol.Protocol):
    def dataReceived(self, data):
        self.transport.write(data)
 
def main():
    factory = protocol.ServerFactory()
    factory.protocol = Echo
 
    reactor.listenTCP(1234,factory)
    reactor.run()
 
if __name__ == '__main__':
    main()
EchoClient
from twisted.internet import reactor, protocol
 
 
# a client protocol
 
class EchoClient(protocol.Protocol):
    """Once connected, send a message, then print the result."""
 
    def connectionMade(self):
        self.transport.write("hello alex!")
 
    def dataReceived(self, data):
        "As soon as any data is received, write it back."
        print "Server said:", data
        self.transport.loseConnection()
 
    def connectionLost(self, reason):
        print "connection lost"
 
class EchoFactory(protocol.ClientFactory):
    protocol = EchoClient
 
    def clientConnectionFailed(self, connector, reason):
        print "Connection failed - goodbye!"
        reactor.stop()
 
    def clientConnectionLost(self, connector, reason):
        print "Connection lost - goodbye!"
        reactor.stop()

# this connects the protocol to a server running on port 8000
def main():
    f = EchoFactory()
    reactor.connectTCP("localhost", 1234, f)
    reactor.run()
 
# this only runs if the module was *not* imported
if __name__ == '__main__':
    main()

运行服务器端脚本将启动一个TCP服务器,监听端口1234上的连接。服务器采用的是Echo协议,数据经TCP Transports对象写出。运行客户脚本将对服务器发起一个TCP连接,回显服务器端的回应然后终止连接并停止reactor事件循环。这里的Factory用来对连接的方法生成Protocol对象实例。两端的通信是异步的,connectTCP负责注册回调函数到reactor事件循环中,当socket上有数据可读时通知回调处理。

 

一个传送文件的例子

server side

import optparse, os
 
from twisted.internet.protocol import ServerFactory, Protocol
 
 
def parse_args():
    usage = """usage: %prog [options] poetry-file
 
This is the Fast Poetry Server, Twisted edition.
Run it like this:
 
  python fastpoetry.py <path-to-poetry-file>
 
If you are in the base directory of the twisted-intro package,
you could run it like this:
 
  python twisted-server-1/fastpoetry.py poetry/ecstasy.txt
 
to serve up John Donne's Ecstasy, which I know you want to do.
"""
 
    parser = optparse.OptionParser(usage)
 
    help = "The port to listen on. Default to a random available port."
    parser.add_option('--port', type='int', help=help)
 
    help = "The interface to listen on. Default is localhost."
    parser.add_option('--iface', help=help, default='localhost')
 
    options, args = parser.parse_args()
    print("--arg:",options,args)
 
    if len(args) != 1:
        parser.error('Provide exactly one poetry file.')
 
    poetry_file = args[0]
 
    if not os.path.exists(args[0]):
        parser.error('No such file: %s' % poetry_file)
 
    return options, poetry_file
 
 
class PoetryProtocol(Protocol):
 
    def connectionMade(self):
        self.transport.write(self.factory.poem)
        self.transport.loseConnection()
 
 
class PoetryFactory(ServerFactory):
     protocol = PoetryProtocol
 
    def __init__(self, poem):
        self.poem = poem
 
 
def main():
    options, poetry_file = parse_args()
 
    poem = open(poetry_file).read()
 
    factory = PoetryFactory(poem)
 
    from twisted.internet import reactor
 
    port = reactor.listenTCP(options.port or 9000, factory,
                             interface=options.iface)
 
    print 'Serving %s on %s.' % (poetry_file, port.getHost())
 
    reactor.run()
 
 
if __name__ == '__main__':
    main()

client side

import optparse
 
from twisted.internet.protocol import Protocol, ClientFactory
 
 
def parse_args():
    usage = """usage: %prog [options] [hostname]:port ...
 
This is the Get Poetry Now! client, Twisted version 3.0
Run it like this:
 
  python get-poetry-1.py port1 port2 port3 ...
"""
 
    parser = optparse.OptionParser(usage)
 
    _, addresses = parser.parse_args()
 
    if not addresses:
        print parser.format_help()
        parser.exit()
 
    def parse_address(addr):
        if ':' not in addr:
            host = '127.0.0.1'
            port = addr
        else:
            host, port = addr.split(':', 1)
 
        if not port.isdigit():
            parser.error('Ports must be integers.')
 
        return host, int(port)
 
    return map(parse_address, addresses)
 
 
class PoetryProtocol(Protocol):
 
    poem = ''
 
    def dataReceived(self, data):
        self.poem += data
 
    def connectionLost(self, reason):
        self.poemReceived(self.poem)
 
    def poemReceived(self, poem):
        self.factory.poem_finished(poem)
 
 
class PoetryClientFactory(ClientFactory):
 
    protocol = PoetryProtocol
 
    def __init__(self, callback):
        self.callback = callback
     def poem_finished(self, poem):
        self.callback(poem)
 
 
def get_poetry(host, port, callback):
    """
    Download a poem from the given host and port and invoke
 
      callback(poem)
 
    when the poem is complete.
    """
    from twisted.internet import reactor
    factory = PoetryClientFactory(callback)
    reactor.connectTCP(host, port, factory)
 
 
def poetry_main():
    addresses = parse_args()
 
    from twisted.internet import reactor
 
    poems = []
 
    def got_poem(poem):
        poems.append(poem)
        if len(poems) == len(addresses):
            reactor.stop()
  
    for address in addresses:
        host, port = address
        get_poetry(host, port, got_poem)
 
    reactor.run()
 
    for poem in poems:
        print poem
 
 
if __name__ == '__main__':
    poetry_main()

 

 

Twisted深入

http://krondo.com/an-introduction-to-asynchronous-programming-and-twisted/

http://blog.csdn.net/hanhuili/article/details/9389433

posted @ 2016-03-25 10:22  binges  阅读(1321)  评论(0编辑  收藏  举报