[Python] how to fix a threading problem in python for a socket server code

Discussão em 'Python' iniciado por Stack, Novembro 28, 2024.

  1. Stack

    Stack Membro Participativo

    i'm trying to build a Trivia game in socket python but i'm facing a problem that when multiple clients try to submit their answers to the server the server most of the time doesn't accept all the answers of the clients which causes a scoring issue in the game here's the function that for handelling the clients answers and i believe is making the problem :

    def handle_client_answers(server_socket, question, correct_answer):
    """Handle answers for the current question."""
    start_time = time.time()
    first_correct_time = None

    def process_answer(data, addr):
    """Process a single client's answer."""
    nonlocal first_correct_time # Allow modification of the shared variable
    answer = data.decode().strip()
    with lock:
    if addr not in clients or clients[addr]["answered"]:
    return

    clients[addr]["answered"] = True

    server_socket.sendto(f"Answer Submitted: {answer}".encode(), addr)
    if answer.lower() == correct_answer.lower():
    if not first_correct_time:
    first_correct_time = time.time()
    clients[addr]["score"] += 10 # Full points for first correct answer
    else:
    time_diff = time.time() - first_correct_time
    score_multiplier = max(0.5, 1 - time_diff / 10) # Decrease score for slower answers
    clients[addr]["score"] += int(10 * score_multiplier)
    server_socket.sendto("Correct!".encode(), addr)
    print(f"Received answer from {clients[addr]['username']} ({addr}): {answer} - Correct!")
    else:
    server_socket.sendto("Wrong answer.".encode(), addr)
    print(f"Received answer from {clients[addr]['username']} ({addr}): {answer} - Incorrect!")


    while time.time() - start_time < 30:
    try:
    data, addr = server_socket.recvfrom(1024)
    # Start a thread to process this answer
    threading.Thread(target=process_answer, args=(data, addr), daemon=True).start()

    # Exit early if all clients have answered
    with lock:
    if all(client["answered"] for client in clients.values()):
    break
    except socket.timeout:
    continue
    time.sleep(2)



    i tried asking ChatGPT to solve the problem and it intreduced a solution using a queue:

    from queue import Queue

    answer_queue = Queue() # Queue to hold incoming answers

    def handle_client_answers(server_socket, question, correct_answer):
    """Handle answers for the current question."""
    start_time = time.time()
    first_correct_time = None

    def enqueue_answer(data, addr):
    """Add the answer to the processing queue."""
    answer_queue.put((data, addr))

    def process_answers():
    """Continuously process answers from the queue."""
    nonlocal first_correct_time
    while time.time() - start_time < 30 or not answer_queue.empty():
    try:
    data, addr = answer_queue.get(timeout=1) # Wait for answers from the queue
    process_answer(data, addr) # Process the answer
    except Exception as e:
    continue # Handle timeouts or empty queue gracefully

    def process_answer(data, addr):
    """Process a single client's answer."""
    nonlocal first_correct_time # Allow modification of the shared variable
    answer = data.decode().strip()
    with lock:
    if addr not in clients or clients[addr]["answered"]:
    return

    clients[addr]["answered"] = True

    server_socket.sendto(f"Answer Submitted: {answer}".encode(), addr)
    if answer.lower() == correct_answer.lower():
    if not first_correct_time:
    first_correct_time = time.time()
    clients[addr]["score"] += 10 # Full points for first correct answer
    else:
    time_diff = time.time() - first_correct_time
    score_multiplier = max(0.5, 1 - time_diff / 10) # Decrease score for slower answers
    clients[addr]["score"] += int(10 * score_multiplier)
    server_socket.sendto("Correct!".encode(), addr)
    print(f"Received answer from {clients[addr]['username']} ({addr}): {answer} - Correct!")
    else:
    server_socket.sendto("Wrong answer.".encode(), addr)
    print(f"Received answer from {clients[addr]['username']} ({addr}): {answer} - Incorrect!")

    # Start the worker thread to process answers from the queue
    threading.Thread(target=process_answers, daemon=True).start()

    # Collect answers during the question period
    while time.time() - start_time < 30:
    try:
    data, addr = server_socket.recvfrom(1024)
    enqueue_answer(data, addr) # Add the answer to the queue
    except socket.timeout:
    continue

    time.sleep(2)


    but the problem remained the same

    to access the full code please visit this github :https://github.com/moe-the-goat/1st-network-project

    Continue reading...

Compartilhe esta Página