【发布时间】:2017-09-10 19:07:12
【问题描述】:
我目前正在尝试编写一个小型多人游戏的网络部分,并且在存储我的 TCP 套接字时遇到了问题,这些套接字在 SFML 中是不可复制的(我是 C++ 的初学者)。
我有三个类:Server、Client(用于存储有关连接客户端的所有信息的服务器端类)和ClientManager,负责存储所有客户端并为它们提供 ID 等.
ClientManager.h
class ClientManager {
public:
ClientManager();
std::map<int, Net::Client*> getClients();
int attribID();
void addClient(Net::Client *client);
sf::TcpSocket getClientSocket(int id) throw(std::string);
void setClientSocket(int id, sf::TcpSocket);
private:
std::map<int, Net::Client*> m_clients;
std::map<int, sf::TcpSocket> m_clientSockets;
std::vector<int> m_ids;
int m_lastID;
};
当客户端连接时,我最初计划做的是:
void Net::Server::waitForClient() {
while(true) {
if(m_listener.accept(m_tcpSocket) != Socket::Done) {
cout << "Error happened during client connection. skipping. " << endl;
return;
}
int newID = m_clientManager.attribID();
this->m_clientManager.addClient(new Net::Client(newID, m_tcpSocket, m_tcpSocket.getRemoteAddress()));
}
}
所以,添加一个新的Client 到 ClientManager 的列表中,带有它的 ID、一个用于发送信息的 TcpSocket 和他的地址。
但是,问题是 SFML 的 TcpSocket 类是不可复制的,这意味着我不能像这样将它复制到客户端。
我可以将它作为指向原始 TcpSocket 的指针传递,但是如果另一个客户端连接呢?指针指向的数据会发生变化,程序会出错。我不知道这种行为是否与智能指针相同,但我认为是这样(但我根本不掌握它们)。
将它们存储在std::map 或std::vector 中会导致同样的问题,因为它们都复制了对象。将它们存储为指向原始 TcpSocket 的指针(在映射中)将导致与以前相同的问题,因为套接字也会改变,并且指针将指向同一个对象。
如何在不使用引用、指针或复制我的对象的情况下存储我的套接字?
任何帮助将不胜感激:)
【问题讨论】:
-
回到家后我将不得不对此进行更多研究,但我相信您可以将套接字的地址传递给您的 clientManager,然后从套接字中获取 IP 和端口信息并将其存储起来.
-
您可以使用动态内存,使用 std::unique_ptr 或 shared_ptr,并将指针存储在您的向量/映射中(这需要您为每个连接分配内存)。
-
您好,感谢您的回答!它确实需要为每个新连接的客户端分配内存(或者我们会遇到指针的情况)。通过分配内存,您的意思是:在 while 循环的开头创建一个
shared_ptr指针,使用new分配内存,然后使用std::map<int, std::shared_ptr<TcpSocket>>(或使用另一个shared_ptr的任何其他方式)将它们存储在ClientManager? -
是的,我就是这个意思。
-
如果有人遇到同样的问题(即存储 SFML 套接字),我在他们的文档中找到了一个很好的例子:sfml-dev.org/documentation/2.4.2/classsf_1_1SocketSelector.php