Ich habe versucht, einen Server zu bauen. Neben der Annahme von Verbindungen von Clients, wie es normale Server tun, verbindet mein Server auch andere Server als einen Client.Twisted: Verwenden von ConnectProtocol zum Verbinden von Endpunkt verursachen Speicherverlust?
Ich habe das Protokoll und Endpunkt wie im Folgenden beschrieben:
p = FooProtocol()
client = TCP4ClientEndpoint(reactor, '127.0.0.1' , 8080) # without ClientFactory
Dann, nach Anruf reactor.run()
, wird der Server hören/neue Socket-Verbindungen akzeptieren. wenn neue Socket-Verbindungen (in connectionMade) vorgenommen werden, wird der Server connectProtocol(client, p)
aufrufen, die unten wie die Pseudo-Code wirkt:
while server accept new socket:
connectProtocol(client, p)
# client.client.connect(foo_client_factory) --> connecting in this way won't
# cause memory leak
Da die Verbindungen zum Client vorgenommen werden, wird der Speicher nach und nach verbraucht (expliziten Aufruf gc
doesn arbeite nicht).
Verwende ich Twisted falsch?
----- ----- UPDATE
Mein Test programe: Server wartet Kunden zu verbinden. Wenn die Verbindung vom Client hergestellt wird, Server 50 Verbindungen zu anderen Server
Hier ist der Code schaffen:
#! /usr/bin/env python
import sys
import gc
from twisted.internet import protocol, reactor, defer, endpoints
from twisted.internet.endpoints import TCP4ClientEndpoint, connectProtocol
class MyClientProtocol(protocol.Protocol):
def connectionMade(self):
self.transport.loseConnection()
class MyClientFactory(protocol.ClientFactory):
def buildProtocol(self, addr):
p = MyClientProtocol()
return p
class ServerFactory(protocol.Factory):
def buildProtocol(self, addr):
p = ServerProtocol()
return p
client_factory = MyClientFactory() # global
client_endpoint = TCP4ClientEndpoint(reactor, '127.0.0.1' , 8080) # global
times = 0
class ServerProtocol(protocol.Protocol):
def connectionMade(self):
global client_factory
global client_endpoint
global times
for i in range(50):
# 1)
p = MyClientProtocol()
connectProtocol(client_endpoint, p) # cause memleak
# 2)
#client_endpoint.connect(client_factory) # no memleak
times += 1
if times % 10 == 9:
print 'gc'
gc.collect() # doesn't work
self.transport.loseConnection()
if __name__ == '__main__':
server_factory = ServerFactory()
serverEndpoint = endpoints.serverFromString(reactor, "tcp:8888")
serverEndpoint.listen(server_factory)
reactor.run()
Das klingt, als ob es ein Fehler in Twisted sein könnte, aber Sie haben nicht genug Code hier angeschlossen, um zu erzählen. Kannst du ein ganzes Programm anhängen? – Glyph
Danke zu antworten! Eine Aktualisierung wurde mit meinem Testcode vorgenommen. –
Hier scheint tatsächlich ein Leck zu sein. Tatsächlich bekomme ich ein Leck mit * beiden * Beispielen, obwohl es mit dem connectProtocol-basierten Beispiel ein wenig schneller ist. Dies ist definitiv ein Fehler in Twisted, und wir müssen nachforschen. – Glyph