PingServer and Client

I'm trying to get my program(s) to communicate between a client and a server. I need to have the client send packets to the server, and the server simulates packet loss, so I need to get the client to retry.

My problem is the client is retrying even after the server has sent a reply, though I don't need that.

I'm trying to use a class to start new threads to help me implement this. Maybe I don't understand enough about Java threads?

In the thread class, I attempt to have it sleep and then send if there's no reply.


If you feel like you need more information my code and what I need, post some suggestion, THEN request.
// PingClient.java

import java.io.*;
import java.net.*;
import java.util.*;


/*
 * Server to process ping requests over UDP.
 */
public class PingClient // implements Runnable
{
   private static final double LOSS_RATE = 0.3;
   private static final int AVERAGE_DELAY = 100;  // milliseconds
   static DatagramPacket request;
   static DatagramPacket response;
   static DatagramSocket socket;
   static boolean received = false;
   public static int num = 0;
   /*
   PingClient()
   {
       Thread thisThread = new Thread( this );
       thisThread.start();
   }
   */
   public static void main(String[] args) throws Exception
   {
      // Get command line argument.
      if (args.length < 2) {
         System.out.println("Required arguments: port, address");
         return;
      }
      int port = Integer.parseInt(args[0]);

      // Create random number generator for use in simulating 
      // packet loss and network delay.
      Random random = new Random();

      // Create a datagram socket for receiving and sending UDP packets
      // through the port specified on the command line.
      socket = new DatagramSocket(port);
      
      /* DatagramConnection sender =
          (DatagramConnection)Connector.open("datagram://target:32767"); */

      // Processing loop.
      while (true)
      {
          byte kilo[] = new byte[1024];
          char[] transfer;
          String num2 = "" + num;
          transfer = num2.toCharArray();
          for(int i = 0; i < transfer.length; i++)
          {
              kilo[i] = (byte)transfer[i];
          }
         // Create a datagram packet to hold outgoing UDP packet.
         InetAddress address = InetAddress.getByName(args[1]);
         request = new DatagramPacket(kilo, kilo.length, address /* InetAddress ipAddress */ , /* int port */ 1024); // port 1024
         // InetAddress.getLocalHost()
         response = new DatagramPacket(kilo, kilo.length);
         
         
         socket.send(request);
         
         System.out.println("Starting thread");
         PingThread ping = new PingThread(request, response, socket, received, num);
         
         // ping.start();
         

          // System.out.println("hello");
          socket.receive(response); // we won't necessarily get anything back
         // Thread.sleep(200);
          ping.myStop();
          System.out.println("hello");

         
         // System.out.println("Hello; 3");
         /*
         InetAddress serverHost = request.getAddress();
         int serverPort = request.getPort();
         byte[] buf = request.getData();
         DatagramPacket reply = new DatagramPacket(buf, buf.length, serverHost, serverPort);
         socket.send(reply);
         */
         // end insertion
         
         
         
         
         
         
        printData(response);
        
        received = true;
         /*
         // Decide whether to reply, or simulate packet loss.
         if (random.nextDouble() < LOSS_RATE) {
            System.out.println("Reply not sent.");
            continue; 
         }

         // Simulate network delay.
         Thread.sleep((int) (random.nextDouble() * 2 * AVERAGE_DELAY));

         // Send reply.
         InetAddress clientHost = request.getAddress();
         int clientPort = request.getPort();
         byte[] buf = request.getData();
         DatagramPacket reply = new DatagramPacket(buf, buf.length, clientHost, clientPort); // a length here
         socket.receive(reply);

         System.out.println("   Reply recieved.");
         */
          received = false;
          num++;
          if(num == 11)
              return;
          System.out.println(num);
      }
   }

   
   
   /*
   public void run()
   {
       System.out.println("Hello");
       try
       {
           Thread.sleep(200);
       }
       catch(InterruptedException e)
       {
           System.out.println("Bug detected: " + e);    
       }
       if(!received)
       {
           try
           {
               socket.send(request);
               Thread thisThread = new Thread( this );
               thisThread.start();
               socket.receive(response);
           }
           catch(IOException e)
           {
               System.out.println("Bug detected: " + e);
           }
       }
   }
   */
   
   
   
   
   /* 
    * Print ping data to the standard output stream.
    */
   public static void printData(DatagramPacket request) throws Exception
   {
      // Obtain references to the packet's array of bytes.
      byte[] buf = request.getData();

      // Wrap the bytes in a byte array input stream,
      // so that you can read the data as a stream of bytes.
      ByteArrayInputStream bais = new ByteArrayInputStream(buf);

      // Wrap the byte array output stream in an input stream reader,
      // so you can read the data as a stream of characters.
      InputStreamReader isr = new InputStreamReader(bais);

      // Wrap the input stream reader in a bufferred reader,
      // so you can read the character data a line at a time.
      // (A line is a sequence of chars terminated by any combination of \r and \n.) 
      BufferedReader br = new BufferedReader(isr);

      // The message data is contained in a single line, so read this line.
      String line = br.readLine();

      // Print host address and data received from it.
      System.out.println(
         "Received from " + 
         request.getAddress().getHostAddress() + 
         ": " +
         new String(line) );
   }
}


// PingThread.java

import java.io.*;
import java.net.*;
import java.util.*;


/**
 * Write a description of class PingThread here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class PingThread implements Runnable
{
   static DatagramPacket request;
   static DatagramPacket response;
   static DatagramSocket socket;
   static boolean received = false;
   static int num;
   public static boolean stopFlag = false;
   public void myStop()
   {
       System.out.println("used stop flag");
       stopFlag = true;
   }
   PingThread(DatagramPacket request, DatagramPacket response, DatagramSocket socket, boolean received, int num)
   {
       stopFlag = false;
       this.request = request;
       this.response = response;
       this.socket = socket;
       this.received = received;
       this.num = num;
       Thread thisThread = new Thread( this );
       thisThread.start();
   }
   public void run()
   {
       // PingClient check = new PingClient();
       // System.out.println("Hello");
       try
       {
           Thread.sleep(200); // problem is this will wait too long
           if(stopFlag)
           {
               System.out.println("returning");
               return;
           }
           System.out.println("num: " + num);
       }
       catch(InterruptedException e)
       {
           System.out.println("Bug detected: " + e);    
       }
       if(!received)
       {
           try
           {
               socket.send(request);
               // Thread thisThread = new Thread( this ); // this may be the problem
               // thisThread.start();
               // socket.receive(response);
           }
           catch(IOException e)
           {
               System.out.println("Bug detected: " + e);
           }
       }
   }
}

// PingServer.java

import java.io.*;
import java.net.*;
import java.util.*;

/*
 * Server to process ping requests over UDP.
 */
public class PingServer
{
   private static final double LOSS_RATE = 0.3;
   private static final int AVERAGE_DELAY = 100;  // milliseconds

   public static void main(String[] args) throws Exception
   {
      // Get command line argument.
      if (args.length != 1) {
         System.out.println("Required arguments: port");
         return;
      }
      int port = Integer.parseInt(args[0]);

      int num = 0;
      
      // Create random number generator for use in simulating 
      // packet loss and network delay.
      Random random = new Random();

      // Create a datagram socket for receiving and sending UDP packets
      // through the port specified on the command line.
      DatagramSocket socket = new DatagramSocket(port);

      // Processing loop.
      while (true)
      {
          byte kilo[] = new byte[1024];
          char[] transfer;
          String num2 = "" + num;
          transfer = num2.toCharArray();
          for(int i = 0; i < transfer.length; i++)
          {
              kilo[i] = (byte)transfer[i];
          }
          
          
          
          // Create a datagram packet to hold incomming UDP packet.
          DatagramPacket request = new DatagramPacket(new byte[1024], 1024); // , InetAddress.getLocalHost(), 54321);

          
          
         // Block until the host receives a UDP packet.
         socket.receive(request); // on the other end, the destination will be specified
         
         // Print the recieved data.
         printData(request);

         // Decide whether to reply, or simulate packet loss.
         if (random.nextDouble() < LOSS_RATE) {
            System.out.println("Reply not sent.");
            continue; 
         }

         // Simulate network delay.
         Thread.sleep((int) (random.nextDouble() * 2 * AVERAGE_DELAY));

         // Send reply.
         InetAddress clientHost = request.getAddress();
         int clientPort = request.getPort();
         byte[] buf = request.getData();
         DatagramPacket reply = new DatagramPacket(buf, buf.length, clientHost, clientPort);
         socket.send(reply); // at this point the client recieves

         System.out.println("   Reply sent.");
         num++;
      }
   }

   /* 
    * Print ping data to the standard output stream.
    */
   private static void printData(DatagramPacket request) throws Exception
   {
      // Obtain references to the packet's array of bytes.
      byte[] buf = request.getData();

      // Wrap the bytes in a byte array input stream,
      // so that you can read the data as a stream of bytes.
      ByteArrayInputStream bais = new ByteArrayInputStream(buf);

      // Wrap the byte array output stream in an input stream reader,
      // so you can read the data as a stream of characters.
      InputStreamReader isr = new InputStreamReader(bais);

      // Wrap the input stream reader in a bufferred reader,
      // so you can read the character data a line at a time.
      // (A line is a sequence of chars terminated by any combination of \r and \n.) 
      BufferedReader br = new BufferedReader(isr);

      // The message data is contained in a single line, so read this line.
      String line = br.readLine();

      // Print host address and data received from it.
      System.out.println(
         "Received from " + 
         request.getAddress().getHostAddress() + 
         ": " +
         new String(line) );
   }
}

// PingThread.java (for PingServer)

import java.io.*;
import java.net.*;
import java.util.*;


/**
 * Write a description of class PingThread here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class PingThread implements Runnable
{
   static DatagramPacket request;
   static DatagramPacket response;
   static DatagramSocket socket;
   static boolean received = false;
   PingThread(DatagramPacket request, DatagramPacket response, DatagramSocket socket, boolean received)
   {
       this.request = request;
       this.response = response;
       this.socket = socket;
       this.received = received;
       Thread thisThread = new Thread( this );
       thisThread.start();
   }
   public void run()
   {
       // System.out.println("Hello");
       try
       {
           Thread.sleep(200);
       }
       catch(InterruptedException e)
       {
           System.out.println("Bug detected: " + e);    
       }
       if(!received)
       {
           try
           {
               socket.send(request);
               Thread thisThread = new Thread( this );
               thisThread.start();
               // socket.receive(response);
           }
           catch(IOException e)
           {
               System.out.println("Bug detected: " + e);
           }
       }
   }
}

Open in new window

JCW2Asked:
Who is Participating?
 
manavilaiCommented:
package com.ibm.vivek;

//PingClient.java

import java.io.*;
import java.net.*;
import java.util.*;

public class PingClient // implements Runnable
{
   private static final double LOSS_RATE = 0.3;
   private static final int AVERAGE_DELAY = 100;  // milliseconds
   static DatagramPacket request;
   static DatagramPacket response;
   static DatagramSocket socket;
   static boolean received = false;
   public static int num = 0;
   /*
   PingClient()
   {
       Thread thisThread = new Thread( this );
       thisThread.start();
   }
   */
   public static void main(String[] args) throws Exception
   {
      // Get command line argument.
      if (args.length < 2) {
         System.out.println("Required arguments: port, address");
         return;
      }
      int port = Integer.parseInt(args[0]);

      // Create random number generator for use in simulating
      // packet loss and network delay.
      Random random = new Random();

      // Create a datagram socket for receiving and sending UDP packets
      // through the port specified on the command line.
      socket = new DatagramSocket(port);
     
      /* DatagramConnection sender =
          (DatagramConnection)Connector.open("datagram://target:32767"); */

      // Processing loop.
      received = false;
      while (!received)
      {
          byte kilo[] = new byte[1024];
          char[] transfer;
          String num2 = "" + num;
          transfer = num2.toCharArray();
          for(int i = 0; i < transfer.length; i++)
          {
              kilo[i] = (byte)transfer[i];
          }
         // Create a datagram packet to hold outgoing UDP packet.
         InetAddress address = InetAddress.getByName(args[1]);
         request = new DatagramPacket(kilo, kilo.length, address /* InetAddress ipAddress */ , /* int port */ 1024); // port 1024
         // InetAddress.getLocalHost()
         response = new DatagramPacket(kilo, kilo.length);
         
         
         socket.send(request);
         
         System.out.println("Starting thread");
         PingThread ping = new PingThread(request, response, socket, received, num);
         
         // ping.start();
         

          // System.out.println("hello");
          socket.receive(response); // we won't necessarily get anything back
         // Thread.sleep(200);
          ping.myStop();
          System.out.println("hello");

         
         // System.out.println("Hello; 3");
         /*
         InetAddress serverHost = request.getAddress();
         int serverPort = request.getPort();
         byte[] buf = request.getData();
         DatagramPacket reply = new DatagramPacket(buf, buf.length, serverHost, serverPort);
         socket.send(reply);
         */
         // end insertion
         
        printData(response);
       
        received = true;
         /*
         // Decide whether to reply, or simulate packet loss.
         if (random.nextDouble() < LOSS_RATE) {
            System.out.println("Reply not sent.");
            continue;
         }

         // Simulate network delay.
         Thread.sleep((int) (random.nextDouble() * 2 * AVERAGE_DELAY));

         // Send reply.
         InetAddress clientHost = request.getAddress();
         int clientPort = request.getPort();
         byte[] buf = request.getData();
         DatagramPacket reply = new DatagramPacket(buf, buf.length, clientHost, clientPort); // a length here
         socket.receive(reply);

         System.out.println("   Reply recieved.");
         */
          //received = false;
          //num++;
          //if(num == 11)
              //return;
          //System.out.println(num);
      }
   }

   
   
   /*
   public void run()
   {
       System.out.println("Hello");
       try
       {
           Thread.sleep(200);
       }
       catch(InterruptedException e)
       {
           System.out.println("Bug detected: " + e);    
       }
       if(!received)
       {
           try
           {
               socket.send(request);
               Thread thisThread = new Thread( this );
               thisThread.start();
               socket.receive(response);
           }
           catch(IOException e)
           {
               System.out.println("Bug detected: " + e);
           }
       }
   }
   */
   
   
   
   
   /*
    * Print ping data to the standard output stream.
    */
   public static void printData(DatagramPacket request) throws Exception
   {
      // Obtain references to the packet's array of bytes.
      byte[] buf = request.getData();

      // Wrap the bytes in a byte array input stream,
      // so that you can read the data as a stream of bytes.
      ByteArrayInputStream bais = new ByteArrayInputStream(buf);

      // Wrap the byte array output stream in an input stream reader,
      // so you can read the data as a stream of characters.
      InputStreamReader isr = new InputStreamReader(bais);

      // Wrap the input stream reader in a bufferred reader,
      // so you can read the character data a line at a time.
      // (A line is a sequence of chars terminated by any combination of \r and \n.)
      BufferedReader br = new BufferedReader(isr);

      // The message data is contained in a single line, so read this line.
      String line = br.readLine();

      // Print host address and data received from it.
      System.out.println(
         "Received from " +
         request.getAddress().getHostAddress() +
         ": " +
         new String(line) );
   }
}

// PingThread.java

import java.io.*;
import java.net.*;
import java.util.*;


/**
 * Write a description of class PingThread here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class PingThread implements Runnable
{
   static DatagramPacket request;
   static DatagramPacket response;
   static DatagramSocket socket;
   static boolean received = false;
   static int num;
   public static boolean stopFlag = false;
   public void myStop()
   {
       System.out.println("used stop flag");
       received = true;
       stopFlag = true;
   }
   PingThread(DatagramPacket request, DatagramPacket response, DatagramSocket socket, boolean received, int num)
   {
       stopFlag = false;
       this.request = request;
       this.response = response;
       this.socket = socket;
       this.received = received;
       this.num = num;
       Thread thisThread = new Thread( this );
       thisThread.start();
   }
   public void run()
   {
       // PingClient check = new PingClient();
       // System.out.println("Hello");
       while(!received)
       {
            
      try
       {
           Thread.sleep(200); // problem is this will wait too long
           if(stopFlag)
           {
               System.out.println("returning");
               break;
           }
           System.out.println("num: " + num);
       }
       catch(InterruptedException e)
       {
           System.out.println("Bug detected: " + e);    
       }
       //if(!received)
       //{
           try
           {
               socket.send(request);
               // Thread thisThread = new Thread( this ); // this may be the problem
               // thisThread.start();
               // socket.receive(response);
               num++;
           }
           catch(IOException e)
           {
               System.out.println("Bug detected: " + e);
           }
       //}
       }
   }
}
0
 
Ted BouskillSenior Software DeveloperCommented:
OK, by the very definition of UDP it is unreliable without any handshaking:
http://en.wikipedia.org/wiki/User_Datagram_Protocol

Here is the relevant quote: "UDP uses a simple transmission model without implicit hand-shaking dialogues for guaranteeing reliability, ordering, or data integrity. Thus, UDP provides an unreliable service and datagrams may arrive out of order, appear duplicated, or go missing without notice."

If you want reliability use TCP.
0
 
JCW2Author Commented:
TCP isn't an option. In this project I'm trying to get my program to retry with UDP, in a correct manner.
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

 
Ted BouskillSenior Software DeveloperCommented:
It won't work.  What you require isn't available in the stack nor the packets.  UDP is working exactly as designed.
0
 
manavilaiCommented:
i think your while(true) logic is playing spoil sport.
i have tried to modify you client and thread logic slightly.
see if it is useful.
0
 
Steve JenningsIT ManagerCommented:
I'm too lazy to read thru your code so I don't know if you have a code problem or an unrealistic view of how UDP works. Any kind of error handling done with UDP has to be handled by a controlling application. If you understand that, then your code may simply need tweaking.

I wrote something similar out of boredom years ago where I'd send 500 UDP datagrams with a sequence number incremented in the payload, randomly skipping a number or 2. Wait a half second and then send 500 more with random loss. The receiving application would determine if something was lost. If so, it would send back a datagram with a list of missing sequence numbers.

I was trying to see if I could send a "stream" of data and process retransmits on the fly.

I think it was kind of pointless, but I learned a little about java, buffering, and async communication.

Good luck,
SteveJ
0
 
JCW2Author Commented:
Thank you for your help.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.