THTTPClientを使った非同期 HTTP リクエスト[JAPAN]

Posted by on in Programming

毛利です。

 

THTTPClientを使って非同期HTTPリクエストを試してみました。

TNetHTTPClientと言うコンポーネントもありますが、TNetHTTPClient classにはTHTTPClientが 内包されています。

THTTPClientの非同期HTTPが使えるメソッドは下記です。

メソッド名   機能
BeginDelete public 非同期 HTTP リクエストを、DELETE HTTP リクエスト メソッドを使用して開始します。
BeginExecute public 非同期 HTTP リクエストを開始します。
BeginGet public 非同期 HTTP リクエストを、GET HTTP リクエスト メソッドを使用して開始します。
BeginGetRange public 非同期 HTTP リクエストを、GET HTTP リクエスト メソッドを Range ヘッダーと共に使用して開始します。
BeginHead public 非同期 HTTP リクエストを、HEAD HTTP リクエスト メソッドを使用して開始します。
BeginMerge public 非同期 HTTP リクエストを、MERGE HTTP リクエスト メソッドを使用して開始します。
BeginMergeAlternative public MERGE HTTP リクエスト メソッドを使用した非同期 HTTP リクエストを、PUT HTTP リクエスト メソッドとしてマス
BeginOptions public 非同期 HTTP リクエストを、OPTIONS HTTP リクエスト メソッドを使用して開始します。
BeginPatch public 非同期 HTTP リクエストを、PATCH HTTP リクエスト メソッドを使用して開始します。
BeginPatchAlternative public PATCH HTTP リクエスト メソッドを使用した非同期 HTTP リクエストを、PUT HTTP リクエスト メソッドとしてマスクします
BeginPost public 非同期 HTTP リクエストを、POST HTTP リクエスト メソッドを使用して開始します。
BeginPut public 非同期 HTTP リクエストを、PUT HTTP リクエスト メソッドを使用して開始します。
BeginTrace public 非同期 HTTP リクエストを、TRACE HTTP リクエスト メソッドを使用して開始します。

 

 

 

 

 

 

 

 

 

 

 



 

コンソール アプリケーションを新規プロジェクトC++Builder(Win64)で作成しTHTTPClientBeginGet()を試したコードです。

////
struct _net_request:public TObject
{
	using inherited = TObject;
	std::mutex m_;
	bool f_wait{false};
	THTTPClient* f_netc_{THTTPClient::Create()};
	String f_temp;
	_net_request():inherited()
	{
		f_netc_->OnReceiveData = receive_event;
	}
	void __fastcall receive_event(TObject * const Sender, __int64 AContentLength, __int64 AReadCount, bool &Abort)
	{
		if (Abort == false)
		{
			std::wcout << L"AReadCount=" << AReadCount << std::endl;
		}

	}
	void set_wait(const bool value_)
	{
		std::lock_guard<std::mutex> lk_(m_);
		f_wait = value_;
	}
	bool get_wait()
	{
		std::lock_guard<std::mutex> lk_(m_);
		return f_wait;
	}
	__fastcall ~_net_request(void)
	{
		delete f_netc_;
	}
};

 int _tmain(int argc, _TCHAR* argv[])
{
	String url_			= argv[1];
	String fname_		= argv[2];
	String path_name_	= System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetSharedDownloadsPath(), fname_);
	std::unique_ptr<_net_request> req_ = std::make_unique<_net_request>();
	//
	int lengs_ = req_->f_netc_->Head(url_)->ContentLength;
	std::cout << "ContentLength" << lengs_ << std::endl;

	std::unique_ptr<TFileStream> down_file_ = std::make_unique<TFileStream>(path_name_, fmCreate);
	down_file_->Position = 0;
	TDateTime tstart_ = Now();
	_di_IAsyncResult res_= req_->f_netc_->BeginGet([&req_, &tstart_](const System::Types::_di_IAsyncResult AsyncResult)
		{
			req_->set_wait(true);
			TDateTime tend_ = Now() - tstart_;
			std::wcout <<  FormatDateTime("hh:nn:ss.zzz",tend_).w_str() << L" End Download." << std::endl;
		}, url_, down_file_.get());

	if (res_ != nullptr)
	{
		// Wait until BeginGet() is over.
		while (! req_->get_wait() )
		{
			std::this_thread::sleep_for(std::chrono::seconds(2));
		}
	}
	return 0;
}



コマンドラインで  URLとファイル名を指定すればダウンロードを非同期で実行します。

ダウンロード中のステータスはコールバックで処理します。

THTTPClient::OnReceiveDataです。

////
f_netc_->OnReceiveData = receive_event;

 

BeginGet()関数_di_TAsyncCallbackはLambdaを使って処理が可能です。

////
_di_IAsyncResult res_= req_->f_netc_->BeginGet([&req_, &tstart_](const System::Types::_di_IAsyncResult AsyncResult)
	{
		req_->set_wait(true);
		TDateTime tend_ = Now() - tstart_;
		std::wcout <<  FormatDateTime("hh:nn:ss.zzz",tend_).w_str() << L" End Download." << std::endl;
	}, url_, down_file_.get());

 

最後にコンソールアプリなので終了を待っています。

////
// Wait until BeginGet() is over.
while (! req_->get_wait() )
{
	std::this_thread::sleep_for(std::chrono::seconds(2));
}

 

メインでf_wait(bool)を待っています、裏のスレッドで終了時にf_waitを書くのでstd::mutexを使ってロックしています。

 

細川さんがDelphi版で詳しく説明されています

THttpClient の落とし穴1

 

 


https://github.com/mojeld/THTTPClient_Console

 



About
Gold User, No rank,
Delphi / C++Builder blogger

Comments

Check out more tips and tricks in this development video: