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

C++ Discussion :

[Structure] Conseils pour l'implementation d'un protocole sur RS232 ?


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut [Structure] Conseils pour l'implementation d'un protocole sur RS232 ?
    Salut,

    Je dois implementer, sous windows XP, un protocole de securite a partir des specifications fournies par le constructeur. Mon programme se limite a la communication avec un validateur d'acces (interface supportant scanners retiens, scanners d'empreintes, ...)

    La communication se fait par liaison serie RS232 mais je devrais apres la porter sur reseau Ethernet (pour controler plusieurs validateurs d'acces).

    Suite a la lecture des 700 pages de specifications et aux tests realises, je peux dire que le protocole n'a plus de secrets pour moi :

    Les paquets sont de tailles variables mais l'en-tete contient la longueur du paquet. Bien qu'il semble y avoir un type de paquets qui n'a pas d'en-tete mais dont la taille est fixe.
    Les paquets de donnees sont relativement petits. (fixons le relatif a 100 octets)

    La connexion est un "3 ways handshake" avec echange de paquets de synchronisation et d'acknowledgement.

    Avant de me lancer dans l'implementation, j'aimerais savoir par ou commencer et comment structurer le programme :
    Dois-je utiliser une liaison serie en mode synchrone/asynchrone ? Avec ou sans thread de reception ?

    La manipulation des paquets via basic_string<unsigned char> est-elle viable ?

    Cette structure vous semble-t-elle correcte :
    • Une classe RS232 responsable des fonctions de lecture/ecriture sur le peripherique serie. (+/- couche physique)
    • Une classe STREAM responsable de la recuperation de l'integralite d'un paquet. (+/- couche liaison de donnees)
    • Une classe PROTOCOL responsable de l'exctraction/insertion des informations a recevoir/envoyer. (+/- couche application)

    Merci de me faire part de vos conseils.

  2. #2
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    quelques conseils en vrac:

    -> de façon générale, le mode asynchrone pour le port série est déconseillé car trop difficile à gérer et le mode synchrone est suffisant dans l'immense majorité des cas.

    -> généralement, la méthode pour l'écriture/lecture utilisée est la suivant:
    --> on envoie une trame (écriture)
    --> on lit la réponse dans une boucle avec un nombre d'essai déterminé pour éviter la boucle infinie.

    Cette méthode a l'avantage déviter d'utiliser un thread (comme toujours, si on peut faire simple, c'est mieux).

    -> pour l'utilisation des string, je ne vois pas de problème, au contraire. Au niveau le plus bas, tu es tout de même obligé de manipuler des tableaux de char, mais la classe string de la SL fourni tout ce qu'il faut pour passer de l'un à l'autre.

    -> ton design me semble bien à première vue. Il est cependant difficile d'en dire plus avec si peu de détails.

    Si ça peut aider, je te copie une classe que j'utilise souvent pour la couche basse (lecture/écriture sur le port série). Ne fonctionne que pour Windows:

    Code : 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
    // SerialPortManager.h
     
    #include <windows.h>
     
    class SerialPortManager
    {
    public:
    	SerialPortManager(){}
    	~SerialPortManager();
     
    	bool	OpenPort( int port );
    	void	FlushPort();
    	int	Read( unsigned char * buffer, int buffLen );
    	void	Write( const unsigned char * buffer, const int buffLen );
    	void	ClosePort();
     
    private:
    	HANDLE m_hCom;
    };
    Code : 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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    #include "SerialPortManager.h"
     
    #include <sstream>
     
    SerialPortManager::~SerialPortManager()
    {
        ClosePort();
    }
     
    bool SerialPortManager::OpenPort( int port )
    {	
    	std::stringstream device;
    	device << "COM";
    	device << port;
     
    	m_hCom = CreateFile ( device.str().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, 
    		OPEN_EXISTING, 0, NULL );
     
    	if ( m_hCom == INVALID_HANDLE_VALUE )
    	{
    		//TODO: gestion erreur
    		return false;
    	}
     
    	DCB				dcb;
    	ZeroMemory(&dcb, sizeof(DCB));
    	COMMTIMEOUTS	timeouts;
    	dcb.DCBlength	= sizeof(DCB);
    	dcb.ByteSize	= 8;
    	dcb.Parity		= NOPARITY;
    	dcb.StopBits	= ONESTOPBIT;
    	dcb.BaudRate	= CBR_38400;
    	dcb.fRtsControl = RTS_CONTROL_DISABLE;
    	dcb.fDtrControl = DTR_CONTROL_DISABLE;
     
    	if ( GetCommTimeouts( m_hCom, &timeouts ) == 0 )
    	{
    		//TODO: gestion erreur
    		return false;
    	}
     
    	timeouts.ReadIntervalTimeout = MAXDWORD;
    	if ( SetCommTimeouts( m_hCom, &timeouts) == 0 )
    	{
    		//TODO: gestion erreur
    		return false;
    	}
     
    	if ( SetCommState( m_hCom, &dcb) == 0 )
    	{
    		//TODO: gestion erreur
    		return false;
    	}
     
    	return true;
    }
     
    void SerialPortManager::FlushPort()
    {
    	DWORD	nChar	= 1;
    	BYTE	cInBuf [8];
    	while ( nChar >0 )
    		ReadFile( m_hCom, cInBuf, 1, &nChar, NULL);
    }
     
    int SerialPortManager::Read( unsigned char * buffer, int buffLen )
    {
    	int	nbRetry = 5;
    	int	nbCharRead = 0;
    	int	countFailed	= 0;
    	DWORD	nChar	= 0;
     
    	while ( countFailed < reintentos )
    	{
    		ReadFile( m_hCom, &buffer[nbCharLeido], 1, &nChar, NULL );
    		if ( nChar > 0 )
    		{
    			nbCharRead +=nChar;
    		}
    		else
    		{
    			countFailed++;
    			Sleep( 100 );
    		}
    	}
     
    	return nbCharRead;
    }
     
    void SerialPortManager::Write( const unsigned char * buffer, const int buffLen )
    {	
     
    	DWORD nChar = 0;
    	if ( WriteFile( m_hCom, buffer, buffLen, &nChar, NULL) == 0 )
    	{
    		// TODO: gestion erreur
    	}
    }
     
    void SerialPortManager::ClosePort()
    {
    	std::cout << "ClosePort" << std::endl;
    	CloseHandle( m_hCom );
    }
    Hope it helps.

  3. #3
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par r0d Voir le message
    Bonjour,

    quelques conseils en vrac:

    -> de façon générale, le mode asynchrone pour le port série est déconseillé car trop difficile à gérer et le mode synchrone est suffisant dans l'immense majorité des cas.

    le mode asynchrone est plustôt conseillé...
    Avec Qt ça se fait comme une lettre à la poste. Ça à surtout l'avantage de ne pas bloquer l'application lors de la lecture du port.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut
    Merci, pour ces precisions.

    J'ai regarde ta classe et elle est similaire a celle que je viens tout juste de terminer. Il y a quand meme deux differences que je ne comprends pas :

    Quelle est l'utilitee du ZeroMemory dans le renseignement de la strucutre DCB ?

    Quelle est l'utilite de la fonction FlushPort() ? Elle semble lire des octets tant qu'elle en recoit.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut
    Citation Envoyé par Mongaulois Voir le message

    le mode asynchrone est plustôt conseillé...
    Avec Qt ça se fait comme une lettre à la poste. Ça à surtout l'avantage de ne pas bloquer l'application lors de la lecture du port.
    Pourquoi, le mode asynchrone serait plus indique ? Si je suis les conseils de r0d en faisant n essais de lecture le port se liberera forcement.

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Tymk Voir le message
    Pourquoi, le mode asynchrone serait plus indique ? Si je suis les conseils de r0d en faisant n essais de lecture le port se liberera forcement.
    la lecture sur le port est bloquante, c'est à dire que si il n'y as rien à lire, la lecture va bloquer l'exécution. Donc si tu utilise une thread, tous ton programme est bloqué. Utiliser un thread qui fera la lecture permet de ne pas bloquer le reste. Que la thread se bloque, c'est pas grave puis qu'elle sert à ca.
    Si tu as une IHM, c'est pas terrible d'avoir l'ihm qui ne repond plus.

    De la même manière, si tu lit beaucoup de donnée, ton application ne fera que ça et va laisser peu de ressource pour le reste=> même problème.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut
    Ok, mais je suis plutot de l'avis de r0d : rester simple si possible.

    Je pense que je peux m'en sortir de la sorte :

    Je sais exactement ce que je dois obtenir en lecture car c'est le PC qui interroge l'interface. L'interface ne fait que repondre. Donc, j'envoie mon message et je passe en lecture sur le peripherique pour recuperer la reponse.

    Si l'interface repond plus vite que le temps necessaire au programme passe de l'ecriture en lecture (ce dont je doute), le driver bufferise les octets.

    Ensuite, je lis les octets correspondant a l'en-tete de mon paquet. Je connais maintenant la taille exacte du paquet. Je recupere donc le nombre d'octets restants.

    Pendant ce temps, le programme ne peut rien faire d'autre sans la reponse de l'interface. D'ou l'inutilite du threading.

    Fonctionnement non-nominal :

    Si le programme attend des octets que l'interface n'envoie pas, un timeout sort de la lecture et la requete est renvoyee.

    Si le programme recupere moins d'octets que ce qu'a envoyee l'interface, le crc permet de detecter l'erreur.

    [edit] Mon application n'interagit pas avec un utilisateur [/edit]

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par Tymk Voir le message
    Je sais exactement ce que je dois obtenir en lecture car c'est le PC qui interroge l'interface. L'interface ne fait que repondre. Donc, j'envoie mon message et je passe en lecture sur le peripherique pour recuperer la reponse.

    Pendant ce temps, le programme ne peut rien faire d'autre sans la reponse de l'interface.

    Si le programme attend des octets que l'interface n'envoie pas, un timeout sort de la lecture et la requete est renvoyee.
    Et que pense tu qui va se passé à ton interface pendant c'est periode(en gras)???
    =>interface bloqué, non répondante, qui deviens blanc ou autre jusqu'a la recuperation des ressources
    Bien sur que tu peut te passé d'une thread pour faire simple. Mais simple ne correspond pas toujours à performant et ce qu'il faut faire...
    Aprés ce n'est que mon avis
    a toi de voire

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut
    Pardon, je me suis mal exprime.

    Je parlais d'interface pour signifier "validateur d'acces". C'est une interface electronique qui se situe a l'autre bout du cable et a laquelle je ne touche pas. Il ne s'agit pas d'interface graphique. Mon application est autonome.

  10. #10
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Ooops oui pardon, je voulais dire l'inverse

    de façon générale, le mode synchrone pour le port série est déconseillé car trop difficile à gérer et le mode asynchrone est suffisant dans l'immense majorité des cas.

    pardon

    Au sujet d'un thread ou non, effectivement tout dépend de savoir si le "blocage" de ton appli est un problème ou non. Dans certains cas, il peut même être souhaitable.

    Citation Envoyé par Tymk
    Quelle est l'utilitee du ZeroMemory dans le renseignement de la strucutre DCB ?
    Dans certains cas (en fait je crois presque tout le temps), ça ne fonctionnera tout simplement pas si tu ne le fais pas. Le standard c++ ne précise pas comment doit être initialisée une structure. Ce que je veux dire, c'est que lorsque déclar une structure (lorsque tu en créé uns instance donc), les compilateurs la remplissent n'importe comment. Le ZeroMemory la rempli de 0 (zéro).

    Citation Envoyé par Tymk
    Quelle est l'utilite de la fonction FlushPort() ? Elle semble lire des octets tant qu'elle en recoit.
    C'est exactement ça. Cette fonction sert à vider le buffer d'entrée du port serie. Elle est indispensable dans certains cas, mais pas toujours. Par exemple, en ce moment je travail sur une machine qui m'envoie une "preuve de vie": toute les 10 secondes, elle m'envoie un octet (0x00 dans mon cas précis). Je suis donc obligé de vider le buffer (flush) avant chaque envoi/réception de trame. Il y a aussi des machines qui envoie des parasytes, c'est à dire qu'ils envoient de temps en temps des octets "poubelle" sur le port. J'en avais rencontré lorsque je bossait dans la RFID.

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut
    Ok

    Pour le mode asynchrone, il suffit de renseigner le flag ldOverlap ou il y a d'autres modifications a faire dans le code ?

    Au passage, r0d, ta classe ouvre un port en mode synchrone, il me semble.

  12. #12
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 288
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Tymk Voir le message
    Pour le mode asynchrone, il suffit de renseigner le flag ldOverlap ou il y a d'autres modifications a faire dans le code ?
    Je ne sais pas.

    Citation Envoyé par Tymk Voir le message
    Au passage, r0d, ta classe ouvre un port en mode synchrone, il me semble.
    Mhh, je ne sais plus. Il me semble effectivement qu'il y a deux façon d'utiliser le mot synchrone/asynchrone quand on parle du port serie. Mais je ne sais plus là, vous m'avez perdu

  13. #13
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035

  14. #14
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 688
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 688
    Par défaut protocol -> stream -> RS232
    J'aime bien un découpage en 3 couches:
    application (7) -> session (4) -> liaison de données (2)

    Lorsqu'on va passer de RS232 à Ethernet, ce sera pour supporter plusieurs connexions.
    1. Que peut-on faire côté "design" pour limiter les changements à la couche "liaison de données"?
    2. Et autoriser la gestion de plusieurs sessions à la fois?


    Le fantôme threads ou pas traine toujours dans le décors ;-(
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  15. #15
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Citation Envoyé par Tymk
    La manipulation des paquets via basic_string<unsigned char> est-elle viable ?
    Attention à être bien sûr que les données qui transitent sur ta liaison RS232 sont sous forme ASCII et non binaire. En effet, en ASCII le '\0' = NULL = 0 terminera la chaîne et ira très bien avec ce container. Mais en binaire, ta trame pourra très bien contenir un 0 qui fera tomber le reste de ta trame aux oubliettes.
    Attention également aux trames UNICODE, car chaque caractère ASCII imprimable chez nous sera précédé d'un 0 et n'ira donc pas avec ton container.

    Sinon, j'ai appris par expérience que l'utilisation d'un nom de flux de type "COMX" pour le CreateFile d'une liaison série est limitée jusqu'au COM9. Si tu veux utiliser un port COM supérieur (possible jusqu'à 255 il me semble), il faut utiliser la notation complète du périphérique série:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    wsprintf( sz, "\\\\.\\COM%d", portnumber);   
    m_hCom = CreateFile( sz,
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED,
            NULL );
    Mais soyons honnêtes, tout le monde n'a pas 36 ports COM

    Enfin, pour ce qui est du thread ou non, tu connais déjà mon avis...

  16. #16
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Quelques conseils a adapté ensuite selon tes envies et besoins:
    -> Si ton système est asymétrique (un émetteur et un récepteur), je spécialiserais les classes RS323 et PROTOCOL en deux: une pour l'émission et une pour la réception,
    -> Si tu penses ensuite aller sur du IP, tes sockets pourront se situer à ce niveau (PROTOCOL pour TCP, RS232 pour UDP),
    -> Personnellement, je préfère le mode asynchrone. Cela permet de garder une certaine dynamique à ton programme: ton système peut encore réagir à l'environnement (IHM, signaux, etc...),
    -> Je préfère découper les systèmes avec des flux réseaux en plusieurs thread: un pour la communication, un pour le traitement principal et en poussant le vice, un spécifiquement à l'IHM. Ca semble plus compliqué mais au final c'est plus souple, notamment pour la gestion des erreurs.
    Tout ceci est ensuite à adapter aux spécificités de ton système et au temps dont tu disposes pour le développer.
    Cordialement.

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut
    Citation Envoyé par spoutspout Voir le message
    Attention à être bien sûr que les données qui transitent sur ta liaison RS232 sont sous forme ASCII et non binaire. En effet, en ASCII le '\0' = NULL = 0 terminera la chaîne et ira très bien avec ce container. Mais en binaire, ta trame pourra très bien contenir un 0 qui fera tomber le reste de ta trame aux oubliettes.
    Il me semblait que la classe string ne contenait pas de caractere de fin de chaine. En tout cas, j'arrive a envoyer/recevoir des tames en affectant a certains unsigned char la valeur 0x00.

    Citation Envoyé par spoutspout Voir le message
    Enfin, pour ce qui est du thread ou non, tu connais déjà mon avis...
    Oui, je sais que ce sujet a deja ete discute. Je me suis permis de reposer la question pour collecter plus d'avis.

  18. #18
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Citation Envoyé par Tymk Voir le message
    Il me semblait que la classe string ne contenait pas de caractere de fin de chaine.
    Si l'on parle bien de la classe string de la STL, un 0 est placé à la fin de la chaîne du buffer interne. Tu peux le vérifier avec le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    std::string sEssai;
    sEssai.push_back('a');
    sEssai.push_back('b');
    sEssai.push_back(0);
    sEssai.push_back('c');
    sEssai.push_back('d');
    sEssai.push_back('e');
    En debug, si tu regardes le buffer du string sEssai, tu verras qu'il y a un 0 à la fin des caractères de la chaîne.
    Citation Envoyé par Tymk Voir le message
    En tout cas, j'arrive a envoyer/recevoir des tames en affectant a certains unsigned char la valeur 0x00.
    OK je me suis mal exprimé. Avec l'exemple que je t'ai donné, tu verras qu'effectivement le buffer continue de se remplir après l'ajout du 0. Mais si tu utilises par exemple le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char sBuffer[10];
    sprintf(sBuffer, sEssai.c_str());
    tu verras que le .c_str() renvoie une chaîne de caractère qui s'arrête au 0, donc "ab".
    L'important es d'être conscient de cette subtilité

  19. #19
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Par défaut
    Le point que tu souleves est tres important puisque les fonctions WriteFile et ReadFile demande des pointeurs sur des types constants. (Donc, necessite la conversion vers des chaines C).

    Mais, j'ai contourne le probleme en parcourant mon basic_string<unsigned char> et en envoyant/recevant les octets un par un.

  20. #20
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 688
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 688
    Par défaut
    Citation Envoyé par Tymk Voir le message
    Le point que tu souleves est tres important puisque les fonctions WriteFile et ReadFile demande des pointeurs sur des types constants. (Donc, necessite la conversion vers des chaines C).

    Mais, j'ai contourne le probleme en parcourant mon basic_string<unsigned char> et en envoyant/recevant les octets un par un.
    ne serait-il pas plus sage de définir une "trame" comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    unsigned char length; // la longueur
    unsigned char data[MAX_TRAME]; // le contenu.
    plutôt que de canibaliser un type qui n'est qu'un tableau de caractère dans lequel 0 à un sens assez particulier?
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. structure conseillée pour un site ?
    Par jarailet dans le forum Débuter
    Réponses: 1
    Dernier message: 15/07/2009, 15h23
  2. [Conception] Besoin d'un conseil pour structurer ma base
    Par pierrot10 dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 15/01/2008, 14h02
  3. Conseil pour implementation d'un graphe
    Par lusiole dans le forum C
    Réponses: 6
    Dernier message: 08/08/2007, 19h35
  4. [Forum] Conseil pour trouver un forum java à mettre sur un portail
    Par tinico dans le forum Développement Web en Java
    Réponses: 1
    Dernier message: 02/05/2007, 10h59
  5. conseil pour structurer un xml
    Par jbat dans le forum Delphi
    Réponses: 2
    Dernier message: 14/07/2006, 07h49

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