<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C++ | バスにっき</title>
	<atom:link href="https://takabus.com/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>https://takabus.com</link>
	<description>バスに関するニュース・マメ知識を紹介しています</description>
	<lastBuildDate>Thu, 08 Apr 2021 05:24:39 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.3</generator>

<image>
	<url>https://takabus.com/wp-content/uploads/2022/08/cropped-takabusサイトロゴスクエア余白なし-1-32x32.png</url>
	<title>C++ | バスにっき</title>
	<link>https://takabus.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【C++】POSTでデータを送信するには？WinINetを使ってPOSTする方法</title>
		<link>https://takabus.com/cpp-wininet/</link>
					<comments>https://takabus.com/cpp-wininet/#respond</comments>
		
		<dc:creator><![CDATA[takabus]]></dc:creator>
		<pubDate>Thu, 25 Mar 2021 01:04:26 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[GET]]></category>
		<category><![CDATA[WinINet]]></category>
		<category><![CDATA[Win32]]></category>
		<category><![CDATA[POST]]></category>
		<guid isPermaLink="false">https://nikki.takabus.com/?p=3958</guid>

					<description><![CDATA[C++（Win32）でPOSTしたいときの方法を紹介します。Win32ではWinINetを使用すると、比較的かんたんにPOSTすることができます。当記事ではWinINetを使用したPOSTの方法をサンプルコードとあわせて紹介していきます。]]></description>
										<content:encoded><![CDATA[
<p>　C++（Win32）でPOSTしたいときの方法を紹介します。Win32ではWinINetを使用すると、比較的かんたんにPOSTすることができます。当記事では、WinINetを使用したPOSTの方法をサンプルコードとあわせて紹介していきます。</p>



<h2 class="wp-block-heading">サンプルコード</h2>



<p>さっそくサンプルコードを公開します。</p>



<p>URL「http://192.168.1.4/test/test.php」に、次のデータをPOSTする例です。</p>



<ul><li><span class="marker-animation">キー「a」値「1234」</span></li><li><span class="marker-animation">キー「b」値「5678」</span></li></ul>



<pre class="wp-block-code"><code>// ConsoleApplication1.cpp : このファイルには 'main' 関数が含まれています。プログラム実行の開始と終了がそこで行われます。
//

#include &lt;iostream&gt;//std::coutなど使うのに必要
#include &lt;tchar.h&gt;//_Tを使うのに必要
#include &lt;windows.h&gt;//wininet.hを使うのに必要
#include &lt;wininet.h&gt;//HTTP通信に必要

//追加の依存ファイルにwininet.libを設定
#pragma comment (lib, "wininet.lib")


int main()
{
	// インターネット接続のハンドルを作成
	HINTERNET hInternet = InternetOpen(
		NULL, //User-Agentに設定したい文字列を指定する
		INTERNET_OPEN_TYPE_PRECONFIG,//接続方法（直接接続・プロキシ使用）を指定する
		NULL,//プロキシサーバーのアドレスを指定する
		NULL,//プロキシサーバー使用時、プロキシを経由させないで直接接続するアドレスを指定する
		0//オプション
	);

	// インターネット接続を確立して、コネクトハンドルを得る
	HINTERNET hConnect = InternetConnect(
		hInternet,
		_T("192.168.1.4"),//サーバーアドレス
		INTERNET_DEFAULT_HTTP_PORT,//ポート番号を指定する
		NULL,//認証ユーザー名を指定する
		NULL,//認証パスワードを指定する
		INTERNET_SERVICE_HTTP,//サービスタイプ(HTTP・FTP)を指定する
		0,//FTP接続時、パッシブモードにするかどうか指定する
		0
	);

	// リクエストを開いて、リクエストハンドルを得る
	HINTERNET hRequest = HttpOpenRequest(
		hConnect,
		_T("POST"),//POSTにする
		_T("/test/test.php"), //ホスト名以下
		_T("HTTP/1.1"),//HTTPプロトコルバージョン
		NULL, NULL, INTERNET_FLAG_RELOAD, 0);

	// ヘッダーを設定する
	wchar_t header&#91;] = L"Content-Type: application/x-www-form-urlencoded; charset=utf-8";//コンテンツタイプをFORMに指定

	//送信データを指定する
	char data&#91;] = "a=1234&amp;b=5678";

	// リクエストを送信する
	BOOL r = HttpSendRequest(
		hRequest,//リクエストハンドルを指定する
		header, //ヘッダーを指定する
		wcslen(header), //ヘッダーのサイズを求めて指定する
		(LPVOID)(data),//送信コンテンツを指定する
		strlen(data) //送信コンテンツのサイズを求めて指定する
	);

	// エラーがあれば表示する
	std::cout &lt;&lt; GetLastError() &lt;&lt; std::endl;

        // ハンドルを閉じる
	InternetCloseHandle(hInternet);
}</code></pre>



<p>実行すると、サーバーに次のようなデータが届きます。</p>



<pre class="wp-block-code"><code>2020-12-10 12:15:08 Array //リクエストヘッダー
(
    &#91;Content-Type] =&gt; application/x-www-form-urlencoded
    &#91;Host] =&gt; 192.168.1.4
    &#91;Content-Length] =&gt; 13
    &#91;Cache-Control] =&gt; no-cache
)

2020-12-10 12:15:08 Array //POSTデータ
(
    &#91;a] =&gt; 1234
    &#91;b] =&gt; 5678
)</code></pre>



<p>きちんとPOSTできていますね。</p>



<p>▼PHPでリクエストヘッダとPOSTされたデータを書き出す方法は、次のページで紹介しています。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-together">

<a href="https://takabus.com/201214-dump-post-data-php/" title="【PHP】POST・GETされたデータとヘッダーをロギングする方法" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://takabus.com/wp-content/uploads/2021/03/image-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://takabus.com/wp-content/uploads/2021/03/image-160x90.png 160w, https://takabus.com/wp-content/uploads/2021/03/image-120x68.png 120w, https://takabus.com/wp-content/uploads/2021/03/image-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">【PHP】POST・GETされたデータとヘッダーをロギングする方法</div><div class="blogcard-snippet internal-blogcard-snippet">デバッグするときに、POST・GETで送信したデータやリクエストヘッダーを確認したいときがあります。こういったデータをテキストファイルに書き出すPHPコードを掲載しておきます。かんたんにクライアントからのリクエストを把握できるようになるので、とても便利ですよ～</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://takabus.com" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">takabus.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2021.01.10</div></div></div></div></a>
<p></p>
</div>



<h2 class="wp-block-heading">解説</h2>



<p>　C#（.NET）なら、WebRequestを使ってかんたんにPOSTできますが、<strong><span class="marker-animation">C++ではWinINetを使用します。</span></strong></p>



<p>　WinINetのほかにWinHTTPというAPIもありますが、通常は使用する必要はありません。WinHTTPのWebクライアントとしての機能は、WinINetに内包されています。よって、クライアントとしてPOSTするだけなら、基本的にWinINetを使用すればOKです。逆に、HTTPサーバーを構築するときは、WinHTTPを使用する必要があります。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img fetchpriority="high" decoding="async" width="559" height="336" src="https://takabus.com/wp-content/uploads/2021/03/image-4.png" alt="" class="wp-image-3962" srcset="https://takabus.com/wp-content/uploads/2021/03/image-4.png 559w, https://takabus.com/wp-content/uploads/2021/03/image-4-300x180.png 300w" sizes="(max-width: 559px) 100vw, 559px" /></figure></div>



<p>　次のページにWinINetとWinHTTPの機能比較表が掲載されていますが、利用可能な機能もWinINetのほうが多いです。WinINetなら、HTTPのみならず、FTPも使用することができます。</p>




<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/wininet-vs-winhttp" title="WinINet vs. WinHTTP - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">WinINet vs. WinHTTP - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">Learn how to choose between WinInet and WinHTTP. Read a comparison of features, and review related topics.</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/wininet-vs-winhttp" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>



<h3 class="wp-block-heading">処理の流れ</h3>



<p>　まず、全体の流れを整理します。</p>



<div class="wp-block-cocoon-blocks-blank-box-1 blank-box block-box has-border-color has-amber-border-color">
<ol><li><strong>InternetOpen・・・初期化</strong></li><li><strong>InternetConnect・・・セッション開始</strong></li><li><strong>HttpOpenRequest・・・リクエスト作成</strong></li><li><strong>HttpSendRequest・・・データの送信</strong></li></ol>
</div>



<p>　最初に<strong>InternetOpen関数</strong>を実行します。</p>



<pre class="wp-block-code"><code>void InternetOpenW(
  LPCWSTR lpszAgent,
  DWORD   dwAccessType,
  LPCWSTR lpszProxy,
  LPCWSTR lpszProxyBypass,
  DWORD   dwFlags
);</code></pre>



<p>　InternetOpen関数を実行することで、WinINetが初期化されます。初期化が完了すると、ハンドルが返されます。以降、ここで得られたハンドルを使用して、処理を行っていきます。</p>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-tips block-box has-border-color has-yellow-border-color">
<p><span class="badge">ギモン</span><strong> <span class="marker-animation">void型なのにHANDLEが返るってどういうこと？</span></strong></p>



<p>C++のvoid型というのは、「型指定なしのポインタ（void*型）」のことを指しています。</p>



<p>HANDLE型も、実体は型指定なしのポインタ（すなわちvoid*型）です。よって、HANDLEを返す関数の返り値はvoid型であるといえます。</p>



<p>C#に慣れていると、「void型＝返り値なし」という認識になりがちですが、C++では何も返さないとは限らないので、注意が必要です。</p>
</div>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-comment block-box has-border-color has-pink-border-color">
<p>Unicode対応版としてビルドした場合、InternetOpen関数をはじめ、ほとんどの関数はワイド文字対応版の関数（末尾に「W」がついている関数）に置き換えられます。（既定ではUnicode対応版としてビルドされます。）よって、<strong><span data-ma_color="#fac0ff" class="marker-animation">InternetOpen関数とInternetOpenW関数は同じものとして考えてもらってかまいません。</span></strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="840" height="564" src="https://takabus.com/wp-content/uploads/2021/03/image-2.png" alt="" class="wp-image-3960" srcset="https://takabus.com/wp-content/uploads/2021/03/image-2.png 840w, https://takabus.com/wp-content/uploads/2021/03/image-2-300x201.png 300w, https://takabus.com/wp-content/uploads/2021/03/image-2-768x516.png 768w, https://takabus.com/wp-content/uploads/2021/03/image-2-272x182.png 272w" sizes="(max-width: 840px) 100vw, 840px" /><figcaption>既定では、ワイド文字対応版の関数が使用されるようになっています。</figcaption></figure>
</div>



<p>　次に<strong><span class="marker-animation">InternetConnect関数</span></strong>を実行します。</p>



<pre class="wp-block-code"><code>void InternetConnectW(
  HINTERNET     hInternet,
  LPCWSTR       lpszServerName,
  INTERNET_PORT nServerPort,
  LPCWSTR       lpszUserName,
  LPCWSTR       lpszPassword,
  DWORD         dwService,
  DWORD         dwFlags,
  DWORD_PTR     dwContext
);</code></pre>



<p>　これにより、サーバーに接続が行われ、セッションが開始されます。</p>



<p>　あとは、HTTPOpenRequest関数とHTTPSendRequest関数により、データをPOSTします。</p>



<pre class="wp-block-code"><code>// リクエストを開いて、リクエストハンドルを得る
HINTERNET hRequest = HttpOpenRequest(
	hConnect,
	_T("POST"),//POSTにする
	_T("/test/test.php"), //ホスト名以下
	_T("HTTP/1.1"),//HTTPプロトコルバージョン
	NULL, NULL, INTERNET_FLAG_RELOAD, 0);

// ヘッダーを設定する
wchar_t header&#91;] = L"Content-Type: application/x-www-form-urlencoded";//コンテンツタイプをFORMに指定

//送信データを指定する
char data&#91;] = "a=1234&amp;b=5678";

// リクエストを送信する
BOOL r = HttpSendRequest(
	hRequest,//リクエストハンドルを指定する
	header, //ヘッダーを指定する
	wcslen(header), //ヘッダーのサイズを求めて指定する
	(LPVOID)(data),//送信コンテンツを指定する
	strlen(data) //送信コンテンツのサイズを求めて指定する
);</code></pre>



<p>　POSTでデータを送信する際には、何らかのMIMEタイプにデータをエンコードする必要があります。jsonなどをはじめ、使用できるMIMEタイプは多岐にわたりますが、今回はformタグを送信する際に使用される「application/x-www-form-urlencoded」を採用します。この場合、送信データは「キー＝値」のペアを&amp;で区切る形でエンコードされますので、送信データもそれに従って定義しておきます。</p>



<pre class="wp-block-code"><code>//送信データを指定する
char data&#91;] = "a=1234&amp;b=5678";</code></pre>




<a rel="noopener" href="https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/POST" title="POST &#12522;&#12463;&#12456;&#12473;&#12488;&#12513;&#12477;&#12483;&#12489; - HTTP | MDN" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://s.wordpress.com/mshots/v1/https%3A%2F%2Fdeveloper.mozilla.org%2Fja%2Fdocs%2FWeb%2FHTTP%2FMethods%2FPOST?w=160&#038;h=90" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">POST &#12522;&#12463;&#12456;&#12473;&#12488;&#12513;&#12477;&#12483;&#12489; - HTTP | MDN</div><div class="blogcard-snippet external-blogcard-snippet">POST は HTTP のメソッドで、サーバーにデータを送信します。リクエストの本体の型は Content-Type ヘッダーで示されます。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://developer.mozilla.org/ja/docs/Web/HTTP/Methods/POST" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">developer.mozilla.org</div></div></div></div></a>



<p>　リクエストヘッダーのContent-typeにも、「application/x-www-form-urlencoded」を指定しておきます。これでサーバーは受け取ったデータを適切にパースしてくれるようになります。</p>



<pre class="wp-block-code"><code>// ヘッダーを設定する
wchar_t header&#91;] = L"Content-Type: application/x-www-form-urlencoded";//コンテンツタイプをFORMに指定</code></pre>



<p>　リクエストの送信が完了したら、ハンドルを破棄しましょう。</p>



<pre class="wp-block-code"><code>//ハンドルを閉じる(hRequestなどは同時に閉じられるのでClose不要)
InternetCloseHandle(hInternet);</code></pre>



<p>　当プログラムでは、複数のハンドルが使用されていますが、hInternetハンドルだけ閉じれば十分です。二次的に生成されているhRequestなどのハンドルは、自動的に同時に閉じられます。</p>



<p>　POSTによる送信については以上です。エラーはGetLastError関数で取得できますので、うまくいかないときは追加してみてください。</p>



<h2 class="wp-block-heading">レスポンスを取得するには？</h2>



<p>　POSTした後、サーバーからのレスポンスを取得したいケースもあるでしょう。サーバーからのレスポンスは、<strong>hRequestハンドル</strong>にFileとして格納されています。</p>



<p>　<a href="https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetreadfile">InternetReadFile関数</a>を使用すると、格納されているレスポンスデータを読み出すことができます。</p>



<h3 class="wp-block-heading">サンプルコード</h3>



<p><code>InternetCloseHandle(hInternet);</code>の前に、次のコードを追加してください。</p>



<pre class="wp-block-code"><code>
//レスポンス取得・表示

char buf&#91;1024] = { 0 };//バッファ
DWORD size = 1024;//1回あたり読み出すサイズ
BOOL bResult;
DWORD lpdwReadLength;

for (;;) {

	//レスポンスを取得する
	bResult = InternetReadFile(hRequest, buf, sizeof(buf), &amp;lpdwReadLength);

	//読み出しサイズ0以下のとき、ループを抜ける
	if (lpdwReadLength &lt;= 0) {
		break;
	}

	//バッファを出力する
	printf("%s", buf);
	//std::cout &lt;&lt; buf;
}

// エラーがあれば表示する
std::cout &lt;&lt; GetLastError() &lt;&lt; std::endl;

//ハンドルを閉じる(hRequestなどは同時に閉じられるのでClose不要)
InternetCloseHandle(hInternet);</code></pre>



<p>これを追加して実行すると、コンソールにレスポンスが出力されます。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="595" height="374" src="https://takabus.com/wp-content/uploads/2021/03/image-6.png" alt="" class="wp-image-3964" srcset="https://takabus.com/wp-content/uploads/2021/03/image-6.png 595w, https://takabus.com/wp-content/uploads/2021/03/image-6-300x189.png 300w" sizes="(max-width: 595px) 100vw, 595px" /><figcaption>レスポンスを表示。最後の0はGetLastErrorによるもの。</figcaption></figure></div>



<h3 class="wp-block-heading">解説</h3>



<p>　<a href="https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetreadfile">InternetReadFile関数</a>は、hRequestハンドルの中に格納されているレスポンスボディを読み出します。</p>



<pre class="wp-block-code"><code>BOOLAPI InternetReadFile(
  HINTERNET hFile,
  LPVOID    lpBuffer,
  DWORD     dwNumberOfBytesToRead,
  LPDWORD   lpdwNumberOfBytesRead
);</code></pre>



<p>　第3引数に、1回あたり読み出すバイト数を指定します。読み出されたデータ（文字配列）は、第2引数に出力されます。第2引数に文字型配列（char[]）を指定することで、指定したバイト数だけ、サーバーからのレスポンスを文字列として取り出せるという仕組みです。これをforでループさせて、レスポンス全体を取得します。</p>



<p>　使用する変数は、最初に定義してあります。</p>



<pre class="wp-block-code"><code>char buf&#91;1024] = { 0 };//バッファ
DWORD size = 1024;//1回あたり読み出すサイズ
BOOL bResult;
DWORD lpdwReadLength;</code></pre>



<div class="wp-block-cocoon-blocks-tab-box-1 blank-box bb-tab bb-check block-box has-border-color has-lime-border-color">
<p><strong><span class="marker-under">NULL終端</span></strong></p>



<p>Cでの文字列は、必ずNULLで終わっていなければならないというルールがあります。これを<strong>NULL終端</strong>といいます。</p>



<p>今回、バッファとして使用する配列（buf）は、変数定義の時点でゼロクリアしておきました。<code>buf[1024]={0}</code>とは、次のコードを実行しているのとほぼ同義です。</p>



<pre class="wp-block-code"><code>for (int i = 0; i &lt; 1024; i++) {
	buf&#91;i] = '\0';
}</code></pre>



<p>これをせずに、ただの空配列としてbufを定義してしまうと、bufがレスポンスデータで埋めつくされない場合に問題が出ます。末尾の要素が不定となってしまい、以下のような実行結果になってしまいます。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="653" height="512" src="https://takabus.com/wp-content/uploads/2021/04/image-39.png" alt="" class="wp-image-4129" srcset="https://takabus.com/wp-content/uploads/2021/04/image-39.png 653w, https://takabus.com/wp-content/uploads/2021/04/image-39-300x235.png 300w" sizes="(max-width: 653px) 100vw, 653px" /><figcaption>NULL終端させないと、末尾におかしなデータが。。。</figcaption></figure></div>



<p>NULL終端に関わる部分は、脆弱性の元となることもあります。次のページに詳しい解説がなされていますので、興味があれば参照してみてください。</p>




<a rel="noopener" href="https://codezine.jp/article/detail/4644" title="文字列はNULL終端させる　――C/C++セキュアコーディング入門（3）" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://codezine.jp/static/common/images/czlogo4fb_ogp.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">文字列はNULL終端させる　――C/C++セキュアコーディング入門（3）</div><div class="blogcard-snippet external-blogcard-snippet">文字列操作に関するプログラミングエラーはいくつかありますが、今回は基本的であるが間違いを犯しやすい文字列のNULL終端エラーについて解説します。</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=http://codezine.jp/article/detail/4644" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">codezine.jp</div></div></div></div></a>
</div>



<h2 class="wp-block-heading">ステータスコードを取得するには？</h2>



<p>　ステータスコードなど、各種情報を取得したいときには<strong>HttpQueryInfo関数</strong>を使用します。</p>



<p><strong>例）ステータスコードを取得する</strong></p>



<pre class="wp-block-code"><code>
//ステータスコード取得
DWORD buf2 = { 0 };
DWORD buf2len = sizeof(buf2);

HttpQueryInfoW(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &amp;buf2, &amp;buf2len, 0);

printf("%d", buf2);
</code></pre>



<p>　実行すると、ステータスコードが表示されます。</p>



<pre class="wp-block-code"><code>404</code></pre>



<p>　ステータスコード以外にも、HttpQueryInfo関数を使用すると、ヘッダーに含まれる様々な情報を取得することができます。第2引数にパラメーターを指定することで、取得するデータを切り替えることができます。指定できるパラメータは、次のページにまとめられています。</p>




<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/query-info-flags" title="Query Info Flags (Wininet.h) - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">Query Info Flags (Wininet.h) - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">The following lists contain the attributes and modifiers used by HttpQueryInfo and QueryInfo.</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/query-info-flags" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>



<h2 class="wp-block-heading">日本語のデータを送るには？</h2>



<p>　基本的にこのままでOKです。data変数に日本語を追加してもらえれば、日本語も送れるはずです。</p>



<pre class="wp-block-preformatted">char data[] = "a=1234&amp;b=5678&amp;あ=あいうえお";</pre>



<p>　実際にやってみたところ、日本語も送信することができました。</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="406" height="198" src="https://takabus.com/wp-content/uploads/2021/03/image-1.png" alt="" class="wp-image-3959" srcset="https://takabus.com/wp-content/uploads/2021/03/image-1.png 406w, https://takabus.com/wp-content/uploads/2021/03/image-1-300x146.png 300w" sizes="(max-width: 406px) 100vw, 406px" /><figcaption>日本語も送信できました。取得方法は<a href="https://takabus.com/201214-dump-post-data-php/" data-type="post" data-id="3944">こちら</a></figcaption></figure></div>



<div class="wp-block-cocoon-blocks-icon-box information-box common-icon-box block-box">
<p>ただし、環境によっては、文字コードの変換などが必要となる可能性があります。 </p>
</div>



<h2 class="wp-block-heading">WinINetのオプションを活用する</h2>



<p>　WinINetには、さまざまなオプションが用意されています。オプションを設定するには<strong>InernetSetOption関数</strong>を使用します。タイムアウト時間を変更したり、接続失敗時に自動的にリトライするようにしたりすることができるようになります。</p>



<pre class="wp-block-preformatted">BOOL InernetSetOption(
     IN HINTERNET hInternet OPTIONAL,
     IN DWORD Option,
     IN LPVOID Buf,
     IN DWORD BufSize);</pre>



<p>第1引数には、hInternetハンドルを指定します。InternetOpen関数で返されるハンドルです。</p>



<h3 class="wp-block-heading">タイムアウト時間を変更する</h3>



<p>　Optionに<strong>”INTERNET_OPTION_CONNECT_TIMEOUT”</strong>を指定すると、タイムアウト時間を任意に設定することができます。</p>



<pre class="wp-block-preformatted">InternetSetOption(hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, &amp;dwtimeoutMs, sizeof(timeoutMs));</pre>



<p>　第3引数にタイムアウトまでの時間をミリ秒単位で指定します。指定時間内にサーバーとの接続が確立できないと、エラー12002（ERROR_INTERNET_TIMEOUT）が発生します。</p>



<h3 class="wp-block-heading">接続できないときに自動で再試行するようにする</h3>



<p>　<strong>INTERNET_OPTION_CONNECT_RETRIES</strong>オプションを設定すると、接続失敗時に自動再試行させることもできます。</p>



<pre class="wp-block-preformatted">InternetSetOption(hInternet, INTERNET_OPTION_CONNECT_RETRIES , &amp;dwRetryTimes, sizeof(dwRetryTimes));</pre>



<p>　自動再試行する回数や間隔を任意の値に設定することができます。</p>



<p>　ほかにも様々なオプションが用意されています。MSDNに指定できるパラメーターが掲載されていますので、ご参照ください。</p>




<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/option-flags" title="Option Flags (Wininet.h) - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">Option Flags (Wininet.h) - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">The following option flags are used with the InternetQueryOption and InternetSetOption functions. All valid option flags...</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/option-flags" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>



<p></p>



<h2 class="wp-block-heading">まとめ</h2>



<p>　.NET Frameworkの活用が当たり前になっている世の中で、「今頃C++？？」という印象を受ける方もいるかもしれません。</p>



<p>　しかし、実際動かしてみると、<strong><span class="marker-animation">C#とは比較にならないくらい、爆速で動作します。</span></strong>一瞬で処理が完了するので、とにかく速く動作させたいというニーズには、今でもぴったりな選択肢といえるでしょう。</p>



<p>　それに、メモリを初期化したりなど、C#では味わえない<strong><span class="marker-animation">”コンピューターをコントロールしている感覚”</span></strong>がまた新鮮です。きっちり理解していないと動作させられないので、勉強になります。ふだんHTTPClientを使用されている方も、たまにはC++で遊んでみてはいかがでしょうか。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-reference-link">
<p>　WinINetに関しては、Microsoft Docsに詳細が掲載されています。あわせて参照することをおすすめします。</p>

<a rel="noopener" href="https://docs.microsoft.com/en-us/windows/win32/wininet/http-sessions" title="HTTP Sessions - Win32 apps" class="blogcard-wrap external-blogcard-wrap a-wrap cf" target="_blank"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img loading="lazy" decoding="async" src="https://learn.microsoft.com/en-us/media/open-graph-image.png" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">HTTP Sessions - Win32 apps</div><div class="blogcard-snippet external-blogcard-snippet">Resources on the WWW are accessed by using http.</div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://learn.microsoft.com/en-us/windows/win32/wininet/http-sessions" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">learn.microsoft.com</div></div></div></div></a>
</div>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://takabus.com/cpp-wininet/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
