将不透明指针包装在shared_ptr中

问题描述:

我试图使用winsock2实现简单的TCP服务器应用程序。为此,我有一个接受连接的类(TcpServer)和一个处理连接的类(TcpListener)。为此目的,这些物体需要共享SOCKET,whis被定义为UINT_PTR。为了安全地分享这个shared_ptr似乎是要走的路。不幸的是,shared_ptr似乎应该包装structclass,因此我的实施如下。将不透明指针包装在shared_ptr中

struct SafeSocket_ 
{ 
    SOCKET Socket; 
    SafeSocket_(SOCKET socket) 
     : Socket(socket) 
    {} 
    ~SafeSocket_() 
    { 
     closesocket(Socket); 
     std::cout << "destroyed SafeSocket_" << std::endl; 
    } 
}; 
typedef std::shared_ptr<SafeSocket_> SafeSocket; 

要创建/接受一个新的套接字我使用以下可怕的代码。更糟的是,我需要在各地使用ClientSocket->Socket

SafeSocket ClientSocket = SafeSocket(new SafeSocket_(accept(ListenSocket, NULL, NULL))); 

必须有处理这个除了使用一个漂亮的包装库一个更好的办法。

注意:我知道有一些不错的包装库,比如来自boost的asio,但我只是为了让我的头脑解决一些C++基础问题而烦恼。

基本问题是UINT_PTR不是一个不透明的指针。这是一个整数。如果它是typedef struct __socket SOCKET;,那么你可以只写std::shared_ptr<decltype(*SOCKET{})>,在自定义删除程序中调用close_socket,你会笑。

有许多可能的方法:

  • 制作SafeSocket是包含shared_ptr的一类,并且具有socket成员函数。然后你在那里写ClientSocket.socket()
  • 如上所述,但给出SafeSocket版本的套接字函数,并且它提供了实际的套接字参数。因此,您可以编写ClientSocket.read(...)而不是read(ClientSocket.Socket, ...)
  • 恢复到SafeSocket作为一个typedef,而是把更多的功能SafeSocket_,所以你写ClientSocket->read(...)

我想我更喜欢中间的最佳解决方案。

+0

好主!我们进行了三次编辑,让它几乎正确! –

+2

使用自定义[在std :: unique_ptr中有'SOCKET']是可能的(http://stackoverflow.com/questions/24611215/one-liner-for-raii-on-non-pointer) 'Deleter'将'SOCKET'定义为'pointer'类型,即使它不是一个真正的指针。不知道是否可以用'std :: shared_ptr'完成同样的工作,尽管它也支持自定义的'Deleter',但也许或者不是自定义指针?我还没有挖掘到它看。 –

+0

我选择了中间解决方案。 Remy表示会很好,但我现在意识到将资源编号包装在指针容器中会造成混淆。 – Wouter