Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 26/06/2008, à 20:19

Bzh

[PROG C] Variables globales et threads

Bonjour,

J'ai un programme qui utilise des threads "fils" et qui a une variable globale.

Or, si, dans un threads, j'incrémente la variable globale ( int ), sa valeur aura bien pris une unité de plus, mais lors de la fin du thread, cette variable revient à zéro !

Je suis perdu...

Pas simple du tout le C.

Quelqu'un pourrait-il m'expliquer rapidement le pourquoi du comment ?

Merci beaucoup

Hors ligne

#2 Le 26/06/2008, à 20:31

Dark-Sham

Re : [PROG C] Variables globales et threads

Fais voir le code ?


Script de sauvegarde/restauration APT

Ubuntu 8.04 "Hardy Heron"
CPU : AMD Athlon XP 2800+ ; GPU : ATI Radeon 9250/9200 Series ; RAM : 2 Gigots + 512 Mégots ; Carte mère : Asus A7N8X-E Deluxe

Hors ligne

#3 Le 26/06/2008, à 21:06

nicolas.sitbon

Re : [PROG C] Variables globales et threads

Bzh a écrit :

J'ai un programme qui utilise des threads "fils" et qui a une variable globale.

ça commence mal, il n'y a pas de notion affiliation pour les threads, on ne parle pas de thread père ou fils; à la rigueur, on peut parler de thread primaire en désignant le premier thread d'un processus mais pas plus.

Bzh a écrit :

Or, si, dans un threads, j'incrémente la variable globale ( int ), sa valeur aura bien pris une unité de plus, mais lors de la fin du thread, cette variable revient à zéro !

ton code est buggé. Montre ton code!

Bzh a écrit :

Pas simple du tout le C.

Le C n'a aucune notion de thread ni même de processus, quel est ton système? ta bibliothèque de thread?

Bzh a écrit :

Quelqu'un pourrait-il m'expliquer rapidement le pourquoi du comment ?

Montre ton code!

Hors ligne

#4 Le 26/06/2008, à 21:20

Bzh

Re : [PROG C] Variables globales et threads

Tout d'abord merci beaucoup pour vos réactions.

Le soucis de mon code est sa taille. Je vous montre tout le code et s'il est trop long je ré-éditerais mon message.

#include <sys/types.h>                            /* Types prédéfinis "c" */
#include <sys/socket.h>                           /* Généralités sockets */
#include <sys/param.h>                            /* Paramètres et limites système */
#include <netinet/in.h>                           /* Spécifications socket internet */
#include <arpa/inet.h>                            /* Adresses format "arpanet" */
#include <signal.h>                               /* Signaux de communication */
#include <string.h>                               /* Gestion des chaines de caratères */
#include <stdio.h>                                /* I/O fichiers classiques */
#include <stdlib.h>                               /* Gestion de EXIT */
#include <netdb.h>                                /* Gestion network database */
#include <errno.h>                                /* Erreurs système */
#include <time.h>
#include "md5.c"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Gestion des constantes
extern const char* const sys_errlist[];           /* Liste messages erreurs */
#define SERVICE_LABEL            ("st*****at") /* Nom service requis */
#define SERVICE_PROTOCOL                ("tcp")   /* Protocole service requis */
#define SZ_BUF                          (256000)     /* Taille buffer */
//Gestion des variables globales
int sk_creat;                              /* Socket de création */
int sk_dialog;                             /* Socket de dialogue */
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Déclaration de nos structures
struct parametresAuteur {
	char *auteur;
	char *md5;
	char *destinataire;
	char *message;
};
//Structure d'un message
struct structureMessage {
	char auteur[256];
	char destinataire[256];
	char message[256];
	int  heure;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//On déclare nos variables globales
char ENTETES_HTTP[]="HTTP/1.1 200 OK\nDate: Wed, 25 Jun 2008 13:32:29 GMT\nServer: ****** V1.0 by ******\nExpires: Thu, 19 Nov 1981 08:52:00 GMT\nCache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\nPragma: no-cache\nContent-Type: text/html; charset=iso-8859-15";
char ENTETE_MD5[]  ="875"; //Pour Manu => fec83147f8c18d1dcb4a2c4418455a84
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Déclaration de la structure gérant la liste de nos messages
struct structureMessage *listesMessages;
int nbMessages;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Fonction qui envoie le résultat au navigateur
void envoyerReponse( char *buffer ){
	//On construit notre réponse
	char *s = malloc ( sizeof (*s) * SZ_BUF);
	s = strcpy( s, ENTETES_HTTP );
	s = strcat( s, "\n\n" );
	s = strcat( s, buffer );
	//On envoie notre réponse
	write( sk_dialog, s, strlen( s ) );
	//On libère la mémoire utilisé
	free( s );
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Fonction enregistrant un nouveau message a distribuer
void enregistrerMessage( struct  parametresAuteur client ){
	//Si le message est vide ou egal à NULL, on quitte
	if( strcmp( client.message, "NULL" ) == 0 || strcmp( client.message, "" )  == 0  ){ return; }
	//On incrémente le compteur
	nbMessages++;
	//On créé notre nouveau message
	struct structureMessage messageTmp;
	//On enregistre les infos du message
	strcpy( messageTmp.auteur, client.auteur );			//On copie les pseudo de l'auteur
	strcpy( messageTmp.destinataire, client.destinataire );		//On copie les pseudo du destinataire
	strcpy( messageTmp.message, client.message );			//On copie le message
	messageTmp.heure = ( int ) time( NULL );
	//On augmente la taille de la liste des messages
	listesMessages = realloc ( listesMessages, sizeof( messageTmp ) * nbMessages );
	//On ajoute notre nouveau message dans la liste
	listesMessages = memmove( listesMessages + ( sizeof( messageTmp ) * ( nbMessages - 1 ) ), &messageTmp , (int) sizeof( messageTmp ) );
	
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Vérification de l'identité du client
int verficationIdentite( struct  parametresAuteur client ){
	//Allocation en mémoire
	char *s = malloc ( sizeof (*s) * SZ_BUF);
	char *t = malloc ( sizeof (*s) * SZ_BUF);
	int statut = 0;
	//Vérification de l'identité de l'emetteur
	s = strcpy( s, ENTETE_MD5 );
	s = strcat( s, client.auteur );
	s = strcat( s, "\0" );
	//On teste les md5
	if( strcmp( md5( s, t ),  client.md5 ) != 0 ){
		//MD5 incorrect, on retourn 0 
		statut = 0;
	}else{
		//MD5 correct
		statut = 1;
	}
	//On libère la mémoire alouée
	free( s );
	free( t );
	return statut;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Traitement des connexions des clients
void traitementClient( char *buffer ){
	//Declaration des variables
	int cptBuffer = 0;
	//On vérifie que des parametres GET sont bien présent
	char *bufferPos = strchr( buffer, '?');
	if( bufferPos == NULL ){ envoyerReponse( "ERREUR  parametres manquants" ); return; }			//Si un parametre n'est pas présent, on quitte
	//On valide la position de ? comme début
	buffer = bufferPos + 1;
	//On isole la première ligne de l'entete HTTP
	bufferPos = strchr( buffer , ' ' );								//On récupère l'adresse du premier saut de ligne
	*bufferPos = '\0';													//On le remplace pour une fin de chaine de caratères
	//Nous avant donc isolé correctement la partie GET de l'url, comptons le nombre de & et = pour vérifier la syntaxe de la partie GET
	//Allocation de la mémoire
	struct parametresAuteur paraGet;
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On récupère le parametre "a" ( auteur du message )
	if( ( bufferPos = strstr( buffer,"a=" ) ) == NULL ){ envoyerReponse( "ERREUR  auteur manquant" ); return; }			//Si un parametre n'est pas présent, on quitte
	bufferPos = bufferPos + 2;
	//On compte le nombre de caractères
	cptBuffer = 0;
	while( *( bufferPos + cptBuffer ) != '&' && *( bufferPos + cptBuffer ) != '\0' ){
		//On incrémente le compteur
		cptBuffer++;
	}
	//On enregistre sa valeur
	paraGet.auteur = malloc ( sizeof( char * ) * 255 );
	paraGet.auteur = strncpy ( paraGet.auteur ,  bufferPos,  cptBuffer);
	paraGet.auteur = strcat( paraGet.auteur, "\0" );
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On récupère le parametre "c" ( clée MD5 )
	if( ( bufferPos = strstr( buffer,"c=" ) ) == NULL ){ envoyerReponse( "ERREUR  clee manquante" ); free( paraGet.auteur ); return; }			//Si un parametre n'est pas présent, on quitte
	bufferPos = bufferPos + 2;
	//On compte le nombre de caractères
	cptBuffer = 0;
	while( *( bufferPos + cptBuffer ) != '&' && *( bufferPos + cptBuffer ) != '\0' ){
		//On incrémente le compteur
		cptBuffer++;
	}
	//On enregistre sa valeur
	paraGet.md5 = malloc ( sizeof( char * ) * 255 );
	paraGet.md5 = strncpy ( paraGet.md5 ,  bufferPos,  cptBuffer );
	paraGet.md5 = strcat( paraGet.md5, "\0" );
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On récupère le parametre "d" ( destinataire )
	if( ( bufferPos = strstr( buffer,"d=" ) ) == NULL ){ envoyerReponse( "ERREUR  destinataire manquant" ); free( paraGet.auteur ); free( paraGet.md5 ); return; }			//Si un parametre n'est pas présent, on quitte
	bufferPos = bufferPos + 2;
	//On compte le nombre de caractères
	cptBuffer = 0;
	while( *( bufferPos + cptBuffer ) != '&' && *( bufferPos + cptBuffer ) != '\0' ){
		//On incrémente le compteur
		cptBuffer++;
	}
	//On enregistre sa valeur
	paraGet.destinataire = malloc ( sizeof( char * ) * 255 );
	paraGet.destinataire = strncpy ( paraGet.destinataire ,  bufferPos,  cptBuffer );
	paraGet.destinataire = strcat( paraGet.destinataire, "\0" );
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On récupère le parametre "t" ( texte du message )
	if( ( bufferPos = strstr( buffer,"t=" ) ) == NULL ){ envoyerReponse( "ERREUR  texte manquant" ); free( paraGet.auteur ); free( paraGet.md5 ); free( paraGet.destinataire ); return; }			//Si un parametre n'est pas présent, on quitte
	bufferPos = bufferPos + 2;
	//On compte le nombre de caractères
	cptBuffer = 0;
	while( *( bufferPos + cptBuffer ) != '&' && *( bufferPos + cptBuffer ) != '\0' ){
		//On incrémente le compteur
		cptBuffer++;
	}
	//On enregistre sa valeur
	paraGet.message = malloc ( sizeof( char * ) * 255 );
	paraGet.message = strncpy ( paraGet.message ,  bufferPos,  cptBuffer );
	paraGet.message = strcat( paraGet.message, "\0" );
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On lance la vérification de l'identité du client
	if( verficationIdentite( paraGet ) != 1 ){ envoyerReponse( "ERREUR  identite non verifie" ); free( paraGet.auteur ); free( paraGet.md5 ); free( paraGet.destinataire ); free( paraGet.message ); return; }
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On lance l'enregistrement de son message
	enregistrerMessage( paraGet );
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On libère l'espace alloué
	free( paraGet.auteur );
	free( paraGet.md5 );
	free( paraGet.destinataire );
	free( paraGet.message );
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////










//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Fonction principale de gestion des sockets
int main(
       int argc,                                  /* Nbre arguments */
       char *argv[])                              /* Ptr arguments */
{
      /* Déclaration des variables */
      ushort i;                                  /* Indice de boucle */
      ushort j;                                  /* Indice de boucle */
      int pid;                                   /* Process créé */
      int len_adr;                               /* Taille adresse */
      int sz_read;                                            /* Nbre octets lus */
      //char buf[SZ_BUF];                                       /* Buffer texte */
      char hostname[MAXHOSTNAMELEN + 1];                      /* Nom machine locale */
      struct sockaddr_in adr_serveur;                         /* Adresse socket serveur */
      struct sockaddr_in adr_client;                          /* Adresse socket client */
      struct hostent *host_info;                              /* Info. host client connecté */
      struct servent *service_info;                           /* Info. service demandé */
      char *adr_ascii;                                        /* Adresse client mode ascii */
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//On alloue en mémoire le nombre de messages
	//nbMessages=111;
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      /* Détournement du signal émis à la mort du fils (il ne reste pas zombie) */
      signal(SIGCHLD, SIG_IGN);
      /* Récuperation nom machine locale (juste pour l'exemple) */
      if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
      {
              exit(errno);
      }
      /* Récuperation port dans "/etc/services" */
      if ((service_info=getservbyname(SERVICE_LABEL, SERVICE_PROTOCOL)) == NULL)
      {
              exit(errno);
      }
      /* Création socket */
      if ((sk_creat=socket(AF_INET, SOCK_STREAM, 0)) == (-1))
      {
              exit(errno);
      }
      /* Remplissage adresse socket */
      memset(&adr_serveur, 0, sizeof(struct sockaddr_in));
      adr_serveur.sin_family=AF_INET;
      adr_serveur.sin_port=service_info->s_port;
      adr_serveur.sin_addr.s_addr=INADDR_ANY;
      /* Identification socket/réseau */
      if ( bind(sk_creat, &adr_serveur, sizeof(struct sockaddr_in)) == (-1))
      {
              exit(errno);
      }
      printf("Socket connectée au réseau\n");
      /* Ecoute de la ligne */
      listen(sk_creat, 1);
       while (1)
       {
              /* Attente connexion client */
              len_adr=sizeof(struct sockaddr_in);
              if ((sk_dialog=accept(sk_creat, &adr_client, &len_adr)) == (-1))
              {
                      exit(errno);
              }
              /* Client connecté */
             
              /* Duplication du process */
              switch (pid=fork())
              {
                      case (-1): /* Erreur de fork */
                              close(sk_creat);
                              close(sk_dialog);
                              exit(errno);
                      case 0: /* Fils */
                              /* Fermeture socket inutilisée */
                              close(sk_creat);
				//Allocation de la mémoire
				char *buf = malloc ( sizeof (*buf) * SZ_BUF);
                              /* Lecture en boucle sur la socket */
                              while ((sz_read=read(sk_dialog, buf, SZ_BUF)) > 0)
                              {
                              		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                              		//On lance le traitement des données
					traitementClient( buf );
					//Une fois les donnee traitees, on quitte la boucle
					break;
                              		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                           	}
				//On libère la mémoire allouée
				free( buf );					
                           /* Si l'arrêt de la lecture est dû à une erreur */
                           if (sz_read == (-1))
                           {
                                    close(sk_dialog);
                                    exit(errno);
                           }
                           /* Fin du fils */
                           close(sk_dialog);
                           exit(0);
                     default: /* Père */
                           close(sk_dialog);
              }
      }
      /* Pas de sortie de programme - Boucle infinie */
      /* Fermeture socket et fin théorique du programme (pour être propre) */
      close(sk_creat);
      return(0);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Vous pouvez voir dans la fonction main la création d'un thread.

Puis différentes fonctions s'enchainent.

Voici l'endroit le plus interressant:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Déclaration de la structure gérant la liste de nos messages
struct structureMessage *listesMessages;
int nbMessages;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Fonction qui envoie le résultat au navigateur
void envoyerReponse( char *buffer ){
	//On construit notre réponse
	char *s = malloc ( sizeof (*s) * SZ_BUF);
	s = strcpy( s, ENTETES_HTTP );
	s = strcat( s, "\n\n" );
	s = strcat( s, buffer );
	//On envoie notre réponse
	write( sk_dialog, s, strlen( s ) );
	//On libère la mémoire utilisé
	free( s );
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Fonction enregistrant un nouveau message a distribuer
void enregistrerMessage( struct  parametresAuteur client ){
	//Si le message est vide ou egal à NULL, on quitte
	if( strcmp( client.message, "NULL" ) == 0 || strcmp( client.message, "" )  == 0  ){ return; }
	//On incrémente le compteur
	nbMessages++;
	//On créé notre nouveau message
	struct structureMessage messageTmp;
	//On enregistre les infos du message
	strcpy( messageTmp.auteur, client.auteur );			//On copie les pseudo de l'auteur
	strcpy( messageTmp.destinataire, client.destinataire );		//On copie les pseudo du destinataire
	strcpy( messageTmp.message, client.message );			//On copie le message
	messageTmp.heure = ( int ) time( NULL );
	//On augmente la taille de la liste des messages
	listesMessages = realloc ( listesMessages, sizeof( messageTmp ) * nbMessages );
	//On ajoute notre nouveau message dans la liste
	listesMessages = memmove( listesMessages + ( sizeof( messageTmp ) * ( nbMessages - 1 ) ), &messageTmp , (int) sizeof( messageTmp ) );
	
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Voila, la variable "nbMessages" est déclarée comme variable GLOBALES et la fonction enregistrerMessage() incrémente cette variable.


Comme vous pouvez le voir, il s'agit d'un serveur de messagerie instantannée utilisant le protocle HTTP pour que les clients soient developpé en AJAX !

Dernière modification par Bzh (Le 26/06/2008, à 21:26)

Hors ligne

#5 Le 26/06/2008, à 21:39

nicolas.sitbon

Re : [PROG C] Variables globales et threads

et le fichier md5.c (bizarement inclu) où est il?

Hors ligne

#6 Le 26/06/2008, à 21:43

Bzh

Re : [PROG C] Variables globales et threads

/*

 **********************************************************************

 ** md5.h -- Header file for implementation of MD5                   **

 ** RSA Data Security, Inc. MD5 Message Digest Algorithm             **

 ** Created: 2/17/90 RLR                                             **

 ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version              **

 ** Revised (for MD5): RLR 4/27/91                                   **

 **   -- G modified to have y&~z instead of y&z                      **

 **   -- FF, GG, HH modified to add in last register done            **

 **   -- Access pattern: round 2 works mod 5, round 3 works mod 3    **

 **   -- distinct additive constant for each step                    **

 **   -- round 4 added, working mod 7                                **

 **********************************************************************

 */



/*

 **********************************************************************

 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **

 **                                                                  **

 ** License to copy and use this software is granted provided that   **

 ** it is identified as the "RSA Data Security, Inc. MD5 Message     **

 ** Digest Algorithm" in all material mentioning or referencing this **

 ** software or this function.                                       **

 **                                                                  **

 ** License is also granted to make and use derivative works         **

 ** provided that such works are identified as "derived from the RSA **

 ** Data Security, Inc. MD5 Message Digest Algorithm" in all         **

 ** material mentioning or referencing the derived work.             **

 **                                                                  **

 ** RSA Data Security, Inc. makes no representations concerning      **

 ** either the merchantability of this software or the suitability   **

 ** of this software for any particular purpose.  It is provided "as **

 ** is" without express or implied warranty of any kind.             **

 **                                                                  **

 ** These notices must be retained in any copies of any part of this **

 ** documentation and/or software.                                   **

 **********************************************************************

 */



/* typedef a 32 bit type */

typedef unsigned long int UINT4;



/* Data structure for MD5 (Message Digest) computation */

typedef struct {

  UINT4 i[2];                   /* number of _bits_ handled mod 2^64 */

  UINT4 buf[4];                                    /* scratch buffer */

  unsigned char in[64];                              /* input buffer */

  unsigned char digest[16];     /* actual digest after MD5Final call */

} MD5_CTX;



void MD5Init ();

void MD5Update ();

void MD5Final ();



/*

 **********************************************************************

 ** End of md5.h                                                     **

 ******************************* (cut) ********************************

 */



/*

 **********************************************************************

 ** md5.c                                                            **

 ** RSA Data Security, Inc. MD5 Message Digest Algorithm             **

 ** Created: 2/17/90 RLR                                             **

 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version                  **

 **********************************************************************

 */



/*

 **********************************************************************

 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **

 **                                                                  **

 ** License to copy and use this software is granted provided that   **

 ** it is identified as the "RSA Data Security, Inc. MD5 Message     **

 ** Digest Algorithm" in all material mentioning or referencing this **

 ** software or this function.                                       **

 **                                                                  **

 ** License is also granted to make and use derivative works         **

 ** provided that such works are identified as "derived from the RSA **

 ** Data Security, Inc. MD5 Message Digest Algorithm" in all         **

 ** material mentioning or referencing the derived work.             **

 **                                                                  **

 ** RSA Data Security, Inc. makes no representations concerning      **

 ** either the merchantability of this software or the suitability   **

 ** of this software for any particular purpose.  It is provided "as **

 ** is" without express or implied warranty of any kind.             **

 **                                                                  **

 ** These notices must be retained in any copies of any part of this **

 ** documentation and/or software.                                   **

 **********************************************************************

 */



/* -- include the following line if the md5.h header file is separate -- */

/* #include "md5.h" */



/* forward declaration */

static void Transform ();



static unsigned char PADDING[64] = {

  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

};



/* F, G and H are basic MD5 functions: selection, majority, parity */

#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))

#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))

#define H(x, y, z) ((x) ^ (y) ^ (z))

#define I(x, y, z) ((y) ^ ((x) | (~z))) 



/* ROTATE_LEFT rotates x left n bits */

#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))



/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */

/* Rotation is separate from addition to prevent recomputation */

#define FF(a, b, c, d, x, s, ac) \

  {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \

   (a) = ROTATE_LEFT ((a), (s)); \

   (a) += (b); \

  }

#define GG(a, b, c, d, x, s, ac) \

  {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \

   (a) = ROTATE_LEFT ((a), (s)); \

   (a) += (b); \

  }

#define HH(a, b, c, d, x, s, ac) \

  {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \

   (a) = ROTATE_LEFT ((a), (s)); \

   (a) += (b); \

  }

#define II(a, b, c, d, x, s, ac) \

  {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \

   (a) = ROTATE_LEFT ((a), (s)); \

   (a) += (b); \

  }



void MD5Init (mdContext)

MD5_CTX *mdContext;

{

  mdContext->i[0] = mdContext->i[1] = (UINT4)0;



  /* Load magic initialization constants.

   */

  mdContext->buf[0] = (UINT4)0x67452301;

  mdContext->buf[1] = (UINT4)0xefcdab89;

  mdContext->buf[2] = (UINT4)0x98badcfe;

  mdContext->buf[3] = (UINT4)0x10325476;

}



void MD5Update (mdContext, inBuf, inLen)

MD5_CTX *mdContext;

unsigned char *inBuf;

unsigned int inLen;

{

  UINT4 in[16];

  int mdi;

  unsigned int i, ii;



  /* compute number of bytes mod 64 */

  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);



  /* update number of bits */

  if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])

    mdContext->i[1]++;

  mdContext->i[0] += ((UINT4)inLen << 3);

  mdContext->i[1] += ((UINT4)inLen >> 29);



  while (inLen--) {

    /* add new character to buffer, increment mdi */

    mdContext->in[mdi++] = *inBuf++;



    /* transform if necessary */

    if (mdi == 0x40) {

      for (i = 0, ii = 0; i < 16; i++, ii += 4)

        in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |

                (((UINT4)mdContext->in[ii+2]) << 16) |

                (((UINT4)mdContext->in[ii+1]) << 8) |

                ((UINT4)mdContext->in[ii]);

      Transform (mdContext->buf, in);

      mdi = 0;

    }

  }

}



void MD5Final (mdContext)

MD5_CTX *mdContext;

{

  UINT4 in[16];

  int mdi;

  unsigned int i, ii;

  unsigned int padLen;



  /* save number of bits */

  in[14] = mdContext->i[0];

  in[15] = mdContext->i[1];



  /* compute number of bytes mod 64 */

  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);



  /* pad out to 56 mod 64 */

  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);

  MD5Update (mdContext, PADDING, padLen);



  /* append length in bits and transform */

  for (i = 0, ii = 0; i < 14; i++, ii += 4)

    in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |

            (((UINT4)mdContext->in[ii+2]) << 16) |

            (((UINT4)mdContext->in[ii+1]) << 8) |

            ((UINT4)mdContext->in[ii]);

  Transform (mdContext->buf, in);



  /* store buffer in digest */

  for (i = 0, ii = 0; i < 4; i++, ii += 4) {

    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);

    mdContext->digest[ii+1] =

      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);

    mdContext->digest[ii+2] =

      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);

    mdContext->digest[ii+3] =

      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);

  }

}



/* Basic MD5 step. Transform buf based on in.

 */

static void Transform (buf, in)

UINT4 *buf;

UINT4 *in;

{

  UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];



  /* Round 1 */

#define S11 7

#define S12 12

#define S13 17

#define S14 22

  FF ( a, b, c, d, in[ 0], S11, 3614090360); /* 1 */

  FF ( d, a, b, c, in[ 1], S12, 3905402710); /* 2 */

  FF ( c, d, a, b, in[ 2], S13,  606105819); /* 3 */

  FF ( b, c, d, a, in[ 3], S14, 3250441966); /* 4 */

  FF ( a, b, c, d, in[ 4], S11, 4118548399); /* 5 */

  FF ( d, a, b, c, in[ 5], S12, 1200080426); /* 6 */

  FF ( c, d, a, b, in[ 6], S13, 2821735955); /* 7 */

  FF ( b, c, d, a, in[ 7], S14, 4249261313); /* 8 */

  FF ( a, b, c, d, in[ 8], S11, 1770035416); /* 9 */

  FF ( d, a, b, c, in[ 9], S12, 2336552879); /* 10 */

  FF ( c, d, a, b, in[10], S13, 4294925233); /* 11 */

  FF ( b, c, d, a, in[11], S14, 2304563134); /* 12 */

  FF ( a, b, c, d, in[12], S11, 1804603682); /* 13 */

  FF ( d, a, b, c, in[13], S12, 4254626195); /* 14 */

  FF ( c, d, a, b, in[14], S13, 2792965006); /* 15 */

  FF ( b, c, d, a, in[15], S14, 1236535329); /* 16 */



  /* Round 2 */

#define S21 5

#define S22 9

#define S23 14

#define S24 20

  GG ( a, b, c, d, in[ 1], S21, 4129170786); /* 17 */

  GG ( d, a, b, c, in[ 6], S22, 3225465664); /* 18 */

  GG ( c, d, a, b, in[11], S23,  643717713); /* 19 */

  GG ( b, c, d, a, in[ 0], S24, 3921069994); /* 20 */

  GG ( a, b, c, d, in[ 5], S21, 3593408605); /* 21 */

  GG ( d, a, b, c, in[10], S22,   38016083); /* 22 */

  GG ( c, d, a, b, in[15], S23, 3634488961); /* 23 */

  GG ( b, c, d, a, in[ 4], S24, 3889429448); /* 24 */

  GG ( a, b, c, d, in[ 9], S21,  568446438); /* 25 */

  GG ( d, a, b, c, in[14], S22, 3275163606); /* 26 */

  GG ( c, d, a, b, in[ 3], S23, 4107603335); /* 27 */

  GG ( b, c, d, a, in[ 8], S24, 1163531501); /* 28 */

  GG ( a, b, c, d, in[13], S21, 2850285829); /* 29 */

  GG ( d, a, b, c, in[ 2], S22, 4243563512); /* 30 */

  GG ( c, d, a, b, in[ 7], S23, 1735328473); /* 31 */

  GG ( b, c, d, a, in[12], S24, 2368359562); /* 32 */



  /* Round 3 */

#define S31 4

#define S32 11

#define S33 16

#define S34 23

  HH ( a, b, c, d, in[ 5], S31, 4294588738); /* 33 */

  HH ( d, a, b, c, in[ 8], S32, 2272392833); /* 34 */

  HH ( c, d, a, b, in[11], S33, 1839030562); /* 35 */

  HH ( b, c, d, a, in[14], S34, 4259657740); /* 36 */

  HH ( a, b, c, d, in[ 1], S31, 2763975236); /* 37 */

  HH ( d, a, b, c, in[ 4], S32, 1272893353); /* 38 */

  HH ( c, d, a, b, in[ 7], S33, 4139469664); /* 39 */

  HH ( b, c, d, a, in[10], S34, 3200236656); /* 40 */

  HH ( a, b, c, d, in[13], S31,  681279174); /* 41 */

  HH ( d, a, b, c, in[ 0], S32, 3936430074); /* 42 */

  HH ( c, d, a, b, in[ 3], S33, 3572445317); /* 43 */

  HH ( b, c, d, a, in[ 6], S34,   76029189); /* 44 */

  HH ( a, b, c, d, in[ 9], S31, 3654602809); /* 45 */

  HH ( d, a, b, c, in[12], S32, 3873151461); /* 46 */

  HH ( c, d, a, b, in[15], S33,  530742520); /* 47 */

  HH ( b, c, d, a, in[ 2], S34, 3299628645); /* 48 */



  /* Round 4 */

#define S41 6

#define S42 10

#define S43 15

#define S44 21

  II ( a, b, c, d, in[ 0], S41, 4096336452); /* 49 */

  II ( d, a, b, c, in[ 7], S42, 1126891415); /* 50 */

  II ( c, d, a, b, in[14], S43, 2878612391); /* 51 */

  II ( b, c, d, a, in[ 5], S44, 4237533241); /* 52 */

  II ( a, b, c, d, in[12], S41, 1700485571); /* 53 */

  II ( d, a, b, c, in[ 3], S42, 2399980690); /* 54 */

  II ( c, d, a, b, in[10], S43, 4293915773); /* 55 */

  II ( b, c, d, a, in[ 1], S44, 2240044497); /* 56 */

  II ( a, b, c, d, in[ 8], S41, 1873313359); /* 57 */

  II ( d, a, b, c, in[15], S42, 4264355552); /* 58 */

  II ( c, d, a, b, in[ 6], S43, 2734768916); /* 59 */

  II ( b, c, d, a, in[13], S44, 1309151649); /* 60 */

  II ( a, b, c, d, in[ 4], S41, 4149444226); /* 61 */

  II ( d, a, b, c, in[11], S42, 3174756917); /* 62 */

  II ( c, d, a, b, in[ 2], S43,  718787259); /* 63 */

  II ( b, c, d, a, in[ 9], S44, 3951481745); /* 64 */



  buf[0] += a;

  buf[1] += b;

  buf[2] += c;

  buf[3] += d;

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Fonction créé afin de pouvoir génerer le code ASCII d'un hash MD5
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
char *md5( char *chaine, char *s ){
	//Variable de la fonction
	int i;
	MD5_CTX mdContext;

	//On hash la chaine de caractère
	MD5Init (&mdContext);

	MD5Update (&mdContext, chaine, strlen( chaine ) );

	MD5Final (&mdContext);
	//On boucle afin de traiter chaque caratères du hash MD5

 	for (i = 0; i < 16; i++){

   		sprintf(s + ( 2 * i ), "%02x", mdContext.digest[i]);
	}
	//On retourne le résultat du la fonction
	return s;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Voila, vous avez tout.

En quoi est-il bizarement inclue ?

Hors ligne

#7 Le 26/06/2008, à 23:39

nicolas.sitbon

Re : [PROG C] Variables globales et threads

Bon!
ton programme ne créer aucun thread, il créé des processus (fork) donc pas étonnant le comportement de ta variable globale.
D'autre part, il faut d'urgence que tu prennes des cours de C plus sérieux, il te manque les bases...
J'ai corrigé une partie de ton code mais pas tout (trop fatigué...)
main.c

#include <sys/types.h>          /* Types prédéfinis "c" */
#include <sys/socket.h>         /* Généralités sockets */
#include <sys/param.h>          /* Paramètres et limites système */
#include <netinet/in.h>         /* Spécifications socket internet */
#include <arpa/inet.h>          /* Adresses format "arpanet" */
#include <signal.h>             /* Signaux de communication */
#include <string.h>             /* Gestion des chaines de caratères */
#include <stdio.h>              /* I/O fichiers classiques */
#include <stdlib.h>             /* Gestion de EXIT */
#include <netdb.h>              /* Gestion network database */
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "md5.h"

#define SERVICE_LABEL            "st*****at"  /* Nom service requis */
#define SERVICE_PROTOCOL         "tcp"  /* Protocole service requis */
#define SZ_BUF                   256000  /* Taille buffer */
#define STR_SIZE                 256
#define ENTETE_MD5               "875" //Pour Manu => fec83147f8c18d1dcb4a2c4418455a84
#define ENTETES_HTTP "HTTP/1.1 200 OK\nDate: Wed, 25 Jun 2008 13:32:29 GMT\n" \
                     "Server: ****** V1.0 by ******\n" \
                     "Expires: Thu, 19 Nov 1981 08:52:00 GMT\n" \
                     "Cache-Control: no-store, no-cache, must-revalidate, " \
                     "post-check=0, pre-check=0\n" \
                     "Pragma: no-cache\n" \
                     "Content-Type: text/html; charset=iso-8859-15"


struct parametresAuteur
{
   char *auteur;
   char *md5;
   char *destinataire;
   char *message;
};

struct structureMessage
{
   char auteur[STR_SIZE];
   char destinataire[STR_SIZE];
   char message[STR_SIZE];
   time_t heure;
};

static struct structureMessage *listesMessages;
static unsigned nbMessages;
static int sk_creat;                   /* Socket de création */
static int sk_dialog;                  /* Socket de dialogue */

//Fonction qui envoie le résultat au navigateur
static void envoyerReponse (char const *buffer)
{
   write (sk_dialog, ENTETES_HTTP "\n\n", sizeof ENTETES_HTTP + 1);
   //On envoie notre réponse
   write (sk_dialog, buffer, strlen (buffer));
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Fonction enregistrant un nouveau message a distribuer
static void enregistrerMessage (struct parametresAuteur client)
{
   //Si le message est vide ou egal à NULL, on quitte
   if (strcmp (client.message, "NULL") != 0 && strcmp (client.message, "") != 0)
   {
      void *temp = NULL;
      struct structureMessage messageTmp; //On créé notre nouveau message      
      nbMessages++; //On incrémente le compteur
      //On enregistre les infos du message
      strcpy (messageTmp.auteur, client.auteur);  //On copie les pseudo de l'auteur
      strcpy (messageTmp.destinataire, client.destinataire);  //On copie les pseudo du destinataire
      strcpy (messageTmp.message, client.message);  //On copie le message

      messageTmp.heure = time (NULL);
      //On augmente la taille de la liste des messages
      temp = realloc (listesMessages, nbMessages * sizeof *listesMessages);
      
      if (temp != NULL)
      {
         //On ajoute notre nouveau message dans la liste
         listesMessages = temp;
         listesMessages =  memmove (listesMessages + (sizeof (messageTmp) * (nbMessages - 1)), &messageTmp, sizeof (messageTmp));
      }
      else
      {
         perror (__func__);
      }
   }
}

//Vérification de l'identité du client
static int verficationIdentite (struct parametresAuteur client)
{
   int statut = 0;
   //Allocation en mémoire
   char *s = malloc (SZ_BUF * sizeof *s);
   
   if (s != NULL)
   {
      char *t = malloc (SZ_BUF * sizeof *s);
      
      if (t != NULL)
      {       
         //Vérification de l'identité de l'emetteur
         s = strcpy (s, ENTETE_MD5);
         s = strcat (s, client.auteur);

         //On teste les md5
         if (strcmp (md5 (s, t), client.md5) == 0)
         {
            //MD5 correct
            statut = 1;
         }
         
         free (t), t = NULL;        
      }
      else
      {
         perror (__func__);
      }
      
      free (s), s = NULL;
   }
   else
   {
      perror (__func__);
   }
   
   return statut;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Traitement des connexions des clients
static void traitementClient (char *buffer)
{
   //On vérifie que des parametres GET sont bien présent
   char *bufferPos = strchr (buffer, '?');
   
   if (bufferPos == NULL)
   {
      envoyerReponse ("ERREUR  parametres manquants");
   }                        //Si un parametre n'est pas présent, on quitte
   else
   {
      //On valide la position de ? comme début      
      buffer = bufferPos + 1;
      //On isole la première ligne de l'entete HTTP
      bufferPos = strchr (buffer, ' ');  //On récupère l'adresse du premier saut de ligne

      *bufferPos = '\0';           //On le remplace pour une fin de chaine de caratères
      //Nous avant donc isolé correctement la partie GET de l'url, comptons le nombre de & et = pour vérifier la syntaxe de la partie GET
      //Allocation de la mémoire
      
      //On récupère le parametre "a" ( auteur du message )
      if ((bufferPos = strstr (buffer, "a=")) == NULL)
      {
         envoyerReponse ("ERREUR  auteur manquant");//Si un parametre n'est pas présent, on quitte
      }                            
      else
      {
         struct parametresAuteur paraGet;
         unsigned cptBuffer = 0;
      
         bufferPos += 2;
         //On compte le nombre de caractères

         while (*(bufferPos + cptBuffer) != '&' && *(bufferPos + cptBuffer) != '\0')
         {
            //On incrémente le compteur
            cptBuffer++;
         }
         //On enregistre sa valeur
         paraGet.auteur = malloc (255);
         paraGet.auteur = strncpy (paraGet.auteur, bufferPos, cptBuffer);
         paraGet.auteur = strcat (paraGet.auteur, "\0");
         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         //On récupère le parametre "c" ( clée MD5 )
         if ((bufferPos = strstr (buffer, "c=")) == NULL)
         {
            envoyerReponse ("ERREUR  clee manquante");
            free (paraGet.auteur);
            return;
         }                            //Si un parametre n'est pas présent, on quitte

         bufferPos = bufferPos + 2;
         //On compte le nombre de caractères
         cptBuffer = 0;
         while (*(bufferPos + cptBuffer) != '&' && *(bufferPos + cptBuffer) != '\0')
         {
            //On incrémente le compteur
            cptBuffer++;
         }
         //On enregistre sa valeur
         paraGet.md5 = malloc (sizeof (char *) * STR_SIZE);
         paraGet.md5 = strncpy (paraGet.md5, bufferPos, cptBuffer);
         paraGet.md5 = strcat (paraGet.md5, "\0");
         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         //On récupère le parametre "d" ( destinataire )
         if ((bufferPos = strstr (buffer, "d=")) == NULL)
         {
            envoyerReponse ("ERREUR  destinataire manquant");
            free (paraGet.auteur);
            free (paraGet.md5);
            return;
         }                            //Si un parametre n'est pas présent, on quitte

         bufferPos = bufferPos + 2;
         //On compte le nombre de caractères
         cptBuffer = 0;
         while (*(bufferPos + cptBuffer) != '&' && *(bufferPos + cptBuffer) != '\0')
         {
            //On incrémente le compteur
            cptBuffer++;
         }
         //On enregistre sa valeur
         paraGet.destinataire = malloc (STR_SIZE);
         paraGet.destinataire = strncpy (paraGet.destinataire, bufferPos, cptBuffer);
         paraGet.destinataire = strcat (paraGet.destinataire, "\0");
         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         //On récupère le parametre "t" ( texte du message )
         if ((bufferPos = strstr (buffer, "t=")) == NULL)
         {
            envoyerReponse ("ERREUR  texte manquant");
            free (paraGet.auteur);
            free (paraGet.md5);
            free (paraGet.destinataire);
            return;
         }                            //Si un parametre n'est pas présent, on quitte

         bufferPos = bufferPos + 2;
         //On compte le nombre de caractères
         cptBuffer = 0;
         while (*(bufferPos + cptBuffer) != '&' && *(bufferPos + cptBuffer) != '\0')
         {
            //On incrémente le compteur
            cptBuffer++;
         }
         //On enregistre sa valeur
         paraGet.message = malloc (STR_SIZE);
         paraGet.message = strncpy (paraGet.message, bufferPos, cptBuffer);
         paraGet.message = strcat (paraGet.message, "\0");
         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         //On lance la vérification de l'identité du client
         if (verficationIdentite (paraGet) != 1)
         {
            envoyerReponse ("ERREUR  identite non verifie");
            free (paraGet.auteur);
            free (paraGet.md5);
            free (paraGet.destinataire);
            free (paraGet.message);
            return;
         }
         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         //On lance l'enregistrement de son message
         enregistrerMessage (paraGet);
         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         //On libère l'espace alloué
         free (paraGet.auteur);
         free (paraGet.md5);
         free (paraGet.destinataire);
         free (paraGet.message);
      }
   }
}

//Fonction principale de gestion des sockets
int main (void)                 /* Ptr arguments */
{
   int ret = 0;
   char hostname[MAXHOSTNAMELEN + 1];

   signal (SIGCHLD, SIG_IGN);
   /* Récuperation nom machine locale (juste pour l'exemple) */
   if (gethostname (hostname, MAXHOSTNAMELEN) != 0)
   {
      ret = EXIT_FAILURE;
   }
   else
   {
      struct servent *service_info = getservbyname (SERVICE_LABEL, SERVICE_PROTOCOL);
      /* Récuperation port dans "/etc/services" */
      if (service_info == NULL)
      {
         ret = EXIT_FAILURE;
      }
      else
      {
         sk_creat = socket (PF_INET, SOCK_STREAM, 0);
         /* Création socket */
         if (sk_creat == -1)
         {
            ret = EXIT_FAILURE;
         }
         else
         {
            struct sockaddr_in adr_serveur = 
            {
               AF_INET,
               (in_port_t) service_info->s_port,
               INADDR_ANY
            };
            
            if (bind (sk_creat, (struct sockaddr *) &adr_serveur, sizeof adr_serveur) == (-1))
            {
               ret = EXIT_FAILURE;
            }
            else
            {
               puts ("Socket connectée au réseau");
               /* Ecoute de la ligne */
               listen (sk_creat, 1);
               
               while (1)
               {
                  struct sockaddr_in adr_client;  /* Adresse socket client */
                  socklen_t len_adr = sizeof adr_client;
                  
                  if ((sk_dialog = accept (sk_creat, (struct sockaddr *) &adr_client, &len_adr)) == (-1))
                  {
                     ret = EXIT_FAILURE;
                  }
                  else
                  {
                     pid_t pid;                     /* Process créé */
                     ssize_t sz_read;                 /* Nbre octets lus */

                     /* Duplication du process */
                     switch (pid = fork ())
                     {
                        case -1:               /* Erreur de fork */
                           close (sk_creat);
                           close (sk_dialog);
                           exit (errno);
                        case 0:                  /* Fils */
                           /* Fermeture socket inutilisée */
                           close (sk_creat);
                           //Allocation de la mémoire
                           char *buf = malloc (SZ_BUF);
                           /* Lecture en boucle sur la socket */
                           while ((sz_read = read (sk_dialog, buf, SZ_BUF)) > 0)
                           {
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                              //On lance le traitement des données
                              traitementClient (buf);
                              //Une fois les donnee traitees, on quitte la boucle
                              break;
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                           }
                           //On libère la mémoire allouée
                           free (buf), buf = NULL;

                           /* Fin du fils */
                           close (sk_dialog);
                           break;
                        default:                 /* Père */
                           close (sk_dialog);
                     }
                  }
               }
               /* Pas de sortie de programme - Boucle infinie */
               /* Fermeture socket et fin théorique du programme (pour être propre) */
               close (sk_creat);
            }
         }
      }
   }
   return ret;
}

md5.c

#include "md5.h"

#include <string.h>
#include <stdio.h>

static unsigned char PADDING[64] =
{
   0x80
};

/* F, G and H are basic MD5 functions: selection, majority, parity */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
{ \
   (a) += F ((b), (c), (d)) + (x) + (uint32_t) (ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
}

#define GG(a, b, c, d, x, s, ac) \
{ \
   (a) += G ((b), (c), (d)) + (x) + (uint32_t) (ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
}

#define HH(a, b, c, d, x, s, ac) \
{ \
   (a) += H ((b), (c), (d)) + (x) + (uint32_t) (ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
}

#define II(a, b, c, d, x, s, ac) \
{ \
   (a) += I ((b), (c), (d)) + (x) + (uint32_t) (ac); \
   (a) = ROTATE_LEFT ((a), (s)); \
   (a) += (b); \
}

static void Transform (uint32_t * buf, uint32_t * in)
{
   uint32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];

   /* Round 1 */

#define S11 7

#define S12 12

#define S13 17

#define S14 22

   FF (a, b, c, d, in[0], S11, 3614090360);  /* 1 */
   FF (d, a, b, c, in[1], S12, 3905402710);  /* 2 */
   FF (c, d, a, b, in[2], S13, 606105819);  /* 3 */
   FF (b, c, d, a, in[3], S14, 3250441966);  /* 4 */
   FF (a, b, c, d, in[4], S11, 4118548399);  /* 5 */
   FF (d, a, b, c, in[5], S12, 1200080426);  /* 6 */
   FF (c, d, a, b, in[6], S13, 2821735955);  /* 7 */
   FF (b, c, d, a, in[7], S14, 4249261313);  /* 8 */
   FF (a, b, c, d, in[8], S11, 1770035416);  /* 9 */
   FF (d, a, b, c, in[9], S12, 2336552879);  /* 10 */
   FF (c, d, a, b, in[10], S13, 4294925233);  /* 11 */
   FF (b, c, d, a, in[11], S14, 2304563134);  /* 12 */
   FF (a, b, c, d, in[12], S11, 1804603682);  /* 13 */
   FF (d, a, b, c, in[13], S12, 4254626195);  /* 14 */
   FF (c, d, a, b, in[14], S13, 2792965006);  /* 15 */
   FF (b, c, d, a, in[15], S14, 1236535329);  /* 16 */

   /* Round 2 */

#define S21 5

#define S22 9

#define S23 14

#define S24 20

   GG (a, b, c, d, in[1], S21, 4129170786);  /* 17 */
   GG (d, a, b, c, in[6], S22, 3225465664);  /* 18 */
   GG (c, d, a, b, in[11], S23, 643717713);  /* 19 */
   GG (b, c, d, a, in[0], S24, 3921069994);  /* 20 */
   GG (a, b, c, d, in[5], S21, 3593408605);  /* 21 */
   GG (d, a, b, c, in[10], S22, 38016083);  /* 22 */
   GG (c, d, a, b, in[15], S23, 3634488961);  /* 23 */
   GG (b, c, d, a, in[4], S24, 3889429448);  /* 24 */
   GG (a, b, c, d, in[9], S21, 568446438);  /* 25 */
   GG (d, a, b, c, in[14], S22, 3275163606);  /* 26 */
   GG (c, d, a, b, in[3], S23, 4107603335);  /* 27 */
   GG (b, c, d, a, in[8], S24, 1163531501);  /* 28 */
   GG (a, b, c, d, in[13], S21, 2850285829);  /* 29 */
   GG (d, a, b, c, in[2], S22, 4243563512);  /* 30 */
   GG (c, d, a, b, in[7], S23, 1735328473);  /* 31 */
   GG (b, c, d, a, in[12], S24, 2368359562);  /* 32 */

   /* Round 3 */

#define S31 4

#define S32 11

#define S33 16

#define S34 23

   HH (a, b, c, d, in[5], S31, 4294588738);  /* 33 */
   HH (d, a, b, c, in[8], S32, 2272392833);  /* 34 */
   HH (c, d, a, b, in[11], S33, 1839030562);  /* 35 */
   HH (b, c, d, a, in[14], S34, 4259657740);  /* 36 */
   HH (a, b, c, d, in[1], S31, 2763975236);  /* 37 */
   HH (d, a, b, c, in[4], S32, 1272893353);  /* 38 */
   HH (c, d, a, b, in[7], S33, 4139469664);  /* 39 */
   HH (b, c, d, a, in[10], S34, 3200236656);  /* 40 */
   HH (a, b, c, d, in[13], S31, 681279174);  /* 41 */
   HH (d, a, b, c, in[0], S32, 3936430074);  /* 42 */
   HH (c, d, a, b, in[3], S33, 3572445317);  /* 43 */
   HH (b, c, d, a, in[6], S34, 76029189);  /* 44 */
   HH (a, b, c, d, in[9], S31, 3654602809);  /* 45 */
   HH (d, a, b, c, in[12], S32, 3873151461);  /* 46 */
   HH (c, d, a, b, in[15], S33, 530742520);  /* 47 */
   HH (b, c, d, a, in[2], S34, 3299628645);  /* 48 */

   /* Round 4 */

#define S41 6

#define S42 10

#define S43 15

#define S44 21

   II (a, b, c, d, in[0], S41, 4096336452);  /* 49 */
   II (d, a, b, c, in[7], S42, 1126891415);  /* 50 */
   II (c, d, a, b, in[14], S43, 2878612391);  /* 51 */
   II (b, c, d, a, in[5], S44, 4237533241);  /* 52 */
   II (a, b, c, d, in[12], S41, 1700485571);  /* 53 */
   II (d, a, b, c, in[3], S42, 2399980690);  /* 54 */
   II (c, d, a, b, in[10], S43, 4293915773);  /* 55 */
   II (b, c, d, a, in[1], S44, 2240044497);  /* 56 */
   II (a, b, c, d, in[8], S41, 1873313359);  /* 57 */
   II (d, a, b, c, in[15], S42, 4264355552);  /* 58 */
   II (c, d, a, b, in[6], S43, 2734768916);  /* 59 */
   II (b, c, d, a, in[13], S44, 1309151649);  /* 60 */
   II (a, b, c, d, in[4], S41, 4149444226);  /* 61 */
   II (d, a, b, c, in[11], S42, 3174756917);  /* 62 */
   II (c, d, a, b, in[2], S43, 718787259);  /* 63 */
   II (b, c, d, a, in[9], S44, 3951481745);  /* 64 */

   buf[0] += a;
   buf[1] += b;
   buf[2] += c;
   buf[3] += d;
}

void MD5Init (MD5_CTX * mdContext)
{
   mdContext->i[0] = mdContext->i[1] = 0;
   mdContext->buf[0] = (uint32_t) 0x67452301;
   mdContext->buf[1] = (uint32_t) 0xefcdab89;
   mdContext->buf[2] = (uint32_t) 0x98badcfe;
   mdContext->buf[3] = (uint32_t) 0x10325476;

}

void MD5Update (MD5_CTX * mdContext, unsigned char const *inBuf, size_t inLen)
{
   int mdi = (int) ((mdContext->i[0] >> 3) & 0x3F);
   /* update number of bits */

   if ((mdContext->i[0] + ((uint32_t) inLen << 3)) < mdContext->i[0])
   {
      mdContext->i[1]++;
   }

   mdContext->i[0] += ((uint32_t) inLen << 3);
   mdContext->i[1] += ((uint32_t) inLen >> 29);

   while (inLen--)
   {
      /* add new character to buffer, increment mdi */

      mdContext->in[mdi++] = *inBuf++;

      /* transform if necessary */

      if (mdi == 0x40)
      {
         uint32_t in[16];
         
         for (size_t i = 0, j = 0; i < 16; i++, j += 4)
         {
            in[i] = (uint32_t) mdContext->in[j + 3]  << 24 |
                    (uint32_t) mdContext->in[j + 2]  << 16 |
                    (uint32_t) mdContext->in[j + 1]  <<  8 |
                    (uint32_t) mdContext->in[j];
         }

         Transform (mdContext->buf, in);
         mdi = 0;
      }
   }
}

void MD5Final (MD5_CTX * mdContext)
{
   uint32_t in[16] =
   {
      [14] = mdContext->i[0],
      [15] = mdContext->i[1]
   };

   int mdi = (int) ((mdContext->i[0] >> 3) & 0x3F);

   /* pad out to 56 mod 64 */

   size_t padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);

   MD5Update (mdContext, PADDING, padLen);

   /* append length in bits and transform */

   for (size_t i = 0, j = 0; i < 14; i++, j += 4)
   {
      in[i] = (uint32_t) mdContext->in[j + 3]  << 24 |
              (uint32_t) mdContext->in[j + 2]  << 16 |
              (uint32_t) mdContext->in[j + 1]  <<  8 |
              (uint32_t) mdContext->in[j];
   }

   Transform (mdContext->buf, in);

   /* store buffer in digest */

   for (size_t i = 0, j = 0; i < 4; i++, j += 4)
   {

      mdContext->digest[j] = (unsigned char) (mdContext->buf[i] & 0xFF);

      mdContext->digest[j + 1] =

         (unsigned char) ((mdContext->buf[i] >> 8) & 0xFF);

      mdContext->digest[j + 2] =

         (unsigned char) ((mdContext->buf[i] >> 16) & 0xFF);

      mdContext->digest[j + 3] =

         (unsigned char) ((mdContext->buf[i] >> 24) & 0xFF);

   }

}

//Fonction créé afin de pouvoir génerer le code ASCII d'un hash MD5
char *md5 (char const *chaine, char *s)
{
   MD5_CTX mdContext;

   //On hash la chaine de caractère
   MD5Init (&mdContext);
   MD5Update (&mdContext, chaine, strlen (chaine));
   MD5Final (&mdContext);
   //On boucle afin de traiter chaque caratères du hash MD5

   for (size_t i = 0; i < 16; i++)
   {
      sprintf (s + (2 * i), "%02hhx", mdContext.digest[i]);
   }
   //On retourne le résultat du la fonction
   return s;
}

md5.h

#ifndef MD5_H
#define	MD5_H

#include <stdint.h>
#include <stddef.h>

typedef struct
{
   uint32_t i[2];                  /* number of _bits_ handled mod 2^64 */
   uint32_t buf[4];                /* scratch buffer */
   unsigned char in[64];        /* input buffer */
   unsigned char digest[16];    /* actual digest after MD5Final call */

}
MD5_CTX;

extern void MD5Init (MD5_CTX *mdContext);
extern void MD5Update (MD5_CTX *mdContext, unsigned char const *inBuf, size_t inLen);
extern void MD5Final (MD5_CTX *mdContext);
extern char *md5 (char const *chaine, char *s);

#endif /* MD5_H */

Cordialement.

Dernière modification par nicolas.sitbon (Le 27/06/2008, à 06:59)

Hors ligne

#8 Le 27/06/2008, à 02:12

Bzh

Re : [PROG C] Variables globales et threads

Je ne sais comment te remercier. smile

Je voulais tout de même preciser que je suis étudiant mais pas en informatique et le C n'est vraiment pas un langage simple, je fais de mon mieu, par moi même. roll

J'essaye d'apprendre le C simplement par curiosité et par plaisir...

Le code source "md5.c" n'est pas de moi, enfin seulement la toute dernière fonction, et je remarque avec plaisir, que celle là, et bien tu n'y a pas touché. tongue

Au moin une de correcte...

En tout cas, encore merci, j'étudie tout ça à tête reposé demain... big_smile

Hors ligne

#9 Le 27/06/2008, à 06:58

nicolas.sitbon

Re : [PROG C] Variables globales et threads

Bzh a écrit :

Je ne sais comment te remercier. smile

Tu n'as pas à le faire, je le fais par pûr plaisir.

Bzh a écrit :

Je voulais tout de même preciser que je suis étudiant mais pas en informatique et le C n'est vraiment pas un langage simple, je fais de mon mieu, par moi même. roll

C'est bien d'avoir la tête sur les épaules comme ça, de plus ta remarque  sur le c est tout à fait pertinente, ça n'est pas un langage facile ou simple comme j'ai pu le lire sur le forum à maintes reprises...

Bzh a écrit :

J'essaye d'apprendre le C simplement par curiosité et par plaisir...

C'est la meilleur des raisons d'apprendre, et le C est un excellent langage, qui demande rigueur.

Bzh a écrit :

Le code source "md5.c" n'est pas de moi, enfin seulement la toute dernière fonction, et je remarque avec plaisir, que celle là, et bien tu n'y a pas touché. tongue

un petit peu quand même lol

Bzh a écrit :

Au moin une de correcte...

Faut pas désespéré ;-)

Bzh a écrit :

En tout cas, encore merci, j'étudie tout ça à tête reposé demain... big_smile

J'attends tes retours...

Hors ligne

#10 Le 27/06/2008, à 15:08

Bzh

Re : [PROG C] Variables globales et threads

Donc les nouvelles smile:

J'ai bien relu tout ton code et je vois très bien mes problèmes, avec un exemple sous les yeux, c'est nettement plus facile pour comprendre.

J'ai donc potassé différents cours sur la programmation distribuée ( dont cet excellent cours que je vous invite à régarder ).

Etant donné que je dois travailler sur une "petite base de données" et que chaque connexion d'un client DOIT pouvoir accèder à cette base de données, l'utilisation des forks rend la chose plus compliquée ( utilisation de MEMOIRE PARTAGEE, de TUBES etc... )

Si j'ai bien compris, l'avantage de créer un processus ( fork ) permet ( exactement comme le fait Apache dans sa version 2 ) de se proteger. Car si un des processus s'arrete brutalement ( dépassement de mémoires etc... ), les autres processus pourront terminer leur travail normalement. Ce qui n'est pas le cas pour un programme utilisant les threads.

Or dans mon cas, comme je dois utiliser une mémoire accèssible par chaque processus/threads, je vais plustot utiliser les threads en utilisant une variable globale.

Maintenant, si j'ai bien compris, il va faloir éviter les "collisions", par exemple attendre que le threads qui modifie la variable globale est bien terminé avant d'autoriser les autres à la lire etc...

Donc il va faloir bloquer les accès à la variable globale... Là je potasse encore ça, il me semble qu'un MUTEX le permet, ais-je bon ???

Merci de me dire si mon raisonnement ne tient pas la route... big_smile

Hors ligne

#11 Le 27/06/2008, à 15:24

nicolas.sitbon

Re : [PROG C] Variables globales et threads

Bzh a écrit :

J'ai donc potassé différents cours sur la programmation distribuée ( dont cet excellent cours que je vous invite à régarder ).

Mouais, le coup du programme C compiler avec g++, ça ne me dis rien de bon, de plus, le -D_REENTRANT ne sert plus rien de nos jours mais bon...

Bzh a écrit :

Si j'ai bien compris, l'avantage de créer un processus ( fork ) permet ( exactement comme le fait Apache dans sa version 2 ) de se proteger. Car si un des processus s'arrete brutalement ( dépassement de mémoires etc... ), les autres processus pourront terminer leur travail normalement. Ce qui n'est pas le cas pour un programme utilisant les threads.

Apache peut utiliser au moins 3 modèles différents de fonctionnements : un basé sur des processus, un sur des threads et un szur des évènements. Si un des processus s'arrète brutalement c'est qu'il y a un bug, il ne faut pas voir là un avantage des processus sur les threads mais bien un problème dans le code.

Bzh a écrit :

Or dans mon cas, comme je dois utiliser une mémoire accessible par chaque processus/threads, je vais plustot utiliser les threads en utilisant une variable globale.

OK mais soit certain qu'il n'y ait pas d'autres solutions avant de te lancer dans les variables globales..

Bzh a écrit :

Maintenant, si j'ai bien compris, il va faloir éviter les "collisions", par exemple attendre que le threads qui modifie la variable globale est bien terminé avant d'autoriser les autres à la lire etc...

exact, on parle de "race condition".

Bzh a écrit :

Donc il va faloir bloquer les accès à la variable globale... Là je potasse encore ça, il me semble qu'un MUTEX le permet, ais-je bon ???

On est en 2008, aujourd'hui on utilise les futex (sous linux du moins) (voir des sémaphores dans certains cas) après suivant les systèmes, il existe d'autres moyens de synchro.

Hors ligne

#12 Le 27/06/2008, à 16:11

Bzh

Re : [PROG C] Variables globales et threads

Yes merci ! smile

Une question toute bête, mais je veux être sur de la réponse.

char *fonctionTeste( char * buffer )
{
              //Allocation de mémoire
              char chaineDeCaractere[256];

             //Déroulement de la fonction

            //Fin de la fonction
            return buffer;
}

Lorsque cette fonction sera fini, l'espace mémoire allouée à "chaineDeCaractere" sera libérée naturellement. Cette fonction ne présente pas de danger apparant.

Par contre:

char *fonctionTeste( char * buffer )
{
              //Allocation de mémoire
              char *chaineDeCaractere = malloc( 256 * * sizeof *chaineDeCaractere );

             //Déroulement de la fonction

             //On oublie de libérer la mémoire 
             //free( chaineDeCaractere );

            //Fin de la fonction
            return buffer;
}

Dans ce cas là, la mémoire allouée à chaineDeCaractere ne sera pas libérée. Le fait que le pointeur soit déclaré comme variable appartenant à la fonction "fonctionTeste()" et que cette dernière se termine, la mémoire allouée ne sera pas libérée ?

Seul free() permet de libérer la mémoire allouée à un pointeur ?

Dernière modification par Bzh (Le 27/06/2008, à 16:14)

Hors ligne

#13 Le 27/06/2008, à 16:17

nicolas.sitbon

Re : [PROG C] Variables globales et threads

Bzh a écrit :

Seul free() permet de libérer la mémoire allouée à un pointeur ?

Exact, d'une manière générale, pour chaque malloc/calloc/realloc, il doit y avoir un free correspondant dans le code.

Hors ligne

#14 Le 27/06/2008, à 16:57

Bzh

Re : [PROG C] Variables globales et threads

J'en reviens aux threads/forks,

Si l'histoire du bug n'est pas un critère, quels sont les critères de choix entre l'utilisation de threads ou bien d'un forks ?

Hors ligne

#15 Le 27/06/2008, à 17:51

nicolas.sitbon

Re : [PROG C] Variables globales et threads

Pour moi, il n'y a plus beaucoup de raison valable d'utiliser des processus en lieu et place des threads, ne serait ce que pour les performances et la consommation mémoire.

Hors ligne