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

Python游戏服务器中socket.sendto()调用无限挂起问题排查求助

UDP sendto() hangs indefinitely in game server-to-client communication

Problem Description

I'm setting up a server for my game, but the server is behaving abnormally at the final stage of sending data to the client. The issue seems to stem from this line of code:

sock.sendto(json.dumps({player_identifier: message}), self.udp_addr)

The call hangs indefinitely—my console prints "sending" but never "sent", and the client never prints "data received".

Additional context:

  • The client's socket is bound to 0.0.0.0:1235, and the server is sending to the client's IP (127.0.0.1) on port 1235.
  • I've verified the message is intact when entering the send_udp function, and the client's run function executes normally.
  • This feature was working previously, and I can't find clear troubleshooting info.

Server code snippet:

def send_udp(self, player_identifier, message):
    """ Send udp packet to player (game logic interaction) """
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    print("sending", flush = True)
    sock.sendto(json.dumps({player_identifier: message}), self.udp_addr)
    print("sent", flush = True)

Client code snippet:

class Client:
    def __init__(self, server_host, server_port_tcp=1234, server_port_udp=1234, client_port_udp=1235):
        """ Create a game server client """
        self.client_udp = ("0.0.0.0", client_port_udp)
        self.lock = threading.Lock()
        self.server_listener = SocketThread(self.client_udp, self, self.lock)
        self.server_listener.start()
        self.server_udp = (server_host, server_port_udp)
        self.server_tcp = (server_host, server_port_tcp)
        self.register()

class SocketThread(threading.Thread):
    def __init__(self, addr, client, lock):
        """ Client udp connection """
        threading.Thread.__init__(self)
        self.client = client
        self.lock = lock
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.bind(addr)

    def run(self):
        """ Get responses from server """
        while True:
            data, addr = self.sock.recvfrom(1024)
            print("data received")
            self.lock.acquire()
            try:
                self.client.server_message.append(data)
            finally:
                self.lock.release()

Solution & Troubleshooting Steps

Let's break down the most likely causes and fixes for your hanging sendto() call:

1. You’re passing a string instead of bytes to sendto() (Python 3 critical issue)

In Python 3, UDP sockets require bytes-like objects for sending data, but json.dumps() returns a string. If you’re running Python 3, this should throw a TypeError, but if the code is wrapped in an uncaught exception handler (or running in a thread where exceptions aren’t printed), it might appear as a hang instead.

Fix this by encoding the JSON string to bytes:

sock.sendto(json.dumps({player_identifier: message}).encode('utf-8'), self.udp_addr)

2. No timeout set on the server socket

UDP is typically connectionless and non-blocking, but if the OS send buffer fills up (unlikely in testing, but possible), sendto() will block indefinitely. Adding a timeout will force the call to fail fast and give you debug info:

def send_udp(self, player_identifier, message):
    """ Send udp packet to player (game logic interaction) """
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(5)  # Add 5-second timeout
    print("sending", flush=True)
    try:
        sock.sendto(json.dumps({player_identifier: message}).encode('utf-8'), self.udp_addr)
        print("sent", flush=True)
    except socket.timeout:
        print(f"Send timed out to {self.udp_addr}", flush=True)
    except Exception as e:
        print(f"Send failed: {str(e)}", flush=True)
    finally:
        sock.close()  # Clean up the socket

3. Verify self.udp_addr is correctly set

Double-check that self.udp_addr is indeed ("127.0.0.1", 1235) (matching your client’s bound port). Add a print statement before sendto() to confirm:

print(f"Sending to {self.udp_addr}", flush=True)

It’s easy to accidentally use the server’s UDP port (1234) here instead of the client’s 1235.

4. Confirm the client’s listener is running correctly

Even if you think the client’s run function is working, add a debug print at the start of the SocketThread.run() method to confirm the listener is active and bound to the right port:

def run(self):
    """ Get responses from server """
    print(f"UDP listener active on {self.sock.getsockname()}", flush=True)
    while True:
        data, addr = self.sock.recvfrom(1024)
        print("data received")
        # ... rest of your code

5. Check for player_identifier serialization issues

JSON requires object keys to be strings. If player_identifier is a custom object or non-serializable type, json.dumps() could hang or throw an exception. Test serialization in isolation to rule this out:

test_data = {player_identifier: message}
print(f"Test serialization: {json.dumps(test_data)}", flush=True)

If this line fails, you’ll need to convert player_identifier to a string (or another JSON-supported type) before serialization.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:08:12