杰瑞科技汇

Python socket server如何高效处理多客户端连接?

Of course! Here is a comprehensive guide to creating a Python socket server, starting with a simple, classic example and then building up to a more robust, multi-threaded version.

Python socket server如何高效处理多客户端连接?-图1
(图片来源网络,侵删)

What are Sockets?

Think of a socket as an endpoint for sending or receiving data across a computer network. It's like a phone jack in a wall. You plug a phone (your program) into it, and you can have a two-way conversation with another phone connected to the other end of the line.

In Python, the socket module provides access to the BSD socket interface. It's the fundamental building block for most network communication.


The Simplest Python Socket Server

This is the "Hello, World!" of socket programming. It will:

  1. Create a socket.
  2. Bind it to a specific address and port on the server.
  3. Listen for incoming connections.
  4. Accept a connection.
  5. Receive data from the client.
  6. Send a response back.
  7. Close the connection.

The Server Code (server_simple.py)

# Import the socket module
import socket
# Define the host and port
# '0.0.0.0' means the server will listen on all available network interfaces
HOST = '0.0.0.0'
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)
# Create a socket object
# socket.AF_INET: Use IPv4
# socket.SOCK_STREAM: Use TCP (reliable, connection-oriented)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # Bind the socket to the address and port
    s.bind((HOST, PORT))
    # Listen for incoming connections
    # The '1' is the backlog, the number of unaccepted connections that the system
    # will allow before refusing new connections.
    s.listen()
    print(f"Server listening on {HOST}:{PORT}")
    # Accept a connection
    # .accept() returns a new socket object to communicate with the client,
    # and the address of the client.
    # This is a blocking call, meaning the program will pause here until a client connects.
    conn, addr = s.accept()
    # Use a 'with' statement to automatically close the connection when done
    with conn:
        print(f"Connected by {addr}")
        while True:
            # Receive data from the client
            # 1024 is the buffer size in bytes
            data = conn.recv(1024)
            # If recv() returns an empty object, the client has closed the connection
            if not data:
                break
            # Print the received data (it's in bytes, so we decode it to a string)
            print(f"Received from client: {data.decode('utf-8')}")
            # Send a response back to the client
            # We must encode the string to bytes before sending
            response = "Message received!"
            conn.sendall(response.encode('utf-8'))
print("Connection closed.")

The Client Code (client_simple.py)

To test the server, you need a client. You can run this from another terminal or even on another machine.

Python socket server如何高效处理多客户端连接?-图2
(图片来源网络,侵删)
import socket
HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 65432        # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    message_to_send = "Hello, Server!"
    s.sendall(message_to_send.encode('utf-8'))
    # Look for the response
    data = s.recv(1024)
print(f"Received from server: {data.decode('utf-8')}")

How to Run It:

  1. Save the two files as server_simple.py and client_simple.py.
  2. Open two terminal windows.
  3. In the first terminal, run the server:
    python server_simple.py

    You will see: Server listening on 0.0.0.0:65432

  4. In the second terminal, run the client:
    python client_simple.py

Expected Output:

  • Server Terminal:

    Server listening on 0.0.0.0:65432
    Connected by ('127.0.0.1', 54321)  # The port number will vary
    Received from client: Hello, Server!
    Connection closed.
  • Client Terminal:

    Python socket server如何高效处理多客户端连接?-图3
    (图片来源网络,侵删)
    Received from server: Message received!

A More Robust, Multi-Threaded Server

The simple server has a major limitation: it can only handle one client at a time. After it accepts a connection, it enters a loop and doesn't listen for any other clients until the first one disconnects.

A multi-threaded server solves this by creating a new thread for each client connection. This allows the main server thread to keep listening for new connections while other threads handle the communication with existing clients.

The Multi-Threaded Server Code (server_threaded.py)

import socket
import threading
# The function that will be run in each thread to handle a client
def handle_client(conn, addr):
    """Handles a single client connection."""
    print(f"[NEW CONNECTION] {addr} connected.")
    try:
        with conn:
            while True:
                data = conn.recv(1024)
                if not data:
                    # If no data is received, the client has closed the connection
                    break
                print(f"[{addr}] Received: {data.decode('utf-8')}")
                # Echo the message back to the client
                response = f"Server got your message: {data.decode('utf-8')}"
                conn.sendall(response.encode('utf-8'))
    except ConnectionResetError:
        print(f"[{addr}] Connection was forcibly closed by the client.")
    finally:
        print(f"[{addr}] Disconnected.")
def start_server(host, port):
    """Starts the server and listens for connections."""
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # This allows us to reuse the address if the server is restarted quickly
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    try:
        server.bind((host, port))
        server.listen()
        print(f"Server is listening on {host}:{port}")
        while True:
            # Accept a new connection
            conn, addr = server.accept()
            # Create a new thread to handle the client
            # target is the function to run
            # args are the arguments to pass to the function
            thread = threading.Thread(target=handle_client, args=(conn, addr))
            # Start the thread. The main loop will immediately continue to listen
            # for the next connection.
            thread.start()
            print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
    except KeyboardInterrupt:
        print("\nServer is shutting down...")
    finally:
        server.close()
        print("Server has shut down.")
if __name__ == "__main__":
    HOST = '0.0.0.0'
    PORT = 65432
    start_server(HOST, PORT)

How to Run It:

  1. Save the code as server_threaded.py.
  2. Run the server:
    python server_threaded.py
  3. Open multiple client terminals (or use the same client_simple.py script multiple times).
  4. Connect each client. You'll see the server's terminal print a new connection message for each one and show the active connection count.

Key Concepts Explained

Method/Concept Description
socket.socket(family, type) Creates a new socket object. AF_INET is for IPv4, SOCK_STREAM is for TCP.
socket.bind((host, port)) Assigns an address (IP and port) to the socket. The port must be unique on that machine.
socket.listen(backlog) Enables the server to accept connections. backlog is the number of connections that can be queued.
socket.accept() Blocking call. Waits for an incoming connection and returns a new socket object (conn) to communicate with that client, along with their address (addr).
conn.recv(buffer_size) Receives data from the client. It's also a blocking call. Returns data as bytes. Returns an empty bytes object if the client closes the connection.
conn.sendall(data) Sends all the data in the bytes object to the client. It continues to send until all data is sent or an error occurs.
conn.close() Closes the connection with the client. The with statement handles this automatically.
threading.Thread(...) Creates a new thread of execution. This is essential for building servers that can handle multiple clients concurrently.
分享:
扫描分享到社交APP
上一篇
下一篇