2011-04-26 56 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