【问题标题】:sendMessage from outside in autobahn running in separate thread从高速公路外部发送消息在单独的线程中运行
【发布时间】:2015-05-02 05:05:53
【问题描述】:

我想从MyServerProtocol 类外部调用sendMessage 方法并向连接的客户端发送消息。我使用threading 来做到这一点。

当我使用这段代码时:

from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
from twisted.internet import reactor
import threading

class MyServerProtocol(WebSocketServerProtocol):
    def onConnect(self, request):
        print("Client connecting: {0}".format(request.peer))

    def onOpen(self):
        print("WebSocket connection open.")

    def onMessage(self, payload, isBinary):
        if isBinary:
            print("Binary message received: {0} bytes".format(len(payload)))
        else:
            print("Text message received: {0}".format(payload.decode('utf8')))

        self.sendMessage(payload, isBinary)

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))


class Connection(threading.Thread):
    def __init__(self):
        super(Connection, self).__init__()

    def run(self):
        self.factory = WebSocketServerFactory("ws://localhost:9000", debug=False)
        self.factory.protocol = MyServerProtocol
        reactor.listenTCP(9000, self.factory)
        reactor.run(installSignalHandlers=0)

    def send(self, data):
        reactor.callFromThread(self.factory.protocol.sendMessage, self.factory.protocol, data)

connection = Connection()
connection.daemon = True
connection.start()
connection.send('test')

发生此错误:

connection.send('test')
reactor.callFromThread(self.factory.protocol.sendMessage, self.factory.protocol, data)
AttributeError: 'Connection' object has no attribute 'factory'

如果我尝试注释掉connection.send('test') 行,就会出现这个错误:

TypeError: 'NoneType' object is not iterable

我的代码有什么问题?

我这样做是否正确?还是有其他方法可以从协议类之外向客户端发送消息?

谢谢。

【问题讨论】:

  • 调用 send 时 self.factory 是否存在?尝试在 start() 和 send() 之间休眠并检查。另外,使用调试器。
  • 你有没有想过如何做到这一点?我也有同样的问题。

标签: python autobahn


【解决方案1】:

[还有]另一种从服务器类外部发送客户端消息的方法吗?

我做这样的事情来发送消息。我使用twisted 来运行我的网络应用程序。

import json
from autobahn.twisted.websocket import WebSocketServerProtocol
from twisted.internet import reactor

class MyProtocol(WebSocketServerProtocol):
    connections = list()

    def onConnect(self, request):
        self.connections.append(self)

    def onClose(self, wasClean, code, reason):
        self.connections.remove(self)

    @classmethod
    def broadcast_message(cls, data):
        payload = json.dumps(data, ensure_ascii = False).encode('utf8')
        for c in set(cls.connections):
            reactor.callFromThread(cls.sendMessage, c, payload)


# Somewhere else
MyProtocol.broadcast_message({'greeting': 'Hello world'})

我不知道它是否是 The Right Way™,但它对我很有效。

【讨论】:

    【解决方案2】:

    将 self.factory 添加到您的“init(self):”中,见下文:

    from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
        from twisted.internet import reactor
        import threading
    
        class MyServerProtocol(WebSocketServerProtocol):
            def onConnect(self, request):
                print("Client connecting: {0}".format(request.peer))
    
            def onOpen(self):
                print("WebSocket connection open.")
    
            def onMessage(self, payload, isBinary):
                if isBinary:
                    print("Binary message received: {0} bytes".format(len(payload)))
                else:
                    print("Text message received: {0}".format(payload.decode('utf8')))
    
                self.sendMessage(payload, isBinary)
    
            def onClose(self, wasClean, code, reason):
                print("WebSocket connection closed: {0}".format(reason))
    
    
        class Connection(threading.Thread):
            def __init__(self,factory):
                super(Connection, self).__init__()
                self.factory=WebSocketServerFactory("ws://localhost:9000", debug=False)
            def run(self):
                self.factory.protocol = MyServerProtocol()
                reactor.listenTCP(9000, self.factory)
                reactor.run(installSignalHandlers=0)
    
            def send(self, data):
                reactor.callFromThread(self.factory.protocol.sendMessage, self.factory.protocol, data)
    
        connection = Connection()
        connection.daemon = True
        connection.start()
        connection.send('test')
    

    【讨论】:

    • 这个线程是否也处理对等点的多个连接?
    猜你喜欢
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    相关资源
    最近更新 更多