Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Python to communicate with web socket using JSON

In order to better understand how websockets are used beyond the basic hello-world, I set myself the task of getting some data from a page using websockets and JSON (because the source code of gitxiv is readily available, I chose to look at http://gitxiv.com/day/2015/12/31).

Connecting to this websocket via Python seems to be straightforward

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

I'm not entirely clear about the variables in the ws:// url, like '212'. Running this code seems to reliably connect (although it is always possible that failing to have the right variables in there causes the server to refuse to cooperate later?)

Now if I watch the communication between Firefox and the gitxiv page, I see that following connection of the websocket the server sends

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

The above script gets the same response, so it seems that the connection is successfully made.

However, this is where I stumble. The next step in the communication is that my browser sends quite a lot of information to the web service, such as the line:

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

Sending these lines directly using ws.send() results in 'broken framing'. Sending just:

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

results in something being sent that looks like:

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'

I get a different error:

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

It seems, therefore, that there is something wrong in the way that I am sending this JSON message to the websocket. Does anybody know what format it expects, and how to achieve it using websocket/websocket-client? Any clarification/suggestions would be most welcome.

The JSON messages I am looking to send are those that Firefox's Websocket developer tool reports: here is a screenshot:

Firefox Web Developer Tool report

like image 562
Soz Avatar asked Jun 06 '16 14:06

Soz


People also ask

Can we send json data in a WebSocket connection?

To create a WebSocket and open the connection to FME Server use getWebSocketConnection method. The result is an open WebSocket you can use in your application to communicate with FME Server. This example sends a basic JSON object as a string to the server, and displays the response from the server.

How does Python connect to WebSockets?

WebSocket Client with PythonCreate a new File “client.py” and import the packages as we did in our server code. Now let's create a Python asynchronous function (also called coroutine). async def test(): We will use the connect function from the WebSockets module to build a WebSocket client connection.

Can Python be used with json?

Python Supports JSON Natively! Python comes with a built-in package called json for encoding and decoding JSON data.


1 Answers

If you look closely at what what's sent through the browser, notice that it's:

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

This looks an awful lot like an array of JSON strings. Indeed, if you try to replicate it:

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

You'll see that you get connected. Here's my entire code:

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))
like image 128
Wayne Werner Avatar answered Sep 30 '22 00:09

Wayne Werner