Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python socketio example to connect to cryptocompare

I am trying to connect to Cryptocompare's websocket stream using socketIO from a Python client. This is proving to be challenging. Here is some sample Python code:

from socketIO_client import SocketIO

print "connecting to server"
socketIO = SocketIO('https://streamer.cryptocompare.com/',443, transports=['websocket'])
print "Connected"

However, I am not able to connect, whatever I do. In fact, this is the result of that connect

connecting to server
Traceback (most recent call last):
  File "test.py", line 4, in <module>
socketIO = SocketIO('https://streamer.cryptocompare.com/',443, transports=['websocket'])
  File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 353, in __init__
resource, hurry_interval_in_seconds, **kw)
  File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 54, in __init__
self._transport
  File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 62, in _transport
self._engineIO_session = self._get_engineIO_session()
  File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 76, in _get_engineIO_session
transport.recv_packet())
StopIteration

Wrapping the above code in a try-catch and printing the exception yields no extra information. Any help would be greatly appreciated.

like image 954
Barry Steyn Avatar asked Oct 04 '17 16:10

Barry Steyn


People also ask

Does Socket.IO use WebSockets?

Socket.IO is NOT a WebSocket implementation. Although Socket.IO indeed uses WebSocket for transport when possible, it adds additional metadata to each packet.

What is Socket.IO used for?

Socket.IO was created in 2010. It was developed to use open connections to facilitate realtime communication, still a relatively new phenomenon at the time. Socket.IO allows bi-directional communication between client and server.

Does Socket.IO use HTTP?

js) and the Socket.IO client (browser, Node. js, or another programming language) is established with a WebSocket connection whenever possible, and will use HTTP long-polling as fallback.


1 Answers

The socketIO_client library does not seem to support the XHR polling protocol that is used by cryptocompare. I got it to work by overriding the method recv_packet in the socketIO_client.transports.XHR_PollingTransport class.

import logging
import socketIO_client
from socketIO_client.transports import get_response
from socketIO_client.parsers import get_byte, _read_packet_text, parse_packet_text

from requests.exceptions import ConnectionError

# extra function to support XHR1 style protocol
def _new_read_packet_length(content, content_index):
    packet_length_string = ''
    while get_byte(content, content_index) != ord(':'):
        byte = get_byte(content, content_index)
        packet_length_string += chr(byte)
        content_index += 1
    content_index += 1
    return content_index, int(packet_length_string)

def new_decode_engineIO_content(content):
    content_index = 0
    content_length = len(content)
    while content_index < content_length:
        try:
            content_index, packet_length = _new_read_packet_length(
                content, content_index)
        except IndexError:
            break
        content_index, packet_text = _read_packet_text(
            content, content_index, packet_length)
        engineIO_packet_type, engineIO_packet_data = parse_packet_text(
            packet_text)
        yield engineIO_packet_type, engineIO_packet_data

def new_recv_packet(self):
    params = dict(self._params)
    params['t'] = self._get_timestamp()
    response = get_response(
        self.http_session.get,
        self._http_url,
        params=params,
        **self._kw_get)
    for engineIO_packet in new_decode_engineIO_content(response.content):
        engineIO_packet_type, engineIO_packet_data = engineIO_packet
        yield engineIO_packet_type, engineIO_packet_data

setattr(socketIO_client.transports.XHR_PollingTransport, 'recv_packet', new_recv_packet)

logging.basicConfig(level=logging.DEBUG)

try:
    socket = socketIO_client.SocketIO('https://streamer.cryptocompare.com')
    socket.emit('SubAdd', { 'subs': ['0~Kraken~BTC~USD'] });
    socket.wait()
except ConnectionError:
    print('The server is down. Try again later.')

The solution is heavily based on this github comment: https://github.com/invisibleroads/socketIO-client/issues/129#issuecomment-330058318

like image 161
Timo.S Avatar answered Sep 19 '22 06:09

Timo.S