【问题标题】:Handling multiple client sockets with SFML使用 SFML 处理多个客户端套接字
【发布时间】:2017-09-10 19:07:12
【问题描述】:

我目前正在尝试编写一个小型多人游戏的网络部分,并且在存储我的 TCP 套接字时遇到了问题,这些套接字在 SFML 中是不可复制的(我是 C++ 的初学者)。

我有三个类:ServerClient(用于存储有关连接客户端的所有信息的服务器端类)和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::mapstd::vector 中会导致同样的问题,因为它们都复制了对象。将它们存储为指向原始 TcpSocket 的指针(在映射中)将导致与以前相同的问题,因为套接字也会改变,并且指针将指向同一个对象。

如何在不使用引用、指针或复制我的对象的情况下存储我的套接字?

任何帮助将不胜感激:)

【问题讨论】:

  • 回到家后我将不得不对此进行更多研究,但我相信您可以将套接字的地址传递给您的 clientManager,然后从套接字中获取 IP 和端口信息并将其存储起来.
  • 您可以使用动态内存,使用 std::unique_ptr 或 shared_ptr,并将指针存储在您的向量/映射中(这需要您为每个连接分配内存)。
  • 您好,感谢您的回答!它确实需要为每个新连接的客户端分配内存(或者我们会遇到指针的情况)。通过分配内存,您的意思是:在 while 循环的开头创建一个shared_ptr 指针,使用new 分配内存,然后使用std::map&lt;int, std::shared_ptr&lt;TcpSocket&gt;&gt;(或使用另一个shared_ptr 的任何其他方式)将它们存储在ClientManager ?
  • 是的,我就是这个意思。
  • 如果有人遇到同样的问题(即存储 SFML 套接字),我在他们的文档中找到了一个很好的例子:sfml-dev.org/documentation/2.4.2/classsf_1_1SocketSelector.php

标签: c++ pointers sfml stdmap


【解决方案1】:

没有指针会很痛苦。我个人使用智能指针来管理套接字本身(std::vector&lt;std::unique_ptr&lt;sf::TcpSocket&gt;&gt; 或类似的),以及 `sf::SocketSelector' 来管理实际通信

【讨论】:

  • 这就是我结束做的事情,正如我在回复 Eddge 的评论中所建议的那样,除了我使用了 std::map(因为我也需要一个 ID)和 std::shared_ptr(我不知道它是否适合我的用例,因为我不能很好地掌握智能指针,但至少可以)。我也结束了使用sf::SocketSelector :)
  • 我建议在可能的情况下使用 unique_ptr 而不是 shared_ptr (关于此的大量互联网争论,我不会让你厌烦......),但我怀疑它会给你带来任何问题。很高兴它的工作:)
  • 我稍后会(大)看看这个,这是我想了解更多的主题的一部分:)
  • 如果您经常使用 SFML,那么 irc 频道中到处都是(大部分很有帮助的)怪人,他们有(也有一些没有)SFML 专业知识,请加入我们...
  • 我会试试看的:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2016-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多