Ich versuche, binäre Daten über Websockets, insbesondere komprimierte Strings über Web-Sockets zu übergeben. In meinem aktuellen Setup verwende ich Tornado als Server mit einem websocket Client, der die Binärdaten überträgt. Die Binärdaten werden durch Komprimieren der Daten mit zlib
gebildet. Sowohl der Client als auch der Server sind so einfach wie sie sind und werden unten gezeigt.Tornado websockets unterstützt Binär-Teil 2
Server:
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.web
class WebSocketServer(tornado.websocket.WebSocketHandler):
def open(self):
print 'OPEN'
def on_message(self, message):
print 'len = {}'.format(len(message))
print 'GOT MESSAGE: {}'.format(message.decode('zlib'))
def on_close(self):
print 'CLOSE'
app = tornado.web.Application([
(r'/', WebSocketServer)
])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(9500)
tornado.ioloop.IOLoop.instance().start()
Auftraggeber:
import websocket
host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
message = 'this is my message'.encode('zlib')
print 'Length of message is {}'.format(len(message))
ws.send(message)
Der Client werfen keine Fehler, druckt es, dass die Botschaft: Length of message is 24
. Die Nachricht wird als str
gemäß dem zlib-Standard codiert. Der Server am anderen Ende zeigt nicht an, dass er irgendwelche Nachrichten empfangen hat, er versteht nur, dass ein Client eine Verbindung hergestellt hat, und trennt dann die Verbindung. Weiß jemand, wo das Problem liegt? Ich bin mir nicht sicher, ob das Problem in Tornado oder der Websockets-Bibliothek liegt. Irgendwelche Vorschläge?
EDIT: Als Reaktion auf den Kommentar unten (@plg), modifizierte ich den oben genannten Skripte, um zu zeigen:
- Nicht-codierten Nachrichten können vom Client an den Tornado-Server gesendet werden
- Tornado kann mit einer codierten Nachricht
Server antworten:
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.web
class WebSocketServer(tornado.websocket.WebSocketHandler):
def open(self):
print 'OPEN'
def on_message(self, message):
print 'len = {}'.format(len(message))
print 'GOT MESSAGE: {}'.format(message)
self.write_message(message.encode('zlib'))
def on_close(self):
print 'CLOSE'
app = tornado.web.Application([
(r'/', WebSocketServer)
])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(9500)
tornado.ioloop.IOLoop.instance().start()
Auftraggeber:
import websocket
host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
#message = 'this is my message'.encode('zlib')
message = 'this is my message'
print 'Length of message is {}'.format(len(message))
ws.send(message)
assert ws.recv().decode('zlib') == message
Das System funktioniert gut. Die Bestätigung wirft keinen Fehler. Die decodierte Nachricht stimmt mit der Sende-Nachricht überein. Also ich denke, es gibt ein Problem mit entweder:
- eine codierten Nachricht von dem Client gesendet
- Tornado Empfang codierte Nachrichten
ganz ehrlich zu sein, ich glaube, dass die erste Option mehr ist wahrscheinlich als Tornado. Meiner Meinung nach würde Tornado mich warnen, wenn eine eingehende Nachricht nicht korrekt gemäß dem Websocket-Standard entschlüsselt wird. Noch mehr Vorschläge?
EDIT: Mehr Entwicklung auf wer ist schuld. Anstatt meinen eigenen Server zu verwenden, um meine Verbindung zurück zu übertragen, habe ich die Verbindung an ws://echo.websocket.org/
weitergeleitet. Meine Testanwendung ist wie folgt:
import websocket
host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://echo.websocket.org/')
message = 'this is my message'
ws.send(message.encode('zlib'))
got = ws.recv().decode('zlib')
print 'GOT: {}'.format(got)
assert got == message
Das hat den Test tatsächlich bestanden, die Daten wurden gerade gut erhalten. Ich denke also, dass etwas nicht stimmt, wenn Tornado die Daten empfängt?
Haben Sie es anders herum versucht, um zu sehen, ob es funktioniert oder eine Ausnahme auslöst? Verwenden von ws.recv() im Client und in open(): self.write_message ('dies ist meine Nachricht'.encode (' zlib ')). Hast du es auch ohne die zlib-Komprimierung versucht, nur für den Fall, dass etwas fehlt. – ThinkChaos
@plg Es funktioniert andersherum. Ich schickte eine Standard-ASCII-Nachricht an Tornado, und Tornado antwortete mit der codierten Nachricht. Also diese Richtung funktioniert. – jakebird451