Question

Je ne parviens pas à comparer les chaînes en C (avec lesquelles je suis assez novice). J'ai un socket sur cette application serveur en attente d'accepter les données d'un client. Dans cette partie de mon programme, je souhaite pouvoir exécuter une requête MySQL en fonction des données reçues du client. Je veux pouvoir savoir quand les données reçues ont la valeur de "newuser". engager une procédure d'enregistrement simple. Strcmp renvoie une valeur positive de 1 où je pense que je devrais obtenir un 0 car les valeurs doivent être égales.

Code source:

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

Sortie:

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

J'ai l'impression que je ne gère pas correctement le tampon entrant ou que je ne le copie pas par erreur.

Était-ce utile?

La solution

strncpy copie au maximum - dans ce cas, sizeof octets de contrôle. Si l'octet nul n'est pas dans cette plage, il n'est pas copié. Vous obtenez probablement le mot " newuser " dans le cadre d'une phrase plus longue, comme "newuser bla blah" donc vous devez placer que nul vous-même

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

ou utilisez strlcpy , si disponible.

Autres conseils

Voici l'exemple de code que vous avez donné dans votre question (avec le code de débogage supprimé):

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

Ce code est faux; vous êtes potentiellement en train de copier plus d'octets de buf [] que ceux reçus. Cela vous amènera à comparer avec des ordures (qui, par hasard, pourraient correspondre à votre chaîne "newuser"). Et comme d’autres personnes l’ont dit, vous avez un deuxième bogue car NUL ne termine pas l’une de vos chaînes.

Dans ce cas, j'utiliserais memcmp (). Cela ressemble à strcmp (), mais il faut un paramètre de longueur plutôt que d’attendre des chaînes terminées par 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. Pas directement lié, mais recv () peut échouer en renvoyant -1 avec numéro d'erreur == EINTR . Ce n'est pas une condition d'erreur, il vous suffit d'essayer à nouveau. Normalement, cela se produit si rarement que les utilisateurs s'en sortent sans le vérifier, jusqu'à ce qu'ils intègrent un autre code qui utilise des signaux et que leur code échoue soudainement.

Dans une application basée sur select () , vous devez également définir vos sockets comme non bloquantes, puis rechercher errno == EAGAIN et revenir à le select () dans ce cas. Cela peut arriver si la pile TCP / IP reçoit un paquet corrompu - elle pense avoir un paquet, donc select () vous dira qu'il est lisible. Ce n'est que lorsque vous essayez de le lire que le protocole TCP / IP stack effectue le calcul de la somme de contrôle et se rend compte qu'il doit jeter les données. Il bloquera alors (mauvais) ou, s'il est défini sur non bloquant, il renverra -1 avec errno == EAGAIN .

Je pense que le problème ici (l'un des problèmes rencontrés) est que fromUser (en raison de la manière dont il est créé) n'est pas terminé (null).

Il manque le caractère '\ 0' à la fin de fromUser:

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

Deux modifications requises:

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

Ce code semble désactivé:

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

Remplacer par:

char check[] = "newuser\0";
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top