< プリンタ追加バッチ | ATL COM AppWizard プロジェクトで MFC を使う >

March 26, 2004

MFC の WinInet クラスで HTTP を実装してみる

MFCのWinInetクラスを使ってみました。印象としてはVBのInetコントロールと同じくらいお手軽です。VC++6.0のヘルプなら

MSDN ライブラリ Visual Studio 6.0
┗Visual C++ ドキュメント
 ┗Visual C++ ユーザーズ ガイド
  ┗Visual C++ プログラマーズ ガイド
   ┗プログラム機能の追加
    ┗詳細
     ┗インターネットのトピック
      ┗インターネットのプログラミング
       ┗代表的な HTTP クライアント アプリケーションの作成手順

に必要な手順がまとめてくれてあります。さらに簡潔に書くとこんな感じでしょう。

  1. CInternetSession オブジェクトを作成。サーバーに接続されます。
  2. CInternetSession::GetHttpConnection をでサーバに接続します。CHttpConnection オブジェクトが返されます。
  3. CHttpConnection::OpenRequest を呼び出して、サーバへの要求をオープンします。CHttpFile オブジェクトが返されます。
  4. CHttpFile::SendRequestを呼び出して、要求を送信します。
  5. CHttpFile より、受信したデータを読み取ります。
  6. 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 ステータスコード" などでググってみてください。

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?