Python扭曲 - 需要通过所有连接并找到客户端

时间:2011-07-23 00:28:04

标签: python twisted connection

我正在尝试创建一个简单的优惠券计划。

客户端连接到服务器并询问凭证是否还有剩余时间,如果是,则服务器会响应多长时间。

我控制了服务器和客户端,客户端也由我编码。

现在这就是我的服务器端,客户端是不言自明的。

这方面的一个重大缺陷是,如果2个客户端使用相同的凭证代码连接,他们都将具有访问权限,因为服务器没有检查是否存在具有该代码的活动客户端。

有人可以解释或导致文件记录如何实现吗?

#!/usr/bin/env python

from twisted.internet import reactor, protocol

class Responder(protocol.Protocol):

    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("=")
            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 main():
    factory = protocol.ServerFactory()
    factory.protocol = Responder
    reactor.listenTCP(6500,factory)
    reactor.run()

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:5)

如果凭证在客户端检查时变为“正在使用”,然后在客户端断开连接时变为未使用状态,则听起来您需要保留一组您在检查完成时添加的凭证并从中删除客户端断开连接。您可以将其保留在工厂中,以便在所有客户端连接之间共享。例如:

#!/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.LineOnlyReceivertwisted.protocols.basic中的其他协议,而不只是Protocol。只要通过网络接收到任何字节,就会调用dataReceived。由于TCP是面向流的传输而不是面向消息的传输,因此最终可能会调用dataReceived("chec")等快速跟随dataReceived("k=somecode")的调用。由于您的dataReceived现已实施,因此不会处理此案例,客户端也不会收到任何回复。 LineOnlyReceiver添加了基于行的框架,因此像“check = somecode \ r \ n”这样的字节可以被解释为一个完整的消息,并且“check = somecode”一次性传递到一个lineReceived调用

其次,SQLConnect看起来可能会执行一些阻塞I / O.如果这是真的,则意味着您的服务器将无法很好地处理并发客户端请求,因为任何阻止都会阻止处理所有新事件,包括来自不同客户端的事件。您可能需要查看twisted.enterprise.adbapi以获取非阻塞SQL API。