0
votes

I have an hardware ARM control as UDP server and I am communicating to it via the code below written in C#. PC is UDP Client. Server simply echoes the data.

This works fine without any issue and this is stable.

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();
        }
    }
}

Now, I want the same PC code in Win32 C application. I tried the code below.

/*
    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;
}

This code is able to send to the UDP server and it echoes back. But recvfrom call will be waiting for data till infinite time. recvfrom is blocking call. I am giving correct IP address and PORT. Still I am not able to receive data from server in Win32 app. Can you help?

1
instead of gets(message) try hard code a message; see if it worksYasir Majeed
An apparent bug in your code is that you havent put '\0' character at the end of messag[]. It means strlen() behavior will be unexpectedYasir Majeed
Did not work even after hardcoding :(SHRI
Y are your both code sending to 192.168.0.10? Is it a server? I mean third machine?Yasir Majeed
Yes. It is IP address of server. But it is not third machine. ONly two machines exist. 1. PC(Client) 2. Hardware board(Server)SHRI

1 Answers

1
votes

If you want to receive data on a socket, you need to bind it to one or more local addresses and a local port. Your C# version achieves this via new UdpClient(PORT) (note the PORT argument), but your C version does not do anything comparable.

After creating the socket, do

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));

and verify that it returns 0 to indicate success.

Alternatively, the C version would be more parallel to the C# version if you created a second socket for receiving the server response. I don't think it's necessary to do that in C (in Winsock2, to be more precise), but it is possible that using the same socket to both send and receive would require you to bind to a specific local address instead of to INADDR_ANY.