Search code examples
javasocketsudpip-addressdatagram

UDP messaging service


I have to create a program that will send and receive messages to/from a remote IP address. So basically it should simulate a messaging service. In the program, you must enter the an IP address and the data will be sent to that specific address. Currently, I can send but on the remote IP address machine, no content is received and vice versa. Please could you help me to understand why it is not working.

public class UDPchat extends Thread
{
   private final static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
   int port=1234;                             // port to send/receive datagrams on
   String remoteIPaddress= null;      // IP to send datagrams

   // constructor, parameter is command line parameters
   public UDPchat(String IPAdrr) throws Exception
    {

    System.out.println("chat program: IP address " + InetAddress.getLocalHost().toString() + " port " + port );

    start();        // start thread to receive and display datagrams
    // loop waiting for keyboard input, send datagram to remote IP                
    while(true)
      try
        {
        String s = in.readLine();                       // read a String
        System.out.println("Sending to " + IPAdrr + " socket " + port + " data: " + s);
        byte[] data = s.getBytes();                                     // convert to byte array
        DatagramSocket theSocket = new DatagramSocket();                // create datagram socket and the datagram
        DatagramPacket   theOutput = new DatagramPacket(data, data.length, InetAddress.getByName(IPAdrr), port);
        theSocket.send(theOutput);                                      // and send the datagram
        System.out.println("send everything");
        start();

       }
      catch (Exception e) {System.out.println("Eroor sending datagram " + e);
   // thread run method, receives datagram and display contents as a string
   public void run()                
        {
          try
              {
              // open DatagramSocket to receive 
              DatagramSocket ds = new DatagramSocket(port);
              // loop forever reading datagrams from the DatagramSocket
              while (true)
                 {
                 byte[] buffer = new byte[65507];   
                 // array to put datagrams in
                 DatagramPacket dp = new DatagramPacket(buffer, buffer.length); // DatagramPacket to hold the datagram
                 ds.receive(dp);
                 // wait for next datagram
                 String s = new String(dp.getData(),0,dp.getLength());        // get contenets as a String
                 System.out.println("UDP datagram length " + s.length()+ "  from IP " + dp.getAddress() + " received: " + s );
                 }
              }
          catch (SocketException se) {System.err.println("chat error " + se); }
          catch (IOException se) {System.err.println("chat error " + se);}
          System.exit(1);                                                       // exit on error
        }

public static void main(String args[]) throws Exception
{
    Scanner in = new Scanner(System.in);
    String remoteIPaddress = in.nextLine();
   UDPchat c=new UDPchat(remoteIPaddress);
}

}

Solution

  • Firstly, for a messaging service you should use TCP for its reliability.

    UDP is meant for real time communication in which latest data is more important.

    Well considering your problem, it might be because of the Network Address Translation done by the router if your computers are in different networks.

    I believe you are sending packets to correct IP address but the port is not correct. The port to which you might be sending the packets is the local port to the machine. You need to send the packets to the port assigned by the router (or external port).

    When the packet goes from a computer A to computer B through the router, the router maps the local port of computer to some random external port.

    So, if computer B needs to send a packet to computer A, then the computer B needs to reply on the external IP:port assigned to computer A by the router. The router will then forward it to the local IP:port of computer A.

    I suggest first understand how this mapping is created when UDP packets travel through a router within or external to the network.

    Please read about some network concepts like Network Address Translation, UDP holepunching carefully before working with TCP/UDP stuff.

    These source may help:

    Network Address Translation

    How NAT works?

    UDP Hole Punching

    RFC 4787 NAT Behavioral Requirements UDP

    RFC 5128 P2P across NAT

    You can also refer to some of my answers to same/similar problems here:

    How to Send A UDP packet via public IP through NAT?

    How to send an UDP message for an array of clients (java)

    UDP Image transfer works depending on network