Websockets mit Tornado: Holen Sie sich den Zugriff von "außen" zum senden von Nachrichten an clients
Ich fange an, in WebSockets als Weg zur übertragung von Daten von einem server an die verbundenen clients. Da ich python Programmieren jede Art von Logik, ich sah der Tornado so weit. Der Codeausschnitt unten zeigt die einfachen Beispiel kann man überall auf der Web:
import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
class WSHandler(tornado.websocket.WebSocketHandler):
def open(self):
print 'new connection'
self.write_message("Hello World")
def on_message(self, message):
print 'message received %s' % message
self.write_message('ECHO: ' + message)
def on_close(self):
print 'connection closed'
application = tornado.web.Application([
(r'/ws', WSHandler),
])
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Als es ist, das funktioniert wie vorgesehen. Aber ich kann nicht meinem Kopf herum wie kann dieses "integriert" in dem rest meiner Bewerbung. Im obigen Beispiel wird die WebSocket-nur sendet etwas an die clients als Antwort auf eine client-Nachricht. Wie kann ich auf die WebSocket-von "außen"? Zum Beispiel zur Anzeige aller momentan verbundenen clients, die eine Art-Ereignis aufgetreten ist, -- und dieser Fall ist NICHT jede Art von Nachricht von einem client. Im Idealfall würde ich mag zu schreiben, die irgendwo in meinem code so etwas wie:
websocket_server.send_to_all_clients("Good news everyone...")
Wie kann ich dies tun? Oder muss ich eine komplette misundersanding, wie WebSockets (oder Tornado) arbeiten sollten. Danke!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist aufbauend auf Hans Dann dem Beispiel. Ich hoffe, es hilft Ihnen zu verstehen, wie Sie Ihre server initiieren Sie die Kommunikation mit Ihren Kunden, ohne die Kunden auslösen der Interaktion.
Hier ist der server:
Ich aus der client-Liste einer Klasse, variable, anstatt global. Ich eigentlich nicht dagegen, mit einer globalen variable für diesen, aber da waren Sie besorgt, hier ist ein alternativer Ansatz.
Und hier ist ein Beispiel-client:
Können Sie dann auf dem server ausgeführt werden, und zwei Instanzen der test-client eine Verbindung herstellen. Wenn Sie das tun, der server gibt diese:
Den ersten client druckt diese:
Und der zweite druckt diese:
Für die Zwecke dieses Beispiels, hatte ich gerade den server sendet die Nachricht an die clients, die auf eine 15 Sekunden Verzögerung, aber es könnte ausgelöst werden durch das, was Sie wollen.
ws = WebSocket()
umfasst der server gestartet wird und dann einws.write_to_clients(msg)
wenn ein Ereignis aufgetreten ist? Ist das nicht der Grundgedanke hier? Aber ich konnte nicht finden ein Beispiel noch.write_to_clients
ist nur eine Funktion der obersten Ebene des Moduls, sondern als Methode einer Klasse. Es könnte auch ein parameter, anstatt nur immer mit "Hallo, es gibt". Dann ist Ihr event-handling-code kann nur aufrufen dieser Methode. Macht das Sinn?send_to_all_clients
Methode auf der obersten Ebene des Moduls. Aber in seinem Beispiel ist er immer noch ruft diese Methode innerhalb der WSHandler Klasse. Aber wie kann ich das aufrufen dieser Methode von "überall"? -- Um ein Beispiel zu geben: Sagen Sie, was meine Anwendung macht komplexe Berechnungen, und jedes mal, wenn eine neue Folge verfügbar ist, möchte ich bekannt geben, dass er an alle verbundenen clients.WSHandler.clients
im inneren stattcls.clients
. Dann rufen Sie einfachwrite_to_clients
von der Funktion tun, die Berechnungen.Müssen Sie verfolgen alle clients, die eine Verbindung herstellen. Also:
clients
und für jeden client rufen Sie diewrite_message
Methode. Aber wohin mit der Schleife. Wenn ich das Skript starte, scheint alles blockiert zu sein. Könnte Sie verlängern meine anfängliche Beispiel, um ein komplettes Beispiel mit Ihrem Ansatz, einschließlich einer Schleife über die client-array. Das wäre genial!send_to_all_clients
Aufruf innerhalb der WSHandler Klasse. Wie kann ich jetzt rufen Sie diese Methode von praktisch überall zu integrieren in eine größere Anwendung? Vielleicht habe ich einfach ein völliges Missverständnis über WebSockets.send_to_all_clients
aus, wohin Sie wollen.from ... import send_to_all_clients
und dannsend_to_all_clients('External message')
. Es ist einfach nicht die gleiche Tragweite, dieclients
array ist immer leer, wenn genannt wie diese. Können Sie ein konkretes Beispiel von "Sie können es nennen, von überall Sie wollen"?meine Lösung dazu: zuerst fügen Sie
"if __name__ == '__main__':"
- der main.py. dann importieren main.py in die websocket-Modul. z.B. (import main as MainApp
) . es ist nun möglich, eine Funktion aufzurufen, die in 'main.py" in der ws.py/WebSocketHandler-Funktion. - in den Handler übergeben Sie die Nachricht etwa so:MainApp.function(message)
ich weiß nicht, ob das ist das Gegenteil von elegant, aber es funktioniert für mich.
..plus erstellen und importieren Sie eine benutzerdefinierte 'config.py' (das sieht aus wie:
someVar = int(0)
) in der 'mainApp.py' .. etwa so:import config as cfg
--> jetzt können Sie verändern Variablen mitcfg.someVar = newValue
aus dem inneren der Funktion in 'main.py' das einmal genannt wurde, die von der Prozedur 'ws.py'.