HttpAddFragmentToCache和OS错误​​50

时间:2011-04-26 11:18:41

标签: windows delphi winapi http http.sys

我正在尝试在应用程序中创建嵌入式Web服务器。为此,我使用Windows中的http.sys HTTP服务器组件。当我不尝试使用HttpAddFragmentToCache时,一切运作良好。

到目前为止我做了什么(删除了任何错误检查,但没有片段缓存它工作正常):

HttpInitialize( HTTPAPI_VERSION_1, HTTP_INITIALIZE_SERVER );
HttpCreateHttpHandle( FQueueHandle )
HttpAddUrl( FQueueHandle, PWideChar( W ) );
...
HttpRemoveUrl( FQueueHandle, PWideChar( W ) );
HttpTerminate( HTTP_INITIALIZE_SERVER );

现在,当一个请求来自辅助线程时:

HttpReceiveHttpRequest( FQueueHandle, FRequestID, 0, FRequest^, FRequestBufferSize, @Bytes );
// if needed:
HttpReceiveRequestEntityBody( FQueueHandle, FRequestId, 0, @FRequestContent[ 0 ], Longword( N ), @BytesRead )
// Fill in chunks...
// Respond
HttpSendHttpResponse( FQueueHandle, FRequestId, 0, FResponse, nil, N );

我想要改变的是将一些静态文档添加到片段缓存中(在上面的省略号中):

Chunk.DataChunkType           := hctFromMemory;
Chunk.FromMemory.pBuffer      := @Content[ 0 ];
Chunk.FromMemory.BufferLength := Length( Content );
Policy.Policy                 := hcpUserInvalidates;
Policy.SecondsToLive          := 0;
Result := HttpAddFragmentToCache( FQueueHandle, PWideChar( W ), Chunk, Policy );

注意:在我的代码中,所有重叠参数都可选择为nil / NULL,这解释了为什么你可能会错过该参数。

这将产生50的结果(不支持请求)。我试图从内存和文件句柄添加片段,所有不同的策略。检查在反汇编中传递的值是否正确,检查传递给HttpAddFragmentToCache的字符串是否确实是传递给HttpAddUrl的字符串的有效subURL(如果不是你得到操作系统错误2那么这也是不是)。

我的问题是:这可能是什么?我尝试以最简单的方式使用此API调用(这是API的设计目的),但显然我做错了..

更新

看起来添加函数HttpAddFragmentToCache的fragmens具有最大大小:

当上面的代码被替换为:

Chunk.FromMemory.BufferLength := Min( 256*1024, Length( Content ) );

没有错误发生;当被

取代时
Chunk.FromMemory.BufferLength := Min( 256*1024 + 1, Length( Content ) );

失败了。显然有一个尺寸限制......我找到了它:

http://support.microsoft.com/kb/820129

  

UriMaxUriBytes 262144(字节)   4096(4k) - 16777216(16MB)字节任意   响应大于此   值没有缓存在内核中   响应缓存。

这留下两个选项:1。为更大的文件保留多个片段。或2.在注册表中增加此限制。

2 个答案:

答案 0 :(得分:1)

解决了问题:片段缓存每个片段可以缓存的大小有限制;默认为256KB。有关详细信息,请参阅问题的更新。

答案 1 :(得分:0)

如果没有实施的所有源代码,这有点困难。

您何时致电HttpAddFragmentToCache?它应该在客户端TThread实例中对HttpReceiveHttpRequest()的任何调用之前。

例如,您的HttpReceiveHttpRequest()通话对我来说听起来有点奇怪。你应该使用

HttpReceiveRequestEntityBody( FQueueHandle, FRequest^.RequestID, ... ) 

查看我们SynCrtSock单元中的THttpApiServer类,以及http.sys服务器的工作示例。它还不支持缓存,但至少主要初始化和线程池按预期工作。