2008年3月29日土曜日

インサイドWindows第4版下

インサイドWindows第4版上に続いてようやくインサイドWindows第4版下を買えました。近くの本屋さんにはいつ見ても上しか置いてなくて…でも注文するのは負けた気がするし。
読んでいて一つ参考になった話題を。大容量のメモリを搭載しているWindows XPでもタスクマネージャのシステムキャッシュを見ると512MBで抑えられている場合があります。このPCは68MBとしょぼしょぼですが(;;
こういう場合、パフォーマンス オプションで「システム キャッシュ」を選択すると512MB以上のメモリをシステムキャッシュに割り当てられるようになります。メモリが余ってる人はどうぞ。
64bit版やWindows Vistaはこのリミッターが最初から解除されています。

HTTP Server API

以前からWindows OSにはIISが含まれていたけど、Windows XP SP2、Windows Server 2003以降にはOS側にWebサーバ機能が組み込まれていて、IISもこれを使う設計らしい。
試しにこのHTTP Server APIを使ってみた。

HTTPAPI_VERSION version = HTTPAPI_VERSION_1;
HttpInitialize( version, HTTP_INITIALIZE_SERVER, NULL );

HANDLE handle;
HttpCreateHttpHandle( &handle, NULL );

HttpAddUrl( handle, L"http://+:80/", NULL );

while( !stop ){
HTTP_REQUEST_ID requestId;
HTTP_SET_NULL_ID( &requestId );
char buffer[ 4096 ] = {};
PHTTP_REQUEST request = reinterpret_cast<PHTTP_REQUEST>( buffer );
ULONG size;
HttpReceiveHttpRequest( handle, requestId, 0, request, sizeof buffer, &size, NULL );

HTTP_RESPONSE response;
memset( &response, 0, sizeof response ); // デフォルトコンストラクタ用意してください(;;)
HTTP_DATA_CHUNK chunk;
HANDLE file = INVALID_HANDLE_VALUE;
if( request->Verb != HttpVerbGET )
response.StatusCode = 503;
else{
// URLパスの先頭の'/'をスキップ
file = CreateFileW( &request->CookedUrl.pAbsPath[1], FILE_READ_DATA, 0, NULL, OPEN_EXISTING, 0, NULL );
if( file == INVALID_HANDLE_VALUE )
response.StatusCode = 404;
else{
chunk.DataChunkType = HttpDataChunkFromFileHandle;
chunk.FromFileHandle.ByteRange.StartingOffset.QuadPart = 0;
chunk.FromFileHandle.ByteRange.Length.QuadPart = HTTP_BYTE_RANGE_TO_EOF;
chunk.FromFileHandle.FileHandle = file;
response.StatusCode = 200;
response.EntityChunkCount = 1;
response.pEntityChunks = &chunk;
}
}
HttpSendHttpResponse( handle, request->RequestId, 0, &response, NULL, &size, NULL, 0, NULL, NULL );
if( file != INVALID_HANDLE_VALUE )
CloseHandle( file );
}
HttpRemoveUrl( handle, L"http://+:80/" );
CloseHandle( handle );
HttpTerminate( HTTP_INITIALIZE_SERVER, NULL );
サンプルなのでエラー処理は省いてます。機能的には、カレントディレクトリのファイルを返します。
stop = trueとしてもすぐには終了しません。HttpReceiveHttpRequest()でブロックされているので、次のリクエストを処理したところでループを抜けます。

2008年3月2日日曜日

fwrite()と改行コード

fwrite()は任意のバイナリデータをstreamに書き込むライブラリ関数だと理解していましたが、今更ながらstreamがテキストモードの場合、任意文字列を書き込むものだと知りました。具体的にはバイナリデータを文字列と見なし、その中からNL(0x0A)をCR-LF(0x0D-0x0A)に置き換えられてはまりました。
テキストとバイナリを混在させたstreamの場合、その都度モードを切り替える必要があるそうです。

FILE* stream;
_setmode( _fileno( stream ), _O_BINARY );