MFC の WinInet クラスで HTTP を実装してみる
MFCのWinInetクラスを使ってみました。印象としてはVBのInetコントロールと同じくらいお手軽です。VC++6.0のヘルプなら
MSDN ライブラリ Visual Studio 6.0 ┗Visual C++ ドキュメント ┗Visual C++ ユーザーズ ガイド ┗Visual C++ プログラマーズ ガイド ┗プログラム機能の追加 ┗詳細 ┗インターネットのトピック ┗インターネットのプログラミング ┗代表的な HTTP クライアント アプリケーションの作成手順
に必要な手順がまとめてくれてあります。さらに簡潔に書くとこんな感じでしょう。
- CInternetSession オブジェクトを作成。サーバーに接続されます。
- CInternetSession::GetHttpConnection をでサーバに接続します。CHttpConnection オブジェクトが返されます。
- CHttpConnection::OpenRequest を呼び出して、サーバへの要求をオープンします。CHttpFile オブジェクトが返されます。
- CHttpFile::SendRequestを呼び出して、要求を送信します。
- CHttpFile より、受信したデータを読み取ります。
- CInternetSession オブジェクトを破棄すると、接続は終了し、開いているファイルのハンドルと接続が自動的にクリアされます。
というわけで実装です。とりあえずサーバのファイルを一個とってきて表示するだけのちょんプロを作成してみました。VC++でWin32 Console Applicationプロジェクトを作成します。stdafx.h で afxinet.h をインクルードします。そうそう、とってくるファイルですが、コンソールアプリなのでHTMLをとってきても仕方ないし、かといって「てすと」とか書いたテキストファイルを取ってくるのもあんまりです。そこで、テストらしくこんなCGIを作ってサーバにおいておくことにします。
#!/usr/bin/perl -w
use strict;
use vars qw($key $val);
format STDOUT =
@<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$key, $val
.
print <<'HEADER_END';
Content-Type: text/plain
HEADER_END
while ( ( $key, $val ) = each( %ENV ) )
{
write();
}
1;
showenv.cgi とかいう名前をつけてサーバに転送し、パーミッションを変更しておきます。サーバ側で取得可能な環境変数を列挙するのみのCGIプログラムです。
で、VC++のほうはこんな感じで・・・どうでしょうか。
static BOOL GetResuest()
{
CInternetSession inetSess( _T( "HttpTest1 Browser" ), 1, INTERNET_OPEN_TYPE_PRECONFIG );
INTERNET_PORT nPort = INTERNET_DEFAULT_HTTP_PORT;
LPCTSTR lpszServer = _T( "frog.raindrop.jp" );
LPCTSTR lpszObject = _T( "httptest1.cgi?testquery=testvalue" );
BOOL bRet = FALSE;
CHttpConnection* lpHttpConn = inetSess.GetHttpConnection( lpszServer, nPort );
if ( lpHttpConn == NULL ) {
std::cout << _T( "GetHttpConnection エラー" ) << std::endl;
} else {
CHttpFile* lpHttpFile = lpHttpConn->OpenRequest( CHttpConnection::HTTP_VERB_POST, lpszObject );
if ( lpHttpFile == NULL ) {
std::cout << _T( "OpenRequest エラー" ) << std::endl;
} else {
BOOL bRet = lpHttpFile->SendRequest();
if ( !bRet ) {
std::cout << _T( "SendRequest エラー" ) << std::endl;
} else {
DWORD dwStatus;
bRet = lpHttpFile->QueryInfoStatusCode( dwStatus );
if ( !bRet ) {
std::cout << _T( "QueryInfoStatusCode エラー" ) << std::endl;
} else {
switch ( dwStatus )
{
case HTTP_STATUS_OK:
{
CString strBuf;
while ( lpHttpFile->ReadString( strBuf ) )
{
std::cout << (LPCTSTR)strBuf << endl;
}
bRet = TRUE;
}
default:
std::cout << _T( "StatusCode:" ) << dwStatus << endl;
}
}
}
}
}
return bRet;
}
うーん、コメントもありません。でも、必要ないくらい簡単な感じです。ちゃんと動作しました。
トラックバック
- このエントリーにトラックバック:
- http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/283
コメント
初めてメ-ルします。
田中と申します。
上記プログラム試したのですが、
bRet= lpHttpFile->QueryInfoStatusCode( dwStatus );
でbRetが404が帰ってきます。
動作環境はマイクロソフトの.NETを使用しています。
以上
HTTP404 は File Not Found ですね。
アクセスしようとした URI のリソースが存在しないことを意味するエラーです。
"HTTP ステータスコード" などでググってみてください。