0

I have an application that sends data (server) to a UDP client. It runs perfectly on the same computer, and over the LAN as long as I know as the destination address of the client. However, the moment I do this over the internet, it no longer works because it does not have the address of the destination computer. Here is the server code:

public ServerSender(String address, Int32 port, int TTL)
{
  m_Address = address;
  m_Port = port;
  m_TTL = TTL;

  Init();
}

private Socket m_Socket;
private IPEndPoint m_EndPoint;
private String m_Address;
private Int32 m_Port;
private Int32 m_TTL;


private void Init()
{
  IPAddress destAddr = IPAddress.Parse(m_Address);

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

  m_EndPoint = new IPEndPoint(destAddr, m_Port);     
}

public void SendBytes(Byte[] bytes)
{
  m_Socket.SendTo(bytes, 0, bytes.Length, SocketFlags.None, m_EndPoint);
}

Here is the client:

    public void Connect(string strAddress, int port)
    {
        m_Address = IPAddress.Parse(strAddress);
        m_Port = port;

        m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // Multicast Socket

        m_Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);

        m_EndPoint = new IPEndPoint(m_Address, m_Port);

        m_Socket.Bind(m_EndPoint);

        m_Socket.Connect(m_EndPoint);

        IsConnected = true;

        this.DoRead();
    }

    private void DoRead()
    {
        try
        {
            m_Socket.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), m_Socket);
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }

Obviously the server will need to listen for the remote connection and the client will need to connect to the server. I would think that I could then get the remote address and then in the SendBytes method I would sent to a remote endpoint. I have tried many different examples of async servers and they all lead to various errors. Is there any simple way to change this code to allow it to connect to a remote host over the internet? Thanks

Tom
  • 527
  • 1
  • 8
  • 28
  • For UDP, there is no connection established. There is no such thing as a UDP connection in terms of the prorocol. – Michael Beer Aug 21 '18 at 21:10
  • Ok the, how does one find out the remote address? I know it can be done with a UDPClient since I have such an application working over the internet. Can this not be done with sockets? – Tom Aug 22 '18 at 02:55
  • It depends. Assuming you know what is probably ging on on a typical wan (like NATing and the like): – Michael Beer Aug 22 '18 at 06:40
  • And over the Internet just alike. The entire infrastructure usually assumes that your client sends the initial packet. For TCP, this is done implicitly during the connection establishment. UDP does nothing like that. client send the first datagram to your Server - just send a dummy dgram. The dgram contains a source socket(IP & port) which you can then use TO send back from your Server (the source socket might not be the socket you are actually sending from at your client - it should not matter). – Michael Beer Aug 22 '18 at 06:52
  • If you are keen to figure out the background of this, read about NAT ( https://en.m.wikipedia.org/wiki/Network_address_translation ) . – Michael Beer Aug 22 '18 at 06:53
  • This, however, does not away with the connectionlessness of UDP: A BSD UDP socket usually has no connected peer, thus you perhaps need to use some different approach on the Server: try reading a DatagramPacket from your Java socket and extract its source socket. Then as soon as your client send its initial dummy packet, the Server will get a socket to send its data to... Look at the guide here: https://www.baeldung.com/udp-in-java Sorry for my incoherent writing, its early in the morning and all i got currently is my crappy little mobile ;) hope i could hell a bit... – Michael Beer Aug 22 '18 at 07:01
  • Hi, ok that's the key here...the client is not sending anything to the server. It is just listening on its local endpoint for packets being sent from the server that has a hard coded destination. I will modify the code to first send a packet from the client, so that the remote address is known. I will update this with an answer. Many thanks, these comments put this into perspective properly. Tom – Tom Aug 22 '18 at 15:26
  • Hey, great if it helped. Sorry for this mess though. Great that you got the knack of it nevertheless ;) – Michael Beer Aug 22 '18 at 15:42
  • Hi, as I mentioned earlier, I have another class in the same application, that also works over the internet. This class on the ReceivedDataCallback(IAsyncResult AR) method has a byte[] data = clientSocket.EndReceive(AR, ref source); line. This is done before the above class runs. from the source, I can get the IP address of the remote machine! So I pass the above IP address with the different port to the above code. This works on the LAN. However again it is not working on the internet. Now, does the remote client have to send data through it's local router before it can receive? – Tom Aug 22 '18 at 18:32
  • I ask this because I am using a mobile phone hotspot and I do not have access to it's router. In other words, does the client have to initiate the communications? – Tom Aug 22 '18 at 18:34
  • Hm, it gets a bit confusing, to recall, you got an application running on an host with a public IP and an host behind some router / firewall , i.e. without a public IP? Your 'server' is running on the host with the public IP, your 'client' behind the router. Just to make one thing clear: Both UDP and TCP build upon IP, and routing stuff is handled by the IP layer. If you are able to even ping each host from the other one, your routing is set up properly. – Michael Beer Aug 25 '18 at 13:40
  • I will write a short answer, stuffing everything into these comment blocks is tedious... – Michael Beer Aug 25 '18 at 13:44

1 Answers1

1

To summarize / elaborate on the comments a bit:

  • You got an host with a public IP, i.e. directly connected to the inet (your 'server')
  • You got an host without a public IP, i.e. connected to the inet over some gateway/firewall ... (your 'client' )

Since I don't know how much you know about networking: TCP / UDP packets are wrapped in IP packets. IP deals with IP addresses, TCP and UDP know about ports, but: TCP port 1 and UDP port 1 are different things!

Your network setup probably look like , with some sample IPs:

|--------|  47.46.43.42              |---------|192.168.0.1       |--------|
| Server |======== The INET =========| Gateway |==================| Client |
|--------|               81.82.83.84 |---------|     192.168.0.100|--------|

The gateway hererin is your 'router'.

Your client will be configured to send any traffic not belonging to the local LAN to the Gateway (if you are able to browse websites from your client, it is configured the right way).

Note again: The network devices will deliver IP packets to the proper recipients, if the destination IP belongs to 'their' network. They won't deliver to anyone if the destination IP is not known.

If your client tries to send an UDP packet to your server port 1 , it will send an IP packet that contains the destination IP 47.46.43.42 and the source IP 192.168.0.100 to the gateway, along with the destination port 1 and the port it uses to send the packet (lets assume port 2). The gateway receives the packet, sees the destination IP and sends the content of the IP packet as a new IP packet with (destination 47.46.43.42:1, source 81.82.83.84) further along. It has to use another UDP port for sending, lets say 15. The key thing here is: It also remembers that it sent a packet from 192.168.0.100 port 2 to 47.46.43.42 port 1 its own port 15. Whenever an UDP packet arrives on port 15 from 47.46.43.42, it can assume that it is some reply that should be forwarded to 192.168.0.100 port 2.

Then if the server receives the packet, all it sees is (dest IP 47.46.43.42:1, source IP 81.82.83.84:83:15). if it wants to send back an answer, it will send an IP packet with (dest 81.82.83.84:15, source 47.46.43.42:1). NOTE that the server only 'sees' the gateway, not your client behind it! The gateway receives the packet, recalls that it just sent an IP packet (dest 47.46.43.42:1, source 192.168.0.100:2), assumes that the IP packet is some kind of answer, and sends a new IP packet (dest 192.168.0.100:2, source 47.46.43.42:1) with the content received from the server to your client.

NOTE ESPECIALLY that this only works because the gateway received a packet from the client and learned from this that 192.168.0.100 and 81.82.83.84 'speak to each other'. Only because of that it knows what to do with packets arriving from your server!

Now lets try the other way round. There are two possible cases:

  1. The server knows the IP of your client (192.168.0.100) . Recall that this IP is not known to any device in the internet, thus if it sends out an IP packet (dest 192.168.0.100, source 81.82.83.84), it will not reach the gateway because the only packets reaching the gateway are those with a destination IP of 47.46.43.42 . This option will never work.

  2. The server knows the IP of the gateway and sends out an IP packet (destination 47.46.43.42, source 81.82.83.84). This packet will reach the gateway. But what should the gateway do with it? It never memorized that packets from IP 81.82.83.84 should probably be forwarded to your client. The only way for the gateway to learn would be if the client sent out a packet to your server first. This option will not work either.

Thus, it does not suffice* for the server to know the IP of the client, but the gateway needs to learn about the 'conversation' between your server and client. And the way your gateway works requires that the client sends out a packet first, using precisely the port for sending that you want to use further on. If your server should send to your client UDP port 2, the client must have sent a packet to the server first from UDP port 2.

What your gateway does is NATTING, and you better read a bit about it.

I assume, however, some standard setup of your network. This is likely, but technically, it could be entirely different, perhaps your gateway acts as a firewall, partially blocking outgoing traffic as well, perhaps your server is configured to use your gateway as a gateway as well (weird, but technically possible).

Thus troubleshooting offline is hard, and I am sorry if I cannot give you the solution (TM) for your concrete problem here.

PS: You might wonder why your client can send packets to the gateway with a wrong destination IP, while your server can't. This relates to the fact, that on the ethernet layer, your LAN is a single network, while the internet is not...

Michael Beer
  • 853
  • 5
  • 12