简体   繁体   English

RAII,伯克利套接字和STL容器

[英]RAII, Berkeley Sockets, and STL Containers

Let me start by stating I am using a GNU C++ compiler that does NOT support move constructors. 首先,我要说明我正在使用不支持move构造函数的GNU C ++编译器。 It only supports the 98 standard. 它仅支持98标准。

Given that, I want to write a C++ class that wraps Berkeley style sockets in a simple way that follows RAII. 鉴于此,我想编写一个遵循RAII的简单方式包装Berkeley样式套接字的C ++类。 Here is a very simple class: 这是一个非常简单的类:

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;
    }
  }
};

Let's say I want to create a whole bunch of these in a STL C++ vector like so. 假设我想像这样在STL C ++向量中创建全部这些。

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

What I found was that vector uses the copy constructor to move the objects around and then destructing the old sockets. 我发现向量使用了复制构造函数来移动对象,然后破坏了旧的套接字。 This has the unfortunate side-effect of calling closeSocket() which closes my file descriptor. 不幸的是,调用closeSocket()会关闭我的文件描述符的副作用。

I want to follow RAII and close the file descriptor when the object's destructor is called but it makes it where I cannot use it inside of the STL C++ containers. 我想跟随RAII并在调用对象的析构函数时关闭文件描述符,但是它使它无法在STL C ++容器中使用它。 I know that I can update my compiler and implement a move constructor which would fix the problem but I work for a company that does not believe in using anything that is modern. 我知道我可以更新编译器并实现可解决该问题的move构造函数,但我在一家不相信使用现代工具的公司工作。 (I'm really frustrated by it but there is nothing I can do about it.) (对此我确实感到沮丧,但是对此我无能为力。)

Both Linux and Windows implement reference counting in the kernel/winsock2 level. Linux和Windows都在kernel / winsock2级别实现引用计数。 you could have used a reference counted pointer in your user mode program, but that would waste more memory than you'd think. 您本可以在用户模式程序中使用引用计数的指针,但这会浪费比您想象的更多的内存。 you can elevate the reference counting you OS already does behind the scenes. 您可以提高参考数量,以计数您的操作系统在后台已经执行的操作。 here is an example implementation for Linux: 这是Linux的示例实现:

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

The operating system will increment the reference count of the specified socket and will return a new descriptor in which you can use. 操作系统将增加指定套接字的引用计数,并返回一个可以在其中使用的新描述符。 do note that when you "copy" a socket this way, both of the sockets will refer to the same underlying socket even if the descriptors are different. 请注意,当您以这种方式“复制”套接字时,即使描述符不同,两个套接字也会引用相同的基础套接字。

如果可以使用Smart Pointers Boost库 ,则将类存储在shared_ptr中,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM