문제

나는 C에서 문자열을 비교하는 데 어려움을 겪고있다 (내가 상당히 새로운). 이 서버 애플리케이션에 소켓이 클라이언트의 데이터를 수락하기 위해 기다리고 있습니다. 내 프로그램 의이 특정 부분에서는 클라이언트로부터받은 데이터를 기반으로 MySQL 쿼리를 실행할 수 있기를 원합니다. 수신 된 데이터에 간단한 등록 절차를 시작하기 위해 "NewUser"의 값이 언제인지 알 수 있습니다. STRCMP는 값이 같아야하기 때문에 0을 받아야한다고 생각하는 양의 1 값을 반환합니다.

소스 코드:

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

산출:

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

들어오는 버퍼를 올바르게 처리하거나 버퍼를 잘못 복사하지 않는 느낌이 듭니다.

도움이 되었습니까?

해결책

strncpy 최대 사본 -이 경우 - sizeof 바이트를 점검하십시오. NUL 바이트가 해당 범위에 있지 않으면 복사되지 않습니다. 당신은 아마도 "Newuser blah blah"와 같은 더 긴 문장의 일부로 "Newuser"라는 단어를 얻을 것입니다.

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

또는 사용 strlcpy, 가능한 경우.

다른 팁

다음은 질문에 제공 한 샘플 코드입니다 (디버깅 코드가 제거됨) :

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

이 코드는 잘못되었습니다. 받은 것보다 buf []에서 더 많은 바이트를 복사 할 수 있습니다. 이로 인해 쓰레기와 비교할 수 있습니다 (우연히 "Newuser"문자열과 일치 할 수 있습니다). 그리고 다른 사람들이 말했듯이, 당신은 당신의 줄 중 하나를 종료하지 않기 때문에 두 번째 버그가 있습니다.

이 경우 memcmp ()를 사용합니다. 이것은 strcmp ()와 같지만 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");
    }

추신은 직접 관련이 없지만 recv () 돌아와서 실패 할 수 있습니다 -1 ~와 함께 errno==EINTR. 이것은 오류 조건이 아니며 다시 시도하면됩니다. 일반적으로 이것은 사람들이 신호를 사용하고 갑자기 코드가 무작위로 실패하는 다른 코드와 통합 될 때까지 사람들이 확인하지 않고 도망 갈 수 없습니다.

안에 select()-기반 앱, 소켓을 차단하지 않은 상태로 설정 한 다음 확인해야합니다. errno==EAGAIN, 그리고 다시 돌아갑니다 select() 이 경우. TCP/IP 스택에 손상된 패킷을받는 경우 발생할 수 있습니다. 패킷이 있다고 생각합니다. select() 읽을 수 있다고 말할 것입니다. TCP/IP 스택이 체크섬 계산을 수행하고 데이터를 버려야한다는 사실을 읽으려고 할 때만 가능합니다. 그런 다음 블록 (나쁜)이거나 차단되지 않은 상태로 설정되면 반환됩니다. -1 ~와 함께 errno==EAGAIN.

여기서 문제가있는 문제는 (여기서 문제 중 하나) FromUser (생성 방식으로 인해)가 널 종료되지 않았다는 것입니다.

Fromuser의 끝에서 ' 0'숯을 그리워합니다.

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

필요한 두 가지 변경 사항 :

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

이 코드는 다음과 같습니다.

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

대체 : :

char check[] = "newuser\0";
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top