hideburn
hideburn

Reputation: 436

Client doesn't get response message until the server closes the connection (Java)

My colleague and I were working on a client application that communicates with the web service in order to process some transaction data. These are steps in our communication:

  1. Client application initiates the connection and sends the request message (timestamp = T1)
  2. Web service accepts the connection and processes the request (timestamp ≈ T1)
  3. Web service returns the response message (timestamp = T1 + few_seconds)
  4. Web service closes the connection (timestamp = T1 + 3_minutes)
  5. Client application gets the response message and proceed with data parsing (timestamp = T1 + 3_minutes)

Our problem lies in the timestamp references: The web service process the request and retrieves the response almost immediately but the client application does not get the response message until the server closes the connection. Here are log files:

Client application log snippet:

10:46:25,031 INFO  MessageHandler.java:115 Message sent.
10:49:25,071 INFO  MessageHandler.java:125 Message received.
10:49:25,103 DEBUG  MessageParser.java:67 Message parsed.

Server application log:

10:46:25:153 <INFO>   Client connection accepted.
...
10:46:26:602 <INFO>   Response message sent.
...
10:49:25:069 <INFO>   Closing connection...

As you can see, client gets the response only when the server closes the connection.

Here is the client app code of the method where the communication is done:

public static String sendMsg(byte[] msg, String serverIp, int port) {
    try {
            InetAddress address = InetAddress.getByName(serverIp);
            Socket socket = new Socket(address, port);
            OutputStream os = socket.getOutputStream();

            logger.info("Message sent.");

            os.write(msg, 0, msg.length);
            os.flush();

            InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String msgReceived = br.readLine();

            logger.info("Message received.");
            os.close();
            return msgReceived;
        } ...(catch blocks) ... 
}

Suppose that we can't change the web service implementation, is there a way to get the response message on the client side immediately when the service initiates the response (and then to close the connection by client) ? Thanks in advance.

Upvotes: 1

Views: 3705

Answers (3)

David Schwartz
David Schwartz

Reputation: 182753

Most likely, the client is not properly implementing the message protocol. For example, the client calls readLine. Does the message protocol specify that the message is a line? If not, readLine will keep waiting until the connection closes, still trying to get that line that was never going to be sent.

The client will be unable to find the end of a message unless it understands how a message is delimited. How is a message delimited in your protocol? Where is the client code to detect the end of a message? If you didn't write it, it won't happen.

Upvotes: 3

Gil Hamilton
Gil Hamilton

Reputation: 12347

As @Yeroc suggested, it seems likely that the web server is buffering its response and not flushing the buffer until some timeout occurs. (This strikes me as a poor design choice on the server side but if you have no control over the server, presumably you're stuck with it.)

I would try doing a shutdown(SHUT_WR) on the client side. This should produce an "end of file" indication in the server which would presumably lead it to flush its buffer and close the connection. Since that's exactly what you want to happen, that may get you your response more quickly. The shutdown with SHUT_WR only shuts down the connection in one direction -- the client-to-server direction -- so you should still be able to receive the response.

(It's possible the server could choose to close without flushing, but it seems likely that flushing the buffer is being done as a side-effect of a high-level close call on the server side so it's definitely worth a try.)

Upvotes: 1

Yeroc
Yeroc

Reputation: 1111

It sounds unlikely there's anything you can do about this from the client-side. What's probably happening is the web server is buffering the response from the webservice (so it can set content length headers etc.) so until the webservice closes the connection no data is sent. You can indirectly test this hypothesis by using the br.read() method to read a single character of data instead of a whole line at a time as you are now.

Upvotes: 1

Related Questions