2013-06-23 42 views
2

我正在制作一个简单的套接字应用程序,通过TCP使用我的服务器进行连接。我需要阅读,有时2个字节的值,因此这一切都像:Java套接字 - 丢失字节和100%处理器功耗

public byte[] read(int bytes) 
{ 
    byte b[] = new byte[bytes]; 
    try { 
     in.read(b); //in is InputStream from properly connected Socket.getInputStream() 
    return b; 
    } catch (IOException e) { 
     return null; 
    } 
} 

这个功能应该receieve字节的给定数量和排列返回。问题是,有时在休息可用之前它读取一个字节并返回奇怪的数据。

byte a[]=read(2); //Program is blocked here untill some bytes arrive... 
System.out.prntln(a[0]); //always correct 
System.out.prntln(a[1]); //unprintable character (probably 0 or -1) 

我速战速决是添加while循环检查是否有足够的数据来读:

public byte[] read(int bytes) 
{ 
    byte b[] = new byte[bytes]; 
    try { 
     while (in.available()<bytes); //It does the thing 
     in.read(b); 
    return b; 
    } catch (IOException e) { 
     return null; 
    } 
} 

但是,循环使用的处理器功率的100%(其中,核心,实际上),这是很烦人。有没有什么方法可以重写这个函数(参数和返回值必须完全一样)才能正常工作?

提前感谢名单:)

+1

我为什么要在这里做这件事,并且这会做这份工作?终于{}和我的问题之间我找不到任何真正的,我错了吗? –

+0

这是一个评论btw你必须关闭你的资源,当你打开例如InputStreams – nachokk

+0

我关闭他们,当我不需要这些InputStreams了。这只是一个帮手功能。另外,套接字是否自动关闭流? –

回答

7

是。你的快速修复是一个坏主意。实际上,任何使用available的代码都可能损坏。

以下是我应该这样做:

public byte[] read(int bytes) throws IOException { 
    byte b[] = new byte[bytes]; 
    int pos = 0; 
    while (pos < b.length) { 
     int nosRead = in.read(b, pos, b.length - pos); 
     if (nosRead == -1) { 
      return null; // Not the best idea ... see below. 
     } else { 
      pos += nosRead; 
     } 
    } 
    return b; 
} 

没有必要为“轮询”流使用available()。没有必要睡觉。你只是利用read只有在它已经读取至少一个字节或你适合“流结束”时才会返回的事实。


请注意,我也并不认为这是正确的返回null如果您read方法失败。最好抛出一个异常...或让呼叫in.read()传播。

这也适用于我的重写......我不想在这方面改变你的代码的行为。

+0

正是我需要的。另一个答案也很好,如果我接受一个答案(因为C先生的代表比你少),对你来说可以吗?谢谢你的帮助:) –

+1

@kittyPL - 不幸的是,如果你仔细阅读“C先生”的回答,它会有一些错误。 (我会留给你弄清楚他的代码中的错误是什么......但他对NIO的建议是错误的,或者至少被简化了。) –

+0

我现在明白了。希望他会改变这个:) –

2

扔掉它并使用DataInputStream.readFully()。