Pregunta

Tengo problemas para comparar cadenas en C (con las cuales soy bastante nuevo). Tengo un socket en esta aplicación de servidor esperando para aceptar datos de un cliente. En esta parte particular de mi programa, quiero poder ejecutar una consulta MySQL basada en los datos recibidos del cliente. Quiero poder saber cuándo los datos recibidos tienen el valor de "nuevo usuario" para iniciar un procedimiento de registro simple. Strcmp está devolviendo un valor positivo 1 donde creo que debería obtener un 0 porque los valores deberían ser iguales.

Código fuente:

//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");
    }

Salida:

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

Tengo la sensación de que no estoy manejando el búfer entrante correctamente o copiando erróneamente el búfer.

¿Fue útil?

Solución

strncpy copia a lo sumo, en este caso, sizeof comprueba los bytes. Si el byte nulo no está en ese rango, no se copia. Probablemente esté recibiendo la palabra "nuevo usuario" como parte de una oración más larga, como "newuser blah blah" así que debes colocar ese nul tú mismo

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

o use strlcpy , si está disponible.

Otros consejos

Aquí está el código de muestra que proporcionó en su pregunta (con el código de depuración eliminado):

//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");
    }

Este código está mal; potencialmente está copiando más bytes de buf [] de los que se han recibido. Esto lo llevará a comparar con la basura (que por casualidad podría coincidir con su cadena de "nuevo usuario"). Y como han dicho otras personas, tiene un segundo error debido a que NUL no termina una de sus cadenas.

En este caso, usaría memcmp (). Esto es como strcmp () pero toma un parámetro de longitud en lugar de esperar cadenas terminadas en 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. No está directamente relacionado, pero recv () puede fallar al devolver -1 con errno == EINTR . Esta no es una condición de error, solo necesita volver a intentarlo. Normalmente esto sucede tan raramente que las personas se escapan sin verificarlo, hasta que se integran con algún otro código que usa señales y de repente su código falla al azar.

En una aplicación basada en select () , también debe configurar sus sockets para que no se bloqueen y luego verificar errno == EAGAIN , y volver a select () en ese caso. Esto puede suceder si la pila TCP / IP recibe un paquete dañado: cree que tiene un paquete, por lo que select () le dirá que es legible, solo cuando intenta leerlo el TCP / IP stack realiza el cálculo de la suma de comprobación y se da cuenta de que tiene que tirar los datos. Luego bloqueará (incorrecto), o si está configurado para no bloquear, devolverá -1 con errno == EAGAIN .

Creo que el problema aquí (uno de los problemas aquí) es que fromUser (debido a la forma en que se creó) no se termina de forma nula.

Echas de menos '\ 0' char al final de fromUser:

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

Se requieren dos cambios:

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

Este código parece estar apagado:

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;
}

Reemplazar con:

char check[] = "newuser\0";
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top