2012-05-02 1 views
0

Я реализовал HTTP-сервер в Netty, используя его встроенные функции. Теперь я реализовал поддержку Range-Headers, которые позволяют получать только часть страницы. Что мне делать в Нетти является:Почему 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 - это проблема, я использую тот же принцип в разных частях сервера. Когда поток закончен, он возвращает ChannelBuffers.EMPTY_BUFFER, а затем будет вызываться из netty, поэтому поток определенно завершен. Мне удалось обойти проблему с вызовом channel.close() после raf.close в методе close, но этот хак не делает меня счастливым. Что я делаю не так?

ответ

0

БудущееListener получит уведомление, когда isEndOfInput() возвращает true. Поэтому я думаю, что вы должны отлаживать, если isEndOfInput() когда-либо будет истинным в этом случае.

+0

Проблема не в том, что isEndOfInput должен возвращать true, это всегда было так, когда был достигнут конец моего потока. Реальная проблема заключалась в том, что nextChunk не возвращал NULL, когда isEndOfInput возвращался true, в моем случае он возвратил последний кусок. Netty распознает только конец потока, когда isEndOfInput возвращает true И nextChunk возвращает значение null. –

+0

, если это случай, то это ошибка. Не могли бы вы открыть отчет об ошибке в журнале отслеживания проблем netty. Единичный тест был бы очень приятным, а событие лучше исправить;) –

+0

Я добавил тестовый пример, и поведение, которое вы видели, не воспроизводится. Может быть, вы используете старую версию netty? –

 Смежные вопросы

  • Нет связанных вопросов^_^