Create standalone WebSocket server using tornado (Python)

Zahid
Written by Zahid on
Create standalone WebSocket server using tornado (Python)

How to create a standalone WebSocket server using python and JavaScript.

Updating data on the web without refreshing the page is ideal for many applications. Here are few examples

  1. Real-time data graphs
  2. Election results
  3. Baseball scoreboard
  4. Chat app

Let’s dive in to see how this can be achieved with just few lines of code.

Prerequisite : tornado webserver. Install using following command in the cmd line

pip install tornado

OR

easy_install tornado

Step 1 : Create tornado server (server.py) that accepts the WebSocket connections from frontend, maintains connections and sends message to the frontend when required.


from tornado import httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web

clients = []
userid = 0
class WSHandler(tornado.websocket.WebSocketHandler):
    
    #Called when attempt is made for connection from client
    def open(self):
        obj = SessionManagement()
        obj.createsession(self)#storing web socket object for further communication with client
     
    #Called when client sends message  
    def on_message(self, message):
        print 'message received %s' % userid
 
    #Called when user refreshes or closes the page
    def on_close(self):
        obj = SessionManagement()
        obj.deletesession(self)#deleting web socket object
        print clients


class SessionManagement():
    #Create session and stores into array
    def createsession(self, obj):
        userid = obj.get_argument("userid")
        componentid = obj.get_argument("compid")
        clients.append({"wsobj":obj, "userid":userid, "compid":componentid})
        
    #Delete session from array when client refreshes the page or closes the page    
    def deletesession(self, obj):
        for temp in clients:
            if (obj==temp['wsobj']):
                clients.remove(temp)
        
            
class PushToUser(tornado.web.RequestHandler):
    def get(self):
        userid = self.get_argument('userid')
        compid = self.get_argument('compid')
        message = self.get_argument('message')
        for temp in clients:
            if (temp['userid'] == userid and temp['compid'] == compid):
                temp['wsobj'].write_message(message) 
                
class PushToAll(tornado.web.RequestHandler):
    def get(self):
        message=self.get_argument('message')
        for temp in clients:
            temp['wsobj'].write_message(message)
                 
application = tornado.web.Application([
    (r'/ws', WSHandler),
    (r'/push', PushToUser), #Ex. /push?userid=123&compid=123&message=hello
    (r'/pushtoall', PushToAll), #Ex. /pushtoall?message="hello"
])
 
if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

Now, run server.py to start the server using

python server.py

Step 2 : Below is a frontend example that interacts with the server that you just created in step 1.

        $(document).ready(function () {

            var ws;
            var host = '192.168.1.1'; //server IP
            var port = '8888'; //server port
            var uri = 'ws'; //websocket uri
            ws = new WebSocket("ws://" + host + ":" + port + uri); //create web socket object

            //Called when connection is established with server
            ws.onopen = function (evt) {
                alert("Connection open");
            };

            //Called when message is sent from server
            ws.onmessage = function (evt) {
                alert("message received: " + evt.data)
            };

            //Called when connection is closed from server
            ws.onclose = function (evt) {
                alert("Connection close");
            };
        });

Step 4: Sending message to client using REST

  • Push message to specific user

  • Push message to all users