Essayer de diriger des données d’un serveur de processus enfant vers son processus parent

Je travaille sur une tâche pour ma classe de systèmes dissortingbués. Je suis un étudiant de master en CS, mais ma spécialité en programmation est .NET et je travaille sur un projet qui nécessite des connaissances Unix relativement impliquées, ce qui me fait chuter.

L’affectation met en œuvre une API de protocole de canal de vidage. Donc, je coder une petite bibliothèque de fonctions que d’autres applications peuvent implémenter pour utiliser la communication flush channel. Je l’ai configuré de manière à ce que lorsque la fonction init est appelée, un processus enfant soit utilisé comme serveur pour les messages entrants. L’enfant communique avec le processus parent en envoyant les données entrantes au parent via un canal.

Cela fonctionne correctement si les messages sont envoyés et reçus un par un; par exemple,

envoyer -> recevoir -> envoyer -> recevoir -> etc.

Cependant, si plusieurs messages sont envoyés avant de faire, reçoit; par exemple,

envoyer -> envoyer -> envoyer -> recevoir

alors ça se gâte. Plus précisément, le premier message est reçu correctement, mais lorsque je vais recevoir le deuxième message, le programme se bloque et doit être supprimé. J’ai fait beaucoup de recherches en ligne et je me suis débrouillé pendant des heures, mais je n’ai pas beaucoup progressé.

Le programme dans son ensemble est beaucoup trop vaste pour être affiché ici, mais voici les éléments les plus pertinents. Voici la partie où le serveur va et reçoit des messages. Notez la ligne

write (fd [1], buffer, (strlen (buffer) +1));

– Je pense que c’est un bon candidat pour être la source du problème ici, mais je ne sais pas trop quoi faire différemment. (Essayé fwrite () et ça n’a pas marché du tout.)

fd = malloc(2 * sizeof(int)); int nbytes; if (pipe(fd) < 0) { perror("Could not create pipe"); return -1; } pID = fork(); if (pID < 0) { perror("Failed to fork"); return -1; } else if (pID == 0) { // child close(fd[0]); // close input side of pipe int cc; int fsize; struct sockaddr_in from; int serials[500]; int i; for (i = 0; i < 500; i++) serials[i] = 0; char buffer[2048]; while (1) { fsize = sizeof(from); cc = recvfrom(socketNo, buffer, 2048, 0, (struct sockaddr*)&from, &fsize); if (cc < 0) perror("Receive error"); datagram data = decodeDatagram(buffer); if (serials[data.serial] == 0) { write(fd[1], buffer, (strlen(buffer)+1)); serials[data.serial] = 1; } } } else { // parent close(fd[1]); // close output side of pipe return 0; } 

(Le tableau “serials” sert à ne pas transmettre les messages répétés, car les messages sont envoyés plusieurs fois pour améliorer la fiabilité. Je sais qu’une taille fixe pour ce tableau n’est pas une bonne pratique, mais les tests pour cette affectation n’envoient pas autant de messages. c’est OK dans ce contexte.)

Le début de la fonction de réception ressemble à ceci:

 int fRecv(int* id, char* buf, int nbytes) { checkDatagramTable(*id); char* tbuf = malloc((nbytes + 9) * sizeof(char)); int rbytes = read(fd[0], tbuf, nbytes + 9); 

Le “+9” est destiné à recevoir des informations supplémentaires qui sont empaquetées avec le message à envoyer, pour un classement de canal affleurant. C’est également un domaine plutôt sommaire, mais l’allocation de plus d’espace pour être plus sûr n’a pas aidé le problème.

Je sais qu’il y a beaucoup de choses superflues ici, des références à d’autres fonctions, etc. Mais le problème réside sûrement dans la manière dont je transmets les données, de sorte que la source de mon problème devrait se trouver quelque part.

Merci d’avance pour votre aide; c’est vraiment apprécié.

Cela semble suspect. (qu’y a-t-il dans les paquets? Ils pourraient être binarys) Où est la définition du datagramme?

 fsize = sizeof(from); cc = recvfrom(socketNo, buffer, 2048, 0, (struct sockaddr*)&from, &fsize); if (cc < 0) perror("Receive error"); datagram data = decodeDatagram(buffer); if (serials[data.serial] == 0) { write(fd[1], buffer, (strlen(buffer)+1)); // <-- ???? serials[data.serial] = 1; } 

J'essaierais plutôt:

  write(fd[1], buffer, cc); 

METTRE À JOUR:

Si le message n'est pas terminé par null, vous devrez le terminer explicitement:

  (if cc == 2048) cc -= 1; buffer [cc] = '\0'; // <<-- datagram data = decodedatagram(buffer); ... 

En outre, il est conseillé d'utiliser "sizeof buffer" au lieu de "2048".

UPDATE2: Vous pouvez tester si les chaînes dans les paquets sont vraiment terminées par:

  unsigned pos; cc = recvfrom(socketNo, buffer, 2048, 0, (struct sockaddr*)&from, &fsize); if (cc < 0) perror("Receive error"); for pos=0; pos < cc; pos++) { if (buff[pos] == 0) break; } switch (cc-pos) { case 0: fprintf (stderr, "No nul byte found in packet: I lose!\n" ); break; default: fprintf (stderr, "Spurious nul byte found in the middle of packet\n" ); case 1: break; } datagram data = decodeDatagram(buffer); if (serials[data.serial] == 0) { write(fd[1], buffer, cc); serials[data.serial] = 1; }