【问题标题】:Not able to receive data from UDP server in win32 UDP socket application在 win32 UDP 套接字应用程序中无法从 UDP 服务器接收数据
【发布时间】:2025-12-04 22:25:01
【问题描述】:

我有一个硬件 ARM 控件作为 UDP 服务器,我通过下面用 C# 编写的代码与它通信。 PC是UDP客户端。服务器只是回显数据。

这很好用,没有任何问题,而且很稳定。

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

namespace UDPSocket
{
    class UDPSender
    {
        static void Main(string[] args)
        {
            UInt32 i=0;
            Int32 PORT = 45555;
            for (; i < 15; )
            {
                Console.WriteLine(i++);
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
                    ProtocolType.Udp);

                IPAddress broadcast = IPAddress.Parse("192.168.0.10");

                byte[] sendbuf = Encoding.ASCII.GetBytes("Shriganesh Damle, Infineon Techonologies India Pvt Ltd, Bangalore");
                IPEndPoint ep = new IPEndPoint(broadcast, PORT);

                //Creates a UdpClient for reading incoming data.
                UdpClient receivingUdpClient = new UdpClient(PORT);

                s.SendTo(sendbuf, ep);

                Console.WriteLine("Message sent to the broadcast address");

                //Creates an IPEndPoint to record the IP Address and port number of the sender.  
                // The IPEndPoint will allow you to read datagrams sent from any source.
                IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

                // Blocks until a message returns on this socket from a remote host.
                Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);

                string returnData = Encoding.ASCII.GetString(receiveBytes);

                Console.WriteLine("This is the message you received " +
                                            returnData.ToString());
                Console.WriteLine("This message was sent from " +
                                            RemoteIpEndPoint.Address.ToString() +
                                            " on their port number " +
                                            RemoteIpEndPoint.Port.ToString());
                //Console.Read();
                receivingUdpClient.Close();
            }
            Console.Read();
        }
    }
}

现在,我想在 Win32 C 应用程序中使用相同的 PC 代码。我尝试了下面的代码。

/*
    Simple udp client    
*/
#include<stdio.h>
#include<winsock2.h>

#pragma comment(lib,"ws2_32.lib") //Winsock Library

#define SERVER "192.168.0.10"  //ip address of udp server
#define BUFLEN 512  //Max length of buffer
#define PORT 45555   //The port on which to listen for incoming data

int main(void)
{
    struct sockaddr_in si_other;
    int s, slen=sizeof(si_other);
    char buf[BUFLEN];
    char message[BUFLEN];
    WSADATA wsa;

    //Initialise winsock
    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        printf("Failed. Error Code : %d",WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    printf("Initialised.\n");

    //create socket
    if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
    {
        printf("socket() failed with error code : %d" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    //setup address structure
    memset((char *) &si_other, 0, sizeof(si_other));
    si_other.sin_family = AF_INET;
    si_other.sin_port = htons(PORT);
    si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);

    //start communication
    while(1)
    {
        printf("Enter message : ");
        gets(message);

        //send the message
        if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
        {
            printf("sendto() failed with error code : %d" , WSAGetLastError());
            exit(EXIT_FAILURE);
        }

        //receive a reply and print it
        //clear the buffer by filling null, it might have previously received data
        memset(buf,'\0', BUFLEN);
        //try to receive some data, this is a blocking call
        if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
        {
            printf("recvfrom() failed with error code : %d" , WSAGetLastError());
            exit(EXIT_FAILURE);
        }

        puts(buf);
    }

    closesocket(s);
    WSACleanup();

    return 0;
}

此代码能够发送到 UDP 服务器并回显。但是 recvfrom 调用将等待数据直到无限时间。 recvfrom 正在阻止呼叫。我给出了正确的 IP 地址和端口。我仍然无法在 Win32 应用程序中从服务器接收数据。你能帮忙吗?

【问题讨论】:

  • 而不是 gets(message) 尝试对消息进行硬编码;看看有没有效果
  • 您的代码中一个明显的错误是您没有在messag[] 的末尾放置'\0' 字符。这意味着 strlen() 行为将出乎意料
  • 即使在硬编码后也无法工作:(
  • 您的两个代码都发送到 192.168.0.10 吗?是服务器吗?我是说第三台机器?
  • 是的。它是服务器的IP地址。但它不是第三台机器。只有两台机器存在。 1. PC(客户端) 2. 硬件板(服务器)

标签: c sockets udp winsock2 winsockets


【解决方案1】:

如果你想在一个套接字上接收数据,你需要将它绑定到一个或多个本地地址和一个本地端口。您的 C# 版本通过 new UdpClient(PORT)(注意 PORT 参数)实现了这一点,但您的 C 版本没有做任何可比的事情。

创建套接字后,做

sockaddr_in localAddr;

localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(PORT);
localAddr.sin_addr.S_un.S_addr = INADDR_ANY;

bind(s, &localAddr, sizeof(sockaddr_in));

并验证它是否返回0 表示成功。

或者,如果您创建了第二个套接字来接收服务器响应,C 版本将与 C# 版本更加平行。我认为在 C 中没有必要这样做(在 Winsock2 中,更准确地说),但是使用相同的套接字发送和接收可能需要您绑定到特定的本地地址而不是 @ 987654325@.

【讨论】:

  • 绑定(s, INADDR_ANY, PORT);返回错误代码 10014。如果我将 INADDR_ANY 更改为特定地址 192.168.0.2,则会收到错误代码 10049。
  • @SHRI,我的错,我写得太仓促了。错误代码 10014 应该可以通过我上面的更新来解决。
  • 还有一个问题:UDPClient 使用'bind' API 而不是'connect' API 是否正确?
  • @SHRI, bind() 确定UDPClient 发送的数据包的 地址和(尤其是)端口,以及它将在哪里接收任何打算发送给它的数据包.另一方面,connect() 为其发送的数据包建立(默认)destination 地址和端口。两者做不同的事情;它们不是彼此的替代品。根据您实际想要完成的任务,使用其中一种或两种。