Le protocole UDP suit le principe de la poste.
Une socket UDP permet d'envoyer / recevoir des paquets vers / depuis n'importe quelle autre socket UDP accessible.
Pas de notion de connexion !
Si on envoie P1 puis P2 à une même adresse, on peut recevoir P1 puis P2, ou P2 puis P1, ou P1 seulement ou P2 seulement ou bien rien du tout.
L'accès au protocole IP en Java est très limité.
Représentés en Java par InetAddress
avec deux sous-classes Inet4Address
et Inet6Address
.
On travaillera toujours avec InetAddress
.
InetAddress
Pas de constructeur public
.
Création avec la méthode InetAddress.getByName(String host).
InetAddress addr1 = InetAddress.getByName("192.168.0.1"); InetAddress addr2 = InetAddress.getByName("FE80:0:0:0:0202:B3FF:FE1E:8329"); InetAddress addr3 = InetAddress.getByName("www.google.fr"); System.out.println(addr1 + "\n" + addr2 + "\n" + addr3);
/192.168.0.1 /fe80:0:0:0:202:b3ff:fe1e:8329 www.google.fr/64.233.166.94
Dans le dernier cas, il y a une résolution DNS.
InetAddress
= address (numérique) + [ name (littéral) ]
InetSocketAddress
Adresse de socket = Adresse IP + port
Plusieurs constructeurs :
InetAddress inetAddress = InetAddress.getByName("www.google.com"); InetSocketAddress insa1 = new InetSocketAddress(inetAddress, 7); InetSocketAddress insa2 = new InetSocketAddress("www.u-pem.fr", 7); InetSocketAddress insa3 = new InetSocketAddress("192.168.0.1", 1025); InetSocketAddress insa4 = new InetSocketAddress(7777); System.out.println(insa1 + "\n" + insa2 + "\n" + insa3 + "\n" + insa4);
www.google.com/173.194.67.147:7 www.u-pem.fr/193.50.159.151:7 /192.168.0.1:1025 0.0.0.0/0.0.0.0:7777
DatagramChannel
Les sockets UDP (les boîtes aux lettres) sont représentées par la classe DatagramChannel
.
On les crée avec la méthode factory :
DatagramChannel.open
DatagramChannel dc = DatagramChannel.open();
Une fois crée, elle n'est pas encore "attachée" : elle n'a pas d'adresse de socket.
L'attachement (faire le lien entre la boîte aux lettre et son adresse) se fait avec datagramChannel.bind
.
dc.bind(null);
Attachement à un numéro de port libre aléatoire.
Pour envoyer un paquet, il faut :
ByteBuffer
) et InetSocketAddress
)On utilise la méthode send
du DatagramChannel
:
send(ByteBuffer buffer, SocketAddress destination);
DatagramChannel dc; ... var buffer = StandardCharsets.UTF_8.encode("Hello world €"); var destination = new InetSocketAddress("gaspard.univ-mlv.fr", 7); dc.send(buffer, destination);
Pour recevoir un paquet (dans la boîte aux lettres), il faut prévoir l'espace nécessaire dans un ByteBuffer
pour stocker les données.
La méthode receive
renvoie l'adresse de l'expéditeur du paquet :
SocketAddress datagramChannel.receive(ByteBuffer buffer);
La méthode est bloquante.
DatagramChannel dc; ... var buffer = ByteBuffer.allocate(1024); var sender = (InetSocketAddress) dc.receive(buffer); buffer.flip(); System.out.println("Received " + buffer.remaining() + " bytes from " + sender);
Attention au flip()
!
Si la taille du paquet reçu dépasse la taille de stockage, la fin est perdue sans notification.
La création open
et
l'attachement bind
réservent des ressources système
(descripteur et buffer associés au port réservé).
Il faut impérativement les libérer explicitement :
datagramChannel.close();
try( DatagramChannel dc = DatagramChannel.open() ){ ... }