私は、TCPを介してメッセージをディスパッチできるクラスを持っています。ここでは単純化されたインタフェース:shared_ptrを使ったAsio-handlingリゾルバとソケットのブーケ
class CommandScreenshot : public CameraCommand
{
public:
CommandScreenshot();
~CommandScreenshot();
void Dispatch(boost::shared_ptr<boost::asio::io_service> io_service);
private:
void resolve_handler(const boost::system::error_code& err,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
};
にあなたが、私は実際には非同期操作を開始することを目的としている機能Dispatch
を持って見ることができるように:他に
void CommandScreenshot::Dispatch(boost::shared_ptr<boost::asio::io_service> io_service)
{
boost::asio::ip::tcp::resolver resolver(*io_service);
boost::asio::ip::tcp::resolver::query query(m_hostname,"http");
resolver.async_resolve(query,boost::bind(&CommandScreenshot::resolve_handler,this,boost::asio::placeholders::error, boost::asio::placeholders::iterator));
return;
}
すべては、次のコールバックで行われます機能。 io_service
オブジェクトと対応するスレッドは別のクラス(CommandScreenshot
のインスタンスを持ち、Dispatch
関数を呼び出します)によって管理されます。
ブーストとの簡単なTCP接続を実装するには、resolver
オブジェクトとsocket
オブジェクトが必要です(どちらもio_service
オブジェクトにバインドされています)。 io_service
オブジェクトはその時点でのみ渡されるので、関数が呼び出され、クラスコンストラクタでそれらを初期化できません。 また、それらをクラスメンバーとして宣言し、関数自体で初期化することはできません。
私の最初のアイデアは、関数呼び出し時にそれらを初期化し、それらを私の完了ハンドラに渡すことでした。つまり、関数が呼び出されるたびに両方のオブジェクトを宣言し、io_service
にバインドすることを意味します。その後、async_resolve
で、私はboost::bind
を介してパラメータとして両方を追加します。それは私のresolve_handler
は複数の引数を期待することを意味する - 例えば:
void resolve_handler(const boost::system::error_code& err,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator,
boost::asio::ip::tcp::resolver resolver,
boost::asio::ip::tcp::socket socket);
私は実際にこれがまともなかつ公正な解決策であることを疑います。通常、これらのオブジェクトはメンバーとして保持され、コピーされないようにする必要があります - 私は別の考えを与え、私の心はboost::shared_ptr
に私を連れて行きました。私のヘッダーで
それはこのようになりましたになります。
// Stuff above stays the same
private:
boost::shared_ptr<boost::asio::ip::tcp::resolver> m_resolver;
boost::shared_ptr<boost::asio::ip::tcp::socket> m_socket;
// Stuff below stays the same
そして、実装は次のようになります。これにより
void CommandScreenshot::Dispatch(boost::shared_ptr<boost::asio::io_service> io_service)
{
m_resolver.reset(new boost::asio::ip::tcp::resolver(*io_service));
m_socket.reset(new boost::asio::ip::tcp::socket(*io_service));
boost::asio::ip::tcp::resolver::query query(m_hostname,"http");
m_resolver->async_resolve(query,boost::bind(&CommandScreenshot::resolve_handler,this,boost::asio::placeholders::error, boost::asio::placeholders::iterator));
return;
}
を、私も4(または多分のように周りにコピーする必要はありませんより多くの)パラメータを定義し、それらを結合します。ソケットオブジェクトが必要なときには、クラスメンバーであるポインタを介してアクセスできます。
今私の簡単な質問は - >これは正しい方法ですか?非同期部分が終了していなくても、関数は複数回呼び出すことができます。 (私はソケットとリゾルバをミューテックスで保護しなければならないことを知っています)。しかし、これはきれいです、毎回私はDispatch
関数を呼び出すときに新しいオブジェクトを作成するのですか? reset
コールは不必要なメモリを取り除くのに十分ですか?
私はこれが特定の短い質問のための長いテキストであり、さらにはtiselfでもエラーがないことを知っています。しかし、私はいつもそれが私が行っているまともな方法であるかどうか、そしてより良いものがあれば、どうやってそれをするのかを知りたい。