jjmcc
jjmcc

Reputation: 875

Why are my UDP packets not being received when sent to my own public IP?

I have a simple C# UDP server which is running a listener and a sender on separate threads. The listener binds to the current machine on a specified port and listens for any incoming UDP packets. The writer will send data to a given endpoint, which works in some cases.

The problem I'm having at the moment though is that when UDP packets are sent to my public IP on the listening port, they are not being received, however if I change the public IP to my router ip (192.168.0.2) then it works fine. This isn't what I'm looking for as the hosted server can only send to the client's public IP.

Process

Sender ("5.5.5.5", 1000) sends data via UDP to a given endpoint ("1.2.3.4", 1000)

Server on ("1.2.3.4", 1000) receives data

Echoes data back to sender using their public IP and listening port ("5.5.5.5", 1000)

Why is the data not being sent back to the public ip even though it is listening on the given port?


When testing locally, running the server and client on the same machine, when the endpoint is set to my public IP and listening port, the data isn't received locally at all.

  Program()
    {

        ipep = new IPEndPoint(IPAddress.Any, 1000);
        listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        listenSocket.Bind(ipep);//this should bind to port 1000


        Thread listenThread = new Thread(listen);
        Thread writeThread = new Thread(send);

        listenThread.Start();
        writeThread.Start();

        listenThread.Join();
        writeThread.Join();

    }

    void listen()
    {
        Console.WriteLine("Starting listener for echoback...");
        while (true)
        {
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
            EndPoint epSender = (EndPoint)sender;
            byte[] buffer = new byte[1024];

            listenSocket.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epSender);

            string receivedString = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
            Console.WriteLine("Received via UDP: " + receivedString);
        }

    }

    void send()
    {
        while (true)
        {
            byte[] msg = Encoding.ASCII.GetBytes("Test message".ToCharArray());
//when this is router IP 192.168.0.2, it works fine, but not for public ip
            UdpClient client = new UdpClient("PUBLIC IP", 1000);
            client.Send(msg, msg.Length);

            Thread.Sleep(2000);

        }

    }
}

I have noticed that when the UDP packet is received by the 'server', the sender port is always different and I read that you need to reply on this IP/port, but the client is not listening on the receiving port so I create a new endpoint with the sender's address, and the port it should be listening on. So how do games or other applications manage this where there is constant communication from client-server via UDP.

Upvotes: 1

Views: 3223

Answers (1)

selbie
selbie

Reputation: 104569

Welcome to the world of NAT traversal. Where IP addresses get translated and port numbers aren't mapped consistently.

What you are attempting is called NAT Hairpinning. Whereby a client node behind your NAT attempts to send to its own public IP address. Not all NATs support this mode.. This is why sending to your private IP address works, but not your public IP address. When your NAT receives the datagram with the IP address destined to its own public IP, it does not know which of the many nodes its managing to send it back to (your pc, your phone, your game console, etc...). So it just drops the packet.

Upvotes: 3

Related Questions