我想向服务器发送命令,并找出我是否得到响应。
现在我正在使用BufferedReader
的readline()
函数,它会阻塞直到服务器响应,但我只想首先验证是否有来自服务器的响应。
我尝试使用ready()
或reset()
来避免此块,但它没有帮助。
这导致我的程序卡在等待服务器响应时卡住,这永远不会发生。 根据我对事物的理解,InputStreamReader
似乎也在做同样的事情。
在这里找到的关于这个主题的其他问题没有回答我的问题,所以如果你能回答我的问题,那就太好了。
如果你想异步读取响应,我建议启动一个读取 BufferedReader 的线程。 这更容易编码和控制。
您可能只需要InputStream
,而无需将其包装在BufferedReader
while (inputStream.available() > 0) {
int i = inputStream.read(tmp, 0, 1024);
if (i < 0)
break;
strBuff.append(new String(tmp, 0, i));
}
我希望这有所帮助。
如果您使用标准Java IO,则不会阻塞是一项棘手的任务。常见的答案是迁移到NIO或netty。内蒂是更可取的选择。但是,有时您别无选择,因此我建议您尝试我的解决方法:
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();
}
此解决方法不是灵丹妙药,但它具有一些重要功能:
- 不使用 readline()。此方法对于网络通信很危险,因为某些服务器不返回
LF/CR
符号,并且您的代码将被卡住。当您从文件中读取时,无论如何您都会到达文件的末尾并不重要。 - 不使用
char symbol = (char) fr.read();
.这种方法比读取字符[] 慢 - 它具有超时功能,您可能会在慢速连接时中断通信
我最近使用CountDownLatch做了类似的事情。可能有一些更好的方法,但这很容易,而且似乎工作得很好。您可以调整 CountDownLatch 的等待时间以满足您的需求。
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();
}
}