简体   繁体   English

如何 memcpy() 结构 sockaddr_in

[英]How to memcpy() a struct sockaddr_in

I'm programming a server-client program.我正在编写一个服务器-客户端程序。 On the server I manage the clients through an array of this data structure:在服务器上,我通过这个数据结构的数组来管理客户端:

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

struct Client CLIENTS[MAX_CLI];

When I receive the first packet from the client through my UDP socket当我通过我的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);

I want to copy his address to my struct.我想将他的地址复制到我的结构中。 So I do:所以我这样做:

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

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

The strange thing is that the first try of communication fails, printing 0.0.0.0 .奇怪的是,第一次尝试通信失败,打印0.0.0.0 But the next try that the client does, is successful and everything goes fine.但是客户的下一次尝试是成功的,一切都很顺利。 Why that happens?为什么会这样?

The addr_cli was not filled by the call to recvfrom .recvfrom的调用未填充addr_cli The last two arguments of recvfrom are a little bit tricky. recvfrom的最后两个 arguments 有点棘手。 They are他们是

struct sockaddr *src_addr,
socklen_t *addrlen

If src_addr is not NULL, the recvfrom expects that addrlen points to the length of src_addr buffer.如果src_addr不是 NULL, recvfrom期望addrlen指向src_addr缓冲区的长度。 (Normally it is the size of sockaddr structure). (通常是sockaddr结构的大小)。 If the value of addrlen is too small, the returned address will be truncated.如果addrlen的值太小,返回的地址会被截断。 After the call to recvfrom the addrlen will be set to the actual address length.调用recvfromaddrlen将设置为实际地址长度。 Look at documentation for details.查看文档了解详细信息。

So you need to initialize laddr_cli before calling recvfrom() :所以你需要在调用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);

I had a problem just this morning when I tried to copy an address returned from getaddrinfo.就在今天早上,当我试图复制从 getaddrinfo 返回的地址时,我遇到了一个问题。 It's probably similar to your problem copying an address returned from recvfrom.这可能类似于您复制从 recvfrom 返回的地址的问题。

I had a struct addrinfo *rp, and I wanted to copy rp->ai_addr to local storage so I could be sure it would stick around after calling freeaddrinfo.我有一个 struct addrinfo *rp,我想将 rp->ai_addr 复制到本地存储,这样我可以确定它会在调用 freeaddrinfo 后继续存在。 This worked:这有效:

struct sockaddr_storage addr;
memcpy(&addr, rp->ai_addr, rp->ai_addrlen);

In my case I could not declare addr as a sockaddr_in because that would overflow the buffer when I saw an AF_INET6 address.在我的情况下,我不能将 addr 声明为 sockaddr_in,因为当我看到 AF_INET6 地址时,这会溢出缓冲区。 Using sockaddr_in6 worked, but I am sticking with sockaddr_storage so I can be absolutely protocol neutral in case new address families crop up.使用 sockaddr_in6 有效,但我坚持使用 sockaddr_storage,因此如果出现新的地址系列,我可以绝对保持协议中立。

EDIT: That said, it does seem a bit wasteful to keep an entire struct sockaddr_storage as a field in a client structure.编辑:也就是说,将整个 struct sockaddr_storage 保留为客户端结构中的字段似乎有点浪费。 That thing is 128 bytes.那东西是128字节。 A struct sockaddr_in6 is only 28 bytes. struct sockaddr_in6 只有 28 个字节。 How "protocol neutral" do I really need to be?我真的需要多“协议中立”?

Probably better to keep a sockaddr_in6 and if I ever see an address length greater than that, just have the program die.保留 sockaddr_in6 可能更好,如果我看到地址长度大于这个长度,就让程序死掉。 That way if someone comes up with a new family AF_WEIRD that's 37 bytes long, I could adapt to it then without having to burn 128 bytes all time until then.这样,如果有人提出一个 37 字节长的新系列 AF_WEIRD,我就可以适应它,而不必一直烧掉 128 字节。

Not only that, but my server sets hints to AF_INET6 anyway, which allows it to receive either AF_INET or AF_INET6 packets, while presumably dropping any new AF_WEIRD.不仅如此,我的服务器还是将提示设置为 AF_INET6,这允许它接收 AF_INET 或 AF_INET6 数据包,同时可能会丢弃任何新的 AF_WEIRD。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM