Domanda

Ho due semplici programmi impostati che condividono dati tramite un socket di dominio unix. Un programma legge i dati da una coda e lo invia al l'altra applicazione. Prima che sia trasmesso ciascun dato è front-assegnata da quattro byte con la lunghezza, se è meno poi quattro byte del byte in eccesso sono il simbolo '^'.

L'applicazione client legge quindi i primi quattro byte, imposta un buffer alla dimensione appropriata e quindi legge il resto. Il problema che sto avendo è che la prima volta attraverso il messaggio verrà inviato alla perfezione. Ogni altra volta, dopo che c'è dati aggiuntivi vengono inviati in modo da un messaggio del tipo "quello che una bella giornata fuori" sarebbe venuto fuori come "quello che una bella giornata fuori ?? X ??". Così mi sento come un buffer non viene eliminato correttamente, ma io non riesco a trovarlo.

Codice cliente:

listen(sock, 5);
for (;;) 
{
    msgsock = accept(sock, 0, 0);
    if (msgsock == -1)
        perror("accept");
    else do 
    {
        char buf[4];
        bzero(buf, sizeof(buf));
        if ((rval = read(msgsock, buf, 4)) < 0)
        perror("reading stream message");

        printf("--!%s\n", buf);

        string temp = buf;
        int pos = temp.find("^");
        if(pos != string::npos)
        {
            temp = temp.substr(0, pos);
        }

        int sizeOfString = atoi(temp.c_str());
        cout << "TEMP STRING: " << temp << endl;
        cout << "LENGTH " << sizeOfString << endl;
        char feedWord[sizeOfString];
        bzero(feedWord, sizeof(feedWord));

        if ((rval = read(msgsock, feedWord, sizeOfString)) < 0)
              perror("reading stream message");

          else if (rval == 0)
              printf("Ending connection\n");
          else
              printf("-->%s\n", feedWord);
              bzero(feedWord, sizeof(feedWord));
              sizeOfString = 0;
              temp.clear();
      } 
        while (rval > 0);
      close(msgsock);
  }
  close(sock);
  unlink(NAME);

Server Codice

                pthread_mutex_lock(&mylock);
                string s;
                s.clear();
                s = dataQueue.front();
                dataQueue.pop();
                pthread_mutex_unlock(&mylock);

                int sizeOfString = strlen(s.c_str());
                char sizeofStringBuffer[10];

                sprintf(sizeofStringBuffer, "%i", sizeOfString);
                string actualString = sizeofStringBuffer;
                int tempSize = strlen(sizeofStringBuffer);

                int remainder = 4 - tempSize;
                int x;
                for(x =0; x < remainder; x++)
                {
                    actualString = actualString + "^";
                }

                cout << "LENGTH OF ACTUAL STRING: " << sizeOfString << endl;

                actualString = actualString + s;

                cout << "************************" << actualString << endl;
                int length = strlen(actualString.c_str());

                char finalString[length];
                bzero(finalString, sizeof(finalString));
                strcpy(finalString, actualString.c_str());

                           if (write(sock, finalString, length) < 0)
                           perror("writing on stream socket");      
È stato utile?

Soluzione

Invece di imbottitura la lunghezza del pacchetto con '^', si sarebbe molto meglio solo facendo:

snprintf(sizeofStringBuffer, 5, "%04d", sizeOfString);

in modo che il valore è 0 imbottito -. Allora non c'è bisogno di analizzare i caratteri '^' nel codice del ricevitore

Si prega inoltre di modificare il vostro codice di debug - c'è solo un write() nel codice attuale, e non corrisponde la vostra descrizione del protocollo

.

Idealmente - dividere la routine l'invio in una funzione propria. È inoltre possibile usufruire di writev() per gestire coalescenza la stringa contenente il campo "lunghezza" con il buffer che contiene i dati effettivi e poi inviarli come un unico write() atomica.

codice non testato segue:

int write_message(int s, std::string msg)
{
     struct iovec iov[2];
     char hdr[5];

     char *cmsg = msg.c_str();
     int len = msg.length();

     snprintf(hdr, 5, "%04d", len);  // nb: assumes len <= 9999;

     iov[0].iov_base = hdr;
     iov[0].iov_len = 4;

     iov[1].iov_base = cmsg;
     iov[1].iov_len = len;

     return writev(s, iov, 2);
}

Altri suggerimenti

È necessario controllare i valori di ritorno di entrambi write e read non solo per -1 ma per brevi (meno di richiesta) scrive / legge. Lei sembra anche per continuare solo dopo la stampa di un errore con perror - fare un exit(2) o qualcosa là

.

Due cose:

In primo luogo -. Sul lato server che si sta scrivendo al largo della fine della matrice

char finalString[length];
bzero(finalString, sizeof(finalString));
strcpy(finalString, actualString.c_str());

Il strcpy() copierà caratteri length+1 in finalString (personaggio tirare il terminatore null).

In secondo luogo (e molto probabilmente ad essere il problema) - sul lato client che non sono di terminazione null la stringa che leggi, quindi il printf() potranno stampare la stringa, e quindi tutto ciò che è sullo stack fino al punto che colpisce un nullo.

Aumentare entrambi i buffer per uno, e si dovrebbe essere in una forma migliore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top