2012-03-12 2 views
8

Я разрабатываю приложение Server-Client, и у меня возникла проблема с ожиданием ввода данных по входному потоку.Java InputStream ждет данных.

У меня есть поток, посвященный чтению входных данных. В настоящее время он использует цикл while, пока данные не будут доступны. (Протокол N.B. следующий: отправить размер пакета, скажем 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 
    } 
} 

Он работает, но блокирует поток, пока цикл - это ИМО, плохая идея. Я мог бы использовать Thread.sleep (X), чтобы предотвратить непрерывное потребление ресурсов циклом, но, безусловно, должен быть лучший способ.

Также я не могу полагаться на InputStream.read, чтобы заблокировать поток, поскольку часть данных может быть отправлена ​​сервером с задержками. Я попытался, но это всегда приводило к неожиданному поведению.

Я бы признателен за любые идеи :)

+2

InputStream.read уже блоки, когда данные отсутствуют , поэтому отмените метод 'available'. – UmNyobe

ответ

12

Вы можете использовать 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(); 
} 
+3

Вы, вероятно, не хотите читать 2GiB в свою память –

4

Как сказал UmNyobe, available() предназначен для использования, если вы DonT хотите блокировать, как поведение по умолчанию блокирует.

Просто используйте нормальный read читать все, что доступно, но только отправить пакет для обработки в другом потоке как только вы packetData.length байт в буфере ...

+0

Спасибо ... Сохранял мой день. – Velu

Смежные вопросы