我有项目代码,它创建一个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
答案 0 :(得分:1)
有两个问题:一个是你不在任何地方使用caddr
而你没有说它是什么,所以很难帮助你;另一个(可能是您遇到的问题)是您从recvmsg
获得的地址不是字符串。
msg.msg_name
应指向struct sockaddr_in
,msg.msg_namelen
应sizeof(struct sockaddr_in)
。然后你从那里得到地址。