「Win32/64ネットワーク開発 004 winsockを使ったhttp通信」の版間の差分
(→概要) |
(→概要) |
||
12行目: | 12行目: | ||
なんにしても、複雑なことをする前に、風前の灯となりつつあるHTTP通信の習得からですね。 | なんにしても、複雑なことをする前に、風前の灯となりつつあるHTTP通信の習得からですね。 | ||
<syntaxhighlight lang="cpp" line start=1> | |||
#define WIN32_LEAN_AND_MEAN | |||
#define _WINSOCK_DEPRECATED_NO_WARNINGS | |||
#include <Windows.h> | |||
#include <cstdio> | |||
#include <winsock2.h> | |||
#include <iostream> | |||
#include <string> | |||
#pragma comment( lib, "ws2_32.lib" ) | |||
int main() | |||
{ | |||
WSADATA WSADATAwsaData; | |||
LPHOSTENT LPHOSTENTlpHostnet; | |||
SOCKET SOCKETs; | |||
int iReturn; | |||
SOCKADDR_IN SOCKADDR_INsockadd; | |||
char szServer[256], szURL[256], szStrRcv[1024], szPort[8], szYesNo[4]; | |||
wchar_t wchStr[256]; | |||
u_short u_shortPort; | |||
unsigned int uiAddr; | |||
while (1) { | |||
if (WSAStartup(MAKEWORD(1, 1), &WSADATAwsaData) != 0) { | |||
perror("WSAStartupエラー\n"); | |||
return -1; | |||
} | |||
printf("Webサーバー名(ex.www.yo-net.jp):"); | |||
std::cin >> szServer; | |||
printf("ポート番号(ex.80):"); | |||
std::cin >> szPort; | |||
if (strcmp(szPort, "") == 0) { | |||
strcpy_s(szPort, strlen("80"), "80"); | |||
} | |||
u_shortPort = (u_short)atoi(szPort); | |||
printf("URL(ex.https://www.yo-net.jp/index.html):"); | |||
std::cin >> szURL; | |||
if (strcmp(szURL, "") == 0){ | |||
strcpy_s(szURL, strlen("/"), "/"); | |||
} | |||
//ソケット処理 | |||
SOCKETs = socket(PF_INET, SOCK_STREAM, 0); | |||
if (SOCKETs == INVALID_SOCKET) { | |||
perror("ソケットをオープンできない。\n"); | |||
WSACleanup(); | |||
return -2; | |||
} | |||
//ホスト情報取得処理 | |||
LPHOSTENTlpHostnet = gethostbyname(szServer); | |||
if (LPHOSTENTlpHostnet == NULL) { | |||
uiAddr = inet_addr(szServer); | |||
LPHOSTENTlpHostnet = gethostbyaddr((char*)&uiAddr, 4, AF_INET); | |||
if (LPHOSTENTlpHostnet == NULL) { | |||
int iUTF16Len = MultiByteToWideChar(932, 0, szServer, -1, NULL, 0); | |||
std::wstring wstringCP932Str(iUTF16Len, 0); | |||
if (iUTF16Len > 0) { | |||
MultiByteToWideChar(932, 0, szServer, -1, &wstringCP932Str[0], iUTF16Len); | |||
} | |||
wsprintf(wchStr, L"%sが見つからない\n", wstringCP932Str.c_str()); | |||
int iCP932Len = WideCharToMultiByte(932, 0, wchStr, -1, NULL, 0, NULL, NULL); | |||
std::string stringCP932Str(iCP932Len, 0); | |||
if (iCP932Len > 0) { | |||
WideCharToMultiByte(932, 0, wchStr, -1, &stringCP932Str[0], iCP932Len, NULL, NULL); | |||
} | |||
perror(stringCP932Str.c_str()); | |||
WSACleanup(); | |||
return -3; | |||
} | |||
} | |||
//SOCKADDR型構造体への値設定処理 | |||
memset(&SOCKADDR_INsockadd, 0, sizeof(SOCKADDR_INsockadd)); | |||
SOCKADDR_INsockadd.sin_family = AF_INET; | |||
SOCKADDR_INsockadd.sin_port = htons(u_shortPort); | |||
SOCKADDR_INsockadd.sin_addr = *((LPIN_ADDR)*LPHOSTENTlpHostnet->h_addr_list); | |||
//接続処理 | |||
if (connect(SOCKETs, (PSOCKADDR)&SOCKADDR_INsockadd, sizeof(SOCKADDR_INsockadd)) != 0) { | |||
perror("サーバーソケットに接続失敗\n"); | |||
closesocket(SOCKETs); | |||
WSACleanup(); | |||
return -4; | |||
} | |||
//送信メッセージ形成処理 | |||
int iUTF16Len = MultiByteToWideChar(932, 0, szURL, -1, NULL, 0); | |||
std::wstring wstringCP932Str(iUTF16Len, 0); | |||
if (iUTF16Len > 0) { | |||
MultiByteToWideChar(932, 0, szURL, -1, &wstringCP932Str[0], iUTF16Len); | |||
} | |||
wsprintf(wchStr, L"GET %s HTTP/1.0\r\n\r\n", wstringCP932Str.c_str()); | |||
int iCP932Len = WideCharToMultiByte(932, 0, wchStr, -1, NULL, 0, NULL, NULL); | |||
std::string stringCP932Str(iCP932Len, 0); | |||
if (iCP932Len > 0) { | |||
WideCharToMultiByte(932, 0, wchStr, -1, &stringCP932Str[0], iCP932Len, NULL, NULL); | |||
} | |||
//送信処理 | |||
iReturn = send(SOCKETs, stringCP932Str.c_str(), (int)strlen(stringCP932Str.c_str()), 0); | |||
//受信処理 受信最終文字までループ継続 | |||
while (1) { | |||
memset(szStrRcv, '\0', sizeof(szStrRcv)); | |||
iReturn = recv(SOCKETs, szStrRcv, (int)sizeof(szStrRcv) - 1, 0); | |||
printf("%s", szStrRcv); | |||
if (iReturn == 0){ | |||
break; | |||
} | |||
if (iReturn == SOCKET_ERROR) { | |||
perror("recvエラー\n"); | |||
break; | |||
} | |||
} | |||
//終了処理 シャットダウン→クローズ→WSAクリア | |||
if (shutdown(SOCKETs, SD_BOTH) != 0) { | |||
perror("ソケットシャットダウン失敗\n"); | |||
} | |||
closesocket(SOCKETs); | |||
WSACleanup(); | |||
//プログラム継続判定 | |||
printf("\n再実行(Y/N):"); | |||
std::cin >> szYesNo; | |||
if (strcmp(szYesNo, "n") == 0 || strcmp(szYesNo, "N") == 0){ | |||
break; | |||
} | |||
} | |||
return 0; | |||
} | |||
</syntaxhighlight> | |||
上記のコードはコマンドプロンプトで動くコンソールアプリケーションです。プロジェクトのプロパティでリンカーの入力の追加の依存ファイルに;WSock32.lib;ws2_32.libを追加しなければなりません。 | |||
では少しづつ、動きを確認してみましょう。 | |||
2023年12月4日 (月) 17:44時点における版
前の記事:Win32/64ネットワーク開発 003 wininetを使ったftp通信
次の記事:[[Win32/64ネットワーク開発 005]]
概要
WinSockという通信の窓口を使って、ネットワークを通信してみたいと思います。自分ではネットワークの基礎となる装置を作るのは大変なのでWindowsではコレを使うのが最も基礎的なネットワークのプログラムを始める原点になると思います。
まずはhttp通信を処理するプログラムを作りますが、今はhttpsという通信が主要なので、あまり役に立たないですね。でも、https通信を行うとなると一気に難しくなります。httpsはSSL(Secure Socket Layer)やTLS(Transport Layer Security)という暗号方式で通信を行います。暗号通信おそるべし。そしてftpにもSSLがあります。ftpsですね。リモートにあるサーバを端末から操作する際、通信される一切の情報を暗号化するSSH(Secure SHell)を使ったSFTPもあるか。UNIX系のシェルが備えられている場合に使われるSCP(Secure Copy Protocol)もあるね。いろいろあります。ネットワーク通信楽しいけど、通信の道を出歩くときはちゃんと装備をして出歩かないと、街で強盗に合うような、通信の傍受をされることもあります。悪いことをする人がいなくなるといいんだけど、不平不満がなくならない世界に悪はなくならない。我慢が足りない人はたくさん存在するし、裕福な人の生活があり、そこをうらやむ人がいて、埋めようとする人がいる。ソフトウェアの勉強でもして人生を消費するのも楽しいのにね。Windows/Linux/Macパソコンがあるだけで裕福だと思うし、ましてや電力契約・ネットワーク通信契約が存在する環境があるなんて裕福過ぎる。スマホだと開発はあまりできないから、SNSに時間を消費したり暇になっちゃうかな。ここの管理人はSNSはやらないっすけどね。使い方だけちょろっと知って、あとはそっとしておくっす。
なんにしても、複雑なことをする前に、風前の灯となりつつあるHTTP通信の習得からですね。
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <Windows.h>
#include <cstdio>
#include <winsock2.h>
#include <iostream>
#include <string>
#pragma comment( lib, "ws2_32.lib" )
int main()
{
WSADATA WSADATAwsaData;
LPHOSTENT LPHOSTENTlpHostnet;
SOCKET SOCKETs;
int iReturn;
SOCKADDR_IN SOCKADDR_INsockadd;
char szServer[256], szURL[256], szStrRcv[1024], szPort[8], szYesNo[4];
wchar_t wchStr[256];
u_short u_shortPort;
unsigned int uiAddr;
while (1) {
if (WSAStartup(MAKEWORD(1, 1), &WSADATAwsaData) != 0) {
perror("WSAStartupエラー\n");
return -1;
}
printf("Webサーバー名(ex.www.yo-net.jp):");
std::cin >> szServer;
printf("ポート番号(ex.80):");
std::cin >> szPort;
if (strcmp(szPort, "") == 0) {
strcpy_s(szPort, strlen("80"), "80");
}
u_shortPort = (u_short)atoi(szPort);
printf("URL(ex.https://www.yo-net.jp/index.html):");
std::cin >> szURL;
if (strcmp(szURL, "") == 0){
strcpy_s(szURL, strlen("/"), "/");
}
//ソケット処理
SOCKETs = socket(PF_INET, SOCK_STREAM, 0);
if (SOCKETs == INVALID_SOCKET) {
perror("ソケットをオープンできない。\n");
WSACleanup();
return -2;
}
//ホスト情報取得処理
LPHOSTENTlpHostnet = gethostbyname(szServer);
if (LPHOSTENTlpHostnet == NULL) {
uiAddr = inet_addr(szServer);
LPHOSTENTlpHostnet = gethostbyaddr((char*)&uiAddr, 4, AF_INET);
if (LPHOSTENTlpHostnet == NULL) {
int iUTF16Len = MultiByteToWideChar(932, 0, szServer, -1, NULL, 0);
std::wstring wstringCP932Str(iUTF16Len, 0);
if (iUTF16Len > 0) {
MultiByteToWideChar(932, 0, szServer, -1, &wstringCP932Str[0], iUTF16Len);
}
wsprintf(wchStr, L"%sが見つからない\n", wstringCP932Str.c_str());
int iCP932Len = WideCharToMultiByte(932, 0, wchStr, -1, NULL, 0, NULL, NULL);
std::string stringCP932Str(iCP932Len, 0);
if (iCP932Len > 0) {
WideCharToMultiByte(932, 0, wchStr, -1, &stringCP932Str[0], iCP932Len, NULL, NULL);
}
perror(stringCP932Str.c_str());
WSACleanup();
return -3;
}
}
//SOCKADDR型構造体への値設定処理
memset(&SOCKADDR_INsockadd, 0, sizeof(SOCKADDR_INsockadd));
SOCKADDR_INsockadd.sin_family = AF_INET;
SOCKADDR_INsockadd.sin_port = htons(u_shortPort);
SOCKADDR_INsockadd.sin_addr = *((LPIN_ADDR)*LPHOSTENTlpHostnet->h_addr_list);
//接続処理
if (connect(SOCKETs, (PSOCKADDR)&SOCKADDR_INsockadd, sizeof(SOCKADDR_INsockadd)) != 0) {
perror("サーバーソケットに接続失敗\n");
closesocket(SOCKETs);
WSACleanup();
return -4;
}
//送信メッセージ形成処理
int iUTF16Len = MultiByteToWideChar(932, 0, szURL, -1, NULL, 0);
std::wstring wstringCP932Str(iUTF16Len, 0);
if (iUTF16Len > 0) {
MultiByteToWideChar(932, 0, szURL, -1, &wstringCP932Str[0], iUTF16Len);
}
wsprintf(wchStr, L"GET %s HTTP/1.0\r\n\r\n", wstringCP932Str.c_str());
int iCP932Len = WideCharToMultiByte(932, 0, wchStr, -1, NULL, 0, NULL, NULL);
std::string stringCP932Str(iCP932Len, 0);
if (iCP932Len > 0) {
WideCharToMultiByte(932, 0, wchStr, -1, &stringCP932Str[0], iCP932Len, NULL, NULL);
}
//送信処理
iReturn = send(SOCKETs, stringCP932Str.c_str(), (int)strlen(stringCP932Str.c_str()), 0);
//受信処理 受信最終文字までループ継続
while (1) {
memset(szStrRcv, '\0', sizeof(szStrRcv));
iReturn = recv(SOCKETs, szStrRcv, (int)sizeof(szStrRcv) - 1, 0);
printf("%s", szStrRcv);
if (iReturn == 0){
break;
}
if (iReturn == SOCKET_ERROR) {
perror("recvエラー\n");
break;
}
}
//終了処理 シャットダウン→クローズ→WSAクリア
if (shutdown(SOCKETs, SD_BOTH) != 0) {
perror("ソケットシャットダウン失敗\n");
}
closesocket(SOCKETs);
WSACleanup();
//プログラム継続判定
printf("\n再実行(Y/N):");
std::cin >> szYesNo;
if (strcmp(szYesNo, "n") == 0 || strcmp(szYesNo, "N") == 0){
break;
}
}
return 0;
}
上記のコードはコマンドプロンプトで動くコンソールアプリケーションです。プロジェクトのプロパティでリンカーの入力の追加の依存ファイルに;WSock32.lib;ws2_32.libを追加しなければなりません。
では少しづつ、動きを確認してみましょう。
前の記事:Win32/64ネットワーク開発 003 wininetを使ったftp通信
次の記事:[[Win32/64ネットワーク開発 005]]