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

Auteur Sujet: Problème avec les sélectors.  (Lu 7243 fois)

0 Membres et 1 Invité sur ce sujet

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Problème avec les sélectors.
« le: Juin 18, 2013, 04:08:39 pm »
Salut, alors je vais mettre un code simple et minime cette fois : lorsque j'exécute ça côté serveur :
code du serveur :
if (listener.listen(4567) == Socket::Done && socketUDP.bind(4568) == Socket::Done)
        cout<<"Ok"<<endl;
    selector.add(listener);
    selector.add(socketUDP);
    while (true) {
        if (selector.wait()) {
            if (selector.isReady(listener)) {

                TcpSocket *client = new TcpSocket();
                if (listener.accept(*client) == Socket::Done) {
                    cout<<"Client connected"<<endl;
                    selector.add(*client);
                    clients.push_back(client);
                }
            } if (selector.isReady(socketUDP)) {
                Packet packet;
                IpAddress address;
                unsigned short int port;
                if (socketUDP.receive(packet,address, port) == Socket::Done) {
                    string message;
                    packet>>message;
                    cout<<"Received from client (UDP) : "<<message<<endl;
                    packet.clear();
                    message = "Ceci est un message UDP!";
                    packet<<message;
                    socketUDP.send(packet, IpAddress::LocalHost, 4569);
                }
            }
            for (unsigned int i = 0; i < clients.size(); i++) {
                if (selector.isReady(*clients[i])) {
                    Packet packet;
                    if (clients[i]->receive(packet) == Socket::Done) {
                        string message;
                        packet>>message;
                        cout<<"Received from client (TCP) : "<<message<<endl;
                        packet.clear();
                        message = "Ceci est un message TCP!";
                        packet<<message;
                        clients[i]->send(packet);
                    }
                } else {
                    selector.remove(*clients[i]);
                    vector<TcpSocket*>::iterator it;
                    for (it = clients.begin(); it != clients.end();)
                        if (*it ==clients[i])
                            it = clients.erase(it);
                        else
                            it++;
                }
            }
        }
    }
}
 
Lorsque j'envoie un message UDP suivit d'un message TCP avec le client, seul le message UDP est reçu par le serveur.
Code côté client :
#include <SFML/Network.hpp>
#include <iostream>
#include <sstream>
using namespace std;
using namespace sf;
int main () {
    TcpSocket clientTCP;
    UdpSocket socketUDP;
    SocketSelector selector;
    if (clientTCP.connect(IpAddress::LocalHost, 4567) == Socket::Done && socketUDP.bind(4569) == Socket::Done);
        cout<<"Ok"<<endl;
    selector.add(clientTCP);
    selector.add(socketUDP);
    Packet packet;
    string message = "";
    stringstream ss;
    ss<<"Ceci est un message pour test le protocole TCP avec la SFML."<<endl;
    message += ss.str();

    packet<<message;
    clientTCP.send(packet);
    packet.clear();
    message = "Ceci est un message UDP!";
    packet<<message;
    socketUDP.send(packet,IpAddress::LocalHost,4568);
    while (true) {
        if (selector.wait()) {
            packet.clear();
            message = "";
            IpAddress address;
            unsigned short int port;
            if (selector.isReady(clientTCP)) {
                if (clientTCP.receive(packet) == Socket::Done) {
                    packet>>message;
                    cout<<"Received from server (TCP) : "<<message<<endl;
                }
            }
            if (selector.isReady(socketUDP) == Socket::Done) {
                if (socketUDP.receive(packet, address, port) == Socket::Done) {
                    packet>>message;
                    cout<<"Received from server (UDP) : "<<message<<endl;
                }
            }
        }
    }

    return 0;
}
 
Quand je mets des else if au lieu des if côté serveur dans la boucle ça va déja mieux mais lorsque je ferme et que je relance le client, le serveur ne reçoit juste qu'un message UDP et le client ne reçoit plus rien, bref, j'ai des ennuis avec ça dans mon plus gros projet, parfois , j'ai des messages qui n'arrivent pas et ça fait carrément planté le programme. :/
Voici la version avec les else if.
code côté serveur :
#include "server.h"
using namespace std;
using namespace sf;
void Server::launch() {
    if (listener.listen(4567) == Socket::Done && socketUDP.bind(4568) == Socket::Done)
        cout<<"Ok"<<endl;
    selector.add(listener);
    selector.add(socketUDP);
    while (true) {
        if (selector.wait()) {
            if (selector.isReady(listener)) {

                TcpSocket *client = new TcpSocket();
                if (listener.accept(*client) == Socket::Done) {
                    cout<<"Client connected"<<endl;
                    selector.add(*client);
                    clients.push_back(client);
                }
            }  else if (selector.isReady(socketUDP)) {
                Packet packet;
                IpAddress address;
                unsigned short int port;
                if (socketUDP.receive(packet,address, port) == Socket::Done) {
                    string message;
                    packet>>message;
                    cout<<"Received from client (UDP) : "<<message<<endl;
                    packet.clear();
                    message = "Ceci est un message UDP!";
                    packet<<message;
                    socketUDP.send(packet, IpAddress::LocalHost, 4569);
                }
            } else {
                for (unsigned int i = 0; i < clients.size(); i++) {
                    if (selector.isReady(*clients[i])) {
                        Packet packet;
                        if (clients[i]->receive(packet) == Socket::Done) {
                            string message;
                            packet>>message;
                            cout<<"Received from client (TCP) : "<<message<<endl;
                            packet.clear();
                            message = "Ceci est un message TCP!";
                            packet<<message;
                            clients[i]->send(packet);
                        }
                    } else {
                        selector.remove(*clients[i]);
                        vector<TcpSocket*>::iterator it;
                        for (it = clients.begin(); it != clients.end();)
                            if (*it ==clients[i])
                                it = clients.erase(it);
                            else
                                it++;
                    }
                }
            }
        }
    }
}
 
code côté client.

Le même que celui ci-dessus.

PS : la méthode close() est en protected, on a plus besoin de le faire ça, la sfml le fait automatiquement ?
« Modifié: Juin 18, 2013, 04:45:03 pm par Lolilolight »

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #1 le: Juin 18, 2013, 10:04:57 pm »
Autre chose, parfois il ne m'affiche aucune message en TCP et ça bloque (il ne m'affiche rien au débuguage), ou alors un reste d'un ancien paquet, ça dépend, dans mon exemple si je renvoie 2 fois le même message au client là ça ne marche plus, il ne le reçoit pas.

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #2 le: Juin 19, 2013, 08:37:21 am »
J'ai tester ce code là, quand le serveur envoient plusieurs messages, le client ne reçois que les messages TCP :
#include "server.h"
using namespace std;
using namespace sf;
void Server::launch() {
    if (listener.listen(4567) == Socket::Done && socketUDP.bind(4568) == Socket::Done)
        cout<<"Ok"<<endl;
    selector.add(listener);
    selector.add(socketUDP);
    while (true) {
        if (selector.wait()) {
            if (selector.isReady(listener)) {

                TcpSocket *client = new TcpSocket();
                if (listener.accept(*client) == Socket::Done) {
                    cout<<"Client connected"<<endl;
                    selector.add(*client);
                    clients.push_back(client);
                }
            }  else if (selector.isReady(socketUDP)) {
                Packet packet;
                IpAddress address;
                unsigned short int port;
                if (socketUDP.receive(packet,address, port) == Socket::Done) {
                    string message;
                    packet>>message;
                    cout<<"Received from client (UDP) : "<<message<<endl;
                    packet.clear();
                    message = "Ceci est un message UDP!";
                    packet<<message;
                    socketUDP.send(packet, IpAddress::LocalHost, 4569);
                    socketUDP.send(packet, IpAddress::LocalHost, 4569);
                }
            } else {
                for (unsigned int i = 0; i < clients.size(); i++) {
                    if (selector.isReady(*clients[i])) {
                        Packet packet;
                        if (clients[i]->receive(packet) == Socket::Done) {
                            string message;
                            packet>>message;
                            cout<<"Received from client (TCP) : "<<message<<endl;
                            packet.clear();
                            message = "Ceci est un message TCP!";
                            packet<<message;
                            clients[i]->send(packet);
                            clients[i]->send(packet);
                        }
                    } else {
                        selector.remove(*clients[i]);
                        vector<TcpSocket*>::iterator it;
                        for (it = clients.begin(); it != clients.end();)
                            if (*it ==clients[i])
                                it = clients.erase(it);
                            else
                                it++;
                    }
                }
            }
        }
    }
}
 
Et comme je l'ai déja dis quand je ferme puis relance le client sans fermer le serveur, le serveur reçois que le messsage UDP.
Bizarre.
Tu es tout seul pour coder cette librairie ?
Bref si un jour tu tests ça chez toi, ou bien au pire je ferai appel à une autre librairie pour la gestion du réseau.
Pour ma part je vais essayer de compiler la sfml en mode debug pour voir si j'ai plus d'infos parce que la..., c'est chercher une aiguille dans une botte de foin.
PS : non, pas de message d'erreur en mode debug, la seule chose qui change est que il m'affiche 2 messages TCP et 1 message UDP pour le client donc il m'afficje des choses différentes en version release et en version débug.
« Modifié: Juin 19, 2013, 08:49:14 am par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème avec les sélectors.
« Réponse #3 le: Juin 19, 2013, 08:50:34 am »
Je vais essayer de tester ça, mais je ne te garantis rien, je n'ai pas beaucoup de temps libre en ce moment :(
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #4 le: Juin 19, 2013, 09:33:15 am »
Ok. :/
Sinon comment est ce que je pourrai avoir plus d'informations sur les erreurs renvoyées par la méhode send ?
Dans mon application à certains moment la méthode send me renvoie une erreur :
void User::sendTCPMessage(Packet& packet) {
    if(clientTCP.send(packet) == Socket::Done)
        cout<<"Ok"<<endl;
    else
        cout<<"Error"<<endl;
}
void User::sendUDPMessage(Packet &packet) {
    if (clientUDP.send(packet, address, remotePortUDP) == Socket::Done)
        cout<<"Ok"<<endl;
    else
        cout<<"Error"<<endl;
}
 

La gestion du réseau est exactement la même que dans le code que je t'ai donné en simplifié, dans mon plus gros projet, la seule chose qui change est que j'envoie plus de messages dans mon plus gros projet bien évidement.
Comment pourrai je savoir si je surcharge la pile TCP par exemple ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème avec les sélectors.
« Réponse #5 le: Juin 19, 2013, 09:36:59 am »
Via SFML tu ne peux pas avoir plus d'information.

J'ai compilé ton code et trouvé une première cacahuète : dans le code client, tu as un ; à la fin de la ligne "if (connect && bind)".

Maintenant je teste.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème avec les sélectors.
« Réponse #6 le: Juin 19, 2013, 09:46:50 am »
Erreur de logique : il ne faut pas appeler la fonction isReady avec des "else if", il peut y avoir plusieurs sockets prêtes en même temps, ce n'est pas exclusif. C'est d'ailleurs ce qui arrive dans ton test : le client envoie le message TCP et le message UDP en même temps, et du coup côté serveur seul le premier à arriver est traité alors que les deux sockets sont prêtes.

Dis moi si après ça il te reste encore des erreurs.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #7 le: Juin 19, 2013, 09:59:20 am »
Ok mais quand j'enlève le else if et donc le code côté serveur ressemble donc à ça :
#include "server.h"
using namespace std;
using namespace sf;
void Server::launch() {
    if (listener.listen(4567) == Socket::Done && socketUDP.bind(4568) == Socket::Done)
        cout<<"Ok"<<endl;
    selector.add(listener);
    selector.add(socketUDP);
    while (true) {
        if (selector.wait()) {
            if (selector.isReady(listener)) {

                TcpSocket *client = new TcpSocket();
                if (listener.accept(*client) == Socket::Done) {
                    cout<<"Client connected"<<endl;
                    selector.add(*client);
                    clients.push_back(client);
                }
            }
            for (unsigned int i = 0; i < clients.size(); i++) {
                if (selector.isReady(*clients[i])) {
                    Packet packet;
                    if (clients[i]->receive(packet) == Socket::Done) {
                        string message;
                        packet>>message;
                        cout<<"Received from client (TCP) : "<<message<<endl;
                        packet.clear();
                        message = "Ceci est un message TCP!";
                        packet<<message;
                        if(clients[i]->send(packet) == Socket::Done)
                            cout<<"Ok"<<endl;
                        else
                            cout<<"Erreur"<<endl;
                        if(clients[i]->send(packet) == Socket::Done)
                            cout<<"Ok"<<endl;
                        else
                            cout<<"Erreur"<<endl;
                    }
                } else {
                    selector.remove(*clients[i]);
                    vector<TcpSocket*>::iterator it;
                    for (it = clients.begin(); it != clients.end();)
                        if (*it ==clients[i])
                            it = clients.erase(it);
                        else
                            it++;
                }
            }
            if (selector.isReady(socketUDP)) {
                Packet packet;
                IpAddress address;
                unsigned short int port;
                if (socketUDP.receive(packet,address, port) == Socket::Done) {
                    string message;
                    packet>>message;
                    cout<<"Received from client (UDP) : "<<message<<endl;
                    packet.clear();
                    message = "Ceci est un message UDP!";
                    packet<<message;
                    if(socketUDP.send(packet, IpAddress::LocalHost, 4569) == Socket::Done)
                        cout<<"Ok"<<endl;
                    else
                        cout<<"Erreur"<<endl;
                    if(socketUDP.send(packet, IpAddress::LocalHost, 4569) == Socket::Done)
                        cout<<"Ok"<<endl;
                    else
                        cout<<"Erreur"<<endl;
                }
            }
        }
    }
}
 
Le serveur ne reçoit que le message UDP, pourquoi ça marche chez toi ?
PS : Ha par contre dans ma plus grosse appli là ça marche mieux et la fonction send ne me renvoie plus d'erreur depuis que j'ai enlever les "else if".
« Modifié: Juin 19, 2013, 10:13:11 am par Lolilolight »

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #8 le: Juin 19, 2013, 10:50:07 am »
Bon écoute ce n'est plus la peine de chercher car dans mon gros projet, ça marche.
Depuis que j'ai recompiler la SFML avec le nouveau patch, et que j'envoie des plus long message en TCP au lieu d'envoyer plusieurs petits messages, bah la fonction send ne me renvoie plus d'erreur et le client reçoit bien tout mes messages.  :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème avec les sélectors.
« Réponse #9 le: Juin 19, 2013, 11:00:49 am »
Cool :)

Par contre je crois qu'il y a une erreur dans ton dernier morceau de code : le "else" qui supprime le client est associé au "if isReady" alors qu'il devrait être associé à "if receive == Done".
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #10 le: Juin 19, 2013, 12:27:49 pm »
Ha oui juste c'est ça qui foirait tout dans ce petit bout code que j'avais donc, mal recopier de mon plus gros projet.

Par contre la pile TCP me semble assez petite, comment on peut connaitre sa taille ?
Je voudrais juste savoir combien de messages max je peux envoyer en même temps.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème avec les sélectors.
« Réponse #11 le: Juin 19, 2013, 12:49:40 pm »
Pour connaître le nombre d'octets que tu peux envoyer sans exploser la file d'attente, le mieux est encore de faire un test qui augmente progressivement la taille envoyée jusqu'à ce que la fonction send() te renvoie autre chose que Socket::Done.

Mais au fait, pourquoi as-tu besoin d'envoyer autant de données ?
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #12 le: Juin 19, 2013, 01:11:41 pm »
Bah, je n'en envoie pas beaucoup, juste les informations sur le personnage et le monstre toutes les secondes (ça je l'envoie en UDP) et quelques informations en TCP du genre un ensemble de points pour les déplacements du monstre et du personnage à la souris (Le pathfinding quoi.) à chaque fois que le personnage ou le monstre change de trajet.



« Modifié: Juin 19, 2013, 01:13:35 pm par Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Problème avec les sélectors.
« Réponse #13 le: Juin 19, 2013, 01:22:19 pm »
Et avec ces informations de pathfinding, tu excèdes les 65 Ko en un coup ?
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
Re : Problème avec les sélectors.
« Réponse #14 le: Juin 19, 2013, 01:27:59 pm »
Non mais j'ai des erreurs que me renvoie send si j'envoie trop de paquets d'un coup.