2014-11-01 90 views
0

我沒有第一次獲得正確的客戶端IP地址。這是我的服務器主代碼。第一次沒有正確獲取客戶端IP地址

server.c

int main() 
{ 
    int sockfd, connfd, lisfd, retval; 

    struct sockaddr_in servaddr, clntaddr; 
    socklen_t client; 
    struct packet pckt; 
    int clnt_len; 
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
      perror("socket"); 
      exit(1); 
    } 

    memset(&servaddr, 0, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(8000); 
    retval = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 
    if(retval) { 
      perror("bind"); 
    } 

    if((lisfd = listen(sockfd, 4)) < 0) { 
      perror("listen"); 
      exit(3); 
    } 
    clnt_len = sizeof(clnt_len)-1; // clnt_len = sizeof(clnt_len); 
    while(1) { 
      if((connfd = accept(sockfd, (struct sockaddr *)&clntaddr, &clnt_len)) < 0) { 
        perror("accept"); 
        exit(2); 
      } 
      printf("IP address is: %s\n", inet_ntoa(clntaddr.sin_addr)); 

      read(connfd, &pckt, sizeof(pckt)); 
      printf("%s\n", pckt.msg); 

    } 

}

packet是在hdr.h像以下聲明的結構。

struct packet { 
    char msg[50]; 
    int cmd; 
}; 

輸出是:

IP address is: 255.127.0.0 
Hi 
IP address is: 127.0.0.1 
Hello 
IP address is: 127.0.0.1 
Good 
... 

對於第一次,我得到了錯誤的IP。我不明白髮生了什麼事?如何獲得正確的IP?

回答

1

正如accept(2)手冊頁解釋,clnt_len應該被初始化爲可用大小的clntaddr調用accept()前:

while(1) { 
    clnt_len = sizeof clntaddr; 
    if ((connfd = accept(sockfd, (struct sockaddr *)&clntaddr, &clnt_len)) < 0) { 
     perror("accept"); 
     exit(2); 
    } 

編輯:clnt_len = sizeof(clnt_len)-1; // clnt_len = sizeof(clnt_len);是有問題的線路。它將clnt_len設置爲無效值:一個小於套接字長度變量的長度,當它應該是clntaddr中可用的內存量時。

這小於sizeof (struct sockaddr_in),因此當accept()返回第一個連接時clntaddr將不會被分配。 clnt_len確實被分配到客戶端地址的長度(是的,它允許大於其原始值;這意味着clntaddr不夠大;詳情請參閱man page),因此在以下連接上,clnt_len是合適的大小,並且您獲得了第二個和更多連接的地址,僅缺少初始連接地址。

要修復,請將clnt_len = sizeof clntaddr;行添加到while (1) lopp主體的開頭。

有問題?

+0

你怎麼想象clnt_len沒有被初始化?如果clnt_len爲0,那麼我會得到「不良地址」錯誤。 – SGG 2014-11-01 18:40:13

+1

@SGG:我不是傳心者!您的代碼不會初始化它。如果您的實際代碼不同,請適當修復您問題中的代碼。至於'clnt_len',我錯了;在第一次調用期間,它很可能介於1和'sizeof(struct sockaddr_in)-1'之間 - 這正好解釋了您所看到的症狀。修正了我的答案,謝謝。 – 2014-11-01 18:42:38

+0

已編輯的問題。 – SGG 2014-11-01 18:55:07