2010-12-07 44 views
0

我正在开发一个应用程序,通过套接字与第三方应用程序进行通信。基本上,我的应用程序需要发送一些请求到服务器,并且服务器返回一些数据。当服务器向我发回少量数据时,一切正常。但是,当我从服务器请求大量数据时,我的应用程序有时不会收到完整的数据,并且会间歇性地发生。Java Socket读取大量数据时遇到间歇性错误

我在互联网上做了一些研究,并遵循了我发现的套接字编程示例,但仍然无法解决问题。以下是我目前的实施。

 BufferedInputStream is = new BufferedInputStream(socket.getInputStream()); 

    //I know the size of data that I am expecting from the server 
    byte[] buffer = new byte[length]; 

    int count = 0; 
    int current = 0; 

    while(count < length) { 
     current = is.read(buffer, count, length - count); 

     if(current == -1) { 
      break; 
     } else {     
      count += current; 
     }   
    } 

我知道我期望从服务器获得的数据大小。发生问题时,read()方法在从服务器完全接收数据之前返回-1。我没有任何访问服务器端的实现。请告诉我,如果我错过了我的代码中的任何内容,或者有更好的方法去做。

回答

1

你的代码看起来基本健全。 (使用BufferedInputStream在这种情况下不会提高性能,如果有的话,它会使速度变慢,但这不太可能导致此问题。)

也可能在内存中缓存大量内容客户端导致客户端无响应足够长的时间导致套接字超时。但是,如果你的文件大小只有几兆字节,你可能会打折这种可能性。

但是,我怀疑真正的问题是客户端或服务器端的套接字超时太小。但是,如果您无法访问服务器端配置和日志,则很难诊断此问题。

3

如果read方法返回-1,则服务器在发送它发送的任何内容后关闭套接字。期。如果你期待更多的数据,你错了。

服务器可能是错误编码的,例如,关闭其套接字而不是最外面的输出流,从而丢失数据。或者可能您的结尾不正确,例如,通过为每个套接字创建多个BufferedInputStreams,而不是一个套接字的生命周期。

您的代码只是复制DataInputStream.readFully()。但是你真正应该做的是处理每个缓冲区的负载,而不是试图在内存中创建一个任意大的缓冲区。这只会浪费空间并增加延迟。

+0

谢谢!我在整个套接字的生命周期中只使用一个BufferedInputStreams。所以我可能必须检查服务器端。 – 2010-12-07 10:03:53

+0

对于你提到最后一段关于“处理收到的每个缓冲区负载”的问题,我不是很清楚。你能解释一下吗?非常感谢EJP。 – 2010-12-07 10:11:41

+0

当您读取少量数据时,BufferedInputStream很有用,例如一次只能读取一个字节,当一次读取就能够一次获得更多数据。即它可以在操作系统的一次大型读取中使成千上万的小读取成为可能。然而,在你的情况下,最大读取大小比缓冲区大,并且大于你要读取的典型数据包大小。即它的正上方 – 2010-12-07 10:42:34

0

有自己的代码中一些严重的问题:

假设长度= 8GB

你会得到很多的创造这样规模的一个byte []的问题。

int count 
int current 

这应该是

long count 
long current 

,但如果你这样做,代码将不再编译。所以你有一个Integer.MAX_VALUE的最大文件大小。如果你将你的下载存储到一个bytearray中。 (感谢EJP)

你必须将这些数据写入到除RAM之外的其他内存中。对于32位JVM,您绝不会创建比〜1,3 GB更大的字节。