Java套接字 - 丢失字节和100%处理器功耗

noi*_*cat 2 java sockets networking stream

我正在制作一个简单的套接字应用程序,通过TCP连接我的服务器.我有时需要读取2个字节的值,所以它们都像:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

此函数应接收给定的字节数并将其返回到数组中.问题是,有时它会在休息可用之前读取一个字节并返回奇怪的数据.

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)
Run Code Online (Sandbox Code Playgroud)

我的快速修复是添加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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是这个循环使用100%的处理器能力(实际上是一个核心),这非常烦人.有没有办法重写该函数(param和返回值必须完全相同),以便它正常工作?

提前Thanx :)

Ste*_*n C 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;
}
Run Code Online (Sandbox Code Playgroud)

没有必要使用"轮询"流available().没有必要睡觉.您只需使用read只有在读取了至少一个字节或者您已经适合"流结束"时才会返回的事实.


请注意,null如果您的read方法失败,我也不认为返回a是正确的.最好抛出异常......或者让IOException来自in.read()调用的传播.

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