2011-04-26 112 views
3

我正尝试在应用程序中创建一个嵌入式Web服务器。为此,我使用Windows中的http.sys HTTP服务器组件。当我不尝试使用HttpAddFragmentToCache时,一切正常。HttpAddFragmentToCache和操作系统错误50

我做了什么至今(删除任何错误检查,但没有片段缓存它的工作原理确定):

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); 

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

这将产生50的结果(不支持该请求)。我试图从内存和文件句柄中添加片段,所有不同的策略。检查传递的值在拆卸时是否正确,如果传递给HttpAddFragmentToCache的字符串确实是传递给HttpAddUrl的字符串的有效子URL(如果没有,则得到操作系统错误2,因此也不是这样)。

我的问题是:这可能是什么?我尝试使用这个API调用以最直接的方式,我可以看到(这是其中API是专为),但显然我做错了什么..

更新:

它看起来像片段(fragments)与功能添加HttpAddFragmentToCache具有最大尺寸:

当上述代码被替换为:

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.在注册表中增加此限制。

回答

1

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

+0

我不知道!很好的接收!这就是组块的绕过来绕过这个限制。使用高达256 KB的块,你可以缓存一个任意大小的文件,但是我不确定缓存这么大文件的速度会有什么好处,从磁盘上的文件异步读取会更好,因为如果有足够的RAM,它将会保留在内存中。 'HttpAddFragmentToCache'是为小型静态文件(通常是一些.js .css或.jpg .png,它们在http.sys托管的网站中的任何地方使用)。 – 2011-04-27 05:23:36

+0

@Bouchez:的确如此。因为我想将所有静态文件(包括1MB +的extjs-all.js)都添加到碎片中,所以我只关注它。正如你所描述的那样:除了小部分外,静态文件(通常是一些.js .css或.jpg .png,这些文件在http.sys托管的网站中的任何地方都可以使用);-)。 – 2011-04-27 09:20:04

0

如果没有实现所有源代码,这是有点困难。

你什么时候打电话给HttpAddFragmentToCache?它应该在客户端TThread实例中调用HttpReceiveHttpRequest()之前调用。

例如,您的HttpReceiveHttpRequest()调用听起来有点奇怪。您应该使用

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

看看在THttpApiServer类在我们SynCrtSock单位,工作示例的HTTP.SYS服务器。它还不支持缓存,但至少主要的初始化和线程池按预期工作。

+0

是的,我在开始处理任何请求之前调用它。我看过你的代码,处理循环看起来非常相似(除了我使用更小的缓冲区更经典的尝试,获得大小和重试。这工作很好btw,没有问题,我只保留本地HTTP请求ID下一步到HTTP_REQUEST结构我的问题在于HttpAddFragmentToCache调用,也许我错过了一些东西,但我没有看到你的库的任何调用该函数,他们是非常相似的BTW – 2011-04-26 13:13:47

+0

我可以添加源代码(单元),但那是有点大... – 2011-04-26 13:14:50

+0

或者它的一个链接到一个PasteBin网站,例如? – 2011-04-26 18:17:57