【问题标题】:Using Python to communicate with web socket using JSON使用 Python 与使用 JSON 的 web socket 通信
【发布时间】:2016-10-06 05:57:48
【问题描述】:

为了更好地理解 websockets 是如何在基本的 hello-world 之外使用的,我给自己设定了使用 websockets 和 JSON 从页面获取一些数据的任务(因为 gitxiv 的源代码很容易获得,所以我选择查看在http://gitxiv.com/day/2015/12/31)。

通过 Python 连接到这个 websocket 似乎很简单

from websocket import create_connection
import websocket
import pprint

websocket.enableTrace(True)
ws=create_connection("ws://gitxiv.com/sockjs/212/2aczpiim/websocket")
result = ws.recv()
print "Received '%s'" % result
result = ws.recv()
print "Received '%s'" % result

我对 ws:// url 中的变量并不完全清楚,例如“212”。运行这段代码似乎可以可靠地连接(尽管总是有可能没有正确的变量导致服务器稍后拒绝合作?)

现在,如果我观察 Firefox 和 gitxiv 页面之间的通信,我会看到服务器发送的 websocket 连接之后

o
a["{\"server_id\":\"0\"}"]

上面的脚本得到同样的响应,看来连接成功了。

然而,这是我绊倒的地方。通信的下一步是我的浏览器向网络服务发送了相当多的信息,例如:

"["{\"msg\":\"connect\",\"version\":\"1\",\"support\":[\"1\",\"pre2\",\"pre1\"]}"]"

使用 ws.send() 直接发送这些行会导致“框架中断”。仅发送:

controlstr='{"msg":"connect","version":"1","support":["1","pre2","pre1"]}';
ws.send(controlstr)

导致发送的内容类似于:

send: '\x81\xbd\xef\x17F8\x945+K\x885|\x1a\x8cx(V\x8at2\x1a\xc350]\x9dd/W\x815|\x1a\xde5j\x1a\x9cb6H\x80e2\x1a\xd5Ld\t\xcd;dH\x9drt\x1a\xc356J\x8a&de\x92'

我得到一个不同的错误:

'a["{\\"msg\\":\\"error\\",\\"reason\\":\\"Bad request\\"}"]'

因此,我将此 JSON 消息发送到 websocket 的方式似乎有问题。有谁知道它期望什么格式,以及如何使用 websocket/websocket-client 来实现它?任何澄清/建议都将受到欢迎。

我希望发送的 JSON 消息是 Firefox 的 Websocket 开发人员工具报告的消息:这是一个屏幕截图:

【问题讨论】:

  • 212 只是 URL 的一部分,因此有点随意。你从哪里得到那个发送字符串?此外,我宁愿生成数据结构,然后通过 json.dumps 将其转换为 json。我认为这些消息来自流星框架,因此您可以在那里寻找协议。但是你应该验证它们真的来自流星。
  • 我只是通过使用开发者工具 websocket 扩展来找出 Firefox 发送了哪些流量,从而得到了发送字符串,遵循的理念是说同样的事情应该导致同样的结果。 212 确实有所不同(每次都会获得一个新的网址),但我不确定它有什么影响。听起来很可能是流星-谢谢!
  • 啊抱歉,我的意思是 '\x81\xbd\xef\x17F8...' 此外,您似乎确实需要发送一个由单个字符串组成的 json 列表(这又是有效的 json )。请务必正确转义引号。
  • 那个奇怪的 \x81 等是 Python 所说的它正在打印的内容(行 websocket.enableTrace(True) 导致它给出发送和接收的每条消息的详细信息)。 ws.send() 显然在内部进行了这种转换。
  • 似乎 websocket 客户端对有效负载做了一些二进制处理,这就是打印的内容。除非您想深入了解 websocket 细节,否则我认为输出没有帮助。 Werner 在下面实现了“带有一个有效 json 字符串的数组”,看起来很有希望。

标签: python json websocket telescope


【解决方案1】:

如果您仔细查看通过浏览器发送的内容,请注意:

["{\"msg\":\"connect\"}"]

这看起来很像 JSON 字符串数组。事实上,如果你尝试复制它:

ws.send(json.dumps([json.dumps({'msg': 'connect', 'version': '1', 'support': ['1', 'pre2', 'pre1']})]))

你会发现你已经建立了联系。这是我的完整代码:

import json
import pprint
import websocket
from websocket import create_connection

websocket.enableTrace(True)
ws = create_connection('ws://gitxiv.com/sockjs/212/2aczpiim/websocket')

result = ws.recv()
print('Result: {}'.format(result))

result = ws.recv()
print('Result: {}'.format(result))

ws.send(json.dumps([json.dumps({'msg': 'connect', 'version': '1', 'support': ['1', 'pre2', 'pre1']})]))
result = ws.recv()
print('Result: {}'.format(result))

【讨论】:

  • 我试过一个 json.dumps 没有效果。我没有想到要嵌套它们,就像在 json.dumps([json.dumps({stuff})]) 中那样。这是一个奇妙而神秘的解决方案! (你知道这是不是常见的食谱吗?)
  • @Soz 我个人之前没见过这个。直觉上我会假设数组中的实际 json 更有意义(例如 [{msg1}, {msg2}]),但也许开发人员有他们的理由。
  • 老实说,这对我来说似乎有点疯狂。我能想出的唯一原因是他们有一个可能一次发送多条消息的Web客户端,并指定每条消息必须是JSON编码的。但这真的很奇怪,因为我刚刚指定消息是 JSON 编码的消息数组,例如json.dumps([{'msg': 'connect'}, {'msg': 'frobnosticate'}]),而不是 JSON 编码对象的 JSON 编码列表。我不确定我能想出一个好的理由(尽管我可以发明一些其他“有意义”的理由)
猜你喜欢
  • 1970-01-01
  • 2012-03-28
  • 2019-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 2020-07-06
  • 1970-01-01
相关资源
最近更新 更多