2014-11-01 85 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