2012-03-12 14 views
8

Sto sviluppando un'applicazione Client-Server e ho un problema con l'attesa dei dati di input sul flusso di input.Java InputStream attendere i dati.

Ho thread dedicato alla lettura dei dati di input. Attualmente utilizza il ciclo da mantenere finché i dati non sono disponibili. (Il protocollo N.B. è il seguente: invia la dimensione del pacchetto, dite N, come int quindi invia N byte).

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 
    } 
} 

Funziona ma blocca il thread mentre il ciclo è IMO una cattiva idea. Potrei usare Thread.sleep (X) per evitare che le risorse vengano continuamente consumate dal ciclo, ma sicuramente deve esserci un modo migliore.

Inoltre, non posso fare affidamento su InputStream.read per bloccare il thread poiché parte dei dati potrebbe essere inviata dal server con ritardi. Ho provato ma ha sempre comportato un comportamento inaspettato.

Apprezzerei tutte le idee :)

+2

InputStream.read già blocchi quando i dati non è disponibile . quindi scarta il metodo 'available'. – UmNyobe

risposta

12

È possibile utilizzare 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 
} 

Io preferisco usare il blocco NIO che supporta tamponi riutilizzabili.

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

Probabilmente non vuoi leggere 2GiB nella tua memoria –

4

Come ha detto UmNyobe, available() è destinato a essere utilizzato se si non avete vogliono bloccare come il comportamento predefinito sta bloccando.

Basta usare il normale read di leggere tutto ciò che è disponibile, ma solo pacchetto di invio per l'elaborazione in altro thread una volta che hai packetData.length byte nel buffer ...

+0

Grazie ... Salvato il mio giorno. – Velu

Problemi correlati