我有一个连接到服务器的客户端。服务器和客户端以字符串格式交换数据。问题是,服务器在消息末尾没有'\ n'字符,因此客户端在readLine()
方法中被阻止。不幸的是,服务器端无法更改。如何从流中读取那种最后没有'\ n'的消息?
我的客户代码:
public class json
{
private static Socket socket;
public static void main(String args[])
{
String sendMessage = "";
Gson gson = new Gson();
JSON_package authentication = new JSON_package();
authentication.setType("Identifying");
authentication.setSource("exampleClient");
Package_Parser pp = new Package_Parser();
sendMessage = gson.toJson(authentication);
sendMessage = authentication.buildPackage(sendMessage);
try
{
String host = "host_address";
int port = port_number;
InetAddress address = InetAddress.getByName(host);
System.out.println("Connecting.");
socket = new Socket(address, port);
System.out.println("Connected.");
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+sendMessage);
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
StringBuffer buffer = new StringBuffer();
String message = br.readLine();
message = pp.Parser(message);
System.out.println("Message received from the server : " +message);
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
//Closing the socket
try
{
socket.close();
System.out.println("Closed.");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
答案 0 :(得分:4)
您可以尝试使用ready和read(char c)方法。 这是一个例子:
StringBuffer sb = new StringBuffer();
while (br.ready()) {
char[] c = new char[] { 1024 };
br.read(c);
sb.append(c);
}
答案 1 :(得分:1)
最简单的解决方案是读取每个字符的消息字符,但这里的主要问题是知道消息何时完成。在面向行的协议中,这很简单,发送的换行符是消息之间的“分隔符”。没有,有两种可能的情况,这个问题很容易解决:
案例1:消息总是在末尾有一个固定的字符,这在消息中不会出现
// let's pretend ! is the end of message marker
final char endMarker = '!';
// or of course StringBuffer if you need to be treadsafe
StringBuilder messageBuffer = new StringBuilder();
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
char c = (char)value;
// end? jump out
if (c == endMarker) {
break;
}
// else, add to buffer
messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();
案例2:消息具有固定长度
// let's pretend message is always 80 long
int messageLength = 80;
StringBuilder messageBuffer = new StringBuilder();
int charactersRead = 0;
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
char c = (char)value;
// end? jump out
if (++charactersRead >= messageLength) {
break;
}
// else, add to buffer
messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();
在这两种情况下,您都必须添加一些代码来检查您收到的内容的完整性,您可能在阅读期间收到了EOF。
如果没有明显的消息分隔符,并且消息的长度可变,那将会更加困难。
答案 2 :(得分:0)
readLine()
的目的是读取数据,确保输入以换行结束。通常,在解析输入时,必须有一些标记 - 输入中的某些字符或字符组合,您可以使用它来决定是否
如果您无法保证会发送换行符,则readLine()
是错误的工具。请改用InputStreamReader
的字符数组read method之类的内容。您将不得不迭代您读入的字符数组,并找出何时有足够的输入来处理。您还可以使用read()
一次性InputStreamReader
方法,这将导致代码更简单但效率更低。
如果你使用read()
的字符数组版本,如果你在解析一些之后回去收集输入,不要忘记把剩下的东西放到你得到足够的东西来解析回来排队等待下一轮。