2012-05-02 4 views
0

Netty에 내장 된 기능을 사용하여 HTTP 서버를 구현했습니다. 이제는 페이지의 일부만 수신 할 수있는 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에서 close가 호출되므로 스트림이 완전히 끝납니다. close-method에서 raf.close 다음에 channel.close()를 수행 할 때 문제를 해결할 수 있었지만이 해킹으로 인해 나를 행복하게 만들 수 없습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

답변

0

FutureReference는 isEndOfInput()이 true를 반환하면 알림을받습니다. 그래서 isEndOfInput()이이 경우 true가 될 경우 디버깅해야한다고 생각합니다.

+0

문제는 isEndOfInput이 true를 반환해야한다는 것이 아니라, 스트림의 끝에 도달했을 때 항상 그렇습니다. 진짜 문제는 isEndOfInput이 true를 반환 할 때 nextChunk가 NULL을 반환하지 않는다는 것입니다. 내 경우에는 마지막 청크를 반환했습니다. Netty는 isEndOfInput이 true를 리턴하고 nextChunk가 null을 리턴 할 때만 스트림의 끝을 인식합니다. –

+0

그 다음 버그가있는 경우 .. netty의 문제 추적기에서 버그 보고서를 열 수 있습니까? 단위 테스트는 매우 좋거나 이벤트가 더 좋을 수도 있습니다.) –

+0

테스트 케이스가 추가되어 사용자가 본 동작을 재현 할 수 없습니다. 어쩌면 당신은 오래된 버전의 netty를 사용할 것입니까? –

관련 문제