2011-10-27 50 views
3

我写了一个小程序,用于将文件从一个客户端发送到另一个客户端。我已经为接收者和客户端设置了进度条,但问题是发件人的进度条完成速度比实际传输快得多。问题在于它如何计算已写入的字节数。我假设它正在计算我读入缓冲区的字节数,而不是通过网络发送的字节数,所以我如何才能找到解决此问题的解决方案?接收方正在以正确的速率计算他接收的字节数,但发送方没有正确地执行他的部分。测量通过Java套接字写入的实际字节数

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

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. 
     } 
    } 
+0

您可以在输出之后立即尝试调用输出流上的flush() .write()调用,这将刷新缓冲区并实际上导致数据通过网络发送。但是,缓冲区可以提高性能,并且如果保持flush()性能可能会受到影响。 – prunge

+0

@prunge flush()不会*'实际上导致数据在网络上传输',实际上flush()在未装饰的套接字输出流上什么也不做。 – EJP

+0

@EJP你是对的,看着源代码显示flush()什么也不做。我想有些事情要做,以减少延迟可能是套接字setTcpNoDelay(false),这将关闭[Nagel的算法](http://en.wikipedia.org/wiki/Nagle%27s_algorithm)。 – prunge

回答

2

从套接字获取输入流,另一方面,当您向磁盘写入字节选择时,将结果写入输出流。产生第二个线程来处理这些信息的读取,并将其链接到您的柜台。

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

4

简而言之,考虑到您和“wire”本身之间的缓冲区数量,我认为您完全可以从“发件人”一方获得您要查找的准确可见度。但是,我认为这不重要。原因如下:

  1. 当它们被交给网络堆栈时,字节计数为“已发送”。当你发送少量字节(比如你的8K例子)时,这些字节将被缓冲& write()调用将很快返回。

  2. 一旦您达到网络饱和,您的write()调用将会随着各种网络缓冲区变满而开始阻塞 - 因此您将会对时序有一个真正的了解。

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