`
wwty
  • 浏览: 536695 次
  • 性别: Icon_minigender_1
  • 来自: 北京-郑州
社区版块
存档分类
最新评论

reactor.ConnectTCP的源码分析

阅读更多

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连接的同时,会创建这个连接的协议,连接和协议应该是一对一的关系,而工厂却可以放置管理多个协议。

学习需要实践,需要融汇贯通,这都需要时间,也许在下面的项目中,等自己顿悟之后,还可以回来再好好说说。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics