5

私は Twisted を学んでおり、初心者向けのチュートリアルでは Factory と Protocol を例としてよく使用します。Factory およびProtocolインターフェイスはメッセージの送信をサポートしていないようです。メッセージの送信は Protocol インターフェイスとは独立して実装されると予想されますか?

class IProcessProtocol(Interface):
    def makeConnection(process):
    def childDataReceived(childFD, data):
    def childConnectionLost(childFD):
    def processExited(reason):
    def processEnded(reason):
4

1 に答える 1

20

見る:

ファクトリは Protocol インスタンスを作成します。

これが意味することは、ファクトリがプロトコルを使用して、データをリッスンして送信する方法を決定することです ( ここを参照してください。また、独自のプロトコルを作成することもできます)。

で使用できるメソッドは次のProtocolとおりです。

Method  logPrefix Return a prefix matching the class name, to identify log messages related to this protocol instance.
Method  dataReceived  Called whenever data is received.
Method  connectionLost  Called when the connection is shut down.

BaseProtocol から継承:

Method  makeConnection  Make a connection to a transport and a server.
Method  connectionMade  Called when a

接続が行われます。

接続が確立されると、次のようにデータを書き込むことができますtransport

from twisted.internet.protocol import Protocol
class SomeProtocol(Protocol):
    def dataReceived(self, data):
        print('Do something with data: {}'.format(data))

    def connectionMade(self):
        self.transport.write("Hello there")

しかし、どこからProtocol取得self.transportするのですか?

>>> from twisted.internet.protocol import Protocol, BaseProtocol
>>> import inspect
>>> from pprint import pprint
>>> pprint(inspect.getclasstree(inspect.getmro(Protocol)))
[(<class 'object'>, ()),
 [(<class 'twisted.internet.protocol.BaseProtocol'>, (<class 'object'>,)),
  [(<class 'twisted.internet.protocol.Protocol'>,
    (<class 'twisted.internet.protocol.BaseProtocol'>,))]]]
>>> dir(Protocol)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', 
 '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
 '__hash__', '__implemented__', '__init__', '__le__', '__lt__', 
 '__module__', '__ne__', '__new__', '__providedBy__', '__provides__', 
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
 '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
 'connected', 'connectionLost', 'connectionMade', 'dataReceived', 
 'logPrefix', 'makeConnection', 'transport']

さてProtocoltransportオブジェクト/メソッドはどうですかBaseProtocol:

>>> dir(BaseProtocol)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',           
 '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
 '__hash__', '__implemented__', '__init__', '__le__', '__lt__', 
 '__module__', '__ne__', '__new__', '__providedBy__', '__provides__', 
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
 '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 
 'connected', 'connectionMade', 'makeConnection', 'transport']
>>> type(BaseProtocol.transport)
<class 'NoneType'>

なぜNoneですか?

それでは、BaseProtocol ここを見てみましょう:

def makeConnection(self, transport): (ソース) オーバーライド

twisted.internet.endpoints._WrapIProtocol,
twisted.protocols.amp.BinaryBoxProtocol,
twisted.protocols.basic.NetstringReceiver,
twisted.protocols.ftp.ProtocolWrapper,
twisted.protocols.ftp.SenderProtocol,
twisted.protocols.policies.ProtocolWrapper,
twisted.protocols.stateful.StatefulProtocol Make a connection to a
transport and a server.

ノート:

This sets the 'transport' attribute of this
Protocol, and calls the connectionMade() callback.

が呼び出されると、プロトコルmakeConnectionの属性が設定されます。transport

では、それは工場でどのように機能しますか?

Factory ここソースを見てみましょうbuildProtocol

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.

    Alternatively, C{None} may be returned to immediately close the
    new connection.

    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

そして:

class BaseProtocol:
    """
    This is the abstract superclass of all protocols.

    Some methods have helpful default implementations here so that they can
    easily be shared, but otherwise the direct subclasses of this class are more
    interesting, L{Protocol} and L{ProcessProtocol}.
    """
    connected = 0
    transport = None

    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()

ここでは transport は None と定義されていますが、それでもどこtransportから来ているのでしょうか?

メソッドが呼び出されreactorたときから来ています。reactor.connect

TCP の例を見てみましょう。

from twisted.internet import reactor
# 
#
#
reactor.connectTCP('localhost', 80, SomeProtocolFactory())

から、次のようreactorに呼び出しますconnectTCP

from twisted.internet.iocpreactor import tcp, udp
#
#
#
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

ここtcp.Connectorのように呼び出しています:from twisted.internet.iocpreactor import tcp, udp

def connect(self):
    """Start connection to remote server."""
    if self.state != "disconnected":
        raise RuntimeError("can't connect in this state")

    self.state = "connecting"
    if not self.factoryStarted:
        self.factory.doStart()
        self.factoryStarted = 1
    ##################
    # ah here we are
    ##################
    self.transport = transport = self._makeTransport()
    if self.timeout is not None:
        self.timeoutID = self.reactor.callLater(self.timeout, transport.failIfNotConnected, error.TimeoutError())
    self.factory.startedConnecting(self)

次のようにトランスポートを返します:

class Connector(TCPConnector):
    def _makeTransport(self):
        return Client(self.host, self.port, self.bindAddress, self,
                      self.reactor)

次に、ソケット接続を作成しています。

だからあなたの質問への短い答え:

メッセージの送信は Protocol インターフェイスとは独立して実装されると予想されますか?

リアクタがインスタンスでセットを呼び出すと、 は None に初期化されProtocolます。transportconnecttransportProtocol

次に、リアクターはプロトコル トランスポート オブジェクトを使用して、着信/発信接続が確立されたときに読み取り/書き込みを行います。

Protocolを使用して、インスタンスで tcp ソケット経由でデータを送信できますself.transport.write()

見る:

于 2015-08-08T03:57:02.983 に答える