Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2003
    Messaggi
    348

    [C-Socket] funzione read aspetta fino a...\0??

    Ciao a tutti, riprendendo in mano un po' di codice sui socket mi e' sopraggiunto un problema con la funzione read.
    Lasciando stare tutta la parte di connessione riporto solo le funzioni di invio e ricezione del messaggio lungo un descrittore.


    Parte client
    codice:
    char *test ="ciaooo";
    int size=	invio_msg(tcp_sk , test , sizeof(char) * strlen(test));
    printf("Valori scritti: %d\n" , size);
    Parte server, legge quello che ha inviato il client
    codice:
    int size = read_msg(new_sk ,buff , 100);
    Funzioni di supporto per invio e lettura
    codice:
    int invio_msg(int desc , char * msg , int size){
    	int byte ;
    	int valore = 0;
    	
    	while(size > 0){
    		
    		if((byte=write(desc , msg , size )) < 0){
    			if(errno == EINTR){
    				printf("Errore nell'invio dei dati\n");
    				continue ;
    			}else{
    				printf("Errore nell'invio\n");
    				return -1;
    			}
    		}
    		valore += byte;
    		size -= byte ;
    		msg += byte ;
    		
    	}//while
    	
    	return byte; 
    }
    
    
    
    int read_msg(int sd ,char * msg , int max_size ){
    
    	int value , byte;
    	int size=0;
    	value = max_size;
    
    	while(value > 0 ){
    				
    		if((byte=read(sd , msg ,  max_size - 1)) < 0 ){
    			if(errno == EINTR){
    				continue;
    			}else{
    				return -1;
    			}
    			
    		}else{
    			if( byte == 0){
    				break ;
    			}
    		}
    		msg += (byte * sizeof(char));
    		value -= 	byte;
    		size += 	byte ;
    
    	}
    	return size;
    }
    La funzione read dovrebbe leggere fino a quando non incontra il carattere di escape \0?Oppure sbaglio io da qualche parte?Perche' mi rimane bloccato nella funzione di read_msg e non riesco a venirne fuori.

    Grazie e scusatemi

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Legge finché ha qualcosa da leggere. Se non lo trova si ferma e aspetta che arrivi qualcosa. Dovresti aprire il socket in modalità non bloccante o monitorarlo tramite una select.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2003
    Messaggi
    348
    sicuro?
    forse mi sono spiegato male.

    Il server fa un fork quindi dovrebbe essere in attesa il figlio, se metto non bloccante ho un errore in fase di esecuzione.

    Un socket e' bloccante quando, a seguito di una chiamata alla funzione di attesa per una connessione, blocca il thread in cui e' stata creata, fino all'arrivo di una richiesta di connessione.
    Con un socket non bloccante, invece, non si ha una attesa indefinita. Se al momento della verifica, non e' presente alcuna richiesta di connessione, allora il thread continuera' con la propria esecuzione senza bloccarsi.

    Comunque posto interemante il codice sia del client sia del server:

    server
    codice:
    int server(){
            
            struct hostent * host ;
    	struct sockaddr_in addr ;
    	struct sockaddr_in client ;	
    	socklen_t size_sock ;
    	
    
    	bzero(&(addr), sizeof(addr));
    	addr.sin_family = AF_INET ;
    	addr.sin_port = htons(8000) ;
    	size_sock = sizeof(struct sockaddr);
    
    	addr.sin_addr.s_addr = ((struct in_addr *)(host->h_addr_list[0]))->s_addr;
    	addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
    
    	memset(addr.sin_zero , '\0', sizeof(addr.sin_zero));
    	
    	
    	if((tcp_sk=socket(PF_INET , SOCK_STREAM, 0))==-1){
    		perror("Error initialazing");
    		exit(0);
    	}
    	
    
    	if((bind(tcp_sk , (struct sockaddr *)(&addr) , sizeof(addr) ))<0){
    		perror("Error bind");
    		exit(-1);
    	}
    	
    	if(listen(tcp_sk , 2) < 0){
    		perror("Error listen");
    		exit(-1);
    	}
    	
    	
    	
    	while(1){
    		if((new_sk=(accept(tcp_sk , (struct sockaddr *)&client , &size_sock))) < 0 ){
    
    			perror("Error accept");
    			exit(-1);
    		}
    
    		pthread_mutex_lock(&mutex_db);
    		
    		if((pid=fork())==0){
    		
    			close(tcp_sk);		
    			printf("Client:%s\n",inet_ntoa(client.sin_addr));
    			richiesta(new_sk);
    			close(new_sk);
    			exit(2); /* figlio termina */	
    			
    		}else{
    			
    			
    			close(new_sk);		
    			int va;
    			wait(&va);
    			pthread_mutex_unlock(&mutex_db);	
    		}//if-else del fork
    richiesta
    codice:
    void richiesta(int new_sk){
    
    	int scelta;
    	char buff[100];
    
    	int size = read_msg(new_sk ,buff , 100);	
    	buff[size] = '\0';
    	printf("Valore ricevuto:%s\n" , buff);
    }

    client
    codice:
    int main(){
    	
    	
    	
    	int size=0;
    	int tcp_sk; 
    	struct sockaddr_in addr ;
    
    	bzero(&(addr), sizeof(addr));
    	addr.sin_family = AF_INET ;
    	addr.sin_port = htons(8000) ;
    	
    	addr.sin_addr.s_addr = inet_addr( "127.0.0.1" ) ;
    	memset(addr.sin_zero , '\0', sizeof(addr.sin_zero));
    	
    	char choice= "w";
             printf("Valore passato:%c\n" , choice[0]);
    				
    				if((tcp_sk=socket(PF_INET , SOCK_STREAM, 0))==-1){
    					perror("Error socket\n");
    					exit(0);
    				}
    				//chiedo la connessione!!!!!
    				if(connect(tcp_sk, (struct sockaddr *)&(addr) ,sizeof(addr) ) !=0){
    					perror("Error connect\n");
    					exit(0);	
    				}
    
    
    
    				int size=	invio_msg(tcp_sk , choice , sizeof(char));
    
    				printf("Valori scritti: %d\n" , size);
    
    				read_and_format(tcp_sk);							
    				close(tcp_sk);
    
    
    }//main
    
    
    int read_and_format(int tcp_sk){
    	int size;
    	char parola[100];
    	
    	while((size = read_msg(tcp_sk ,parola , 100 )) !=0){
    		if(size == -1){
    			printf("Errore in lettura\n");
    			return -1;
    		}
    		
    	
    	printf("Stringa: %s \n " ,parola);
    		
    	}//while
    
    
    }//read_and_format
    Il client resta giustamente in attesa che il server restituisca dei dati, ma il server e' bloccato.
    Quando killo il client dall'altra parte si stampa il carattere che ho passato tramite il socket.

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Originariamente inviato da nomida
    Un socket e' bloccante quando, a seguito di una chiamata alla funzione di attesa per una connessione, blocca il thread in cui e' stata creata, fino all'arrivo di una richiesta di connessione.
    O fallisce la connessione.
    Comunque non è quello il socket da fare non bloccante, ma quello ricevuto dalla accept sul quale avviene la lettura con la read. Se quello è bloccante la funzione rimane in attesa di dati e se non arrivano si ferma tutto. Quando accoppi il client la read del server figlio si sblocca perché la connessione è stata chiusa.
    Il fatto che ci sia o no una fork è irrilevante per la read.

    Curiosità: a che serve quel mutex?
    Sarebbe meglio che lo sbloccassi quando il figlio termina.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2003
    Messaggi
    348
    eh immaginavo la domanda sul mutex

    In soldoni il server che ho postato e' un thread di un programma che accede ad un dbms(postgre).
    Il programma intero e' un demone che accede ogni 30 minuti al db.
    Il mutex(cosi come l'ho messo) mi serve per non avere un doppio accesso al db sia dal server sia dal demone che lo aggiorna.

    codice:
    wait(&va);
    pthread_mutex_unlock(&mutex_db);
    Ma il padre non aspetta che il figlio finisca??oppure ho cannato anche questa?!

    domani ti aggiorno con la i socket bloccanti e non (devo studiarmeli per benino).
    per caso hai qualche link utile?Ho ancora dubbi perche' ho sistemato il problema modificando read_msg pero' non sono pienamente soddisfatto.

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Beh, vedendolo li solo soletto mi faceva pena
    Non conosco a fondo la fork (preferisco i thread). Se non sbaglio dovrebbe duplicare l'intero processo server, giusto? In quel caso ( e a naso) mi sembra che se non rilasci il mutex prima che il figlio termini, all'esecuzione successiva il mutex si trovi già acquisito bloccando il tutto.
    Per precauzione metterei la riga in rosso.
    codice:
    	while(1){
    		if((new_sk=(accept(tcp_sk , (struct sockaddr *)&client , &size_sock))) < 0 ){
    
    			perror("Error accept");
    			exit(-1);
    		}
    
    		pthread_mutex_lock(&mutex_db);
    		
    		if((pid=fork())==0){
    		
    			close(tcp_sk);		
    			printf("Client:%s\n",inet_ntoa(client.sin_addr));
    			richiesta(new_sk);
    			close(new_sk);
                            pthread_mutex_unlock(&mutex_db);
    			exit(2); /* figlio termina */	
    			
    		}else{
    			
    			
    			close(new_sk);		
    			int va;
    			wait(&va);
    			pthread_mutex_unlock(&mutex_db);	
    		}//if-else del fork
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

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 © 2024 vBulletin Solutions, Inc. All rights reserved.