Threads, fonction et mutex ?

Résolu
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010 - 5 mai 2010 à 12:14
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010 - 10 mai 2010 à 19:37
bonjour à tout le monde

dans mon projet de créer un tchat il faut que j'applique sur le client un thread qui exécute une autre fonction qui doit lire les messages.

Hors je doit mettre la fonction en dehors de "main" et la fonction pour lire les messages ne reconnais plus aucune variables ni même les sockets.
Comment puis-je faire ? utiliser les mutex ? de plus je ne sais pas trop comment mettre en place cela surtout que le thread gère une boucle infinie.

voila déjà se que j'ai fait pour le moment. (je vous ais mis seulement les parties qui posent problème car sinon c'est trop long)

void* message(void* data);
 
 
int main(int argc, char *argv[])
{
 
/*
 
..............Variables et socket................
 
*/
 
pthread_t thread;/* crée un thread */
pthread_create(&thread, NULL, message, NULL);/* Permet d'exécuter le fonction message en parallèle */
 
while (1)
{ /* début boucle wirthe */
 
system("CLS");
 
printf("\n%s : ", pseudo);
 
    fgets(chaine, sizeof chaine, stdin);
    clean(chaine);
    
   
    snprintf(buffer, sizeof(buffer), "%s : %s \n", pseudo, chaine);
    
   send(s, buffer, strlen(buffer), 0); 
 
    if  ( strcmp( chaine, "exit" ) == 0 )
    { 
 
       goto fin; /* je sais goto c'est pas bien mais c'est juste pour faire les testes en attendant :p */
        
    }  
} /* fin boucle writhe */  
pthread_join(thread, NULL);
 
/*
.........fermeture socket..............
*/
 
return o;
}
 
void* message(void* data); /* Fonction de réception de message */
      {
   while(1)  /* boucle de réception des messages */
   {
 memset(buffer, '\0', sizeof(buffer));
 n = recv(s, buffer, sizeof(buffer) - 1, 0);
 printf("%s\n",buffer);
   }
      } /* Finc de la fonction de réception des messages */        
 


Merci.

________________________________________________________________
j'ai 16 ans et j'aime l'informatique, surtout les programmes

11 réponses

fregolo52 Messages postés 1114 Date d'inscription mercredi 15 juin 2011 Statut Membre Dernière intervention 6 mai 2021 4
10 mai 2010 à 09:43
ton message de samedi, ton revc et send me semble correct.

Sinon, tu es perdu, donc oublies les structures, surtout que tu en a pas besoin.

dans le main :
pthread_create(&thread, NULL, message, (void *)&s);


dans message :
void* message(void* data) /* Fonction de réception de message */
{
      
char buff[1024];
SOCKET *s = (SOCKET *)data;
char buff[1024];
int n; // ton main s'en fout de n
recep *pStruct = (SOCKET *)data;

while(1)  /* boucle de réception des messages */
   {
 memset(buff, '\0', sizeof(buff)); 
 n = recv(*s, buff, sizeof(buff) - 1, 0);
 printf("%s\n",buff);

   }
  
} /* Finc de la fonction de réception des messages


J'ai pas fait gaffe, ce code est le code du client ? Si c'est le serveur, ca ne marche pas. Va voir cet ex.
3
fregolo52 Messages postés 1114 Date d'inscription mercredi 15 juin 2011 Statut Membre Dernière intervention 6 mai 2021 4
5 mai 2010 à 13:37
tu dois passer la socket en paramètre de ton thread :

dans main :

SOCKET s;
// init sock
...
pthread_t thread;
pthread_create(&thread, NULL, message, (void *)&s);


dans ton thread :
void* message(void* data) {
SOCKET *s = (SOCKET *)data; // attention c'est un pointeur
....
}
0
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010
5 mai 2010 à 21:14
Merci, ça marchais presque.

alors voila la fonction crée
void* message(void* data) /* Fonction de réception de message */
{

SOCKET *s = (SOCKET *)data;
char *buffer;
int *n;

while(1)  /* boucle de réception des messages */
   {
 memset(buffer, '\0', sizeof(buffer));
 n = recv(s, buffer, sizeof(buffer) - 1, 0);
 printf("%s\n",buffer);
   }
  
} /* Finc de la fonction de réception des messages */     


erreur:
C:\Dev-Cpp\chatbox_real\Client\main.c In function `message':

337 C:\Dev-Cpp\chatbox_real\Client\main.c [Warning] passing arg 1 of `recv' makes integer from pointer without a cast

337 C:\Dev-Cpp\chatbox_real\Client\main.c [Warning] assignment makes pointer from integer without a cast


pour pouvoir faire SOCKET *s = (SOCKET *)data; il faut donc ajouter "&s" à la place de NULL dans le thread. Comment ajouter char *buffer; et
int *n; ?

malgré ces erreurs le client compile mais je ne voit pas la chaine que j'écris mais elle est bien envoyé au serveur. (je pense que c'est le faite que j'utilise des boucle infini non ? )

________________________________________________________________
j'ai 16 ans et j'aime l'informatique, surtout les programmes
0
fregolo52 Messages postés 1114 Date d'inscription mercredi 15 juin 2011 Statut Membre Dernière intervention 6 mai 2021 4
6 mai 2010 à 08:25
si tu veux passer plusieurs paramètres il va falloir les mettre dans une structure et passer cette structure au thread.

s est un pointeur, donc il ne faut pas oublier le '*' :
recv(*s, .....);
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010
6 mai 2010 à 17:59
salut alors j'ai fait la structure:
struct MaStructure 
      {
       SOCKET *s;
       char *buffer;
       int *n;
       };


mais je n'ai pas réussie en l'ajouter dans les paramètre du thread j'avais essayé de cette façon sans résulta.

pthread_create(&thread, NULL, message, (struct *)&MaStructure);


j'ai 16 ans et j'aime l'informatique, surtout les programmes
0
fregolo52 Messages postés 1114 Date d'inscription mercredi 15 juin 2011 Statut Membre Dernière intervention 6 mai 2021 4
7 mai 2010 à 10:11
c'est pas beau ce que tu as fait !!!

un truc simple, mais y'a bcp mieux.

struct MaStructure 
      {
       SOCKET s;
       char buffer[mets ici un taille max];
       int n;
       };


MaStructure datastruct;
datastruct.s = ...;
....
pthread_create(&thread, NULL, message, (struct *)&datastruct);


void* message(void* data) /* Fonction de réception de message */
{

MaStructure *pStruct = (SOCKET *)data;

while(1)  /* boucle de réception des messages */
   {
 memset(pStruct->buffer, '\0', sizeof(pStruct->buffer)); // là j'ai un doute sur le sizeof
 pStruct->n = recv(pStruct->s, pStruct->buffer, sizeof(pStruct->buffer) - 1, 0);
 printf("%s\n",pStruct->buffer);
   }
  
} /* Finc de la fonction de réception des messages */   
0
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010
7 mai 2010 à 11:55
ok mais j'ai 2 questions.

est-ce que je peut placer
MaStructure datastruct;
datastruct.s = ...;

n'importe où dans main ? ou ça a une place bien précise ?

et que dois-je mettre à la place des trois petit point ?
j'avais pensé à ça: datastruct.s = *((struct MaStructure*)data);
Mais je pense pas que ça fonctionnera

Merci de m'aider en tout cas :)



j'ai 16 ans et j'aime l'informatique, surtout les programmes
0
fregolo52 Messages postés 1114 Date d'inscription mercredi 15 juin 2011 Statut Membre Dernière intervention 6 mai 2021 4
7 mai 2010 à 12:20
bah tu dois placer la déclaration où tu veux mais bien sûre avant le while.

non, dans le main, dans datastruct.s tu mets s (le même s du send de la boucle while) :
datastruct.s = s;

mais en relisant ton 1er message, je ne vois pas l'intérêt de la structure.

ton main et ton thread message peuvent (et meme, doivent) gérer leur propre buffer. Vu que chacun fait son printf.
0
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010
8 mai 2010 à 15:00
ok donc je doit mettre ensuite par exemple
MaStructure datastruct;
datastruct.s =  s;
datastruct.b = buffer;
datastruct.n = n;


pour gérer leur propre buffer donc sur le client on envoi la chaine + pseudo dans le buffer qui s'envoie au serveur
le serveur lit le buffer et le renvoi au client mais j'avais pensé faire comme ça: (sa compile mais je ne sais pas si ça marche car j'ai pas terminer les structures)

Serveur
while(1)
   {
 memset(buffer, '\0', sizeof(buffer));
 n  = recv(s_client, buffer, sizeof(buffer) - 1, 0);
 printf("%s\n",buffer); 
 strcpy(buff, ("%s\n", buffer)); /*copi dans buff le buffer */
 send(s_client, buff, (int)strlen(buff), 0); /*envoi le buff au client */
   }



Client (sans les structures)
while(1)  /* boucle de réception des messages */
   {
 memset(buff, '\0', sizeof(buff)); // là j'ai un doute sur le sizeof
 n = recv(s, buff, sizeof(buff) - 1, 0);
 printf("%s\n",buff);

   }


j'ai 16 ans et j'aime l'informatique, surtout les programmes
0
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010
9 mai 2010 à 15:23
Bon je crois que je suis un peu perdu

je récapitule.

j'ai fait le structure

struct recep   
      {
       SOCKET *s; //je met des pointeurs car elles sont déjà dans main
       int *n;
      };





je ne vois franchement pas à quoi ces commandes sèvrent
MaStructure datastruct;
datastruct.s = ...; 
....


voici le code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <string.h>
#include <winsock2.h>
#include 

static void purger(void)
{
    int c;

    while ((c = getchar()) != '\n' && c != EOF)
    {}
}

static void clean (char *chaine)
{
    char *p = strchr(chaine, '\n');

    if (p)
    {
        *p = 0;
    }

    else
    {
        purger();
    }
}
/*------------------------------------------*/
static void purgera(void)
{
    int d;

    while ((d = getchar()) != '\n' && d != EOF)
    {}
}

static void cleaner (char *pseudo)
{
    char *q = strchr(pseudo, '\n');

    if (q)
    {
        *q = 0;
    }

    else
    {
        purgera();
    }
}

void* message(void* data);


int main(int argc, char *argv[])
{
    
    char chaine[5000];
    char pseudo[30];


/*
----------------------------------------------------
*/



WSADATA wsaData;

    if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
        fprintf(stderr, "La fonction WSAStartup a echoue.\n");
    else
    {
        SOCKET s;
        
        s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s == INVALID_SOCKET)
            fprintf(stderr, "La fonction socket a echoue.\n");
        else
        {
            SOCKADDR_IN server;
            
            server.sin_family       = AF_INET;
            server.sin_addr.s_addr  = inet_addr("127.0.0.1");
            server.sin_port         = htons(5050);
            memset(&server.sin_zero, '\0', sizeof(server.sin_zero));
            
            if (connect(s, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR)
                fprintf(stderr, "La fonction connect a echoue.\n");
            else
            {
                char buffer[1024];
                
                int n;
                
                n = recv(s, buffer, sizeof(buffer) - 1, 0); 
                
                if (n != SOCKET_ERROR)
                {
                    buffer[n] = '\0';
                    printf("%s", buffer);
                    /*-----------------------------------------------*/
                    
                    struct recep 
      {
       SOCKET *s;
       int *n;
      };

                    system("CLS");
                    printf("Choisissez un pseudo visible par les autre membres.\n\n"); 

    printf("choix ? ");
    
    fgets(pseudo, sizeof pseudo, stdin);
    clean(pseudo);
    
printf("\n\nBienvenu %s\n", pseudo);
getch();

system("CLS"); 
                    
                    /*-----------------------------------------------*/
                          
  
  
pthread_t thread;/* crée un thread */
pthread_create(&thread, NULL, message, (void *)&datastruct);/* Permet d'exécuter le fonction message en parallèle, une erreur ici */

int compteur;
for (compteur = 0 ; compteur < 2 ; compteur++) //obligé d'employer une boucle ici car la copie du buffer ne marhcait pas
   {
   snprintf(buffer, sizeof(buffer), "user: %s, rejoint la conversation.", pseudo);
   send(s, buffer, strlen(buffer), 0);
   }

while (1)
 { /* début boucle wirthe */

printf("\n%s : ", pseudo);
 
    fgets(chaine, sizeof chaine, stdin);
    clean(chaine);
    
   
    snprintf(buffer, sizeof(buffer), "%s : %s ", pseudo, chaine);
    
   send(s, buffer, strlen(buffer), 0); 

    if  ( strcmp( chaine, "exit" ) == 0 )
    { 

       goto fin; /* je sais goto c'est pas bien mais c'est juste pour faire les testes en attendant :p */
        
    }  
 } /* fin boucle writhe */  

 

pthread_join(thread, NULL);

   

           fin: 
                    send(s, "Au revoir\n", (int)strlen("Au revoir\n"), 0); 
                    
                    
                }
                
                shutdown(s, SD_SEND);
            }
            
            closesocket(s);
        }
        
        WSACleanup();
    }
    
    return 0;
}




void* message(void* data) /* Fonction de réception de message */
{
      
char buff[1024];
recep *pStruct = (SOCKET *)data;

while(1)  /* boucle de réception des messages */
   {
 memset(buff, '\0', sizeof(buff)); 
 pStruct->n = recv(pStruct->s, buff, sizeof(buff) - 1, 0);
 printf("%s\n",buff);

   }
  
} /* Finc de la fonction de réception des messages




les erreurs:
C:\Dev-Cpp\chatbox_real\Client\main.c In function `main':

275 C:\Dev-Cpp\chatbox_real\Client\main.c `datastruct' undeclared (first use in this function)
(Each undeclared identifier is reported only once for each function it appears in.)


C:\Dev-Cpp\chatbox_real\Client\main.c In function `message':

336 C:\Dev-Cpp\chatbox_real\Client\main.c `recep' undeclared (first use in this function)
336 C:\Dev-Cpp\chatbox_real\Client\main.c `pStruct' undeclared (first use in this function)

0
cs_Adict Messages postés 28 Date d'inscription vendredi 1 janvier 2010 Statut Membre Dernière intervention 10 août 2010
10 mai 2010 à 19:37
Merci beaucoup j'y vois déjà mieux
il ne me reste plus que 3 problèmes à résoudre et je pense pouvoir finaliser mon tchat

Merci encore


j'ai 16 ans et j'aime l'informatique, surtout les programmes
0
Rejoignez-nous