六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 24|回复: 0

reactor.ConnectTCP的源码分析

[复制链接]

升级  62%

39

主题

39

主题

39

主题

秀才

Rank: 2

积分
143
 楼主| 发表于 2013-2-4 21:51:37 | 显示全部楼层 |阅读模式
reactor.ConnectTCP(host,port,xxfactory)
ConnectTCP这个方法在twisted.internet.posixbase.py当中
方法源码如下:
    def connectTCP(self, host, port, factory, timeout=30, bindAddress=None):        """@see: twisted.internet.interfaces.IReactorTCP.connectTCP        """        c = tcp.Connector(host, port, factory, timeout, bindAddress, self)        c.connect()        return c 
代码只有关键的两句:
        c = tcp.Connector(host, port, factory, timeout, bindAddress, self)        c.connect() 
下面开始解读:
1、源码位于/twisted/internet/tcp.py
c = tcp.Connector(host, port, factory, timeout, bindAddress, self) 通过一步步的跟踪,可以找出本行代码执行了tcp.Connector的初始化方法:
    def __init__(self, host, port, factory, timeout, bindAddress, reactor=None):        self.host = host        if isinstance(port, types.StringTypes):            try:                port = socket.getservbyname(port, 'tcp')            except socket.error, e:                raise error.ServiceNameUnknownError(string="%s (%r)" % (e, port))        self.port = port        self.bindAddress = bindAddress        base.BaseConnector.__init__(self, factory, timeout, reactor) 
最后这句代码调用了/twisted/internet/base.py当中的BaseConnector的初始化方法:
    def __init__(self, factory, timeout, reactor):        self.state = "disconnected"        self.reactor = reactor        self.factory = factory        self.timeout = timeout 这样就非常清晰了,c = tcp.Connector(host, port, factory, timeout, bindAddress, self)主要做了外部环境的初始化工作。
 
2、源码位于/twisted/internet/base.py
c.connect() /twisted/internet/tcp.py当中的class Connector(base.BaseConnector)继承自base.BaseConnector,c.connect()这个方法就是base.BaseConnector当中的方法。下面看看这个方法的内容:
        def connect(self):        """Start connection to remote server."""        ..................        ..................        self.state = "connecting"        if not self.factoryStarted:            self.factory.doStart()            self.factoryStarted = 1        self.transport = transport = self._makeTransport()       ...........       ........... 
这个方法主要做了两件事情:
一是启动工厂
二是建立socket连接,同时建立protocal处理成功的连接
 
2.1、联系上下文,知道self.factory.doStart()方法会被执行,这个方法当中包含了twisted.internet.protocal
当中的def startFactory(self)这个方法的描述为:
        """This will be called before I begin listening on a Port or Connector.
        It will only be called once, even if the factory is connected
        to multiple ports.
        This can be used to perform 'unserialization' tasks that
        are best put off until things are actually running, such
        as connecting to a database, opening files, etcetera.
        """
2.2、下面就是执行self.transport = transport = self._makeTransport()
_makeTransport()方法包含在/twisted/internet/tcp.py当中的Connector类中:
    def _makeTransport(self):        return Client(self.host, self.port, self.bindAddress, self, self.reactor) 再去找到Client类,也位于/twisted/internet/tcp.py当中:初始化方法:
    def __init__(self, host, port, bindAddress, connector, reactor=None):        .............        .............        whenDone = self.resolveAddress        ..............        ..............        self._finishInit(whenDone, skt, err, reactor) 分析这个方法:self.resolveAddress:
    def resolveAddress(self):        if abstract.isIPAddress(self.addr[0]):            self._setRealAddress(self.addr[0])            .................            ................    def _setRealAddress(self, address):        self.realAddress = (address, self.addr[1])        self.doConnect() 
 
最终会找到doConnect方法,在这个方法当中,完成了socket的连接,然后完成protocal的创建;然后开始等待数据。
 针对socket连接的部分就不具体描述了,doConnect方法的上半部分就是处理socket连接的。
 
doConnect()方法的最后一句代码是调用了_connectDone方法,这个方法当中主要完成了协议的创建--protocal的创建,大家可以顺着看一下protocal是如何创建的:
 
    def _connectDone(self):        self.protocol = self.connector.buildProtocol(self.getPeer())        self.connected = 1        self.logstr = self.protocol.__class__.__name__ + ",client"        self.startReading()        self.protocol.makeConnection(self)    def buildProtocol(self, addr):        """Create an instance of a subclass of Protocol.        The returned instance will handle input on an incoming server        connection, and an attribute \"factory\" pointing to the creating        factory.        Override this method to alter how Protocol instances get created.        @param addr: an object implementing L{twisted.internet.interfaces.IAddress}        """        p = self.protocol()        p.factory = self        return p    def makeConnection(self, transport):        """Make a connection to a transport and a server.        This sets the 'transport' attribute of this Protocol, and calls the        connectionMade() callback.        """        self.connected = 1        self.transport = transport        self.connectionMade()    def connectionMade(self):        """Called when a connection is made.        This may be considered the initializer of the protocol, because        it is called when the connection is completed.  For clients,        this is called once the connection to the server has been        established; for servers, this is called after an accept() call        stops blocking and a socket has been received.  If you need to        send any greeting or initial message, do it here.        """ 
说实在话,源码是能看懂的,但是机制也就是内幕的原理还不是很明白的。但就目前来看当创建了一个socket连接的同时,会创建这个连接的协议,连接和协议应该是一对一的关系,而工厂却可以放置管理多个协议。
学习需要实践,需要融汇贯通,这都需要时间,也许在下面的项目中,等自己顿悟之后,还可以回来再好好说说。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表