Экземпляр фабрики не создает новый отложенный

Я довольно новичок в Twisted, так что я уверен, что это ошибка новичка. Я построил простой сервер, который получает сообщение от клиента, и после получения сообщения сервер запускает обратный вызов, который выводит сообщение на консоль.

Сначала сервер работает как положено. К сожалению, когда я запускаю второй клиент, я получаю следующую ошибку "twisted.internet.defer.AlreadyCalledError". Насколько я понимаю, фабрика создаст новый экземпляр отложенного, то есть новый отложенный не будет вызван раньше?

Пожалуйста, смотрите код ниже. Любая помощь будет принята с благодарностью.

import sys
from twisted.internet.protocol import ServerFactory, Protocol
from twisted.internet import defer

class LockProtocol(Protocol):

  lockData = ''

  def dataReceived(self, data):
    self.lockData += data

    if self.lockData.endswith('??'):
      self.lockDataReceived(self.lockData)

  def lockDataReceived(self, lockData):
    self.factory.lockDataFinished(lockData)

class LockServerFactory(ServerFactory):

  protocol = LockProtocol  

  def __init__(self):
    self.deferred = defer.Deferred() # Initialise deferred

  def lockDataFinished(self, lockData):
      self.deferred.callback(lockData)

  def clientConnectionFailed(self, connector, reason):
      self.deferred.errback(reason)


def main():

  HOST = '127.0.0.1' # localhost
  PORT = 10001

  def got_lockData(lockData):
    print "We have received lockData. It is as follows:", lockData

  def lockData_failed(err):
    print >> sys.stderr, 'The lockData download failed.'
    errors.append(err)


  factory = LockServerFactory()

  from twisted.internet import reactor

  #  Listen for TCP connections on a port, and use our factory to make a protocol instance for each new connection

  port = reactor.listenTCP(PORT,factory)

  print 'Serving on %s' %  port.getHost()

  # Set up callbacks

  factory.deferred.addCallbacks(got_lockData,lockData_failed)

  reactor.run() # Start the reactor

if __name__ == '__main__':
    main()

1 ответ

Обратите внимание, что есть только один LockServerFactory когда-либо созданный в вашей программе:

factory = LockServerFactory()

Тем не менее, как многие LockProtocol экземпляры создаются по мере того, как соединения принимаются. Если у вас есть состояние соединения, место для его установки LockProtocol,

Похоже, ваше событие "блокировка данных завершена" не является одноразовым, поэтому Deferred вероятно, не подходящая абстракция для этой работы.

Вместо LockServerFactory с Deferred это срабатывает, когда происходит это событие, возможно, вам нужен многоцелевой обработчик событий, возможно, специально созданный:

class LockServerFactory(ServerFactory):

  protocol = LockProtocol  

  def __init__(self, lockDataFinished):
    self.lockDataFinished = lockDataFinished

 factory = LockServerFactory(got_lockData)

(Кстати, обратите внимание, что я упал clientConnectionFailed из этой реализации: это метод ClientFactory, Он никогда не будет вызываться на фабрике серверов.)

Другие вопросы по тегам