从高速公路外部发送消息在单独的线程中运行
Posted
技术标签:
【中文标题】从高速公路外部发送消息在单独的线程中运行【英文标题】: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() 之间休眠并检查。另外,使用调试器。 你有没有想过如何做到这一点?我也有同样的问题。 【参考方案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')
【讨论】:
这个线程是否也处理对等点的多个连接?以上是关于从高速公路外部发送消息在单独的线程中运行的主要内容,如果未能解决你的问题,请参考以下文章
将JMS消息从Java EE应用程序发送到Java SE应用程序
Python Tornado 从另一个线程发送 WebSocket 消息