我目前正在使用http服务器,有些事情表现得有些奇怪。
我想生成动态内容,还只提供静态文件。
提供动态生成的内容可以正常工作。
因为我想从零拷贝中获利,所以我使用FileRegions提供静态文件。
我的频道管道包含以下处理程序(按此顺序):


HttpRequestDecoder
HttpResponseEncoder
HttpObjectAggregator
ApiMapper


ApiMapper是可共享的,并且从SimpleInboundHandler派生。
创建时,ApiMapper从静态文件创建FileRegion。
现在,每次请求“ /” uri时都会发生:


DefaultHttpReponse写入ChannelHandlerContext。
DefaultHttpReponse不被重用,并且包含用于
内容类型和内容长度
FileRegion的ReferenceCount使用其keep方法增加。
然后,使用FileRegion作为参数在ChannelHandlerContext上调用writeAndFlush。
向返回的ChannelFuture添加一个ChannelFutureListener,它显示“ DONE”。


第一个响应将按预期工作,浏览器将获取完整文件并正确显示它,并打印“ DONE”。
但是,如果再次调用“ /” uri,则浏览器将不会显示任何内容,而是永远加载,但会打印“ DONE”。
然后,在重新启动服务器后,我使用telnet手动进行呼叫。第一个响应是正确的,但是随后我注意到第二个调用仅返回一个标头,但没有内容。
“完成”仍被打印。

所以我的问题是:同一个FileRegion对象可以多次使用吗?我还有其他错吗?

最佳答案

不可以,因为在transferred对象上更新DefaultFileRegion状态时,不能多次写入同一个FileRegion。您将需要为此处的每次写入创建一个新的DefaultFileRegion实例。

另外,还需要确保在LastHttpContent之后发送FileRegion,否则在编写第二个HttpResponseEncoder时,HttpResponse中的状态机将不会处于正确的状态。

07-26 06:08