状況は次のとおりです。
を格納する Peer クラスとboost::asio::ip::tcp::socket
、Peers のセット (ベクター/マップなど) を持つ Network クラスがあります。
とりあえず、Peer::listen()
非同期読み取りを開始し、イベントの完了を にバインドしPeer::handle_incoming_message
ます。asio::error::eof
これは、ピアが、離れたピアが切断されたかどうかを知るために を探す必要があることを意味します。
このメソッドで Peer オブジェクトを破棄する必要があるため、Peerを呼び出すことができませんNetwork::remove_peer()
(実際には試していませんが、それremove_peer
を呼び出した Peer オブジェクトが破棄された場合、から戻るとクラッシュするか何かになると思います)。だから今私がやっていることは、Peer オブジェクトの状態を に設定することだけです。PEER_STATE_DEAD
ネットワークのセット内のすべてのピアを定期的にチェックし、状態を持つものをすべて削除しますPEER_STATE_DEAD
。
私は Network にhandle_incoming_message([...], Peer* p)
メソッドを持たせたいと思っています。このメソッドは実際には が発生したかどうかのみをチェックし、発生していない場合は に指定されたバッファから読み取るeof
呼び出しを行います。p->receive()
async_read
Network::handle_incoming_message([...], this)
したがって、理想的には、Peer クラスには、構築時 (またはその直後)に初期化される ListenHandler オブジェクトがあります。問題は、このセットアップでコンパイルできないようです。
簡略化されたコード:
通信網:
class Network:
{
[...]
void handle_incoming_message(const system::error_code& error,
Peer* emitter);
[...]
};
void Network::add_peer(shared_ptr<Peer> p)
{
peers.push_back(p);
p->start_listening(bind(&Network::handle_incoming_message, this,
asio::placeholders::error, p.get() ));
}
ピア:
class Peer
{
public:
typedef function<void (const system::error_code&, Peer*)> Handler;
void start_listening(Peer::Handler _listen_handler);
void listen();
[...]
private:
Handler listen_handler;
char last_message[MESSAGE_SIZE];
[...]
};
void Peer::start_listening(Peer::Handler _listen_handler)
{
listen_handler = _listen_handler;
set_state(PEER_STATE_CONNECTED);
listen();
}
void Peer::listen()
{
memset(last_message, 0, MESSAGE_SIZE);
socket->async_read_some(asio::buffer(last_message), listen_handler);
}
void Peer::receive()
{
cout << get_address() << ": " << last_message << endl;
listen();
}
G++:
g++ -c -Wall -D DEBUG_ON -Iinclude -I/usr/include src/Peer.cpp
In file included from /usr/include/boost/asio.hpp:30:0,
from include/Peer.hpp:4,
from src/Peer.cpp:3:
/usr/include/boost/asio/basic_stream_socket.hpp: In instantiation of
‘void boost::asio::basic_stream_socket<Protocol, StreamSocketService>::async_read_some(const MutableBufferSequence&, const ReadHandler&)
[with
MutableBufferSequence = boost::asio::mutable_buffers_1;
ReadHandler = boost::function<void(const boost::system::error_code&, Peer*)>;
Protocol = boost::asio::ip::tcp;
StreamSocketService = boost::asio::stream_socket_service<boost::asio::ip::tcp>]’:
src/Peer.cpp:30:69: required from here
/usr/include/boost/asio/basic_stream_socket.hpp:785:57: error: invalid conversion from ‘long unsigned int’ to ‘Peer*’ [-fpermissive]
In file included from /usr/include/boost/function/detail/maybe_include.hpp:23:0,
from /usr/include/boost/function/detail/function_iterate.hpp:14,
from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:57,
from /usr/include/boost/function.hpp:64,
from include/Peer.hpp:5,
from src/Peer.cpp:3:
/usr/include/boost/function/function_template.hpp:754:17: error:
initializing argument 2 of ‘boost::function2<R, T1, T2>::result_type boost::function2<R, T1, T2>::operator()(T0, T1) const
[with
R = void;
T0 = const boost::system::error_code&;
T1 = Peer*;
boost::function2<R, T1, T2>::result_type = void]’ [-fpermissive]
(error_code、bytes_transferred)でReadHandlerコンストラクターを使用しようとしていることを理解しています。
私はこの質問を読みましたが、バインドは「[もの]を渡さないほど賢い」ようですが、それは、読み取りハンドラーを他のクラスを受け入れる別のクラスから非静的メソッドにバインドする(吸い込む)方法がないことを意味しますか? error_code、bytes_transferred 以外のパラメータ?
(Handler typedef を void(error_code, bytes_transferred, Peer*) に変更しようとしましたが、どちらも機能しませんでした)
あるいは、これのいずれかが悪い設計の悪臭を放っているように思われる場合は、物事をより適切に処理する方法について提案を受け付けています. bind()
への呼び出しの中にへの呼び出しがないことが問題の原因である場合は、async_read()
ネットワーク呼び出しを行うことができると思いますasync_read()
...