2

我感觉应该是一个已解决的问题。我正在编写的 Android 应用程序发送一条消息,就像用户可以附加文件的 SMS 一样。我正在使用 HttpUrlConnection 将此数据发送到我的服务器,这基本上归结为 java.io.OutputStream(我将其包装在 DataOutputStream 中)。

在移动设备上,有时网络连接可能非常糟糕,发送可能需要太长时间。我有以下两个基本问题:

  1. 用户无法知道上传进度
  2. 如果网络很糟糕并且进展很糟糕 - 我宁愿中止或有一些合理的超时,而不是坐在那里尝试 5-10 分钟。

问题1:

我试图根据我正在使用 4K 缓冲区执行的输出流 write() 调用来显示上传进度:

        buffer = new byte[4096];
        long totalBytes = 0;
        while ((bytesRead = fis.read(buffer)) > -1) {
            totalBytes += bytesRead;
            dos.write(buffer, 0, bytesRead);
            if(showProgress){
               updateProgressBar(totalBytes);
            }
        }

虽然这向我展示了进展,但它似乎只是向我展示了应用程序将文件缓冲区传输到操作系统网络堆栈缓冲区的速度。即使在慢速网络上,进度条也很快完成,然后在我最终从服务器获取 JSON 并告诉我发送状态之前又在那里停留了很长时间。从我将它传递给操作系统到我的服务器告诉我它收到它的时间,肯定有一些方法可以取得一些进展吗?

问题2:

有时网络连接很糟糕,但还不够糟糕,以至于硬件无线电触发未找到连接的回调(在这种情况下,我进入离线模式)。所以当它很糟糕但没有关闭时,我的应用程序只会坐在发送对话框中,直到奶牛回家。这与问题 1 相关,因为我需要以某种方式了解实际吞吐量,因为 OutputStream 本身不提供超时机制。如果它低于某个阈值,我可以取消连接并通知用户他们需要去一个接收良好的地方。

旁注:异步发送/输出队列对我来说不是一个选项,因为我无法将消息持久化到磁盘,因此不能保证起草的消息是无限期的,以防它在稍后的某个时间点发送失败。我需要/想要阻止发送,我只需要更聪明地放弃和/或通知用户正在发生的事情。

4

1 回答 1

1

似乎它只是向我展示了应用程序将文件缓冲区传输到操作系统网络堆栈缓冲区的速度。

比那更糟。它向您展示了应用程序可以多快地将您的数据传输到它正在写入HttpURLConnection的内部ByteArrayOutputStream,以便它可以在写入任何内容之前查看内容长度并设置标题。

幸运的是,它也比这更好。如果事先知道数据的长度,设置定长传输模式。如果您不这样做,请将分块传输模式设置为较小的块大小,例如 1024。

然后,您将看到您的应用程序可以多快地将数据移动到套接字发送缓冲区;在分块传输模式的情况下,以块大小为单位。但是,一旦套接字发送缓冲区填满,您的写入将被阻塞,您将看到实际的网络传输,至少在您完成最后一次写入之前。从那时起,写入和关闭都是异步的,因此您的显示会更早弹出,但每个人都有这个问题。

关于问题 2,一旦传输稳定到上述网络速度,您就可以计算自己的吞吐量并在它很差时做出相应的反应。

于 2013-02-22T00:27:59.727 回答