Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214

    [C] read() socket af_unix return 0

    Ciao a tutti, ho un problema con la lettura da un socket. Ho 3 processi server che devono comunicare con un numero variabile di processi client, tuttavia alcuni messaggi non vengono scambiati come dovrebbero e la chiamata a read() che effettua il server per leggere dal socket il messaggio depositato dal client mi restituisce 0. So che questo valore significa che il socket è stato chiuso da una delle due parti, ma non capisco chi lo chiude! Il cliente non lo chiude esplicitamente (ho rimosso questa porzione di codice per verificare che non vi fossero anomalie, ma il problema permane). Il codice è abbastanza semplice: il server accetta una connessione e avvia un thread, che prende come parametro il valore ritornato dalla accept. Il thread è incaricato di leggere il messaggio da questo socket descriptor.

    server:
    codice:
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    while(1){
    if( (acp = accept(fd_sock, NULL, NULL)) != -1 ){
    	thread = pthread_create(&t_id[i], &attr, worker, (void*)&acp); 
    	if(thread == -1)
    	perror("Crezione thread"); 
            i++; 
    	} 
    }
    il thread riceve il messaggio, chiamando 3 volte la receive, leggendo rispettivamente: un char, un int e una stringa.

    codice:
    int sock = *(int*)acp; 
    memset(msg, 0, sizeof(message_t)); 
    
    while( (letti+= read(sock, &msg->type, sizeof(char) < sizeof(char)) )
    if( letti <= 0){
    return -1;
    perror(Leggo char); 
    } 
    
    while( (letti_int+= read(sock, &msg->length, sizeof(unsigned int) < sizeof(unsigned int)) )
    if( letti < sizeof(unsigned int) ) {
    perror(Leggo int); 
    return -1; 
    }
    
    while( (letti_buf+= read(sock, msg->buffer, msg->length)) < msg->lenght)
    if( letti_buf <= msg->length){
    perror(Letto buffer); 
    return -1; 
    }
    Il cliente invece si limita a fare la write sul socket. Questa è corretta perchè invia il numero effettivo di byte.

    A volte la prima read, quella che legge il char ritorna 0. Tuttavia il socket non è stato chiuso da nessuno! Come dovrei procedere per correggere l'errore?

    Per chiarezza, la struttura msg contiene un char, un unsigned int e un char*.

  2. #2
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    Sai com'è, l'errore potrebbe essere ovunque, un puntatore o un sizeof sbagliato, come è già successo (quando fai copia/incolla inoltre dovresti fare più attenzione perché mancano diverse parentesi).

    Dovresti fare un un programma server e client minimali (vedi http://sscce.org/) che inviano anche sempre la stessa struttura e provare con un solo server e un solo client. Se già così hai il problema sarà già più facile da debuggare.
    Inoltre una volta creato puoi postarlo qui direttamente (sia il client che il server, non solo il server) e sarà più facile da studiare.

    Puoi anche postare qui la versione attuale, certo che se è una cosa gigantesca e che nessuno può compilare/provare non è tanto comodo. In questi casi dove trovare il problema può essere complesso è sempre meglio fare una versione ridotta ma che compila e lavorare su quella.

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    Al momento ho testato la versione completa del programma con 12 client e 3 server, e funziona se i clienti vengono avviati in maniera sequenziale. Ora invece devo testare la versione competitiva, dunque i clienti sono avviati tutti insieme. Riduco il più possibile il codice e cerco di postarlo.

  4. #4
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    Ok, mi sfugge solo la differenza tra sequenziale e competitiva. Se li esegui dallo stesso computer sarà sempre sequenziale. (ma comunque anche se esegui i client da computer diversi, le richieste verranno accettate dalla accept() del server una per volta).

    Forse con sequenziale intendi che metti una sleep tra l'avvio di un client e l'altro, mentre competitiva senza nessuna sleep?

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    Con sequenziale intendo che l'avvio di un client avviene dopo la terminazione del precedente. Facendolo con uno script basta semplicemente:

    ./client parametri
    ./client parametri1
    ./client parametri2

    In questo modo se prima non termina l'esecuzione di un comando, il secondo non si avvia.

    Con competitivo intendo che i client sono in esecuzione in contemporanea. Anche qui con uno script:

    ./client parametri &
    ./client parametri1 &
    ./client parametri2 &

    L'attesa della terminazione di un comando non c'è con l'aggiunta dell'esecuzione in background.

  6. #6
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    Ora è chiaro, nel post precedente avevi scritto "se i clienti vengono avviati in maniera sequenziale". Tu volevi dire non "avviati" ma "eseguiti e terminati".

    Certamente il server ti deve funzionare anche con più client eseguiti in contemporanea, su questo non ci piove.

  7. #7
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    Ho semplificato il codice, eliminando le librerie. Ora ci sono tutte le funzioni minime per il funzionamento del client e del server. Ho inserito anche uno script per l'avvio, ma anche qui ci sono problemi...Ho messo tutto in un archivio per non creare confusione, è accessibile qui:

    my_client_server

  8. #8
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    Sul client sono sbagliate le solite due righe:

    < letti += read(sc, risposta.type, sizeof(char));
    > letti += read(sc, &risposta.type, sizeof(char));

    < letti += read(sc, risposta.length, sizeof(unsigned int));
    > letti += read(sc, &risposta.length, sizeof(unsigned int));

    corretto questo e qualche warning (non lasciare nessun warning di compilazione altrimenti poi non vedi i warning importanti) se eseguo test.sh mi scrive:

    $ ./test.sh
    Server riceve: 15, x,
    Client riceve: 15, x,
    Server riceve: 15, x,
    Client riceve: 15, x,

    È corretto? Se è corretto devo fare invece qualche altro test?

    P.S. Non l'ho guardato molto il codice, ci sono varie cose che non hanno senso secondo me ma per adesso le ignoro non essendo la causa del tuo problema di chiusura del socket che lamenti.

  9. #9
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    Manca il il messaggio contenuto in "messaggio->buffer" (dovrebbe stampare 15, x, provaprovaprova) inoltre questo codice se eseguito con più clienti restituisce l'errore che cito nel titolo. Ho parzialmente risolto utilizzando i thread detached, ma il problema rimane.

  10. #10
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    Scusa, mi posso anche andare a guardare il codice, ma hai postato questi due file ser.c e cli.c

    Sul tuo computer se li compili così come sono ed esegui in una shell:
    ./ser
    e in un altra shell nella stessa directory:
    ./cli
    cosa ti stampa?

    A te stampa "provaprovaprova"? Perché se neanche questo funziona non capisco perché non te lo sei corretto tu. Qui non dovevamo guardare solo perché il socket si chiudeva?

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.