3

这是一个有点晦涩的问题,似乎只在我使用某些计算机时才会发生。我今天在我们学校的 XP 计算机上遇到了这个问题,我似乎无法在我的家用计算机 (W7) 上复制它。

无论如何,每当我使用此代码(其中:)时,在 Java 中读取/写入套接字往往会出现问题int avail, InputStream socket, byte[] buffer, String output

                   while( (avail = input.available()) > 0 )
                    {
                        read = input.read( buffer );
                        output += new String( buffer, 0, read );
                    }

这似乎是有道理的(读取所有数据,直到没有数据可用于临时缓冲区,然后是字符串),但在我们学校的计算机上(使用 IE7 测试它),整个事情不知何故暂停了。我在想 input.available() 导致它以某种方式阻塞,因为线程只是继续运行而没有到达端点......实际上只是在某处暂停。

哦,我忘了提一下:每当我在调试模式下运行它并逐步执行每一行时,它完全像它应该的那样工作......这让我更加困惑。

当我回到家复制这个问题时,它工作得很好(只使用 Firefox 和 IE8)。我不知道有什么更好的选择。

PS:如果缓冲区足够大,我只是使用:

                    read = input.read( buffer );
                    output += new String( buffer, 0, read );

它工作得很好,但总是担心发送的数据会超过缓冲区大小。

4

3 回答 3

3

你在想available()错误的方法。该方法告诉您现在可以读取大约多少字节,而不会阻塞。对于您正在尝试做的事情,普遍接受的成语是

int length;
while ((length = in.read(buffer)) != -1) {
    output += new String(buffer, 0, length);
}

或类似的东西(未编译/测试)。

更新:我认为您误解了“流结束”的概念。“流的结束”并不意味着您要读取的所有数据都已被读取。这意味着没有,也永远不会有其他可阅读的内容。例如,这可能意味着您正在读取一个文件并且已经结束,或者这可能意味着您正在从内存中的字节数组中读取并且已经结束。这些是“流的结束”。

在您的问题中,您表示或至少暗示您正在从 Socket 读取。您是否知道在关联的 Socket 或连接的远程端关闭之前,您永远不会到达该流的末尾?仅仅因为您从它那里收到了一些数据并不能使它成为流的结尾。

于 2012-05-22T02:26:15.387 回答
1

为什么不使用缓冲阅读器?就像是:

    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    String output = "";
    try {
        String readLine = null;
        while ((readLine = reader.readLine()) != null) {
            output += readLine + "\n";
        }
    } catch (IOException e) {
        System.err.println("Error: " + e);
    }
    System.out.println("Read from Socket:" + output);
于 2012-05-22T02:31:57.517 回答
1

您的代码无效。这是对available(). 它所做的只是告诉你有多少字节可用于读取而不阻塞。它不能用于指示对等方将发送多少字节,并且它与对等方消息没有必然关系。TCP 中没有消息,只有一个字节流。如果要读取 EOS,只需删除available()测试并读取,直到它返回 -1。如果您想阅读一条消息,对等方将不得不以某种方式为您划界,例如通过带外终止符、长度词前缀或自描述协议(如对象序列化或 XML)。

它在调试模式下“工作”,因为您正在从根本上改变断点的时间。这进一步证明了您所做的事情是不正确的。

于 2012-05-22T03:41:29.760 回答