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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  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
    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.

  5. #5
    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.

  6. #6
    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]

  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
    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.

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