Python Twisted Finger:moving to a component based architecture的个人理解

来源:互联网 发布:阿里云os是什么 编辑:程序博客网 时间:2024/05/18 03:44

以下内容只是今天下午个人的理解,不保证理解的正确性,只是很多天一直被这个问题给纠结着,今天才刚刚有点眉目。

首先来看一段代码:

from twisted.internet import protocol,reactor,deferfrom twisted.protocols import basicfrom twisted.application import internet,servicefrom twisted.web import clientimport timeclass FingerProtocol(basic.LineReceiver):    def connectionMade(self):        self.transport.write("Hello wite URL::\r\n")    def lineReceived(self,url):        self.factory.getUrl(url).addCallback(lambda m:self.echo(url,m)).addErrback(lambda _:"Wrong")    def echo(self,url,mesg):        label = time.strftime("%m%d%H%M%S",time.localtime(time.time()))        if url == 'bye':            self.transport.write("goodbye")            self.transport.loseConnection()        else:            open("xkey-%s.html"%label,'w').write(mesg)            self.transport.write("Get the message is %d, written in xkey-%s.html\r\n"%(len(mesg),label))class FingerFactory(protocol.ServerFactory):    protocol = FingerProtocol    def getUrl(self,url):        print client.getPage(url)        return client.getPage(url)application = service.Application('xkey', uid=1, gid=1)f = FingerFactory()internet.TCPServer(2020,f).setServiceParent(service.IServiceCollection(application))

这其实是一个Server(服务器)端的代码,最后一行就是用来监听2020这个端口的信息

FingerFactory类是Server的Factory,protocol = FingerProtocol就是重新定义的协议,然后就是到FingerProrocol类里进行连接,connectionMade就是连接函数,此函数已经被重载了,这时候服务器和客户端在2020端口就可以进行通信了。当然在这个函数中,你还可以定义FingerProtocol的一些变量。

lineReceived里的url参数是用来接收客服端传递过来的信息的,这也是服务器端接收客户端数据的方式,如果需要调用FingerFactory类中的函数只需要用self.factory.函数名的方式,当然这个方式是个异步操作,需要添加callback和errback函数,一个是调用成功后调用的函数,一个是失败了调用的函数。这里还会返回一个值,上面的代码里面显示的是m

下面给出客户端的代码:

import socketADDR = '127.0.0.1'PORT = 2020def client():    Sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    err = Sock.connect_ex((ADDR,PORT))    if err: print "wrong"    else :        page = Sock.recv(8192)        print page        while True:            url = raw_input(">: ")            if 'bye' in url :break            else :                Sock.send(url+'\r\n')                page = Sock.recv(8192)                print page    Sock.close()if __name__ == '__main__':    client()
这个就是socket编程了,没什么好说的,其实我也不会。


下面才是需要说的内容,需要用到twisted里面的两个东西,interface(接口),component(组件),twisted里面按照我的理解它是面向接口而不是面向对象,也就是说又进行了一层的封装,就是这层封装,看了好久没看懂,文档上说的也不清楚

下面看段代码:

class IFingerService(Interface):    def getUser(user):          pass
class FingerService(service.Service):    implements(IFingerService)

也就是说IFingerService类中所有的方法都应该在FingerService,关键的代码就是implements这行,意思就是FingerService实现了IFingerService里的方法,注意方法的名称是相同的。

class IFingerService(Interface):    def getUser(user):    def getUsers():class FingerProtocol(basic.LineReceiver):    def lineReceived(self, user):        d = self.factory.getUser(user)        d.addErrback(catchError)        def writeValue(value):            self.transport.write(value+'\r\n')            self.transport.loseConnection()        d.addCallback(writeValue)class IFingerFactory(Interface):    def getUser(user):    def buildProtocol(addr):class FingerFactoryFromService(protocol.ServerFactory):    implements(IFingerFactory)    protocol = FingerProtocol    def __init__(self, service):        self.service = service    def getUser(self, user):        return self.service.getUser(user)components.registerAdapter(FingerFactoryFromService,                           IFingerService,                           IFingerFactory)class FingerService(service.Service):    implements(IFingerService)application = service.Application('finger', uid=1, gid=1)f = FingerService('/etc/users')serviceCollection = service.IServiceCollection(application)f.setServiceParent(serviceCollection)internet.TCPServer(79, IFingerFactory(f)                   ).setServiceParent(serviceCollection)

components.registerAdapter(FingerFactoryFromService,
                           IFingerService,
                           IFingerFactory)

这个函数的功能就是实现把IFingerService当做IFingerFactory来用,也就是说可以调用同名的函数,即如果IFingerFactory里面有个函数但是没有实现,那么它的实现一定在IFingerService的同名函数里面,当然由于IFingerService是接口类,那么它的同名函数的实现一定在有这句话的implements(IFingerService)的类里面

声明上述过程的程序是:internet.TCPServer(79, IFingerFactory(f)
                   ).setServiceParent(serviceCollection),当然这个东西叫“声明”肯定不合理,姑且就这么叫吧。 IFingerFactory(f)这个就是实现。然后去找某个类里面有implements(IFingerFactory),就在这里实现的。

有的时候还会遇到resource.Resource这个东西,如下例:


class ISJCJControlService(Interface):
class SJCJControlStatusTree(resource.Resource):    __implements__ = resource.IResource,    def __init__(self, service):        resource.Resource.__init__(self)        self.service = service        self.putChild('sjcjcontrol', SJCJControlXR(self.service))         components.registerAdapter(SJCJControlStatusTree, ISJCJControlService,                           resource.IResource)class SJCJControlXR(xmlrpc.XMLRPC):    def __init__(self, service):        xmlrpc.XMLRPC.__init__(self)        self.__service = service                #Set the control service's xmlrpcObject        self.__service.xmlrpcObject = selfclass SJCJControlService(service.Service):    implements(ISJCJControlService)application = service.Application('sjcjcontrol', uid, gid)serviceCollection = service.IServiceCollection(application)internet.TCPServer(port, server.Site(resource.IResource(f))                   ).setServiceParent(serviceCollection)

其实他们实现的功能都是相同的,关键的就是这句话self.putChild('sjcjcontrol', SJCJControlXR(self.service)) ,应该很好理解,同样也是用ISJCJControlService中的方法来实现SJCJControlXR中的方法。这里多余的就是用到了xmlrpc协议。

然后就是这样一句话server.Site(resource.IResource(f))


这样就应该对了,其实这些都是用来实现服务器端的东西,和客户端没有关系,按照我的总结就是很“麻烦”的多用了一层封装,外加把面向对象改成了面向接口,多穿了层衣服而已,但是这里要佩服Twisted的强大,就是Twisted的文档实在是看不懂啊。

但是困扰了我好多天的这个问题算是解决了吧,里面很多词汇用的是很不标准很不规范,凑合着看吧,貌似现在网上还没有这个东西的一个完整的分析,至少我没有找到。

最后感谢TwistedMatrix提供本文的一部分源码,谢谢。

原文档在http://twistedmatrix.com/documents/current/core/howto/tutorial/components.html



原创粉丝点击