1
Réseau / Clarification sur la création d'un serveur qui gère plusieurs clients.
« le: Décembre 08, 2016, 05:22:12 pm »
Bonsoir, dans le cadre d'un projet universitaire je suis confronté à une difficulté qu'est de créer un serveur donc avec SFML multithreadé (du moins je pense). Cependant je dois mal m'y prendre car je rencontre quelques problèmes...
Approche global de ma vision du serveur :
Le serveur démarre, se met en attente de nouveaux clients, j'ai donc une boucle qui tourne tant que le serveur n'est pas off, à chaque connexion d'un client je démarre un nouveau thread qui sera dédié à la communication avec ce client au moyen du socket, chaque client est stocké dans une map avec un id et son objet connexion (qui comporte la méthode threadé d'au dessus), dans cette méthode j'ai aussi une boucle active tant que la connexion est active puis je lis les paquets reçus, les traites etc.
Je dois passer par des paquets pour faire transiter les données du client vers le serveur, c'est le moyen que je trouve le plus simple et plus intuitif pour ce type de projet. J'utilise des paquets TCP, UDP n'étant pas adapté au projet.
J'aimerais donc avoir des éclaircissement sur comment mettre en place un tel serveur, comment gérer les connexions/déconnexions des clients, la réception des paquets etc le tout le plus optimisé possible.
Mes problèmes
Mon serveur reçoit le paquet mais pompe environ 20% du processeur, je reçois 0 dans le paquet lu alors que j'envoie 42.
Voici ce que j'ai actuellement fait (qui ne fonctionne pas) :
Client
Server
Voila globalement les parties les plus intéressantes, toute aide est la bienvenue.
Bonne soirée, merci.
Clyx.
Approche global de ma vision du serveur :
Le serveur démarre, se met en attente de nouveaux clients, j'ai donc une boucle qui tourne tant que le serveur n'est pas off, à chaque connexion d'un client je démarre un nouveau thread qui sera dédié à la communication avec ce client au moyen du socket, chaque client est stocké dans une map avec un id et son objet connexion (qui comporte la méthode threadé d'au dessus), dans cette méthode j'ai aussi une boucle active tant que la connexion est active puis je lis les paquets reçus, les traites etc.
Je dois passer par des paquets pour faire transiter les données du client vers le serveur, c'est le moyen que je trouve le plus simple et plus intuitif pour ce type de projet. J'utilise des paquets TCP, UDP n'étant pas adapté au projet.
J'aimerais donc avoir des éclaircissement sur comment mettre en place un tel serveur, comment gérer les connexions/déconnexions des clients, la réception des paquets etc le tout le plus optimisé possible.
Mes problèmes
Mon serveur reçoit le paquet mais pompe environ 20% du processeur, je reçois 0 dans le paquet lu alors que j'envoie 42.
Voici ce que j'ai actuellement fait (qui ne fonctionne pas) :
Client
bool Client::connect() {
bool success = m_socket.connect(m_host, m_port) == sf::Socket::Done;
if(success){
std::cout << "Connected !" << std::endl;
m_active = true;
std::thread thread(sendData, this);
thread.detach();
}else{
std::cerr << "Unable to connect to server" << std::endl;
}
return success;
}
//Ma méthode qui enverra les paquets,
void Client::sendData() {
sf::Packet packet;
int i = 42;
packet << i;
m_socket.send(packet);
}
bool success = m_socket.connect(m_host, m_port) == sf::Socket::Done;
if(success){
std::cout << "Connected !" << std::endl;
m_active = true;
std::thread thread(sendData, this);
thread.detach();
}else{
std::cerr << "Unable to connect to server" << std::endl;
}
return success;
}
//Ma méthode qui enverra les paquets,
void Client::sendData() {
sf::Packet packet;
int i = 42;
packet << i;
m_socket.send(packet);
}
Server
void Server::start() {
if(m_port == 0){
std::cerr << "Error the server must have a port !" << std::endl;
return;
}
if(m_listener.listen(m_port) != sf::Socket::Done){
std::cerr << "Error while starting server, port is already in use" << std::endl;
return;
}
m_active = true;
std::cout << "Server started on port " << m_port << " waiting for new client..." << std::endl;
sf::TcpSocket clientSocket;
while(m_active){
if(m_listener.accept(clientSocket) != sf::Socket::Done){
std::cerr << "Error while receiving new connection" << std::endl;
}
unsigned short id = generateClientId();
ClientConnection *clientConnection = new ClientConnection(0, clientSocket);
clientConnection->setActive(true);
addClient(id, clientConnection);
clientConnection->listenPackets();
std::cout << "New client connected, starting thread !" << std::endl;
std::thread thread(&ClientConnection::listenPackets, clientConnection);
thread.detach();
}
std::cout << "Server stopped" << std::endl;
}
//Méthode qui gère la réception des paquets
void ClientConnection::listenPackets() {
sf::Packet packet;
int a;
while(m_active){
m_socket->receive(packet);
while(!packet.endOfPacket()){
packet >> a;
std::cout << "Recu " << a << std::endl;
}
}
}
if(m_port == 0){
std::cerr << "Error the server must have a port !" << std::endl;
return;
}
if(m_listener.listen(m_port) != sf::Socket::Done){
std::cerr << "Error while starting server, port is already in use" << std::endl;
return;
}
m_active = true;
std::cout << "Server started on port " << m_port << " waiting for new client..." << std::endl;
sf::TcpSocket clientSocket;
while(m_active){
if(m_listener.accept(clientSocket) != sf::Socket::Done){
std::cerr << "Error while receiving new connection" << std::endl;
}
unsigned short id = generateClientId();
ClientConnection *clientConnection = new ClientConnection(0, clientSocket);
clientConnection->setActive(true);
addClient(id, clientConnection);
clientConnection->listenPackets();
std::cout << "New client connected, starting thread !" << std::endl;
std::thread thread(&ClientConnection::listenPackets, clientConnection);
thread.detach();
}
std::cout << "Server stopped" << std::endl;
}
//Méthode qui gère la réception des paquets
void ClientConnection::listenPackets() {
sf::Packet packet;
int a;
while(m_active){
m_socket->receive(packet);
while(!packet.endOfPacket()){
packet >> a;
std::cout << "Recu " << a << std::endl;
}
}
}
Voila globalement les parties les plus intéressantes, toute aide est la bienvenue.
Bonne soirée, merci.
Clyx.