Essayer d’utiliser une queue pour gérer les messages clients sur un serveur

J’essaie d’écrire un serveur dans c qui permet aux clients connectés de se envoyer des messages. J’ai essayé de le faire en recevant le message, en le plaçant dans une queue et en demandant au processus qui gère la communication serveur-client (fonction dostuff) de délivrer ce message si le nom d’utilisateur correspond au message.

#include  #include  #include  #include  #include  #include  #include  /******Struct msg*********/ typedef struct msg { char dest [64]; char origin[64]; char text [256]; }msg; /*********Queue*********/ /*Queue - Linked List implementation*/ #include #include struct Node { msg *data; struct Node* next; }; struct Node* front = NULL; struct Node* rear = NULL; void Enqueue(msg *x) { struct Node* temp = (struct Node*)malloc(sizeof(struct Node)); temp->data =x; temp->next = NULL; if(front == NULL && rear == NULL){ front = rear = temp; return; } rear->next = temp; rear = temp; } void Dequeue() { struct Node* temp = front; if(front == NULL) { printf("Queue is Empty\n"); return; } if(front == rear) { front = rear = NULL; } else { front = front->next; } free(temp); } msg *Front() { if(front == NULL) { return 0; } return front->data; } void error(const char *msg) { perror(msg); exit(1); } int interpret(char *line, char username[]) { //printf("Ready to interpret: %s\n",line); /* char *command, *arg1 , *arg2,l[64]; msg *message; strcpy(l,line); command = strtok(l," "); if(strcmp(command, "/tell") == 0) { printf("The command was vaid!\n");//chegou aqui printf("Ready to interpret: %s\n",l); arg1 = strtok(NULL," "); printf("I got this far!"); arg2 = l + strlen(command) + strlen(arg1) + 2; //somamos dois por causa dos espaços message = (msg*)malloc(sizeof(msg)); //printf("I got this far!"); nao está a chegar aqui strcmp(message->dest, arg1); strcmp(message->origin, username); strcmp(message->text, arg2); Enqueue(message); printf("(%s -> %s) -%s- was placed on the queue",message->origin,message->dest,message->text); } else { printf("comando inválido"); } */ //this is temporary because there is an error with the code above which made the message not be correct msg *message; message = (msg*)malloc(sizeof(msg)); strcmp(message->dest, "dest"); strcmp(message->origin, "origin"); strcmp(message->text, "blahblahblah"); Enqueue(message); return 1; } void dostuff (int sock, char username[]) { int n, pid; char buffer[256], dest[64]; pid = fork(); while(1) { if(pid > 0) { bzero(buffer,256); n = read(sock,buffer,255); if (n < 0) error("ERROR reading from socket"); printf("Here is the full message: %s\n",buffer); //n = write(sock,"I got your message!\n",18); //if (n dest); if(strcmp(dest, username) == 0) { strcpy(buffer, Front()->text); Dequeue(); n = write(sock,buffer,strlen(buffer)); if (n < 0) error("ERROR writing to socket"); } } } } } int main(int argc, char *argv[]) { int sockfd, newsockfd, portno, pid , f; int userCount; socklen_t clilen; struct sockaddr_in serv_addr, cli_addr; if (argc < 2) { fprintf(stderr,"ERROR, no port provided\n"); exit(1); } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); bzero((char *) &serv_addr, sizeof(serv_addr)); portno = atoi(argv[1]); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))  0) { newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) error("ERROR on accept"); userCount++; sprintf(dname, "%d", userCount); pid = fork(); if (pid < 0) error("ERROR on fork"); if (pid == 0) { close(sockfd); dostuff(newsockfd, dname); exit(0); } else close(newsockfd); } } close(sockfd); return 0; } 

Le problème semble être que ce morceau de code censé supprimer des éléments de la queue:

 if(Front() != NULL) { strcpy(dest, Front()->dest); if(strcmp(dest, username) == 0) { strcpy(buffer, Front()->text); Dequeue(); n = write(sock,buffer,strlen(buffer)); if (n < 0) error("ERROR writing to socket"); } } 

N’est jamais en cours d’exécution Je n’ai jamais rien fait de tel auparavant, donc cette approche peut être totalement fausse. Si quelqu’un pouvait m’expliquer ce que je fais mal ou proposer une solution différente, ce serait formidable.

Vous ne comprenez pas bien comment les globals sont gérés après fork() .

Ils ne sont pas partagés les processus peuvent modifier leurs propres copies des variables. Ces modifications ne seront pas notifiées aux autres enfants / parents.

Ainsi, ce que vous essayez de faire avec Enqueue permet de modifier la copie locale du pointeur front mais les autres copies du pointeur avant de l’enfant ne sont pas mises à jour.

Réduire votre code au minimum:

 #include  #include  #include  #include  #include  #include  #include  #include  /******Struct msg*********/ typedef struct msg { char dest [64]; char origin[64]; char text [256]; }msg; /*********Queue*********/ /*Queue - Linked List implementation*/ #include #include struct Node { msg *data; struct Node* next; }; struct Node* front = NULL; struct Node* rear = NULL; void Enqueue(msg *x) { struct Node* temp = malloc(sizeof(struct Node)); temp->data =x; temp->next = NULL; if(front == NULL && rear == NULL) { front = rear = temp; printf("front: %p\n", (void *)(front)); printf("rear: %p\n" , (void *)(rear)); printf("temp: %p\n" , (void *)(temp)); return; } rear->next = temp; rear = temp; } void Dequeue(void) { struct Node* temp = front; if(front == NULL) { printf("Queue is Empty\n"); return; } if(front == rear) { front = rear = NULL; } else { front = front->next; } free(temp); } msg *Front(void) { if(front == NULL) { return 0; } return front->data; } void error(const char *msg) { perror(msg); exit(1); } int interpret(void) { //this is temporary because there is an error with the code above which made the message not be correct msg *message; message = (msg*)malloc(sizeof(msg)); strcpy(message->dest, "dest"); strcpy(message->origin, "origin"); strcpy(message->text, "blahblahblah"); Enqueue(message); return 1; } void dostuff (void) { pid_t pid; pid = fork(); if(pid > 0) { interpret(); } else { sleep(1); printf("\nfront: %p\n", (void *)(front)); } } int main(int argc, char *argv[]) { pid_t f, pid; f = fork(); if(f > 0) { pid = fork(); if (pid < 0) error("ERROR on fork"); if (pid == 0) { dostuff(); } } return 0; } 

La sortie sera

 front: 0x18371a0 rear: 0x18371a0 temp: 0x18371a0 root@mypc:~$ front: (nil) 

Utilisez des fils au lieu d’une fourchette. Commencez deux threads. Un pour écouter et un pour répondre.

Fork crée un nouveau processus de système d’exploitation qui partage le même code, mais les segments de données sont différents. Donc, ce que vous changez dans un processus ne sera pas vu dans un autre.