-1

I'm trying to make a program that has a client, and intermediate host and a server. The client sends a packet to the host, the host sends it to the server and than the server sends a packet back to the host who sends it to the client. This should repeat 11 times. Here is my code:

public class SimpleEchoClient {

DatagramPacket sendPacket, receivePacket;
DatagramSocket sendReceiveSocket;

public SimpleEchoClient()
{
   try {

      sendReceiveSocket = new DatagramSocket();
   } catch (SocketException se) {   // Can't create the socket.
      se.printStackTrace();
      System.exit(1);
   }
}


public byte[] createWriteByte() {
    byte[] msg = new byte[100];
    int position = 2;
    Path path = Paths.get("test.txt");
    String fileName = path.getFileName().toString();

    //In datagrampackets, our data needs to be converted into bytes
    msg = new byte[100]; 
    msg[0] = 0x00;
    msg[1] = 0x02;

    for(int i=0; i<fileName.getBytes().length; i++) {
        msg[position] = fileName.getBytes()[i];
        position++;
    }

    msg[position] = 0x00;

    String mode = "netascii";

    position++;
    for(int i = 0; i < mode.getBytes().length; i++) {
        msg[position] = mode.getBytes()[i];
        position++;
    }
    msg[position] = 0;
    return msg;
}


public byte[] createReadByte() {
    byte[] msg = new byte[100];
    int position = 2;
    Path path = Paths.get("test.txt");
    String fileName = path.getFileName().toString();

    //In datagrampackets, our data needs to be converted into bytes
    msg = new byte[100]; 
    msg[0] = 0x00;
    msg[1] = 0x01;

    for(int i=0; i<fileName.getBytes().length; i++) {
        msg[position] = fileName.getBytes()[i];
        position++;
    }

    msg[position] = 0x00;

    String mode = "netascii";

    position++;
    for(int i = 0; i < mode.getBytes().length; i++) {
        msg[position] = mode.getBytes()[i];
        position++;
    }
    msg[position] = 0;
    return msg;
}

public void sendAndReceive(boolean checkRead)
{
        Path path = Paths.get("test.txt");
        String fileName = path.getFileName().toString();

        //In datagrampackets, our data needs to be converted into bytes
        byte[] msg;
        if(checkRead) {
            msg = createReadByte();
            checkRead = false;
        }else{
            msg = createWriteByte();
            checkRead = true;
        }

        String str = new String(msg);
        System.out.println(str);
        System.out.println("Hello");
        System.out.println(msg);

       try {
          sendPacket = new DatagramPacket(msg, msg.length,
                                          InetAddress.getLocalHost(), 5000);
       } catch (UnknownHostException e) {
          e.printStackTrace();
          System.exit(1);
       }

       try {
          sendReceiveSocket.send(sendPacket);
       } catch (IOException e) {
          e.printStackTrace();
          System.exit(1);
       }

    sendReceiveSocket.close();

    try {
        Thread.sleep(5000);
    } catch (InterruptedException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
       System.out.println("Client: Packet sent.\n");
       //NOW TO RECEIVE THE DATA
       DatagramSocket receiveSocket = null;
    try {
        receiveSocket = new DatagramSocket(5000);
    } catch (SocketException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
       byte data[] = new byte[4];
       receivePacket = new DatagramPacket(data, data.length);

       try {
          // Block until a datagram is received via sendReceiveSocket.  
          receiveSocket.receive(receivePacket);
       } catch(IOException e) {
          e.printStackTrace();
          System.exit(1);
       }

       // Process the received datagram.
       for(int j =0; j < data.length; j++) {
            System.out.println(data[j] & 0xff);
        }

       // We're finished, so close the socket.
       sendReceiveSocket.close();

}

public static void main(String args[])
{
    boolean checkRead = true;
    int count =0;
    for(int i = 0; i<10; i++) {
        System.out.println("Count:" + count);
        SimpleEchoClient c = new SimpleEchoClient();
        c.sendAndReceive(checkRead);
    }
}
}


public class IntermediateHost {

DatagramSocket receiveFromClient, receiveFromServer;
DatagramPacket receiveClientPack, sendClientPacket, receiveServerPacket, sendServerPacket;  

public IntermediateHost() {
    try {
        receiveFromClient = new DatagramSocket(5000);
    } catch (SocketException e) {
        e.printStackTrace();
    }
}

public void receiveAndEcho() {
    byte [] b = new byte[100];

    //When we receive the packet we need to store it in a datagrampacket which is initally empty
    receiveClientPack = new DatagramPacket(b, b.length);

    InetAddress  ip = null;
    try {
        receiveFromClient.receive(receiveClientPack);
        ip = InetAddress.getByName("localhost");
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    String message = new String(b);
    System.out.println(message);
    System.out.println(b);


    int port = 3001;

    sendClientPacket = new DatagramPacket(b, b.length, ip, port);
    try {
        receiveFromClient.send(sendClientPacket);
    } catch (IOException e1) {
        e1.printStackTrace();
    }
    receiveFromClient.close();

    //SEND BACK TO THE CLIENT
    try {
        Thread.sleep(5000);
        receiveFromServer = new DatagramSocket(3001);
    } catch (InterruptedException | SocketException e1) {
        e1.printStackTrace();
    }

    byte [] b1 = new byte[4];

    //When we receive the packet we need to store it in a datagrampacket which is initally empty
    receiveServerPacket = new DatagramPacket(b1, b1.length);

    //This method will wait for the incoming packet and it will copy all values from that packet
    //into receiveClientPack..so at this point the byte array will not be empty
    try{
        receiveFromServer.receive(receiveServerPacket);
    }catch (Exception e) {
        System.out.println(e);
    }

    for(int i =0;i < b1.length; i++) {
        System.out.println(b1[i] & 0xff);
    }

    InetAddress ip1 = null;
    try {
        ip1 = InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
    int port1 = 5000;

    sendServerPacket = new DatagramPacket(b1, b1.length, ip1, port1);
    try {
        receiveFromServer.send(sendServerPacket);
    } catch (IOException e) {
        e.printStackTrace();
    }
    receiveFromServer.close();
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}


public static void main(String args[]) throws IOException, InterruptedException {
    while(true) {
    IntermediateHost inter = new IntermediateHost();
    inter.receiveAndEcho();
    }
}

}

public class SimpleEchoServer {

DatagramPacket sendPacket, receivePacket;
DatagramSocket sendSocket, receiveSocket;

public SimpleEchoServer()
{
   try {

      sendSocket = new DatagramSocket();

      receiveSocket = new DatagramSocket(3001);

   } catch (SocketException se) {
      se.printStackTrace();
      System.exit(1);
   } 
}

public byte[] sendBackRead() {
    byte [] bytesToSend = new byte[4];
    bytesToSend[0] = 0x00;
    bytesToSend[1] = 0x03;
    bytesToSend[2] = 0x00;
    bytesToSend[3] = 0x01;

    return bytesToSend;
}

public byte[] sendBackWrite() {
    byte [] bytesToSend = new byte[4];
    bytesToSend[0] = 0x00;
    bytesToSend[1] = 0x04;
    bytesToSend[2] = 0x00;
    bytesToSend[3] = 0x00;

    return bytesToSend;
}

public boolean checkRead(byte[] msg) {
    if(msg[1] == 1) {
        return true;
    }
    return false;
}

public boolean checkWrite(byte[] msg) {
    if(msg[1] == 2) {
        return true;
    }
    return false;
}

public void receiveAndEcho() throws UnknownHostException
{

   byte data[] = new byte[100];
   receivePacket = new DatagramPacket(data, data.length);
   System.out.println("Server: Waiting for Packet.\n");

   try {        
      System.out.println("Waiting..."); // so we know we're waiting
      receiveSocket.receive(receivePacket);
   } catch (IOException e) {
      System.out.print("IO Exception: likely:");
      System.out.println("Receive Socket Timed Out.\n" + e);
      e.printStackTrace();
      System.exit(1);
   }
   boolean checkRead = checkRead(data);
   boolean checkWrite = checkWrite(data);
    String message = new String(data);
    System.out.println(message);
    receiveSocket.close();


   // Slow things down (wait 5 seconds)
   try {
       Thread.sleep(5000);
   } catch (InterruptedException e ) {
       e.printStackTrace();
       System.exit(1);
   }
   byte[] bytesToSend = null;
   System.out.println(data[1]);
   if(checkRead) {
       bytesToSend = sendBackWrite();
   }else if(checkWrite) {
       bytesToSend = sendBackRead(); 
   }

    for(int i =0;i < bytesToSend.length; i++) {
        System.out.println(bytesToSend[i] & 0xff);
    }

    InetAddress ip = InetAddress.getLocalHost();

    sendPacket = new DatagramPacket(bytesToSend, bytesToSend.length,
                            ip, 3001);


   // Send the datagram packet to the client via the send socket. 
   try {
      sendSocket.send(sendPacket);
   } catch (IOException e) {
      e.printStackTrace();
      System.exit(1);
   }

   System.out.println("Server: packet sent");

   // We're finished, so close the sockets.
   sendSocket.close();
   receiveSocket.close();
}

public static void main( String args[] ) throws UnknownHostException
{
    while(true) {
        SimpleEchoServer c = new SimpleEchoServer();
        c.receiveAndEcho();
    }
}
}

Now this code works if I were to only send one packet to the host, which sends to the server which returns another packet to the client from the host. However when I try to send more than one packet I get an error. To send more than one packet I basically create a loop in the main that simply calls the methods 11 times and i place a while loop in the server and host to have it running continuously in order to wait for packets. To see it run once, just eliminate the while loops in the main function of all three classes.

Any help as to how I can fix this error is greatly appreciated! Thanks!

tee
  • 1,286
  • 2
  • 19
  • 35

1 Answers1

1

On each call to the SimpleEchoClient c = new SimpleEchoClient();, your code tries to create a client on port 5000. Since you already have a client running on the same port, the exception is thrown.

So do it only once and send the packet 11 times.

public static void main(String args[])
{
    boolean checkRead = true;
    int count =0;
    SimpleEchoClient c = new SimpleEchoClient();
    for(int i = 0; i<=10; i++) {
        System.out.println("Count:" + count);      
        c.sendAndReceive(checkRead);
    }
}

Check how I have changed the loop condition to <=10 to make sure that 11 packets are sent.

Ishan Thilina Somasiri
  • 1,179
  • 1
  • 12
  • 24
  • agreed, I wouldn't recommend opening and closing the receive socket repeatedly. it should be open and listening for the life of the program. – slipperyseal Jan 19 '18 at 04:23
  • @Ishan Thilina Somasiri When I do what you said for all classes...which is basically to instantiate the object outside the while loop i get the error: Socket closed. – tee Jan 19 '18 at 14:12
  • Of course you need to move the socket closing logic out of the `sendAndReceive`. May be create a new method in the `SimpleEchoClient` class called `closeClient` and call the socket close ( `sendReceiveSocket.close();` ) in that. – Ishan Thilina Somasiri Jan 19 '18 at 14:26
  • @Ishan Thilina Somasiri if I do what you are saying where would I call this method to not get the "address already in use" behaviour nor the "Socket closed" behaviour – tee Jan 19 '18 at 20:10
  • My answer above is for "address already in use" behaviour. My comment asking you to create a new method is for "Socket closed". – Ishan Thilina Somasiri Jan 20 '18 at 02:45