异步非阻塞框架

twisted 是一个事件驱动的网络开发框架,使用 python 开发。

twisted 框架编写的服务器有几个基本的元素:

  • 应用程序对象(application):管理应用程序资源的对象,一个应用程序可以管理多个service对象。
  • 服务(service),服务对象启动监听的端口,
  • 协议工厂(factory):当客户端连接到服务器时,用来创建协议对象。
  • 协议(protocol):每个协议对象对应一个网络连接。协议类处理网络协议(如http,ftp,自定义协议等)

twisted 框架内部运行依赖的元素:

  • reactor:异步事件的主要循环处理类,负责监控事件,调用注册的回调函数提供服务。(在linux上主要使用epoll/select来实现)
  • defer: 异步回调序列,当序列被执行的时候,顺序执行注册的回调函数。

官方的一个例子

实现一个 echo server,创建文件 echoServ.py

#!/usr/bin/env python
# coding: utf-8

from twisted.internet.protocol import Protocol
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.internet import reactor

class Echo(Protocol):
    '''
    协议类实现用户的服务协议,例如 http,ftp,ssh 等
    '''
    def __init__(self, factory):
        self.factory = factory

    def connectionMade(self):
        '''
        连接建立时被回调的方法
        '''
        self.factory.numProtocols = self.factory.numProtocols + 1
        self.transport.write("Welcome! There are currently %d open connections.\n" %
                        (self.factory.numProtocols,))

    def connectionLost(self, reason):
        '''
        连接关闭时被回调的方法
        '''
        self.factory.numProtocols = self.factory.numProtocols - 1

    def dataReceived(self, data):
        '''
        接收数据的函数,当有数据到达时被回调
        '''
        self.transport.write(data)


class EchoFactory(Factory):
    '''
    协议工厂类,当客户端建立连接的时候,创建协议对象,协议对象与客户端连接一一对应
    '''
    numProtocols = 0
    def buildProtocol(self, addr):
        return Echo(self)

if __name__ == '__main__':
    # 创建监听端口
    reactor.listenTCP(8007, EchoFactory())

    # 开始监听事件
    reactor.run()

运行服务程序

python echoServ.py

测试服务程序

telnet 127.0.0.1 8007


例子程序的说明

  • 协议类继承自 twisted.internet.protocol.Protocol,需实现 dataReceived 等方法。在协议类中实现应用协议。
  • 协议工厂继承自 twisted.internet.protocol.Factory,需实现 buildProtocol 方法。协议工厂负责实例化协议类,不应该保存于连接相关的状态信息。
  • transport 就是连接对象,通过它进行网络写数据


使用 daemon 的方式运行程序

  1. 使用守护进程的方式运行服务,需要提供一个 tac 配置文件(这就是一个 python 文件,只是扩展名不同)
  2. 在这个文件中需要创建一个应用程序对象,对象名必须是 application。

创建一个 echo.tac 文件

#!/usr/bin/env python
# coding: utf-8

from twisted.application import service, internet

from echoServ import EchoFactory

# 创建应用程序对象
application = service.Application('Echo 服务程序')

# 创建 service 对象
myServices = internet.TCPServer(8007, EchoFactory())

# 设置 application 为 service 的父元素
myservices.setServiceParent(application)

用守护进程方式运行服务

twistd -y echo.tac

停止服务

kill -15 pid


总结

上面就是 twisted 网络框架编写服务的基本方法,在框架内部有丰富的协议工厂,协议,可是很方便的实现简单的 http,ftp,ssh 等服务器程序。

后面我会介绍一些常用的功能的实现原理,例如:如何记录日志,客户端 http 异步请求的处理,defer运行原理等

right