top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
WinInetを使ったプログラム開発に携わることに
WinInet APIを使ったプログラム開発に携わることになりました。Visual C++.NETベースで開発する模様です。さて WinInet APIの使い方は 何を見れば良いのでしょう (笑)、、、そういえば Visual C++を使った仕事って 久しぶりです。たまには C++も使わないと忘れてしまいますからね。
ごく簡単な HTTP経由ファイル取得ツール (Visual C++版)読者の方へ、、、バグっていたらツッコミ下さい。(バグっていると ちとマズいのであった…) HttpGet.cpp
/**
* シンプルHTTP GETクライアント
* 2002.11.26 t.iga
*/
#include <afx.h>
#include <afxwin.h>
#include <afxinet.h>
CWinApp theApp;
/**
* 転送時のバッファサイズ
*/
const int BUF_SIZE = 2048;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) {
// MFC を初期化して、エラーの場合は結果を印刷します。
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {
_tprintf(_T("MFCの初期化に失敗しました.\n"));
return 1;
}
if (argc <= 1) {
printf("Usage: HttpGet.exe http://www.google.co.jp/\n");
return -1;
}
try {
char* uri = argv[1];
DWORD protocol = 0;
CString serverName;
CString fileName;
INTERNET_PORT port;
if (AfxParseURL(uri, protocol, serverName, fileName, port) == false) {
printf("URLの分解に失敗しました。");
return -1;
}
printf("プロトコル[%ld] ポート[%ld] サーバ[%s] ファイル名[%s]\n",
protocol, port, (LPCSTR)serverName, (LPCSTR)fileName);
CInternetSession session("HttpGet - simple http client");
CHttpConnection* conn = session.GetHttpConnection(
serverName,
CHttpConnection::HTTP_VERB_GET,
port, NULL, NULL);
CHttpFile* file = conn->OpenRequest(
CHttpConnection::HTTP_VERB_GET, fileName,
NULL, 1, NULL, NULL,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE);
file->AddRequestHeaders("Accept: text/*\r\nUser-Agent: HttpGet\r\n");
file->SendRequest();
DWORD statusCode;
file->QueryInfoStatusCode(statusCode);
if (statusCode >= 300) {
printf("何かしらエラー:%ld\n", statusCode);
return -1;
}
TCHAR buf[BUF_SIZE + 1];
for (;;) {
int result = file->Read(buf, BUF_SIZE);
if (result <= 0) {
break;
}
buf[result] = 0x00;
printf(buf);
}
file->Close();
delete file;
conn->Close();
delete conn;
session.Close();
} catch (CInternetException* ex) {
TCHAR szMsg[1024];
ex->GetErrorMessage(szMsg, 1024);
printf("Error occur: %s", szMsg);
ex->Delete();
}
return 0;
}
WinInetはCOMベースであるような記述があり、とりあえずMFCラッパー側で実装してみました。でもそれとは別に Win32 Platform SDK に wininet.hというヘッダーファイルがありこっちは生でAPIが呼べるようにも思います。さてはて。(気分的には 生でAPIを呼びたいのですけれどもね)
で、もう少しつっこんで調べてみたら、HINTERNET InternetOpen()というWin32 APIがあるのがわかりました。こっちは 生APIで C++ではなくってC風に記述できます。さあて Cで行くべきかC++で行くべきか…。ちなみに C言語で生APIの方法は 下記ページに詳細が載っていました。
良くできたウェブページでした。
2002.12.10 追記
Cでアクセスするために別のサンプルを探したりしてみました。(MFCのAPIが どうも怪しいので…)下記のページを参考にしました。
HTTPサーバーからページを受信する http://www.athomejp.com/goldfish/api/wininetreadfile.html
HTTPでリモートのファイルを取得(C言語) http://tokyo.cool.ne.jp/masapico/api_sample_inet04_c.html
できあがった C言語API側のWinInetを呼び出すバージョンです。
(笑) HttpGet.c (C言語バージョン)
/**
* シンプルHTTP GETクライアント
* wininet.libをリンクに追加することが必要です。
* 2002.12.10 t.iga
*/
#include <windows.h>
#include <wininet.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE (1024)
int main(int argc, char* argv[])
{
HINTERNET hsession = 0;
HINTERNET hconnect = 0;
HINTERNET hrequest = 0;
char szBuf[1025];
DWORD dwSize = 0;
hsession = InternetOpen("HttpGet - simple http client",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if (hsession == NULL)
{
printf("hsession==NULL");
return -1;
}
hconnect = InternetConnect(
hsession,
"www.tcct.zaq.ne.jp",
80,
"iga",
"password",
INTERNET_SERVICE_HTTP,
0,
10000);
if (hconnect == NULL)
{
printf("hconnect==NULL");
return -1;
}
hrequest = HttpOpenRequest(
hconnect,
"GET",
"/iga/tosiki/igapyon/diary/2002/ig021126.html",
NULL,
NULL,
NULL,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE,
NULL);
if (hrequest == NULL)
{
printf("hrequest==NULL");
return -1;
}
if (HttpSendRequest(
hrequest,
NULL,
0,
NULL,
0) == FALSE)
{
printf("HttpSendRequest() が失敗しました\n");
return -1;
}
szBuf[0] = 0;
{
dwSize = BUFSIZE;
if (HttpQueryInfo(
hrequest,
HTTP_QUERY_CONTENT_LENGTH,
szBuf, &dwSize, 0))
{
szBuf[dwSize] = 0;
printf("長さ[%s]\n", szBuf);
}
dwSize = BUFSIZE;
if (HttpQueryInfo(
hrequest,
HTTP_QUERY_STATUS_CODE,
szBuf, &dwSize, 0))
{
szBuf[dwSize] = 0;
printf("ステータス[%s]\n", szBuf);
}
dwSize = BUFSIZE;
if (HttpQueryInfo(
hrequest,
HTTP_QUERY_STATUS_TEXT,
szBuf, &dwSize, 0))
{
szBuf[dwSize] = 0;
printf("ステータス文字列[%s]\n", szBuf);
}
}
for (;;)
{
dwSize = BUFSIZE;
if (InternetReadFile(
hrequest,
szBuf,
dwSize,
&dwSize) == FALSE)
{
break;
}
if (dwSize <= 0)
{
break;
}
szBuf[dwSize] = 0;
printf("%s\n", szBuf);
}
InternetCloseHandle(hrequest);
InternetCloseHandle(hconnect);
InternetCloseHandle(hsession);
return 0;
}
やっぱりMFCを使わない方が 私には似合っています。
関連する日記
ごごごってJavaのプログラミングをしました。とっても効率よくコーディングしたのですが、500行くらいしか書くことが出来ませんでした。というか効率良く書いた場合には 私は 500行/1日程度なのでしょうかね(笑)