如何在实时服务器而不是本地主机上使用 Tornado 实现 WebSocket

Posted

技术标签:

【中文标题】如何在实时服务器而不是本地主机上使用 Tornado 实现 WebSocket【英文标题】:how can I implement a WebSocket using Tornado on a live server instead of localhost 【发布时间】:2021-06-29 13:09:08 【问题描述】:

我是使用 WebSockets 的新手,到目前为止,我仅限于通过 localhost 使用它们并在本地开发一切。我已按照本教程进行实时数据可视化: https://medium.com/@benjaminmbrown/real-time-data-visualization-with-d3-crossfilter-and-websockets-in-python-tutorial-dba5255e7f0e

我完成了本教程(所有脚本都可以从文章中的 GitHub 链接获得)并且它可以通过 localhost 完美运行。但是,我有一些网站空间,当 WebSocket 脚本在浏览器中显示网站的同一台本地机器上运行时(在本例中监听 localhost 8001),我可以放置主索引脚本,但是我正在努力弄清楚如何将 WebSocket 与实时服务器一起使用,而不仅仅是通过本文中的本地主机方法!我希望能够通过我的网站访问显示来自任何计算机的实时数据的网页,即有一台运行 WebSocket 的计算机与在其浏览器中显示网站的计算机无关。任何帮助将不胜感激!

编辑:我认为我在重写websocket.py 脚本时特别需要帮助,以便将信息提供给服务器,即www.examplewebsite.com,然后我可以通过我的索引文件页面www.examplewebsite.com/index.html 使用我的索引文件中的js:

var connection = new WebSocket('wss://examplewebsite.com/blank:8001/websocket');

或类似的东西,而不是

 var connection = new WebSocket('ws://localhost:8001/websocket');

在原始版本中,但我不确定在使用现有代码设置 WebSocket 时如何建立它以便在索引文件中侦听。在我的本地机器上运行 WebSocket 时,实时网页成功显示实时更新数据,但是,如果其他人(未运行 WebSocket)进入同一页面,他们将看不到实时数据。

websocket.py脚本如下:

import time
import random
import json
import datetime
import os
from tornado import websocket, web, ioloop
from datetime import timedelta
from random import randint

paymentTypes = ["cash", "tab", "visa","mastercard","bitcoin"]
namesArray = ['Ben', 'Jarrod', 'Vijay', 'Aziz']


class WebSocketHandler(websocket.WebSocketHandler):
  # Addition for Tornado as of 2017, need the following method
  # per: http://***.com/questions/24851207/tornado-403-get-warning-when-opening-websocket/25071488#25071488
  def check_origin(self, origin):
    return True

  #on open of this socket
  def open(self):
    print ('Connection established.')
    #ioloop to wait for 3 seconds before starting to send data
    ioloop.IOLoop.instance().add_timeout(datetime.timedelta(seconds=3), self.send_data)

 #close connection
  def on_close(self):
    print ('Connection closed.')

  def check_origin(self, origin):
    return True

  # Our function to send new (random) data for charts
  def send_data(self):
    print ("Sending Data")
    #create a bunch of random data for various dimensions we want
    qty = random.randrange(1,4)
    total = random.randrange(30,1000)
    tip = random.randrange(10, 100)
    payType = paymentTypes[random.randrange(0,4)]
    name = namesArray[random.randrange(0,4)]
    spent = random.randrange(1,150);
    year = random.randrange(2012,2016)

    #create a new data point
    point_data = 
        'quantity': qty,
        'total' : total,
        'tip': tip,
        'payType': payType,
        'Name': name,
        'Spent': spent,
        'Year' : year,
        'x': time.time()
    

    print (point_data)

    #write the json object to the socket
    self.write_message(json.dumps(point_data))

    #create new ioloop instance to intermittently publish data
    ioloop.IOLoop.instance().add_timeout(datetime.timedelta(seconds=1), self.send_data)

if __name__ == "__main__":
  #create new web app w/ websocket endpoint available at /websocket
  print ("Starting websocket server program. Awaiting client requests to open websocket ...")
  application = web.Application([(r'/static/(.*)', web.StaticFileHandler, 'path': os.path.dirname(__file__)),
                                 (r'/websocket', WebSocketHandler)])
  application.listen(8001)
  ioloop.IOLoop.instance().start()

所有教程脚本的 Github 链接,我使用的是 index.htmlwebsocket.py:https://github.com/benjaminmbrown/real-time-data-viz-d3-crossfilter-websocket-tutorial/tree/master/rt-data-viz

注意:在我的版本中,我已将websocket.py 脚本中的一些随机生成的数字替换为外部设备生成的数字,因此必须在连接到所述外部设备的机器上以 python 建立 WebSocket。

【问题讨论】:

【参考方案1】:

您的 Web 套接字服务器应该运行在可以通过 主机名IP 地址 通过 DNS 找到的系统上,并在端口 8001 上侦听连接。

假设这个系统可以在local.host.home找到(ping,nslookup),然后改变

var connection = new WebSocket('ws://local.host.home:8001/websocket');

现在服务器应该为任何连接的客户端提供数据。

【讨论】:

你的意思是如果我有一些网站 www.example.com/index.html 并且可以创建另一个页面 www.example.com/blank 我可以使用var connection = new WebSocket('ws://example.com/blank:8001/websocket'); 这样做会改变吗WebSocket 本身的 python 代码? 首先我不知道python,但是如果你有一个可以通过网络访问的系统,将你的web socket服务器代码移动到那里并尝试启动它。您不需要该系统上的网络服务器。在您的服务器脚本中,打印出您的 python 服务器正在侦听连接的主机上的名称。使用此主机名:var connection = new WebSocket('ws://host.name:8001/websocket'); 我认为我的具体问题是如何重写上述代码(websocket.py),以便将数据提供给我的服务器,即如何更改脚本中 WebSocket 的位置将 WebSocket 设置到我的本地主机以外的某个地方,而不是如何通过 js 脚本读取另一端的信息

以上是关于如何在实时服务器而不是本地主机上使用 Tornado 实现 WebSocket的主要内容,如果未能解决你的问题,请参考以下文章

Google 广告显示在本地主机上,但不在实时网络服务器上

如何检测用户是不是在 PHP 中的本地主机上?

准备好的语句在本地主机上工作,但不能在实时服务器上工作,无法获得输出 [重复]

模拟本地主机上的慢速连接

API调用代码在本地主机上工作但不在服务器上

本地主机上的客户端和服务器时的CORS?