Home »
Python
Basic concepts of WebSocket server in Python
Python WebSocket server: Here, we are going to learn about the basic concepts of WebSocket server in Python like what is WebSocket server, where and when to use it, python WebSocket libraries, etc.
Submitted by Sapna Deraje Radhakrishna, on September 20, 2019
What is a WebSocket server?
In simple words, a WebSocket server is an application listening on any TCP port server that follows a protocol call WS (or WSS).
Often, a reverse proxy such as an HTTP server is used to detect Websocket handshakes, process them, and send those clients to the WebSocket server. The WebSocket protocol was designed to work well with existing web infrastructure. As part of this design principle, the WebSocket connection starts as an HTTP connection, with full backward compatibility with the pre-WebSocket world. The protocol shift from HTTP to WebSocket is referred to as handshake.
The client sends an Upgrade header:
--- request header ---
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: localhost:4040
Origin: http://localhost:4040
Sec-WebSocket-Key: q0+vBfXgMvGGywjDaHZWiw==
Sec-WebSocket-Version: 13
If the server understands, the WebSocket protocol, it agrees to the protocol switch through the upgrade header.
-----------------------
--- response header ---
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: /YqMq5iNGOMjtELPGCZsnozMSlw=
Date: Sun, 15 Sep 2019 23:34:04 GMT
Server: Python/3.7 websockets/8.0.2
-----------------------
At this point, the HTTP connection breaks down and is replaced by a WebSocket connection over the underlying TCP/IP connection. The WebSocket, similar to HTTP, uses HTTP (80) and HTTPS (443) by default.
Where and When to use WebSockets?
- Real-time applications – when the UI needs to be updated without the client request for data. Here WebSockets are faster than using the traditional AJAX polling, which uses HTTP
- Gaming Applications
- Chat Applications
When not to use WebSockets?
Real-time updates are not required. The WebSockets, since keeps the connection alive until one of the components closes the connection. Instead, RESTful services are sufficient to get the data from the server.
Using python libraries to implement a WebSocket server
Python provides many libraries to implement the WebSocket server. Following are the few of many available in the market. These libraries can be easily installed through Pypi within the virtual environment or in Anaconda environment.
Example code for implementing the WebSocket server
1) Using WebSockets library (ws_server.py)
import asyncio
import websockets
import time
import json
async def say_hello(websocket, path):
while True:
await websocket.send("hello world")
time.sleep(10)
# the server starts up in localhost and port 4040
start_server = websockets.serve(say_hello,'localhost',4040)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
2) Using tornado library (tornado_ws_server.py)
'''
This module hosts a websocket server using tornado
libraries
'''
import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.websocket as ws
from tornado.options import define, options
import time
define('port', default=4041, help='port to listen on')
class web_socket_handler(ws.WebSocketHandler):
'''
This class handles the websocket channel
'''
@classmethod
def route_urls(cls):
return [(r'/',cls, {}),]
def simple_init(self):
self.last = time.time()
self.stop = False
def open(self):
'''
client opens a connection
'''
self.simple_init()
print("New client connected")
self.write_message("You are connected")
def on_message(self, message):
'''
Message received on the handler
'''
print("received message {}".format(message))
self.write_message("You said {}".format(message))
self.last = time.time()
def on_close(self):
'''
Channel is closed
'''
print("connection is closed")
def check_origin(self, origin):
return True
def initiate_server():
#create a tornado application and provide the urls
app = tornado.web.Application(web_socket_handler.route_urls())
#setup the server
server = tornado.httpserver.HTTPServer(app)
server.listen(options.port)
#start io/event loop
tornado.ioloop.IOLoop.instance().start()
if __name__ == '__main__':
initiate_server()
Setup the environment to implement a WebSocket server
- Create a virtual environment
-bash-4.2$ python3 -m venv venv
- Source (or activate) the virtual environment
-bash-4.2$ source venv/bin/activate
- Install the required library using pip
(venv) -bash-4.2$ pip3 install websockets
Collecting websockets
Downloading https://files.pythonhosted.org/packages/f0/4b/ad228451b1c071c5c52616b7d4298ebcfcac5ae8515ede959db19e4cd56d/websockets-8.0.2-cp36-cp36m-manylinux1_x86_64.whl (72kB)
100% |████████████████████████████████| 81kB 2.1MB/s
Installing collected packages: websockets
Successfully installed websockets-8.0.2
(venv) -bash-4.2$
(venv) -bash-4.2$ pip3 install tornado
Collecting tornado
Using cached https://files.pythonhosted.org/packages/30/78/2d2823598496127b21423baffaa186b668f73cd91887fcef78b6eade136b/tornado-6.0.3.tar.gz
Installing collected packages: tornado
Running setup.py install for tornado ... done
Successfully installed tornado-6.0.3
(venv) -bash-4.2$
Execute the sample websocket server
Python3 tornado_ws_server.py
Or
Python3 ws_server.py
Wireshark traces of the client server interaction
References: