I have a simple client / server setup. Here's the client code:
from twisted.internet import reactor
from twisted.internet import protocol
from twisted.internet.endpoints import TCP4ClientEndpoint
class MyProtocol(protocol.Protocol):
def connectionMade(self):
print "Hello!"
def dataReceived(self, data):
print data
class MyProtocolFactory(protocol.ClientFactory):
def startedConnecting(self, connector):
print "Starting to connect!"
def buildProtocol(self, addr):
return MyProtocol()
def clientConnectionLost(self, connector, reason):
print "Lost connection, reason = %s" % reason
def clientConnectionFailed(self, connector, reason):
print "Connection failed, reason = %s" % reason
reactor.stop()
endpoint = TCP4ClientEndpoint(reactor, "127.0.0.1", 54321, timeout=5)
endpoint.connect(MyProtocolFactory())
reactor.run()
For some reason, this client will connect to the server and the protocol works correctly (I can see "Hello!" printed, along with data sent by the server upon a successful connection), but it won't call any of the protocol factory methods. startedConnecting doesn't get called, and if I stop the server, I don't see clientConnectionLost get called. If I try to run the client before the server has started, I would also expect to see clientConnectionFailed get called.
Here's the strange part...If I change the last 3 lines in the code above to the following:
reactor.connectTCP("127.0.0.1", 54321, MyProtocolFactory())
reactor.run()
Then everything works as expected, and all methods get called in all of the cases outlined above.
My understanding of endpoints is that they wrap "connectTCP" (among others) with additional behaviour, but I can't figure out why it works in the second code snippet, but not the first.
Any ideas?
The client endpoint interface does not call the extra connection-state notification methods of
ClientFactory
.So, while endpoints do in some sense "wrap"
connectTCP
et al, it's not true that they have the exact same behavior as using those lower-level methods.With endpoints, the factory's job is to provide protocol instances. The factory is no longer responsible for other aspects of connection management.