【问题标题】:Java socket communication problemJava套接字通信问题
【发布时间】:2011-03-24 10:17:03
【问题描述】:

我正在使用 Java 进行套接字通信。服务器正在从客户端读取字节,如下所示:

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)

当客户端一次发送多条消息时出现问题,服务器混合消息,例如

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

所以消息 1 的尾部是消息 2 的一部分。 null 代表 java nul 符号。

为什么输入流混合消息?

提前致谢!

【问题讨论】:

  • 向我们展示通信双方的代码。

标签: java sockets inputstream


【解决方案1】:

您进行了错误的比较。您检查字符串中是否有 \0,然后相信它是一条消息。错误的。事实上,在第二个例子中,\0 出现了两次。

你应该做不同的事情。逐字符读取流中的字符(使用包装的 BufferedInputStream,否则性能会很糟糕),并在达到 \0 时跳过。现在消息已完成,您可以处理它了。

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())

更好的是使用换行符进行行分隔。在这种情况下,您可以只使用 BufferedReader 的 readline() 功能。

【讨论】:

  • 我曾经一次读取一个字节,但结果是速度很慢导致延迟。因此,我更改了代码以读取字节块。我也尝试了换行方法,但我遇到了问题,因为我在客户端站点上使用 Flash,并且在终止线路时出现问题。
  • @doorman,BufferedInputStream 为你做缓冲提高效率。
  • @Daniel,你确定c 可以是-1,因为它的未签名。 ;)
  • 经过一些实验后,我又遇到了延迟问题。似乎缓冲工作不正常。在我的项目中,连接了多个客户端,并且它们都每秒都在发送消息。在我在问题中编写的代码示例中读取大块字节时,这不是问题。我是否需要配置缓冲以便在逐字符读取流时处理更多流量?
  • @doorman:不,不管有多少客户,它都应该工作。也许错误在其他地方?使用 Wireshark 分析发送的数据并验证它是正确的。
【解决方案2】:

Sockets 和 InputStream 只是字节流,而不是消息。 如果您想根据\0 之类的字符拆分流,您需要自己执行此操作。

但是,在您的情况下,您的发送端似乎存在错误,因为 \0 不是正确的位置,并且极不可能成为客户端的错误。

顺便说一句:使用 String += 非常低效。

【讨论】:

  • String 是不可变的,因此在调用它的每个循环中,它都会获取原始字符串的副本,附加新字符串并创建组合字符串。请参阅@Daniel 的解决方案以获取替代方案。
【解决方案3】:

您从InputStream 读取的数据将进入,因为它可以从操作系统获得,并且无法保证将如何拆分。如果您希望在新行上拆分,您可能需要考虑这样的事情:

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

然后使用reader.readLine() 将每一行作为String 这是您的消息。

【讨论】:

  • 我尝试了 readline 方法,但我在客户端站点上使用 Flash,正确终止线路时出现问题。
  • 你能在消息之间发送任何东西来分隔它们吗?看来您现在完全依赖 XML。这将使在 Java 端拆分它们变得有点棘手。
【解决方案4】:

我认为你的问题在于你的方法:

客户端一次发送多条消息时出现问题

套接字通常只获取字节块,诀窍在于如何发送它们,如何标记消息的开始/结束以及如何检查错误(快速哈希可以做很多好事)所以在我看来,这种行为很好,如果你真的需要一次发送多条消息,你只需要处理你的消息。

套接字将控制您的消息是否在物理方面是完整的,但消息中的内容是您关心的。

【讨论】:

  • 我正在客户端站点上使用 0 来终止消息
  • 我建议用一个开始字符来包装每条消息,然后是消息内容的快速散列,然后是消息,最后是结束字符。然后,您可以通过哈希识别每条消息的开始/停止(将其视为消息的标签),如果哈希与您得到的不正确,那么您可以要求客户端重新发送,如果您可以与客户端通信。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
  • 2015-10-15
  • 2016-09-25
  • 2021-06-20
  • 1970-01-01
相关资源
最近更新 更多