2013-09-22 15 views
7

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:

  1. Nicht-codierten Nachrichten können vom Client an den Tornado-Server gesendet werden
  2. 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:

  1. eine codierten Nachricht von dem Client gesendet
  2. 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?

+1

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

+0

@plg Es funktioniert andersherum. Ich schickte eine Standard-ASCII-Nachricht an Tornado, und Tornado antwortete mit der codierten Nachricht. Also diese Richtung funktioniert. – jakebird451

Antwort

3

Nachdem ich den Quellcode der websocket Bibliothek durchgesehen habe, habe ich festgestellt, dass die Pakete standardmäßig als Text formatiert werden.Durch Ändern der Zeile:

ws.send('message') 
# to: 
ws.send('message', opcode=websocket.ABNF.OPCODE_BINARY) 
# or better yet: 
ws.send_binary('message') 

Das Paket wird nur gut gesendet werden. Tornado Ich glaube, ignorierte nur die gefälschten Binärpakete, da sie als Text markiert und binär enthalten waren.

0

Dank dieser commit unterstützt Tornado Websocket-Kompressionserweiterungen.