Probleme de programmation ss mandrake en c

Forum d'assistance et d'échange sur l'installation, la configuration, et l'utilisation des système Linux et BSD. Vous pouvez y poster vos questions concernant ces systèmes d'exploitation en faisant l'effort préalable de rechercher dans le forum, dans les manuels et les documentations que la réponse n'y figure pas.

Modérateur: modos Ixus

Probleme de programmation ss mandrake en c

Messagepar FireJocker » 20 Sep 2004 08:13

Bonjour, a l'ecole on devais ecrire un petit protocole reseau,
la prof nous a file un code qui permet d'avoir le clavier non blocant,
et qui rentre dans le code lorsque l'on recoit des données sur le port serie, le clavier ou lors du TimeOut.

le probleme est que le code que nous utilisons doit marchait lorsque l'on simule le oport serie
avec 3 appli en parallele, apparemment, le SELECT considere que l'on recoit des datas
lorsque le fichier est ouvert,
comment y remedier selon vous, merci.

ci-apres le code complet de mon projet


Code: Tout sélectionner

//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

#include <unistd.h>
#include <errno.h>
#include <termios.h>

#include <stdlib.h>

#define max(a,b) (a>b ? a : b)

struct termios KbdTermiosNew={0};
struct termios KbdTermiosOld={0};
struct termios ComTermiosNew={0};
struct termios ComTermiosOld={0};

fd_set Readfds={0};
fd_set ReadfdsInstantane={0};
int hPortMax=0;

int NoDescripteurLiaisonSerie;
int NoDescripteurLiaisonEmission ;
int NoDescripteurLiaisonReception;

unsigned char TJeton[]={0xE0,0x00, 0xE0, 0x70};

int NumMach; // Numero de la machine

// A utiliser pour simuler les ports COM par des fichiers
int TacInitLiaison(int NumMachine, int Prec, int Suiv)
{

int Erreur=0;
char Nom1[] = "ttyS0_0",
Nom2[] = "ttyS0_0",
Tempo[3];


// format du fichier : 'ttyS' + Poste qui ecrit + '_' + Poste qui lit
// ex : ttyS1_2   : fichier ecrit par la machine 1 et lue par la 2

// Entier -> Caractere pour faire le nom du fichier
sprintf(Tempo,"%d",Prec);
Nom1[4] = Tempo[0];


sprintf(Tempo,"%d",Suiv);
Nom2[6] = Tempo[0];

sprintf(Tempo,"%d",NumMachine);
Nom1[6] = Tempo[0];
Nom2[4] = Tempo[0];



printf("\n%s\n%s\n",Nom1,Nom2);

// COM2
NoDescripteurLiaisonReception = open(Nom1, O_NOCTTY | O_NONBLOCK | O_RDONLY | O_CREAT|O_TRUNC,S_IRWXU);

printf("NoDescripteurLiaisonReception=%d\n",NoDescripteurLiaisonReception);

// SI l'ouverture s'est mal passee
if (NoDescripteurLiaisonReception==-1) {


// Afficher le message UNIX correspondant au errno
perror("Ouverture liaison serie");
Erreur = 1;

}
// COM1
NoDescripteurLiaisonEmission = open(Nom2, O_NOCTTY | O_NONBLOCK | O_WRONLY | O_CREAT | O_TRUNC| O_APPEND,S_IRWXU);

printf("NoDescripteurLiaisonEmission=%d\n",NoDescripteurLiaisonEmission);

// SI l'ouverture s'est mal passee
if (NoDescripteurLiaisonEmission==-1) {


// Afficher le message UNIX correspondant au errno
perror("Ouverture liaison serie");
Erreur = 1;

}


return Erreur;

}



int TacNettoyage(void)
{

// Remettre les vieux attributs de l'entree standard
tcsetattr(0,TCSANOW,&KbdTermiosOld);


//  close ttty

if (close (NoDescripteurLiaisonEmission)) {


// Afficher le message UNIX correspondant au errno
perror("Fermeture  liaison serie");
}
if (close (NoDescripteurLiaisonReception)) {


// Afficher le message UNIX correspondant au errno
perror("Fermeture  liaison serie");
}

}


//**********************************************************************************//
// Cette procedure extrait l'adresse dest (1) ou src (2) codé sur 3 bits de la trame//
//**********************************************************************************//
int ExtraireAdresse(char Tab[35], int Addr)
{
   char Cadr = Tab[0];
   int Ret=0;

   if (Addr == 1)
      Ret = (int) Cadr>>5;      // Adresse destinataire
   else
      Ret = (int) (Cadr<<3)>>2; // Adresse source
      
   return(Ret);
}

//**********************************************************************************//
// Cette fonction extrait le CRC de la trame                                        //
//**********************************************************************************//
int ExtraireCRC(unsigned char trame[35])
{
   unsigned char Tempo;
   int iCRC, // Index du CRC dans la trame
   Ret;

// recuperation du nombre d'octet du message
   Tempo = trame[1]<<3;
   Tempo = Tempo>>3;

   iCRC = 2 + (int)Tempo;

// creation d'un entier à partir des 2 octets de CRC
   Ret = (int)trame[iCRC];
   Ret = (Ret << 8) + (int)trame[iCRC+1];
   
   return(Ret);

}

//**********************************************************************************//
// Cette fonction calcul un CRC sur la trame                                        //
//**********************************************************************************//
int CRC(unsigned char trame[35], int lgT)
{
   int i,Ret = 0;
   unsigned char parite1=0, parite2=0, temp, c;

   for(i=0;i<lgT;i++)
   {
      c = parite1 ^ trame[i]; // parite bit à bit

      temp = (parite2 & 0x01)<<7; // recup du LSB et repositionnement en MSB
      parite2 = parite2 >> 1;  // decalage a droite de 1 bit
      parite2 = parite2 + temp;// reinjection du premier bit

      parite2 = parite2 ^ trame[i]; // parite bit à bit
   }
   
   // creation d'un entier à partir des 2 octets de CRC
   Ret = (int)parite1;
   Ret = (Ret << 8) + (int)parite2;

   return(Ret);
}

//**********************************************************************************//
// Cette fonction verifie la trame par rapport à son CRC                            //
//**********************************************************************************//
int CRC_OK(unsigned char trame[35], int lgT)
{
return (ExtraireCRC(trame) == CRC(trame,lgT-2));
}

//**********************************************************************************//
// Cette fonction retourne 1 si l'appli est maitre et 0 dans le cas contraire
//**********************************************************************************//
int AppliMaitre()
{
return(NumMach == 1);
}

//**********************************************************************************//
// Cette fonction retourne 1 si l'appli est la source du message et 0 dans le cas contraire
//**********************************************************************************//
int SourceMoi(unsigned char trame[35])
{
return(ExtraireAdresse(trame,2) == NumMach);
}



//**********************************************************************************//
// Cette fonction retourne 1 s'il s'agit d'un message de broadcast et 0 dans le cas contraire
//**********************************************************************************//
int DestinataireMoi(unsigned char trame[35])
{
return(ExtraireAdresse(trame,1) == NumMach);
}

//**********************************************************************************//
// Cette fonction retourne 1 s'il s'agit d'un message de broadcast et 0 dans le cas contraire
//**********************************************************************************//
int DestinataireTous(unsigned char trame[35])
{
return(ExtraireAdresse(trame,1) == 0);
}

//**********************************************************************************//
// Cette fonction envoie le jeton
//**********************************************************************************//

void EnvoyerJeton(void)
{
write(NoDescripteurLiaisonEmission,TJeton,4);
}


//**********************************************************************************//
// Cette fonction renvoir 1 si la trame est une trame de confirmation et 0 dans le cas contraire
//**********************************************************************************//

int TrameDeConfirmation(unsigned char trame[35], int LgT)
{
return(((trame[0] & 0x03)==0) && (LgT == 3));
}

//**********************************************************************************//
/*  Cette fonction permet de traiter une trame

Retour de la fonction :
-----------------------

-1  : Erreur CRC
0   : Message recu et valide
1   : Message a retransferrer, le destinataire est un autre   

*/
//**********************************************************************************//

int TraiterTrame(unsigned char TRAME[35],int Lg)
{
int i, Ret=1;

if ( (ExtraireAdresse(TRAME,1)) == NumMach )
   {
         // la trame est pour ce poste : l'afficher si le crc est bon
         if (ExtraireCRC(TRAME) == CRC(TRAME,Lg-2))
         Ret = 0; // CRC OK
else
   Ret = -1; // Erreur CRC
}
else
{
         // la trame n'est pas pour ce poste, la rexpedier
         write(NoDescripteurLiaisonEmission,TRAME,Lg);   
}

}

//**********************************************************************************//
// Cette fonction permet d'afficher le message d'une trame
//**********************************************************************************//

void AfficherMessage(unsigned char TRAME[35],int Lg)
{
int i;
for (i=2;i<Lg-4;i++) printf("%c",TRAME[i]);
}




//**********************************************************************************//
// Cette fonction permet d'envoyer un message de 31 caracteres max, elle
// retourne le nombre de caractere restant a afficher
//**********************************************************************************//

int EnvoyerMessage(char Message[255], int LgMsg, char CNumMachine)
{
   char CTempAtoi[2] = "0",
   carac,
   TRAME[35];
   
   int LgTransmit,
   i,
   iCRC1,
   iCRC2;
   
   // Codage de l'adresse d'expedition : 3 bits de poids fort
   CTempAtoi[0] = Message[0];
   carac = (char) atoi(CTempAtoi);
   
   // verification que la machine cible est autre que l'expediteur
   if (carac != CNumMachine)
   {
      carac = carac<<5;
      
      // On rajoute les 3 bits de sources pas une operation logique OU
      TRAME[0] = carac | CNumMachine;
   
      // le decalage de 2 vient du formatage du message :    1:Message !      
      if (LgMsg>31+2) // trame trop longue
      {
         LgMsg -= 31;
         LgTransmit = 31;
      }
      else
      {
         LgTransmit = LgMsg-2;
         LgMsg = 0;
      }

      TRAME[1] = (char)LgTransmit;

      // recopie du bout de message a transmettre
      for (i=0;i<LgTransmit;i++) TRAME[i+2] = Message[i];


      // Calcul et insertion du CRC dans les 2 derniers octets
      iCRC1 = CRC(TRAME,LgTransmit+2);
      iCRC2 = iCRC1-((iCRC1>>8)<<8);
      iCRC1 -= iCRC2;
   
      TRAME[LgTransmit] = (char)iCRC1;
      TRAME[LgTransmit+1] = (char)iCRC2;
   
   
      // Envoi de la trame
      write(NoDescripteurLiaisonEmission,TRAME,LgTransmit);
      
      
      // Decalage des datas qui reste a envoyer
      for(i=LgTransmit; i<LgTransmit+LgMsg;i++) Message[i-LgTransmit+2] = Message[i+2];
      
   }
   else
      LgMsg = 0; // destinataire = source > annulation !
   
   return(LgMsg);

}


//**********************************************************************************//
// Cette fonction renvoie une trame
//**********************************************************************************//

void RenvoyerTrame(char Message[255], int LgMsg)
{
write(NoDescripteurLiaisonEmission,Message,LgMsg);
}


//**********************************************************************************//
// Cette fonction retourne une trame de confirmation
//**********************************************************************************//

void EnvoyerConfirmation(char Message[255])
{
char TRAME[3];

int iCRC1,
iCRC2;

// L'adresse de source devient celle de destination
TRAME[0] = Message[0] << 3;

// Codage de l'adresse de source
TRAME[0] = TRAME[0] | NumMach;   

// Calcul et insertion du CRC dans les 2 derniers octets
iCRC1 = CRC(TRAME,1);
iCRC2 = iCRC1-((iCRC1>>8)<<8);
iCRC1 -= iCRC2;

TRAME[1] = (char)iCRC1;
TRAME[2] = (char)iCRC2;
   
   
// Envoi de la trame
write(NoDescripteurLiaisonEmission,TRAME,3);
}




//**********************************************************************************//
// Cette fonction retourne 1 si la trame est un jeton et 0 dans le cas contraire
//**********************************************************************************//

int IsJeton(unsigned char TRAME[35],int Lg)
{
int Ret = 1, i;

if (Lg == 4)
{
for (i=0; i<4; i++)
{
if (TRAME[i] != TJeton[i]) Ret = 0;
}
}
else
Ret = 0;

return(Ret);
}


//**********************************************************************************//
// Cette fonction retourne 1 si la trame est une trame d'erreur
//**********************************************************************************//
int IsTrameErreur(unsigned char TRAME[35],int Lg)
{
int Ret = 1, i;

if ( (Lg != 4) || ((TRAME[i] & 0x02) == 0 ) )
{
   Ret = 0;
}

return(Ret);
}







//**********************************************************************************//
//                             Programme principal
//**********************************************************************************//
main(int argc, char * argv[])
{

   int Arret=0;
   int ValMiniMs = 2000;
   struct timeval Timeout;
   
   int NMach, Prec, Suiv;
   
   int Lg,
   LgC = 0, // longueur du message a envoyer
   i, j = 0,
   iCRC1,
   iCRC2,
   EnCoursTransmission = 0;
   
   char CLAVIER[255], CNumMach;
   
   int Data_E = 0, // data enable : donnee a envoyer
   AttenteReponse = 0, // en attente de reponse
   TrameDejaReemise = 0;
   
   unsigned char TRAME[35];
   
   
   
   printf("Simulation Reseau Serie\n");
   
   
   
   //  ************    Demande de la config de l'appli   **********************************
   
   printf("\nIdentification du poste\n----------------------\n\n\tNumero de la machine : ");
   fflush(stdin);
   scanf("%d",&NumMach);
   
   fflush(stdin);
   
   printf("\n\tNombre de machine totale : ");
   scanf("%d",&NMach);
   
   fflush(stdin);
   
   // recherche du poste suivant sur le reseau
   if (NumMach == NMach) Suiv = 1; else Suiv = NumMach + 1;
   
   // Recherche du poste precedent sur le reseau
   if (NumMach == 1) Prec = NMach; else Prec = NumMach - 1;
   
   // codage de l'adresse de la machine sur les 3 bits suivants :    ...XXX..
   CNumMach = (char) NumMach;
   CNumMach = CNumMach<<5; // decalage de 5 bits vers la gauche pour supprimer les 5 bits de debut
   CNumMach = CNumMach>>3; // decalage de 3 bits vers la droite pour respecter le format
   
   //************************************************************************************
   
   
   /*  L'entree standard est 0 (stdin) */
   /* Passer l'entree standard en mode non bloquant */
   fcntl(0,F_SETFL,fcntl(0,F_GETFL) | O_NONBLOCK);
   
   /* Sauvegarder les vieux attributs de l'entree standard */
   tcgetattr(0,&KbdTermiosOld);
   KbdTermiosNew=KbdTermiosOld;
   
   /* Passer l'entree standard en mode canonique */
   KbdTermiosNew.c_lflag |= ICANON;
   
   // Appliquer maitenenant nos attributs
   tcsetattr(0,TCSANOW,&KbdTermiosNew);
   
   
   
   if (TacInitLiaison(NumMach,Prec,Suiv))
   {
   printf("Erreur initialisation\n");
   exit (1);
   }
   
   // Positionner le bit correspondant au descripteur de la liaison serie
   // dans la table bit du select
   FD_SET(NoDescripteurLiaisonReception,&Readfds);
   
   // L'entree standard est 0 (stdin)
   // Positionner le bit correspondant au descripteur de la l'entree standard
   // dans la table bit du select
   FD_SET(0,&Readfds);
   
   hPortMax = max(hPortMax,NoDescripteurLiaisonReception)+1;
   printf("hPortMax=%d\n",hPortMax);
   

   
   while (!Arret)
   {
      // Reinitialiser la table du select
      memcpy(&ReadfdsInstantane,&Readfds,sizeof(ReadfdsInstantane));
      Timeout.tv_sec = (ValMiniMs / 1000);
      Timeout.tv_usec= (ValMiniMs % 1000) * 1000;
   
      // SI au moins un descripteur parle
      if (select(hPortMax,&ReadfdsInstantane,0,0,&Timeout) > 0)
      {
         printf("%d\n",j);
         j = (j++)%100;
                  
         
         // SI data clavier
         if (FD_ISSET(0,&ReadfdsInstantane))
         {
            
         
      // !!  ** changer le systeme de saisie du clavier pour ne pas perdre de data ** !! //
         
            // faire un systeme pour rajouter le new buffer a un ancien non envoyé
            LgC=read(0,CLAVIER,sizeof(CLAVIER)-2);
            Data_E = (LgC > 0);// and (NumMach != atoi(CLAVIER[0]);               
         }
         
         Lg = 0;
         
         // SI data serie
         if (FD_ISSET(NoDescripteurLiaisonReception,&ReadfdsInstantane))
         {            
            // Lire la liaison serie
            Lg=read(NoDescripteurLiaisonReception,TRAME,sizeof(TRAME));
            if (Lg>0)
            {
            
               if (AppliMaitre())
               {
               // reinitialisation du timeout principal
               }
               
               if (CRC_OK(TRAME, Lg))
               {
               
                  if (AttenteReponse)
                  {
                     // source = moi
                     if (SourceMoi(TRAME))
                     {
                     
                     // destinataire different de tous
                     if (!DestinataireTous(TRAME))
                     {
                        Data_E = 0;
                        EnvoyerJeton();
                     }
                     AttenteReponse = 0;
                     }
                     else
                     {
                     // source = pas moi
                     
                        if (TrameDeConfirmation(TRAME, Lg))
                        {
                           // data_e = 0
                           if (!Data_E)
                           {
                              EnvoyerJeton();
                              AttenteReponse = 0;
                           }
                        }
                        else
                        {
                           if (!TrameDejaReemise)
                           {
                              EnvoyerJeton();
                              AttenteReponse = 0;
                           }
                        }
                     }
                  }
                  else
                  { // pas en attente d'une reponse
               
                     if (IsJeton(TRAME,Lg))
                     {// la trame est le jeton
                        if (Data_E)
                        {// il y a des donnée à emettre
                        
                           // envoi de 31 caracteres max
                           LgC = EnvoyerMessage(CLAVIER, LgC, CNumMach);
                           
                           // positionemment de l'appli en mode attente de reponse
                           AttenteReponse = 1;
                           
                           // reste il des datas à emettre
                           if ( LgC == 0 ) Data_E = 0;
                           
                           // reinitialisation du timeout ici
                        }
                        else
                        {// il n'y a pas de donnée à emettre
                           EnvoyerJeton();
                        }
                     
                     }
                     else
                     {// la trame n'est pas le jeton
                        if (IsTrameErreur(TRAME, Lg))
                        {
                           // il s'agit d'une trame d'erreur
                           if (SourceMoi(TRAME))
                           {   
                              EnvoyerJeton();
                           }
                           else
                           {
                              RenvoyerTrame(TRAME, Lg);
                           }
                        }
                        else
                        {
                           // il ne s'agit pas d'une trame d'erreur
                           if (DestinataireMoi(TRAME))
                           {
                              AfficherMessage(TRAME, Lg);
                              EnvoyerConfirmation(TRAME);
                           }
                           else
                           {
                              if (DestinataireTous(TRAME))
                              {
                                 AfficherMessage(TRAME, Lg);
                                 RenvoyerTrame(TRAME, Lg);
                              }
                              
                           }
                           
                        }
               
                     }
                  }
               }
            }
            
         }
         
         
         if (Lg == 0)
         {// Il n'y a pas eu de données sur le port série
            if (AttenteReponse)
            {
               // Appli dans l'attente d'une reponse
            }
            else
            {   // Appli dans l'attente d'aucune reponse
            }            
         }
      }
   }
   TacNettoyage();
}
Avatar de l’utilisateur
FireJocker
Matelot
Matelot
 
Messages: 10
Inscrit le: 30 Déc 2003 01:00

Retour vers Linux et BSD (forum généraliste)

Qui est en ligne ?

Utilisateur(s) parcourant actuellement ce forum : Aucun utilisateur inscrit et 1 invité

cron