2012-03-12 16 views
8

Estoy desarrollando una aplicación Server-Client y tengo un problema con la espera de datos de entrada en el flujo de entrada.Java InputStream espera datos.

Tengo hilo dedicado a leer datos de entrada. Actualmente usa while loop para mantener hasta que los datos estén disponibles. (El protocolo N.B. es el siguiente: envíe el tamaño del paquete, digamos N, como int y luego envíe N bytes).

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

Funciona, pero bloqueando el hilo por bucle while es la OMI una mala idea. Podría usar Thread.sleep (X) para evitar que el bucle consuma recursos continuamente, pero seguramente debe haber una mejor manera.

Tampoco puedo confiar en InputStream.read para bloquear el hilo porque el servidor puede enviar parte de los datos con demoras. Lo intenté, pero siempre resultó en un comportamiento inesperado.

lo agradecería cualquier idea :)

+2

InputStream.read ya bloques cuando los datos no están disponibles . así que descarta el método 'disponible'. – UmNyobe

Respuesta

12

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

yo prefiero usar el bloqueo de NIO que soporta reutilizables tampones.

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

Probablemente no quiera leer 2GiB en su memoria –

4

Como dijo UmNyobe, available() está destinado a ser utilizado si no te desea bloquear como el comportamiento por defecto es el bloqueo.

Sólo tiene que utilizar la normalidad read para leer lo que está disponible, pero sólo paquete de envío para su tratamiento en otro hilo una vez que tenga packetData.length bytes en el búfer ...

+0

Gracias ... Me salvó el día. – Velu

Cuestiones relacionadas