You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

面向Python新手的多人卡牌游戏:多Socket连接整合为JSON消息的最简实现方案咨询

Simplest Multiplayer Card Game Server/Client for Python Newbies

Hey there! Since your friend is new to Python, let's go with the most straightforward, easy-to-understand approach—threading + socket + queue + JSON. This setup keeps logic clear, avoids complex abstractions, and maps directly to the architecture you described.

Core Architecture Breakdown

First, let's align with your requirements:

  • Multiple clients connect to a central server
  • JSON for message passing
  • Input queue: store incoming messages (with client ID) for the game engine
  • Output queue: store game engine results to send back to clients
  • Thread separation: one thread per client (handling send/receive), one thread for the game engine (processing messages)

Step-by-Step Implementation

1. Server Code (The Heart of It)

This code uses Python's built-in modules—no extra dependencies, which is perfect for newbies to follow along.

import socket
import threading
import queue
import json
from uuid import uuid4

# Thread-safe queues for input/output messages
input_queue = queue.Queue()
output_queue = queue.Queue()
# Track connected clients (client ID -> socket object)
clients = {}

def handle_client(client_socket, client_id):
    """Handle incoming messages from a single client"""
    while True:
        try:
            # Receive message (adjust buffer size as needed)
            raw_data = client_socket.recv(1024)
            if not raw_data:
                # Client disconnected
                del clients[client_id]
                client_socket.close()
                print(f"Client {client_id} disconnected")
                break
            
            # Parse JSON message
            message = json.loads(raw_data.decode("utf-8"))
            # Add to input queue with client ID
            input_queue.put((client_id, message))
            print(f"Received from {client_id}: {message}")
        except Exception as e:
            print(f"Error handling client {client_id}: {e}")
            del clients[client_id]
            client_socket.close()
            break

def game_engine():
    """Process messages from input queue and send results to output queue"""
    while True:
        # Wait for a message to process
        client_id, message = input_queue.get()
        
        # Example game logic (replace with your card game rules)
        if message["type"] == "play_card":
            response = {
                "type": "card_played",
                "player": client_id,
                "card": message["card"],
                "status": "success"
            }
        elif message["type"] == "request_state":
            response = {
                "type": "game_state",
                "players": list(clients.keys()),
                "current_turn": client_id  # Dummy logic for demo
            }
        else:
            response = {"type": "error", "message": "Unknown message type"}
        
        # Send response to output queue
        output_queue.put((client_id, response))
        # Mark the input task as done
        input_queue.task_done()

def send_output():
    """Send messages from output queue to respective clients"""
    while True:
        client_id, response = output_queue.get()
        if client_id in clients:
            try:
                # Serialize response to JSON and send
                raw_response = json.dumps(response).encode("utf-8")
                clients[client_id].send(raw_response)
                print(f"Sent to {client_id}: {response}")
            except Exception as e:
                print(f"Error sending to {client_id}: {e}")
        output_queue.task_done()

def start_server(host="localhost", port=5555):
    """Start the game server"""
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((host, port))
    server_socket.listen(5)
    print(f"Server started on {host}:{port}")

    # Start game engine and output sender threads (daemon=True means they close with main thread)
    threading.Thread(target=game_engine, daemon=True).start()
    threading.Thread(target=send_output, daemon=True).start()

    while True:
        # Accept new client connections
        client_socket, addr = server_socket.accept()
        client_id = str(uuid4())[:8]  # Short unique ID for easy reference
        clients[client_id] = client_socket
        print(f"New client connected: {addr} | ID: {client_id}")
        
        # Start a thread to handle this client
        threading.Thread(target=handle_client, args=(client_socket, client_id), daemon=True).start()

if __name__ == "__main__":
    start_server()

2. Client Code (Simple for Testing)

This client is basic so your friend can quickly test connections and message sending without getting overwhelmed:

import socket
import json
import threading

def receive_messages(client_socket):
    """Thread to listen for server responses in the background"""
    while True:
        try:
            raw_data = client_socket.recv(1024)
            if not raw_data:
                print("Disconnected from server")
                break
            message = json.loads(raw_data.decode("utf-8"))
            print(f"\nServer response: {message}")
        except Exception as e:
            print(f"Error receiving message: {e}")
            break

def start_client(host="localhost", port=5555):
    """Start the game client"""
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((host, port))
    print("Connected to server!")

    # Start thread to listen for server messages
    threading.Thread(target=receive_messages, args=(client_socket,), daemon=True).start()

    # Send messages to server via user input
    while True:
        message_type = input("\nEnter message type (play_card/request_state/quit): ").strip()
        if message_type == "quit":
            client_socket.close()
            break
        elif message_type == "play_card":
            card = input("Enter card to play: ").strip()
            message = {"type": "play_card", "card": card}
        elif message_type == "request_state":
            message = {"type": "request_state"}
        else:
            print("Unknown message type")
            continue
        
        # Serialize and send the JSON message
        raw_message = json.dumps(message).encode("utf-8")
        client_socket.send(raw_message)

if __name__ == "__main__":
    start_client()

Why This Works for Newbies

  • Threading is intuitive: Each client gets its own thread, so your friend can trace exactly how one client's messages are handled without getting confused by event loops (like in asyncio).
  • Built-in modules: No need to install extra packages—everything uses Python's standard library, which means less setup and more focus on game logic.
  • Clear queue separation: The input/output queues act as a simple "buffer" between clients and the game engine, making it easy to see how data flows through the system.
  • JSON is straightforward: Serializing/deserializing messages with json is much simpler than custom protocols, and your friend can inspect the messages easily with print statements.

Alternatives to Consider

  • socketserver.ThreadingTCPServer: This is a higher-level wrapper around socket and threading—it handles client thread creation for you. It's slightly cleaner but hides some underlying logic, which might be less helpful for a newbie trying to learn the basics.
  • asyncio: Great for high-concurrency scenarios (like hundreds of clients), but the event loop model can be confusing for someone new to Python. It adds unnecessary complexity for a small-scale card game.

Key Tips for Your Friend

  • Start with the example logic and gradually replace it with actual card game rules.
  • Add print statements everywhere to trace message flow—this helps debug and understand how the system works.
  • Keep message types simple (e.g., play_card, end_turn, game_over) to avoid overcomplicating the JSON structure.

内容的提问来源于stack exchange,提问作者JJTech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 14:27:45