Ciao a tutti,
ho un problema con un programma che sto sviluppando riguardante la comunicazione tra i processi figli.
ho estratto una parte ridotta del programma (dato che il mio problema è strettamente di comunicazione) per farvi vedere un esempio in cui il client deve semplicemente ottenere la lista dei file presenti sul server.
per necessità questa operazione va fatta gestire da child mentre i rispettivi parent tornano rispettivamente uno in ascolto e l'altro nel menù.

in due parole, a livello comunicativo:
-il client crea il socket del processo padre, seleziona l'azione e la invia al processo padre del server.
-il processo padre del server, ricevuta l'azione crea la socket con una porta random libera che il futuro figlio utilizzerà inviandone il numero al client.
-il client creerà a sua volta la socket del figlio associata alla porta appena ricevuta.
-ambo i lati creano i figli, chiudono le socket del padre e svolgono lo scambio dei dati mentre i padri tornano ai loro compiti principali (il server in attesa, il client nel menu).

il codice non è pulitissimo e ha parecchie stampe di controllo perchè ho fatto molte prove ma non riesco proprio ad uscirne...

posto il codice del client qui mentre il server e l'header nel prossimo messaggio (problemi col numero massimo di caratteri)

codice:
#include "header.h"

int psockfd, csockfd, scritti, letti, num_pack, mod_pack, i;
unsigned int paddrlen, caddrlen;
char azione, *ultimo, *ultimo_lista;
char nomefile[MAXLINE], recvline[MAXLINE + 1], list_file[MAXLINE] =  "Lista file server";
int ricporta;
struct sockaddr_in psrvrddrss;
struct sockaddr_in csrvrddrss;

struct Pacchetto 
{
	int num_seq;
	char bit_string[MAXLINE];
} ricevuto;

DIR *dp;
FILE *filep, *fopen(), *list_fd;

int main (int argc, char** argv)
{
	//Controllo numero argomenti
	if (argc != 2)
	{
		perror("Indirizzo del server ip mancante.\n");
		exit(1);
	}
	
	//Creazione del socket del processo padre
	if ((psockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	{
		perror("Errore nella creazione del socket.\n");
		exit(1);
	}
	
	paddrlen = sizeof(psrvrddrss);
	//Svuotamento srvraddrss
	memset((void *)&psrvrddrss, 0, sizeof(psrvrddrss));
	
	//Assegnazione del tipo di indirizzo
	psrvrddrss.sin_family = AF_INET;
	
	//Assegnazione porta del servar
	psrvrddrss.sin_port = htons (SERV_PORT);
	
	/*Assegnazione dell'indirizzo del server tramite riga di comando
	 l'indirizzo è una stringa e va convertito in network byte order*/
	if (inet_pton(AF_INET, argv[1], &psrvrddrss.sin_addr) <= 0)
	{
		fprintf(stderr, "Errore in inet_pton per %s.\n", argv[1]);
		exit(1);
	}
	
	for ( ; ; )
	{
		//Menu di scelta azione
		printf("Digitare l per ottenere una lista dei file disponibili,\n");
		scanf("%c", &azione);
		getchar();
		
		//Trasmissione al server l'azione scelta dall'utente
		if ((scritti = sendto(psockfd, &azione, 1, 0, (struct sockaddr *)&psrvrddrss, sizeof(psrvrddrss))) < 0)
		{
			perror("Errore nella scrittura.\n");
			exit(1);
		}
		
		//Ricezione numero di porta del server
		if(letti = recvfrom(psockfd, (int*)&ricporta, 4, 0, (struct sockaddr *)&psrvrddrss, &paddrlen) < 0)
		{
			perror("Errore in lettura. \n");
			exit(1);
		}
		
		//Creazione del socket del processo figlio
		if ((csockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
		{
			perror("Errore nella creazione del socket.\n");
			exit(1);
		}
		
		caddrlen = sizeof(csrvrddrss);
		//Svuotamento srvraddrss
		memset((void *)&csrvrddrss, 0, sizeof(csrvrddrss));
		
		//Assegnazione del tipo di indirizzo
		csrvrddrss.sin_family = AF_INET;
		
		//Assegnazione porta del servar
		csrvrddrss.sin_port = ricporta;
		
		/*Assegnazione dell'indirizzo del server tramite riga di comando
		 l'indirizzo è una stringa e va convertito in network byte order*/
		if (inet_pton(AF_INET, argv[1], &csrvrddrss.sin_addr) <= 0)
		{
			fprintf(stderr, "Errore in inet_pton per %s.\n", argv[1]);
			exit(1);
		}
		
		//Creazione processo figlio
		pid_t pid = fork();
		
		//Controllo di errore pid
		if(pid < 0) printf("Errore nella creazione del processo figlio.\n");
		
		//Codice processo figlio
		if(pid == 0)
		{
			printf("Creato il figlio: %d.\n", getpid());
			//Chiusura socket del padre
			close(psockfd);
			
			//Menu di scelta
			switch (azione)
			{
					//Lista file
				case 'l': case 'L':
					
					printf("Richiedo la lista dei file disponibili...\n");
					
					//Apertura del file in scrittura, binario, se il file non esiste viene creato
					list_fd = fopen(list_file, "w+b");
					
					
					/*Ricezione del numero di pacchetti da ricevere dal server*/
					if(letti = recvfrom(csockfd, (int*)&num_pack, 4, 0, (struct sockaddr*)&csrvrddrss, &caddrlen) < 0)
					{
						perror("Errore in lettura.\n");
						exit(1);
					}		
					
					//Ricezione delle dimensioni dell'ultimo pacchetto
					if(letti = recvfrom(csockfd, (int*)&mod_pack, 4, 0, (struct sockaddr*)&csrvrddrss, &caddrlen) < 0)
					{
						perror("Errore in lettura.\n");
						exit(1);
					}
					
					if(mod_pack > 0)
					{
						//Stampe di controllo
						printf("Il numero di pacchetti da ricevere è: %d.\n", num_pack);
						printf("La dimensione dell'ultimo pacchetto è: %d.\n", mod_pack);
					}
					else
					{
						printf("Il numero di pacchetti da ricevere è: %d.\n", num_pack);
						mod_pack = MAXLINE;	
					}
					
					//Azzeramento della memoria contenente i campi della struttura
					memset((void *)&ricevuto, 0, sizeof(ricevuto));
					
					//Ricezione pacchetti e copia nel file, tranne l'ultimo
					for (i=0; i < num_pack - 1; i++)
					{
						
						printf("Sono entrato nel ciclo.\n");
						
						if (letti = recvfrom(csockfd, (void *)&ricevuto, sizeof(ricevuto), 0, (struct sockaddr *)&csrvrddrss, &caddrlen) != sizeof(ricevuto))
						{
							perror("Errore in lettura.\n");
							exit(1);
						}
						
						printf("Ho ricevuto il pacchetto.\n");
						//Scrittura del pacchetto nel file
						fwrite(ricevuto.bit_string, (MAXLINE*sizeof(char)), 1, list_fd);
						printf(" %d / %d pacchetti ricevuti | Numero di sequenza pacchetto: %d.\n", i+1, num_pack, ricevuto.num_seq); //Una parte della stampa è di controllo
						
						//Pulitura dei buffer input
						fflush(stdin);
					}
					
					printf("Dopo il ciclo.\n");
					
					//Allocazione di memoria per l'ultimo pacchetto
					ultimo_lista = (char*) malloc(mod_pack);
					
					//Ricezione dell'ultimo pacchetto
					if(letti = recvfrom(csockfd, ultimo_lista, mod_pack, 0, (struct sockaddr*)&csrvrddrss, &caddrlen) < 0)
					{
						perror("Errore in lettura.\n");
						exit(1);
					}
					
					fwrite(ultimo_lista, (mod_pack), 1, list_fd);
					printf(" %d / %d pacchetti ricevuti. Numero di sequenza: %d.\n", i+1, num_pack, ricevuto.num_seq + 1);
					
					fclose(list_fd);
					printf("Lista ricevuta con successo.\n");
					fflush(stdout);
					break;
					
					//Exit
					case 'e' : case 'E':
					printf("Chiusura programma.\n");
					break;
					default:
					printf("Il comando digitato è errato.\n");
			}
			close(csockfd);
			exit(EXIT_SUCCESS);
		}
		//Codice processo padre
		else
		{
			//Chiusura socket del figlio
			close(csockfd);
			
			//Eliminazione degli zombie
			waitpid(-1, NULL, WNOHANG);
			
			//Caso EXIT
			if(azione == 'e' || azione == 'E') return(0);
		}
	}
	exit(0);									
}