c++ - Solaris 10 -- 从 recvmsg() 的 UDP 多播数据包中获取 IP 源地址

标签 c++ c sockets solaris

我的项目代码创建了一个 UDP 套接字来接收多播数据包。该代码可移植到 Linux 和 Solaris 操作系统。我的项目的一个扩展是在使用 recvmsg() 函数时寻找检索 UDP 数据包的源 IP 地址。我曾就此事询问过一位专家,她提到 Linux 似乎能够提供源 IP 地址,但 Solaris 在使用 recvmsg() 函数时可能无法提供。所以我在这里提出问题,我能否在 Solaris 10 上使用 recvmsg() 检索源 IP 地址?

操作系统:Solaris 10、Sunstudio 12 cc(无 U1 或 U2)。 代码库:C/C++

//Socket initially opened with the following options from a different function.
// This connects the socket to receive multicast:
setsockopt(data->fd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
    (char *)&mregs, sizeof(mregs) ) < 0)

//A different function performs an infinite loop reading from the socket:

struct iovec vector;
vector.iov_base = buf;     //passed in param
vector.iov_len = len;      //passed in param
struct msghdr msg;
char    caddr[100] ;
msg.msg_name =  caddr;
msg.msg_namelen = 100;
msg.msg_iov = &vector;
msg.msg_iovlen = 1;
int flags = 0;

char controlBuffer[1024];
msg.msg_control = controlBuffer;
msg.msg_controllen = 1024;

bytes = ::recvmsg(data->fd, &msg, flags);

//removed error checking    

struct cmsghdr *cmsg;
struct in_pktinfo *dest_ip_ptr;
rrcp_u32_t dest_ip = 0;
cmsg = CMSG_FIRSTHDR(&msg);
for ( cmsg = CMSG_FIRSTHDR(&msg);
    cmsg != NULL;
    cmsg = CMSG_NXTHDR( &msg, cmsg ) )
{
    //if ( cmsg->cmsg_type == IPPROTO_IP && cmsg->cmsg_level == IP_PKTINFO )
    {
#ifdef Linux
        struct in_pktinfo *dest_ip_ptr = (struct in_pktinfo*)CMSG_DATA(cmsg);
        dest_ip = dest_ip_ptr->ipi_addr.s_addr;
#else
        //in_addr only has 1 address
        struct in_addr * dest_ip_ptr = (struct in_addr *)CMSG_DATA(cmsg);
        dest_ip = dest_ip_ptr->_S_un._S_addr;
#endif
    }
}
if( ipaddr ) 
    ipaddr->IP = dest_ip;

//according to the Linux article mentioned below, the caddr should have the source
//socket address.  In my case, the caddr field is not filled with any coherent data,
//so this does not seem to be the source address.  Then again, "source socket" could
//be the interface IP on the local machine, which isn't what I need.

我还看到了以下文章,但它们似乎没有回答我的问题: Get destination address of a received UDP packet ,解决方案:Get destination address of a received UDP packet

最佳答案

有两个问题:一是你哪里都不用caddr也不说是什么,所以不好帮你;另一个(可能是您遇到的问题)是您从 recvmsg 获得的地址不是字符串。

msg.msg_name 应该指向一个struct sockaddr_inmsg.msg_namelen 应该是sizeof(struct sockaddr_in) .然后您可以从中获取地址。

关于c++ - Solaris 10 -- 从 recvmsg() 的 UDP 多播数据包中获取 IP 源地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10922740/

相关文章:

c++ - std::thread对象构造过程中的细节

C 客户端/服务器与 fprintf 通信?

c++ - 在堆或堆栈上分配对象

c++ - 如何读取子进程的返回码

c++ - NonCopyable 和 NonMovable 等接口(interface)是否应该提供虚拟析构函数?

c++ - OPenMP 循环增量

c++ - 正则表达式NFA,用于未定义的 token 顺序

qt - QSslCertificate::importPkcs12 无法解析 PFX 文件

Java - 编码字符串

java - 当我们有 UrlConnection 时为什么要使用套接字