0

我有一个封装 TCP 连接的TcpDevice类,它有一个onRemoteDisconnect方法,只要远程端挂断,就会调用该方法。然后,有一个SessionManager对象创建TcpSession对象,该对象将 TcpDevice作为通信通道并将它们插入到内部指针容器中以供应用程序使用。如果任何托管的TcpSessions应该结束,我希望SessionManager实例得到通知,然后从容器中删除相应的会话,释放与其关联的资源。

我发现我的问题与这个问题非常相似:

对象从容器中删除自身

但由于他有一个用于检查连接状态的线程,它与我的有点不同,而且我打算使用boost::signals解决它的方式,所以我决定针对它提出一个新问题 - 如果它是我道歉错误的方法......我仍然对如何正确使用 SO 有感觉 :)

由于我对 QT 信号/插槽有点熟悉,我发现boost::signals提供了类似的机制(我已经在使用boost::asio并且在这个项目中没有 QT),所以我决定实现一个remoteDeviceDisconnected信号由TcpDevice 的 onRemoteDisconnect发出,为此我将在SessionManager中有一个插槽,然后从容器中删除断开连接的会话和设备。

为了最初尝试,我在tcpdevice.hpp 中将信号声明为TcpDevice的公共成员:

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

我的错!就像我们都应该预料的那样,链接器是正确的......确实有第二个定义,我只是无法立即发现它,因为它没有由我的任何类定义,而只是“浮动”在我的一个.cpp 文件,如boost::signals示例中的文件。

只是为了记录,最初的想法就像一个魅力:当给定的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 回答