简体   繁体   English

Java套接字通信问题

[英]Java socket communication problem

I am using Java for socket communication. 我正在使用Java进行套接字通信。 The server is reading bytes from the client like this: 服务器正在从客户端读取字节,如下所示:

InputStream inputStream;
final int BUFFER_SIZE = 65536;
byte[] buffer = new byte[BUFFER_SIZE];
String msg="";

while (msg.indexOf(0)==-1 && (read = inputStream.read(buffer)) != -1)
{
    msg += new String(buffer, 0, read);
}
handleMessage(msg)

There is a problem when a client is sending multiple messages at once the server mixes the messages eg 当客户端在服务器混合消息时一次发送多个消息时,会出现问题

MSG1: <MyMessage><Hello/>nul
MSG2: </MyMessage><MyMessage><Hello again /></MyMessage>nul

So the tail of Message 1 is part of Message 2. The null represents the java nul symbol. 因此,消息1的尾部是消息2的一部分。null表示java nul符号。

Why does the inputstream mix the messages? 为什么输入流会混合消息?

Thanks in advance! 提前致谢!

You are doing the wrong comparison. 您做错了比较。 You check if there is a \\0 anywhere in the String, and then believe it is a single message. 您检查字符串中的任何地方是否有\\ 0,然后认为它是一条消息。 Wrong. 错误。 In fact, in the second example, the \\0 comes twice. 实际上,在第二个示例中,\\ 0出现两次。

You should do it differently. 您应该以其他方式进行操作。 Read from the Stream in char by char (Using a wrapping BufferedInputStream, else the performance will be awful), and skip when the \\0 is reached. 从char中以char形式从Stream中读取(使用包装的BufferedInputStream,否则性能将很糟糕),并在达到\\ 0时跳过。 Now the message is complete, and you can handle it. 现在消息已完成,您可以处理它。

InputStream bin = new BufferedInputStream(inputStream);
InputStreamReader reader = new InputStreamReader(bin);
StringBuilder msgBuilder = new StringBuilder();
char c;
while ( (c=reader.read()) != -1 ) 
{
    msgBuilder .append(c);
}
handleMessage(msgBuilder.toString())

Even better would be using the newline character for line separation. 最好使用换行符进行行分隔。 In this case you could just use the readline() functionality of BufferedReader. 在这种情况下,您可以只使用BufferedReader的readline()功能。

Sockets and InputStream are only a stream of bytes, not messages. 套接字和InputStream只是字节流,而不是消息。 If you want to break up the stream based on a char like \\0 you need to do this yourself. 如果要基于\\0这样的字符分解流,则需要自己执行此操作。

However, in your case it appears you have a bug on your sending side as the \\0 isn't the right places and it is highly unlikley to be a bug on the client side. 但是,在您的情况下,您似乎在发送方遇到了一个错误,因为\\0位置不正确,并且在客户端很容易成为错误。

btw: Using String += is very inefficient. 顺便说一句:使用字符串+ =效率很低。

The data you read from InputStream will come in as it's available from the OS and there's no guarantee on how it will be split up. InputStream读取的数据将随操作系统一起提供,并且无法保证如何拆分。 If you're looking to split on new lines you might want to consider something like this: 如果您希望分拆新行,则可能需要考虑以下内容:

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

And then use reader.readLine() to get each line as a String that's your message. 然后使用reader.readLine()将每一行作为String ,这就是您的消息。

I think your problem is in your approach: 我认为您的问题出在您的方法中:

There is a problem when a client is sending multiple messages at once 客户端一次发送多个消息时出现问题

Sockets in general just get chunks of bytes and the trick is in how you send them, how do you mark start/end of a message and how do you check it for errors (quick hash can do a lot of good) so the behaviour is fine in my eyes, you just need to work on your messaging if you really need to send multiple messages at once. 套接字通常只获取大块字节,窍门在于如何发送它们,如何标记消息的开始/结束以及如何检查错误(快速哈希可以做很多事情),因此该行为是在我看来,如果确实需要一次发送多封邮件,则只需要处理邮件即可。

Sockets will control if your message is integral physical wise but what is IN the message is your concern. 套接字将控制您的消息是否是完整的物理方法,但是消息中所涉及的是您的关注。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM