Java InputStream 等待数据。

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9666783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 05:51:38  来源:igfitidea点击:

Java InputStream wait for data.

javasocketsstream

提问by Bart Platak

I'm developing Server-Client application and I have a problem with waiting for input data on input stream.

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

I have thread dedicated to reading input data. Currently it uses while loop to hold until data is available. (N.B. protocol is as follow: send size of packet, say N, as int then send N bytes).

我有专门用于读取输入数据的线程。目前它使用 while 循环来保持直到数据可用。(NB协议如下:发送数据包的大小,说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
    }
}

It works but blocking the thread by while loop is IMO a bad idea. I could use Thread.sleep(X) to prevent resources being continously consumed by the loop, but there surely must be a better way.

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

Also I can not rely on InputStream.read to block the thread as part of the data may be sent by the server with delays. I have tried but it always resulted in unexpected behaviour.

此外,我不能依靠 InputStream.read 来阻塞线程,因为服务器可能会延迟发送一部分数据。我试过了,但它总是导致意外的行为。

I'd appreciate any ideas :)

我很感激任何想法:)

采纳答案by Peter Lawrey

You can use DataInputStream.readFully()

您可以使用 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
}

I prefer to use blocking NIO which supports re-usable buffers.

我更喜欢使用支持可重用缓冲区的阻塞 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();
}

回答by Filipe Pina

As UmNyobe said, available()is meant to be used if you dontwant to block as the default behaviour is blocking.

作为UmNyobe说,available()是为了使用,如果你希望阻止的默认行为是阻塞。

Just use the normal readto read whatever is available but only send packet for processing in other threadonce you have packetData.lengthbytes in your buffer...

只需使用正常read读取可用的任何内容,但仅在缓冲区中有字节后才发送数据包以在其他线程中进行处理packetData.length......