
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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# C言語階乗の総和を求める 2 2023/03/04 23:31
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Perlで処理の進行状況をユ...
-
ハウスキープ処理について
-
COBOL97,Power-COBOLでの効率の...
-
asp.net の質問です。
-
一般的なソケット通信プログラム
-
XPでは JSPのファイルは...
-
一定時間でPostBackさせたい(A...
-
httpの後に連続してhttpsのアド...
-
アンケートの回答時間を計り,...
-
ASPとCGIの違い
-
サーバー内でPDF自動生成したい...
-
画面サイズ取得について
-
MVCフレームワークでMとCを分け...
-
JSPでのリアルタイムな時刻表示
-
Redirect & transfer
-
JSPの値により遷移先を変更する
-
インターネット エクスプローラ...
-
ジオのHP(HPビルダーでiモー...
-
JSPで<A HREF=
-
腕時計の時報をならないように...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
NetworkStreamからのRead()で、...
-
IIS+VBScriptでの処理待ちについて
-
Webサービスについて(基になる...
-
CPUを2つ搭載するといいのです...
-
アンケートの回答時間を計り,...
-
Perlで処理の進行状況をユ...
-
3層クライアントサーバとMVCの関係
-
<%@ language="VBScript" %>
-
ASPとCGIの違い
-
別のサーバにリクエストを飛ば...
-
Script 系の言語は、ブラウザ上...
-
PerlからDB接続し、データ登録...
-
ラジオボタンをクリックすると...
-
Redirect & transfer
-
ハウスキープ処理について
-
リアルタイム処理のできる言語
-
信頼性
-
VC++のHTTP通信
-
httpの後に連続してhttpsのアド...
-
一定時間でPostBackさせたい(A...
おすすめ情報