Java InputStream等待数据



我正在开发服务器客户端应用程序,在等待输入流上的输入数据时遇到问题。

我有专门读取输入数据的线程。目前,它使用while循环来保持直到数据可用。(注意:协议如下:发送数据包的大小,比如说N,作为int,然后发送N个字节)。

public void run(){
    //some initialization
    InputStream inStream = sock.getInputStream();
    byte[] packetData;
    //some more stuff
    while(!interrupted){
        while(inStream.available()==0);
        packetData = new byte[inStream.read()];
        while(inStream.available()<packetData.length);
        inStream.read(packetData,0,packetData.length);
        //send packet for procession in other thread
    }
}

它可以工作,但通过while循环阻塞线程是IMO的一个坏主意。我可以使用Thread.sleep(X)来防止循环持续消耗资源,但肯定有更好的方法。

此外,我不能依赖InputStream.read来阻止线程,因为服务器可能会延迟发送部分数据。我试过了,但总是会出现意想不到的行为。

如果有任何想法,我将不胜感激:)

您可以使用DataInputStream.readFully()

DataInputStream in = new DataInputStream(sock.getInputStream());
//some more stuff
while(!interrupted) {
    // readInt allows lengths of up to 2 GB instead of limited to 127 bytes.
    byte[] packetData = new byte[in.readInt()];
    in.readFully(packetData);
    //send packet for procession in other thread
}

我更喜欢使用阻塞NIO,它支持可重用的缓冲区。

SocketChannel sc = 
ByteBuffer bb = ByteBuffer.allocateDirect(1024 *1024); // off heap memory.
while(!Thread.currentThread.isInterrupted()) {
     readLength(bb, 4);
     int length = bb.getInt(0);
     if (length > bb.capacity()) 
         bb = ByteBuffer.allocateDirect(length);
     readLength(bb, length);
     bb.flip();
     // process buffer.
}

static void readLength(ByteBuffer bb, int length) throws EOFException {
     bb.clear();
     bb.limit(length);
     while(bb.remaining() > 0 && sc.read(bb) > 0);
     if (bb.remaining() > 0) throw new EOFException();
}

正如UmNyobe所说,如果不想阻止,就应该使用available(),因为默认行为是阻止。

只需使用普通的read读取任何可用的数据,但只有当缓冲区中有packetData.length字节时,才会发送数据包以在其他线程中进行处理。。。

相关内容

  • 没有找到相关文章

最新更新