Last active
May 8, 2017 19:00
-
-
Save nekko1119/51a7fa140a977b3d217870ba50bc1d66 to your computer and use it in GitHub Desktop.
WinAPIの通信
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//WinHttpでHTTP通信を行う | |
#define WIN32_LEAN_AND_MEAN | |
#include <Windows.h> | |
#include <winhttp.h> | |
#include <iostream> | |
#include <sstream> | |
#include <vector> | |
#pragma comment(lib, "Winhttp.lib") | |
void CALLBACK callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength) { | |
static std::vector<char> data; | |
static DWORD prev_size{}; | |
static DWORD total_size{}; | |
switch (dwInternetStatus) { | |
case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: { | |
std::cout << "send request complete\n"; | |
if (!WinHttpReceiveResponse(hInternet, nullptr)) { | |
std::cout << "receive failure\n"; | |
} | |
break; | |
} | |
case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: { | |
std::cout << "headers available\n"; | |
DWORD headers_length{}; | |
// ヘッダ情報取れる。取らなくても良い | |
//WinHttpQueryHeaders( | |
// hInternet, | |
// WINHTTP_QUERY_RAW_HEADERS_CRLF, | |
// WINHTTP_HEADER_NAME_BY_INDEX, | |
// WINHTTP_NO_OUTPUT_BUFFER, | |
// &headers_length, | |
// WINHTTP_NO_HEADER_INDEX | |
//); | |
if (!WinHttpQueryDataAvailable(hInternet, nullptr)) { | |
std::cout << "data avaliable check failure\n"; | |
} | |
break; | |
} | |
case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: { | |
std::cout << "data available\n"; | |
auto const size = *reinterpret_cast<DWORD*>(lpvStatusInformation); | |
// 全部読み取った | |
if (size == 0U) { | |
std::string const response(data.begin(), data.end()); | |
std::cout << response; | |
break; | |
} | |
prev_size = total_size; | |
total_size += size; | |
data.resize(total_size); | |
if (!WinHttpReadData(hInternet, data.data() + prev_size, size, nullptr)) { | |
std::cout << "read data failure\n"; | |
} | |
break; | |
} | |
case WINHTTP_CALLBACK_FLAG_READ_COMPLETE: { | |
std::cout << "read completed\n"; | |
// 今回のWinHttpReadDataは完了したが、まだ読み取ってないデータが有るか問い合わせる | |
if (!WinHttpQueryDataAvailable(hInternet, nullptr)) { | |
std::cout << "data avaliable check failure\n"; | |
} | |
break; | |
} | |
case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: { | |
auto const async_result = reinterpret_cast<LPWINHTTP_ASYNC_RESULT>(lpvStatusInformation); | |
std::ostringstream oss; | |
oss << "API: " << async_result->dwResult << " Error: " << async_result->dwError; | |
std::cout << oss.str(); | |
break; | |
} | |
} | |
} | |
int main() | |
{ | |
// セッション作成(通信するためのローカルの情報)、 | |
auto const session = WinHttpOpen( | |
L"", | |
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | |
WINHTTP_NO_PROXY_NAME, | |
WINHTTP_NO_PROXY_BYPASS, | |
WINHTTP_FLAG_ASYNC | |
); | |
if (!session) { | |
std::cout << "winhttp open failure\n"; | |
return 1; | |
} | |
// サーバと接続する | |
auto const connection = WinHttpConnect(session, L"www.nicovideo.jp", INTERNET_DEFAULT_HTTP_PORT, 0U); | |
if (!connection) { | |
std::cout << "connect failure\n"; | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// http接続をする | |
auto const request = WinHttpOpenRequest( | |
connection, | |
L"GET", | |
L"/", | |
L"1.0", | |
WINHTTP_NO_REFERER, | |
WINHTTP_DEFAULT_ACCEPT_TYPES, | |
0U | |
); | |
if (!request) { | |
std::cout << "send request failure\n"; | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// コールバック関数を設定する | |
if (WinHttpSetStatusCallback( | |
request, | |
callback, | |
WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, | |
0U | |
) == WINHTTP_INVALID_STATUS_CALLBACK) { | |
std::cout << "set callback failure\n"; | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// 送信する | |
if (!WinHttpSendRequest( | |
request, | |
WINHTTP_NO_ADDITIONAL_HEADERS, | |
0U, | |
WINHTTP_NO_REQUEST_DATA, | |
0U, | |
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, | |
0U | |
)) { | |
std::cout << "send failure\n"; | |
} | |
std::cout << "sent\n"; | |
// 非同期なので、なんでも良いからとりあえず終わるまで待っておく | |
int n{}; | |
std::cin >> n; | |
// リクエスト解放 | |
WinHttpCloseHandle(request); | |
// コネクション解放 | |
WinHttpCloseHandle(connection); | |
// セッション解放 | |
WinHttpCloseHandle(session); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//WinHttpでHTTP通信を行う | |
#define WIN32_LEAN_AND_MEAN | |
#include <Windows.h> | |
#include <winhttp.h> | |
#include <iostream> | |
#include <sstream> | |
#include <vector> | |
#pragma comment(lib, "Winhttp.lib") | |
int main() | |
{ | |
// セッション作成(通信するためのローカルの情報)、 | |
auto const session = WinHttpOpen( | |
L"", | |
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | |
WINHTTP_NO_PROXY_NAME, | |
WINHTTP_NO_PROXY_BYPASS, | |
0 /*WINHTTP_FLAG_ASYNC*/ | |
); | |
if (!session) { | |
std::cout << "winhttp open failure\n"; | |
return 1; | |
} | |
// サーバと接続する | |
auto const connection = WinHttpConnect(session, L"ext.nicovideo.jp", INTERNET_DEFAULT_HTTP_PORT, 0U); | |
if (!connection) { | |
std::cout << "connect failure\n"; | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// http接続をする | |
auto const request = WinHttpOpenRequest( | |
connection, | |
L"GET", | |
L"/api/getthumbinfo/sm9", | |
L"1.0", | |
WINHTTP_NO_REFERER, | |
WINHTTP_DEFAULT_ACCEPT_TYPES, | |
0U | |
); | |
if (!request) { | |
std::cout << "send request failure\n"; | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// 送信する | |
if (!WinHttpSendRequest( | |
request, | |
WINHTTP_NO_ADDITIONAL_HEADERS, | |
0U, | |
WINHTTP_NO_REQUEST_DATA, | |
0U, | |
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, | |
0U | |
)) { | |
std::cout << "send failure\n"; | |
WinHttpCloseHandle(request); | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// 受信 | |
if (!WinHttpReceiveResponse(request, nullptr)) { | |
std::cout << "receive failure\n"; | |
WinHttpCloseHandle(request); | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// ヘッダの取得 | |
// 必要なサイズを取得してからもう1度実行する | |
// WINHTTP_NO_OUTPUT_BUFFERを渡すとFALSEが返るため、正確なエラーチェックはGetLastErrorを確認する必要がある | |
DWORD headers_length{}; | |
WinHttpQueryHeaders( | |
request, | |
WINHTTP_QUERY_RAW_HEADERS_CRLF, | |
WINHTTP_HEADER_NAME_BY_INDEX, | |
WINHTTP_NO_OUTPUT_BUFFER, | |
&headers_length, | |
WINHTTP_NO_HEADER_INDEX | |
); | |
std::vector<char> headers; | |
headers.resize(headers_length); | |
if (!WinHttpQueryHeaders( | |
request, | |
WINHTTP_QUERY_RAW_HEADERS_CRLF, | |
WINHTTP_HEADER_NAME_BY_INDEX, | |
headers.data(), | |
&headers_length, | |
WINHTTP_NO_HEADER_INDEX | |
)) { | |
std::cout << "receive headers failure\n"; | |
WinHttpCloseHandle(request); | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
std::vector<char> data; | |
DWORD total_size{}; | |
DWORD prev_size{}; | |
while (true) { | |
DWORD size{}; | |
// 読み取るデータのサイズを取得 | |
if (!WinHttpQueryDataAvailable(request, &size)) { | |
std::cout << "data avaliable check failure\n"; | |
break; | |
} | |
if (size == 0U) { | |
break; | |
} | |
prev_size = total_size; | |
total_size += size; | |
data.resize(total_size); | |
if (!WinHttpReadData(request, data.data() + prev_size, size, nullptr)) { | |
std::cout << "read data failure\n"; | |
break; | |
} | |
} | |
// リクエスト解放 | |
WinHttpCloseHandle(request); | |
// コネクション解放 | |
WinHttpCloseHandle(connection); | |
// セッション解放 | |
WinHttpCloseHandle(session); | |
std::string const response(data.begin(), data.end()); | |
std::cout << response.substr(response.find("\r\n\r\n") + 4); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//WinSockでHTTP通信を行う | |
#include <WinSock2.h> | |
#include <iostream> | |
#include <sstream> | |
#pragma comment(lib, "ws2_32.lib") | |
int main() | |
{ | |
// ソケット情報を格納する構造体 | |
WSADATA wsadata; | |
// WinSockの初期化 | |
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) { | |
std::cout << "winsock startup failed.\n"; | |
return 1; | |
} | |
// 指定したサービスプロバイダへのTCPソケットを作成する。 | |
auto const sock = socket(PF_INET, SOCK_STREAM, 0); | |
if (sock == INVALID_SOCKET) { | |
std::cout << "couldn't open a socket.\n"; | |
WSACleanup(); | |
return 1; | |
} | |
// ホスト情報を取得 | |
auto const server_name = "ext.nicovideo.jp"; | |
auto host = gethostbyname(server_name); | |
if (host == nullptr) { | |
auto addr = inet_addr(server_name); | |
host = gethostbyaddr(reinterpret_cast<char*>(&addr), 4, AF_INET); | |
if (host == nullptr) { | |
std::cout << server_name << " is not found.\n"; | |
WSACleanup(); | |
return 1; | |
} | |
} | |
// IPv4のソケットアドレス情報を設定する | |
sockaddr_in sockadd; | |
memset(&sockadd, 0, sizeof(sockadd)); | |
sockadd.sin_family = AF_INET; | |
sockadd.sin_port = htons(80); | |
sockadd.sin_addr = *(reinterpret_cast<LPIN_ADDR>(*(host->h_addr_list))); | |
// 指定したソケットへ接続する | |
if (connect(sock, reinterpret_cast<PSOCKADDR>(&sockadd), sizeof(sockadd)) != 0) { | |
std::cout << "connect failure.\n"; | |
closesocket(sock); | |
WSACleanup(); | |
return 1; | |
} | |
// メッセージを送信 | |
std::string const message = "GET /api/getthumbinfo/sm9 HTTP/1.0\r\nHost: ext.nicovideo.jp\r\n\r\n"; | |
auto const res = send(sock, message.c_str(), static_cast<int>(message.size()), 0); | |
if (res == SOCKET_ERROR) { | |
std::cout << "send failure.\n"; | |
closesocket(sock); | |
WSACleanup(); | |
return 1; | |
} | |
// メッセージを受信 | |
std::ostringstream oss; | |
char buf[1024]; | |
while (true) { | |
memset(buf, '\0', sizeof(buf)); | |
auto size = recv(sock, buf, static_cast<int>(sizeof(buf) - 1), 0); | |
oss << buf; | |
// 受信が終わったらループを抜ける | |
if (size == 0) { | |
break; | |
} | |
if (size == SOCKET_ERROR) { | |
std::cout << "recieve error.\n"; | |
break; | |
} | |
} | |
// ソケットの送受信を切断する | |
shutdown(sock, SD_BOTH); | |
// ソケットを破棄する | |
closesocket(sock); | |
//WinSockの解放 | |
WSACleanup(); | |
std::cout << oss.str().substr(oss.str().find("\r\n\r\n") + 4); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//WinSockでHTTP通信を行う | |
#include <ws2tcpip.h> // for getaddrinfo | |
#include <iostream> | |
#include <sstream> | |
#pragma comment(lib, "ws2_32.lib") | |
int main() | |
{ | |
// ソケット情報を格納する構造体 | |
WSADATA wsadata; | |
// WinSockの初期化 | |
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) { | |
std::cout << "winsock startup failed.\n"; | |
return 1; | |
} | |
// ホスト情報を取得 | |
auto const server_name = "ext.nicovideo.jp"; | |
addrinfo hints; | |
addrinfo* result = nullptr; | |
std::memset(&hints, 0, sizeof(hints)); | |
hints.ai_socktype = SOCK_STREAM; | |
hints.ai_family = PF_UNSPEC; | |
if (getaddrinfo(server_name, "http", &hints, &result)) { | |
std::cout << "getaddrinfo failure\n"; | |
WSACleanup(); | |
return 1; | |
} | |
// 指定したサービスプロバイダへのTCPソケットを作成する。 | |
auto const sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol); | |
if (sock == INVALID_SOCKET) { | |
std::cout << "couldn't open a socket.\n"; | |
freeaddrinfo(result); | |
WSACleanup(); | |
return 1; | |
} | |
// 指定したソケットへ接続する | |
if (connect(sock, result->ai_addr, result->ai_addrlen) != 0) { | |
std::cout << "connect failure.\n"; | |
closesocket(sock); | |
freeaddrinfo(result); | |
WSACleanup(); | |
return 1; | |
} | |
freeaddrinfo(result); | |
// メッセージを送信 | |
std::string const message = "GET /api/getthumbinfo/sm9 HTTP/1.0\r\nHost: ext.nicovideo.jp\r\n\r\n"; | |
auto const res = send(sock, message.c_str(), static_cast<int>(message.size()), 0); | |
if (res == SOCKET_ERROR) { | |
std::cout << "send failure.\n"; | |
closesocket(sock); | |
WSACleanup(); | |
return 1; | |
} | |
// メッセージを受信 | |
std::ostringstream oss; | |
char buf[1024]; | |
while (true) { | |
memset(buf, '\0', sizeof(buf)); | |
auto size = recv(sock, buf, static_cast<int>(sizeof(buf) - 1), 0); | |
oss << buf; | |
// 受信が終わったらループを抜ける | |
if (size == 0) { | |
break; | |
} | |
if (size == SOCKET_ERROR) { | |
std::cout << "recieve error.\n"; | |
break; | |
} | |
} | |
// ソケットの送受信を切断する | |
shutdown(sock, SD_BOTH); | |
// ソケットを破棄する | |
closesocket(sock); | |
//WinSockの解放 | |
WSACleanup(); | |
std::cout << oss.str().substr(oss.str().find("\r\n\r\n") + 4); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//WinHttpでHTTP通信を行う | |
#include <Windows.h> | |
#include <winhttp.h> | |
#include <iostream> | |
#include <sstream> | |
#include <vector> | |
#pragma comment(lib, "Winhttp.lib") | |
int main() | |
{ | |
// セッション作成(通信するためのローカルの情報)、 | |
auto const session = WinHttpOpen( | |
L"", | |
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | |
WINHTTP_NO_PROXY_NAME, | |
WINHTTP_NO_PROXY_BYPASS, | |
0 /*WINHTTP_FLAG_ASYNC*/ | |
); | |
if (!session) { | |
std::cout << "winhttp open failure\n"; | |
return 1; | |
} | |
// サーバと接続する | |
auto const connection = WinHttpConnect(session, L"ext.nicovideo.jp", INTERNET_DEFAULT_HTTP_PORT, 0U); | |
if (!connection) { | |
std::cout << "connect failure\n"; | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// http接続をする | |
auto const request = WinHttpOpenRequest( | |
connection, | |
L"GET", | |
L"/api/getthumbinfo/sm9", | |
L"1.0", | |
WINHTTP_NO_REFERER, | |
WINHTTP_DEFAULT_ACCEPT_TYPES, | |
0U | |
); | |
if (!request) { | |
std::cout << "send request failure\n"; | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// 送信する | |
if (!WinHttpSendRequest( | |
request, | |
WINHTTP_NO_ADDITIONAL_HEADERS, | |
0U, | |
WINHTTP_NO_REQUEST_DATA, | |
0U, | |
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, | |
0U | |
)) { | |
std::cout << "send failure\n"; | |
WinHttpCloseHandle(request); | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
// 受信 | |
if (!WinHttpReceiveResponse(request, nullptr)) { | |
std::cout << "receive failure\n"; | |
WinHttpCloseHandle(request); | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
DWORD headers_length{}; | |
// ヘッダの取得 | |
// 必要なサイズを取得してからもう1度実行する | |
// WINHTTP_NO_OUTPUT_BUFFERを渡すとFALSEが返るため、正確なエラーチェックはGetLastErrorを確認する必要がある | |
WinHttpQueryHeaders( | |
request, | |
WINHTTP_QUERY_RAW_HEADERS_CRLF, | |
WINHTTP_HEADER_NAME_BY_INDEX, | |
WINHTTP_NO_OUTPUT_BUFFER, | |
&headers_length, | |
WINHTTP_NO_HEADER_INDEX | |
); | |
std::vector<char> headers; | |
headers.resize(headers_length); | |
if (!WinHttpQueryHeaders( | |
request, | |
WINHTTP_QUERY_RAW_HEADERS_CRLF, | |
WINHTTP_HEADER_NAME_BY_INDEX, | |
headers.data(), | |
&headers_length, | |
WINHTTP_NO_HEADER_INDEX | |
)) { | |
std::cout << "receive headers failure\n"; | |
WinHttpCloseHandle(request); | |
WinHttpCloseHandle(connection); | |
WinHttpCloseHandle(session); | |
return 1; | |
} | |
std::vector<char> data; | |
DWORD total_size{}; | |
DWORD prev_size{}; | |
while (true) { | |
DWORD size{}; | |
// 読み取るデータのサイズを取得 | |
if (!WinHttpQueryDataAvailable(request, &size)) { | |
std::cout << "data avaliable check failure\n"; | |
break; | |
} | |
if (size == 0U) { | |
break; | |
} | |
prev_size = total_size; | |
total_size += size; | |
data.resize(total_size); | |
if (!WinHttpReadData(request, data.data() + prev_size, size, nullptr)) { | |
std::cout << "read data failure\n"; | |
break; | |
} | |
} | |
// リクエスト解放 | |
WinHttpCloseHandle(request); | |
// コネクション解放 | |
WinHttpCloseHandle(connection); | |
// セッション解放 | |
WinHttpCloseHandle(session); | |
std::string const response(data.begin(), data.end()); | |
std::cout << response.substr(response.find("\r\n\r\n") + 4); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment