Bar*_*tak 10 java sockets stream
我正在开发Server-Client应用程序,我在输入流上等待输入数据时遇到问题.
我有致力于读取输入数据的线程.目前,它使用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
}
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理但是通过while循环阻塞线程是IMO的一个坏主意.我可以使用Thread.sleep(X)来防止循环继续消耗资源,但肯定必须有更好的方法.
此外,我不能依赖InputStream.read来阻止线程,因为数据的一部分可能由服务器发送延迟.我试过但它总是导致意想不到的行为.
我很感激任何想法:)
Pet*_*rey 13
您可以使用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
}
Run Code Online (Sandbox Code Playgroud)
我更喜欢使用支持可重用缓冲区的阻塞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();
}
Run Code Online (Sandbox Code Playgroud)
作为UmNyobe说,available()是为了使用,如果你不希望阻止的默认行为是阻塞。
只需使用常规read读取任何可用的内容,但仅在缓冲区中有字节后才发送数据包以供其他线程处理packetData.length ...