2017-04-14 12 views
1

私は現在、マルチプレイヤーゲームのネットワーキングの一部を書こうとしています。私は、SFMLのコピー不可能なTCPソケットを格納する問題に直面しています(私は初心者ですC++)。SFMLで複数のクライアントソケットを扱う

私は三つのクラスがあります。ServerClientすべてのクライアントを格納し、それらのIDを与えることを担当している(サーバー側の接続クライアントに関するすべての情報を格納するために使用されるクラス)とClientManager、など

をクライアントが接続したときに、私はもともと行うことを計画何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にポインタとして格納すると、以前と同じ問題が発生します。これは、ソケットも変更され、ポインタは同じオブジェクトを指しているためです。

リファレンス、ポインタを使用したりオブジェクトをコピーしたりせずにソケットを保存するにはどうすればよいですか?

すべてのヘルプは大歓迎されます:)

+0

私は家に帰るときにこれ以上見る必要があります。ソケットのアドレスをclientManagerに渡してから、ソケットとIP情報を取得して保存してください。 – Eddge

+0

std :: unique_ptrまたはshared_ptrを使用して動的メモリを使用し、ベクトル/マップにポインタを格納するだけで済みます(これにより、接続ごとにメモリを割り当てる必要があります)。 – Eddge

+0

ご回答いただきありがとうございます!実際には、新たに接続されたすべてのクライアントにメモリを割り当てる必要があります(または、ポインタのケースをちょうど満たします)。メモリを割り当てることによって、whileループの先頭に 'shared_ptr'ポインタを作成し、' new'でメモリを割り当て、 'std :: map >'(または他の 'shared_ptr'を使って他の方法で)' ClientManager'に保存しますか? – cocosushi

答えて

1

ポインタをせずに行うには本当の痛みになるだろう。個人的に私は実際の通信を管理するために `sf :: SocketSelector 'と一緒にソケット自体(std::vector<std::unique_ptr<sf::TcpSocket>>またはsimiliar)を管理するためにスマートポインタを使用します

+0

これは私のコメントでEddgeに答えて提案したように、私は 'std :: map'(私もIDが必要です)と' std :: shared_ptr'を使いました(スマートポインタをうまくマスターしていないので、しかし、少なくとも動作します)。私も 'sf :: SocketSelector'を使用して終了しました:) – cocosushi

+0

可能な限りshared_ptrを使ってunique_ptrを使うことをお勧めします(これについてはたくさんのインターネット引数が浮かんでいますが、私はあなたを退屈させません...)。あなたに何か問題が起こります。うまくいきました:) –

+0

これについて後で(大きく)見ていきます。それについてもっと知りたいと思っている科目の一部です:) – cocosushi

関連する問題