Salut Laurent :-)
Oui, c'est normal, c'est comme cela que je procède côté client, en effet.
Le serveur lui, sait de quel client ça vient grâce à sa socket, il retrouve son ID automatiquement et peut renseigner les autres joueurs sur le changement de coordonnées qu'un joueur a fait et renvoyant l'information aux autres joueurs, cette fois-ci avec l'ID du joueur concerné, et côté client, on RÉCEPTIONNE avec l'ID du joueur dont il est question, ça fonctionne très bien comme ça..
En fait, mon problème c'est que je n'arrive pas à envoyer une information directement depuis mon Serveur, on dirait qu'il est " bloqué ".
J'ai refait entièrement un petit programme Serveur/Client de test qui fonctionne mais avec le même problème :
Côté Serveur
#include "../../Headers/Network/Network.h"
Network::Network(std::vector<Client>& vecClient) :
m_Client(vecClient)
{
}
void Network::Launch(USHORT port)
{
m_port = port;
if (m_listener.listen(m_port) == sf::Socket::Done)
{
std::cout << "Serveur lance sur le port " << m_port << std::endl;
m_listener.setBlocking(false);
m_socketSelector.add(m_listener);
m_isRunning = true;
} else {
std::cout << "Impossible de lancer le serveur sur le port " << m_port << std::endl;
}
}
void Network::MainLoop()
{
if (m_socketSelector.wait())
{
if (m_socketSelector.isReady(m_listener))
{
PushNewUser();
} else {
SendToClients();
ReceiveAndSendData();
}
}
}
void Network::PushNewUser()
{
sf::TcpSocket *socket = new sf::TcpSocket();
socket->setBlocking(false);
m_listener.accept(*socket);
std::cout << "Une connexion est detectee." << std::endl;
sf::Uint16 idNumber = 1;
while (m_Client[idNumber].getIdNumber()!=0)
idNumber++;
if (idNumber <= 4)
{
m_Client[idNumber].setSocket(socket);
m_Client[idNumber].setState(true);
m_Client[idNumber].setIdNumber(idNumber);
m_socketSelector.add(*m_Client[idNumber].getSocket());
} else {
m_blackList.push_back(socket);
CheckBlackList();
}
}
void Network::CheckBlackList()
{
if (m_blackList.size() > 0)
{
for (unsigned int i = 0 ; i < m_blackList.size() ; i++)
{
sf::Packet sendPacket;
sendPacket << DATA::INFO << "FULL";
m_Client[i].getSocket()->send(sendPacket);
m_blackList.erase(m_blackList.begin()+i);
}
}
}
void Network::SendToClients()
{
if (_kbhit())
{
if (_getch() == 'w')
{
sf::Packet packTest;
packTest << DATA::INFO << sf::Uint16(0) << "Salut ! ";
for (unsigned int i = 0 ; i < m_Client.size() ; i++)
{
if (m_Client[i].getIdNumber() !=0)
{
sf::Packet packTest;
packTest << DATA::INFO << sf::Uint16(0) << "Salut ! ";
m_Client[i].getSocket()->send(packTest);
std::cout << "Message du serveur envoye au(x) client(s)." << std::endl;
}
}
}
}
}
void Network::ReceiveAndSendData()
{
for (unsigned int i = 0 ; i < m_Client.size() ; i++)
{
if (m_Client[i].getIdNumber()!=0 && m_socketSelector.isReady(*m_Client[i].getSocket()))
{
sf::Packet receivePacket;
if (m_Client[i].getSocket()->receive(receivePacket) == sf::Socket::Done)
{
sf::Uint32 Checker;
receivePacket >> Checker;
switch(Checker)
{
case DATA::INFO:
{
std::string information;
receivePacket >> information;
std::cout << "DATA::INFO du Client N " << m_Client[i].getIdNumber() << " : " << information << std::endl;
sf::Packet sendPacket;
sendPacket << DATA::INFO << information;
m_Client[i].getSocket()->send(sendPacket);
}
break;
case DATA::USERNAME:
{
std::string username;
receivePacket >> username;
m_Client[i].setUsername(username);
std::cout << username << " vient de se connecter." << std::endl;
sf::Packet sendPacket;
sendPacket << DATA::USERNAME << sf::Uint16(0) << m_Client[i].getUsername();
m_Client[i].getSocket()->send(sendPacket);
}
break;
case DATA::DIRECTION:
{
sf::Uint32 direction;
receivePacket >> direction;
std::cout << "DATA::DIRECTION du Client N " << m_Client[i].getIdNumber() << " : " << direction << std::endl;
sf::Packet sendPacket;
sendPacket << DATA::DIRECTION << sf::Uint16(0) << direction;
m_Client[i].getSocket()->send(sendPacket);
}
break;
}
}
}
}
}
///GETTERS///
bool Network::isRunning() const { return m_isRunning; }
Côté Client
#include "../../Headers/Network/Network.h"
Network::Network(Client& client) :
m_Client(client)
{
}
void Network::ConnectToServer(std::string ipAddress, USHORT Port)
{
if (m_socket.connect(ipAddress, Port) == sf::Socket::Done)
{
std::cout << "Connexion reussie au serveur." << std::endl;
m_isRunning = true;
m_socket.setBlocking(false);
} else {
std::cout << "Connexion impossible..." << std::endl;
exit(0);
}
}
void Network::SendData(float timeSend)
{
if (m_clockSend.getElapsedTime().asMilliseconds() > timeSend)
{
if (m_Client.getDirection() != m_structData.Direction)
{
m_structData.Direction = m_Client.getDirection();
if (m_structData.Direction !=0)
{
sf::Packet sendPacket;
sendPacket << DATA::DIRECTION << m_structData.Direction;
m_socket.send(sendPacket);
std::cout <<"Direction envoyee au serveur" << std::endl;
m_structData.Direction = 0;
}
}
if (m_Client.getUsername() != m_structData.Username)
{
m_structData.Username = m_Client.getUsername();
sf::Packet sendPacket;
sendPacket << DATA::USERNAME << m_structData.Username;
m_socket.send(sendPacket);
std::cout <<"Username envoye au serveur" << std::endl;
}
m_clockSend.restart();
}
}
void Network::ReceiveData()
{
sf::Packet receivePacket;
if (m_socket.receive(receivePacket) == sf::Socket::Done)
{
sf::Uint32 Checker;
sf::Uint16 idNumber;
receivePacket >> Checker >> idNumber;
switch(Checker)
{
case DATA::INFO:
{
std::string info;
receivePacket >> info;
std::cout << "Recu info : " << info << std::endl;
}
case DATA::DIRECTION:
{
sf::Uint32 direction;
receivePacket >> direction;
std::cout << "Le serveur vous renvoi votre direction : " << direction << std::endl;
}
break;
}
}
}
///GETTERS///
bool Network::isRunning() const { return m_isRunning; }
J'ai fait, pour le test, en sorte que si l'on appuie sur la touche W, que ça envoi l'information aux Clients avec une itération, mais l'information n'arrive pas instantanément, il faut obligatoirement que les Clients concernés aient renvoyé un message pour que le serveur envoi le sien, comme si il était bloqué / en attente..
Exemple :
Mon serveur à gauche, mon client à droite.
Lorsque j'appuie sur la touche W sur mon serveur, il ne se passe rien côté serveur, ni client..
PAR CONTRE si le client change sa position ALORS le serveur envoi finalement l'information, mais j'ai aussi un bug car le Client reçoit une DATA::DIRECTION de 2292880 alors que je n'ai jamais demandé au serveur de renvoyer la direction à ce moment-là ( et surtout pas avec cette donnée faussée ).
Ma question ultime est, comment faire pour que lorsque je presse la touche 'W' sur mon serveur, celui-ci envoi instantanément aux clients la DATA::INFO que j'ai envie d'envoyer ?
D'où viendrait aussi le bug inhérent à la direction ?
PS : Voici mon enumération de mon Network.h qui est la même de chaque côté :
enum DATA:sf::Uint32{INFO, USERNAME, DIRECTION};
Merci infiniment ! :-)