7

我的问题在于以下假设,我希望这些假设是正确的,因为当我在谷歌搜索我的问题时阅读它们时,我相信这些假设:

  1. 关闭套接字的 OutputStream 也会关闭套接字
  2. OutputStream 的 flush() 方法什么都不做

因此,无论如何,我基本上都需要将数据从我的 OutputStream 对象中刷新出来,以使我的应用程序能够正常工作。

如果您对详细信息感兴趣,请查看以下两个链接:

. 奇怪的行为:将图像从 Android 手机发送到 Java 服务器(代码工作)

此问题已通过关闭 OutputStream 得到解决。这样做会将所有数据刷新到套接字的另一端,并使我的应用程序进一步工作,但这个修复很快引发了问题 2 - 相应的套接字也被关闭:

. SocketException - “套接字已关闭”,即使 isConnected() 返回 true

4

7 回答 7

6

您可以调用 OutputStream 的 flush 方法而不是 close。从 OutputStream 继承的具体类将覆盖 flush() 以执行其他操作(将数据写入文件或通过网络发送)。

于 2012-04-15T22:31:56.527 回答
3

OutputStream 的 flush() 方法什么都不做。

这是不正确的。

确实,类flush()提供的基本实现OutputStream什么都不做。但是,您的应用程序将调用您正在使用的实际流类提供的该方法的版本。如果流类没有直接写入语义,它将覆盖flush()以执行所需的操作。

简而言之,如果需要刷新(并且Socket输出流需要刷新),那么调用flush()将做正确的事情。(如果某些互联网资源告诉您否则它要么是错误的,要么是您误解了它。)


仅供参考,基础OutputStream实现flush()为无操作的原因是:

  • 一些输出流类在刷新时不需要做任何事情;例如ByteArrayOutputStream,和
  • 对于flush()不是无操作的流类,无法在基类级别实现操作。

他们可以(理论上)将流 API 设计为OutputStream抽象类(和flush()抽象方法)或接口。然而,这个 API 在 Java 1.0 之前就被有效地冻结了,当时没有足够的实际 Java 编程经验来意识到 API 设计是次优的。

于 2012-04-16T00:13:02.450 回答
1

关闭套接字的 OutputStream 也会关闭套接字

真的。

OutputStream 的 flush() 方法什么都不做

错误的。有覆盖。请参阅 Javadoc 中的FilterOutputStream.flush(),BufferedOutputStream.flush()​​ , ObjectOutputStream.flush(), 等等。

所以你最初的问题是不存在的,所以你不需要导致问题 #2 的“解决方案”。

于 2012-04-15T22:30:48.710 回答
0

我有同样的问题。在流的末尾添加“\n”。刷新有效,但命运不知道消息是否结束

于 2014-01-29T09:04:55.137 回答
0

我会试一试。我遇到了同样的问题。关闭输出流是我可以“刷新”数据的唯一方法。但因为我仍然需要不是一个选项的输出流。所以第一次我发送字节数组长度,out.writeInt,然后是数组本身。当所有字节都被读取时,即 buffer.length == in.readInt() 我打破循环

    ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    byte[] fileBytes;
    int n;
    int length;

    try
    {
        size = in.readInt();

        while((n = in.read(buffer)) != -1)
        {
            dataBuffer.write(buffer, 0, n);

            if(dataBuffer.toByteArray().length == length)
            {
                fileBytes = dataBuffer.toByteArray(); break;
            }
        }
    }
于 2013-08-24T17:28:25.897 回答
0

YES on Android flush() 什么都不做(基于 api 23 的示例)

public Socket() {
    this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl();
    this.proxy = null;
}

public class PlainSocketImpl extends SocketImpl {

    @Override protected synchronized OutputStream getOutputStream() throws IOException {
        checkNotClosed();
        return new PlainSocketOutputStream(this);
    }


}

private static class PlainSocketOutputStream extends OutputStream {
        // doesn't override base class flush();
}

要在不关闭套接字的情况下刷新输出流,您可以关闭输出:

protected void shutdownOutput() throws IOException

-- 这将关闭 WRITE 文件描述符。

除了使用输出流,您可以直接写入文件描述符或通过使用 OutputStream 创建自己的 Socket 实现,这将覆盖刷新方法(例如,在 c 中使用Berkeley 套接字实现(通过本机调用)。

于 2016-06-20T20:36:23.720 回答
-1

你真的需要冲洗吗?我还有一个问题,c# 服务器上的侦听器无法接收从 android 发送的数据(我试图同步获取数据)。

我确信这是因为在 Android 端,以下代码没有刷新。

OutputStream str = btSocket.getOutputStream();
str.write(data_byte);
// "This implementation does nothing"
str.flush();

事实证明,如果我在服务器的侦听器上使用异步数据检索 - 它会获取数据,并且不需要客户端的 flush()!

于 2013-04-19T09:19:52.853 回答