VC++のHTTP通信についての質問

このQ&Aのポイント
  • VC++2010でHTTP通信のサンプルプログラムを走らせてみたがうまくいかない。
  • サイトや入力方法によって通信結果が異なることについて詳しく知りたい。
  • アドレスを指定してプログラムに自動判断させる方法や、このプログラムの制約について分からない。
回答を見る
  • ベストアンサー

VC++のHTTP通信

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プログラムに関しては全くの素人で分からない事だらけの状態です。できるだけ分り易く書いて頂けると嬉しいです。私が教えて頂きたいことは以下のことです。 ・サイト(通信相手?)による違いはどこで生まれるのでしょうか? ・また、正しくはどのように入力すれば良いのでしょうか?それはどうすれば分かるのでしょうか? ・アドレスを指定しただけであとはプログラムに自動で判断してもらうにはどうすれば良いでしょうか? ・そもそも、このプログラムでは根本的に不可能な事をやろうとしているのでしょうか?もしそうであった場合どうすれば良いでしょうか? 質問だらけで申し訳ありません。誰か分かる方がいらっしゃれば教えて下さい。

質問者が選んだベストアンサー

  • ベストアンサー
  • tsuruharu
  • ベストアンサー率25% (7/28)
回答No.1

すみません、質問に対する直接の回答ではないですがアドバイスを。 VC++でHTTP通信しようと思ったら直接WINSOCKでやるより、 WININETライブラリを使った方が便利です。 WININETはIEの下層となっているライブラリであり、クッキーの処理や SSL通信(https)もサポートしているので後々いろいろやりたいなら こちらのほうが便利です。そうではなくプログラミングの勉強目的 ならWINSOCKでもいいですが。

qazwsx254
質問者

お礼

winsock以外にも方法があるんですね。 調べてみます。ありがとうございました。

その他の回答 (3)

  • unacyo
  • ベストアンサー率51% (35/68)
回答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番台は全て通信終了とみなす、見たいに。

qazwsx254
質問者

お礼

サーバーからの返答はかなり種類があるんですね・・・。 このやり方は少し難しいようなので、アドバイスの通りNo1さんのやり方を調べて見たいと思います。 ありがとうございました。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答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プロトコル』の理解を深める必要はあるでしょう。

qazwsx254
質問者

お礼

そうですね。私はこの辺りの知識がほぼ皆無のようですね・・・。 プログラムのミスなどではなくそういう仕組なんですね。 詳しく教えでくださり、ありがとうございます。

回答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 エラーが帰って来ました。 こちらのサイトでは、存在しないページを指定した場合はエラーを返すようになっているのでしょう。 何が問題なのかわかりません。

qazwsx254
質問者

お礼

エラーとは言っても正常なレスポンスなんですね。 ありがとうございました。

関連するQ&A

  • ゲームの通信プログラムについてなんですが

    ボードゲームで対戦用にとTCP通信プログラムを導入したいのですがどうにもうまくいきません。 ゲームのところでつながっているにはつながっているんですが無限ループのように通信しているようなんです。 VisualStudio2010とwinsocketを使っております。 サーバーのプログラムはこうです。 void COMMU::SERWSA() { port = 6543; //WinSock初期化 rtn = WSAStartup( MAKEWORD(2,2), &wsaData); } void COMMU::SERSOCK() { listen_s = socket( AF_INET, SOCK_STREAM, 0); if(listen_s < 0)     { WSACleanup(); return; } //0で初期化 memset(&saddr, 0, sizeof(SOCKADDR_IN)); saddr.sin_family = AF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = INADDR_ANY; if(bind(listen_s, (struct sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR)     { closesocket(listen_s); WSACleanup(); return; } } void COMMU::SERLIS() { //クライアントからの接続待ち状態にする if(listen(listen_s, 0) == SOCKET_ERROR) { closesocket(listen_s); WSACleanup(); return; } fromlen = (int)sizeof(from); s = accept(listen_s, (SOCKADDR *)&from, &fromlen); if(s == INVALID_SOCKET)     { closesocket(listen_s); WSACleanup(); return; }else{ inet_ntoa(from.sin_addr); } //リスンソケットはもう不要 closesocket(listen_s); MessageBox(NULL,"繋がった","読み込みエラー", MB_OK |MB_ICONERROR); } COMMU::~COMMU() { if(shutdown(s, SD_BOTH) != 0){ perror("シャットダウンに失敗しました\n"); } //ソケットのクローズ closesocket(s); //ソケットのリソース解放 rtn = WSACleanup(); if(rtn == SOCKET_ERROR){ fprintf(stderr, "WSACleanup失敗\n"); return; } printf("WSACleanup成功\n"); printf("サーバ終了\n"); } 続いてクライアントです。 void Client::CLWSA() { //ポート番号の入力 port = 6543; //数値に変換 //WinSock初期化 rtn = WSAStartup( MAKEWORD(2,2),//上位と下位を指定してWORDデータを返すマクロ &wsaData); } void Client::CLSOCK() { //ソケットを開く s = socket( AF_INET, //アドレスファミリ SOCK_STREAM, //TCP(接続型通信)で通信 0); //プロトコル(0:WinSockが自動的に判断) if(s < 0){ //perror("ソケットをオープンできません\n"); WSACleanup(); return; } //ホスト名からホスト情報を取得 lpHost = gethostbyname("PC○○"); if(lpHost == NULL)     { addr = inet_addr(szServer); //ネットワークアドレスからホスト情報を取得 lpHost = gethostbyaddr((char*)&addr,4,AF_INET); } if(lpHost == NULL)    { printf("ホスト情報取得エラー\n"); closesocket(s); WSACleanup(); getchar(); return; } } void Client::CLCONNE() { //0で初期化 memset(&saddr, 0, sizeof(SOCKADDR_IN)); saddr.sin_family = lpHost->h_addrtype; //ホストのアドレスファミリ saddr.sin_port = htons(port); saddr.sin_addr.s_addr = *((u_long *)lpHost->h_addr); //接続要求する if(connect(s, (SOCKADDR *)&saddr, sizeof(saddr)) == SOCKET_ERROR){ printf("connectエラー\n"); closesocket(s); WSACleanup(); getchar(); return; }else{ MessageBox(NULL,"つながりました","読み込みエラー", MB_OK |MB_ICONERROR); } } Client::~Client() { if(shutdown(s, SD_BOTH) != 0){ perror("シャットダウンに失敗しました\n"); } //ソケットのクローズ closesocket(s); //ソケットのリソース解放 rtn = WSACleanup(); if(rtn == SOCKET_ERROR){ fprintf(stderr, "WSACleanup失敗\n"); return; } printf("WSACleanup成功\n"); printf("クライアント終了\n"); } です。 わかりにくいかと思いますがかなり困ってます・・・ 回答よろしくお願いします。

  • winsock recvでの文字化け

    Winsockによりサーバ名、ポート番号、URLを指定するとそのソースファイルをテキスト出力するプログラミングを作成しています。 文字エンコーディングがShift_JISであるページは日本語も正しく表示させることができたのですが、それ以外の文字エンコーディング(EUC-JP、Unicode(UTF-8))のページでは日本語が文字化けしてしまいうまく出力できません。 デバックでrecv関数で文字を取得した際の変数szStrRcvを確認したところ、取得した時点で既に文字化けしているようです。 以下に問題部のソースを示します。 開発環境:WindowsXP Visualstudio.NET2003 VisualC++ WSADATA wsaData; LPHOSTENT lpHost; SOCKET s; int nRtn; SOCKADDR_IN sockadd; _TCHAR szStrRcv[1024]; char szURL[1024] //URL char szStr[256], szYN[4]; u_short sock_port; unsigned int addr; fp = fopen(filename, "a"); sock_port = (u_short)atoi(port); s = socket(PF_INET, SOCK_STREAM, 0); if (s == INVALID_SOCKET) { //perror("ソケットをオープンできません\n"); //WSACleanup(); //return -2; } lpHost = gethostbyname(host); if (lpHost == NULL) { addr = inet_addr(host); lpHost = gethostbyaddr((char *)&addr, 4, AF_INET); //wsprintf(szStr, "%sが見つかりません\n", host); //perror(szStr); //WSACleanup(); //return -3; } memset(&sockadd, 0, sizeof(sockadd)); sockadd.sin_family = AF_INET; sockadd.sin_port = htons(sock_port); sockadd.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list); if (connect(s, (PSOCKADDR)&sockadd, sizeof(sockadd)) != 0) { //perror("サーバーソケットに接続失敗\n"); closesocket(s); } wsprintf(szStr, "GET %s\n", szURL); //szURLには正常にURLが入っている nRtn = send(s, szStr, (int)strlen(szStr), 0); while(1) { memset(szStrRcv, '\0', sizeof(szStrRcv)); ///////////////////////////問題の部分///////////////////////////// nRtn = recv(s, szStrRcv, (int)sizeof(szStrRcv) - 1, 0); _ftprintf(fp, _T("%s\n"), szStrRcv); //HTMLソースを.txtに書き込む //////////この時点でszStrRcvには日本語が文字化けした内容が格納されている/////////////// if (nRtn == 0) break; if (nRtn == SOCKET_ERROR) { perror("recvエラーです\n"); break; } } closesocket(s); WSACleanup(); fclose(fp); 何か対策がありましたらご教授をお願いいたします。

  • VC++でのソケット通信について

    いつも拝見させていただいております。 このたびは、皆様のお知恵をお借りしたく質問させていただきました。 ソケット通信を行いたく、以下のサンプルを作成いたしました。 この関数を5回ループさせると、エラーが起きてしまいます。 エラーコードは10061です。 解決方法をご存知の型が降りましたら、 ご教授ください。 よろしくお願いいたします。 (VC++での開発です) extern "C" __declspec( dllexport ) bool __stdcall ssl_SockOpen(LPSTR p_c_IpAddress, LPSTR p_c_PortNum) { struct sockaddr_in addr; //socketの情報を代入する構造体 WSADATA p_obj_SockInit; //Windows Sockets初期化変数 //■ Windows Socketsを初期化する WSAStartup( 0x0101, &p_obj_SockInit ); //■ ソケット確保 if( (g_obj_Socket = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ){ pMsg = "ソケットの確保に失敗しました。"; return false; } //■ ソケットの情報を入れる memset( &addr, 0, sizeof( addr ) ); //構造体addrの初期化 addr.sin_family = AF_INET; //AF_INETを指定 addr.sin_port = htons( atoi( p_c_PortNum ) ); //ポートを指定 addr.sin_addr.s_addr = inet_addr( p_c_IpAddress ); //inet_addr()により指定されたIPを構造体に代入 //■ 接続要求を行う▼▼▼▼ここでエラー!!▼▼▼▼ if( connect( g_obj_Socket, (struct sockaddr *)&addr, sizeof(addr) ) < 0 ){ pMsg = "接続要求に失敗しました。"; int i; i = GetLastError( ); return false; } return( true ); }

  • コンソールアプリケーションで通信したい

    クライエントプログラムを起動もしていないのに、アクセスがありましたと表示されます。 どこが悪いのか教えてくださいませんでしょうか? サーバー側 #include <stdio.h> #include <winsock2.h> int main() { WSADATA wsaData; LPHOSTENT host; SOCKET s; SOCKADDR_IN name = { AF_INET } , client; int client_addr=sizeof(SOCKADDR_IN); SOCKADDR_IN addr,addr2; addr.sin_family=AF_INET; addr.sin_port=2048; IN_ADDR ip;//実際と異なるアドレス ip.S_un.S_un_b.s_b1=180; ip.S_un.S_un_b.s_b2=328; ip.S_un.S_un_b.s_b3=9; ip.S_un.S_un_b.s_b4=56; addr.sin_addr=ip; WSAStartup(2 , &wsaData); s = socket(AF_INET , SOCK_STREAM , 0); bind(s , (SOCKADDR *)&addr , sizeof(addr)); listen(s , 1); int sizeaddr2=sizeof(addr2); accept(s , (SOCKADDR *)&addr2 , &sizeaddr2); printf("アクセスがありました\nポート %d : アドレス = %s\n" ,addr.sin_port , inet_ntoa(addr.sin_addr)); shutdown(s , SD_BOTH); closesocket(s); WSACleanup(); getchar(); return 0; } クライエント側 #include <stdio.h> #include <winsock2.h> int main() { while(1) { WSADATA wsaData; SOCKET s; WSAStartup(2 , &wsaData); s = socket(AF_INET,SOCK_STREAM , 0); IN_ADDR ip;//実際と異なるアドレス ip.S_un.S_un_b.s_b1=180; ip.S_un.S_un_b.s_b2=328; ip.S_un.S_un_b.s_b3=9; ip.S_un.S_un_b.s_b4=57; SOCKADDR_IN addr; addr.sin_family=AF_INET; addr.sin_port=2048; addr.sin_addr=ip; connect(s,(PSOCKADDR)&addr,sizeof(SOCKADDR)); send(s,"OK",3,0); shutdown(s , SD_BOTH); closesocket(s); WSACleanup(); } return 0; }

  • winsockを使った通信方法

    送信側 #include <winsock2.h> #include <string.h> int main() { WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; typedef struct recv { char Name[32]; int Flag; } RECV; RECV send; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); strcat(send.Name, "ABC"); send.Flag=12; len=sizeof(send); sendto(sock,(char *)&send,len, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); system("pause"); return 0; } 受信側 #include <stdio.h> #include <winsock2.h> #include <string.h> int main() { typedef struct rcv { char Name[32]; int Flag; } RECV; WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; RECV rcv; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = INADDR_ANY; bind(sock, (struct sockaddr *)&addr, sizeof(addr)); len=sizeof(rcv); recv(sock,(char *)&rcv, len, 0); printf("%s [%d]\n",rcv.Name,rcv.Flag); closesocket(sock); WSACleanup(); system("pause"); return 0; } winsockを使ったUDP通信プログラムで構造体データを送る事が出来ないのですが どこに誤りがあるのでしょうか? コンパイルは通ってるのですが、送信側を起動しても受信側で受け取ることが出来ていない状況です。

  • 外部シンボルって

    本に載っていた以下のようなサンプルコード #include <stdio.h> #include <winsock.h> void main( void ) { WSADATA wsadata; if ( WSAStartup( 0x0101, &wsadata ) != 0 ) { printf( "WSAStartup の実行に失敗 %d\n", WSAGetLastError()); } int sock; struct sockaddr_in addr; int ret ; struct hostent *hostinfo; unsigned long inetaddress; char *hostname = "localhost"; inetaddress = inet_addr( hostname ); if ( inetaddress == INADDR_NONE ) { hostinfo = gethostbyname( hostname ); if ( hostinfo == 0 ) { // ホスト名解決に失敗 return ; } inetaddress = *(unsigned long *)hostinfo->h_addr_list[0]; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inetaddress; addr.sin_port = htons(80); sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); ret = connect( sock, (struct sockaddr *)&addr, sizeof addr ); if ( ret < 0 ) { printf( "localhost 80 に接続できなかった" ); return ; } char get[] = "GET /index.html HTTP/1.0\r\n\r\n"; send( sock, get, strlen(get), 0 ); char buf[256]; int n; printf( "recv data\n" ); while ( 1 ) { n = recv( sock, buf, sizeof(buf)-1, 0 ); if ( n <= 0 ) break; buf[ n ] = '\0'; printf( buf ); } closesocket( sock ); WSACleanup(); } をVC++6.0でコンパイルしたのですが sample_client_win.obj : error LNK2001: 外部シンボル "_WSACleanup@0" は未解決です のようなコンパイルエラーが出て実行できません。これはなにが悪いのでしょうか。本に載っているサンプルコードなのでソース自体は間違っていないと思うのですが・・・もしよろしかったらご教授ください。

  • UDP通信について

    UDP通信で困っています。 TCP/IP通信はすぐにうまくいったのですが、 UDPの簡単なサンプルがちゃんと動きません。 間違いがあればご指摘ください。 よろしくお願いします。 (クライアント側ソース int sock; struct sockaddr_in din; memset(&din, 0, sizeof(din)); din.sin_port = htons(50050); din.sin_family = AF_INET; din.sin_addr.s_addr = inet_addr("サーバーIP"); sock = socket(AF_INET, SOCK_DGRAM, 0); int buf = 12345; sendto(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&din,sizeof(struct sockaddr_in)); (サーバー側ソース int sock; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_DGRAM, 0); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(50050); sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { return(1); } struct sockaddr_in fromaddr; socklen_t len = sizeof(struct sockaddr_in); int buf; recvfrom(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&fromaddr,&len); printf("recv:%d\n",buf);

  • getaddrinf()で取得したIPアドレス表示

    お世話になります。 C言語でソケット通信の勉強中です。 CentOS6.4を使っています。 LIST1は、 IPアドレスではなくホスト名がコマンド引数で渡されたとき、 getaddrinfo()でIPアドレスを取得して、 sendto()でサーバにメッセージを送信するだけの、 クライアントのプログラムです。 このLIST1のudp通信自体は上手くいくのですが、 終わりの方で、 getaddrinfo()で取得したIPアドレスを inet_ntoa()を使って文字列表示しようとすると、 セグメンテーション違反です (コアダンプ)となってしまいます。 inet_ntoa()の引数が疑わしく、 いろいろ渡し方を変えたり、参照方法を変えたりしてみたのですが、、 なかなか解決しません。 ちゃんと、192.168.12.1とか表示するにはどうすれば良いでしょうか? ■LIST1 #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <errno.h> int main(int argc,char *argv[]){ int sock; struct addrinfo hints,*res; int n; int err; if(argc != 2){ fprintf(stderr,"Usage : %s dst \n",argv[0]); return 1; } /* IP アドレス表記+ホスト名両方に対応 */ memset(&hints,0,sizeof(hints)); hints.ai_family = AF_UNSPEC; /* IPV4 IPV6 両方に対応 */ hints.ai_socktype = SOCK_DGRAM; err = getaddrinfo(argv[1],"12345",&hints,&res); if(err != 0){ perror("getaddrinfo"); printf("getaddrinfo %s\n",strerror(errno)); printf("getaddrinfo : %s \n",gai_strerror(err)); return 1; } sock = socket(res->ai_family,res->ai_socktype,0); if(sock < 0){ perror("socket"); return 1; } { const char *ipverstr; switch (res->ai_family){ case AF_INET: ipverstr = "IPv4"; break; case AF_INET6: ipverstr = "IPv6"; break; default: ipverstr = "unknown"; break; } printf("ipverstr = %s\n ",ipverstr); } n = sendto(sock,"HELLO",5,0,res->ai_addr,res->ai_addrlen); //n = sendto(sock,"HELLO", 5, 0,(struct sockaddr *)addr, sizeof(addr)); if(n<1){ perror("sendto"); { } return 1; } printf("############ finish !! #######\n"); close(sock); freeaddrinfo(res); struct sockaddr_in *addr; addr = (struct sockaddr_in *)res->ai_addr; printf("inet_ntoa(in_addr)sin = %s\n",inet_ntoa((struct in_addr)addr->sin_addr)); return 0; }

  • ITです。早速ですがwinsockでURLを指定した接続確認をしたいの

    ITです。早速ですがwinsockでURLを指定した接続確認をしたいのですが、うまくいきません。 下記のソースで、URLを指定してinet_addr関数呼び出すと-1、 gethostbynameを呼び出すと0が却ってきてしまい、うまく接続出来ません。 IPアドレス(127.0.0.1)を指定すれば、上記の関数は成功するのですが。 URLからIPアドレスの変換方法が解りません。 どうか助けて下さい。 int main(int argc, char* argv[]) { WSADATA wsaData; sockaddr_in server; SOCKET sock; long err; hostent *host; char *url = "http://www.yahoo.co.jp"; // winsock2の初期化 err = WSAStartup(MAKEWORD(2,0), &wsaData); if (err != 0) { printf("WSAStartup error = %d\n", err); return(-1); } // ソケットの取得 sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { printf("socket error = %d\n", WSAGetLastError()); return(-1); } // IPアドレスの取得 memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(80); server.sin_addr.S_un.S_addr = inet_addr(url); if (server.sin_addr.S_un.S_addr == -1) { host = gethostbyname(url); if (host == NULL) { printf("host not found host = %d\n", WSAGetLastError()); return(-1); } }

  • TCP/IP通信型大文字・小文字変換プログラム

    TCP/IP通信型大文字・小文字変換プログラムを作りたいです。 しかし、うまく2つのプログラムが接続されません。 恐らく、IPアドレスやホスト名の問題だと思います。 超初心者でそこのところをあまり理解していません。 どなたかプログラムの補足をお願いします。 概要は ・クライアント キーボードから文字列を入力し、サーバーに送信。 サーバーから送信された文字列を画面に出力。 ・サーバー クライアントから送信された文字列に対し、 大文字は小文字に、小文字は大文字に変換して返す。 クライアント側プログラム #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #define SOCK_NAME "./socket" int main() { struct sockaddr_in saddr; int soc; char buf[1024]; if ( (soc =socket(AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=inet_addr("192.168.1.1"); saddr.sin_port=htons(1357); if(connect(soc, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("connect"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", soc); while(fgets(buf, 1024, stdin)){ if(buf[strlen(buf) -1] == "\n") buf[strlen(buf) -1] = "\0"; write(soc, buf, 1024); read(soc, buf, 1024); fprintf(stdout, "%s\n", buf); } close(soc); return 0; } サーバー側プログラム #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define SOCK_NAME "./socket" int main() { int i; int fd1, fd2; struct sockaddr_in saddr; struct sockaddr_in caddr; int len; int ret; char buf[1024]; if((fd1 =socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_port=htons(1357); unlink(SOCK_NAME); if(bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } if(listen(fd1,5) < 0 ) { perror("listen"); exit(1); } while(1){ len = sizeof(caddr); if((fd2 = accept(fd1, (struct sockaddr *)&caddr, &len)) < 0){ perror("accept"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", fd2); while((ret = read(fd2, buf, 1024)) > 0 ){ fprintf(stderr, "read: &s\n", buf); for(i=0; i<ret; i++) if(islower(buf[i])) buf[i] = toupper(buf[i]); if(isupper(buf[i])) buf[i] = tolower(buf[i]); fprintf(stderr, "write: %s\n", buf); write(fd2, buf, 1024); } close(fd2); } close(fd1); return 0; }