IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

std::string mal envoyée sur le réseau.


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut std::string mal envoyée sur le réseau.
    Salut, j'essaye d'extraire un certificat d'openssl :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int Rsa::ossl_getCertificate (unsigned char** out) {
            return i2d_X509(x, out);
    }

    Pour l'envoyer à mon client.

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void Network::sendPbKeyRsa(User &user) {
                unsigned char* out = nullptr;
                int length = EncryptedPacket::getCertificate(&out);
                std::string response (reinterpret_cast<char*>(out), length);
                Packet packet;
                packet<<response;
                user.getTcpSocket().send(packet);
                user.setHasPbKeyRsa(true);
            }

    Mais à la réception ma chaîne de caractère est vide, le paquet est invalide car la taille de la chaîne est trop longue par rapport à la taille initiale du paquet.

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if (clientTCP.receive(packet) == Socket::Done) {
                            packet>>message;
                            Network::setPbKey(message);
                            pbKeyRsaReceived = true;

    De ce fait je n'ai pas de message et mon programme plante.
    Pourtant cela marchait bien auparavant, y a t'il eu des changements ?
    Faut il rajouter un \0 manuellement à la fin du tableau d'unsigned char ?
    Bref je ne comprends plus rien car au départ ça fonctionnait bien et ici tout à coup ça ne fonctionne plus.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Est-ce que out est correct ? Est-ce que response est correct ?
    Est-ce que je dois deviner l'implémentation des opérateurs << et >> ainsi que la structure de ta classe Packet ? Ou bien celle de send et son utilisation de Packet ?
    Comment est fait le recv et utilise-t-il Packet ? D'où sort message ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour voici l'implémentation de la classe paquet pour les string.
    à la réception :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    ////////////////////////////////////////////////////////////
    Packet& Packet::operator >>(std::string& data)
    {
        // First extract string length
        Uint32 length = 0;
        *this >> length;
     
        data.clear();
        if ((length > 0) && checkSize(length))
        {
            // Then extract characters
            data.assign(&m_data[m_readPos], length);
     
            // Update reading position
            m_readPos += length;
        }
     
        return *this;
    }
    Et à l'envoi :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    ////////////////////////////////////////////////////////////
    Packet& Packet::operator <<(const std::string& data)
    {
        // First insert string length
        Uint32 length = static_cast<Uint32>(data.size());
        *this << length;
     
        // Then insert characters
        if (length > 0)
            append(data.c_str(), length * sizeof(std::string::value_type));
     
        return *this;
    }

    Le problème est que à la réception je n'ai pas la même taille pour ma std::string que à l'envoi.

    A l'envoie ma std::string fait 635 de long.

    A la réception je me retrouve avec une taille invalide de 1608473334 hors que je devrais avoir la même taille que à l'envoi c'est à dire 635.

    Voici les méthodes send et receive du socket :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    ////////////////////////////////////////////////////////////
    Socket::Status TcpSocket::send(Packet& packet)
    {
        // TCP is a stream protocol, it doesn't preserve messages boundaries.
        // This means that we have to send the packet size first, so that the
        // receiver knows the actual end of the packet in the data stream.
     
        // We allocate an extra memory block so that the size can be sent
        // together with the data in a single call. This may seem inefficient,
        // but it is actually required to avoid partial send, which could cause
        // data corruption on the receiving end.
     
        // Get the data to send from the packet
        std::size_t size = 0;
        const void* data = packet.onSend(size);
     
        // First convert the packet size to network byte order
        Uint32 packetSize = htonl(static_cast<Uint32>(size));
     
        // Allocate memory for the data block to send
        std::vector<char> blockToSend(sizeof(packetSize) + size);
     
        // Copy the packet size and data into the block to send
        std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
        if (size > 0)
            std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
     
        // Send the data block
        std::size_t sent;
        Status status = send(&blockToSend[0] + packet.m_sendPos, blockToSend.size() - packet.m_sendPos, sent);
     
        // In the case of a partial send, record the location to resume from
        if (status == Partial)
        {
            packet.m_sendPos += sent;
        }
        else if (status == Done)
        {
            packet.m_sendPos = 0;
        }
     
        return status;
    }
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    ////////////////////////////////////////////////////////////
    Socket::Status TcpSocket::receive(Packet& packet)
    {
        // First clear the variables to fill
        packet.clear();
     
        // We start by getting the size of the incoming packet
        Uint32 packetSize = 0;
        std::size_t received = 0;
        if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
        {
            // Loop until we've received the entire size of the packet
            // (even a 4 byte variable may be received in more than one call)
            while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
            {
                char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
                Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
                m_pendingPacket.SizeReceived += received;
     
                if (status != Done)
                    return status;
            }
     
            // The packet size has been fully received
            packetSize = ntohl(m_pendingPacket.Size);
        }
        else
        {
            // The packet size has already been received in a previous call
            packetSize = ntohl(m_pendingPacket.Size);
        }
     
        // Loop until we receive all the packet data
        char buffer[1024];
        while (m_pendingPacket.Data.size() < packetSize)
        {
            // Receive a chunk of data
            std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
            Status status = receive(buffer, sizeToGet, received);
            if (status != Done)
                return status;
     
            // Append it into the packet
            if (received > 0)
            {
                m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
                char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
                std::memcpy(begin, buffer, received);
            }
        }
     
        // We have received all the packet data: we can copy it to the user packet
        if (!m_pendingPacket.Data.empty())
            packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
     
        // Clear the pending packet data
        m_pendingPacket = PendingPacket();
     
        return Done;
    }

    Voilà.

  4. #4
    Invité
    Invité(e)
    Par défaut
    J'ai trouvé l'erreur.

    En fait le client peut très bien recevoir d'autres messages en attendant j'ai donc fait précédé ma chaîne de caractère par un tag :

    Le serveur :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    void Network::sendPbKeyRsa(User &user) {
                unsigned char* out = nullptr;
                int length = EncryptedPacket::getCertificate(&out);
                std::string response (reinterpret_cast<char*>(out), length);
                response.insert(0, "RSAKEY");
                Packet packet;
                packet<<response;
                user.getTcpSocket().send(packet);
                user.setHasPbKeyRsa(true);
            }
            void Network::sendPbKey(User &user) {
                string response = string(SymEncPacket::getKey()) + "-" + string(SymEncPacket::getIv());
                response.insert(0, "AESKEY");
                EncryptedPacket packet;
                packet<<response;
                user.getTcpSocket().send(packet);
                user.setHasPbKey(true);
            }

    Le client :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    if (clientTCP.receive(packet) == Socket::Done) {
                            packet>>message;
                            if (message.find("RSAKEY") != std::string::npos) {
                                message.erase(0, 6);
                                std::cout<<"message : "<<message<<std::endl;
                                Network::setPbKey(message);
                                pbKeyRsaReceived = true;
                                packet.clear();
                                message = "GetPbKey";
                                enc_packet<<message;
                                clientTCP.send(enc_packet);
                                enc_packet.clear();
                            }
                        }
                    }
                    if (pbKeyRsaReceived && !done) {
                        if (clientTCP.receive(enc_packet) == Socket::Done) {
                            string message;
                            enc_packet>>message;
                            if (message.find("AESKEY")!= std::string::npos) {
                                message.erase(0, 6);
                                std::cout<<"message : "<<message<<std::endl;
                                Network::setSymPbKey(message);
                                done = true;
                                enc_packet.clear();
                            }
                        }
                    }

    Voilà; résolu!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Envoyer/recevoir des messages sur un réseau privé
    Par Tutotictac dans le forum Qt
    Réponses: 1
    Dernier message: 27/06/2008, 10h55
  2. Envoyer un fichier sur le réseau
    Par marmarbenh dans le forum Entrée/Sortie
    Réponses: 6
    Dernier message: 07/12/2007, 14h33
  3. Pb sur conversion CString en std:string
    Par Minos2 dans le forum MFC
    Réponses: 2
    Dernier message: 18/07/2007, 17h18
  4. Questions sur les std::string
    Par olive_le_malin dans le forum SL & STL
    Réponses: 6
    Dernier message: 23/02/2007, 08h44
  5. Erreur de compilation sur std::string avec Dev C++
    Par dada57 dans le forum Dev-C++
    Réponses: 4
    Dernier message: 20/03/2006, 18h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo