#define GROUP "239.137.194.222"Il sera aussi nécessaire de définir un port de communication comme cela est fait habituellement en mode unicast traditionnel.
#define PORT 55501
/*
* Fichiers include
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/*
* descripteurs de socket
*
* sdr : pour la reception
* sdw : pour l'emission
*/
int sdr, sdw;
/*
* sockets
*
* sock_r : pour la reception
* sock_w : pour l'emission
*/
struct sockaddr_in sock_r, sock_w;
/*
* creation des sockets
*/
sdr = socket(PF_INET, SOCK_DGRAM, 0);
if (sdr < 0) {
perror("socket");
exit(1);
}
sdw = socket(PF_INET, SOCK_DGRAM, 0);
if (sdw < 0) {
perror("socket");
exit(1);
}
/*
* initialisation de la socket de reception
*/
memset(&sock_r, 0, sizeof(sock_r));
sock_r.sin_family = AF_INET;
sock_r.sin_port = htons(PORT);
sock_r.sin_addr.s_addr = htonl(INADDR_ANY);
/*
* initialisation de la socket d'emission
*/
memset(&sock_w, 0, sizeof(sock_w));
sock_w.sin_family = AF_INET;
sock_w.sin_port = htons(PORT);
sock_w.sin_addr.s_addr = inet_addr(GROUP);
len_r = sizeof(sock_r);
len_w = sizeof(sock_w);
La fonction inet_addr("string") permet de convertir la chaîne
de caractères de 4 octets décimaux représentant l'adresse IP
en une valeur binaire codée sur 32 bits au format réseau.
if (setsockopt(sdr, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *) &imr, sizeof(struct ip_mreq)) < 0) {
perror("setsockopt - IP_ADD_MEMBERSHIP");
exit(1);
}
où imr est une structure de type ip_mreq, définie dans le fichier
/usr/include/netinet/in.h, qui est décrite comme suit :
struct ip_mreq {
struct in_addr imr_multiaddr; /* multicast group to join */
struct in_addr imr_interface; /* interface to join on */
}
/*
* allocation de la structure imr
*/
struct ip_mreq imr;
/*
* initialisation de la structure imr
*/
imr.imr_multiaddr.s_addr = inet_addr(GROUP);
imr.imr_interface.s_addr = htonl(INADDR_ANY);
En mode réception il est aussi nécessaire d'effectuer une opération bind()
entre la socket et son descripteur :
/*
* opération bind
*/
if (bind(sdr, (struct sockaddr *)&sock_r, sizeof(sock_r)) < 0) (
perror("bind");
exit(1);
}
La réception proprement dite des données se réalisera par un appel à
recvfrom() à travers l'interface socket.
/*
* réception des datagrammes
*/
while (1) {
cnt = recvfrom(sdr, buf, sizeof(buf), 0, (struct sockaddr *)&sock_r, &len_r);
if (cnt < 0) {
perror("recvfrom");
exit(1);
}
else if (cnt == 0) { /* fin de transmission */
break;
}
printf("%s\n", buf); /* affichage du message */
}
Les adresses comprises entre 224.0.0.0 et 224.0.0.255 peuvent être utilisées localement sur le sous-réseau mais ne seront jamais relayées par les routeurs car elles sont réservées aux protocoles de routage.
Pour faire des tests il est conseillé d'utiliser un TTL de 1 et une adresse du type "239.jj.mm.aa" où jj represente le jour, mm le mois et aa l'année.
L'opération qui permet de fixer la valeur du TTL est la suivante :
int r;
unsigned char ttl = 1;
setsockopt(sdw, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
if (r == -1) {
perror("setsockopt: IP_MULTICAST_TTL");
}
L'émission proprement dite des données se fera par l'appel système sendto()
à travers l'interface socket.
/*
* emission des datagrammes
*/
cnt = sendto(sdw, buf, strlen(buf), 0, (struct sockaddr *)&sock_w, len_w);
if (cnt < 0) {
perror("sendto");
exit(1);
}
int r;
r = setsockopt(sdr, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(imr));
if (r == -1) {
perror("setsockopt: IP_DROP_MEMBERSHIP");
}
int r, reuse = 1;
r = setsockopt(sdr, SOL_SOCKET, SO_REUSEADDR, (int *)&reuse, sizeof(reuse));
if (r == -1) {
perror("setsockopt: SO_REUSEADDR");
}
Cet appel système doit précéder l'appel système
bind().
int r;
unsigned char loop = 1; /* 0 = disable, 1 = enable */
r = setsockopt(sdr, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
if (r == -1) {
perror("setsockopt: IP_MULTICAST_LOOP");
}
int r, bufsize = 8192;
r = setsockopt(sdw, SOL_SOCKET, SO_SNDBUF, (void *)&bufsize, sizeof(bufsize));
if (r == -1) {
perror("setsockopt: SO_SNDBUF");
}
import java.io.*;
import java.net.*;
int group;
int port;
InetAddress group = InetAddress.getByName(group);
MulticastSocket s = new MulticastSocket(port);
s.joinGroup(group);
byte[] msg = "Hello World!";
DatagramPacket hi = new DatagramPacket(msg, msg.length, group, port);
s.send(hi);
byte[] buf = new byte[512];
DatagramPacket recv = new DatagramPacket(buf, buf.length);
s.receive(recv);
s.leaveGroup(group);
byte ttl;
s.setTTL(ttl);
int vif = -1; /* -1 = enable normal multicast forwarding */
setsockopt(sdr, IPPROTO_IP, IP_MULTICAST_VIF, &vif, sizeof(vif));
© (Copyright) Philippe Dax - 1995-1999