4. UDP广播与接收

任务目标

实现一个UDP广播发送端和一个接收端:发送端向子网广播地址发送消息,同一网络中的多个接收端进程都能收到该消息。通过本案例掌握UDP广播的地址设置、套接字选项配置及多客户端接收验证方法。

实现原理与关键点

UDP广播使用受限广播地址 255.255.255.255 或子网定向广播地址(如 192.168.1.255)。发送端无需特殊配置,接收端必须设置 SO_REUSEADDR 套接字选项,否则多个接收端绑定同一端口会冲突。广播消息默认被路由器隔离,仅在当前局域网内传播。

完整代码

# udp_broadcast.py
import socket
import sys

def broadcast_sender(message="Hello Broadcast", port=8888):
    """发送UDP广播消息"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 允许广播
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    # 使用受限广播地址,发送到所有子网
    sock.sendto(message.encode(), ('255.255.255.255', port))
    sock.close()
    print(f"[发送端] 已广播: {message}")

def broadcast_receiver(port=8888):
    """接收UDP广播消息(可多实例同时运行)"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 关键:允许多个接收端绑定同一端口
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('', port))
    print(f"[接收端] 监听端口 {port},等待广播...")
    while True:
        data, addr = sock.recvfrom(1024)
        print(f"[接收端] 收到来自 {addr} 的消息: {data.decode()}")

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("用法:")
        print("  发送: python udp_broadcast.py send [消息内容]")
        print("  接收: python udp_broadcast.py receive")
        sys.exit(1)
    
    mode = sys.argv[1].lower()
    if mode == 'send':
        msg = sys.argv[2] if len(sys.argv) > 2 else "Hello Broadcast"
        broadcast_sender(msg)
    elif mode == 'receive':
        broadcast_receiver()
    else:
        print("未知模式,使用 send 或 receive")

运行与验证

环境要求:Python 3.6+,无需第三方库。所有测试设备需连接同一局域网(同一Wi-Fi或交换机)。

验证步骤:

  1. 打开两个或多个终端,均进入代码所在目录,分别执行接收命令:
python udp_broadcast.py receive

每个终端都会显示“监听端口 8888,等待广播...”。

  1. 另开一个终端,执行发送命令:
python udp_broadcast.py send "测试广播消息"

通过条件:所有正在运行的接收端终端都同时打印出 [接收端] 收到来自 ('发送端IP', 临时端口) 的消息: 测试广播消息,且发送端显示发送成功。若多个接收端均收到同一条消息,则验证通过。

常见问题

  • 接收端收不到消息:检查防火墙是否拦截UDP端口8888;确认发送端与接收端在同一网段(可用 ipconfig/ifconfig 查看IP);部分云服务器或虚拟网络环境不支持广播,需改用真实局域网测试。
  • 第二个接收端启动报错“Address already in use”:确认代码中已设置 SO_REUSEADDR;Windows系统下该选项对UDP多绑定生效,Linux/macOS同样支持。
  • 发送端报错“Permission denied”:某些系统禁止向 255.255.255.255 发送,可改用子网定向广播地址(如 192.168.1.255,需根据实际子网修改)。