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

    [C] Conversione di interi scambiati su socket

    Ciao a tutti, ho realizzato un protocollo di comunicazione tra due processi mediante una socket. Questi si scambiano una struttura contenente un char, un intero e una stringa.

    codice:
    typedef struct {
      /** tipo del messaggio */
        char type;
      /** lunghezza messaggio in byte */
        unsigned int length;
      /** buffer messaggio */
        char buffer[MAXBUF];
    } message_t;
    Il messaggio inviato viene impacchettato in un buffer costituito in questo modo:
    codice:
     
    buffer[0] = msg.type; 
    buffer[1] = msg.length;  //intero formattato come int64_t corrispondente alla lunghezza del campo buffer
    buffer[sizeof(int64_t)+1] = msg.buffer;
    Quando un processo invia un messaggio, stampa a video la stringa corrispondente al messaggio, e attende che il secondo processo gli risponda con la medesima stringa. Ad esempio un modello di comunicazione è il seguente:

    Processo1 invia: <T><9><messaggio>
    Processo1 riceve: <T><9><messaggio>

    T rappresenta msg.type, 9 rappresenta msg.length e "messaggio" rappresenta msg.buffer.
    La comunicazione avviene senza problemi poichè i due processi scambiano messaggi correttamente. Il problema sorge "localmente" al processo. Ovvero, ho definito una funzione che stampa la struttura message_t, struttura popolata mediante i messaggi scambiati sulla socket. La funzione è la seguente:

    codice:
    printMessage(message_t*msg){
      if ( msg->length == 0 )  {
        printf("%c : <void>\n", msg->type);
        return;
      }
      printf("%c : %s\n", msg->type,msg->buffer);
    }
    Il problema è che il campo lenght contiene un valore numerico in formato macchina, dunque la condizione msg->length == 0 risulta sempre vera.
    Questo valore è memorizzato mediante la chiamata:
    read(socket, msg->length, sizeof(int64_t);

    Quale funzione di conversione devo utilizzare per poter usare questo valore? Ho provato con le funzioni definite in endian.h ma senza risultati. Sono sicuro che il valore sia correttamente scambiato tra i processi, come dicevo sopra, tutti i messaggi vengono inviati ricevuti e stampati correttamente, e nei messaggi è presente questo valore!
    Spero possiate aiutarmi, vi ringrazio!

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Non ti era stato detto di usare la memcpy ?
    Tutto il resto, sul formato macchina ecc., non ha senso ... il valore è inviato in binario e lo devi copiare su una variabile tramite una memcpy, ottenendo automaticamente il valore leggibile. Nessuna conversione in nessun senso.

    Questo programma è veramente ostico per te e la causa è la mancanza di una preparazione di base sul linguaggio.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    No, il buffer è preparato con la memcpy, quello che ho scritto sotto è solo per dare un'idea di cosa occupa quale "posto" nel buffer.

    Inoltre tutte le variabili vengono memorizzate mediante 3 chiamate alla read, ovvero:

    - alloco un nuovo messaggio;
    - leggo e memorizzo con read(socket, msg->type, sizeof(char));
    - leggo e memorizzo l'intero con read(socket, msg->lenght, sizeof(int64_t));
    - leggo e memorizzo il buffer con read(socket, msg->buffer, msg->lenght);

    Ho chiesto della conversione perchè non mi spiego il motivo del comportamento della funzione in due chiamate praticamente consecutive, ovvero:

    se scrivo printf("%d", msg->length), ottengo il valore esatto;
    se scrivo if(msg->length == 0) risulta sempre vero, anche se ho appena visualizzato il valore corretto della lunghezza.
    Inoltre, come ho già detto, la comunicazione avviene correttamente, e quel valore è stampato a video correttamente sia dal mittente che dal ricevente del messaggio.

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Se hai quel problema, evidentemente qualcosa non va ...

    Quando dici

    se scrivo printf("%d", msg->length), ottengo il valore esatto;
    se scrivo if(msg->length == 0)

    intendi proprio una riga sotto l'altra? O la printf la fai in una funzione e la if in un'altra?

    Mostra il codice esatto con cui visualizzi e controlli e tutto il codice della ricezione che hai scritto ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    Il condizionale è in una funzione separata, ma chiamata esattamente sotto quel printf. A breve posterò il codice.

  6. #6
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    Ricezione del messaggio:

    codice:
    int ricezione(int sc, message_t* msg){
    //Controllo parametri omesso 
    /*Prima read, leggerò un solo char ottenendo il tipo del messaggio*/
    	letti = read(sc, &msg->type, sizeof(char) );
    	if( (letti == -1) || (letti == 0) || (letti < sizeof(char)) ){
    		perror("Read type");
    		return -1;
    	}
    	/*Seconda read, leggerò un int64_t ottenendo la lunghezza del messaggio*/
    	int letti_length = 0;
    	letti_length = read(sc, &msg->length, sizeof(int64_t) );
    	if( (letti_length == -1) || (letti_length == 0) || (letti_length < sizeof(int64_t)) ){
    		perror("Read length");
    		return -1;
    	}
    	letti += letti_length;
    	/*Terza read, leggerò msg->length caratteri ottenendo il buffer del messaggio*/
    	int letti_buf = 0;
    	while( (letti_buf += read(sc, &msg->buffer, msg->length) ) < msg->length){
    		if( (letti_buf == -1) || (letti_buf == 0) ){
    		perror("Read buffer");
    		return -1;
    		}
    	}
    
    return (letti+letti_buf);
    }
    stampo a video il messaggio appena ricevuto (qui è dove NON stampa il messaggio):
    codice:
    void  printMessage(message_t * msg) {
      if ( msg->length == 0 )  {
        printf("%c : <void>\n", msg->type);
        return;
      }
      printf("%c : %s\n", msg->type,msg->buffer);
    }
    Invio il medesimo messaggio appena ricevuto in questo modo (msgr è un messaggio di risposta nel quale copio il messaggio appena ricevuto):

    codice:
        msgr.type = MSG_QUERY;
        strcpy(msgr.buffer,"server: ");
    
        if (msg.length > 0) strcat(msgr.buffer,msg.buffer);
        msgr.length = strlen(msgr.buffer) +1;
    Il messaggio appena inviato verrà stampato CORRETTAMENTE dall'altro processo con questa funzione:

    codice:
    printMessage(&msg);

  7. #7
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    A parte questa linea

    strcat(msgr.buffer,msg.buffer);

    che non capisco a cosa ti possa servire (la strcat serve ad accodare stringhe non a copiarle), se poi dici

    "verrà stampato CORRETTAMENTE"

    allora il problema dove sta?

    Ti avevo chiesto di mostrarci la sequenza

    printf ... if

    in cui i valori non corrispondevano ma mi hai confuso di più con questa ultima risposta ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  8. #8
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    strcat serve per accodare al buffer del messaggio di risposta, il buffer del messaggio appena ricevuto.
    La sequenza if..printf è questa:

    il processo chiama printMessage e NON stampa (if msg->length == 0 risulta true).
    accodando il primo buffer al buffer del messaggio di risposta, la condizione if (msg->length > 0) risulta anch'essa true, altrimenti il messaggio di risposta sarebbe stampato in maniera errata!

    Forse sono poco chiaro, provo con un esempio:

    - A invia a B il seguente messaggio: Q 4 ciao.
    - A riceve il messaggio, lo spacchetta nella sua struttura e stampa la struttura: ===> stampa nulla
    Crea un messaggio di risposta usando la stessa struttura che prima ha prodotto la stampa nulla:
    - IosonoAetirispondo: Q 4 ciao. =======> il messaggio è stato ricevuto e spacchettato correttamente se è stato possibile reinviarlo.

  9. #9
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    La sequenza if..printf è questa:
    Mi dispiace ma non ti spieghi.

    Dove sta la chiamata a printMessage? Mostra il main o la funzione completa in cui chiami la printMessage.

    Considera che tu hai "chiaro" quello che stai facendo ma da quest'altra parte del forum non si sa nulla dei messaggi ricevuti, copiati e reinviati ...
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  10. #10
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    214
    codice:
    void mainProcessoA(){  
    for ( i = 0; i<N ; i++ ) {
        if ( receiveMessage(sk_c,&msg)  == -1) {
         perror("testserv: receiveMssage");
         break;
        }
        /* stampa del messaggio */
        printMessage(&msg);
        /* creazione messaggio di risposta */
        msgr.type = MSG_QUERY;
        strcpy(msgr.buffer,"server: ");
    
        if (msg.length > 0) strcat(msgr.buffer,msg.buffer);
        msgr.length = strlen(msgr.buffer) +1;
    
        /* invio messaggio di risposta */
        if ( sendMessage(sk_c,&msgr) == -1 )  {
          perror("testcli: sendMessage");
          break;
        }
      }
    }
    codice:
    void mainProcessoB{
      for ( i = 0; i<N ; i++ ) {
    
        /* preparo il messaggio ...*/
        msg.type=ch[i];
        msg.length=0;
        memset(msg.buffer,'\0',MAXBUF);
        if ( text[i] !=NULL ) {
          msg.length=strlen(text[i])+1;
          strcpy(msg.buffer,text[i]);
        }
        /* lo invio */
        /* sck e' la connessione su cui mandare il msg */
        if ( sendMessage(sck,&msg) == -1 )  {
          perror("testcli: sendMessage");
          break;
        }
        fprintf(stdout,"testcli: invio <%c><%d><%s> \n",msg.type,msg.length,msg.buffer);
        /* leggo la risposta */
        if ( receiveMessage(sck,&msg)  == -1) {
          perror("testcli: receiveMessage");
          break;
        }
    
        /* stampo la risposta */
        fprintf(stdout,"testcli: recevo <%c><%d><%s> \n",msg.type,msg.length,msg.buffer);
      }
    }
    printMessage non stampa nulla
    fprintf(stdout,"testcli: recevo <%c><%d><%s> \n",msg.type,msg.length,msg.buffer); stampa correttamente.

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.