以下是发件人和收件人的代码(合并)。
int main (int argc, char *argv[]) {
struct in6_addr localInterface;
struct sockaddr_in6 groupSock;
// socket descriptor for multicast
int sd;
char databuf[10];
// length of message
int datalen = sizeof(databuf);
/* Create a datagram socket on which to send/receive. */
sd = socket(AF_INET6, SOCK_DGRAM, 0);
if(sd < 0) {
perror("Opening datagram socket error");
exit(1);
}
else {
printf("Opening the datagram socket...OK.\n");
}
/* Enable SO_REUSEADDR to allow multiple instances of this */
/* application to receive copies of the multicast datagrams. */
{
int reuse = 1;
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(sd);
exit(1);
}
else {
printf("Setting SO_REUSEADDR...OK.\n");
}
}
/* Initialize the group sockaddr structure with a */
memset((char *) &groupSock, 0, sizeof(groupSock));
groupSock.sin6_family = AF_INET6;
// address of the group
// groupSock.sin6_addr = inet6_addr("ff5e::/16");
inet_pton(AF_INET6, "ff5e::/16", &(groupSock.sin6_addr));
groupSock.sin6_port = htons(4321);
/* Set local interface for outbound multicast datagrams. */
/* The IP address specified must be associated with a local, */
/* multicast capable interface. */
char *ip_address = argv[2];
inet_pton (AF_INET6, ip_address, &(localInterface.s6_addr));
memset((char *) &localInterface, 0, sizeof(localInterface));
int ifindex;
ifindex = if_nametoindex ("eth5");
printf ("ifindex is %d\n", ifindex);
if(setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)))
{
perror("Setting local interface error");
exit(1);
}
else {
printf("Setting the local interface...OK\n");
}
// choice is 0 for sending and 1 for receiving
int choice;
sscanf (argv[1], "%d", &choice);
// if sending
if (choice == 0) {
int i;
for (i = 0; i < datalen-1; ++i) {
databuf[i] = 'a';
}
databuf[i] = 0;
if (sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0) {
printf ("Error in send\n");
}
else {
printf ("Send okay!\n");
}
}
// if receiving
else if (choice == 1) {
groupSock.sin6_addr = in6addr_any;
if(bind(sd, (struct sockaddr*)&groupSock, sizeof(groupSock))) {
perror("Binding datagram socket error");
close(sd);
exit(1);
}
else {
printf("Binding datagram socket...OK.\n");
}
/* Join the multicast group ff5e::/16 on the local */
/* interface. Note that this IP_ADD_MEMBERSHIP option must be */
/* called for each local interface over which the multicast */
/* datagrams are to be received. */
struct ipv6_mreq group;
inet_pton (AF_INET6, "ff5e::", &(group.ipv6mr_multiaddr.s6_addr));
// group.imr_interface.s6_addr = inet_addr(ip_address);
group.ipv6mr_interface = ifindex;
if(setsockopt(sd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) {
perror("Adding multicast group error");
close(sd);
exit(1);
}
else {
printf("Adding multicast group...OK.\n");
}
if (read(sd, databuf, datalen) < 0) {
perror("Error in read");
}
else {
printf("Read Okay\n");
printf ("Message is : %s\n", databuf);
}
}
}
如果发送方和接收方位于不同的节点上,接收方不会收到消息(我已经检查过它们是否通过ping6连接)。我正在使用Linux Ubuntu 14.04。使用tcpdump捕获ipv6数据包会发现数据包不是在发送方发送的。有什么问题?
答案 0 :(得分:2)
一个问题是您的IPv6多播地址选择不当。 FF5E::
像这样分解:
FF
表示它是多播。5
是标志集(0101
),此值是一组无效的标志。最高位设置意味着您有一个嵌入式RP地址,您显然不会这样做。为此,标志集必须为7
(0111
),然后遵循嵌入RP地址的所有规则。E
表示它是全局范围。应该在与路由器相遇的任何路径中正确删除此多播地址。
请参阅RFC 4291,3306和3956以创建IPv6多播地址,包括标志和范围的含义。