如何memcpy()一个struct sockaddr_in

时间:2015-04-01 18:56:52

标签: c c89

我正在编写服务器客户端程序。 在服务器上,我通过这个数据结构的数组来管理客户端:

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。但客户端的下一次尝试是成功的,一切都很顺利。为什么会这样?

1 个答案:

答案 0 :(得分:2)

addr_cli的来电未填写recvfromrecvfrom的最后两个论点有点棘手。他们是

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);