Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Problème dans le système d'écoute côté serveur  (Lu 3471 fois)

0 Membres et 1 Invité sur ce sujet

GG_A_SsaSsIbs

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Problème dans le système d'écoute côté serveur
« le: Mars 13, 2014, 05:21:55 pm »
Bonjour à tous,

Je réalise à titre d'entrainement un client/serveur basique de type chat. Je rencontre un problème lors de l'écoute et du traitement des données côté serveur, mon programme server toutefois compile bien et ne plante pas mais il ne retourne pas le résultat attendu .

Mon système fonctionne ainsi :

Le serveur stock les clients dont la connexion à réussi dans un conteneur list et à partir de ce conteneur list j'écoute chaque client connecté pour gérer les packets entrant/sortant.

Voici le morceau de code traitant de ceci :

if(selector.wait(sf::milliseconds(100)))
    {
        if (selector.isReady(listener))
        {
            client = new sf::TcpSocket;

            if(listener.accept(*client) == sf::Socket::Done)
            {
                clientList.emplace_back(client);
                for(std::list<std::unique_ptr<sf::TcpSocket>>::iterator it = clientList.begin(); it != clientList.end(); ++it)
                {
                    if(**it == *client)
                     {
                        selector.add(**it);
                     }
                }
                std::cout << "Client IP : " << client->getRemoteAddress() << "connected" << std::endl;

            }else{

                delete client;

            }
        }
        if(!clientList.empty())
        {
            for(auto& clientCurrentList: clientList)
            {
                std::cout << selector.isReady(*clientCurrentList) << std::endl;
                if(selector.isReady(*clientCurrentList))
                {
                    std::cout << "test2" << std::endl;
                    if(clientCurrentList->receive(packet) == sf::Socket::Done)
                    {
                        std::cout << "Client IP : " << clientCurrentList->getRemoteAddress() << "send a packet" << std::endl;
                        packet >> message;
                        for(auto& sendClientCurrentList: clientList)
                        {
                            packet << message;
                            sendClientCurrentList->send(packet);
                        }
                    }else if(clientCurrentList->receive(packet) == sf::Socket::Error)
                    {
                        std::cout << "Client IP : " << clientCurrentList->getRemoteAddress() << "error with a packet" << std::endl;
                    }
                }
            }
        }

    }

Mon problème ce situe dans la seconde partie du code, ici précisément :

if(selector.isReady(*clientCurrentList))
Ma condition est toujours fausse quoi qu'il arrive ce qui fait que mon client plante puisque le packet n'arrive jamais, il faut que j'éteigne le serveur pour débloquer le client.

Si une âme charitable pouvait m'expliquer ce que j'ai fait de travers, je suis preneur. :)

Merci par avance.

GG_A_SsaSsIbs

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : Problème dans le système d'écoute côté serveur
« Réponse #1 le: Mars 19, 2014, 06:52:25 pm »
Je viens du coup apporter quelque précisions car mon explication ci-dessus est erroné.

J'ai modifié un peu mon code en utilisant les smartPointer et voici :

if(selector.wait(sf::milliseconds(50)))
    {
        std::cout << "entrer dans le selector wait" << std::endl;
        if (selector.isReady(listener))
        {
            std::unique_ptr<sf::TcpSocket> client = make_unique<sf::TcpSocket>();


            if(listener.accept(*client) == sf::Socket::Done)
            {
                ip = client->getRemoteAddress().toString();
                std::cout << "Client IP : " << client->getRemoteAddress() << " connected" << std::endl;
                clientList.emplace_back(std::move(client));
                for(auto& clientCurrentList: clientList)
                {
                    if(clientCurrentList->getRemoteAddress().toString() == ip)
                    {
                        selector.add(*clientCurrentList);
                    }
                }


            }
        }else{
            for(auto& clientCurrentList: clientList)
            {
                if(selector.isReady(*clientCurrentList))
                {
                    if(clientCurrentList->receive(packet) == sf::Socket::Done)
                    {
                        std::cout << "Client IP : " << clientCurrentList->getRemoteAddress() << "send a packet" << std::endl;
                        packet >> message;
                        for(auto& sendClientCurrentList: clientList)
                        {
                            packet << message;
                            sendClientCurrentList->send(packet);
                        }
                    }else if(clientCurrentList->receive(packet) == sf::Socket::Error)
                    {
                        std::cout << "Client IP : " << clientCurrentList->getRemoteAddress() << "error with a packet" << std::endl;
                    }
                }
            }
        }
    }

En réalité mon problème et que je rentre bien dans "selector.wait(sf::milliseconds(50))" lorsque le sélecteur détecte une action venant du listener mais hors mit ce cas de figure, je ne rentre plus jamais dans cette condition.

 Du coup je me demande ou sa pêche puisque avec ce nouveau code, je stock mon nouvel objet TcpSocket() dans mon std::list et dans le sélecteur, je référence le nouvel objet socket :"selector.add(*clientCurrentList)".

Je fais envoyer au client dont la connexion à réussi avec le serveur, un 'sf::packet' contenant une chaine de caractère basique pour tester et pourtant, à chaque bouclage côté serveur, je ne rentre quand même pas dans la condition, comme si le sélecteur avait perdu la trace ou n'avait tout simplement jamais eu la référence aux sockets stockés dans le conteneur et du coup rien n'écoute les dites socket.

Je ne sais pas si j'aurais plus d'aide ou de succès qu'a mon premier post :) mais sa ne coute rien d'essayer. Je continue d'investiguer de mon côté.

Merci par avance.
« Modifié: Mars 19, 2014, 07:08:48 pm par GG_A_SsaSsIbs »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème dans le système d'écoute côté serveur
« Réponse #2 le: Mars 19, 2014, 08:45:39 pm »
A priori rien de bizarre dans ton code.

Si tu fais un exemple complet minimal, j'aurais peut-être 5 minutes pour tester à l'occase.
Laurent Gomila - SFML developer

kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Problème dans le système d'écoute côté serveur
« Réponse #3 le: Mars 19, 2014, 08:51:47 pm »
Il y a un premier problème ici:

if(selector.isReady(*clientCurrentList))
{
    // Ici, le client est prêt à recevoir donc receive sera fait sans attendre.
    if(clientCurrentList->receive(packet) == sf::Socket::Done)
        // ...

    // À ce moment là, le client n'a probablement rien reçu d'autre
    // donc un nouvel appel à receive va bloquer le programme.
    else if(clientCurrentList->receive(packet) == sf::Socket::Error)
        // ...
}

Il ne faut appeler receive qu'une seule fois.
Tu peux procéder ainsi:
if(selector.isReady(*clientCurrentList))
{
    sf::Socket::Status status = clientCurrentList->receive(packet);
    if(status == sf::Socket::Done)
        // ...
    else if(status == sf::Socket::Error)
        // ...
}

Autre remarque:
Ta façon d'ajouter les clients est plutôt bizarre. Tu ajoutes le client en fin de liste puis tu le cherches dans ta liste, alors qu'il est à disposition.
Pourquoi pas simplement:
std::cout << "Client IP : " << client->getRemoteAddress() << " connected" << std::endl;
selector.add(*client);
clientList.emplace_back(std::move(client));

GG_A_SsaSsIbs

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : Problème dans le système d'écoute côté serveur
« Réponse #4 le: Mars 19, 2014, 09:44:51 pm »
Merci pour vos réponses. Je prépare un code minimal et j'envois ça. ;)

Pour les remarques, merci, je viens de corriger le code en conséquence même si ça n'a rien changé à mon problème. :)

GG_A_SsaSsIbs

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : Problème dans le système d'écoute côté serveur
« Réponse #5 le: Mars 19, 2014, 10:59:45 pm »
Voila, je transmet mon serveur dans un premier zip, il contient les sources, les libs/includes et même le programme compilé si vous êtes sous windows. ( Le projet ainsi que la lib SFML ont été Compilés sous MinGW TDM-GCC 4.8.1 )

Pour démarrer le serveur, il faut ouvrir votre interpréteur de commande et lancer l’exécutable en y ajoutant l'argument "start" -> server-chat.exe start

Une fois le serveur lancé, vous pouvez l’arrêter à tout moment en rentrant l'argument "off" ( sans les guillemets ) toujours dans votre interpréteur de commande.

http://dl.free.fr/getfile.pl?file=/yUpxs4kT

Pour la composition du zip client minimal, c'est la même que celle du serveur. La seule différence est que vous pouvez lancer directement l’exécutable. ( Attention, le client minimal utilises les même chemins de lib/includes que le serveur, faire attention à ça en cas de re-compilation ).

http://dl.free.fr/getfile.pl?file=/e0tc2pzB

Merci. :)

 

anything