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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
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
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

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
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Steve JenningsSr Manager Cloud Networking OpsCommented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.