我正在编写一个简单的Java客户机/服务器应用程序供我自己使用。它应该允许客户端发送单行文本消息和读取多行响应。这种通信应该使用相同的连接可重复多次。
这是我在客户端读取响应的内容:
BufferedReader input = new BufferedReader(new InputStreamReader(server.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
// processing here
}
这样做的问题是,一旦服务器发送第一个响应,readLine()就会阻塞,因此客户端无法发送新消息。这是可以理解的。一种简单的解决方案可能是通过发送某种已知的特殊字符串值来让服务器发出其输出结束的信号,客户机随后将识别该字符串值并结束读取循环。然而,这个问题有没有更好的解决方案呢?
由于您的客户端应该读取来自同一连接的多个多行响应并处理每个响应块,这可能对您的情况有用:
BufferedReader input = new BufferedReader(new InputStreamReader(server.getInputStream()));
String line;
StringBuilder sb = new StringBuilder();
while ((line = input.readLine()) != null) {
if (line.equals("~~/START/~~"))
sb = new StringBuilder();
else if (line.equals("~~/END/~~")) {
doSthWithParagraph(sb.toString());
sb.delete(0, sb.length());
} else
sb.append(line);
}
您可以使用自己的特殊字符串来识别每个消息块的开始和结束
我不会为你的主循环依赖readLine
,因为readLine
依赖于"未来"数据(CR,或LF,或CR+LF,并返回null,如果流的结束已经到达)。因此,如果CR后面没有LF, BufferedReader
就会卡住。此readLine
方法更适合于读取文件内容。
在你的例子中,我会用
一次读取一个字符while ((myChar = input.read()) != -1) {
// processing here, storing information in a buffer and taking appropriate actions if
// A CR or LF is found
}
但是即使这种行为也是可疑的,因为Unicode字符可以超过一个字节,所以如果发送了第一个字节而不是第二个字节,流可能会卡住。你确定你的通信是Unicode吗?如果没有,InputStream
会比Reader
更合适。