Websocket scheme: callback or coroutine

0xCryptoQuant
2 min readNov 23, 2023

--

Before formulating a trading strategy, it is typically necessary to retrieve data from the cex websocket interface. Therefore, adopting an excellent websocket data retrieval solution is essential. This article will compare two different implementations of websocket clients.

Difference between coroutine and callback

coroutine

In the context of websockets, coroutines can be utilized to efficiently handle asynchronous tasks. For instance, an asynchronous coroutine might be employed to manage incoming messages in a non-blocking manner. The following is a simple code example for setting up a server:

code example for setting up a server:

#!/usr/bin/env python
import asyncio
import websockets

# the websocket parameter is an instance of the WebSocketServerProtocol class,
# and it represents the communication channel between the server and
# a specific client connected to the WebSocket server
async def handler(websocket):
while True:
message = await websocket.recv()
print(message)
# Send the same message back to the client
await websocket.send(f"Server echoing: {message}")

# will be called each time a new client connects to the server
async def main():
# "" represents loopback interface that allows
# communication between processes on the same device.
async with websockets.serve(handler, "", 8001):
await asyncio.Future() # run forever

if __name__ == "__main__":
asyncio.run(main())

client-side code:

import asyncio
import websockets

async def connect_to_server():
uri = "ws://localhost:8001" # Change the URI to match your server address

async with websockets.connect(uri) as websocket:
while True:
message = input("Enter a message to send to the server (or 'exit' to quit): ")

if message.lower() == 'exit':
break

await websocket.send(message)

# Receive and print the echoed message from the server
response = await websocket.recv()
print(f"Received from server: {response}")

if __name__ == "__main__":
asyncio.run(connect_to_server())

callback

In the realm of websockets, callbacks may be employed to define functions that execute when specific events occur, such as receiving a message, establishing a connection, or encountering an error. Let’s now rewrite the client code using a callback scheme:

import websocket

def on_message(ws, message):
print(f"Received from server: {message}")

def connect_to_server():
uri = "ws://localhost:8001" # Change the URI to match your server address

ws = websocket.WebSocketApp(uri, on_message=on_message)

while True:
user_input = input("Enter a message to send to the server (or 'exit' to quit): ")

if user_input.lower() == 'exit':
break

ws.send(user_input)

ws.close()

if __name__ == "__main__":
connect_to_server()

Comparison

Callbacks are prevalent in older asynchronous code and may be utilized in systems heavily reliant on event-driven architectures. Coroutines, on the other hand, are the preferred approach in modern Python asynchronous programming, especially with the introduction of the async/await syntax.

I favor the coroutine scheme primarily because it provides a more elegant and readable solution for asynchronous programming, making it the preferred approach in modern Python development.

--

--

0xCryptoQuant

truth miner ⛏️ - diving into the depths of digital gold 🤿. twitter@0xCryptoQuant