javascript - ws4py - send/received_message not working -


i'm encountering issues on making websocket server/client.

this websocket clas:

wslist = []  class loginlivewebsockethandler(websocket):  # /live/ws/zones     loggedon = false      def opened(self):         log("opened!")         wslist.append(self)      def received_message(self, m):         log("received message!")         log(m)         log(m.data)         m = str(m.data)         if not m.startswith("login: ") & (not self.loggedon):             return         if m.startswith("login: ") & self.loggedon:             return         if m.startswith("login: ") & (not self.loggedon):             split = m.replace("login: ", "").split(":")             try:                 id = split[0]                 key = split[1]             except keyerror:                 self.send("login: 0", false)                 return             try:                 usr = users.getuser(id, key)                 nick = usr["nick"]                 loggedin = true                 token = usr["groupme_token"]                 active = usr["active"]             except keyerror or typeerror:                 self.send("login: 0", false)                 return             if (not loggedin) | (not active) | (not local.token) | (local.user["faction"] != "f"):                 self.send("login: 0", false)                 return             self.send("login: 1", false)             self.loggedon = true             return      def closed(self, code, reason=""):         log("closed!")         wslist.remove(self) 

and javascript page (note, not whole):

function init() {             showblocking("connecting...", "progress-bar-success");             var wsprotocol = (location.protocol == "https:") ? "wss://" : "ws://";             var loc = location.pathname;             loc = loc.replace(/live\u002flive$/i, "");             var wsurl = wsprotocol + location.host + loc + "/live/ws_zones";             console.log(wsurl);             var ws = new websocket(wsurl);              var key = getcookie("key");             var id = getcookie("id");              var closed = true;              ws.onopen = function(evt) {                 console.log("onopen");                 $('#pbheader').text("logging in...");                 ws.send("login: " + id + ":" + key);                 closed = false;             }              ws.onmessage = function(evt) {                 console.log("onmessage");                 var channel = evt.data.substring(0, 7);                 var data = evt.data.substr(6);                 if (channel == "login: ") {                     if (data == "0") {                         ws.close();                         closed = true;                         alert("invalid login, please re-login.");                         $('#pbheader').text("invalid login!");                         history.back();                     } else if (data == "1") {                         hideblocking();                     }                 } else if (channel == "zonea: ") {                     // add new thing...                     // %gridref% %zoneid% %zonename% %faction% %legion% %faceless% %swarm%                     var datadict = json.parse(data);                     var replitem = itemtemplate.replace("%count%", count).replace("%gridref%", datadict.gridref).replace("%zoneid%", datadict.zoneid).replace("%zonename%", datadict.zonename).replace("%faction%", datadict.faction).replace("%legion%", datadict.legion).replace("%faceless%", datadict.faceless).replace("%swarm%", datadict.swarm);                     $('#live').prepend(replitem);                     var curritem = $('#item' + count);                     settimeout(function () { fadeoutremove(curritem); }, 60*1000);                     count = count + 1;                 }             }              ws.onclose = function(evt) {                 console.log("closed");                 closed = true;             }              ws.onerror = function(evt) {                 console.log("error");                 closed = true;             }         }          window.addeventlistener("load", init, false); 

mounting service:

log("starting webserver (cherrypy)") cherrypy.server.unsubscribe() if config.do_ssl true:     server1 = cherrypy._cpserver.server()     server1.socket_port = config.listen_port_ssl     server1._socket_host = config.listen     server1.thread_pool = 30     server1.ssl_certificate = config.ssl_certificate     server1.ssl_private_key = config.ssl_private_key     server1.ssl_certificate_chain = config.ssl_chain     server1.ssl_module = config.ssl_handler     server1.subscribe() server2 = cherrypy._cpserver.server() server2.socket_port = config.listen_port server2._socket_host = config.listen server2.thread_pool = 30 server2.subscribe()  websocketplugin(cherrypy.engine).subscribe() cherrypy.tools.websocket = websockettool()  cherrypy.tree.mount(apiservice.apiservice(), "/api", config={"/": {'error_page.404': apiservice.ep}}) cherrypy.tree.mount(jsonservice.jsonservice(), "/json", config={"/": {'error_page.404': jsonservice.ep}}) cherrypy.tree.mount(usrapiservice.usrapiservice(), "/usrapi", config={"/": {'error_page.404': usrapiservice.ep}}) cherrypy.tree.mount(usrapiadminservice.usrapiadminservice(), "/usrapi/admin", config={     "/": {'error_page.404': usrapiservice.ep}}) cherrypy.tree.mount(rootservice.rootservice(), "/", config={"/": {'error_page.404': rootservice.ep}}) cherrypy.tree.mount(adminservice.adminservice(), "/admin", config={"/": {'error_page.404': adminservice.ep}}) cherrypy.tree.mount(helperpanel.helperpanel(), "/helper", config={"/": {'error_page.404': helperpanel.ep}}) cherrypy.tree.mount(liveservice.liveservice(), "/live", config={"/": {'error_page.404': liveservice.ep},                                                                 "/ws_zones": {'tools.websocket.on': true,                                                                               'tools.websocket.handler_cls':                                                                                   liveservice.loginlivewebsockethandler                                                                               }}) cherrypy.tree.mount(none, "/static", config={"/": {'error_page.404': adminservice.ep,                                                    'tools.staticdir.on': true,                                                    'tools.staticdir.dir':                                                        os.path.join(__current_dir, "web/static")}}) cherrypy.engine.start() log("started webserver (cherrypy)") 

liveservice:

class liveservice(object):      @cherrypy.expose     @require(level=0)     def index(self, user, usrname, usrhelper, usradmin):         return render("index", usrname, usrhelper, usradmin)      @cherrypy.expose     @require(level=4)  # require login, groupme, active , faceless     def live(self, user, usrname, usrhelper, usradmin):         return render("websocket/zonesdata", usrname, usrhelper, usradmin)      @cherrypy.expose     def ws_zones(self):         log("handler created: %s" % repr(cherrypy.request.ws_handler))         cherrypy.request.ws_handler.send(b"login 0", false) 

so, mounting , starting works, whole run in production months now, new liveservice ws not working. in log, im getting [21/jul/2015:16:55:28] engine starting websocket processing , opened messages, never receive or able send messages. when change liveservice.loginliveservicewebsockethandler echowebsocket gets messages , sends them, on ws_zones handler

cherrypy.request.ws_handler.send(b"login 0", false)

is not working. wether b or not.

analysis

first thing should pay attention debugging tools @ disposal. instance, when try app in firefox, firebug (or web console) tells you:

firefox can't establish connection server @ ws://127.0.0.1:8080/live/ws_zones.

chromium console has more useful error message:

websocket connection 'ws://127.0.0.1:8080/live/ws_zones' failed: error during websocket handshake: invalid status line

ok, have handshake problem.

if open wireshark (or sniffer) can see indeed our login 0 appears before ws4py replies handshake response (or maybe there race condition).

i can understand confusion, because in several places ws4py documentation either alludes or directly guides wrong way. let's see:

alludes — can not send normal handler.

@cherrypy.expose def ws(self):     # can access class instance through     handler = cherrypy.request.ws_handler 

guides incorrectly — can not send opened hook.

def opened(self):     """     called server when upgrade handshake     has succeeeded.     """     pass 

so think it's either outdated documentation or bug.

solution

for suggest initiate communication on client side. if have pre-login "chat", can make little protocol on top of web sockets (you end doing anyway). this:

#!/usr/bin/env python3   import json  import cherrypy ws4py.server.cherrypyserver import websocketplugin, websockettool ws4py.websocket import websocket   class loginlivewebsockethandler(websocket):    wsset = set()   '''class level attr, not rebind'''     def opened(self):     '''you can not send yet, because handshake has not been completed.     yes, documentation not correct ;-)     '''      cherrypy.log('opened!')     self.wsset.add(self)    def closed(self, code, reason = ''):     cherrypy.log('closed!')     self.wsset.remove(self)    def received_message(self, message):     cherrypy.log('received message!')      message = json.loads(message.data.decode())     if message['cmd'] == 'init':       self.send('login 0')     else:       self.send(message['payload'] + ' pong')   class liveservice(object):    @cherrypy.expose   def index(self):     return '''<!doctype html>       <html>       <body>         <div id='log'></div>         <script type='application/javascript'>           var ws = new websocket('ws://127.0.0.1:8080/live/ws_zones');            ws.onopen = function(event)           {             ws.send(json.stringify({'cmd': 'init'}));           };           ws.onmessage = function(event)           {             document.getelementbyid('log').innerhtml += event.data + '<br/>';           };            var handle = setinterval(function()           {             if(ws.readystate == websocket.closing || ws.readystate == websocket.closed)             {               clearinterval(handle);             }             else             {               ws.send(json.stringify({'cmd': 'chat', 'payload': 'ping'}));             }           }, 1000);           </script>       </body>       </html>     '''    @cherrypy.expose   def ws_zones(self):     '''you can not send yet, because handshake has not been completed'''     cherrypy.log('handler created: %r' % cherrypy.request.ws_handler)    if __name__ == '__main__':   cherrypy.config.update({     'server.socket_host' : '127.0.0.1',     'server.socket_port' : 8080,     'server.thread_pool' : 8   })    cherrypy.tools.websocket = websockettool()   websocketplugin(cherrypy.engine).subscribe()    cherrypy.tree.mount(liveservice(), '/live', {     '/ws_zones' : {       'tools.websocket.on'          : true,       'tools.websocket.handler_cls' : loginlivewebsockethandler     }   })    cherrypy.engine.signals.subscribe()   cherrypy.engine.start()   cherrypy.engine.block() 

Comments

Popular posts from this blog

python - Healpy: From Data to Healpix map -

c - Bitwise operation with (signed) enum value -

xslt - Unnest parent nodes by child node -