Les datagrammes UDP
Pour utiliser le protocole de transport UDP, il est nécessaire en
Java de manipuler deux classes DatagramPacket
et DatagramSocket
La classe DatagramPacket
Cette classe permet de créer des objets qui contiendront les données
envoyées ou reçues ainsi que l'adresse de destination ou
de provenance du datagramme.
Deux constructeurs sont disponibles, un pour les paquets à recevoir,
l'autre pour les paquets à envoyer.
-
public DatagramPacket(byte buffer[], int taille)
-
Construit un objet pour recevoir un datagramme. Le paramètre buffer
correspond à la zone où doit être stocké le
datagramme reçu et le paramètre taille
correspond à la taille maximale des datagrammes à recevoir.
-
public DatagramPacket(byte buffer[], int taille,
InetAddress adresse, int port)
-
Construit un objet pour envoyer un datagramme. Le paramètre buffer
correspond à la zone où est stocké le datagramme à
envoyer, le paramètre taille
correspond à la taille du datagramme à envoyer, adresse
correspond à l'adresse de la machine à qui envoyer le datagramme
et port sur quel port UDP.
Des méthodes sont disponibles pour manipuler de tels objets :
-
public synchronized InetAddress getAddress ()
-
Retourne l'adresse stockée dans le paquet.
-
public synchronized int getPort ()
-
Retourne le port stocké dans le paquet.
-
public synchronized byte[] getData ()
-
Retourne les données stockées dans le paquet.
-
public synchronized int getLength ()
-
Retourne la taille des données stockées dans le paquet.
-
public synchronized void setAddress(InetAddress
iaddr)
-
Modifie ou affecte l'adresse de destination.
-
public synchronized void setPort(int iport)
-
Modifie ou affecte le port de destination.
-
public synchronized void setData(byte ibuf[])
-
Modifie ou affecte la référence de
la zone contenant les données.
-
public synchronized void setLength(int ilength)
-
Modifie ou affecte la taille de la zone contenant
les données.
La classe DatagramSocket
Cette classe permet de créer des sockets UDP qui permettent
d'envoyer et de recevoir des datagrammes UDP.
Avant toute communication en mode UDP il est nécessaire de créer
une socket aussi bien du coté client que du coté serveur.
Pour cela Java propose trois constructeurs :
-
public DatagramSocket () throws SocketException
-
Crée un objet de type socket et l'attache à un port
disponible de la machine locale. Ce constructeur doit être utilisé
dans les clients pour lesquels le port d'attachement n'a pas besoin d'être
connu.
-
public DatagramSocket (int port) throws SocketException
-
Crée un objet de type socket et l'attache au port UDP local
passé en paramètre. En particulier, ce constructeur doit
être utilisé dans les serveurs pour lesquels le port d'attachement
a besoin d'être fixé préalablement afin qu'il soit
connu des clients.
-
public DatagramSocket(int port, InetAddress laddr)
throws SocketException
-
Crée un objet de type socket, l'attache au port UDP local
passé en paramètre et à une adresse spécifique
de la machine locale. Ce constructeur n'est utile que si la machine locale
dispose de plusieurs adresses Internet.
Une fois la socket (objet de type DatagramSocket)
créée et attachée à un port
particulier de la machine locale, il est possible d'envoyer et de recevoir
des datagrammes,
via cette socket, au moyen des méthodes suivantes
:
-
public void send(DatagramPacket data) throws
IOException
-
Permet d'envoyer les données contenues dans la variable data
vers la machine et le port dont les valeurs ont été préalablement
spécifiées dans la variable data.
-
public synchronized void receive(DatagramPacket
data) throws IOException
-
Permet de recevoir un datagramme qui sera stocké dans data.
Après appel, data contient
les données reçues, leur taille, l'adresse de l'envoyeur
ainsi que son port d'attachement. Cette méthode est bloquante tant
qu'il n'y a rien à recevoir. Si le message est trop long pour être
stocké, celui-ci est tronqué, et le reste est perdu. Il n'est
donc pas possible de recevoir des messages dont on ne connait pas préalablement
la taille.
Il est possible de spécifier un délai d'attente maximal en
reception. Pour cela, il faut positionner une variable de timeout
sur la socket au moyen de la méthode :
-
public synchronized void setSoTimeout(int timeout)
throws SocketException
-
Une valeur de 0 (zéro) correspond
à ne pas avoir de timeout.
D'autres méthodes sont disponibles pour manipuler ces sockets
:
-
public void close ()
-
Ferme la socket et libère les ressources qui lui sont associées.
La socket ne pourra plus être utilisée ni pour envoyer,
ni pour recevoir des datagrammes.
-
public int getLocalPort ()
-
Retourne le port d'attachement de la socket.
-
public synchronized int getSoTimeout() throws
SocketException
-
Retourne la valeur courante du timeout associé à la
socket.
Exemple :
Dans cet exemple nous créons deux classes :
-
une classe ServeurEcho qui attend
une chaîne de caractères et la retourne
-
une classe ClientEcho qui envoye
une chaîne de caractères, attend que le serveur la lui retourne
et l'affiche.
import java.io.*;
import java.net.*;
class ServeurEcho
{
final static int port = 8532;
final static int taille = 1024;
final static byte buffer[] = new byte[taille];
public static void main(String argv[]) throws Exception
{
DatagramSocket socket = new DatagramSocket(port);
while(true)
{
DatagramPacket data = new DatagramPacket(buffer,buffer.length);
socket.receive(data);
System.out.println(data.getAddress());
socket.send(data);
}
}
}
import java.io.*;
import java.net.*;
public class ClientEcho
{
final static int taille = 1024;
final static byte buffer[] = new byte[taille];
public static void main(String argv[]) throws Exception
{
InetAddress serveur = InetAddress.getByName(argv[0]);
int length = argv[1].length();
byte buffer[] = argv[1].getBytes();
DatagramPacket dataSent = new DatagramPacket(buffer,length,serveur,ServeurEcho.port);
DatagramSocket socket = new DatagramSocket();
socket.send(dataSent);
DatagramPacket dataRecieved = new DatagramPacket(new byte[length],length);
socket.receive(dataRecieved);
System.out.println("Data recieved : " + new String(dataRecieved.getData()));
System.out.println("From : " + dataRecieved.getAddress() + ":" + dataRecieved.getPort());
}
}