ラベル libcurl の投稿を表示しています。 すべての投稿を表示
ラベル libcurl の投稿を表示しています。 すべての投稿を表示

2020年1月3日金曜日

libcurl を用いた画像のPOST(multipart/form-data or raw 形式)

libcurl を用いて画像をPOST(multipart/form-data or raw 形式)する例題です。

multipart/form-data にて Base64化された送信(CURL_PostFormMedia)と、バイナリ形式での送信(CURL_PostRawMedia)をそれぞれ切り替えて利用することが出来ます。
サーバー側の実装例も合わせて記載(CGIを実行する際の引数で受信する形式を切替)。

multipart/form-data で送信する際には、ファイルが埋め込まれたフィールド名(<input type="file" name="file" />)を送受信側で合わせる必要があります。
サーバー側の form 内に、<input type="file" name="file"> と記載されている場合には name で指定されている "file" というフィールドに画像データを埋め込んで送信する必要があります(下記実装例では、CURL_PostFormMedia 関数の引数 fdname で指定しています)。

サーバ側実装例(perl/cgi)

サーバー側では GET で画像ファイルをPOSTする form を表示し、自分自身に画像をPOSTする実装となっています。
また、このCGIに直接画像をPOSTする際には引数にて(postimage.cgi?name=sample.jpg&type=raw) と指定すればバイナリ形式での受信も可能となります。 実行結果

2017年9月2日土曜日

libcurl による連続取得における排他処理

HTTPS コネクション時の libcurl による連続GET にて HTTPS への GET リクエストを行う際、curl ハンドラを初期化せずに利用した方が高速にダウンロードされると言う例題を記載しましたが、別のスレッドでタイミングがバラバラに GET したい場合、排他処理にて安全性を確保するための例題です。

libcurl 自体はスレッドセーフ化されているので、curl_easy_init にて毎回ハンドラを初期化し利用すれば何の問題もなく別のスレッドで GET リクエストを行えますが、同じハンドラを使いまわしたい場合には同じタイミングで同じハンドラが利用されないように排他処理を行っておく必要があります(今回のような特別な用途でないかぎりは全く必要のない例題です)。

pthread_mutex_lock にて排他処理を行っているので、GET リクエストが並列化されるわけではないので並列化による恩恵は受けれませんが、HTTPS への要求時における証明書の取得などの内部処理を毎回行わずに済むなどの恩恵が大きい場合に利用します(例題のweb.fc2.comはその恩恵が得られないサイトで、証明書が正しくない場合に起こるようです、別のサーバーにてお試しください)。 実行結果

2017年8月14日月曜日

libcurl-multi による並行GETリクエスト

libcurl-multi による並行GETリクエストを行う例題です。

例題では複数のURLを指定し並列にGETリクエストを行い、その結果を用意した char 型のバッファ内に格納しています。
HTTPS で連続取得を行う場合にはこちらで試した方法の方が高速な場合があります。 実行結果

2017年8月11日金曜日

HTTPS コネクション時の libcurl による連続GETリクエストの高速化の検討

HTTPS コネクション時の libcurl による連続GETリクエストを高速化するための検証用の例題です。

libcurl による GET 取得時の高速化手段として以下のサイトでまとめられています。
https://moz.com/devblog/high-performance-libcurl-tips
(c-ares/PowerDNS 等により DNSのリスポンスを良くするとか libcurl-multi による並列処理化等、上記サイトには書かれていませんが TCP FAST OPEN に対応しているサーバーであれば libcurl からオプションを指定して利用できます)

一方、HTTPS でのリクエストでは証明書の検証等で、単純なデータやり取り以外の部分で内部的に処理が食われてしまうことがあります。
下記の例題では HTTPS にてデータ取得を行うサイトが信頼のあるサイトであることを前提とし、証明書の検証を行っていません。

例題では以下の3つの手法にてサイトからのデータ取得をループし、取得時間を計測しています。
CURL_RequestText1:毎回CURLハンドラを初期化し、データ取得を行う例
CURL_RequestText2:毎回CURLハンドラを初期化し、内部的に確保されているコネクションの再利用等は行わずデータ取得を行う例(CURLOPT_FORBID_REUSE/CURLOPT_FRESH_CONNECT)
CURL_RequestText3:CURLハンドラを予め準備しておき、繰り返し利用する間は再利用する例
結果では、1/2 はサイトにより多少の変化はあるもののあまり差はなく(2の方が若干早い印象)、3 は 1 の半分程度の時間でデータ取得が行われています(この例題では記載していませんが、POST 時の応答も高速化されていました)。
TCP FAST OPEN(CURLOPT_TCP_FASTOPEN)の影響があるかどうかどうかを見てみましたが、特に影響はありませんでした。

HTTPS 接続が正常に機能しているサイトではほぼ 3 の設定で高速化される印象ですが、ブラウザ接続した際に「信頼できる運営者情報はありません」等のアラートが出るサイトでは全く変化はありませんでした(証明書の検証を行っていないにも関わらず)。
新しいサーバーでテストする際等には証明書を正しく入れてもらうようにお願いするしかない状況です(libcurl の設定では対処できない)。

今回テストしたのはサーバーからの応答を取得後に別の応答を取得する必要がある場合の処理です。
URLが異なる複数の結果を予め取得しておく場合には libcurl-multi や CURL ハンドラを複数準備して別スレッドで並行して結果を取得すれば容易に高速化することは可能かと思います(スレッドで用いる場合は CURLOPT_NOSIGNAL を指定)。 実行結果