杰瑞科技汇

Python socket文档核心要点有哪些?

Of course! Here is a comprehensive guide to Python's socket module, structured from the basics to more advanced concepts, complete with examples and explanations.

Python socket文档核心要点有哪些?-图1
(图片来源网络,侵删)

Python socket Module: The Complete Guide

The socket module in Python provides access to the BSD socket interface. It's the fundamental way of performing low-level network operations in Python. You can use it to create both clients and servers for various types of network communication.

What is a Socket?

Think of a socket as an endpoint for sending or receiving data across a computer network. To build a connection, you need two sockets: one on the client side and one on the server side.

  • IP Address: The address of the machine on the network (e.g., 168.1.10 or 0.0.1 for localhost).
  • Port Number: A number that identifies a specific application or service on that machine (e.g., 80 for HTTP, 443 for HTTPS). Ports range from 0 to 65535.

A socket is uniquely identified by the combination of an IP address and a port number.


Key Concepts

  1. Server Socket: A socket that listens for incoming connections from clients. It's like a receptionist at a hotel, waiting for guests.
  2. Client Socket: A socket that initiates a connection to a server. It's like a guest calling the hotel to request a room.
  3. Connection-Oriented vs. Connectionless:
    • TCP (Transmission Control Protocol): Connection-oriented. It establishes a reliable, ordered, and error-checked connection before data is sent. Like making a phone call. This is the most common type of socket.
    • UDP (User Datagram Protocol): Connectionless. It sends datagrams (packets) without establishing a connection first. It's faster but less reliable, as packets can be lost or arrive out of order. Like sending a postcard.

The Basic Server-Client Workflow (TCP)

This is the classic pattern for most network applications.

Python socket文档核心要点有哪些?-图2
(图片来源网络,侵删)

Server Steps:

  1. socket(): Create a socket object.
  2. bind(): Associate the socket with a specific network interface and port.
  3. listen(): Put the socket into "listening" mode, ready to accept connections.
  4. accept(): Block and wait for an incoming connection. When a client connects, it returns a new socket object to communicate with that client, and the client's address.
  5. recv() / send(): Use the new socket object to receive data from and send data to the client.
  6. close(): Close the sockets.

Client Steps:

  1. socket(): Create a socket object.
  2. connect(): Attempt to connect the socket to the server's address and port.
  3. send() / recv(): Use the socket to send data to and receive data from the server.
  4. close(): Close the socket.

Code Examples

Let's build a simple "Echo Server" and a corresponding client. The server will receive a message from the client and send it back.

The Server (server.py)

This server will listen on localhost (which means "this same machine") on port 65432.

# server.py
import socket
# Use 'with' statements to ensure sockets are closed automatically
# AF_INET is the address family for IPv4
# SOCK_STREAM is the socket type for TCP
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # Bind the socket to an address and port
    # '' means listen on all available interfaces on this host
    # 65432 is the port number (choose one > 1024 to avoid needing root)
    s.bind(('', 65432))
    # Enable the server to accept connections
    # 5 is the number of unaccepted connections that the system will allow
    # before refusing new connections
    s.listen()
    print("Server is listening on port 65432...")
    # accept() blocks execution and waits for an incoming connection.
    # When a client connects, it returns a new socket object (conn)
    # and a tuple representing the address of the client (addr)
    conn, addr = s.accept()
    # Use another 'with' block for the connection socket
    with conn:
        print(f"Connected by {addr}")
        while True:
            # Receive data from the client (up to 1024 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')}")
            # Echo the data back to the client
            conn.sendall(data)
        print("Client disconnected.")

The Client (client.py)

This client will connect to the server running on localhost at port 65432.

# client.py
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:
    # Connect to the server
    s.connect((HOST, PORT))
    # The message to send to the server (must be encoded to bytes)
    message = b"Hello, server! This is a test message."
    s.sendall(message)
    print(f"Sent: {message.decode('utf-8')}")
    # Wait to receive the echoed data from the server
    data = s.recv(1024)
print(f"Received: {data.decode('utf-8')}")

How to Run It:

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

    You will see: Server is listening on port 65432...

    Python socket文档核心要点有哪些?-图3
    (图片来源网络,侵删)
  4. In the second terminal, run the client:
    python client.py

    You will see:

    Sent: Hello, server! This is a test message.
    Received: Hello, server! This is a test message.
  5. Back in the server's terminal, you will see:
    Connected by ('127.0.0.1', 54321)  # Port number will vary
    Received from client: Hello, server! This is a test message.
    Client disconnected.

Important Methods and Attributes

Method/Attribute Description
socket(family, type) Constructor. Creates a socket object.
family: socket.AF_INET (IPv4), socket.AF_INET6 (IPv6)
type: socket.SOCK_STREAM (TCP), socket.SOCK_DGRAM (UDP)
s.bind(address) Binds the socket to address. For TCP/IPv4, address is a tuple (host, port).
s.listen(backlog) Enables the server to accept connections. backlog is the maximum number of queued connections.
s.accept() (Server) Accepts a connection. Returns (conn, addr) where conn is a new socket for the connection and addr is the client's address.
s.connect(address) (Client) Connects to a remote socket at address.
s.sendall(data) Sends all data to the connected socket. It continues to send data until all of it has been sent.
s.send(data) Sends data to the socket. May not send all of the data if the network is busy. Returns the number of bytes sent.
s.recv(bufsize) Receives up to bufsize bytes of data from the socket. Returns a bytes object. Returns an empty bytes object if the connection is closed.
s.close() Marks the socket as closed. All future operations on the socket object will fail.
s.settimeout(seconds) Sets a timeout on blocking socket operations. Raises a socket.timeout exception if the operation is not completed within the specified time.

Handling Errors and Exceptions

Network operations can fail for many reasons (connection refused, network down, etc.). It's crucial to handle these exceptions.

import socket
try:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect(('127.0.0.1', 65432))
        s.sendall(b"Hello, world")
        data = s.recv(1024)
except ConnectionRefusedError:
    print("Error: Connection refused. Is the server running?")
except socket.timeout:
    print("Error: The connection timed out.")
except socket.error as e:
    print(f"A socket error occurred: {e}")
else:
    print(f"Received: {data.decode('utf-8')}")

Advanced: Making the Server Handle Multiple Clients

The accept() call is blocking, meaning the server stops and waits for a client. To handle multiple clients simultaneously, you need a more advanced approach.

Here are two common methods:

  1. Threading: The main server thread accepts a connection and then starts a new thread to handle that client, allowing the main thread to go back to accept() immediately.
  2. select module: A more efficient, single-threaded approach that can monitor multiple sockets for activity, but is more complex to implement.

Here's a simple threaded server example.

Threaded Server (threaded_server.py)

# threaded_server.py
import socket
import threading
def handle_client(conn, addr):
    """Function to handle a single client connection."""
    print(f"[NEW CONNECTION] {addr} connected.")
    try:
        with conn:
            while True:
                data = conn.recv(1024)
                if not data:
                    break # Connection closed by client
                print(f"[{addr}] Received: {data.decode('utf-8')}")
                conn.sendall(data) # Echo back
    except ConnectionResetError:
        print(f"[{addr}] Connection reset by peer.")
    finally:
        print(f"[{addr}] Disconnected.")
def start_server():
    """Main function to start the server."""
    SERVER = "127.0.0.1"
    PORT = 65432
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((SERVER, PORT))
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}:{PORT}")
    try:
        while True:
            conn, addr = server.accept()
            # Create a new thread for each new client
            thread = threading.Thread(target=handle_client, args=(conn, addr))
            thread.start()
            print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
    except KeyboardInterrupt:
        print("\n[SHUTTING DOWN] Server is shutting down.")
    finally:
        server.close()
if __name__ == "__main__":
    start_server()

This server can now handle multiple clients concurrently without getting stuck waiting for one to finish.


Official Documentation

For the most detailed and up-to-date information, always refer to the official Python documentation:

This guide covers the core concepts and patterns you'll need to get started with network programming in Python using the socket module.

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