使用 DataInputStream 读取的 TCP 套接字的字节前面不需要的 NUL 字符



我正在编写一个Android应用程序,该应用程序涉及连接到TCP服务器(我也编写了)并从中发送/接收文本。现在我在最终阅读(客户端)中有一个错误。

当我在 Eclipse 中使用调试器时,它显示我正在接收发送的所有字节,但对于某些文本片段,如果我期望 n 个字节,我将获得第一个 n - k,一些 m NUL 字节,然后是最后的 k - m 个有意义的字节。如果我正确解释问题,Java 会看到大量的 0,并决定之后没有任何有用的内容可读(调试器显示字节数组和它转换为的字符串,但如果我尝试进一步检查它,则将其丢弃)。

我怎么能忽略 NUL 的大量涌入,只阅读重要的东西?

// Find out how many bytes we're expecting back
int count = dis.readInt(); // dis is a DataInputStream
dos.writeInt(count); // dos is a DataOutputStream
// Read that many bytes
byte[] received = new byte[count];
int bytesReceived = 0;
int bytesThisTime = 0;
while (-1 < bytesReceived && bytesReceived < count) {
    bytesThisTime = dis.read(received, 0, count);
    if (bytesThisTime <= 0) break;
    bytesReceived += bytesThisTime;
    String bytesToString = new String(received, 0, bytesThisTime, "UTF-8");
    sb_in.append(bytesToString);
    received = new byte[count];
}
in = sb_in.toString();

下面是正在编写的服务器代码:

            // Convert the xml into a byte array according to UTF-8 encoding
            // We want to know how many bytes we're writing to the client
            byte[] xmlBytes = xml.getBytes("UTF-8");
            int length = xmlBytes.length;
            // Tell the client how many bytes we're going to send
            // The client will respond by sending that same number back
            dos.writeInt(length);
            if (dis.readInt() == length) {
              dos.write(xmlBytes, 0, length); // All systems go - write the XML
            }
            // We're done here
            server.close();

替换:

String bytesToString = new String(received, "UTF-8");

跟:

String bytesToString = new String(received, 0, bytesThisTime, "UTF-8");

基本上dis.read(received, 0, count)可以返回 0 到 count 之间的任意数量的字节。 bytesThisTime告诉您这次读取了多少字节。但稍后您使用整个数组,而不仅仅是实际读取的部分。

顺便说一句,考虑使用 InputStreamReader 它会为您即时解码字符串(但count会有不同的语义)。此外,请仔细阅读IOUtils API。

Java看到了大量的0,并决定之后没有什么有用的东西可以阅读

不。Java根本不看数据,更不用说做出这样的语义决策了。

我怎么能忽略 NUL 的大量涌入,只阅读重要的东西?

没有"大量涌入的NUL"可以忽视。Java不这样做,TCP不这样做,什么都不做。

你自己的代码中只有编程错误。

我可以无休止地详细介绍这些内容,但本质上你应该使用 DataInoutStream.readFull(),而不是尝试用你自己的错误缠身的版本复制它。

相关内容

  • 没有找到相关文章

最新更新