如何解析通过TCP收到的损坏的消息

时间:2011-01-03 10:05:33

标签: java sockets networking tcp

我正在使用套接字从客户端应用程序向我的服务器应用程序发送一个字符串消息。我正在使用DataOutputStream从客户端和DataInputStream发送以在我的服务器中接收消息。我从客户端发送一个字符串,但我注意到,当它到达服务器时,它有时会被分成几个消息。我该如何处理这个问题或者处理这个问题的最佳方法是什么?

我可能会读取收到的每条损坏的消息,并检查每个字符的分隔符,以确定它是一条消息的结尾。但是有更好的方法来解决这个问题吗?

3 个答案:

答案 0 :(得分:3)

TCP中没有“消息”这样的东西。它是一种面向流的协议。当然,在较低级别,它在单独的数据包中传输,但您无法控制它,您所看到的可能与这些数据包不同。您只需在任何特定时刻读取接收缓冲区中的可用内容即可。您可能会将您的消息视为已故,但您可能会遇到多条消息合并为一个消息的情况。

因此,在阅读邮件时,您应该使用某种分隔符来确定邮件的结束位置,或使用带有邮件长度的标头。如果要发送简单字符串,将它们编码为UTF-8并使用空字节终止它们应该可以正常工作。对于更复杂的事情,显然你需要更复杂的方法。

答案 1 :(得分:0)

虽然要为邮件添加标题前缀?发送带有传输长度和校验和的标头是很常见的。这样,您就可以分配适当大小的缓冲区并验证数据完整性。

答案 2 :(得分:0)

首先发送长度的简单示例。注意:我在读取时检查长度,因为无效的消息长度可能导致OutOfMemoryException,这可能会引起混淆/警告。

public static void writeBytes(DataOutput out, byte [] bytes) throws IOException {
    out.writeInt(bytes.length);
    out.write(bytes);
}

public static byte[] readBytes(DataInput in) throws IOException {
    int len = in.readInt();
    if (len < 0 || len > 1 << 24) throw new StreamCorruptedException("Invalid message length "+len);
    byte [] bytes = new byte[len];
    in.readFully(bytes);
    return bytes;
}