Reputation: 1961
I want to send a command to a server, and find out if I get a response.
Right now i am using BufferedReader
's readline()
function, which blocks until there's a response from server, but all I want to do is verify that there's a response from the server in the first place.
I tried using ready()
or reset()
to avoid this block, but it doesn't help.
This is causing my program to get stuck waiting for the server to respond, which never happens. InputStreamReader
seems to do the same thing, by my understanding of things.
Other questions I found here on the subject didn't answer my question, so please if you can answer my question it will be great.
Upvotes: 3
Views: 7269
Reputation: 3736
It's a tricky task not get blocking if you use standard java IO. Common answer is migration to NIO or netty. Netty is more preferable choice. However sometimes you don't have a choice so I suggest you to try my workaround:
public String readResponse(InputStream inStreamFromServer, int timeout) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(inStreamFromServer, Charsets.UTF_8));
char[] buffer = new char[8092];
boolean timeoutNotExceeded;
StringBuilder result = new StringBuilder();
final long startTime = System.nanoTime();
while ((timeoutNotExceeded = (TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) < timeout))) {
if (reader.ready()) {
int charsRead = reader.read(buffer);
if (charsRead == -1) {
break;
}
result.append(buffer, 0, charsRead);
} else {
try {
Thread.sleep(timeout / 200);
} catch (InterruptedException ex) {
LOG.error("InterruptedException ex=", ex);
}
}
}
if (!timeoutNotExceeded) throw new SocketTimeoutException("Command timeout limit was exceeded: " + timeout);
return result.toString();
}
This workaround isn't a silver bullet but it has some important feature:
LF/CR
symbols and your code will be stuck. When you read from a file it isn't critical you will reach end of the file anyway.char symbol = (char) fr.read();
. This approach is slower than reading to char[]Upvotes: 1
Reputation: 2465
I did something similar recently using a CountDownLatch. There may be some better ways, but this is pretty easy, and seems to work reasonably well. You can adjust the wait tome of the CountDownLatch to suit your needs.
package com.whatever;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestRead {
private static final Logger log = LoggerFactory.getLogger(TestRead.class);
private CountDownLatch latch = new CountDownLatch(1);
public void read() {
URLReader urlReader = new URLReader();
Thread listener = new Thread(urlReader);
listener.setDaemon(true);
listener.start();
boolean success = false;
try {
success = latch.await(20000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
log.error("error", e);
}
log.info("success: {}", success);
}
class URLReader implements Runnable {
public void run() {
log.info("run...");
try {
URL oracle = new URL("http://www.oracle.com/");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
latch.countDown();
} catch (Exception ex) {
log.error("error", ex);
}
log.info("consumer is done");
}
}
public static void main(String[] args) {
TestRead testRead = new TestRead();
testRead.read();
}
}
Upvotes: 0
Reputation: 533492
If you want to read responses asynchronously, I suggest starting a thread which read a BufferedReader. This is much simpler to code and easier to control.
Upvotes: 3
Reputation: 4000
May be all you need is the InputStream
without wrapping it in a BufferedReader
while (inputStream.available() > 0) {
int i = inputStream.read(tmp, 0, 1024);
if (i < 0)
break;
strBuff.append(new String(tmp, 0, i));
}
I hope this helps.
Upvotes: 1