Linux 获取接收到的 UDP 数据包的目标地址
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5281409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get destination address of a received UDP packet
提问by Matt Joiner
Upon receiving a UDP packet, I need to respond to the sender with the address he used to send the packet to which I'm replying.
收到 UDP 数据包后,我需要使用他用来发送我正在回复的数据包的地址来响应发件人。
The recvfrom
call lets me get the address of the sender, but how do I get the destination address of the received packet, which should match the address of one of the local host's interfaces?
该recvfrom
调用让我获得了发送方的地址,但是我如何获得接收到的数据包的目标地址,它应该与本地主机的接口之一的地址相匹配?
采纳答案by gby
You set the IP_PKTINFO option using setsockopt and then use recvmsg and get a in_pktinfo structure in the msg_control member of struct msghdr. the in_pktinfo has a field with the destination address of the packet.
您使用setsockopt 设置IP_PKTINFO 选项,然后使用recvmsg 并在struct msghdr 的msg_control 成员中获取in_pktinfo 结构。in_pktinfo 有一个字段,其中包含数据包的目标地址。
See: http://www.linuxquestions.org/questions/programming-9/how-to-get-destination-address-of-udp-packet-600103/where I found the answer for more details.
请参阅:http: //www.linuxquestions.org/questions/programming-9/how-to-get-destination-address-of-udp-packet-600103/在那里我找到了更多详细信息的答案。
回答by Matt Joiner
I've constructed an example that extracts the source, destination and interface addresses. For brevity, no error checking is provided.
我已经构建了一个提取源、目标和接口地址的示例。为简洁起见,不提供错误检查。
// sock is bound AF_INET socket, usually SOCK_DGRAM
// include struct in_pktinfo in the message "ancilliary" control data
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
// the control data is dumped here
char cmbuf[0x100];
// the remote/source sockaddr is put here
struct sockaddr_in peeraddr;
// if you want access to the data you need to init the msg_iovec fields
struct msghdr mh = {
.msg_name = &peeraddr,
.msg_namelen = sizeof(peeraddr),
.msg_control = cmbuf,
.msg_controllen = sizeof(cmbuf),
};
recvmsg(sock, &mh, 0);
for ( // iterate through all the control headers
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&mh, cmsg))
{
// ignore the control headers that don't match what we want
if (cmsg->cmsg_level != IPPROTO_IP ||
cmsg->cmsg_type != IP_PKTINFO)
{
continue;
}
struct in_pktinfo *pi = CMSG_DATA(cmsg);
// at this point, peeraddr is the source sockaddr
// pi->ipi_spec_dst is the destination in_addr
// pi->ipi_addr is the receiving interface in_addr
}