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

Auteur Sujet: Paquet TCP incomplet  (Lu 2941 fois)

0 Membres et 1 Invité sur ce sujet

Thall206

  • Newbie
  • *
  • Messages: 16
    • Voir le profil
Paquet TCP incomplet
« le: Juin 01, 2019, 04:51:13 pm »
Bonjour,

Je me casse les dents sur un petit soucis, j'aimerais un simple programme serveur-client qui permet d'envoyer des messages, et afin de m'entraîner, j'utilise aussi le multi-threading c++11.

Seulement, voilà, pour je ne sais quel raison, les paquets reçus par le client sont incomplets (voir screen), après quelques recherches, je me rend compte que ça vient peut-être des paquets envoyés. Apparemment, lorsque que je fais
packet << cmd;
avec cmd qui est un string, le paquet ne contient pas tout le string contenu dans cmd.

Par le plus grand des hasards, quand je rajoute la ligne
std::cout << "Message original: " << cmd << std::endl;
juste avant, cela fonctionne, mais sans cette ligne, les messages reçus sont parfois incomplets, pourquoi?

Code du serveur émettant:

#include <SFML/Network.hpp>
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <stdlib.h>
#include <thread>



void sendString(const std::string &msg, std::unique_ptr<sf::TcpSocket> &client)
{
    sf::Packet packet;
    packet << msg;
    client->send(packet);
    packet.clear();

}


void thread_function(std::string *cmd)
{
    while(*cmd != "close")
    {
        if(*cmd == "")
        {
            std::cout << "Entrez votre commande: ";
            getline(std::cin, *cmd);
        }
    }
}


int main()
{
    std::string cmd = ""; //Gere les commandes

    sf::TcpListener listener;
    std::vector<std::unique_ptr<sf::TcpSocket>> clients;

    int iClient = 0;

    sf::Socket::Status status;

    clients.push_back(std::unique_ptr<sf::TcpSocket>(new sf::TcpSocket()));
    listener.listen(53000);
    listener.accept(*clients[iClient]);
    std::cout << "Connexion " << iClient+1 << " reussie !" << std::endl;
    sendString("Connexion reussie !", clients[iClient]);

    listener.setBlocking(false);


    std::thread threadObj(thread_function, &cmd);//Thread gerant les commandes de son côté

    clients.push_back(std::unique_ptr<sf::TcpSocket>(new sf::TcpSocket()));
    iClient++;

    while(cmd != "close")
    {

        if(listener.accept(*clients[iClient]) == sf::Socket::Done)
        {
            clients.push_back(std::unique_ptr<sf::TcpSocket>(new sf::TcpSocket()));
            sendString("Connexion reussie !", clients[iClient]);
            iClient++;
            std::cout << "Connexion " << iClient << " reussi !"<< std::endl;
        }

        if(cmd != "")
        {
//            std::cout << "Message original: " << cmd << std::endl; // <------ Ligne qui résout le soucis

            for(int i = 0; i < clients.size()-1; i++)
            {
                sf::Packet packet;
                packet << cmd;
                status = clients[i]->send(packet);
            }
            cmd = "";
        }

    }




    for(int i = 0; i < clients.size()-1; i++)
        sendString("Connexion over", clients[i]);

    threadObj.join(); //Attend que l'autre thread est fini avant de fermer le programme
    return 0;
}


 

Code du client recevant:

int main(){
    sf::TcpSocket socket;
    socket.connect("127.0.0.1", 53000);
    std::string msgrecu;


    while(msgrecu != "over")
    {
        sf::Packet packet;
        if(socket.receive(packet) == sf::Socket::Done)
        {
            packet >> msgrecu;
            std::cout << packet.getDataSize() << " : " << msgrecu << std::endl;
            packet.clear();

        }

    }

}

Merci bien de m'avoir lu, en espérant que j'ai été clair,

Bonne journée


Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re: Paquet TCP incomplet
« Réponse #1 le: Juin 01, 2019, 06:15:05 pm »
Tu n'as aucune sorte de synchronisation entre tes threads, alors que chacun va aller taper dans la même variable. Ca ne peut pas marcher de manière fiable. Il faut protéger l'accès à la variable "cmd" (avec un mutex ou autre).

Et pour l'instant le multi-thread ne sert à rien dans ton code mais j'imagine que tu en es conscient et que c'est pour apprendre que tu fais ça :)
Laurent Gomila - SFML developer

Thall206

  • Newbie
  • *
  • Messages: 16
    • Voir le profil
Re: Paquet TCP incomplet
« Réponse #2 le: Juin 01, 2019, 08:54:07 pm »
Effectivement c'était ça.

Et oui, je compte utiliser le multi-thread pour implémenter un système de multi-joueur avec le serveur qui gère le jeu dans un thread, et peut recevoir des commandes sans freeze à cause du "getline" dans un autre.

Je profite de ce poste pour rapidement poser une question hors-sujet: Aurais-tu des sites/forums pour rejoindre des projets en développement ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re: Paquet TCP incomplet
« Réponse #3 le: Juin 02, 2019, 03:21:01 pm »
Citer
Aurais-tu des sites/forums pour rejoindre des projets en développement ?
Non je n'en connais pas, désolé.
Laurent Gomila - SFML developer