0

我已经使用 Netty 的内置功能在 Netty 中实现了一个 HTTP 服务器。现在我实现了对 Range-Headers 的支持,它只允许接收页面的一部分。我在netty中所做的是:

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 ,所以流肯定完成了。我设法解决了在关闭方法中 raf.close 之后执行 channel.close() 的问题,但是这个 hack 并不让我高兴。我究竟做错了什么?

4

1 回答 1

0

一旦 isEndOfInput() 返回 true,FutureListener 就会收到通知。因此,我认为您应该调试 isEndOfInput() 在这种情况下是否为真。

于 2012-05-03T06:35:48.090 回答