2014-02-21 1 views
0

서버를 실행 한 후 두 개의 클라이언트 인스턴스를 실행합니다. 이제 클라이언트를 처음 실행하면 수신 된 데이터가 배열 [0]에 저장되지만 두 번째 클라이언트를 실행하면 array [0]의 값이 새로운 값으로 놀랍게 덮어 씁니다. 새 데이터는 덮어 쓰지 않고 배열 [1]에 저장됩니다. 어떤 실수를 저질렀습니까?배열 값이 예기치 않게 변경된 후 recv()

char * Array [100]; int ArrayCount = 0; 전역 변수입니다. RECV 후

data in Array[0] before recv : (null) 
data in Array[0] after recv : (null) 
data in Array[0] before recv : 1st Instance 
data in Array[0] after recv : 2nd Instance 

적 데이터가 "1 인스턴스"이어야 나 배열을 인쇄이기 때문에, [0]

void *server() 
{ 
int listenfd = 0; 
connfd = 0; 
struct sockaddr_in serv_addr; 

listenfd = socket(AF_INET, SOCK_STREAM, 0); 
memset(&serv_addr, '0', sizeof(serv_addr)); 

serv_addr.sin_family = AF_INET; 
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
serv_addr.sin_port = htons(atoi(port)); 

if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))<0) 
{ 
    perror("bind"); 
    exit(1); 
} 

listen(listenfd, 10); 

while(1) 
{ 
    connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); 

    printf("data in Array[0] before recv : %s\n",Array[0]); 

    int ns; 
    char revdData[2000]; 
    bzero(revdData,2000); 
    ns = recv(connfd,revdData,2000,0); 
    close(connfd); 

    printf("data in Array[0] after recv : %s\n",Array[0]); 

    Array[ArrayCount] = revdData; 
    ArrayCount = ArrayCount+1; 
} 
} 

클라이언트 코드

void *client() 
{ 

int soctype = SOCK_STREAM; 
struct hostent *hp, *gethostbyname(); 
struct sockaddr_in servR; 
struct servent *seR; 
int tempSocket; 
char *host = "localhost"; 

if ((tempSocket = socket(AF_INET, soctype, 0)) < 0) 
{ 
    perror("socket"); 
    exit(1); 
} 

if ((hp = gethostbyname(host)) == NULL) 
{ 
    exit(1); 
} 

servR.sin_family = AF_INET; 
memcpy(&servR.sin_addr, hp->h_addr, hp->h_length); 
if (isdigit(*port)) 
{ 
    servR.sin_port = htons(atoi(port)); 
} 
else 
{ 
    if ((seR = getservbyname(port, (char *)NULL)) < (struct servent *) 0) 
    { 
     perror(port); 
     exit(1); 
    } 
    servR.sin_port = seR->s_port; 
} 


if (connect(tempSocket, (struct sockaddr *) &servR, sizeof(servR)) < 0) 
{ 
    perror("connect"); 
    exit(1); 
} 

char input[100]; 
fgets(input,100,stdin); 
int n; 
n=send(tempSocket,input,100,0); 
if (n < 0) 
{ 
    error("Send"); 
} 
} 

출력은 다음과 같다. revdDataserver()로 구분 된 범위가 로컬 배열이기 때문에

Array[ArrayCount] = revdData; 

이 잘못된 코드 :

+0

'struct hostent * hp, * gethostbyname();'이 잘못되었습니다. 대신, 적절한 헤더 파일을'#include '한다. 아니면 더 나은,'getaddrinfo()'와'getnameinfo()'에 의해'getservbyname()'과'gethostbyname()'을 대체하십시오. – glglgl

답변

4

서버 코드에서이 할당은 당신이 원하는 일을하지 않습니다. 할당은 배열을 복사하지 않고 포인터를 첫 번째 요소에 복사합니다. 따라서 server()에서 돌아 오면 Array에 잘못된 위치에 대한 포인터가 포함되어 있습니다. 로컬 revdData 배열의 메모리가 유효하지 않습니다. 다음에 일어날 일은 알려지지 않았습니다. 일반적으로 server()을 다시 호출하므로 새로운 revdData 배열에 대해 동일한 메모리 공간이 재사용 될 가능성이 높습니다. 따라서 원하지 않는 것을 덮어 씁니다.

수정하려면 Array[ArrayCount]에 메모리를 할당 한 다음 strncpy을 사용하거나 strndup을 사용해야합니다.

다음은 strncpy로 할 수있는 작업은 다음과 같습니다 또한

Array[ArrayCount] = malloc(ns); 
strncpy(Array[ArrayCount], revdData, (size_t) ns); 

, 당신은 recv의 반환 유형입니다 ssize_tint에서 ns을 변경할 수 있습니다.

당신이 strndup를 사용하려는 경우, 당신은 명시 적으로 데이터가 null 바이트를 포함하는 경우 그러나, 그것은 그 시점을 넘어 복사하지 않습니다, malloc를 사용할 필요가 없습니다되어 있지 않으면, 그것은 널을 추가합니다 중복 된 문자열의 바이트. 원하는 문자열이 아닐 수도 있습니다.

이 접근 방식은 메모리 관리의 문제를 유발한다는 점에 유의하십시오. 어떤 시점에서 Array에서 찍은 각 위치에 할당 된 메모리를 확보해야합니다. 작은 프로그램에서는 일반적으로 프로그램이 종료되면 할당 된 모든 메모리가 운영 체제에 의해 해제된다는 사실에 의존 할 수 있지만 책임은 사용자에게 있습니다.

1

포인터 revdDataArray[i]에 복사하는 중입니다. 따라서 모든 Array 요소는 revdData을 가리 킵니다.

당신은 당신의 Array 요소에 약간의 메모리를 할당하고 Array[ArrayCount]으로 revdData의 값을 복사해야합니다.

// Just after you recv 
Array[ArrayCount] = malloc(sizeof(char) * ns); 
strncpy(Array[ArrayCount], revdData, (size_t)ns); 
ArrayCount++; 


// Free allocated memory before you exit 
for(i = 0; i < ArrayCount; i++) { 
    free(Array[ArrayCount]); 
    Array[ArrayCount] = 0; 
} 

더 나은 클라이언트/서버 디자인을 보려면 튜토리얼을 참조하십시오.

+0

이것은 작동하지 않습니다. 'sizeof (Array [ArrayCount])'를'strncpy'에 넘겨 줄 수 없습니다. 왜냐하면 그것은'char * '의 크기로 평가 될 것이기 때문에 당신이 원하는 것이 아닙니다. 'Array [ArrayCount]'는 배열이 아니므로 포인터입니다. 이것을'ns'로 대체해야합니다. –

+0

@ FilipeGonçalves 감사 :-) – HAL

관련 문제