[英]Websockets with Tornado: Get access from the “outside” to send messages to clients
我開始將WebSockets作為將數據從服務器推送到連接客戶端的方式。 因為我使用python來編寫任何類型的邏輯,所以我到目前為止看了Tornado。 下面的代碼段顯示了可以在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()
實際上,這是按預期工作的。 但是,我無法理解如何將這個“集成”到我的應用程序的其余部分。 在上面的示例中,WebSocket僅向客戶端發送內容作為對客戶端消息的回復。 如何從“外部”訪問WebSocket? 例如,要通知所有當前連接的客戶端已發生某種事件 - 此事件不是來自客戶端的任何類型的消息。 理想情況下,我想在我的代碼中寫一些類似於:
websocket_server.send_to_all_clients("Good news everyone...")
我怎樣才能做到這一點? 或者我對WebSockets(或Tornado)應該如何工作有一個完全的誤解。 謝謝!
您需要跟蹤所有連接的客戶端。 所以:
clients = []
def send_to_all_clients(message):
for client in clients:
client.write_message(message)
class WSHandler(tornado.websocket.WebSocketHandler):
def open(self):
send_to_all_clients("new client")
clients.append(self)
def on_close(self):
clients.remove(self)
send_to_all_clients("removing client")
def on_message(self, message):
for client in clients:
if client != self:
client.write_message('ECHO: ' + message)
這是以Hans Then的例子為基礎的。 希望它可以幫助您了解如何讓服務器啟動與客戶的通信,而無需客戶端觸發交互。
這是服務器:
#!/usr/bin/python
import datetime
import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
class WSHandler(tornado.websocket.WebSocketHandler):
clients = []
def open(self):
print 'new connection'
self.write_message("Hello World")
WSHandler.clients.append(self)
def on_message(self, message):
print 'message received %s' % message
self.write_message('ECHO: ' + message)
def on_close(self):
print 'connection closed'
WSHandler.clients.remove(self)
@classmethod
def write_to_clients(cls):
print "Writing to clients"
for client in cls.clients:
client.write_message("Hi there!")
application = tornado.web.Application([
(r'/ws', WSHandler),
])
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(seconds=15), WSHandler.write_to_clients)
tornado.ioloop.IOLoop.instance().start()
我使客戶端列表成為一個類變量,而不是全局變量。 我實際上不介意為此使用全局變量,但由於你關注它,這里是另一種方法。
這是一個示例客戶端:
#!/usr/bin/python
import tornado.websocket
from tornado import gen
@gen.coroutine
def test_ws():
client = yield tornado.websocket.websocket_connect("ws://localhost:8888/ws")
client.write_message("Testing from client")
msg = yield client.read_message()
print("msg is %s" % msg)
msg = yield client.read_message()
print("msg is %s" % msg)
msg = yield client.read_message()
print("msg is %s" % msg)
client.close()
if __name__ == "__main__":
tornado.ioloop.IOLoop.instance().run_sync(test_ws)
然后,您可以運行服務器,並讓測試客戶端的兩個實例連接。 當你這樣做時,服務器打印出這個:
bennu@daveadmin:~$ ./torn.py
new connection
message received Testing from client
new connection
message received Testing from client
<15 second delay>
Writing to clients
connection closed
connection closed
第一個客戶打印這個:
bennu@daveadmin:~$ ./web_client.py
msg is Hello World
msg is ECHO: Testing from client
< 15 second delay>
msg is Hi there! 0
第二個打印出來:
bennu@daveadmin:~$ ./web_client.py
msg is Hello World
msg is ECHO: Testing from client
< 15 second delay>
msg is Hi there! 1
出於示例的目的,我只是讓服務器在15秒的延遲時間內將消息發送給客戶端,但它可以由您想要的任何內容觸發。
我的解決方案:首先將"if __name__ == '__main__':"
- 添加到main.py. 然后將main.py導入websocket模塊。 例如( import main as MainApp
)。 現在可以在ws.py/WebSocketHandler-function中調用'main.py'中的函數。 - 在Handler內傳遞消息,如下所示: MainApp.function(message)
我不知道如果這是優雅的反面但它對我有用。
..plus創建並將自定義'config.py'(看起來像: someVar = int(0)
)導入'mainApp.py'..就像這樣: import config as cfg
- >現在你可以改變變量cfg.someVar = newValue
來自'main.py'中函數內部的cfg.someVar = newValue
,曾由Handler從'ws.py'調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.