2014-02-21 29 views
0

之後數組值出現意外的改變,我運行了兩個客戶端實例。現在我第一次運行客戶端,接收到的數據被保存到數組[0]中,但是當我運行第二個客戶端時,array [0]的值會被新值覆蓋。新數據將保存在數組[1]中而不是覆蓋。我犯了什麼錯誤?在我運行服務器之後recv()

char * Array [100]; int ArrayCount = 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"); 
} 
} 

輸出如下:

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 

的recv後理想地數據應該是 「第一實例」,因爲我打印陣列[0]。

+0

'struct hostent * hp,* gethostbyname();'是壞的。相反,'#include'適當的頭文件。或者更好,用新的getaddrinfo()和getnameinfo()替換'getservbyname()'和'gethostbyname()'。 – glglgl

回答

4

這種分配在服務器代碼中沒有做你想要什麼:

Array[ArrayCount] = revdData; 

這是無效的代碼,因爲revdData是本地陣列範圍限定於server()。該賦值不復制數組,它將指針複製到其第一個元素。因此,當您從server()返回時,Array包含指向無效位置的指針 - 本地revdData陣列的內存無效。接下來發生的事情未知。通常,由於您將再次調用server(),因此很有可能相同的內存空間正在被重新用於新的revdData陣列,因此最終會覆蓋您不想要的內容。

要解決該問題,您必須先分配內存Array[ArrayCount],然後使用strncpy或使用strndup

這裏是你可以用strncpy做什麼:

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

此外,您還可以從int改變nsssize_t,這是recv返回類型。

如果你想使用strndup,你並不需要顯式地使用malloc,但是,如果你的數據包含空字節,它不會複製超越這一點,如果沒有,它會添加一個空字節在重複的字符串中,這可能不是你想要的。

請注意,這種方法引入了內存管理的問題;在某些時候,您必須釋放爲Array中的每個位置分配的內存。您有責任這樣做,儘管在小程序中您通常可以依賴於所有分配的內存在程序終止時被操作系統釋放的事實。

1

您只需將指針revdData複製到Array[i]即可。因此,您所有的Array元素僅指向revdData

您應該爲Array元素分配一些內存,並將revdData的值複製到Array[ArrayCount]

// 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

相關問題