java Java在服务器和客户端之间发送没有换行符的消息
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17710625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java sending message between server and client without newline character
提问by Genesist
I have a client which is connecting to a server. The server and the client exchange datas in string format. The problem is that, the server does not take '\n' character at the end of the message and because of this the client blocked in readLine()
method. Unfortunately the server-side can't be changed. How can read from stream that kind of message which does not have '\n' at the end?
我有一个连接到服务器的客户端。服务器和客户端以字符串格式交换数据。问题是,服务器在消息的末尾没有使用 '\n' 字符,因此客户端在readLine()
方法中被阻塞。不幸的是,服务器端无法更改。如何从流中读取末尾没有 '\n' 的那种消息?
My client code:
我的客户代码:
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();
}
}
}
}
采纳答案by fmodos
You can try to use readyand read(char c)methods. Here is one example:
您可以尝试使用ready和read(char c)方法。这是一个例子:
StringBuffer sb = new StringBuffer();
while (br.ready()) {
char[] c = new char[] { 1024 };
br.read(c);
sb.append(c);
}
回答by fvu
The easiest solution is to read the message character per character, but the main problem here is to know when the message is complete. In a line-oriented protocol this is simple, the newline that was sent is the "separator" between messages. Without, there are two possible situations where this problem is easy to solve:
最简单的解决方案是读取每个字符的消息字符,但这里的主要问题是知道消息何时完成。在面向行的协议中,这很简单,发送的换行符是消息之间的“分隔符”。如果没有,有两种可能的情况可以轻松解决此问题:
Case 1: the message always has a fixed character at the end, that can't occur in the message
情况 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();
Case 2: the message has a fixed length
情况二:消息有固定长度
// 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();
In both cases you'll have to add some code to check the sanity of what you received, you may have received EOF during read.
在这两种情况下,您都必须添加一些代码来检查收到的内容的完整性,您可能在阅读过程中收到了 EOF。
If there is no obvious message separator and message have a variable length it will be a lot harder.
如果没有明显的消息分隔符并且消息具有可变长度,那将会困难得多。
回答by Tim Boudreau
The point of readLine()
is to read data where it really is guaranteed that the input will end with a newline. Generally, when parsing input, there has to be some token- some character or combination of characters in the input, which you can use to decide whether to
重点readLine()
是在真正保证输入将以换行符结尾的地方读取数据。通常,在解析输入时,必须有一些标记- 输入中的某些字符或字符组合,您可以使用它来决定是否
- Wait for more input
- Do something with the information you've gotten already
- And possibly decide whether to go back to waiting for more input afterwards
- 等待更多输入
- 用你已经获得的信息做一些事情
- 并可能决定之后是否返回等待更多输入
If you cannot guarantee that a newline will be sent, then readLine()
is the wrong tool for the job. Use something like the character-array read methodof InputStreamReader
instead. You will have to iterate the array of characters you read in, and figure out when you have enough input to work with. You could also use the one-character-at-a-time read()
method of InputStreamReader
which will result in simpler but probably less efficient code.
如果您不能保证会发送换行符,则readLine()
是该工作的错误工具。使用类似的字符阵列的读取方法的InputStreamReader
替代。您必须迭代读入的字符数组,并确定何时有足够的输入来处理。您还可以使用一次一个字符的read()
方法,InputStreamReader
这将导致更简单但效率可能较低的代码。
If you use the character-array version of read()
, and if you go back to collecting input after parsing some, don't forget to put whatever is left over when you do get enough to parse back into the queue to handle on the next round.
如果您使用 的字符数组版本read()
,并且如果您在解析一些输入后返回收集输入,请不要忘记在您获得足够的解析回队列以处理下一轮时将剩余的任何内容放入。