Zum Inhalt springen

Websocket vs Socket.IO / Socket.IO zeigt keine Events


Noobfire

Empfohlene Beiträge

Hallo zusammen,

ich habe schon in der Vergangenheit mit der Trading-API gearbeitet und da nie große Probleme gehabt. Egal, ob man vorgefertige Modules nimmt oder die paar GET/POST-Requests eben selbst implementiert, das ging immer einwandfrei.

Als ich mich aber mit der Echtzeit-Tradingbook-Abfrage über den Websocket/Socket.IO-Server beschäftigte, bin ich auf größere Probleme gestoßen.

Wie ich sehe, gibt es folgende Möglichkeiten, diese Server zu nutzen (bitte mich korrigieren bzw. weitere Möglichkeiten nennen, wenn ich sie nicht nenne!):

  • Wie in der Doku unter https://www.bitcoin.de/de/api/tapi/v4/docu beschrieben den Socket.IO-Server in Version 0.9.16 unter https://ws.bitcoin.de nutzen. Das war mir persönlich einfach zu blöd, da entsprechende Libraries mit einer solch alten Version zu finden
  • HTTP-GET-Request an https://ws.bitcoin.de/socket.io/1, um Websocket-Key zu bekommen und dann Websocket an wss://ws.bitcoin.de/socket.io/1/websocket/[KEY] binden. Funktioniert soweit super, bricht aber wie mehrfach im Forum genannt nach rund 90 Sekunden ab.
  • Den Websocket unter wss://ws.bitcoin.de/socket.io/1/websocket/ nicht getrennt vom GET-Request aufbauen, sondern die ursprüngliche HTTP-Verbindung zum Erhalt eines Keys zu einer Websocket-Verbindung "upgraden", wie im Code von Matthias Linden geschehen: https://github.com/matthiaslinden/bitcoinDE_API/blob/master/bitcoinDEws.py. Das behebt das Problem des Abbrechens nach 90 Sekunden.
  • Wieso der ganze Stress? Im Quellcode zum Marketplace von Bitcoin.de auf z.B.: https://www.bitcoin.de/de/etheur/market sieht man ganz klar in Zeile 710 u.f., dass KEINER dieser genannten Server verwendet wird, sondern ein REINER Socket.IO Server unter https://ws2.bitcoin.de:443/market (path: /socket.io/1), siehe diesen Auszug aus Quellcode:
var socket = io('https://ws2.bitcoin.de:443/market', {path: '/socket.io/1'});

Wenn ich diesen in einem Online-Socket.IO-Open-Source-Tool teste, funktioniert auch alles direkt ohne verschwurbeltes Connection-"Upgrade", uralten Socket.IO-Versionen oder irgendwelchen Websockets ["always aim for the simplest solution"]:

https://amritb.github.io/socketio-client-tool/#url=aHR0cHM6Ly93czIuYml0Y29pbi5kZTo0NDMvbWFya2V0&path=L3NvY2tldC5pby8x&opt=&events=add_order,remove_order

Wenn ich das aber mit diesem Minimal-Example-Code teste, erhalte ich eine Message, dass die Connection hergestellt werden konnte, aber leider KEINE add_order/remove_order-Events:

import socketio

sio = socketio.Client()

@sio.event
def connect():
    print('connection established')

@sio.event
def add_order(data):
    print('message received with ', data)

@sio.event
def remove_order(data):
    print('message received with ', data)

@sio.event
def disconnect():
    print('disconnected from server')

sio.connect("https://ws2.bitcoin.de:443/market/", socketio_path="/socket.io/1")
sio.wait()

# connection established
# [Warten...Warten...]
# [STRG-C] 
# disconnected from server

Handelt es sich dabei um ein Problem an meinem Netzwerk oder ist etwas an meinem Code falsch? Mit Socket.IO kenne ich mich leider nicht so super aus, bin eher in der Numerik unterwegs..

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 Wochen später...

Hallo,

ich bin ebenfalls auf diese Probleme gestoßen und kann den Ärger absolut nachvollziehen; die Dokumentation zur WebSocket API ist unzureichend. Du findest die Lösung im Code von Matthias Linden; der Handshake mit dem EIO-Server wird mit einer Folge von Nachrichten abgeschlossen (https://socket.io/docs/v2/internals/), wobei mit der letzten Nachricht die Market-Messages (add_order, remove_order) angefordert werden (kann man auch sehr schön in den Chrome-Developer Tools nachvollziehen).

Viele Grüße

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke @jacketis für den Tipp, mit den Chrome Developer Tools die Netzwerkpakete zu sniffen.

Dort ist mir mit verschiedenen Websocket-Client-Tools und dem schon von mir angesprochenen Socket.io Client Tool (neue URL: https://amritb.github.io/socketio-client-tool/v1/#url=aHR0cHM6Ly93czIuYml0Y29pbi5kZTo0NDMv&path=L3NvY2tldC5pby8x&opt=&events=add_order,remove_order) aufgefallen, dass neben dem Verbinden mit dem Websocket noch das Packet "40/market," gesendet wird.

Nach ein bisschen Recherche war mir dann bewusst, dass es dabei um den Namespace "/market" geht, der noch verbunden werden muss. Das war der Grund, wieso die Connection ohne Probleme funktioniert hatte, die Events aber nicht triggern. Diese werden nämlich erst geschickt, sobald man mit dem Namespace "/market" verbindet.

Außerdem ist mir beim Paket sniffen auch aufgefallen, dass die Websocket/Socket.io-Tools nur ein "Upgrade"-Paket an "wss://ws3.bitcoin.de/socket.io/1/?EIO=3&transport=websocket" senden, mit dem dann ein Websocket aufgebaut wird. Also kein "Get"-Paket, um dann in einem Handshake Verfahren eine "sid" (Session ID) zu erhalten, mit der man sich daraufhin wieder neu verbinden/die Connection upgraden muss. Ein einzelnes Paket tut es also auch.

Hier also der nun ohne Probleme funktionierende und wesentlich kompaktere/aufgeräumtere Code im Vergleich zu z.B. dem Code von Matthias Linden:

import socketio

sio = socketio.Client()


@sio.on('connect')
def connect():
    print('connection established')


@sio.on('add_order', namespace="/market")
def add_order(data):
    print('add received with ', data)


@sio.on('remove_order', namespace="/market")
def remove_order(data):
    print('remove received with ', data)


@sio.on('disconnect')
def disconnect():
    print('disconnected from server')


sio.connect("wss://ws3.bitcoin.de", socketio_path="/socket.io/1", transports="websocket", namespaces=["/market"])
sio.wait()

Wenn man da mal "hinter die Kulissen" schaut, also den Source-Code betrachtet, sieht man, dass nur ein Websocket aufgebaut wird (Z. 373 f. in engineio/client.py):

        try:
            ws = websocket.create_connection(
                websocket_url + self._get_url_timestamp(), header=headers,
                cookie=cookies, enable_multithread=True, **extra_options)

Dann auf ein "OPEN"-Paket (z.B.: 0{"sid":"oDpvivQAFR2URXc_CUTF","upgrades":[],"pingInterval":25000,"pingTimeout":5000} ) gehorcht wird (Z. 417 f. in engineio/client.py):

            try:
                p = ws.recv()
            except Exception as e:  # pragma: no cover
                raise exceptions.ConnectionError(
                    'Unexpected recv exception: ' + str(e))
            open_packet = packet.Packet(encoded_packet=p)
            if open_packet.packet_type != packet.OPEN:
                raise exceptions.ConnectionError('no OPEN packet')

Und schlussendlich mit allen angegebenen Namespaces verbunden wird (in meinem Falle nur "/market") mit einem Paket "40/market" (Z. 478 f. in socketio/client.py):

            for n in self.namespaces:
                self._send_packet(packet.Packet(packet.CONNECT, namespace=n))

Im Hintergrund passiert dann noch in der "_ping_loop" (Z. 523 f. in engineio/client.py), dass im angegebenen Intervall ein Paket "2" gesendet wird, welches wiederum vom Websocket mit einem Paket "3" erwidert wird.

            self._send_packet(packet.Packet(packet.PING))
            self.ping_loop_event.wait(timeout=self.ping_interval)

Also im Grunde genommen keine große Magie, man muss auch nicht irgendwelche Sessions im Handshake-Verfahren upgraden, eigene Socks-Sockets aufbauen, etc.

Man kann das sehr einfach selbst nachstellen:

import websocket

ws = websocket.create_connection("wss://ws3.bitcoin.de/socket.io/1/?EIO=3&transport=websocket")  # Aufbauen des Websocket
# Es kommen noch keine add_order / remove_order events an
ws.send(b"40/market,")  # Verbinden mit Namespace "market"

while True:
    print(ws.recv())  # Jetzt sieht man Haufenweise Events

Wenn man jetzt noch in einem extra Thread immer wieder einmal ein Ping Paket ("2") gesendet wird, bricht diese Verbindung auch nicht ab und läuft im Prinzip endlos.

Das passiert bei python-socketio/engine io in Zeile 439 f. in engineio/client.py und spawnt intern einen Thread mit dem threading-Modul:

        self.ping_loop_task = self.start_background_task(self._ping_loop)

 

Bearbeitet von Noobfire
  • Thanks 1
Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke erstmal an euch beide, da ihr euch ja wirklich tief in die GEschichte reingefuchst habt, und ich - da der Websocket nicht klappte - alle paar sekunde für mien Projekt das Orderbuch abfrage :D

Eher so Weg des geringsten Widerstands als Eleganz.

Da ich aber bei eurer für mich beeindruckenden Unterhaltung ca 5 Niveais zu tief einsteige habe ich noch ein paar Fragen.

Ich habe nun das socketio-Packet von Miguel Grinberg eingebunden und dein (noobfire) Codebeispiel läuft ohne Fehler durch.

Allerdings Endet der Code nach einem Durchlauf "erfolgreich".

Es erscheint nicht mal das

@sio.on('connect')
def connect():
    print('connection established')

Event.

Ich habe irgendwie erwartet, dass die Prozedur weiterläuft und bei einkommenden Ereignissen die Daten ausgibt, wie es bei dem socketio-client-tool der Fall ist, wenn man die Events korrekt eingibt.

Habe ich einen Denkfehler bzw. wo liegt dieser?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi Tyler,

super, dass der Code schon Leuten helfen konnte!

Ohne weitere Informationen kann man da nicht viel helfen. Bitte füge mal direkt nach Instantiieren des SocketIO Clients folgende Zeilen hinzu:

sio = socketio.Client()
# Neue Zeilen:
sio.logger.setLevel("INFO")
sio.eio.logger.setLevel("INFO")

Damit werden dann Debug-Informationen mit ausgegeben.

Ein korrekter Output ist dann z.B.:
 

Attempting WebSocket connection to wss://ws3.bitcoin.de/socket.io/1/?transport=websocket&EIO=3
WebSocket connection accepted with {'sid': 'AN8nFfqcyh4cAo3bCdOU', 'upgrades': [], 'pingInterval': 25000, 'pingTimeout': 5000}
Engine.IO connection established
Sending packet PING data None
Received packet MESSAGE data 0
Namespace / is connected
Sending packet MESSAGE data 0/market
connection established
Received packet PONG data None
Received packet MESSAGE data 0/market,
Namespace /market is connected
Received packet MESSAGE data 2/market,["add_order",{"id":"124387689","type":"order","amount":"1","min_amount":"0.5","price":"1260.01","volume":"1260.01","min_trust_level":"bronze","only_kyc_full":"1","seat_of_bank_of_creator":"de","bic_short":"0yzjuYIRljklPFBa","bic_full":"0yzjuYIR3nAUN_5IB4io2TAw2g..","uid":"0ywbxpkNpYslfFWTrss.","trade_to_sepa_country":"[\"DE\",\"AT\",\"CH\",\"BE\",\"GR\",\"MT\",\"SI\",\"BG\",\"IE\",\"NL\",\"SK\",\"DK\",\"IT\",\"ES\",\"HR\",\"PL\",\"CZ\",\"EE\",\"LV\",\"PT\",\"HU\",\"FI\",\"LT\",\"RO\",\"GB\",\"FR\",\"LU\",\"SE\",\"CY\",\"IS\",\"LI\",\"NO\",\"MQ\"]","is_shorting":"0","is_shorting_allowed":"0","is_trade_by_sepa_allowed":"1","is_trade_by_fidor_reservation_allowed":"0","is_sip_possible":"0","trading_pair":"etheur","fidor_account":"0","is_kyc_full":"1","price_de":"1.260,01 €","volume_de":"1.260,01 €","amount_de":"1","min_amount_de":"0,5","country_payment_method_de":"Deutschland","price_formatted_de":"1.260,01 ","price_en":"€1,260.01","volume_en":"€1,260.01","amount_en":"1","min_amount_en":"0.5","country_payment_method_en":"Germany","price_formatted_en":"1,260.01","price_fr":"1 260,01 €","volume_fr":"1 260,01 €","amount_fr":"1","min_amount_fr":"0,5","country_payment_method_fr":"Allemagne","price_formatted_fr":"1 260,01 ","price_es":"€ 1.260,01","volume_es":"€ 1.260,01","amount_es":"1","min_amount_es":"0,5","country_payment_method_es":"Alemania","price_formatted_es":" 1.260,01","price_it":"€ 1.260,01","volume_it":"€ 1.260,01","amount_it":"1","min_amount_it":"0,5","country_payment_method_it":"Germania","price_formatted_it":" 1.260,01","order_id":"A72B6X","order_type":"buy","sepa_option":"0","payment_option":"2"}]
Received event "add_order" [/market]

 

  • Thanks 1
Link zu diesem Kommentar
Auf anderen Seiten teilen

Ah, ok.

Guter Tipp.

Es kommt websocket-client package not installed, only polling transport is available

Ich habe also offentsichtlich das falsche package installiert.

Dann brauche ich sogar hier mal einen Tipp.

Wenn ich

pip3 install "python-socketio[client]"

in der Shell ausführe, bekomme ich ein Packet namens websocket-client, dass über

import socketio

nicht eingebunden werden kann.

Ich habe dann die Library manuell durchsucht nach dem websocket packat, das laut Signatur von Miguel Grinberg ist: python-socketio.
Die Verlinkung führt auch zu der githubpage, dessen Dokumentation du oben geteilt hast.

Und schon stehe ich auf dem Schlauch :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich weiß gerade nicht, welches OS du verwendest.

Ich vermute mal eher Windows. Es sollte einfach ein

pip3 install python-socketio python-engineio websockets

ausreichen.

Bei Linux Clients (z.B. Ubuntu mit Debian Paketmanager) geht z.B.

sudo apt install python3-socketio python3-engineio python3-websockets

 

  • Like 1
Link zu diesem Kommentar
Auf anderen Seiten teilen

vor einer Stunde schrieb Noobfire:

pip3 install python-socketio python-engineio websockets

 

Windows ist korrekt.

Über pip3 list bekomme ich foldende Packages, die installiert sind.

Package          Version
---------------- ---------
bidict           0.21.2
certifi          2020.12.5
chardet          4.0.0
idna             2.10
pip              21.0.1
python-engineio  4.0.0
python-socketio  5.0.4
requests         2.25.1
setuptools       3.3
six              1.15.0
urllib3          1.26.2
websocket-client 0.57.0
websockets       3.3

Interessanterweise bekomme ich in Pycharm

PyJWT 1.7.1 2.0.1
bidict 0.21.2 0.21.2
cachetools 4.2.0 4.2.1
certifi 2020.12.5 2020.12.5
chardet 4.0.0 4.0.0
google-api-core 1.25.0 1.25.1
google-api-python-client 1.12.8 1.12.8
google-auth 1.24.0 1.25.0
google-auth-httplib2 0.0.4 0.0.4
google-auth-oauthlib 0.4.2 0.4.2
googleapis-common-protos 1.52.0 1.52.0
gspread 3.6.0 3.6.0
httplib2 0.18.1 0.18.1
idna 2.10 3.1
oauthlib 3.1.0 3.1.0
pip 21.0 21.0.1
protobuf 3.14.0 3.14.0
pyasn1 0.4.8 0.4.8
pyasn1-modules 0.2.8 0.2.8
python-engineio 4.0.0 4.0.0
python-socketio 5.0.4 5.0.4
pytz 2020.5 2021.1
requests 2.25.1 2.25.1
requests-oauthlib 1.3.0 1.3.0
rsa 4.7 4.7
setuptools 52.0.0 53.0.0
six 1.15.0 1.15.0
twilio 6.51.0 6.51.1
uritemplate 3.0.1 3.0.1
urllib3 1.26.2 1.26.3

Und das erscheint mir schon einleuchtender. Jetzt befürchte ich, dass ich hier irgdnwie eine Pythonverwirrung drin habe. 😱

Muss ich mal schauen, was da los ist.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der Interpreter für das Projekt ist D:\Programme\Python\Python39\python.exe

Was mich etwas wundert ist, dass die Shell bei python help auf [...]\AppData\Local\Microsoft\WindowsApps verweist, in dem auch noch mal python.exe und python3.9.exe liegen.

Das weiß ich aber nicht, wie die Pythoninstallation die Dateien ablegt und ob das nur ein Verweis ist.

Edit:

Anscheinend ist über den Windows Store eine Pythoninstanz installiert, und ich habe es manuell installiert gehabt.
Ich versuche das mal zusammen zu ziehen.
Bis jetzt ist es nicht aufgefallen, da ich alle packages über pycharm installiert habe. Wenn ich jetzt den client über pip3 install installiert habe, hat er es auf die windows Store installation geschrieben (wo auch immer die liegt).

Ich deinstalliere jetzt alles, starte neu und installierte noch einmal. Mal sehen was dann rum kommt.

 

Edit2:

Jetzt ist alles klar. Alle meine Probleme kamen anscheinend tatsächlich daher, dass ich 2 mal python installiert hatte (wie auch immer und warum auch immer das ging)

Vielen lieben Dank! Jetzt kann ich mich damit beschäftigen die events durchzuarbeiten.
Vielleicht kann ich dir als Dank eine kleine Hilfe geben: LINK

zB ist da die reason aufgeschlüsselt. die für mich sehr relevant ist.

Zitat

 

"0yzjOGFy3vQgfFm0re8." : Durch Nutzer gelöscht

 "0yxjWYBw2RVoMdjPhsLkivcyUrDYnJQ." : Angebot ausgelaufen

und wenn erfolgreich angenommen 

 "0yyDOGDwkTklP1BR" : gekauft

 "0yzjXAA9kDutfQA." : verkauft

 

Zitat

Attempting WebSocket connection to wss://ws3.bitcoin.de/socket.io/1/?transport=websocket&EIO=4
WebSocket connection accepted with {'sid': '07hn71jG3YqNyOUkCz0Y', 'upgrades': [], 'pingInterval': 25000, 'pingTimeout': 5000}
Engine.IO connection established
Sending packet MESSAGE data 0/market
Received packet MESSAGE data 0
Namespace / is connected
connection established
Received packet MESSAGE data 0/market,
Namespace /market is connected
Received packet MESSAGE data 2/market,["refresh_express_option",{"124434364":{"is_trade_by_sepa_allowed":"0","is_trade_by_fidor_reservation_allowed":"1","trading_pair":"btceur"}}]
Received event "refresh_express_option" [/market]

 

Bearbeitet von Tyler_Durden
Link zu diesem Kommentar
Auf anderen Seiten teilen

Am 7.2.2021 um 14:35 schrieb Noobfire:

Wenn man jetzt noch in einem extra Thread immer wieder einmal ein Ping Paket ("2") gesendet wird, bricht diese Verbindung auch nicht ab und läuft im Prinzip endlos.

Ich wieder 😐

Mein Code läuft soweit, wie ich es mir vortslle und loggt schön meinen Datensatz weg :) Danke erst einmal dafür, jetzt spare ich mir das Orderbuck abrufen und bin sogar noch kompletter.

Allerdings stoße ich jetzt auf die von dir erwähnten Verbindungsabbrüche

connection established: 2021-02-11 18:05:46
WebSocket connection accepted with {'sid': '', 'upgrades': [], 'pingInterval': 25000, 'pingTimeout': 5000}

[...]

packet queue is empty, aborting
Exiting write loop task
Received packet NOOP data None
WebSocket connection was closed, aborting
Waiting for write loop task to end
Engine.IO connection dropped
Connection failed, new attempt in 0.96 seconds
Exiting read loop task
disconnected from server: 2021-02-11 18:06:16

Wobei diese alle 30 Sekunden auftreten. (pingInterval + pingTimeout: 25000+5000 ms?)

Ich habe es auch mit dem Ping ws.send("2") probiert und bekomme auch die 3 als Serverantwort. Der Abbruch folgt aber trotzdem, auch wenn ich über websocket statt socketio verbinde.

Ich habe keine analoge Methodik für die socketio gefunden um die Verbindung offen zu halten.
Momentan lasse ich den Code einfach laufen. Allerdings spammt mir

connection established 2021-02-11 18:12:48
packet queue is empty, aborting
disconnected from server 2021-02-11 18:13:18
connection established 2021-02-11 18:13:19

meinen Output zu :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 Wochen später...
Am 23.1.2021 um 16:48 schrieb Noobfire:

HTTP-GET-Request an https://ws.bitcoin.de/socket.io/1, um Websocket-Key zu bekommen und dann Websocket an wss://ws.bitcoin.de/socket.io/1/websocket/[KEY] binden. Funktioniert soweit super, bricht aber wie mehrfach im Forum genannt nach rund 90 Sekunden ab.

Diese Variante benutze ich schon seitdem es die websocket gibt und hatte eig noch nie probleme und auch keinen Abbruch nach 90 sek (mit dem python modul ws4py).

Habe eben die Mail erhalten, dass bitcoin.de updaten wird und in der Doku sieht man, dass man dann auch einen namespace="market" mit übergeben muss.
Bin nicht sonderlich bewandert was das programmieren angeht und ich frag mich gerade, wie ich bei diesem Ansatz, wo ich kein socketio selbst verwende, sondern ganz normale websocket, einen namespace übergeben kann?

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Tyler_Durden Klingt sehr stark danach, als sei am Code generell etwas falsch oder das Netzwerk macht Probleme, wenn du Disconnect messages gespammt bekommst.

@Serpens66 Dass das generell "so geht", hatte ich in meinem ersten Beitrag ja auch beschrieben. Es ist nur völlig überflüssig und umständlich, da ja schon eine socket.io-Anbindung existiert, in die man mit einem 2 Liner connecten kann und sich um nichts mehr kümmern muss.

Das mit den "Namespaces" siehst du in meinem zweiten Kommentar erläutert: https://coinforum.de/topic/23801-websocket-vs-socketio-socketio-zeigt-keine-events/?do=findComment&comment=544326

Da zeige ich, wie alles ohne Probleme mit ein wenig Zeilen Code funktioniert. Dafür muss man aber Socket.io verwenden.

Im Hintergrund passiert da folgendes (Zitat aus meinem Kommentar) nach dem Verbinden mit dem Websocket, um den Namespace zu triggern:

"Und schlussendlich mit allen angegebenen Namespaces verbunden wird (in meinem Falle nur "/market") mit einem Paket "40/market" (Z. 478 f. in socketio/client.py):"

Im gleichen Kommentar zeige ich übrigens ein Minimal-Working Beispiel anhand von einem websocket.

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Noobfire Funktioniert deine Implementierung nach der Wartung von heute (23.02.2021) noch?

Ich hatte meinen Bot bis zur Wartung im Einsatz; seitdem Bitcoin.de wieder erreichbar ist, kann ich mich nicht mehr auf ws2.bitcoin.de, und/oder ws3.bitcoin.de verbinden (das sind die beiden Endpunkte, die bisher schon mit der 2er-Version von Socket.IO funktionierten und ja auch vom Marketplace verwendet werden). Einen 0.9.6-kompatiblen Client hatte ich meinerseits gar nicht mehr implementiert, weil ich davon ausgegangen bin, dass der früher oder später einmal abgelöst wird, kann dazu also keine Aussage treffen...

Die geänderte Dokumentation zur API 4.0 habe ich natürlich schon gesichtet (ws-mig.bitcoin.de funktioniert ebenfalls nicht). Die Verbindungen brechen mir bereits vor dem Probing ab.. das Upgrade der Connection kann mein Client noch einleiten; ich kann die SID entgegennehmen und dann wird die Verbindung vom Host geschlossen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe gerade die von mir bereits genannte socket.io Implementierung getestet und diese hat über eine Viertelstunde Ergebnisse gezeigt (hier einmal mit aktiviertem Debug-Logging):

Attempting WebSocket connection to wss://ws3.bitcoin.de/socket.io/1/?transport=websocket&EIO=3
WebSocket connection accepted with {'sid': 'Zhfxo1U8-51GOHlsAuwi', 'upgrades': [], 'pingInterval': 25000, 'pingTimeout': 5000}
Engine.IO connection established
Sending packet PING data None
Received packet MESSAGE data 0
Namespace / is connected
Sending packet MESSAGE data 0/market
connection established
Received packet PONG data None
Received packet MESSAGE data 0/market,
Namespace /market is connected
Received packet MESSAGE data 2/market,["add_order",{"id":"127294699","type":"offer","amount":"3","min_amount":"2.6","price":"23.55","volume":"70.65","min_trust_level":"bronze","only_kyc_full":"0","seat_of_bank_of_creator":"de","bic_short":"0yzjPeTwlzkig1B-","bic_full":"0yzjPeTw33DssfxIB4io2Mow-w..","uid":"0yybRRwJoQshfFW-rrE.","trade_to_sepa_country":"[\"DE\",\"AT\",\"CH\",\"BE\",\"GR\",\"MT\",\"SI\",\"BG\",\"IE\",\"NL\",\"SK\",\"DK\",\"IT\",\"ES\",\"HR\",\"PL\",\"CZ\",\"EE\",\"LV\",\"PT\",\"HU\",\"FI\",\"LT\",\"RO\",\"GB\",\"FR\",\"LU\",\"SE\",\"CY\",\"IS\",\"LI\",\"NO\",\"MQ\"]","is_shorting":"0","is_shorting_allowed":"0","is_trade_by_sepa_allowed":"1","is_trade_by_fidor_reservation_allowed":"1","is_sip_possible":"0","trading_pair":"btgeur","fidor_account":"0","is_kyc_full":"1","price_de":"23,55 €","volume_de":"70,65 €","amount_de":"3","min_amount_de":"2,6","country_payment_method_de":"Deutschland","price_formatted_de":"23,55 ","price_en":"€23.55","volume_en":"€70.65","amount_en":"3","min_amount_en":"2.6","country_payment_method_en":"Germany","price_formatted_en":"23.55","price_fr":"23,55 €","volume_fr":"70,65 €","amount_fr":"3","min_amount_fr":"2,6","country_payment_method_fr":"Allemagne","price_formatted_fr":"23,55 ","price_es":"€ 23,55","volume_es":"€ 70,65","amount_es":"3","min_amount_es":"2,6","country_payment_method_es":"Alemania","price_formatted_es":" 23,55","price_it":"€ 23,55","volume_it":"€ 70,65","amount_it":"3","min_amount_it":"2,6","country_payment_method_it":"Germania","price_formatted_it":" 23,55","order_id":"TRGM75","order_type":"sell","sepa_option":"0","payment_option":"3"}]
Received event "add_order" [/market]

Hier noch einmal der genutzte Code:

import socketio

sio = socketio.Client()
sio.logger.setLevel("INFO")
sio.eio.logger.setLevel("INFO")

@sio.on('connect')
def connect():
    print('connection established')


@sio.on('add_order', namespace="/market")
def add_order(data):
    print('add received with ', data)


@sio.on('remove_order', namespace="/market")
def remove_order(data):
    print('remove received with ', data)


@sio.on('disconnect')
def disconnect():
    print('disconnected from server')


sio.connect("wss://ws3.bitcoin.de", socketio_path="/socket.io/1", transports="websocket", namespaces=["/market"])
sio.wait()

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ebenfalls funktioniert die Websocket-Implementierung noch ohne Problem:

0{"sid":"Y6QAXrXiDrWyebpwAu_E","upgrades":[],"pingInterval":25000,"pingTimeout":5000}
40
40/market,
42/market,["remove_order",{"id":"127294631","order_id":"YQ62GV","order_type":"buy","type":"order","reason":"0yzjOGFy3vQgfFm0re8.","trade_user_id":"0yybR5sNowsmfFXerrA.","trading_pair":"btceur"}]
42/market,["add_order",{"id":"127294908","type":"order","amount":"0.62","min_amount":"0.0122","price":"39584.09","volume":"24542.1358","min_trust_level":"bronze","only_kyc_full":"0","seat_of_bank_of_creator":"de","bic_short":"0yzjuYIRljklPFBa","bic_full":"0yzjuYIR3nAUN_5IB4io2TAw2g..","uid":"0ywbxpkNpYslfFWTrss.","trade_to_sepa_country":"[\"DE\",\"AT\",\"CH\",\"BE\",\"GR\",\"MT\",\"SI\",\"BG\",\"IE\",\"NL\",\"SK\",\"DK\",\"IT\",\"ES\",\"HR\",\"PL\",\"CZ\",\"EE\",\"LV\",\"PT\",\"HU\",\"FI\",\"LT\",\"RO\",\"GB\",\"FR\",\"LU\",\"SE\",\"CY\",\"IS\",\"LI\",\"NO\",\"MQ\"]","is_shorting":"0","is_shorting_allowed":"0","is_trade_by_sepa_allowed":"1","is_trade_by_fidor_reservation_allowed":"0","is_sip_possible":"0","trading_pair":"btceur","fidor_account":"0","is_kyc_full":"1","price_de":"39.584,09 €","volume_de":"24.542,14 €","amount_de":"0,62","min_amount_de":"0,0122","country_payment_method_de":"Deutschland","price_formatted_de":"39.584,09 ","price_en":"€39,584.09","volume_en":"€24,542.14","amount_en":"0.62","min_amount_en":"0.0122","country_payment_method_en":"Germany","price_formatted_en":"39,584.09","price_fr":"39 584,09 €","volume_fr":"24 542,14 €","amount_fr":"0,62","min_amount_fr":"0,0122","country_payment_method_fr":"Allemagne","price_formatted_fr":"39 584,09 ","price_es":"€ 39.584,09","volume_es":"€ 24.542,14","amount_es":"0,62","min_amount_es":"0,0122","country_payment_method_es":"Alemania","price_formatted_es":" 39.584,09","price_it":"€ 39.584,09","volume_it":"€ 24.542,14","amount_it":"0,62","min_amount_it":"0,0122","country_payment_method_it":"Germania","price_formatted_it":" 39.584,09","order_id":"8YZNC8","order_type":"buy","sepa_option":"0","payment_option":"2"}]

Mit diesem Code 

import websocket

ws = websocket.create_connection("wss://ws3.bitcoin.de/socket.io/1/?EIO=3&transport=websocket")  # Aufbauen des Websocket
# Es kommen noch keine add_order / remove_order events an
ws.send(b"40/market,")  # Verbinden mit Namespace "market"

while True:
    print(ws.recv())  # Jetzt sieht man Haufenweise Events

 

  • Like 1
Link zu diesem Kommentar
Auf anderen Seiten teilen

@Noobfire Ich habe dein Beispiel ausprobiert; der Client https://github.com/miguelgrinberg/python-socketio möchte die Socket.IO-Protokollversion 4 verwenden, was vermutlich zu folgenden Fehler führt:

Attempting WebSocket connection to wss://ws3.bitcoin.de/socket.io/1/?transport=websocket&EIO=4
Traceback (most recent call last):
  File "Y:/src/socketio/python-example/sample.py", line 28, in <module>
    sio.connect("wss://ws3.bitcoin.de", socketio_path="/socket.io/1", transports="websocket", namespaces=["/market"])
  File "Y:\src\socketio\python-example\venv\lib\site-packages\socketio\client.py", line 284, in connect
    raise exceptions.ConnectionError(exc.args[0]) from None
socketio.exceptions.ConnectionError: Connection error

Process finished with exit code 1

Weißt du wie man die Protokollversion steuern kann?

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 8 Stunden schrieb Noobfire:

@Tyler_Durden Klingt sehr stark danach, als sei am Code generell etwas falsch oder das Netzwerk macht Probleme, wenn du Disconnect messages gespammt bekommst.

@Serpens66 Dass das generell "so geht", hatte ich in meinem ersten Beitrag ja auch beschrieben. Es ist nur völlig überflüssig und umständlich, da ja schon eine socket.io-Anbindung existiert, in die man mit einem 2 Liner connecten kann und sich um nichts mehr kümmern muss.

Das mit den "Namespaces" siehst du in meinem zweiten Kommentar erläutert: https://coinforum.de/topic/23801-websocket-vs-socketio-socketio-zeigt-keine-events/?do=findComment&comment=544326

Da zeige ich, wie alles ohne Probleme mit ein wenig Zeilen Code funktioniert. Dafür muss man aber Socket.io verwenden.

Im Hintergrund passiert da folgendes (Zitat aus meinem Kommentar) nach dem Verbinden mit dem Websocket, um den Namespace zu triggern:

"Und schlussendlich mit allen angegebenen Namespaces verbunden wird (in meinem Falle nur "/market") mit einem Paket "40/market" (Z. 478 f. in socketio/client.py):"

Im gleichen Kommentar zeige ich übrigens ein Minimal-Working Beispiel anhand von einem websocket.

danke, schön dass es so simpel mit der zeile

ws.send(b"40/market,")  # Verbinden mit Namespace "market"

geht, dann mach ich das so (probier ich morgen mal aus). Hatte die oberen Posts nur überflogen, weil mir das technisch alles viel zu hoch ist und mir war nichtmal klar, dass es schon vorher nen namespace gab. Ich gehe immer den Weg des kleinsten Widerstandes, ich kenn das websocket modul und wie ich mich mit wenigen Zeilen zu bitcoinde und jedem anderen exchange verbinde, da sehe ich nicht ein, warum ich mir jetzt auch noch socketio angucken sollte, wenns auch mit normaler websocket geht :)

Bearbeitet von Serpens66
Link zu diesem Kommentar
Auf anderen Seiten teilen

@jacketis Dass die aktuelle python-socketio & python-engineio Implementierung EIO Version 4 nutzt, ist hardgecoded in engineio.client.py Z.559: https://github.com/miguelgrinberg/python-engineio/blob/2f806acc927ac334541f77455b3a51a879649aeb/engineio/client.py#L559

Da kann man ohne Änderung am Source-Code auch nichts dran ändern.

Das funktioniert bei mir aber auch ohne Probleme, daher kann es nicht daran liegen. Ich würde mal in den Debugger reinschauen, was genau da das Problem ist. Klingt nach einem Netzwerk- oder Package-Problem.

Der Fehler kommt jedenfalls hier: https://github.com/miguelgrinberg/python-socketio/blob/6f812ef8e4b86db8d15fcc9a4d79b721fe7ca068/socketio/client.py#L295 , was wiederum vermutlich hier einen Fehler wirft: https://github.com/miguelgrinberg/python-engineio/blob/2f806acc927ac334541f77455b3a51a879649aeb/engineio/client.py#L419

Logging am besten mal voll einschalten, um genau zu sehen, was genau wann versucht wird. Das geht mit den beiden "[...].logger.setLevel("INFO")" Statements, die ich genannt hatte. Scheint ja am VPN zu liegen?

@Serpens66 Das mit den Namespaces war mir ja wie im ersten Beitrag beschrieben vorher auch nicht bekannt :-D Habe das nur durch Package-"Sniffing" im Chrome mitbekommen (F12 - Network). Das ist für so etwas ziemlich praktisch, weil man sich absolut sicher sein kann, dass genau nur solche Pakete gesendet werden müssen, die ja im Browser anscheinend auch schon funktionieren. Z.B. im Vergleich zu dem Code-Ungestüm von Matthias Linden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 1 Monat später...

aus gegebenen Anlass möchte ich mich gerne an den Thread anhängen, da meine Anfrage mit dem Inhalt zu tun hat. Ab 5.4.2021 wird ja nur noch die neue Schnittstelle der websocket 2.4.0 unterstützt die derzeit schon unter ws-mig.bitcoin.de zur Verfügung steht. Ich selbst arbeite unter perl und habe bisher wie folgt den websocket Verbindungsaufbau vorgenommen:

1. SSL Verbindung zu ws.bitcoin.de:443

2. Request: "GET /socket.io/1/websocket/ HTTP/1.1\nUser-Agent: curl/7.21.4\nHost: ws.bitcoin.de\nAccept: */*\n\n"

3. Auswerten des Reply: "3SwZatg8vOjZfkklTJrM:60:60:websocket,htmlfile,xhr-polling,jsonp-polling" und Übernahme des Keys für den nächsten Request.

4. Request: "GET /socket.io/1/websocket/3SwZatg8vOjZfkklTJrM HTTP/1.1\nUser-Agent: curl/7.21.4\nHost: ws.bitcoin.de\nAccept: */*\nConnection: Upgrade\nUpgrade: websocket\nSec-WebSocket-Version: 13\nSec-WebSocket-Key: 1\n\n"

nun kamen die Daten der Schnittstelle.

ich versuche heute schon den ganzen Tag das bei ws-mig.bitcoin.de hinzubekommen. Kann mir jemand auf die Sprünge helfen. Wo ist die grobe Veränderung?

 

statt "GET /socket.io/1/websocket/" habe ich bei der neuen Schnittstelle "GET /socket.io/1/?EIO=3&transport=polling" versucht. Erhalte dann auch eine SID. Aber jegliche weitere Requests zb "GET /socket.io/1/?EIO=3&transport=websocket&sid=[erhaltene SID] HTTP/1.1" verlaufen ins Leere oder einen 400 Request Error.

 

Jemand eine Idee?

 

 

Bearbeitet von alwi
Link zu diesem Kommentar
Auf anderen Seiten teilen

nach benötigter Ruhepause habe ich nun doch Erfolge verzeichnen können. Es lag an der "10:40/market," wie in anderen Posts schon angesprochen. Nun erhalte ich auf der Verbindung auch Nachrichten. Lediglich das Umschalten auf websocket bleibt erfolglos. Dies wird jedesmal mit "HTTP/1.1 400 Bad Request" quitiert.

 

Meine Anfragen sehen nun wie folgt aus:

GET /socket.io/?EIO=3&transport=polling HTTP/1.1

erhalte dann die sid mit dem Reply:

96:0{"sid":"9rqCqq0FN2T3ECjheEIx","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}2:40"

POST /socket.io/1/?EIO=3&transport=polling&sid=9rqCqq0FN2T3ECjheEIx HTTP/1.1

Postdata: 10:40/market,

GET /socket.io/1/?EIO=3&transport=polling&sid=9rqCqq0FN2T3ECjheEIx HTTP/1.1

erhalten dann Market Daten

dies kann ich beliebig wiederholen. Bekomme stets Market Daten.

dann  Versuch des Websocket Upgrade:

 

Request: GET /socket.io/1/?EIO=3&transport=websocket&sid=9rqCqq0FN2T3ECjheEIx HTTP/1.1
Host: ws2.bitcoin.de
Origin: https://www.bitcoin.de
User-Agent: curl/7.21.4
Accept-Encoding: gzip, deflate, br
Connection: keep-alive, Upgrade
Accept: */*
Upgrade: websocket
Sec-WebSocket-Version: 13
DNT: 1
Sec-WebSocket-Key: 1

 

Reply:

"HTTP/1.1 400 Bad Request
Connection: close
Content-Type: text/html
Content-Length: 11

Bad Request"

 

wo ist die Nadel im Softwarehaufen versteckt???? Vielen Dank für jegliche Hinweise.

 

 

 

Bearbeitet von alwi
Link zu diesem Kommentar
Auf anderen Seiten teilen

so, wieder einen Schritt weiter - Der Request Error kam daher, da der Wert Sec-WebSocket-Key: 1 ungültig war. Wenn ich einen Zufallswert, der dem der Bitcoin.de Seite vom Format entspricht  erhalte ich einen Erfolg:

Received: "HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: GNjnfGW2KXFUifcI8dG2eaQWP8E=

 

aber bisher habe ich mit dem Senden des Wertes "40/market," keinen Erfolg -> Abbruch.

Vielleicht hat ja einer noch eine Idee - sonst kommt die Verzweiflung...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Super, dass es bei dir schonmal voran geht. 

Zu dem Senden von "40/market,". Bei mir war es enorm wichtig, dass dies als Python-Bytes, also ASCII, kodiert war und nicht als Python-String, also UTF-8/Unicode. Da gibt es nämlich insbesondere beim Slash meines Wissens wichtige Unterschiede. Wie das in Perl geht, weiß ich leider nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Erstelle ein Benutzerkonto oder melde Dich an, um zu kommentieren

Du musst ein Benutzerkonto haben, um einen Kommentar verfassen zu können

Benutzerkonto erstellen

Neues Benutzerkonto für unsere Community erstellen. Es ist einfach!

Neues Benutzerkonto erstellen

Anmelden

Du hast bereits ein Benutzerkonto? Melde Dich hier an.

Jetzt anmelden
×
×
  • Neu erstellen...

Wichtige Information

Wir haben Cookies auf Deinem Gerät platziert. Das hilft uns diese Webseite zu verbessern. Du kannst die Cookie-Einstellungen anpassen, andernfalls gehen wir davon aus, dass Du damit einverstanden bist, weiterzumachen.