thread et sockets

thread et sockets - C - Programmation

Marsh Posté le 17-05-2010 à 10:31:07    

Bonjour à tous,
 
Je suis en train de faire un client/serveur. Dans le serveur, j'aimerais y mettre 2 threads par connexion: l'une fait un fread() et attend des données du client (signaux), pendant que l'autre fait un fwrite() et envoie des données au client (évènements).
 
Le problème, c'est que la connexion, une socket réouverte avec fdopen(), n'est pas du tout thread safe: lorsque j'essaye de faire un fread() en même temps qu'un fwrite() le signal SIGABORT est levé au moment où le flux est fermé avec fclose().
 
J'ai essayé de dupliquer le flux d'entrée avec dup(), mais là encore, dup() ne fait qu'un alias, et fwrite() semble n'avoir aucun effet: les données ne sont pas reçues par le client, et ça replante avec SIGABORT. Il semble que celà ne devrait pas fonctionner car le flux créé par dup() partage par exemple la même position de tête de lecture.
 
Quelqu'un peut-t-il m'aider? Merci.
 
Code de la thread principale (fread) :

Code :
  1. // open connexion
  2.   FILE* f=fdopen(sock, "r+" );
  3.   if(!f)
  4.   {
  5.     perror(NULL);
  6.     printf("Cannot turn the socket into a stream\n" );
  7.     close(sock);
  8.     return 0;
  9.   }
  10.   // ...
  11.   // start event thread
  12.   EventThread event_thread;
  13.   if(!event_thread.start(f)) // pthread_create
  14.   {
  15.     printf("Error starting event thread\n" );
  16.     fclose(f);
  17.     return 0;
  18.   }
  19.   // ...
  20.   while(1)
  21.   {
  22.     // read signal
  23.     char c;
  24.     if(fread(&c, 1, 1, f)!=1) break;
  25.     bool quit=0;
  26.     switch(c)
  27.     {
  28.       case 0:
  29.       {
  30.         printf("signal received\n" );
  31.         event_thread.enqueue(EVT_TEST);
  32.       } break;
  33.       case -1: quit=1; break;
  34.       default: break;
  35.     }
  36.     if(quit) break;
  37.   }
  38.   // ...
  39.   event_thread.stop(); // send EVT_QUIT event + pthread_join
  40.   fclose(f);


 
Code de la thread évènementielle (fwrite) :

Code :
  1. static void* event_thread(void* arg)
  2.   {
  3.     EventThread* event_thread=(EventThread*)arg;
  4.     while(1)
  5.     {
  6.       // wait for an event
  7.       Event* event=event_thread->dequeue();
  8.       bool quit=0;
  9.       switch(event->type)
  10.       {
  11.         case EVT_QUIT:
  12.         {
  13.           quit=1;
  14.         } break;
  15.         case EVT_TEST:
  16.         {
  17.           printf("create event\n" );
  18.           char c=20;
  19.           if(fwrite(&c, 1, 1, event_thread->f)!=1) { quit=1; break; }
  20.           printf("event created\n" );
  21.         } break;
  22.         default: break;
  23.       }
  24.       delete event;
  25.       if(quit) break;
  26.     }
  27.     return 0;
  28.   }


Message édité par nargy le 17-05-2010 à 11:34:21
Reply

Marsh Posté le 17-05-2010 à 10:31:07   

Reply

Marsh Posté le 17-05-2010 à 14:58:48    

la seule façon que j'ai trouvé, c'est de passer en mode asynchrone non bloquant, d'utiliser un mutex pour accéder à la connexion, et d'utiliser select() pour faire patienter le thread en lecture.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed