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

Python下P2P聊天应用UDP Socket无法接收对等端数据求助

问题分析与解决方案

你的问题核心在于服务器地址交换逻辑错误,导致客户端拿到了错误的端口信息,后续绑定和发送目标端口全部出错,从而无法接收消息。以下是具体问题点和修正方案:

关键问题点

  • 服务器向客户端发送的地址格式错误:当前发送的是「对方IP、对方端口、自己的端口」,完全没必要传递客户端自己的端口,且后续客户端解析时把对方端口当成了自己的通信端口,导致绑定错误。
  • 客户端存在未定义变量:print语句中的sport是未定义的,应该替换为dport。
  • 客户端重复创建socket并绑定错误端口:监听和发送的socket都绑定到了错误的端口(对方的端口),而非自己实际用于P2P通信的端口。

修正后的代码

1. 服务器代码(修正地址交换逻辑)

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 44444))

while True:
    clients = []
    # 等待两个客户端连接
    while len(clients) < 2:
        data, address = sock.recvfrom(128)
        clients.append(address)
        sock.sendto(b'ready', address)

    c1_addr, c2_addr = clients
    # 向c1发送c2的完整地址,向c2发送c1的完整地址
    try:
        sock.sendto(f"{c2_addr[0]} {c2_addr[1]}".encode(), c1_addr)
        sock.sendto(f"{c1_addr[0]} {c1_addr[1]}".encode(), c2_addr)
    except Exception as e:
        print(str(e))

2. 客户端代码(修正地址解析与通信逻辑)

import socket
import threading

# 第一步:与服务器交互获取对等端地址
my_port = 40270
server_addr = ('X.X.X.X', 44444)

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
    sock.bind(('', my_port))
    sock.sendto(b'0', server_addr)
    
    # 等待服务器的ready响应
    while True:
        data = sock.recv(1024).decode()
        if data.strip() == 'ready':
            break
    
    # 接收对等端的IP和端口
    peer_info = sock.recv(1024).decode().split(' ')
    peer_ip = peer_info[0]
    peer_port = int(peer_info[1])
    print(f"\n对等端地址: {peer_ip}:{peer_port},本地通信端口: {my_port}")

# 第二步:启动监听线程接收对等端消息
def listen():
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('', my_port))
        while True:
            data, _ = s.recvfrom(1024)
            print(f"\rpeer: {data.decode()}\n> ", end='')

listener = threading.Thread(target=listen, daemon=True)
listener.start()

# 第三步:发送消息给对等端
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('', my_port))
    while True:
        msg = input('> ')
        s.sendto(msg.encode(), (peer_ip, peer_port))

修正说明

  1. 服务器现在直接传递对等端的完整IP和端口,不再发送客户端自身的端口,简化逻辑避免混淆。
  2. 客户端明确自己的通信端口(my_port),监听和发送socket都绑定到这个端口,确保能接收到对等端发送到该端口的消息。
  3. 修复了未定义变量sport的问题,打印信息更清晰。
  4. 监听线程中使用recvfrom获取发送方地址(虽然这里用不到,但更符合UDP的使用习惯)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:15:41