Tornado Websockets throws strange error when streaming from Binance

The code looks like this:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado import gen
from tornado.websocket import websocket_connect

api_data = {
        "method": "SUBSCRIBE",
        "params": [
                "btcusdt@trade"
        ],
        "id": "BTCUSDT",
}

class Client(object):
    def __init__(self, url, timeout):
        self.url = url
        self.timeout = timeout
        self.ioloop = IOLoop.instance()
        self.ws = None
        self.connect()
        PeriodicCallback(self.keep_alive, 20000).start()
        self.ioloop.start()

    @gen.coroutine
    def connect(self):
        print("trying to connect")
        try:
            self.ws = yield websocket_connect(self.url)
        except Exception as e:
            print("connection error")
        else:
            yield self.ws.write_message(json.dumps(api_data))
            print("connected")
            self.run()

    @gen.coroutine
    def run(self):
        while True:
            msg = yield self.ws.read_message()
            if msg is None:
                print("connection closed")
                self.ws = None
                break
            else:
                print(msg)
        exit()

    def keep_alive(self):
        if self.ws is None:
            self.connect()
        else:
            self.ws.write_message("keep alive")

if __name__ == "__main__":
    client = Client("wss://stream.binance.com:9443/ws", 5)

When run, it starts to work but very quickly dumps (within 1 minute) with the error {"error":{"code":3,"msg":"Invalid JSON: expected value at line 1 column 1"}}

screenshot https://imgur.com/a/H7i7Umm

The same program works for other websockets, this problem only happens on Binance API. I am not sure how to fix this, and would greatly appreciate some help! `

That’s the wrong way to keep the connection alive. This write_message() call sends a malformed request which the server does not understand.

Please send WebSocket pings instead:

self.ws.ping()
1 Like

that was exactly it! thank you!!

1 Like