2015-04-01 129 views
2

我正在編程一個服務器端客戶端程序。 在服務器上我通過這個數據結構的陣列管理客戶端:如何memcpy()結構sockaddr_in

struct Client 
{ 
    struct sockaddr_in addr; 
    /*...*/ 
}; 

struct Client CLIENTS[MAX_CLI]; 

當我收到來自客戶端的第一個數據包通過我UDP插座

struct sockaddr_in addr_cli; 

memset(&addr_cli,0,sizeof(struct sockaddr_in)); 
b=recvfrom(SOCK_UDP_FATHER, &pdu, sizeof(pdu), MSG_DONTWAIT, 
    (struct sockaddr *)&addr_cli, (socklen_t *)&laddr_cli); 

我想他的地址複製到我的結構。所以我這樣做:

memcpy(&CLIENTS[client].addr,(struct sockaddr*)&addr_cli, 
    sizeof(struct sockaddr_in)); 

printf("IP client: %s",inet_ntoa(CLIENTS[client].addr.sin_addr); 

奇怪的是,通信的第一次嘗試失敗,打印0.0.0.0。但接下來的嘗試,客戶端,是成功的,一切都很好。爲什麼會發生?

+0

告訴你的代碼看起來不錯,所以原因必須是在其他地方。 – alk 2015-04-01 19:13:11

+2

然而,不需要cast'(struct sockaddr *)'。 – alk 2015-04-01 19:14:08

+2

顯示'addr_cli'的聲明。 – 2015-04-01 19:14:09

回答

2

​​未被recvfrom調用填充。 recvfrom的最後兩個參數有點棘手。他們是

struct sockaddr *src_addr, 
socklen_t *addrlen 

如果src_addr不爲空,則recvfrom預計addrlensrc_addr緩衝區的長度。 (通常它是sockaddr結構的大小)。如果addrlen的值太小,則返回的地址將被截斷。撥打recvfrom後,addrlen將被設置爲實際的地址長度。詳情請看documentation

所以你需要調用recvfrom()之前初始化laddr_cli

struct sockaddr_in addr_cli; 
socklen_t laddr_cli = sizeof(addr_cli); // <-- 

memset(&addr_cli,0,laddr_cli);  
b=recvfrom(SOCK_UDP_FATHER, &pdu, sizeof(pdu), MSG_DONTWAIT, 
    (struct sockaddr *)&addr_cli, &laddr_cli);