杰瑞科技汇

Python如何实现Websockets?

Of course! Here's a comprehensive guide to using WebSockets in Python, covering the fundamentals, popular libraries, and a complete practical example.

Python如何实现Websockets?-图1
(图片来源网络,侵删)

What are WebSockets?

Imagine a standard HTTP request-response like a phone call:

  • You (client) call the server.
  • You talk (send a request).
  • The server listens and then hangs up.
  • The server calls you back (sends a response).
  • You hang up.

This is inefficient for things that need constant, two-way communication like chat apps, live notifications, or real-time dashboards.

WebSockets are like a walkie-talkie:

  • You (client) and the server establish a single, long-lived connection.
  • Either party can "talk" (send a message) at any time without waiting for a response.
  • The connection stays open until it's explicitly closed.

This makes WebSockets perfect for:

Python如何实现Websockets?-图2
(图片来源网络,侵删)
  • Real-time chat applications
  • Live notifications
  • Multiplayer online games
  • Real-time data dashboards (stock prices, sensor data)
  • Collaborative editing tools (like Google Docs)

Key Python Libraries for WebSockets

You'll generally need two libraries:

  1. A Server Library: To create the WebSocket server that listens for connections.
  2. A Client Library: To create a client that connects to a WebSocket server.

Here are the most popular choices:

Library Server Client Description
websockets The de-facto standard library. Pure Python, powerful, and easy to use. Great for learning and most applications.
Socket.IO Built on top of WebSockets. Provides fallbacks (like long-polling), rooms, namespaces, and automatic reconnection. More feature-rich.
Django Channels Integrates WebSockets directly into the Django framework. The go-to choice if you're already using Django.
FastAPI Modern, fast web framework with built-in support for WebSockets via Starlette. Excellent for building APIs with real-time features.

For this guide, we'll focus on the websockets library as it's the most fundamental and widely used.


Step-by-Step Example: A Simple Chat App

We'll build a simple echo server and a client using the websockets library.

Python如何实现Websockets?-图3
(图片来源网络,侵删)

Step 1: Installation

First, you need to install the library. Open your terminal or command prompt and run:

pip install websockets

Step 2: The WebSocket Server

Create a file named server.py. This server will listen for incoming WebSocket connections. When a client connects, it will wait for a message, print it, and then send the same message back to the client (an "echo" server).

# server.py
import asyncio
import websockets
# This function will be called for each new client connection
async def handler(websocket, path):
    """
    Handle a WebSocket connection.
    `websocket`: The connection object for the client.
    `path`: The path the client connected to.
    """
    print(f"A new client connected from {websocket.remote_address}")
    try:
        # Keep listening for messages from the client indefinitely
        async for message in websocket:
            print(f"Received message: {message}")
            # Send the same message back to the client
            await websocket.send(f"Echo: {message}")
    except websockets.exceptions.ConnectionClosed as e:
        print(f"Connection closed: {e}")
    finally:
        print("Client disconnected.")
# Start the WebSocket server
async def main():
    # host="0.0.0.0" makes the server accessible from other machines on the network
    # port=8765 is the port to listen on
    async with websockets.serve(handler, "0.0.0.0", 8765):
        print("WebSocket server started on ws://0.0.0.0:8765")
        # Keep the server running forever
        await asyncio.Future()  # run forever
# Run the main function
if __name__ == "__main__":
    asyncio.run(main())

To run the server:

python server.py

You should see the output: WebSocket server started on ws://0.0.0.0:8765

Step 3: The WebSocket Client

Now, create a file named client.py. This client will connect to the server we just created, send a message, and then print the response it receives.

# client.py
import asyncio
import websockets
async def client():
    uri = "ws://localhost:8765"  # The server's URI
    try:
        # Connect to the WebSocket server
        async with websockets.connect(uri) as websocket:
            print("Connected to the server!")
            # Send a message to the server
            message = "Hello, Server!"
            await websocket.send(message)
            print(f"Sent: {message}")
            # Wait for a response from the server
            response = await websocket.recv()
            print(f"Received: {response}")
    except websockets.exceptions.ConnectionClosed:
        print("Connection to the server was closed.")
    except ConnectionRefusedError:
        print("Could not connect to the server. Is it running?")
    except Exception as e:
        print(f"An error occurred: {e}")
# Run the client
if __name__ == "__main__":
    asyncio.run(client())

To run the client: Open a new terminal window and run:

python client.py

Expected Output:

In the Server Terminal:

A new client connected from 127.0.0.1:54321
Received message: Hello, Server!
Client disconnected.

In the Client Terminal:

Connected to the server!
Sent: Hello, Server!
Received: Echo: Hello, Server!

Advanced Concepts: Broadcasting to Multiple Clients

A real chat app needs to send a message from one client to all other clients. This is called "broadcasting". The websockets library makes this easy with a set to keep track of all connected clients.

Step 1: Modify the Server for Broadcasting

Update your server.py to handle multiple clients and broadcast messages.

# server.py (Broadcasting Version)
import asyncio
import websockets
import json
# A set to keep track of all connected clients
connected_clients = set()
async def handler(websocket, path):
    """
    Handle a WebSocket connection, add the client to the set,
    and broadcast messages from this client to all others.
    """
    # Add the new client to our set
    connected_clients.add(websocket)
    client_address = websocket.remote_address
    print(f"Client connected: {client_address}. Total clients: {len(connected_clients)}")
    try:
        async for message in websocket:
            print(f"Received from {client_address}: {message}")
            # Broadcast the message to all other clients
            await broadcast(message, exclude=websocket)
    except websockets.exceptions.ConnectionClosed as e:
        print(f"Connection closed for {client_address}: {e}")
    finally:
        # Remove the client from the set when they disconnect
        connected_clients.remove(websocket)
        print(f"Client disconnected: {client_address}. Total clients: {len(connected_clients)}")
async def broadcast(message, exclude=None):
    """
    Send a message to all connected clients, except for the one specified.
    """
    # Create a list of tasks to send the message to each client
    tasks = [
        client.send(message)
        for client in connected_clients
        if client is not exclude  # Don't send back to the original sender
    ]
    # Wait for all the send operations to complete
    if tasks:
        await asyncio.gather(*tasks, return_exceptions=True)
async def main():
    async with websockets.serve(handler, "0.0.0.0", 8765):
        print("Broadcasting WebSocket server started on ws://0.0.0.0:8765")
        await asyncio.Future()  # run forever
if __name__ == "__main__":
    asyncio.run(main())

Step 2: Create a More Interactive Client

Now, let's create a client that can continuously send messages. This is more like a real chat application.

# client.py (Interactive Version)
import asyncio
import websockets
import json
async def client():
    uri = "ws://localhost:8765"
    username = input("Enter your username: ")
    try:
        async with websockets.connect(uri) as websocket:
            print(f"Connected to the server as {username}!")
            # Create a task to listen for messages from the server
            receive_task = asyncio.create_task(receive_messages(websocket))
            # Send a join message
            await websocket.send(json.dumps({"type": "join", "username": username}))
            # Main loop to send messages from the user
            while True:
                message = input("> ")
                if message.lower() == 'exit':
                    break
                await websocket.send(json.dumps({"type": "chat", "message": message}))
            # Cancel the receive task when we exit
            receive_task.cancel()
    except websockets.exceptions.ConnectionClosed:
        print("Connection to the server was closed.")
    except ConnectionRefusedError:
        print("Could not connect to the server. Is it running?")
    except Exception as e:
        print(f"An error occurred: {e}")
async def receive_messages(websocket):
    """A dedicated task to print incoming messages."""
    try:
        async for message in websocket:
            data = json.loads(message)
            if data.get("type") == "join":
                print(f"*** {data.get('username')} joined the chat. ***")
            elif data.get("type") == "chat":
                print(f"[{data.get('username')}] {data.get('message')}")
    except asyncio.CancelledError:
        pass # Task was cancelled, which is expected on exit.
    except Exception as e:
        print(f"Error receiving message: {e}")
if __name__ == "__main__":
    asyncio.run(client())

How to test this:

  1. Run the server.py (broadcasting version).
  2. Open two or three different terminal windows.
  3. In each window, run python client.py and enter a different username.
  4. Start typing messages in one client window. You will see the messages appear in all other client windows instantly!

This example demonstrates the core power of WebSockets: real-time, bidirectional communication between multiple clients.

分享:
扫描分享到社交APP
上一篇
下一篇