【问题标题】:Measuring actual bytes written through Java sockets测量通过 Java 套接字写入的实际字节数
【发布时间】:2011-10-27 23:25:06
【问题描述】:

我编写了一个小程序,可以将文件从一个客户端发送/接收到另一个客户端。我已经为接收方和客户端设置了进度条,但问题是发送方的进度条完成速度似乎比实际传输快得多。问题在于它如何计算已写入的字节数。我假设它正在计算我读入缓冲区的字节数,而不是通过网络发送的字节数,那么我怎样才能找到解决这个问题的方法呢?接收者正在以正确的速率计算他收到的字节,但发送者没有正确地完成他的工作。

设置较低的缓冲区大小会稍微抵消差异,但仍然不正确。我尝试使用 CountingOutputStream 包装输出流,但它返回的结果与下面的代码 sn-p 相同。传输最终正确完成,但我需要正确的“发送”值来更新我的进度条,就像在接收器端实际接收并写入磁盘的内容一样。我包含了一个非常精简的代码 sn-p,它代表了我计算传输字节的方式。任何解决方案的示例都会非常有帮助。

try
    {
    int sent = 0;
    Socket sk = new Socket(ip, port);
    OutputStream output = sk.getOutputStream();
    FileInputStream file = new FileInputStream(filepath);

    byte[] buffer = new byte[8092];

    while ((bytesRead = file.read(buffer)) > 0)
        {
        output.write(buffer, 0, bytesRead);
        sent += bytesRead;
        System.out.println(sent); // Shows incorrect values for the actual speed.
        }
    }

【问题讨论】:

  • 您可以尝试在 output.write() 调用之后立即在输出流上调用 flush(),这将刷新缓冲区并实际上导致数据通过网络发送。但是,缓冲区可以提高性能,如果您继续刷新(),性能可能会受到影响。
  • @prunge flush() not '实际上导致数据通过网络发送',实际上未修饰的套接字输出流上的 flush() 什么都不做.
  • @EJP 你是对的,查看源代码表明 flush() 什么都不做。我想减少延迟的方法可能是在套接字上设置 setTcpNoDelay(false),这将关闭Nagel's algorithm

标签: java sockets networking progress-bar outputstream


【解决方案1】:

简而言之,考虑到您与“线路”本身之间的缓冲区数量,我认为您无法仅从“发送方”方面获得所需的准确可见性。但是,我认为这并不重要。原因如下:

  1. 当它们被交给网络堆栈时,它们被视为“已发送”。当您发送少量字节(例如您的 8K 示例)时,这些字节将被缓冲,并且 write() 调用将快速返回。

  2. 一旦达到网络饱和,您的 write() 调用将开始阻塞,因为各种网络缓冲区已满 - 因此您将真正了解时间安排。

  3. 如果你真的必须有某种“你收到了多少字节?”您必须让接收端通过带外机制(例如 gloomcoder 建议)定期发回该数据

【讨论】:

    【解决方案2】:

    从套接字获取输入流,另一方面,当您将选择的字节写入磁盘后,将结果写入输出流。生成第二个线程来处理此信息的读取,并将其链接到您的计数器。

    您的变量是sent - 它是准确的。您需要的是 receivedprocessed 变量,为此您需要双向通信。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多