【问题标题】:RAII, Berkeley Sockets, and STL ContainersRAII、Berkeley 套接字和 STL 容器
【发布时间】:2017-02-16 18:16:24
【问题描述】:

首先让我说明我正在使用不支持移动构造函数的 GNU C++ 编译器。它只支持98标准。

鉴于此,我想编写一个 C++ 类,它以遵循 RAII 的简单方式包装伯克利风格的套接字。这是一个非常简单的类:

class SimpleSocket
{
  int m_sockfd;
public:
  SimpleSocket()
  {
    m_sockfd = socket(AF_INET, ...);
  }
  SimpleSocket(const SimpleSocket& other)
  {
    m_sockfd = other.m_sockfd;
  }
  ~SimpleSocket()
  {
    closeSocket();
  }
  void closeSocket()
  {
    if(m_sockfd != -1)
    { 
      close(m_sockfd);
      m_sockfd = -1;
    }
  }
};

假设我想像这样在 STL C++ 向量中创建一大堆这些。

vector<SimpleSocket> vec_of_sockets;
for(int i = 0 ; i < 10 ; ++i)
{
  SimpleSocket new_sock;
  vec_of_sockets.push_back(new_sock);
}

我发现 vector 使用复制构造函数来移动对象,然后破坏旧的套接字。这具有调用关闭我的文件描述符的 closeSocket() 的不幸副作用。

我想在调用对象的析构函数时遵循 RAII 并关闭文件描述符,但它使我无法在 STL C++ 容器内使用它。我知道我可以更新我的编译器并实现一个可以解决问题的移动构造函数,但我为一家不相信使用任何现代产品的公司工作。 (我真的很沮丧,但对此我无能为力。)

【问题讨论】:

  • 尝试更改复制构造函数并删除const,然后在复制后将other.m_sockfd 设置为-1。您可能还想考虑operator=
  • @RichardCritten 如果没有 const 引用,您将无法拥有复制构​​造函数。你的建议毫无意义
  • @DavidHaim 是的,你可以:"类 T 的复制构造函数是一个非模板构造函数,其第一个参数是 T&、const T&、volatile T& 或const volatile T&"(我的粗体字)请参阅:en.cppreference.com/w/cpp/language/copy_constructor 它不会复制临时对象 - 这就是我在帖子中说“尝试”的原因。

标签: c++ sockets stl


【解决方案1】:

Linux 和 Windows 都在 kernel/winsock2 级别实现引用计数。您可以在用户模式程序中使用引用计数指针,但这会浪费比您想象的更多的内存。您可以提升操作系统已经在幕后执行的引用计数。这是 Linux 的示例实现:

 SimpleSocket(const SimpleSocket& other)
  {
    m_sockfd = dup(other.m_sockfd);
  }

操作系统将增加指定套接字的引用计数,并返回一个您可以使用的新描述符。请注意,当您以这种方式“复制”套接字时,即使描述符不同,两个套接字都将引用同一个底层套接字。

【讨论】:

  • 您需要在 Windows 上使用WSADuplicateSocket。我还将为该类实现一个重载的赋值运算符。
  • 我不知道为什么,但我认为这对我正在做的事情不起作用。我认为每个文件描述符都引用同一个文件描述符存在问题,所以如果我关闭一个,它将关闭另一个。
  • @selbie 对于重载的赋值运算符,你会完全阻止被赋值(抛出异常)还是像复制构造函数一样 dup() 套接字?
  • @TLytle 您可以通过在编译时将运算符声明为private 而不是在运行时抛出异常来防止赋值。或者,您可以通过关闭当前套接字并复制源套接字来实现它。
【解决方案2】:

如果您可以使用 Smart Pointers Boost library,请将您的类存储在 shared_ptr 中,如下所示:

std::vector<boost::shared_ptr<SimpleSocket>>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    • 2015-07-06
    • 2017-05-17
    • 1970-01-01
    • 2011-09-18
    • 2011-04-13
    相关资源
    最近更新 更多