2009-06-22 12 views
0

Ich habe Probleme beim Vergleich Strings in C (mit denen ich ziemlich neu bin). Ich habe Socket auf dieser Server-Anwendung, die darauf wartet, Daten von einem Client zu akzeptieren. In diesem speziellen Teil meines Programms möchte ich in der Lage sein, eine MySQL-Abfrage basierend auf den vom Client empfangenen Daten auszuführen. Ich möchte wissen können, wann die empfangenen Daten den Wert "newuser" haben, um eine einfache Registrierungsprozedur zu initiieren. Strcmp gibt einen positiven 1-Wert zurück, wo ich glaube, dass ich eine 0 bekommen sollte, weil die Werte gleich sein sollten.Vergleiche Strings in C - strcmp

Source Code:

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

Ausgang:

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

Ich habe das Gefühl, ich bin nicht der eingehenden Puffer richtig oder falsch den Puffer kopiert Handhabung.

+1

Sie protokollieren nicht den Wert fromUser, nur seine Länge. – Tom

Antwort

6

strncpy Kopien höchstens - in diesem Fall - sizeof Prüfbytes. Wenn das Null-Byte nicht in diesem Bereich liegt, wird es nicht kopiert. Sie sind wahrscheinlich immer das Wort „newuser“ als Teil eines längeren Satz, wie „newuser bla bla“, so dass Sie Platz benötigen, die sich NUL

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

oder verwenden strlcpy, falls vorhanden.

+0

+1 für die Erwähnung von Strlcpy – Tom

2

Ich glaube, das Problem hier (eines der Probleme hier) ist, dass fromUser (aufgrund der Art, wie es erstellt wird) nicht null beendet ist.

2

Sie vermissen '\ 0' Zeichen am Ende fromuser:

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

Wäre das nicht die Größe (Check) - 1? – DeadHead

-1

Ersetzen durch:

char check[] = "newuser\0"; 
+1

doppelte Anführungszeichen erzeugen Null abgeschlossene Zeichenfolge von sich selbst, nicht wahr? – cube

+1

"" Literale sind implizit NUL terminiert. Hinzufügen eines anderen NUL hilft hier nicht. – laalto

1

Zwei Änderungen erforderlich:

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

Dieser Code scheint aus:

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

Hier ist der Beispielcode Sie in Ihrer Frage gab (mit Debugging-Code entfernt):

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

Dieser Code ist falsch; Sie kopieren möglicherweise mehr Bytes von buf [] als empfangen wurden. Dies wird dazu führen, dass Sie mit Müll vergleichen (das könnte zufälligerweise mit Ihrer "newuser" Zeichenfolge übereinstimmen). Und wie andere Leute gesagt haben, haben Sie einen zweiten Fehler, weil NULL keine Ihrer Strings beendet.

In diesem Fall würde ich memcmp() verwenden. Dies ist wie strcmp(), aber es dauert ein Längenparameter, anstatt NUL-terminierte Strings zu erwarten.

//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. Nicht direkt verwandt, aber recv() kann fehlschlagen, indem -1 mit errno==EINTR zurückgibt. Dies ist kein Fehler, Sie müssen es nur noch einmal versuchen. Normalerweise geschieht dies so selten, dass die Leute davonkommen, ohne es zu überprüfen, bis sie sich mit irgendeinem anderen Code, der Signale verwendet, integrieren und plötzlich ihr Code zufällig ausfällt.

In einer select() -basierte App, sollten Sie auch Ihre Sockets nicht blockierend werden Einstellung und dann für errno==EAGAIN überprüfen, und gehen Sie zurück zum select() in diesem Fall. Dies kann passieren, wenn der TCP/IP-Stapel ein beschädigtes Paket empfängt - er denkt, dass es ein Paket hat, also sagt select() Ihnen, dass es lesbar ist, es ist nur, wenn Sie versuchen, es zu lesen, dass der TCP/IP-Stapel die Prüfsummenberechnung ausführt um die Daten wegzuwerfen. Es wird dann entweder blockiert (schlecht), oder wenn es auf nicht blockierend eingestellt ist, wird es -1 mit errno==EAGAIN zurückgeben.