2012-05-02 27 views
0

我已經在Netty中使用它的內置功能實現了一個HTTP-Server。現在我實現了對Range-Headers的支持,它只允許接收頁面的一部分。我在netty中做的是:爲什麼Close-ChannelFutureListener沒有通知?

final RandomAccessFile raf = new RandomAccessFile(file, "r"); 
raf.seek(ranges[ 0 ]); 

HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.PARTIAL_CONTENT); 
// MUST include accept-ranges!! 
response.setHeader(HttpHeaders.Names.ACCEPT_RANGES, "bytes"); 
// MUST include content-range 
response.setHeader(HttpHeaders.Names.CONTENT_RANGE , "bytes " + ranges[ 0 ] + "-" + ranges[ 1 ] + "/" + file.length()); 

if (null != mime) 
    response.addHeader(HttpHeaders.Names.CONTENT_TYPE, mime.substring(0, mime.indexOf(' '))); 
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, "" + ((ranges[ 1 ] - ranges[ 0 ]) + 1)); 

event.getChannel().write(response); 

event.getChannel().write(new ChunkedInput() { 
    private boolean endOfStream = false; 
    private byte[] buffer = new byte[ 4096 ]; 
    private long bytesRead = ranges[ 0 ]; 

    @Override 
    public boolean hasNextChunk() throws Exception { 
    return !this.endOfStream; 
    } 

    @Override 
    public Object nextChunk() throws Exception { 
    if (false == this.endOfStream) { 
     int read = raf.read(this.buffer); 
     if (read == -1 || this.bytesRead >= ranges[ 1 ]) { 
     this.endOfStream = true; 
     return new DefaultHttpChunk(ChannelBuffers.EMPTY_BUFFER); // send isLast 
     } 

     if (this.bytesRead + read > ranges[ 1 ]) { 
     read = (int) (ranges[ 1 ] - this.bytesRead) + 1; 
     this.bytesRead = ranges[ 1 ]; // next iteration will send last chunk 
     } 

     this.bytesRead += read; 

     return new DefaultHttpChunk(ChannelBuffers.copiedBuffer(this.buffer, 0, read)); 
    } 

    return null; 
    } 

    @Override 
    public boolean isEndOfInput() throws Exception { 
    return this.endOfStream; 
    } 

    @Override 
    public void close() throws Exception { 
    raf.close(); 
    } 
}).addListener(ChannelFutureListener.CLOSE); 

問題是ChannelFutureListener.CLOSE永遠不會被調用。我也嘗試了我自己的監聽器實現 - 它不會被調用。我不認爲我的ChunkedInput-Implementation是問題,我在服務器的不同部分使用相同的原則。流完成後返回ChannelBuffers.EMPTY_BUFFER,然後關閉將從netty調用,所以流確定完成。 我設法解決了在關閉方法raf.close後執行channel.close()的問題,但是這種入侵併沒有讓我開心。我究竟做錯了什麼?

回答

0

一旦isEndOfInput()返回true,FutureListener將得到通知。所以我認爲你應該調試,如果isEndOfInput()在這種情況下永遠是真的。

+0

問題不在於isEndOfInput必須返回true,當流的末尾達到時,情況總是如此。真正的問題是,當isEndOfInput返回true時,nextChunk不返回NULL,在我的情況下,它返回最後一個塊。當isEndOfInput返回true且nextChunk返回null時,Netty僅識別流的結束。 –

+0

如果是這種情況,那麼它的錯誤..你可以請打開netty的問題跟蹤器的錯誤報告。單元測試也會非常好,或者事件更好的修復;) –

+0

我爲它添加了一個測試用例,並且您看到的行爲不可重現。也許你使用舊版本的netty? –

相關問題