Visualizzazione dei risultati da 1 a 2 su 2
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2010
    Messaggi
    17

    [C] Problema read da socket stream con programma client server

    Salve a tutti ho un problema con un programma client/server scritto in c.
    Il client invia al server una stringa con il nome di un file e un intero rappresentante il numero massimo di caratteri che ogni riga del file puo' avere.
    Il server legge il nome del file, prova ad aprirlo e se l'operazione riesce, e risponde con le righe di testo del file che hanno un numero di caratteri <= all'intero passato dal client.

    Il problema sta nel server quando effettuo la seconda read() da stream socket:
    ricevo o l'errore "bad file descriptor" o non riesco a leggere l'intero.

    Posto il codice di client e server. Il problema e' commentato.
    client.c
    codice:
    #include <stdio.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <errno.h>
    
    #define DIM_BUFF 256
    
    int main(int argc, char** argv){
    	//controllo argomenti e inizializzazione strutture dati
    	int sd, fd_file, nread,nwrite,numCar;
    	char buff[DIM_BUFF],ok;
    	char nome_ric[FILENAME_MAX+1];
    	char lungRighe[20];
    	struct hostent * host;
    	struct sockaddr_in serveraddr;
    	
    	if(argc!=3){
    		printf("Errore invocazione comando client: host porta\n");
    		exit(1);
    	} 
    	//inizializzo indirizzo server
    	memset((char*)&serveraddr, 0, sizeof(struct sockaddr_in));
    	serveraddr.sin_family = AF_INET;
    	host = gethostbyname("localhost");
    	if(host == NULL){
    		printf("Host not found.\n");exit(2);
    	}
    	//verifica porta
    	serveraddr.sin_addr.s_addr = ((struct in_addr*)(host->h_addr))->s_addr;
    	serveraddr.sin_port = htons(atoi("1234"));
    
    	//client
    	printf("Client per trasferimento righe file.\n");
    	printf("Nome del file da richiedere al server, EOF per terminare:\n");
    	while(gets(nome_ric)){
    		printf("File da cercare: %s.\n", nome_ric);
    		printf("Numero dei caratteri ammessi per le righe da mostrare:\n");
    		while(gets(lungRighe)==NULL){
    			printf("Numero dei caratteri ammessi per le righe da mostrare:\n");
    		}
    		printf("Numero caratteri: %s\n", lungRighe);
    		sd = socket(AF_INET, SOCK_STREAM, 0); //creo socket
    		if(sd<0){
    			perror("Errore creazione socket.\n");
    			exit(2);
    		}
    		printf("Socket creata: sd = %d\n", sd);
    		if(connect(sd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr))<0){
    			perror("Errore connessione.\n");
    			exit(2);
    		}
    		//invio il nome del file e aspetto risposta
    		//invio numero di righe
    		
    		numCar = atoi(lungRighe);
    		numCar = htonl(numCar);
    		if((nwrite=write(sd, &nome_ric, sizeof(nome_ric)))<0){
    			perror("Errore scrittura...\n");
    			close(sd); exit(4);
    		}
    		if((nwrite=write(sd, &numCar, sizeof(numCar)))<0){//la read sul server di questa non mi funziona
    			perror("Errore scrittura...\n");
    			close(sd); exit(4);
    		}
    		printf("Attendo risposta...\n");
    		if(read(sd, &ok, 1)<0){
    			perror("Errore lettura risposta.\n");
    			continue;
    		}
    		if(ok=='S'){
    			//leggo fino a chiusura sd
    			while((nread=read(sd, buff, sizeof(buff)))>0){
    				if(nwrite = write(1, buff, nread)<0){
    					perror("Errore ricezione file.\n");
    					break;
    				}
    			}if(nread<0){
    				perror("Errore ricezione file.\n");
    				close(sd);
    				printf("Nome del file da richiedere: \n");
    				continue;
    			}
    		}
    		else if(ok=='N'){
    				printf("File inesistente.\n");
    			}
    			close(sd);
    			printf("Nome del file da richiedere: \n");
    	}
    	printf("Client: Termino...\n");
    	exit(0);
    }
    server.c
    codice:
    #include <stdio.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <errno.h>
    #include <dirent.h>
    #include <string.h>
    #define max(a,b) ((a) > (b) ? (a) : (b))
    #define DIM_BUFF 256
    
    
    int conta_file(char * nome_dir, int soglia){
    	printf("Sono in conta file.\n");
    	DIR * dir; 
    	struct dirent * dd;
    	FILE * curr;
    	int count=0,countTot=0;
    	char nome_file[20];
    	if((dir = opendir(nome_dir))!=NULL){
    	while((dd = readdir(dir))!=NULL){
    		printf("%s\n",dd->d_name);
    		if((strcmp(dd->d_name,".."))==0 || (strcmp(dd->d_name,"."))==0) printf("Salto .. e .\n");
    		else{			
    			char * res;
    			char linea[256];
    			printf("Aggiusto nomi dei file.\n");
    			strcpy(nome_file, nome_dir);
    			strcat(nome_file, "/");
    			printf("%s\n", nome_file);
    			strcat(nome_file, dd->d_name);
    			printf("%s\n", nome_file);
    			curr = fopen(nome_file, "r");
    			if(curr==NULL) perror("Errore apertura file.\n");
    			
    			else{
    			count = 0;
    			while((res = fgets(linea, 256, curr))!=NULL){
    					count++;
    				}
    			}
    			fclose(curr);
    			printf("%d\n",count);
    			if(count<=soglia) countTot++;
    		}
    		
    		
    	}
    	printf("Numero totale di file(s) con righe sotto la soglia %d contati: %d\n",soglia, countTot);
    	}
    	
    	closedir(dir);
    	return countTot;
    }
    
    
    void gestore(int signo){
    	int stato;
    	printf("esecuzione gestore SIGCHLD\n");
    	wait(&stato);
    }
    
    int main(int argc, char ** argv){
    	int listenfd, connfd, udpfd, nready, maxfdp1, numCar;
    	char zero=0, buff[DIM_BUFF], nome_file[20], nome_dir[20], num_car[20];
    	const int on = 1;
    	fd_set rset;
    	FILE * fd_file;
    	char * res;
    	char buffer[256];
    	int len, nread, nwrite, num, ris,port,numCar;
    	struct sockaddr_in clientaddr, serveraddr;
    
    	//controllo argomenti...
    	memset((char *)&serveraddr, 0, sizeof(serveraddr));
    	serveraddr.sin_family=AF_INET;
    	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    	serveraddr.sin_port = htons(1234);
    
    	//tcp in ascolto
    	listenfd = socket(AF_INET, SOCK_STREAM, 0);
    	if(listenfd<0){
    		perror("Errore creazione socket d'ascolto.\n");
    		exit(1);
    	}
    	if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))<0){
    		perror("Errore set opt.\n");
    		exit(1);
    	}
    	if(bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))<0){
    		perror("Errore bind.\n");
    		exit(1);
    	}
    	if(listen(listenfd, 5)<0){
    		perror("Errore creazione coda d'ascolto.\n");
    		exit(1);
    	}
    	
    	//socket udp
    	udpfd = socket(AF_INET, SOCK_DGRAM, 0);
    	if(udpfd<0){
    		perror("Errore creazione socket udp.\n");
    		exit(2);
    	}
    	if(setsockopt(udpfd, SOL_SOCKET,SO_REUSEADDR, &on, sizeof(on))<0){
    		perror("Errore set opt per udp.\n");
    		exit(2);
    	}
    	if(bind(udpfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))<0){
    		perror("Errore bind udp.\n");
    		exit(2);
    	}
    	//inizio attività server
    	signal(SIGCHLD, gestore);
    	FD_ZERO(&rset);
    	maxfdp1 = max(listenfd, udpfd)+1;
    	for(;;){
    		FD_SET(listenfd, &rset);
    		FD_SET(udpfd, &rset);
    		if((nread = select(maxfdp1, &rset, NULL,NULL, NULL))<0){
    			if(errno==EINTR) continue;
    			else {perror("Errore nella select.\n");exit(3);}
    		}
    		if(FD_ISSET(udpfd, &rset)){
    			
    			len = sizeof(struct sockaddr_in);
    			if(recvfrom(udpfd, &nome_dir, sizeof(nome_dir), 0, (struct sockaddr *)&clientaddr, &len)<0){
    				perror("Errore recvfrom nome udp.\n");
    				continue;
    			}
    			if(recvfrom(udpfd, &num, sizeof(num), 0, (struct sockaddr *)&clientaddr, &len)<0){
    				perror("Errore recvfrom num udp.\n");
    				continue;
    			}	
    			printf("Ho ricevuto dal client udp: %s %d\n", nome_dir, ntohl(num));
    			num = ntohl(num);
    			num = conta_file(nome_dir, num);
    			ris = htonl(num);
    			if(sendto(udpfd, &ris, sizeof(ris), 0, (struct sockaddr *)&clientaddr, len)<0){
    				perror("Errore sendto udp.\n");
    				continue;
    			}
    		}
    		if(FD_ISSET(listenfd, &rset))
    		{
    			len = sizeof(struct sockaddr_in);
    			if((connfd = accept(listenfd, (struct sockaddr*)&clientaddr,&len))<0){
    				if(errno==EINTR) continue;
    				else{ perror("Errore nella accept.\n"); exit(4);}
    			}
    			if(fork()==0){
    				close(listenfd);
    				printf("Sono il figlio: %d\n", getpid());
    				if((nread=read(connfd, &nome_file, sizeof(nome_file)))<=0){
    					perror("Errore lettura fd figlio.\n");
    					break;
    				}
    				
    				if((nread=read(connfd, &numCar, sizeof(numCar)))<=0){//questa read o genera Bad File Descriptor o risulta vuota
    										//ho provato anche a passare una stringa dal client e nel server a 
    										//convertirla con atoi...ma risulta vuota. Se passo un intero, sia con 
    										//sizeof(int) o con sizeof(nomeInt) risulta comunque vuota.Dove sbaglio?
    					perror("Errore lettura fd figlio.\n");
    					break;
    				}
    				printf("Ho letto: %s\n", nome_file);//qui leggo correttamente nome file
    				printf("Ho letto: %d\n", ntohl(numCar));//qui non leggo nulla
    				fd_file = fopen(nome_file, O_RDONLY);
    				if(fd_file<0){
    					write(connfd, "N", 1);
    				}
    				else{
    					write(connfd, "S", 1);
    					while((nread=read(fd_file, buff, sizeof(buff)))>0){
    						if(nwrite = write(connfd,buff, nread)<0){
    							perror("Errore scrittura file.\n");
    							break;
    						}
    					}
    					close(fd_file);
    				}
    				close(connfd);
    				exit(0); //solo figlio
    			}
    			close(connfd);
    		}
    	}
    	printf("Server: Termino...\n");
    }
    Manca il codice del client udp ma e' irrilevante visto che funziona e non e' fondamentale al funzionamento del programma.
    Spero in un aiuto.
    Grazie ciao.

  2. #2
    Utente di HTML.it
    Registrato dal
    Oct 2010
    Messaggi
    17
    nessuna idea?? un aiutino...un'ipotesi...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.