Direi di rivedere i campi "len" di ogni sendto/recvfrom. Ricorda che il campo sin_port di sockaddr_in è di tipo unsigned short, quindi con ogni probabilità è su 2 byte, non 4 (per evitare certi tipi di problemi, comunque, basta che nel campo len ci scrivi "sizeof(nome_struct.sin_port)").
Inoltre, considera l'ultima sendto del server (quella che ti dà problemi): hai scritto che il numero di byte da inviare è 2, ma con ogni probabilità gli int col tuo compilatore sono di 4 byte (ancora una volta, basta scrivere sizeof(int) o sizeof(sfiglio) per non avere problemi). E altro problema, forse ancora più serio: considera l'ultima recvfrom del server (la prima del processo figlio): quale valore ha caddrlen? Non mi pare gli assegni un valore da nessuna parte... scrivi qualche riga di codice prima "caddrlen = sizeof(cclntddrss);". Anche i cast a "int *" nel caso di sin_port vanno rivisti...
Per farla breve, questi a me funzionano (nota soprattutto l'assegnazione del valore a caddrlen prima della fork() nel server)
(e per carità, elimina quella serie di variabili globali che non si possono guardare, oltre al fatto di essere inutili in quel caso)
server
clientcodice:#include "header.h" int psockfd, csockfd, pletti, cletti, pscritti, cscritti, lpadre = 0, sfiglio = 0, lfiglio = 0; unsigned int paddrlen, caddrlen; struct sockaddr_in temp; struct sockaddr_in pclntddrss; struct sockaddr_in cclntddrss; int main() { //Creazione del socket del processo padre if((psockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Errore nella creazione del socket.\n"); exit(1); } //Azzeramento dello spazio di memoria con l'indirizzo della variabile clntddrss memset((void *)&pclntddrss, 0, sizeof(pclntddrss)); //Assegnazione del tipo di indirizzo pclntddrss.sin_family = AF_INET; //Connessioni accettate su qualunque interfaccia di rete pclntddrss.sin_addr.s_addr = htonl(INADDR_ANY); //Assegnazione del numero di porta pclntddrss.sin_port = htons(SERV_PORT); //Assegnazione dell'indirizzo al socket /*nella prima parte struct sockaddr... fino alla virgola, cambia il tipo della variabile clntddrss*/ if ((bind(psockfd, (struct sockaddr *)&pclntddrss, sizeof(pclntddrss))) < 0) { perror("Errore in bind.\n"); exit(1); } printf("Il padre ha la porta: %d.\n", ntohs(pclntddrss.sin_port)); paddrlen = sizeof(pclntddrss); pletti = recvfrom(psockfd, (int*)&lpadre, 4, 0, (struct sockaddr*)&pclntddrss, &paddrlen); if( pletti < 0) { perror("Errore in lettura.\n"); exit(1); } printf("Il padre ha letto: %d.\n", lpadre); //Creazione socket processo figlio if((csockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Errore nella creazione del socket.\n"); exit(1); } //Azzeramento dello spazio di memoria con l'indirizzo della variabile clntddrss memset((void *)&cclntddrss, 0, sizeof(cclntddrss)); //Assegnazione del tipo di indirizzo cclntddrss.sin_family = AF_INET; //Connessioni accettate su qualunque interfaccia di rete cclntddrss.sin_addr.s_addr = htonl(INADDR_ANY); //Assegnazione del numero di porta cclntddrss.sin_port = htons(0); //Associazione del processo al socket if ((bind(csockfd, (struct sockaddr *)&cclntddrss, sizeof(cclntddrss))) < 0) { perror("Errore in bind.\n"); exit(1); } unsigned int dim = sizeof(temp); getsockname(csockfd, (struct sockaddr *)&temp, &dim); printf("Il figlio ha la porta: %d.\n", ntohs(temp.sin_port)); printf("Premere un tasto per inviare.\n"); getchar(); //Invio numero di porta del socket del processo figlio pscritti = sendto(psockfd, (unsigned short *)&temp.sin_port, 2, 0, (struct sockaddr*)&pclntddrss, sizeof(pclntddrss)); if(pscritti < 0) { perror("Errore in scrittura.\n"); exit(1); } caddrlen = sizeof(cclntddrss); //Creazione del processo figlio pid_t pid = fork(); //Controllo 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()); close(psockfd); pletti = recvfrom(csockfd, (int*)&lfiglio, 4, 0, (struct sockaddr*)&cclntddrss, &caddrlen); if (cletti < 0) { perror("Errore in lettura.\n"); exit(1); } printf("Il figlio ha letto: %d.\n", lfiglio); printf("Premere un tasto per inviare.\n"); getchar(); sfiglio = 9; cscritti = sendto(csockfd, (int*)&sfiglio, 4, 0, (struct sockaddr *)&cclntddrss, sizeof(cclntddrss)); if (cscritti < 0) { perror("Errore in scrittura.\n"); exit(1); } //Chiusura socket figlio close(csockfd); //Terminazione processo figlio exit(EXIT_SUCCESS); } wait(NULL); exit(0); }
codice:#include "header.h" int psockfd, csockfd, pscritti, cscritti, pletti, cletti, spadre = 0, lfiglio = 0, sfiglio = 0; unsigned int paddrlen, caddrlen; int ricporta; struct sockaddr_in psrvrddrss; struct sockaddr_in csrvrddrss; int main(int argc, char** argv) { printf("Prova.\n"); //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); } //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); } paddrlen = sizeof(psrvrddrss); printf("Premi un tasto qualsiasi per inviare.\n"); getchar(); spadre = 5; pscritti = sendto(psockfd, (int*)&spadre, 4, 0, (struct sockaddr*)&psrvrddrss, sizeof(psrvrddrss)); if(pscritti < 0) { perror("Errore in scrittura.\n"); exit(1); } //Ricezione numero di porta del server pletti = recvfrom(psockfd, (unsigned short *)&ricporta, 2, 0, (struct sockaddr*)&psrvrddrss, &paddrlen); if(pletti < 0) { perror("Errore in lettura.\n"); exit(1); } printf("Prova.\n"); printf("Numero porta figlio server: %d.\n", ntohs(ricporta)); //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; printf("Il numero di porta ricevuto è: %d , %d.\n", htons(csrvrddrss.sin_port), htons(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); printf("Premi un tasto qualsiasi per inviare.\n"); getchar(); sfiglio = 7; cscritti = sendto(csockfd, (int*)&sfiglio, 4, 0, (struct sockaddr*)&csrvrddrss, sizeof(csrvrddrss)); if(cscritti < 0) { perror("Errore in scrittura.\n"); exit(1); } cletti = recvfrom(csockfd, (int*)&lfiglio, 4, 0, (struct sockaddr*)&csrvrddrss, &caddrlen); if(cletti < 0) { perror("Errore in lettura.\n"); exit(1); } printf("Il figlio ha letto: %d.\n", lfiglio); close(csockfd); exit(EXIT_SUCCESS); } wait(NULL); exit(0); }

)
Rispondi quotando
FUNZIONA! 