#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
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.
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!
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?
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.
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.
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é.
Au moin une de correcte...
En tout cas, encore merci, j'étudie tout ça à tête reposé demain...
Hors ligne
#9 Le 27/06/2008, à 06:58
- nicolas.sitbon
Re : [PROG C] Variables globales et threads
Je ne sais comment te remercier.
Tu n'as pas à le faire, je le fais par pûr plaisir.
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.
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...
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.
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é.
un petit peu quand même
Au moin une de correcte...
Faut pas désespéré ;-)
En tout cas, encore merci, j'étudie tout ça à tête reposé demain...
J'attends tes retours...
Hors ligne
#10 Le 27/06/2008, à 15:08
- Bzh
Re : [PROG C] Variables globales et threads
Donc les nouvelles :
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...
Hors ligne
#11 Le 27/06/2008, à 15:24
- nicolas.sitbon
Re : [PROG C] Variables globales et threads
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...
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.
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..
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".
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 !
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
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