为了实现类型SOCKET
的{{3}}习语,我创建了一个包装器。包装器在构造函数中调用connect
,在析构函数中调用closesocket
。 std::map
保存所有使用过的套接字。不幸地将新套接字插入容器中会调用临时的析构函数,实际上会关闭刚刚打开的套接字。是否有一种解决这个问题的常用方法?
以下是代码:
#include <iostream>
#include <stdexcept>
#include <map>
#include <winsock2.h>
struct Socket {
SOCKET mSock;
Socket() : mSock(INVALID_SOCKET) {}
Socket(std::string ip, int port);
~Socket();
};
Socket::Socket(std::string ip, int port) {
mSock = socket(AF_INET, SOCK_STREAM, 0);
if (mSock == INVALID_SOCKET)
throw std::runtime_error("socket()");
SOCKADDR_IN addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
if (connect(mSock, reinterpret_cast<SOCKADDR*>(&addr), sizeof(addr))
== SOCKET_ERROR)
throw std::runtime_error("connect()");
std::cout << mSock << " connected" << std::endl;
}
Socket::~Socket() {
if (mSock != INVALID_SOCKET) {
closesocket(mSock);
std::cout << mSock << " closed" << std::endl;
}
}
int main() {
WSADATA wsa;
WSAStartup(MAKEWORD(2, 0), &wsa);
std::map<int, Socket> outbound;
// calls constructur but also destructor
outbound[0] = Socket("192.168.128.125", 4023);
WSACleanup();
return 0;
}
输出是:
1952 connected
1952 closed
1952 closed
答案 0 :(得分:4)
如果将资源保护包装在智能指针中,则可以将资源保护存储在STL容器中。哪个智能指针完全取决于您的环境,如果您不确定,我建议您使用boost :: shared_ptr作为起点。
按照这种方式,您将符合资源保护语义(只有一个管理资源生命周期的实例)和STL容器(保留传递项目的等效副本)。
答案 1 :(得分:1)
正如其他人所提到的,你应该阻止复制你的Socket对象,这可以通过添加:
来完成private:
Socket(const Socket &){}
Socket & operator=(const Socket &){return *this;}
然后实际连接,你可以在默认构造之后执行一个connect方法,可以显式调用,或者由剩下的构造函数调用:
bool Socket::connect(std::string ip, int port) {
mSock = socket(AF_INET, SOCK_STREAM, 0);
if (mSock == INVALID_SOCKET)
return false;
SOCKADDR_IN addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
if (connect(mSock, reinterpret_cast<SOCKADDR*>(&addr), sizeof(addr))
== SOCKET_ERROR)
return false;
std::cout << mSock << " connected" << std::endl;
return true;
}
Socket::Socket(std::string ip, int port) {
if (!connect(ip, port))
throw std::runtime_error("socket()");
}