Python websocket client example

Getting Started

The quickest way to get started with this library is to use the _wsdump.py script. For an easy example, run the following:

python _wsdump.py ws://echo.websocket.events/ -t "hello world" 

The above command will provide you with an interactive terminal to communicate with the echo.websocket.events server. This server will echo back any message you send it.

The wsdump.py script has many additional options too, so it’s a great way to try using this library without writing any custom code. The output of python wsdump.py -h is seen below, showing the additional options available.

python wsdump.py -h usage: wsdump.py [-h] [-p PROXY] [-v [VERBOSE]] [-n] [-r] [-s [SUBPROTOCOLS [SUBPROTOCOLS . ]]] [-o ORIGIN] [--eof-wait EOF_WAIT] [-t TEXT] [--timings] [--headers HEADERS] ws_url WebSocket Simple Dump Tool positional arguments: ws_url websocket url. ex. ws://echo.websocket.events/ optional arguments: -h, --help show this help message and exit -p PROXY, --proxy PROXY proxy url. ex. http://127.0.0.1:8080 -v [VERBOSE], --verbose [VERBOSE] set verbose mode. If set to 1, show opcode. If set to 2, enable to trace websocket module -n, --nocert Ignore invalid SSL cert -r, --raw raw output -s [SUBPROTOCOLS [SUBPROTOCOLS . ]], --subprotocols [SUBPROTOCOLS [SUBPROTOCOLS . ]] Set subprotocols -o ORIGIN, --origin ORIGIN Set origin --eof-wait EOF_WAIT wait time(second) after 'EOF' received. -t TEXT, --text TEXT Send initial text --timings Print timings in seconds --headers HEADERS Set custom headers. Use ',' as separator 

© Copyright 2023. Revision bd506ad2 .

Читайте также:  Диапазон ввода чисел питон

Источник

Quick start#

Here’s a WebSocket server. It receives a name from the client, sends a greeting, and closes the connection.

 1#!/usr/bin/env python 2 3import asyncio 4import websockets 5 6async def hello(websocket): 7 name = await websocket.recv() 8 print(f" name>") 9 10 greeting = f"Hello name>!" 11 12 await websocket.send(greeting) 13 print(f">>> greeting>") 14 15async def main(): 16 async with websockets.serve(hello, "localhost", 8765): 17 await asyncio.Future() # run forever 18 19if __name__ == "__main__": 20 asyncio.run(main()) 

serve() executes the connection handler coroutine hello() once for each WebSocket connection. It closes the WebSocket connection when the handler returns. Here’s a corresponding WebSocket client. It sends a name to the server, receives a greeting, and closes the connection.

 1#!/usr/bin/env python 2 3import asyncio 4import websockets 5 6async def hello(): 7 uri = "ws://localhost:8765" 8 async with websockets.connect(uri) as websocket: 9 name = input("What's your name? ") 10 11 await websocket.send(name) 12 print(f">>> name>") 13 14 greeting = await websocket.recv() 15 print(f"<< greeting>") 16 17if __name__ == "__main__": 18 asyncio.run(hello()) 

Encrypt connections#

Secure WebSocket connections improve confidentiality and also reliability because they reduce the risk of interference by bad proxies. The wss protocol is to ws what https is to http . The connection is encrypted with TLS (Transport Layer Security). wss requires certificates like https .

TLS vs. SSL TLS is sometimes referred to as SSL (Secure Sockets Layer). SSL was an earlier encryption protocol; the name stuck.

Here’s how to adapt the server to encrypt connections. You must download localhost.pem and save it in the same directory as server_secure.py . See the documentation of the ssl module for details on configuring the TLS context securely.

 1#!/usr/bin/env python 2 3import asyncio 4import pathlib 5import ssl 6import websockets 7 8async def hello(websocket): 9 name = await websocket.recv() 10 print(f" name>") 11 12 greeting = f"Hello name>!" 13 14 await websocket.send(greeting) 15 print(f">>> greeting>") 16 17ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) 18localhost_pem = pathlib.Path(__file__).with_name("localhost.pem") 19ssl_context.load_cert_chain(localhost_pem) 20 21async def main(): 22 async with websockets.serve(hello, "localhost", 8765, ssl=ssl_context): 23 await asyncio.Future() # run forever 24 25if __name__ == "__main__": 26 asyncio.run(main()) 
 1#!/usr/bin/env python 2 3import asyncio 4import pathlib 5import ssl 6import websockets 7 8ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) 9localhost_pem = pathlib.Path(__file__).with_name("localhost.pem") 10ssl_context.load_verify_locations(localhost_pem) 11 12async def hello(): 13 uri = "wss://localhost:8765" 14 async with websockets.connect(uri, ssl=ssl_context) as websocket: 15 name = input("What's your name? ") 16 17 await websocket.send(name) 18 print(f">>> name>") 19 20 greeting = await websocket.recv() 21 print(f"<< greeting>") 22 23if __name__ == "__main__": 24 asyncio.run(hello()) 

In this example, the client needs a TLS context because the server uses a self-signed certificate. When connecting to a secure WebSocket server with a valid certificate — any certificate signed by a CA that your Python installation trusts — you can simply pass ssl=True to connect() .

Connect from a browser#

The WebSocket protocol was invented for the web — as the name says! Here’s how to connect to a WebSocket server from a browser. Run this script in a console:

 1#!/usr/bin/env python 2 3import asyncio 4import datetime 5import random 6import websockets 7 8async def show_time(websocket): 9 while True: 10 message = datetime.datetime.utcnow().isoformat() + "Z" 11 await websocket.send(message) 12 await asyncio.sleep(random.random() * 2 + 1) 13 14async def main(): 15 async with websockets.serve(show_time, "localhost", 5678): 16 await asyncio.Future() # run forever 17 18if __name__ == "__main__": 19 asyncio.run(main()) 
1 2html lang="en"> 3 head> 4 title>WebSocket demotitle> 5 head> 6 body> 7 script src="show_time.js">script> 8 body> 9html> 
 1window.addEventListener("DOMContentLoaded", () =>   2 const messages = document.createElement("ul"); 3 document.body.appendChild(messages); 4 5 const websocket = new WebSocket("ws://localhost:5678/"); 6 websocket.onmessage = ( data >) =>   7 const message = document.createElement("li"); 8 const content = document.createTextNode(data); 9 message.appendChild(content); 10 messages.appendChild(message); 11 >; 12>); 

Broadcast messages#

Let’s change the previous example to send the same timestamps to all browsers, instead of generating independent sequences for each client. Stop the previous script if it’s still running and run this script in a console:

 1#!/usr/bin/env python 2 3import asyncio 4import datetime 5import random 6import websockets 7 8CONNECTIONS = set() 9 10async def register(websocket): 11 CONNECTIONS.add(websocket) 12 try: 13 await websocket.wait_closed() 14 finally: 15 CONNECTIONS.remove(websocket) 16 17async def show_time(): 18 while True: 19 message = datetime.datetime.utcnow().isoformat() + "Z" 20 websockets.broadcast(CONNECTIONS, message) 21 await asyncio.sleep(random.random() * 2 + 1) 22 23async def main(): 24 async with websockets.serve(register, "localhost", 5678): 25 await show_time() 26 27if __name__ == "__main__": 28 asyncio.run(main()) 

Manage application state#

A WebSocket server can receive events from clients, process them to update the application state, and broadcast the updated state to all connected clients. Here’s an example where any client can increment or decrement a counter. The concurrency model of asyncio guarantees that updates are serialized. Run this script in a console:

 1#!/usr/bin/env python 2 3import asyncio 4import json 5import logging 6import websockets 7 8logging.basicConfig() 9 10USERS = set() 11 12VALUE = 0 13 14def users_event(): 15 return json.dumps("type": "users", "count": len(USERS)>) 16 17def value_event(): 18 return json.dumps("type": "value", "value": VALUE>) 19 20async def counter(websocket): 21 global USERS, VALUE 22 try: 23 # Register user 24 USERS.add(websocket) 25 websockets.broadcast(USERS, users_event()) 26 # Send current state to user 27 await websocket.send(value_event()) 28 # Manage state changes 29 async for message in websocket: 30 event = json.loads(message) 31 if event["action"] == "minus": 32 VALUE -= 1 33 websockets.broadcast(USERS, value_event()) 34 elif event["action"] == "plus": 35 VALUE += 1 36 websockets.broadcast(USERS, value_event()) 37 else: 38 logging.error("unsupported event: %s", event) 39 finally: 40 # Unregister user 41 USERS.remove(websocket) 42 websockets.broadcast(USERS, users_event()) 43 44async def main(): 45 async with websockets.serve(counter, "localhost", 6789): 46 await asyncio.Future() # run forever 47 48if __name__ == "__main__": 49 asyncio.run(main()) 
 1  2html lang="en"> 3 head> 4 title>WebSocket demotitle> 5 link href="counter.css" rel="stylesheet"> 6 head> 7 body> 8 div class="buttons"> 9 div class="minus button">-div> 10 div class="value">?div> 11 div class="plus button">+div> 12 div> 13 div class="state"> 14 span class="users">?span> online 15 div> 16 script src="counter.js">script> 17 body> 18html> 
 1body   2 font-family: "Courier New", sans-serif; 3 text-align: center; 4> 5.buttons   6 font-size: 4em; 7 display: flex; 8 justify-content: center; 9> 10.button, .value  11 line-height: 1; 12 padding: 2rem; 13 margin: 2rem; 14 border: medium solid; 15 min-height: 1em; 16 min-width: 1em; 17> 18.button  19 cursor: pointer; 20 user-select: none; 21> 22.minus  23 color: red; 24> 25.plus  26 color: green; 27> 28.value  29 min-width: 2em; 30> 31.state  32 font-size: 2em; 33> 
 1window.addEventListener("DOMContentLoaded", () =>   2 const websocket = new WebSocket("ws://localhost:6789/"); 3 4 document.querySelector(".minus").addEventListener("click", () =>   5 websocket.send(JSON.stringify( action: "minus" >)); 6 >); 7 8 document.querySelector(".plus").addEventListener("click", () =>   9 websocket.send(JSON.stringify( action: "plus" >)); 10 >); 11 12 websocket.onmessage = ( data >) =>  13 const event = JSON.parse(data); 14 switch (event.type)  15 case "value": 16 document.querySelector(".value").textContent = event.value; 17 break; 18 case "users": 19 const users = `$event.count> user$event.count == 1 ? "" : "s">`; 20 document.querySelector(".users").textContent = users; 21 break; 22 default: 23 console.error("unsupported event", event); 24 > 25 >; 26>); 

Источник

Оцените статью