Question

I am writing simple Server through TCP/IP for my android app.

I am facing a problem where server only receives messages after the timeout on the app.

My server side:

            System.out.println("Connection accepted");
            
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
            capitalizedSentence = "READY";
            
            writeToUser(outToClient, "READY".getBytes());

            String response = readFromUser(connectionSocket); 
                // Server hangs on readFromUser();  
            
            if(response.contains("IL"))
            {
               byte[] bytes = DatatypeConverter.parseHexBinary(foo);
               writeToUser(outToClient, bytes);
            }

App side:

            if (ack.equals("READY")) {
                ack = "";
                dataOutputStream.writeBytes(command);
                dataOutputStream.flush();
                
                buf = new byte[556];
                dataInputStream.read(buf);
                                    // app hangs on read() and gets timeout
            }

The problem is that, server receives command only after application gets read timeout.

My current scenario is this:

  1. Connection accepted: Application receives "READY"

  2. Application sends commands and tries to read response from server

  3. Server is hanging on readFromUser() and only receives message after the app gets read timeout.

    Any ideas what am I doing wrong ?

Update:

The code works if I use readLine, instead of read(buf) ( if I understand clearly server hangs on read(buf) and is in waiting mode as socket is not closed yet even though no more data is beeing sent. )

However such way I have to add "\n" after each command, and server is only emulator, app works with different device who does not understand "\n" at the end and will crash. Is there any way I could make this work without using readLine() ?

Update 2

   public void writeToUser(DataOutputStream outToClient, byte[] bytes) throws IOException 
   {
       outToClient.write(bytes);
       outToClient.flush();
       String s = new String(bytes);
       
       writeLog("Sent to client: " + s);
   }
   
   public String readFromUser(Socket socket) throws IOException, InterruptedException
   {
        writeLog("Reading...");
        
        BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String clientSentence = inFromClient.readLine();
               
        writeLog("Received: " + clientSentence);
        return clientSentence;
   }

Above readFromUser() method works just as expected. But, this requires adding "\n" on each command sent from client app. And real device I have to communicate with does not understand "\n" and will treat the command as unrecognized... I am writing this server simply for testing purposes and I want it to be as close to real one as possible.

Previously I was just trying to get it done without "\n" on each command using inFromClient.read(cbuf); instead of readLine() and server always got hung on read, and received command only after socket was closed on client side. Even though I know that client sent the command and is waiting for response.

The question is how can I receive command without using readLine(); and "\n" on client side.

Was it helpful?

Solution

'how can I receive command without using readLine(); and "\n" on client side'. If you do not, or can not, want to use "\n" as a command terminator, then you must use another protocol to identify the start and end of the 'command' within the TCP octet/byte stream.

What protocol does your 'real device' server use to identify the start and end of commands? If it uses a byte-by-byte state-machine to identify a valid command then you are going to have to duplicate that in your test server.

OTHER TIPS

You're reading lines but you aren't writing lines. So readLine() blocks until a line terminator arrives or the peer closes the connection.

Append a \n.

Why not you increase timeout from APPs side. Or you can write a thread that will hit server in some interval for some time and if no response then show time out. This problem is in Apps side.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top