Domanda

Ho problemi a confrontare le stringhe in C (con le quali sono abbastanza nuovo). Ho socket su questa applicazione server in attesa di accettare dati da un client. In questa particolare parte del mio programma voglio essere in grado di eseguire una query MySQL sulla base dei dati ricevuti dal client. Voglio essere in grado di sapere quando i dati ricevuti hanno il valore di "nuovo utente" per avviare una semplice procedura di registrazione. Strcmp sta restituendo un valore 1 positivo dove credo che dovrei ottenere uno 0 perché i valori dovrebbero essere uguali.

Codice sorgente:

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
    if (nbytes == 0) {
        // connection closed
        printf("selectserver: socket %d hung up\n", i);
    } else {
        perror("recv");
    }
    close(i); // bye!
    FD_CLR(i, &master); // remove from master set
} else {

    char check[] = "newuser";
    char fromUser[sizeof check];

    strncpy(fromUser,buf, sizeof check);
    printf("length of fromUser: %d\n", sizeof fromUser);
    printf("length of check: %d\n", sizeof check);
    printf("message from user: %s\n", fromUser);
    printf("check = %s \n", check);
    int diff = strcmp(fromUser, check);
    printf("compare fromUser to check: %d\n", diff);
    if ( strcmp(fromUser, check) == 0) {
        printf("aha! new user");
    }

Output:

length of fromUser: 8
length of check: 8
newuser from user: newuser
check = newuser 
compare fromUser to check:

Ho la sensazione di non gestire correttamente il buffer in entrata o di copiarlo erroneamente.

È stato utile?

Soluzione

strncpy copia al massimo - in questo caso - sizeof controlla i byte. Se il byte nul non è compreso in tale intervallo, non viene copiato. Probabilmente stai ricevendo la parola "newuser" come parte di una frase più lunga, come "newuser blah blah" quindi è necessario posizionarlo da soli

strncpy(fromUser, buf, sizeof check);
fromUser[sizeof check - 1] = '\0';

o usa strlcpy , se disponibile.

Altri suggerimenti

Ecco il codice di esempio che hai fornito nella tua domanda (con il codice di debug rimosso):

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
    [... exception handling here ...]
} else {
    char check[] = "newuser";
    char fromUser[sizeof check];

    strncpy(fromUser,buf, sizeof check);
    if ( strcmp(fromUser, check) == 0) {
        printf("aha! new user");
    }

Questo codice è sbagliato; stai potenzialmente copiando più byte da buf [] di quanti ne siano stati ricevuti. Questo ti porterà a confrontarti con la spazzatura (che potrebbe per caso coincidere con la tua stringa "newuser"). E come altri hanno già detto, hai un secondo bug dovuto al fatto che NUL non termina una delle tue stringhe.

In questo caso, userei memcmp (). Questo è come strcmp () ma richiede un parametro di lunghezza anziché aspettarsi stringhe terminate con NUL.

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
    [... exception handling here ...]
} else {
    static const char check[] = "newuser";
    const size_t check_len = sizeof(check) - 1; // exclude the NUL terminator
    if (nbytes >= check_len && memcmp(buf, check, check_len) == 0) {
        printf("aha! new user");
    }

P.S. Non direttamente correlato, ma recv () può fallire restituendo -1 con errno == EINTR . Questa non è una condizione di errore, devi solo riprovare. Normalmente questo accade così raramente che le persone se ne vanno senza controllarlo, fino a quando non si integrano con qualche altro codice che utilizza segnali e improvvisamente il loro codice fallisce in modo casuale.

In un'app basata su select () , dovresti anche impostare i socket su non-blocking, quindi controllare errno == EAGAIN e tornare a il select () in quel caso. Questo può accadere se lo stack TCP / IP riceve un pacchetto danneggiato - pensa di avere un pacchetto quindi select () ti dirà che è leggibile, è solo quando provi a leggerlo che il TCP / IP stack esegue il calcolo del checksum e si rende conto che deve eliminare i dati. Quindi bloccherà (non valido) o se è impostato su non-bloccante, restituirà -1 con errno == EAGAIN .

Credo che il problema qui (uno dei problemi qui) sia che fromUser (a causa del modo in cui è stato creato) non è risolto da null.

Ti manca il carattere '\ 0' alla fine di fromUser:

...
strncpy(fromUser,buf, sizeof check);
fromUser[strlen(check)] = '\0';

Sono necessarie due modifiche:

char fromUser[sizeof check] = {'\0'}; //Make all null characters
strncpy(fromUser,buf, sizeof check -1); //Last character is for null character.

Questo codice sembra disattivato:

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) 
{
 // your stuff
} 
else {
const char *pCheck = "newuser";
char *fromUser = new char[nbytes];
strncpy(fromUser, buff, nbytes);
fromUser[nbytes] = '\0';
if(strcmp(fromUser,check)==0)
 // blah

delete [] fromUser;
}

Sostituisci con:

char check[] = "newuser\0";
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top