我正在开发服务器客户端应用程序,在等待输入流上的输入数据时遇到问题。
我有专门读取输入数据的线程。目前,它使用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
字节时,才会发送数据包以在其他线程中进行处理。。。