見る:
ファクトリは 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']
さてProtocol、transportオブジェクト/メソッドはどうですか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()。
見る: