0

TCP接続をカプセル化するTcpDeviceクラスがあります。このクラスには、リモートエンドが電話を切るたびに呼び出されるonRemoteDisconnectメソッドがあります。次に、TcpDeviceを通信チャネルとして使用するTcpSessionオブジェクト を作成し、アプリケーションが使用できるように内部ポインターコンテナーに挿入するSessionManagerオブジェクトがあります。管理対象のTcpSessionのいずれかが終了する必要がある場合は、SessionManagerインスタンスに通知してから、対応するセッションをコンテナーから削除して、それに関連付けられているリソースを解放します。

私の問題はこの質問と非常に似ていることがわかりました。

オブジェクトはコンテナから自分自身を削除します

しかし、彼は接続状態をチェックするためのスレッドを持っているので、それは私のものとは少し異なり、boost :: signalsを使用してそれを解決することを意図していたので、それに向けた新しい質問に行くことにしました-それがそうである場合はお詫びしますそれを行うための間違った方法...私はまだSOを適切に使用する方法についての感触を得ています:)

私はQTシグナル/スロットに精通しているので、 boost :: signalが同様のメカニズムを提供していることがわかりました(私はすでにboost :: asioを使用しており、このプロジェクトにはQTがありません)。そこで、remoteDeviceDisconnectedシグナルを実装することにしました。 TcpDeviceの onRemoteDisconnectによって発行され、 SessionManagerにスロットがあり、切断されたセッションとデバイスがコンテナから削除されます。

最初に試してみるために、tcpdevice.hppTcpDeviceのパブリックメンバーとしてシグナルを宣言しました。

class TcpDevice
{
             (...)
  public:
    boost::signal <void ()> remoteDeviceDisconnected;
             (...)
}

次に、TcpDeviceの onRemoteDisconnectメソッドから次のように出力しました。

remoteDeviceDisconnected();

さて、このシグナルをセッションマネージャーからSessionManagerスロットに接続する方法はありますか?私はこれを試しました:

unsigned int SessionManager::createSession(TcpDevice* device)
{
  unsigned int session_id = session_counter++;
  boost::mutex::scoped_lock lock(sessions_mutex);
  sessions.push_back(new TcpSession(device, session_id));
  device->remoteDeviceDisconnected.connect(boost::bind(&SessionManager::removeDeadSessionSlot, this));
  return session_id;
}

正常にコンパイルされますが、リンク時に、いくつかのオブジェクトコードファイルでのremoteDeviceDisconnectedの複数の定義について文句を言います。

tcpsession.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here
sessionmanager.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here

シグナルをどこにも再定義しなかったので、これは奇妙だと思いましたが、上記のcreateSessionメソッドで使用しただけです。

ヒントをいただければ幸いです。ありがとうございました!

4

1 に答える 1

0

私の悪い!誰もが予想するように、リンカーは正しかった...確かに2番目の定義がありました。クラスのいずれによっても定義されていなかったため、すぐに見つけることができませんでした。boost::signalsの例にあるような.cppファイル。

念のために言っておきますが、最初のアイデアは魅力のように機能しました。特定のTcpDeviceがリモートエンドから切断されると、remoteDeviceDisconnectedシグナルを送信し、そのTcpDeviceを指すTcpSessionインスタンスを保持するSessionManagerオブジェクトによってキャッチされます。通知されると、SessionManagerのメソッドremoveDeadSessionSlotが実行され、セッションのptr_listコンテナーを反復処理して、切断されたコンテナーを削除します。

void SessionManager::removeDeadSessionSlot()
{
  boost::mutex::scoped_lock lock(sessions_mutex);
  TcpSession_ptr_list_it it = sessions.begin();
  while (it != sessions.end()) {
    if (!(*it).device->isConnected())
      it = sessions.erase(it);
    else
      ++it;
  }
}

それが誰かへの参照として役立つかもしれないことを願っています!

于 2012-04-16T21:57:21.640 に答える