2013-09-22 6 views
7

Próbuję przekazać dane binarne przez websockets, a konkretnie skompresowane łańcuchy na stronach internetowych. W mojej obecnej konfiguracji używam tornada jako serwera z klientem websocket przesyłającym dane binarne. Dane binarne są tworzone przez kompresję danych za pomocą zlib. Zarówno klient, jak i serwer są tak proste, jak to tylko możliwe, i pokazano je poniżej.Sieci webowe podpórki Tornado obsługujące część binarną 2

Serwer:

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() 

Klient:

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) 

Klient nie rzucać żadnych błędów, to wypisuje, że wiadomości: Length of message is 24. Wiadomość jest zakodowana jako str zgodnie ze standardem Zlib. Serwer na drugim końcu nie pokazuje, że otrzymał jakiekolwiek wiadomości, rozumie jedynie, że klient podłączył się, a następnie rozłączył. Czy ktoś wie, gdzie jest problem? Nie jestem pewien, czy problem leży w bibliotece tornada czy w sieci. Jakieś sugestie?


EDIT: W odpowiedzi na komentarz poniżej (@plg), I zmodyfikowane skrypty powyżej, aby pokazać, że:

  1. Non-zakodowane wiadomości można wysyłać od klienta do serwera tornado
  2. Tornado może odpowiadać z zakodowanej wiadomości

Serwer:

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() 

Klient:

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 

System działa dobrze. Aserser nie rzuca błędu. Zdekodowany komunikat odpowiada wiadomości wysłanej. Więc myślę, że jest problem z albo:

  1. Wysyłanie zakodowaną wiadomość od klienta
  2. Tornado odbieranie zakodowane wiadomości

Aby być całkiem szczery, wierzę, że pierwsza opcja jest bardziej prawdopodobne niż tornado. Moim zdaniem, wierzę, że tornado powiadomi mnie, jeśli wiadomość przychodząca nie zostanie poprawnie zdekodowana zgodnie ze standardem websocket. Jakieś dodatkowe sugestie?


EDYCJA: Więcej informacji na temat tego, kto ponosi winę. Zamiast używać mojego własnego serwera do przekazywania z powrotem i czwartego połączenia, przekazałem połączenie do ws://echo.websocket.org/. Moja aplikacja do testowania jest taka jak:

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 

To faktycznie zdało test, dane zostały odebrane dobrze. Sądzę więc, że coś jest nie tak z tornadem odbierającym dane?

+1

Czy próbowałeś zrobić to na odwrót, aby sprawdzić, czy działa lub zgłasza wyjątek? Używanie ws.recv() w kliencie iw open(): self.write_message ("to jest mój message'.encode (" zlib ")). Próbowałeś także bez kompresji zlib, znowu na wypadek, gdyby czegoś nam brakowało. – ThinkChaos

+0

@plg Działa na odwrót. Wysłałem standardową wiadomość ascii do tornada, a tornado odpowiedziało z zakodowaną wiadomością. Ten kierunek działa. – jakebird451

Odpowiedz

3

Po przejrzeniu kodu źródłowego biblioteki websocket stwierdziłem, że domyślnie formatuje pakiety jako tekst.Zmieniając linię:

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

Pakiet zostanie wysłany poprawnie. Tornado Chyba po prostu ignorowałem fałszywe pakiety binarne, ponieważ zostały one oznaczone jako tekst i zawierały binarne.