Home > Software engineering >  Having trouble with Java client-server communication, where the out.println seems to be delayed?
Having trouble with Java client-server communication, where the out.println seems to be delayed?

Time:11-07

I'm confused as to why I cant seem to get the server to output to the client properly. I'm not the most experienced when it comes to java and have exhausted anything I could think of. The other systems in place seem to work fine(The Add/List commands).

You can see the server responses are an input or two behind

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.tcpechoclient;
import java.io.*;
import java.net.*;

/**
 *
 * @author Leepe
 */
public class TCPEchoClient {
 private static InetAddress host;
    private static final int PORT = 1248;

    public static void main(String[] args) {
     try 
     {
        host = InetAddress.getLocalHost();
     } 
     catch(UnknownHostException e) 
     {
    System.out.println("Host ID not found!");
    System.exit(1);
     }
     run();
   }
    
   private static void run() {
    Socket link = null;             //Step 1.
    try 
    {
    link = new Socket(host,PORT);       //Step 1.
        //link = new Socket( "192.168.0.59", PORT);
    BufferedReader in = new BufferedReader(new InputStreamReader(link.getInputStream()));//Step 2.
    PrintWriter out = new PrintWriter(link.getOutputStream(),true);  //Step 2.

    //Set up stream for keyboard entry...
    BufferedReader userEntry =new BufferedReader(new InputStreamReader(System.in));
    String message = "";
        String response = "";

        while (!message.equals("Stop")) {
                       
            System.out.println("Enter message to be sent to server: ");
            message =  userEntry.readLine();
            
            out.println(message);       //Step 3.
            //  out.flush();
            
            response = in.readLine();       //Step 3.
            System.out.println("\nSERVER RESPONSE> "   response);

        }
     }
    catch(IOException e)
    {
    e.printStackTrace();
    } 
    finally 
    {
        try 
        {
            System.out.println("\n* Closing connection... *");
            link.close();               //Step 4.
    }catch(IOException e)
        {
            System.out.println("Unable to disconnect/close!");
            System.exit(1);
    }
    }
 } // finish run method
}  //finish the class

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.tcpechoserverthreads;
import java.io.*;
import java.net.*;

/**
 *
 * @author Leepe
 */
public class TCPEchoServer { 
  private static ServerSocket servSock;
  private static final int PORT = 1248;
  private static int clientConnections = 0;

  public static void main(String[] args) {
    System.out.println("Opening port..." "\n" "Listening on port: " PORT);
    try 
    {
        servSock = new ServerSocket(PORT);      //Step 1.
    }
    catch(IOException e) 
    {
         System.out.println("Unable to attach to port!");
         System.exit(1);
    }
    
    do 
    {
         run();
    }while (true);

  }
  
  synchronized private static void run()
  {
    Socket link = null;                        //Step 2.
    try 
    {
        link = servSock.accept(); 
        clientConnections  ;
        String client_ID = clientConnections   "";
        Runnable resource = new ClientConnectionRun(link, client_ID);
        Thread t = new Thread (resource);
        t.start();
        
    }
    catch(IOException e1)
    {
        e1.printStackTrace();
        try {
        System.out.println("\n* Closing connection... *");
            link.close();                   //Step 5.
    }
       catch(IOException e2)
       {
            System.out.println("Unable to disconnect!");
        System.exit(1);
       }
    }
  } // finish run method 
} // finish the class
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.tcpechoserverthreads;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.*;

/**
 *
 * @author Leepe
 */
public class ClientConnectionRun implements Runnable {
    Socket client_link = null;  
    String clientID;
    public static List<String> currentList = new ArrayList<String>();
    String[] parts;
    String part1;
    String part2;
    String part3;
    String message = "";
    
    public ClientConnectionRun(Socket connection, String cID) {
        this.client_link = connection;
        clientID = cID;     
  }
    
    @Override
    synchronized public void run() {
        try{
            
            BufferedReader in = new BufferedReader( new InputStreamReader(client_link.getInputStream())); //Step 3.
            PrintWriter out = new PrintWriter(client_link.getOutputStream(),true); //Step 3.
            
            System.out.println("\n* started connection with the client "   clientID   " ... *");

           while (!message.equals("Stop")){//Step 4.
                
                message = in.readLine(); 
                
               // out.flush();
                System.out.println("\n Message received from client: "   clientID   " - "  message);
                out.println("\n Echo Message: "   message);
                //out.flush();
                if(message.contains(";")){
                                        // String userinput = message;
                                        // String item = message;   
                                            

                                           // System.out.println("Contains ;");

                                            String[] parts = message.split(";");
                                            String part1 = parts[0]; 
                                            String part2 = parts[1];
                                            
                                            System.out.println(part1);
                                            System.out.println(part2);
                                            
                                            if(parts.length >= 3 && part1.equals("add")){
                                                String part3 = parts[2]; 
                                            
                                            

                                            System.out.println(part1);
                                            System.out.println(part2);
                                            System.out.println(part3);
                                            
                                            currentList.add(part2 " - " part3);
                                            //AddItem();

                                            }
                                           
                                            else if(parts.length <= 2 && part1.equals("list") ){ 
                                                
                                            
                                            System.out.println("list command working");
                                            //ListItem();
                                            
                                            System.out.println();
                                            System.out.println("----------------------");       
                                            System.out.println("To-Do List");
                                            System.out.println("----------------------");
                                            int number = 0;
                                             for (Iterator<String> it = currentList.iterator(); it.hasNext();) {
                                                
                                                message = it.next();
                                                 if(message.contains(part2)){
                                                     System.out.println(  number   " "   message);
                                                 }
                                             }
                                                System.out.println("----------------------");

                                            }
                                            else {
                                                System.out.println("\n Don't add a description if you are searching for a date");
                                            }
                                            
                                        }
                else if(!message.contains(";")){
                    System.out.println("\n Unknown command, Try using 'add' or 'list' followed by a ' ; ' as listed above ");
                }

           }
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
        
        finally 
        {
            try {
                System.out.println("\n* Closing connection with the client "   clientID   " ... *");
                client_link.close();                    //Step 5.
            }
            catch(IOException e)
            {
                System.out.println("Unable to disconnect!");
            }
        }
    }
}

I want the server to be able to output info to the client that's connected. What's happening is that the server will output the info eventually but requires me to enter several more inputs, i'm not sure how its delayed and any help would be appreciated.

CodePudding user response:

Leaving everything else untouched, simply changing your line out.println("\nEcho Message: " message); in your Class ClientConnectionRun to out.println("Echo Message: " message); will fix this.

Essentially, what goes wrong is that your line response = in.readLine(); in the client terminates when it encounters a line-feed. So, if you begin your response with a line-feed, it will terminate instantly and is thus always trailing by one line, which is why you will only see the actual response the next time you enter some input.

From the doc of java.io.BufferedReader.readLine():

Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), a carriage return followed immediately by a line feed, or by reaching the end-of-file (EOF).

Also, some general input:

You can drastically improve your code by using try-with-resources statements (since Java 8). This way you can avoid the "nasty" nested try-catch-finally constructs to handle your streams. For your Client for example you could simplify do:

 try (Socket link = new Socket(host, PORT);
             BufferedReader in = new BufferedReader(new InputStreamReader(link.getInputStream()));
             PrintWriter out = new PrintWriter(link.getOutputStream(), true);
             BufferedReader userEntry = new BufferedReader(new InputStreamReader(System.in))) {

And all you need at the end is this:

} catch (IOException e) {
    e.printStackTrace();
}
  • Related