LinuxC下获取UDP包中的路由目的IP地址和头标识目的地址

您所在的位置:网站首页 ip头结构体 LinuxC下获取UDP包中的路由目的IP地址和头标识目的地址

LinuxC下获取UDP包中的路由目的IP地址和头标识目的地址

2023-09-19 01:14| 来源: 网络整理| 查看: 265

在接受到UDP包后,有时候我们需要根据所接收到得UDP包,获取它的路由目的IP地址和头标识目的地址。

(一)主要的步骤:

在setsockopt中设置IP_PKTINFO,然后通过recvmsg来获取struct in_pktinfo(struct in_pktinfo是struct msghdr中msg_control的成员).in_pktinfo 结构体(如下所示),我们可以从in_pktinfo中获取路由目的地址(destination address of the packet)、头标识目的地址(source address of the packet)。这种方法只能用于UDP(数据报)传输中。

struct in_pktinfo { unsigned int ipi_ifindex; /* 接口索引 */ struct in_addr ipi_spec_dst; /* 路由目的地址 */ struct in_addr ipi_addr; /* 头标识目的地址 */ };

ipi_ifindex指的是接收包的接口的唯一索引,ipi_spec_dst指的是路由表记录中的目的地址,而ipi_addr 指的是包头中的目的地址。如果给 setsockopt传递了IP_PKTINFO,那么外发的包会通过在ipi_ifindex中指定的接口发送出去,同时把ipi_spec_dst设置为目的地址。

(二)下面的例子简单地说明如何获取UDP包中的源地址(interface addresses)、目标地址(destination addresses)。为了代码的简单,下面代码段省去了错误检查。 // sock 使用AF_INET协议族, socket类型SOCK_DGRAM setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)); // 这里,控制数据是脏数据。 char cmbuf[0x100]; // 目标IP地址 struct sockaddr_in peeraddr; //如果你想要获取UDP包中的数据,那么还需要为msg_iovec字段初始化 struct msghdr mh = { .msg_name = &peeraddr, .msg_namelen = sizeof(peeraddr), .msg_control = cmbuf, .msg_controllen = sizeof(cmbuf), }; recvmsg(sock, &mh, 0); struct cmsghdr *cmsg ; for ( // 遍历所有的控制头(the control headers) cmsg = CMSG_FIRSTHDR(&mh); cmsg != NULL; cmsg = CMSG_NXTHDR(&mh, cmsg)) { // 忽略我们不需要的控制头(the control headers) if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO) { continue; } struct in_pktinfo *pi = CMSG_DATA(cmsg); // 在这里, peeraddr是本机的地址(the source sockaddr) // pi->ipi_spec_dst 是UDP包中路由目的地址(the destination in_addr) // pi->ipi_addr 是UDP包中的头标识目的地址(the receiving interface in_addr) } (三)下面我将给出一个完整可运行的例子,这个例子实现了接收UDP广播包,发送UDP广播包,并在接收的时候,打印出UDP包的路由目的IP地址和头标识目的地址。 #include #include #include #include #include #define BUFLEN 255 int main ( int argc, char **argv ) { struct sockaddr_in peeraddr, localaddr; int sockfd; int socklen, n; //(1)创建UDP数据报socket描述符 sockfd = socket ( AF_INET, SOCK_DGRAM, 0 ); if ( sockfdcmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO ) { continue; } struct in_pktinfo *pi = CMSG_DATA ( cmsg ); //(10)将地址信息转换后输出 char dst[100],ipi[100];//用来保存转化后的源IP地址,目标主机地址 // pi->ipi_spec_dst 是UDP包中的路由目的IP地址(the destination in_addr) // pi->ipi_addr 是UDP包中的头标识目的地址(the receiving interface in_addr) if ( ( inet_ntop ( AF_INET,& ( pi->ipi_spec_dst ),dst,sizeof ( dst ) ) ) !=NULL ) { printf ( "路由目的IP地址IPdst=%s\n",dst); } if ( ( inet_ntop ( AF_INET,& ( pi->ipi_addr ),ipi,sizeof ( ipi ) ) ) !=NULL ) { printf ("头标识目的地址ipi_addr=%s\n",ipi); } } printf ( "Send Some Message To Server\n" ); if ( sendto ( sockfd, "Hello", strlen ( buffer ), 0, &peeraddr, socklen)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3