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

ESP32可正常发送UDP数据包,但Win10端.NET程序无法接收

问题:ESP32 UDP广播无法被Win10 .NET程序接收(Python可正常接收)

我正在搭建ESP32的UDP广播握手功能,让ESP32在局域网特定端口广播数据包,供同网络Win10 PC上的.NET程序接收并完成握手。目前已通过Wireshark及PC上的Python脚本确认ESP32能正常广播和接收数据包,但.NET程序无法识别来自ESP32的数据包;不过该.NET程序可接收本地另一.NET测试程序的广播(含127.0.0.1与192.168.1.255)。经初步排查Windows防火墙无阻碍,求指点排查方向。

排查方向

  • 开启.NET程序的广播接收权限:Python socket默认支持广播接收,但.NET的UdpClient默认可能关闭了该功能。在初始化UdpClient后添加以下代码:
    udpClient.EnableBroadcast = true;
    
  • 修正ESP32的广播地址计算:当前手动将IP最后一段设为255的方式仅适用于子网掩码为255.255.255.0的场景,改用系统提供的正确广播地址:
    IPAddress broadcastIP = WiFi.broadcastIP();
    
  • 调整.NET的远程端点配置:代码中remoteEndPoint指定了固定端口12345,但ESP32发送广播的源端口并非固定为该值,修改为允许任意远程端口:
    IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
    
  • 指定.NET程序绑定的网卡:若PC存在多网卡(有线/无线),.NET可能绑定到了非目标局域网的网卡,尝试绑定到具体的局域网IP:
    UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("你的PC局域网IP"), port));
    
  • 统一数据包发送方式:ESP32改用字节数组直接发送,避免字符串转换可能的编码问题:
    const char* message = "Discovery request from ESP32";
    udp.beginPacket(broadcastIP, port);
    udp.write((const uint8_t*)message, strlen(message));
    udp.endPacket();
    
  • 检查Windows UDP监听状态:用命令行确认.NET程序是否正确监听目标端口:
    netsh interface ipv4 show udpconnections
    

相关代码

ESP32固件代码(VSCode PlatformIO Arduino框架)

#include <Arduino.h>
#include <WiFiManager.h>
#include <WiFiUdp.h>

#define BAUDRATE 115200

//UDP
WiFiUDP udp;               // UDP object
const unsigned int port = 12345;  // Port for UDP communication

bool discovered = false;

// Timing variables for sending broadcast packets
unsigned long lastBroadcastTime = 0;
unsigned long broadcastInterval = 2000; // Interval between broadcasts (ms)

void handshakeBroadcast() {
  IPAddress broadcastIP = WiFi.localIP();
  broadcastIP[3] = 255; // Set the last octet to 255 for broadcast
  Serial.print("Broadcast Address: ");
  Serial.println(broadcastIP);

  String message = "Discovery request from ESP32";
  udp.beginPacket(broadcastIP, port);
  udp.print(message.c_str());
  udp.endPacket();
  if (udp.endPacket() == 1) {
        Serial.println("Packet sent successfully");
    } else {
        Serial.println("Error sending packet");
    }
}

void receiveUDP() {
  // Check for incoming UDP messages
  char incomingPacket[255];
  int packetSize = udp.parsePacket();

  if (packetSize) {
    int len = udp.read(incomingPacket, 255);
    if (len > 0) {
      incomingPacket[len] = 0; // Null-terminate the string
    }
    Serial.printf("Received UDP packet from %s:%d\n", 
                  udp.remoteIP().toString().c_str(), udp.remotePort());
    Serial.printf("Packet contents: %s\n", incomingPacket);

    // Respond to the sender
    udp.beginPacket(udp.remoteIP(), udp.remotePort());
    udp.print("Hello from ESP32!");
    udp.endPacket();
  }
}

void loop() {
  // Check for incoming UDP messages
  receiveUDP();
  
  //if Pc client not discovered Boradcast Handshake
  unsigned long currentMillis = millis(); // Non-blocking UDP broadcast sending
  if (currentMillis - lastBroadcastTime >= broadcastInterval)
  {
    handshakeBroadcast();
    lastBroadcastTime = currentMillis;  // Update last broadcast time
  }
}

void setup() {
    Serial.begin(115200);
    
    //WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
    WiFiManager wm;

    bool res;
    res = wm.autoConnect("ESP32-Thing","12345678"); // password protected ap MIN 8 CHARACTERS

    if(!res) {
        Serial.println("Failed to connect");
        // ESP.restart();
    } 
    else {
        // WiFi connected
        Serial.println("Wifi connected.");
        
        Serial.print("IP: ");
        Serial.println(WiFi.localIP());
        
        Serial.print("Subnet mask: ");
        Serial.println(WiFi.subnetMask());

        // Start UDP
        if (udp.begin(port)) {
          Serial.printf("UDP listener started on port: %d\n", port);
        } else {
          Serial.println("Failed to start UDP listener");
        }
    } 
}

Win10 PC .NET程序代码

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

class UdpBroadcastListener
{
    static void Main(string[] args)
    {
        int port = 12345; // Port to listen on

        IPAddress ANY = IPAddress.Parse("0.0.0.0");
        
        UdpClient udpClient = new UdpClient(port);
        IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, port); // Listen on all interfaces 
        Console.WriteLine($"Listening for broadcasts on port {port}...");

        while (true)
        {
            try
            {
                byte[] receivedBytes = udpClient.Receive(ref remoteEndPoint);
                string receivedMessage = Encoding.UTF8.GetString(receivedBytes);
                Console.WriteLine($"Received packet from {remoteEndPoint} with message: {receivedMessage}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }
    }
}

可正常接收的Python脚本

import socket

# Configuration
UDP_IP = "0.0.0.0"  # Listen on all interfaces
UDP_PORT = 12345    # Port to listen on

# Create the UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Bind the socket to the specified IP and port
sock.bind((UDP_IP, UDP_PORT))

print(f"Listening for UDP packets on {UDP_IP}:{UDP_PORT}...")

try:
    while True:
        # Receive data from the socket (buffer size of 1024 bytes)
        data, addr = sock.recvfrom(1024)
        print(f"Received message: {data.decode('utf-8')} from {addr}")
except KeyboardInterrupt:
    print("\nExiting...")
finally:
    sock.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:50:55