Skip to content

Instantly share code, notes, and snippets.

@nekko1119
Last active May 8, 2017 19:00
Show Gist options
  • Save nekko1119/51a7fa140a977b3d217870ba50bc1d66 to your computer and use it in GitHub Desktop.
Save nekko1119/51a7fa140a977b3d217870ba50bc1d66 to your computer and use it in GitHub Desktop.
WinAPIの通信
//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);
}
//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);
}
//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);
}
//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);
}
//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