2012-03-12 19 views
8

Pracuję nad aplikacją Server-Client i mam problem z oczekiwaniem na dane wejściowe w strumieniu wejściowym.Java InputStream czekać na dane.

Mam wątek przeznaczony do odczytu danych wejściowych. Obecnie wykorzystuje pętlę while do przechowywania danych. (Protokół N.B. jest następujący: wyślij rozmiar pakietu, powiedz N, jako int, następnie wyślij N bajtów).

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

Działa, ale blokowanie wątku przez pętlę while jest IMO złym pomysłem. Mogę użyć Thread.sleep (X), aby zapobiec ciągłemu zużyciu zasobów przez pętlę, ale na pewno musi być lepszy sposób.

Również nie mogę polegać na InputStream.read, aby zablokować wątek, ponieważ część danych może być wysyłana przez serwer z opóźnieniami. Próbowałem, ale zawsze powodowało nieoczekiwane zachowanie.

będę wdzięczny za wszelkie pomysły :)

+2

InputStream.read już bloki, gdy dane nie są dostępne . więc odrzuć metodę 'available'. – UmNyobe

Odpowiedz

12

Można użyć 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 
} 

wolę używać blokowania NIO który obsługuje wielokrotnego użytku bufory.

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

Prawdopodobnie nie chcesz czytać 2GiB w swojej pamięci –

4

Jak powiedział UmNyobe, available() ma być używany, jeśli dont chcą blokować jako domyślne zachowanie blokuje.

Wystarczy użyć normalnej read czytać to, co jest dostępne, ale tylko wysyłania pakietów do przetwarzania w innym wątku skoro masz packetData.length bajtów w swoim buforze ...

+0

Dzięki ... Uratowałem mój dzień. – Velu

Powiązane problemy