1

I have an application where I need to receive UDP unicast packets from any IP address (on a particular port), but would like to know the sender's IP address of the received packet. I have created a socket and bound it via the following code:

Socket SocketLocal;
EndPoint epReceive;
int UCPort = 1000;
byte[] Buffer = new byte[1500];

SocketLocal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

SocketLocal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

// Bind Socket
epReceive = new IPEndPoint(IPAddress.Any, UCPort );
SocketLocal.Bind(epReceive);

SocketLocal.BeginReceiveFrom(Buffer, 0, Buffer.Length, SocketFlags.None, ref epReceive, new AsyncCallback(RxCallBack), Buffer);

The callback looks like:

public void RxCallBack(IAsyncResult aResult)
{
    try
    {
        byte[] receivedData = new byte[1500];

        receivedData = (byte[])aResult.AsyncState;

        // I process/intepret the received data
        // ...

        // I have a list box where I simply want to display
        // the sender's IP address
        lstBox.Items.Add(SocketLocal.LocalEndPoint.ToString()));
        //  Here I simply get 0.0.0.0:<port number>
        // If I modify SocketLocal.LocalEndPoint.ToString above to SocketLocal.RemoteEndPoint.ToString it throws an exception

        Buffer = new byte[1500];
        SocketLocal.BeginReceiveFrom(Buffer, 0, Buffer.Length, SocketFlags.None, ref epReceive, new AsyncCallback(RxCallBack), Buffer);

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }

}  // End of RxCallBack

This works well, as I am able to receive data sent from any IP to my computer. However, I would like to know the sender's IP address.

When I try and extract the Sender's IP address I simply get "0.0.0.0" which would make sense given that I set the Socket to IPAddress.any

There must be a way to find out the sender's IP address. I have searched and tried all of the various options to no avail. Can anyone provide some guidance?

PaulG
  • 13,871
  • 9
  • 56
  • 78
  • 1
    "When I try and extract"? How did you do that? Clearly the documentation indicates how to extract the remote end point address, https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receivefromasync?view=netframework-4.7.2 and it works for most users. – Lex Li Mar 05 '19 at 21:45
  • Good day Lex, The doc you reference works perfectly fine when the socket is not configured as IpAddress.any, but a specific address. Doing this I can easily obtain the sender's IP address. When I configure the socket as IPAddress.any the resulting sender's IP comes back as 0.0.0.0. This is the problem... I need to have a socket that I can received from any IP address, however, when I do receive data I would like to know which IP sent it. – NoSpam Please Mar 05 '19 at 22:58
  • In your question, are `epReceive` and `epRemote` supposed to be two different variables? Also, you're missing the part of the code that is wrong; no one can help if you don't post a complete question. – Ben Voigt Mar 06 '19 at 00:34
  • Good day Ben, Sorry, I simply copied a portion of my code and edited it incorrectly. I can add more code, but I was just checking to see if it is possible to obtain the sender's IP address if I have bound a port with the IPAddress.any parameter, – NoSpam Please Mar 06 '19 at 01:11
  • But where is the code that is giving you a wrong result? It has to be in the callback for `BeginReceiveFrom`, because the sender address comes with each incoming packet; you can't possibly know it immediately after binding. – Ben Voigt Mar 06 '19 at 01:22
  • Good day Ben, Absolutely. I am within the callback. I will post this code so you can see what I am talking about. – NoSpam Please Mar 06 '19 at 02:01
  • You have to show a full sample to reproduce the issue. My open source project heavily uses the relevant code so I can confirm proper code should work to match the documentation. – Lex Li Mar 06 '19 at 02:08
  • Good day Lex, I added more of the code just now. It is within the callback where I cannot seem to obtain the sender's IP Address. – NoSpam Please Mar 06 '19 at 02:18
  • You are using epReceive as both remote and local endpoint... Define a remote endpoint as new IPEndPoint(IPAddress.Any, **0** ), pass it in your BeginreceiveFrom and all should work as you want. – C. Gonzalez Mar 06 '19 at 13:29
  • Good day C. Gonzalez, Thank you for your suggestion. I gave it a go just now and sadly, I am getting the same result (0.0.0.0. is being displayed as the sender's IP Address). – NoSpam Please Mar 06 '19 at 13:51
  • Good day All, C. Gonzalez's comments had me dig a bit deeper and I am getting closer. The first issue is that the last parameter of BeginrReceiveFrom should be modified so that it is the socket. This will allow me to extract the resulting socket info within the callback. Within the Callback I can then call EndReceiveFrom using the correct passing IAsyncResult parameter. From here I can extract the sender's IP Address. I am working on the code now and have it working. Once I clean up the code a bit I will post up. ] – NoSpam Please Mar 06 '19 at 14:22
  • Good day All, I just added my working code to my original question and so my question is now closed. Thanks again! – NoSpam Please Mar 06 '19 at 21:06

1 Answers1

2

After reviewing everyone's comments I was able to find the answer to my question. There was a similar question presented here:

C# UDP Socket: Get receiver address

Reviewing this question I used portions of it and was able to create a solution to my original question. The resulting code is appended to my original question listed above and list below:

As a follow up... C Gonzales's comment triggered me to look at this differently and so I was able to resolve my issue with the following. First I modified my "BeginReceiveFrom" method's final parameter (state) to the actual socket. This affects the "IAsyncResult" item that is passed to the call back function. Now my first portion of software looks like this:

// Just the BeginReceiveFrom was changed
SocketLocal.BeginReceiveFrom(Buffer, 0, Buffer.Length, SocketFlags.None, ref epReceive, new AsyncCallback(RxCallBack), SocketLocal);

Next I modified the call back to the following:

public void RxCallBack(IAsyncResult aResult)
{
    try
    {
            // Create Local Buffer
            byte[] receivedData = new byte[1500];

            // Create Socket to get received data
            Socket ReceiveSocket = (Socket)aResult.AsyncState;

            // Create Endpoint
            EndPoint epReceive = new IPEndPoint(IPAddress.Any, 0);

            // Extract Data...
            int UDPRxDataLength = ReceiveSocket.EndReceiveFrom(aResult, ref epReceive);

            // Copy Rx Data to Local Buffer
            Array.Copy(SocketLocal.Buffer, receivedData, UDPRxDataLength);

            //Start listening for a new message.

            // Setup for next Packet to be received
            Buffer = new byte[1500];
            SocketLocal.BeginReceiveFrom(Buffer, 0, Buffer.Length, SocketFlags.None, ref epReceive, (RxCallBack), SocketLocal);

        // I process/intepret the received data
        // ...

        // The Sender's IP Address is located in the epReceive Endpoint
        lstBox.Items.Add( "Sender IP " + ((IPEndPoint)epReceive).Address.ToString() );

    }
    catch (Exception ex)
    {

        MessageBox.Show(ex.ToString());
    }


}  // End of RxCallBack

Doing the above works perfectly!

Thanks to all for your comments!

  • Thank you for posting the code that solved your problem. However, you should remove the code from your question and post it here in this answer – actaram Mar 06 '19 at 22:31