简体   繁体   中英

C# Getting the IP Address of the client which the UDP server socket received data from

I have a very strange problem. I'm not able to find the IP Address of the client which my server receives data from. Below is my UDP Listener class.

The IPPacketInformation does not contain the IP. The clientEndPoint which I reference in my EndReceiveMessageFrom does neither.

When I

Console.Writeline(((IPEndPoint)clientEndPoint).Address); 

I get the IP Address of the server. I have the server hosted on my own machine so I get my own IP Address. When I try to access clientEndPoint.remoteEndPoint it throws an error because the socket isn't connected (due to being UDP).

So basically, a client from an external IP is able to send data, but I can't answer the client since I'm not able to retrieve it's IP. Any help is appreciated!

public class UdpListener
{
    private Socket s;
    public byte[] ReceiveBuffer = new byte[2048];

    public UdpListener()
    {
        s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
        s.Bind(new IPEndPoint(IPAddress.Any, 36200));
    }

    public void Listen()
    {
        try
        {
            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            s.BeginReceiveMessageFrom(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, ref remoteEndPoint, Recv, s);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            throw;
        }
    }

    private void Recv(IAsyncResult res)
    {
        try
        {
            Socket receiveSocket = (Socket)res.AsyncState;

            EndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
            IPPacketInformation packetInfo;
            SocketFlags flags = SocketFlags.None;
            int udpMessageLength = receiveSocket.EndReceiveMessageFrom(res, ref flags, ref clientEndPoint, out packetInfo);
            byte[] udpMessage = new byte[udpMessageLength];
            Array.Copy(ReceiveBuffer, udpMessage, udpMessageLength);

            Console.WriteLine(
                "{0} bytes received from {1} to {2}",
                ReceiveBuffer,
                clientEndPoint,
                packetInfo.Address
            );

            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, ((IPEndPoint)receiveSocket.LocalEndPoint).Port);
            s.BeginReceiveMessageFrom(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, ref remoteEndPoint, Recv, s);

            //Process data
            RaiseDataReceived(new ReceivedDataArgs(packetInfo.Address, ((IPEndPoint)clientEndPoint).Port, udpMessage));
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            throw;
        }
    }

    public delegate void DataReceived(ReceivedDataArgs args);

    public event DataReceived DataReceivedEvent;

    private void RaiseDataReceived(ReceivedDataArgs args)
    {
        DataReceivedEvent?.Invoke(args);
    }
}

I've tried to disable my firewall but that does not help. I've also done Port Forwarding on my router thus I can receive data from external clients.

EDIT to clarify the problem:

Server hosted on my machine behind a NAT with public IP 214.214.214.214.

The client is another machine, behind another NAT with public IP 910.910.910.910.

The client sends a message to the server, server receives it and able to read the content. When server get the IPEndPoint of the client, the displayed IP is 214.214.214.214 (IP of the server, not the Client )

EDIT Maybe I should say that I wasn't able to receive messages from clients on external networks until I ordered a "Dynamic IP" from my ISP. Still can't get the public IP of the source.

EDIT When using Wireshark and sniff a packet sent from external client to my server I can see it's the wrong src IP as well. In the picture below the src IP is my server IP and not the IP of the client that sent the data.

在此输入图像描述

After several days of reading everything I possibly could on routers, network and writing different examples of Receive, ReceiveFrom, ReceiveMessageFrom, BeginReceive, BeginReceiveFrom, BeginReceiveMessageFrom , and ReceiveAsync - I've solved my issue.

I changed my router. I can now get the source IP of the external client using a very old router. The router I was using before was a new Docsis 3.1.

Why it works with an old router, I don't know, but for some reason, the Docsis 3.1 changed the source IP to its own IP before letting the UDP message to my machine.

With using the UdpClient class you can actually retrieve the remote endpoint when receiving a message.

I have used a solution like the following to solve this task:

public void StartServer()
{
    var udpServer = new UdpClient(new IPEndPoint(IPAddress.Any, ConnectionInformation.DETECTION_PORT));
    udpServer.BeginReceive(new AsyncCallback(detectionCallback), udpServer);
}

private void detectionCallback(IAsyncResult ar)
{
    var client = (ar.AsyncState as UdpClient);
    if (client.Client == null) return;

    var endPoint = new IPEndPoint(IPAddress.Any, ConnectionInformation.DETECTION_PORT);
    var bytes = client.EndReceive(ar, ref endPoint);

    Debug.WriteLine($"Detection request from: {endPoint}");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM