wslink
wslink is a Python/JavaScript library designed for robust communication over WebSockets. It facilitates easy bi-directional communication, supporting Remote Procedure Calls (RPC) from client to server and publish/subscribe patterns from server to client, including binary attachments. Maintained by Kitware, it is actively developed with a frequent release cadence, often driven by semantic versioning.
Warnings
- gotcha The wslink server may not reliably detect all forms of client disconnections (e.g., abrupt network loss). This can lead to `ConnectionResetError` exceptions in server logs or the server continuing to manage stale connections indefinitely, potentially impacting stability and resource usage.
- gotcha Protocol compatibility between the Python server and the JavaScript/C++ client is crucial. Mismatched `wslink` library versions or incompatible RPC method signatures between client and server can lead to communication failures or unexpected behavior.
- gotcha This PyPI package (`wslink`) provides the Python server-side implementation. The corresponding client-side library for web browsers (JavaScript) is distributed separately via npm under the name `@kitware/wslink`. Attempting to use Python server modules directly in a browser environment or vice-versa will result in errors.
Install
-
pip install wslink
Imports
- Server
from wslink import Server
- WslinkHandler
from wslink.websocket import WslinkHandler
- WslinkServerProtocol
from wslink.protocols import WslinkServerProtocol
- run_wslink
from wslink.websocket import run_wslink
Quickstart
import asyncio
import logging
from wslink import Server
from wslink.websocket import WslinkHandler, run_wslink
from wslink.protocols import WslinkServerProtocol
# Configure logging for better visibility
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class MyProtocol(WslinkServerProtocol):
"""A simple protocol demonstrating RPC."""
def initialize(self):
# Register this protocol for RPC calls
self.registerVtkWebProtocol(self)
logger.info("MyProtocol initialized.")
@Server.expose("my.hello")
def hello_world(self, name="World"):
"""An RPC method that returns a greeting."""
logger.info(f"RPC 'my.hello' called with name='{name}'.")
return f"Hello, {name} from wslink!"
@Server.expose("my.add")
def add_numbers(self, a, b):
"""An RPC method that adds two numbers."""
logger.info(f"RPC 'my.add' called with a={a}, b={b}.")
return a + b
class MyWslinkHandler(WslinkHandler):
"""Custom wslink handler to use our protocol."""
protocol_class = MyProtocol
async def main():
# Set the host and port for the WebSocket server
host = "127.0.0.1"
port = 8080
logger.info(f"Starting wslink server on ws://{host}:{port}")
logger.info("Press Ctrl+C to stop the server.")
# Run the wslink server
await run_wslink(
port=port,
host=host,
ws=MyWslinkHandler,
# Optionally, set a secret for client authentication:
# secret=os.environ.get('WSLINK_SECRET', 'your_default_secret')
)
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
logger.info("Server stopped by user (KeyboardInterrupt).")
except Exception as e:
logger.error(f"An unexpected error occurred: {e}")