Pb avec l'utilisation des threads

Résolu/Fermé
dc.sara Messages postés 3 Date d'inscription samedi 8 décembre 2007 Statut Membre Dernière intervention 10 mars 2008 - 8 déc. 2007 à 19:48
pascal.barbier Messages postés 33 Date d'inscription samedi 8 décembre 2007 Statut Membre Dernière intervention 7 décembre 2008 - 9 déc. 2007 à 09:49
Bonjour à tous,
Je commence à travailler avec les threads et j'arrive pas bien à les manipuler.
Voici mon problème, je veux coder un simple programme qui fait agit comme suit:
- Un programme principal (main) joue le rôle d'un serveur qui se met à l'écoute des connexions entrantes. A l'acceptation d'une nouvelle connexion il stocke le contenue reçu dans un buffer.
- Un thread B qui manipule le buffer rempli par le main. Ce thread doit être en veille, s'il voit que la taille du buffer n'est pas nulle, il se réveille pour faire des traitements sur le buffer.

La main fonctionne très bien, mon problème c'est avec les threads. Le thread que j'ai codé ne fonctionne pas bien. A l'exécution, même si le buffer est vide, le programme affiche des hellos. Svp, pouvez vous m'aider à résoudre ce mystère … elle est ou la faute dans ma manipulation des threads … et si ce que j'ai fait ne tient pas.. Pouvez vous me dire comment faire ou me donnez un exemple de source qui fait ce que je voudrais faire.
Merci beaucoup.

Voici mon code

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#define MAXPENDING 5 /* Max connection requests */
#define BUFFSIZE 32

pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

void Die(char *mess) { perror(mess); exit(1); }

void *handle(void *buff){

char *buffer;
int i;
buffer = (char *) buff;
if(sizeof(buffer) != 0){
for(i=0; i < sizeof(buffer); i++){
printf(" hello %c\n",buffer[i]);
}
}
}


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

int serversock, clientsock;
struct sockaddr_in echoserver, echoclient;
char buffer[BUFFSIZE];
pthread_t hdl;
int i, received = -1;

if (argc != 2) {
fprintf(stderr, "USAGE: echoserver <port>\n");
exit(1);
}
/* Create the TCP socket */
if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
Die("Failed to create socket");
}
/* Construct the server sockaddr_in structure */
memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */
echoserver.sin_port = htons(atoi(argv[1])); /* server port */
/* Bind the server socket */
if (bind(serversock, (struct sockaddr *) &echoserver, sizeof(echoserver)) < 0) {
Die("Failed to bind the server socket");
}
/* Listen on the server socket */
if (listen(serversock, MAXPENDING) < 0) {
Die("Failed to listen on server socket");
}
/* Run until cancelled */

pthread_create(&hdl, NULL, &handle, (void *) &buffer);

while (1) {
unsigned int clientlen = sizeof(echoclient);
/* Wait for client connection */
if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient, &clientlen)) < 0) {
Die("Failed to accept client connection");
}
fprintf(stdout, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
/* Receive message */
if ((received = recv(clientsock, buffer, BUFFSIZE, 0)) < 0) {
Die("Failed to receive initial bytes from client");
}
/* Send bytes and check for more incoming data in loop */
close(clientsock);
}
}
Merci,
Sara

1 réponse

pascal.barbier Messages postés 33 Date d'inscription samedi 8 décembre 2007 Statut Membre Dernière intervention 7 décembre 2008 6
9 déc. 2007 à 09:49
Le problème n'est pas là où tu cherches.
Pour savoir si le buffer est vide, tu utilises if( sizeof(buffer) != 0 )
sizeof évalue la taille d'une variable et non pas son contenu
ici sizeof(buffer) renverra toujours 4 (la taille d'un pointeur en nombre d'octets).
remplaces par strlen(buffer) et ça devrait aller beaucoup mieux.

Sinon, personnellement j'aurais utilisé une autre logique :
tu as un process main qui écoute le port, accepte les connexions entrantes, lit les données et ensuite un process client qui traite les données.
Lorsque le client va faire son travail, le serveur revient à son accepte et risque de recevoir une autre connexion avant que le client n'ai terminé son job.

Pour éviter cela, j'aurais également confié au client la tâche de recevoir les données. La création de thread serait dans la boucle après accept.
La logique deviendrait :
Le serveur écoute le port et accepte les connexion. Pour chaque connexion entrante, il détache un nouveau process client.
Le process client recoit les données puis les traite. Quand il a terminé le traitement, il se suicide.
Ainsi tu es capable de traiter plusieurs connexions simultanées. La logique est plus simple à mettre en oeuvre parce qu'il n'y a pas de buffer entre le client et le serveur.

Attention : dans ce cas, il faut un buffer pour chaque client.
0