J'essaie d'obtenir un exemple de multidiffusion simple pour travailler sous Linux (j'ai essayé RHEL 4 2.6.9 et Ubuntu 8.04 2.6.24). L'idée générale est que je voudrais que le serveur lier à une adresse unicast, puis ajouter lui-même au groupe ff02 :: 1. Je voudrais alors recevoir des multidiffusions envoyées à ff02 :: 1. Le code ci-dessous fonctionne sous Mac OS X 10.5 (en , un serveur fonctionnant sous OS X reçoit des multidiffusions envoyées par des clients Linux ), mais je ne parviens pas à faire fonctionner le serveur Linux. Il n'obtient pas de multidiffusion. Si je change le code pour lier à :: (INADDR6_ANY) plutôt qu'une adresse unicast (j'ai essayé les adresses link-local et global ), il obtient les multidiffusions. Je me demandais si quelqu'un pourrait signaler ce que je fais mal.Écoute des multidiffusions IPv6 sous Linux
serveur:
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_DGRAM;
// argv[1] is either a link-local or a global address
err = getaddrinfo(argv[1], NULL, &hint, &info);
if(err != 0) {
perror("getaddrinfo");
exit(1);
}
struct sockaddr_in6 * addr = (struct sockaddr_in6*)info->ai_addr;
//addr->sin6_addr = in6addr_any; // if this is uncommented, multicasts are received
addr->sin6_port = htons(7890);
s = socket(AF_INET6, SOCK_DGRAM, 0);
if(bind(s, (struct sockaddr*) addr, info->ai_addrlen) != 0) {
close(s);
perror("bind");
exit(1);
}
if(getaddrinfo("ff02::1", NULL, &hint, &multi) != 0) {
close(s);
perror("getaddrinfo");
exit(1);
}
struct ipv6_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
memcpy(&mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *) multi->ai_addr)->sin6_addr, sizeof(mreq.ipv6mr_multiaddr));
mreq.ipv6mr_interface = 2; // 2 happens to be the interface ID; I've tried other values here
freeaddrinfo(multi);
if(setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) != 0) {
close(s);
perror("IPV6_JOIN_GROUP");
exit(1);
}
for(; ;) {
char data[6];
size_t len;
len = recvfrom(s, data, 5, 0, NULL, NULL);
data[5] = '\0';
printf("Received %s\n", data);
if(strcmp(data, "exitt") == 0) {
break;
}
}
Le code client se présente comme suit:
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_DGRAM;
hint.ai_protocol = 0;
err = getaddrinfo("ff02::1", NULL, &hint, &info);
if(err != 0) {
perror("getaddrinfo");
return 0;
}
struct sockaddr_in6 * addr = (struct sockaddr_in6*)info->ai_addr;
addr->sin6_port = htons(7890);
addr->sin6_scope_id = 2; // 2 happens to be the interface ID
s = socket(AF_INET6, SOCK_DGRAM, 0);
for(; ;) {
char data[6];
size_t len;
scanf("%5s", data);
data[5] = '\0';
printf("Sending %s\n", data);
if(sendto(s, data, 5, 0, info->ai_addr, info->ai_addrlen) != 5) {
printf("Error sending\n");
}
if(strcmp(data, "exitt") == 0) {
break;
}
}
close(s);
Est-ce que cela est documenté quelque part? Si tel était le cas, appeler IPv6_JOIN_GROUP sur un socket lié à une adresse monodiffusion renverrait une erreur, n'est-ce pas? – Ray
Le setsockopt fonctionne toujours car c'est une option valide, consultez Stevens 'pour bind() -> http://books.google.com.hk/books?id=ptSC4LpwGA0C&lpg=PA101&dq=stevens%20bind&hl=en&pg=PA103#v = onepage & q = stevens% 20bind & f = false –