Skip to content

Instantly share code, notes, and snippets.

@Lawouach
Created November 28, 2013 21:00

Revisions

  1. Lawouach created this gist Nov 28, 2013.
    167 changes: 167 additions & 0 deletions ws4py simple chat example
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,167 @@
    # -*- coding: utf-8 -*-
    import argparse
    import random
    import os

    import cherrypy

    from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
    from ws4py.websocket import WebSocket
    from ws4py.messaging import TextMessage

    USERS = ['mike', 'stella', 'john']

    class ChatPlugin(WebSocketPlugin):
    def __init__(self, bus):
    WebSocketPlugin.__init__(self, bus)
    self.clients = {}

    def start(self):
    WebSocketPlugin.start(self)
    self.bus.subscribe('add-client', self.add_client)
    self.bus.subscribe('get-client', self.get_client)
    self.bus.subscribe('del-client', self.del_client)

    def stop(self):
    WebSocketPlugin.stop(self)
    self.bus.unsubscribe('add-client', self.add_client)
    self.bus.unsubscribe('get-client', self.get_client)
    self.bus.unsubscribe('del-client', self.del_client)

    def add_client(self, name, websocket):
    self.clients[name] = websocket

    def get_client(self, name):
    return self.clients[name]

    def del_client(self, name):
    del self.clients[name]

    class ChatWebSocketHandler(WebSocket):
    def opened(self):
    cherrypy.engine.publish('add-client', self.username, self)

    def received_message(self, m):
    text = m.data
    if text.find("@") == -1:
    # echo to all
    cherrypy.engine.publish('websocket-broadcast', m)
    else:
    # or echo to a single user
    left, message = text.rsplit(':', 1)
    print left
    from_username, to_username = left.split('@')
    print repr(from_username), repr(to_username), repr(self.username)
    client = cherrypy.engine.publish('get-client', to_username.strip()).pop()
    print client
    client.send("@@%s: %s" % (from_username.strip()[:-1], message.strip()))

    def closed(self, code, reason="A client left the room without a proper explanation."):
    cherrypy.engine.publish('del-client', self.username)
    cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))

    class Root(object):
    def __init__(self, host, port, ssl=False):
    self.host = host
    self.port = port
    self.scheme = 'wss' if ssl else 'ws'

    @cherrypy.expose
    def index(self):
    return """<html>
    <head>
    <script type='application/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'></script>
    <script type='application/javascript'>
    $(document).ready(function() {

    websocket = '%(scheme)s://%(host)s:%(port)s/ws?username=%(username)s';
    if (window.WebSocket) {
    ws = new WebSocket(websocket, ['mytest']);
    }
    else if (window.MozWebSocket) {
    ws = MozWebSocket(websocket);
    }
    else {
    console.log('WebSocket Not Supported');
    return;
    }

    window.onbeforeunload = function(e) {
    $('#chat').val($('#chat').val() + 'Bye bye...\\n');
    ws.close(1000, '%(username)s left the room');

    if(!e) e = window.event;
    e.stopPropagation();
    e.preventDefault();
    };
    ws.onmessage = function (evt) {
    $('#chat').val($('#chat').val() + evt.data + '\\n');
    };
    ws.onopen = function() {
    ws.send("%(username)s entered the room");
    };
    ws.onclose = function(evt) {
    $('#chat').val($('#chat').val() + 'Connection closed by server: ' + evt.code + ' \"' + evt.reason + '\"\\n');
    };

    $('#send').click(function() {
    console.log($('#message').val());
    ws.send('%(username)s: ' + $('#message').val());
    $('#message').val("");
    return false;
    });
    });
    </script>
    </head>
    <body>
    <form action='#' id='chatform' method='get'>
    <textarea id='chat' cols='35' rows='10'></textarea>
    <br />
    <label for='message'>%(username)s: </label><input type='text' id='message' />
    <input id='send' type='submit' value='Send' />
    </form>
    </body>
    </html>
    """ % {'username': "User%d" % random.randint(0, 100), 'host': self.host,
    'port': self.port, 'scheme': self.scheme}

    @cherrypy.expose
    def ws(self, username):
    # let's track the username we chose
    cherrypy.request.ws_handler.username = username
    cherrypy.log("Handler created: %s" % repr(cherrypy.request.ws_handler))

    if __name__ == '__main__':
    import logging
    from ws4py import configure_logger
    configure_logger(level=logging.DEBUG)

    parser = argparse.ArgumentParser(description='Echo CherryPy Server')
    parser.add_argument('--host', default='127.0.0.1')
    parser.add_argument('-p', '--port', default=9000, type=int)
    parser.add_argument('--ssl', action='store_true')
    args = parser.parse_args()

    cherrypy.config.update({'server.socket_host': args.host,
    'server.socket_port': args.port,
    'tools.staticdir.root': os.path.abspath(os.path.join(os.path.dirname(__file__), 'static'))})

    if args.ssl:
    cherrypy.config.update({'server.ssl_certificate': './server.crt',
    'server.ssl_private_key': './server.key'})

    ChatPlugin(cherrypy.engine).subscribe()
    cherrypy.tools.websocket = WebSocketTool()

    cherrypy.quickstart(Root(args.host, args.port, args.ssl), '', config={
    '/ws': {
    'tools.websocket.on': True,
    'tools.websocket.handler_cls': ChatWebSocketHandler,
    'tools.websocket.protocols': ['toto', 'mytest', 'hithere']
    },
    '/js': {
    'tools.staticdir.on': True,
    'tools.staticdir.dir': 'js'
    }
    }
    )