Если ваучер становится «используемым», когда клиент проверяет его, а затем становится неиспользованным, когда клиент отключается, это звучит так, как будто вам просто нужно сохранить набор ваучеров, которые вы добавляете, когда проверка завершена, и удалять из которых, когдаклиент отключаетсяВы можете оставить это на заводе, чтобы оно было общим для всех клиентских подключений.Например:
#!/usr/bin/env python
from twisted.internet import reactor, protocol
class Responder(protocol.Protocol):
def connectionMade(self):
self.vcode = None
def dataReceived(self, data):
# check the voucher code, and return disabled if its out of time or not there. Otherwise return time left.
if data.startswith("check="):
param, vcode = data.split("=")
if vcode in self.factory.activeVouchers:
self.transport.write("in use")
return
self.factory.activeVouchers.add(vcode)
self.vcode = vcode
checkcode = SQLConnect("check", vcode, vcode)
if checkcode == "disabled":
self.transport.write("disabled")
else:
self.transport.write(str(checkcode))
# Update time left.
if data.startswith("update="):
param, vcode, vtime = data.split("=")
SQLConnect("update", vcode, vtime)
def connectionLost(self, reason):
if self.vcode is not None:
self.factory.activeVouchers.remove(self.vcode)
def main():
factory = protocol.ServerFactory()
factory.activeVouchers = set()
factory.protocol = Responder
reactor.listenTCP(6500,factory)
reactor.run()
if __name__ == '__main__':
main()
Новый атрибут vcode
в Responder
позволяет обновлять набор activeVouchers
, когда клиент отключается (что вызывает вызов Responder.connectionLost
).Дополнительная проверка в начале Responder.dataReceived
добавляет ваучеры к этому набору, когда они используются, и предотвращает использование любого ваучера в использовании.
Кроме этого, есть пара других вещей, которые вы могли бы рассмотреть,Во-первых, вам, вероятно, следует использовать twisted.protocols.basic.LineOnlyReceiver
или один из других протоколов в twisted.protocols.basic
вместо просто Protocol
.dataReceived
вызывается при получении байтов по сети.Так как TCP - это транспорт, ориентированный на поток, а не транспорт, ориентированный на сообщения, вы можете получить вызов типа dataReceived("chec")
, за которым следует dataReceived("k=somecode")
.Поскольку ваш dataReceived
реализован сейчас, этот случай не будет обработан, и клиент не получит ответа.LineOnlyReceiver
добавляет основанное на строке кадрирование, так что такие байты, как «check = somecode \ r \ n», могут быть интерпретированы как полное сообщение, а «check = somecode» доставлено сразу за один вызов lineReceived
.
Во-вторых, SQLConnect
похоже, что он, вероятно, выполняет какой-то блокирующий ввод / вывод.Если это так, это означает, что ваш сервер не будет хорошо обрабатывать параллельные клиентские запросы, поскольку любая блокировка препятствует обработке всех новых событий, в том числе от разных клиентов.Возможно, вы захотите взглянуть на twisted.enterprise.adbapi
для неблокирующего SQL API.