通过任务循环调用将数据发送到工厂会话外的所有客户端

时间:2016-04-02 03:30:01

标签: python python-2.7 twisted

我正在尝试解决一个简单的Twisted问题。

为简单起见,我使用的是Python 2.7 Twisted Chat.py示例。

from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor

class Chat(LineReceiver):

    def __init__(self, users):
        self.users = users
        self.name = None
        self.state = "GETNAME"

    def connectionMade(self):
        self.sendLine("What's your name?")

    def connectionLost(self, reason):
        if self.users.has_key(self.name):
            del self.users[self.name]

    def lineReceived(self, line):
        if self.state == "GETNAME":
            self.handle_GETNAME(line)
        else:
            self.handle_CHAT(line)

    def handle_GETNAME(self, name):
        if self.users.has_key(name):
            self.sendLine("Name taken, please choose another.")
            return
        self.sendLine("Welcome, %s!" % (name,))
        self.name = name
        self.users[name] = self
        self.state = "CHAT"

    def handle_CHAT(self, message):
        message = "<%s> %s" % (self.name, message)
        for name, protocol in self.users.iteritems():
            if protocol != self:
                protocol.sendLine(message)


class ChatFactory(Factory):

    def __init__(self):
        self.users = {} # maps user names to Chat instances

    def buildProtocol(self, addr):
        return Chat(self.users)


reactor.listenTCP(8123, ChatFactory())
reactor.run()

我要做的是使用twisted.internet任务创建一个每60秒运行一次的任务,并将数据发送到所有连接的会话。

半伪码

def broadcastmsg():
    for client in factory:
        client.protocol.transport.write("I am a Test\n\r")

event = task.LoopingCall(broadcastmsg)
event.start(60) 

问题是我不能让扭曲行为正确。我可以在每个会话的基础上实现它。但是,对于连接它的每一次使用,垃圾邮件的垃圾邮件数量都会增加两倍等。

1 个答案:

答案 0 :(得分:0)

你是如何设置循环呼叫的?

如您所知,协议由工厂创建和管理。定期向所有用户发送一些消息看起来像是应该放入工厂的任务。您可以在工厂__init__方法中创建loopingCall,并在init之后立即启动它。由于每个连接都有一个工厂,因此每60秒只发送一次通知

class ChatFactory(Factory):

    def __init__(self):
        self.users = {} # maps user names to Chat instances

        def broadcast_msg():
            for name in self.users:
                self.users[name].sendLine("looping call send to users: {}".format(self.users.keys()))

        self.looping_call = task.LoopingCall(broadcast_msg)
        self.looping_call.start(60)

这应该可行,至少它对我有用。