![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67b6d)
VC++2010でHTTP通信のサンプルプログラムを走らせてみたのですが、どうも上手く行きません。
ソースは以下の通りです。
#include <stdio.h>
#include <winsock2.h>
int main()
{
WSADATA wsaData;
LPHOSTENT lpHost;
SOCKET s;
int nRtn;
SOCKADDR_IN sockadd;
char szServer[256], szURL[256], szStrRcv[1024], szPort[8];
char szStr[256], szYN[4];
u_short port;
unsigned int addr;
while (1) {
// WinSockを初期化
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
perror("WSAStartupエラーです\n");
return -1;
}
// サーバ名、ポート番号、ファイル名を取得
printf("Webサーバ名----");
gets_s(szServer);
printf("ポート番号----");
gets_s(szPort);
if (strcmp(szPort, "") == 0)
strcpy_s(szPort, "80");
port = (u_short)atoi(szPort);
printf("ファイル名----");
gets_s(szURL);
if (strcmp(szURL, "") == 0)
strcpy_s(szURL, "/");
// ソケットをオープン
s = socket(PF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) {
perror("ソケットをオープンできません\n");
WSACleanup();
return -2;
}
// ホスト名からホスト情報を取得
lpHost = gethostbyname(szServer);
if (lpHost == NULL) {
// アドレスを表す文字列を数値表現に変換
addr = inet_addr(szServer);
// ネットワークアドレスからホスト情報を取得
lpHost = gethostbyaddr((char *)&addr, 4, AF_INET);
if (lpHost == NULL) {
wsprintf(szStr, "%sが見つかりません\n", szServer);
perror(szStr);
WSACleanup();
return -3;
}
}
// SOCKADDR_IN構造体に必要事項をセット
memset(&sockadd, 0, sizeof(sockadd));
sockadd.sin_family = AF_INET;
sockadd.sin_port = htons(port);
sockadd.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list);
// ソケットに接続
if (connect(s, (PSOCKADDR)&sockadd, sizeof(sockadd)) != 0) {
perror("サーバソケットに接続失敗\n");
closesocket(s);
WSACleanup();
return -4;
}
// GETリクエストを送信
wsprintf(szStr, "GET %s HTTP/1.0\r\n\r\n", szURL);
nRtn = send(s, szStr, (int)strlen(szStr), 0);
while(1) {
// 受信用バッファ(szStrRcv)をゼロクリア
memset(szStrRcv, '\0', sizeof(szStrRcv));
// データを受信
nRtn = recv(s, szStrRcv, (int)sizeof(szStrRcv) - 1, 0);
// 受信したデータを標準出力に書き出す
printf("%s", szStrRcv);
if (nRtn == 0)
break;
if (nRtn == SOCKET_ERROR) {
perror("recvエラーです\n");
break;
}
}
if (shutdown(s, SD_BOTH) != 0) { // シャットダウン
perror("シャットダウンに失敗しました\n");
}
closesocket(s); // ソケットをクローズ
WSACleanup(); // WinSockのリソースを解放
printf("\nもう一度実行しますか(Y/N)----");
gets_s(szYN);
if (strcmp(szYN, "n") == 0 || strcmp(szYN, "N") == 0)
break;
}
return 0;
}
例えば、ttp://kumei.jp/c_lang/を開こうしとて、
kumei.jp
80
/c_lang/index.html
と入力した場合は上手くレスポンスが帰ってきますが、
googleに接続しようと思い、
www.google.co.jp
80
/
と入力すると 302 Moved と帰ってきます。
しかし
www.google.co.jp
80
www.google.co.jp
と入力した場合は問題なくgoogleのトップページが帰ってきます。
また、ttp://hako.gob.jp/にアクセスしようとして、
hako.gob.jp
80
/index.html
と入力した場合 DOMAIN ERROR が帰ってきます。
さらに、
hako.gob.jp
80
hako.gob.jp
と入力すると 400 エラーが帰って来ました。
私はwindowsプログラムに関しては全くの素人で分からない事だらけの状態です。できるだけ分り易く書いて頂けると嬉しいです。私が教えて頂きたいことは以下のことです。
・サイト(通信相手?)による違いはどこで生まれるのでしょうか?
・また、正しくはどのように入力すれば良いのでしょうか?それはどうすれば分かるのでしょうか?
・アドレスを指定しただけであとはプログラムに自動で判断してもらうにはどうすれば良いでしょうか?
・そもそも、このプログラムでは根本的に不可能な事をやろうとしているのでしょうか?もしそうであった場合どうすれば良いでしょうか?
質問だらけで申し訳ありません。誰か分かる方がいらっしゃれば教えて下さい。
No.1ベストアンサー
- 回答日時:
すみません、質問に対する直接の回答ではないですがアドバイスを。
VC++でHTTP通信しようと思ったら直接WINSOCKでやるより、
WININETライブラリを使った方が便利です。
WININETはIEの下層となっているライブラリであり、クッキーの処理や
SSL通信(https)もサポートしているので後々いろいろやりたいなら
こちらのほうが便利です。そうではなくプログラミングの勉強目的
ならWINSOCKでもいいですが。
No.4
- 回答日時:
302について
302は、指定されたページが移動していることを示します。
新しいページは、レスポンスヘッダのLocation:が示すURLです。
このURLからサーバ名とURIに分解して再度要求をだします。
サイトの違い
ブラウザでhttp:~/hoge/の様に/で終わるURLを指定すると、ページが見れますが、
実際には一度302が帰ってきて、ページ名を省略された場合のデフォルトページ名が
追加されたURLに誘導されています。
自動化
サーバから返されるレスポンスヘッダの一行目は、必ず HTTP/1.X NNN Description
というフォーマットになっています。
XはHTTPのバージョンで1.0か1.1が帰ってきます。最近はほとんど1.1です。
NNNは三桁の数字で、リクエストに対する結果が入ります。
100番台は処理中であることを示します。サーバの処理に時間がかかる場合などに帰ってきますが、
1.0で要求するとこれは帰ってきません。
200番台は成功を示します。300番台は302の様に指定された場所にページは無いけと、他の場所に
存在する、みたいな情報通知みたいなもの。
400番台は失敗を示します。401(認証失敗)や404(ページがない)。
500番台はサーバ側の要因による失敗。
Descriptionは、前記のコードの簡単な説明。
レスポンスコードは、ググれば出てきます。
このレスポンスコードの番号によって、処理をある程度自動化できます。
結構面倒なので、HTTPを使ってサーバにアクセスするのが目的ならば、
ANo1さんのやつを使う方が簡単です。
通信をやる勉強ならば、レスポンスの百の位の値で分類して、それから302みたいに必要な処理を
個別に処理すれば、取り合えず自動化できます。
400番台(400を除く),500番台はクライアント側では対処できませんし、300番台も302以外は継続できませんから
これら以外の300,400,500番台は全て通信終了とみなす、見たいに。
サーバーからの返答はかなり種類があるんですね・・・。
このやり方は少し難しいようなので、アドバイスの通りNo1さんのやり方を調べて見たいと思います。
ありがとうございました。
No.3
- 回答日時:
>・サイト(通信相手?)による違いはどこで生まれるのでしょうか?
相手方の設定などによる…ということかと。
>・また、正しくはどのように入力すれば良いのでしょうか?それはどうすれば分かるのでしょうか?
ホストの想定している形式で……ということになるかと。
後述する名前ベースのバーチャルホストの場合はHTTP/1.0ではどうにもできないかと。
# Hostヘッダ付けたらいけましたが。
>googleに接続しようと思い、
>www.google.co.jp
>80
>/
>と入力すると 302 Moved と帰ってきます。
サーバが複数あったかと思いますので、ロードバランサなどにより別のサーバへ飛んで欲しい…ということでしょう。
>しかし
>www.google.co.jp
>80
>www.google.co.jp
>と入力した場合は問題なくgoogleのトップページが帰ってきます。
HTTPリクエストとしては…ちょっと変かもしれませんが、サーバ側でよろしく処理してくれた…のでしょう。
プロキシ使った場合のGETリクエストではサーバ名も入ったかと思いますけど……
>また、ttp://hako.gob.jp/にアクセスしようとして、
>hako.gob.jp
>80
>/index.html
>と入力した場合 DOMAIN ERROR が帰ってきます。
名前ベースのバーチャルホストなのかも知れません。
なので、「HTTP/1.1」で「Hostヘッダ」が必要なのでしょう。
そこにHTTP/1.0でHostヘッダ無しのアクセスだった為、どのバーチャルホストへのアクセスなのか不明な為エラーを返答してきたのでしょう。
# レスポンスは「HTTP/1.1 200 OK」ですし…。
>さらに、
>hako.gob.jp
>80
>hako.gob.jp
>と入力すると 400 エラーが帰って来ました。
GETリクエストとして不正だったから…でしょうかねぇ。
googleのようにサーバ内部でよろしく処理してくれなかったのでしょう。
# Hostヘッダが無いのでよろしくしようにも無理なんでしょうが……。
>・アドレスを指定しただけであとはプログラムに自動で判断してもらうにはどうすれば良いでしょうか?
サーバからのレスポンスを見て処理する。
ってところでしょうか。
googleの場合は移動先を指定されている筈ですし。
>・そもそも、このプログラムでは根本的に不可能な事をやろうとしているのでしょうか?もしそうであった場合どうすれば良いでしょうか?
期待する応答とは違うかも知れませんが、『HTTPリクエストを投げてHTTPレスポンスを受ける。』という部分についてはとりあえず動作しているとみていいでしょう。
あとは、『HTTPプロトコル』の理解を深める必要はあるでしょう。
そうですね。私はこの辺りの知識がほぼ皆無のようですね・・・。
プログラムのミスなどではなくそういう仕組なんですね。
詳しく教えでくださり、ありがとうございます。
No.2
- 回答日時:
> www.google.co.jp
> 80
> /
> と入力すると 302 Moved と帰ってきます。
ページがリダイレクトされる場合の正常な応答だと思いますが。
> しかし
> www.google.co.jp
> 80
> www.google.co.jp
> と入力した場合は問題なくgoogleのトップページが帰ってきます。
存在しないページを指定した場合に、強制的にトップページを表示するようになっているのでしょう。
> hako.gob.jp
> 80
> hako.gob.jp
> と入力すると 400 エラーが帰って来ました。
こちらのサイトでは、存在しないページを指定した場合はエラーを返すようになっているのでしょう。
何が問題なのかわかりません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・「I love you」 をかっこよく翻訳してみてください
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・昔のあなたへのアドバイス
- ・かっこよく答えてください!!
- ・あなたが好きな本屋さんを教えてください
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ASPとCGIの違い
-
VC++のHTTP通信
-
Perlで処理の進行状況をユ...
-
CPUを2つ搭載するといいのです...
-
MVCフレームワークでMとCを分け...
-
登録済みイベントリスナーの情...
-
ボタンが活性化の場合とは、ボ...
-
腕時計の時報をならないように...
-
Struts2のタグについて
-
リクエストに応じたselectedの...
-
VB6 開発環境のエディタに行...
-
jspでjavascript関数へ引数を渡...
-
ActiveWorkbook.Pathの一つ下の...
-
MySQL・Tomcat・JSP 何度もSub...
-
VBAでTIFF画像を読み込むには?
-
三菱GOTの画面切り替えについて
-
セッションIDの桁数
-
漏電遮断器の黄色ボタンと白色...
-
setAttribute getAttribute 配...
-
StrutsでPOSTのデータ(リクエ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CPUを2つ搭載するといいのです...
-
NetworkStreamからのRead()で、...
-
Webサービスについて(基になる...
-
画面サイズ取得について
-
PerlからDB接続し、データ登録...
-
IIS+VBScriptでの処理待ちについて
-
一定時間でPostBackさせたい(A...
-
ASPとCGIの違い
-
別のサーバにリクエストを飛ば...
-
処理終了後、他のプログラムへP...
-
Socket通信で、通信終了のイベ...
-
ASPでDLLの呼び出し
-
サーバーの仕組みについて
-
ハウスキープ処理について
-
RedirectとTransferの違い
-
<%@ language="VBScript" %>
-
マルチスレッドチャットプログ...
-
CGI(Perl)のメッセージボックス...
-
Perlで処理の進行状況をユ...
-
簡易DBの作成方法について
おすすめ情報