2012-03-12 33 views
8

Tôi đang phát triển ứng dụng Máy khách-Khách hàng và tôi gặp sự cố khi đợi dữ liệu đầu vào trên luồng đầu vào.Java InputStream chờ dữ liệu.

Tôi có chủ đề dành riêng cho việc đọc dữ liệu đầu vào. Hiện tại, nó sử dụng vòng lặp trong khi giữ cho đến khi dữ liệu có sẵn. (N.B. giao thức là như sau: gửi kích thước của gói tin, nói N, như int sau đó gửi 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 
    } 
} 

Nó hoạt động nhưng chặn luồng theo vòng lặp trong khi IMO là một ý tưởng tồi. Tôi có thể sử dụng Thread.sleep (X) để ngăn chặn các tài nguyên liên tục được tiêu thụ bởi vòng lặp, nhưng chắc chắn phải có một cách tốt hơn.

Ngoài ra tôi không thể dựa vào InputStream.read để chặn luồng như một phần của dữ liệu có thể được gửi bởi máy chủ với sự chậm trễ. Tôi đã thử nhưng nó luôn dẫn đến hành vi bất ngờ.

Tôi đánh giá cao bất kỳ ý tưởng :)

+2

InputStream.read đã chặn khi dữ liệu không có sẵn . do đó, loại bỏ phương thức 'sẵn có'. – UmNyobe

Trả lời

12

Bạn có thể sử dụng 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 
} 

Tôi thích sử dụng chặn nio mà hỗ trợ tái sử dụng bộ đệm.

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

Bạn có thể không muốn đọc 2GiB vào bộ nhớ của mình –

4

Như UmNyobe nói, available() có nghĩa là để được sử dụng nếu bạn không muốn chặn như hành vi mặc định chặn.

Chỉ cần sử dụng bình thường read để đọc bất cứ điều gì có sẵn nhưng chỉ gửi gói tin cho việc xử lý trong chủ đề khác một khi bạn có packetData.length byte trong bộ đệm của bạn ...

+0

Cảm ơn ... Đã lưu ngày của tôi. – Velu

Các vấn đề liên quan