2017-04-14 13 views
1

현재 멀티 플레이어 게임의 네트워킹 부분을 작성하려고하고 있습니다. SFML로 복사 할 수없는 TCP 소켓을 저장하는 데 문제가 있습니다. (초보자입니다. C++). Server, Client 등 모든 클라이언트를 저장하고 그들에게 ID를 부여 담당하고 ClientManager (모든 접속 클라이언트에 대한 정보를 저장하는 서버 측 클래스),SFML을 사용하여 여러 클라이언트 소켓 처리

:

난 세 종류를 클라이언트가 연결될 때 내가 원래 할 계획 무엇 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())); 
    } 
} 

따라서 ClientManager의 목록에 ID가있는 Client을 추가하면 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

. 개인적으로 스마트 포인터 (std::vector<std::unique_ptr<sf::TcpSocket>> 또는 similiar)와 함께 실제 통신을 관리하기 위해`sf :: SocketSelector '와 함께 스마트 포인터를 사용합니다.

+0

이것은 Edge에 대한 제 의견에 제안한대로 끝났습니다. 내가'std :: map' (ID가 필요함)과'std :: shared_ptr' (스마트 포인터를 잘 마스터하지 못해 잘 사용하는 지 모르겠다. 하지만 적어도 작품). 나는 또한'sf :: SocketSelector'를 사용하여 끝냈다. :) – cocosushi

+0

shared_ptr을 통해 unique_ptr을 사용할 것을 권하고 싶다. (가능한 많은 인터넷 인자들이 주위에 떠돌고 있는데, 나는 너를 지루하게하지 않을 것이다 ...) 그러나 나는 그것을 의심 할 것이다. 너에게 어떤 문제가 생겨. 다행 이네요. –

+0

나중에 이것에 대해 (크게) 보겠습니다. 그것에 대해 더 자세히 알고 싶은 주제의 일부입니다 :) – cocosushi