2015-04-01 4 views
2

Я программирую сервер-клиентскую программу. На сервере я могу управлять своими клиентами через массив этой структуры данных:Как memcpy() struct 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

+2

Листинг '(struct sockaddr *)' однако не нужен. – alk

+2

Показать объявление 'addr_cli'. –

ответ

2

addr_cli не был заполнен по вызову recvfrom. Последние два аргумента recvfrom немного сложны. Они

struct sockaddr *src_addr, 
socklen_t *addrlen 

Если src_addr не NULL, то recvfrom ожидает, что addrlen указывает на длину src_addr буфера. (Обычно это размер структуры sockaddr). Если значение addrlen слишком мало, возвращаемый адрес будет усечен. После вызова recvfrom значение addrlen будет установлено на фактическую длину адреса. Посмотрите на documentation.

Таким образом, вы должны инициализировать laddr_cli перед вызовом recvfrom():

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); 
Смежные вопросы