IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

gestion protocole UDP


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 855
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 855
    Par défaut gestion protocole UDP
    Bonjour,

    Je dois développer une petite application qui permet de détecter des appareils sur un réseaux. Pour cela, je dois utiliser une protocole custom basé sur UDP.

    J'ai plusieurs cas qui se présentent à moi :
    1- J'envoie manuellement une requête broadcast => j'affiche les IP des appareils qui répondent
    2- Je suis en attente => lorsqu'un appareil est allumée, il envoie une requête pour indiquer sa présence : j'affiche son IP.

    Désolé pour les questions bêtes mais je n'ai encore jamais développé d'application UDP
    Comment faire ceci (structure du projet) ? Je ne peux pas utiliser les sockets vu que je n'ai pas l'adresse de destination (pour le cas 1), non ?

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 855
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 855
    Par défaut
    J'arrive a envoyer/recevoir mes données:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
    public class ScanProduct {
     
    	private int pPortTX = 30303; // port d'emission
     
    	private int pPortRX = 30303; // port de reception
    	private DatagramSocket pSocket;
    	private DatagramPacket pPacketRX;
    	private byte[] pBufferRX;
     
    	// constructeur
    	public ScanProduct(){
    		super();
     
     
    		// ouverture du port de reception
    		try {
    			pSocket = new DatagramSocket(pPortRX);
     
    			pBufferRX = new byte[1500];
    			pPacketRX = new DatagramPacket(pBufferRX, pBufferRX.length);
     
     
    		} catch (SocketException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
     
     
    	public void sendDiscoveryMsg(){
    		byte[] buffer = "Discovery: who is out there?".getBytes();
     
    		//DatagramSocket socketTX;
    		InetAddress myAddress;
    		DatagramPacket packet;
     
    		System.out.println("sendDiscoveryMsg : call");
     
    		try {
    			//socketTX = new DatagramSocket();
    			myAddress = InetAddress.getByName("255.255.255.255");
     
     
    			//packet = new DatagramPacket(buffer, buffer.length, myAddress, pPortTX);
    			//packet.setData(buffer);
    			pPacketRX = new DatagramPacket(buffer, buffer.length, myAddress, pPortTX);
    			pPacketRX.setData(buffer);
     
    			//socketTX.send(packet);
    			pSocket.send(pPacketRX);
    			System.out.println("sendDiscoveryMsg : message envoyé");
     
    			//socketTX.close(); // fermeture
     
    		} catch (SocketException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();			
    		} catch (IOException e) {	
    			// TODO Auto-generated catch block
    			e.printStackTrace();	
    		}
     
    	}
     
    	public void getDiscoveryMsg(){
     
    		try {
    			pSocket.receive(pPacketRX);
    			System.out.println("getDiscoveryMsg : message reçu => " + new String(pPacketRX.getData(), 0, pPacketRX.getLength()));
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
     
    	}
     
    	public void close(){
    		pSocket.close();
    	}
    }
    => en réception, ça m'affiche les données que j'émets (vu que j'émets à l'adresse 255.255.255.255) : n'y a t-il pas moyen de filtrer ceci (sans faire de test sur pPacketRX.getSocketAddress() à chaque packet reçu) ?

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 855
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 855
    Par défaut
    aussi j'ai un autre problème

    j'ai essayé de créer correctement ma classe pour pouvoir l'utiliser avec des thread

    utilisation de la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public class Main {
     
    	public static Thread t;
     
    	public static void main(String[] args) {
     
    		// lancement du programme
    		Discovery obj = new Discovery();
    		obj.sendDiscoveryMsg();
     
    		t = new Thread(obj);
    		t.start();
     
     
     
    		try {
    			Thread.sleep(5000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
     
     
    		obj.close();
    	}
     
     
    	// constructeur
    	/* (non-Java-doc)
    	 * @see java.lang.Object#Object()
    	 */
    	public Main() {
    		super();
     
    	}
     
     
     
    }

    ma classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
     
     
    public class Discovery implements Runnable {
     
    	private InetAddress pMyAddress;
     
    	private int pPortTX = 30303; // port d'emission
    	private int pPortRX = 30303; // port de reception
     
    	//private byte[] pBufferRX;
     
    	private DatagramSocket pSocket;
     
    	private boolean pThreadOn = false;
     
     
     
    	// constructeur
    	public Discovery(){
    		super();
     
     
    		// ouverture du port de reception
    		try {
    			pMyAddress = InetAddress.getLocalHost();
     
    			//System.out.println("sendDiscoveryMsg : test1");
     
    			pSocket = new DatagramSocket(pPortRX);
     
    			//System.out.println("sendDiscoveryMsg : test2");
     
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (SocketException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
     
     
    	// envoie le message
    	public void sendDiscoveryMsg(){
    		byte[] buffer = "Discovery: who is out there?".getBytes();
     
    		InetAddress myAddress;
    		//DatagramSocket socket;
    		DatagramPacket packet;
     
    		//System.out.println("sendDiscoveryMsg : call");
     
    		try {
    			//socket = new DatagramSocket(pPortRX);
     
    			//System.out.println("sendDiscoveryMsg : call1");
     
    			myAddress = InetAddress.getByName("255.255.255.255");
     
    			//System.out.println("sendDiscoveryMsg : call2");
     
    			packet = new DatagramPacket(buffer, buffer.length, myAddress, pPortTX);
    			packet.setData(buffer);
     
    			//socketTX.send(packet);
    			pSocket.send(packet);
    			System.out.println("sendDiscoveryMsg : message envoyé");
     
    			//socketTX.close(); // fermeture
     
    		} catch (SocketException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();			
    		} catch (IOException e) {	
    			// TODO Auto-generated catch block
    			e.printStackTrace();	
    		}
     
    	}
     
     
    	// recupère un message
    	// attention processus blocant
    	public void getDiscoveryMsg(){
     
    		DatagramPacket packet;
    		//DatagramSocket socket;
    		byte[] buffer = new byte[1500];
     
    		try {
    			//socket = new DatagramSocket(pPortRX);
    			packet = new DatagramPacket(buffer, buffer.length);
    			pSocket.receive(packet);
     
    			if (!packet.getSocketAddress().equals(pMyAddress)){
    				System.out.println("getDiscoveryMsg : message reçu => " + new String(packet.getData(), 0, packet.getLength()));
    			}
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
     
    	}
     
     
     
    	// lance le thread
    	public void run() {
     
    //*
    		DatagramPacket packet;
    		//DatagramSocket socket = null;
    		byte[] buffer = new byte[1500];
     
     
    		pThreadOn = true; // pour arreter le thread
     
    		while(pThreadOn){
     
    			try {
    				//socket = new DatagramSocket(pPortRX);
    				packet = new DatagramPacket(buffer, buffer.length);
    				pSocket.receive(packet);
     
    				if (!packet.getSocketAddress().equals(pMyAddress)){
    					System.out.println("getDiscoveryMsg : message reçu => " + new String(packet.getData(), 0, packet.getLength()));
    				}
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
     
    		}
     
    		//pSocket.close();
    		//if (pSocket.isClosed()){
    		//	pSocket = null;
    		//}
    // */		
    	}
     
     
    	// ferme le thread
    	public void close(){
    		pThreadOn = false;
    		System.out.println("Discovery : close");
     
     
    		if (!pSocket.isConnected()){
    			pSocket.disconnect();
    		}
     
    		if (!pSocket.isClosed()){
    			pSocket.close();	
    		}
     
    		pSocket = null;
    	}
    }
    => lorsque je lance une premiere fois mon application depuis eclipse, tout va bien mais après j'ai le message d'erreur suivant :

    java.net.BindException: Address already in use: Cannot bind
    at java.net.PlainDatagramSocketImpl.bind0(Native Method)
    at java.net.PlainDatagramSocketImpl.bind(Unknown Source)
    at java.net.DatagramSocket.bind(Unknown Source)
    at java.net.DatagramSocket.<init>(Unknown Source)
    at java.net.DatagramSocket.<init>(Unknown Source)
    at java.net.DatagramSocket.<init>(Unknown Source)
    at Discovery.<init>(Discovery.java:35)
    at Main.main(Main.java:9)
    Exception in thread "main" java.lang.NullPointerException
    at Discovery.sendDiscoveryMsg(Discovery.java:72)
    at Main.main(Main.java:10)
    De quoi ça peut venir ?
    Est-ce que l'organisation de mon projet en bonne (je n'ai pas encore l'habitude d'utiliser les threads)?

    => j'ai remarqué que si je lance l'application depuis MS-DOS, la fentere DOS ne se ferme pas ... : j'ai l'impression que l'application ne se referme pas après son exécution (et donc la mémoire n'est pas libérée) => il y a une commande spéciale à faire pour fermer un application qui n'utilise pas de fenetre ?

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 855
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 855
    Par défaut
    C'est bon, j'ai trouvé l'erreur : mon thread restait toujours ouvert

    voici mon nouveau code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
     
     
    public class Discovery implements Runnable {
     
    	private InetAddress pMyAddress;
     
    	private int pPortTX = 30303; // port d'emission
    	private int pPortRX = 30303; // port de reception
     
    	private DatagramSocket pSocket;
    	private boolean stopThread = false;
     
     
     
    	// constructeur
    	public Discovery(){
    		super();
     
     
    		// ouverture du port de reception
    		try {
    			pMyAddress = InetAddress.getLocalHost();
     
    			pSocket = new DatagramSocket(pPortRX);
     
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (SocketException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
     
     
    	// envoie le message
    	public void sendDiscoveryMsg(){
    		byte[] buffer = "Discovery: who is out there?".getBytes();
     
    		InetAddress myAddress;
    		DatagramPacket packet;
     
     
    		try {
    			myAddress = InetAddress.getByName("255.255.255.255");
     
    			packet = new DatagramPacket(buffer, buffer.length, myAddress, pPortTX);
    			packet.setData(buffer);
     
    			pSocket.send(packet);
    			System.out.println("sendDiscoveryMsg : message envoyé");
     
    		} catch (SocketException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();			
    		} catch (IOException e) {	
    			// TODO Auto-generated catch block
    			e.printStackTrace();	
    		}
     
    	}
     
     
     
    	// reception des datas
    	// lance le thread
    	public void run(){
     
    		DatagramPacket packet;
    		byte[] buffer = new byte[1500];
     
    		boolean threadOff = false; // pour arreter le thread
     
     
    		while(!threadOff){
     
    			try {
    				//socket = new DatagramSocket(pPortRX);
    				packet = new DatagramPacket(buffer, buffer.length);
    				pSocket.receive(packet);
     
    				if (!packet.getAddress().equals(pMyAddress)){
     
    					// affichage des données reçues
    					String myStr = new String(packet.getData(), 0, packet.getLength());
    					String[] myStr2 = myStr.split("\r\n");
     
    					System.out.print("getDiscoveryMsg : message reçu => " );
     
    					for(int i = 0; i<myStr2.length; i++){
    						if (i !=0){
    							System.out.print(" / ");
    						}
    						System.out.print(myStr2[i]);											
    					}
    					System.out.println(); // fin de la ligne
    				}
     
                    synchronized(this) {
                        Thread.yield();
     
                        // lecture du boolean 
                        threadOff = this.stopThread;
                    } 
     
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				//e.printStackTrace();
    				break; // exeption detectée du a la fermeture suavage de pSocket
    			}
    		} 
     
     
    		pSocket.close();
    		System.out.println("Discovery : isClosed");
     
    	}
     
     
     
     
    	// ferme le thread
    	public void close(){
     
    		this.stopThread = true;
    		pSocket.close(); // fait lever une exception sur pSocket (s'il est en cours d'utilisation) pour pouvoir arreter le thread de reception
     
    		System.out.println("Discovery : close");
     
    	}
    }

    Donc pour lancer mon Thread, je fais comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    public class Main {
     
    	public static Thread t;
     
    	public static void main(String[] args) {
     
    		// lancement du programme
    		Discovery obj = new Discovery();
     
    		t = new Thread(obj);
    		t.start();
     
     
    		obj.sendDiscoveryMsg();
     
     
    		try {
    			Thread.sleep(10000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
     
     
    		obj.close(); // a partir de là, il ne faut plus appeler sendDiscoveryMsg()
    	}
     
     
    	// constructeur
    	/* (non-Java-doc)
    	 * @see java.lang.Object#Object()
    	 */
    	public Main() {
    		super();
     
    	}
     
    }
    => Est-ce que j'utilise la bonne méthode pour fermer mon Thread ? ... pSocket.receive(packet); étant bloquant, je fais un pSocket.close(); pour faire lever une exception et ainsi pouvoir fermer mon Thread

    Est-ce que la methode sendDiscoveryMsg est correctement déclarée ? puis-je la lancer n'importe quand (par exemple un clic sur un bouton après avoir lancé mon Thread...n'y a t-il pas de risque de conflit avec le Thread de réception ?) ?

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    on va faire dans l'ordre

    Sur quelle addresse te brancher? Ben sur l'adresse multicast que tu mentionne au point 1, c'est comme ça qe ca marche le multicat. Tu te branche sur la socket avec cette adresse, et tout ceux qui l'ont fait vont recevoir les maquets multicast (mieux que l'adresse de broadcast quand même).

    Le close(), c'est une solution comme une autre (je crois qu'il y a aussi des méhodes non bloquantes, de mémoire)

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 855
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 855
    Par défaut
    ok merci,

    Citation Envoyé par tchize_ Voir le message
    on va faire dans l'ordre

    Sur quelle addresse te brancher? Ben sur l'adresse multicast que tu mentionne au point 1, c'est comme ça qe ca marche le multicat. Tu te branche sur la socket avec cette adresse, et tout ceux qui l'ont fait vont recevoir les maquets multicast (mieux que l'adresse de broadcast quand même).
    Je suis obligé d'utiliser l'adresse Broadcast car ça m'est imposé par les appareils a détecter (c'est comme ça qu'ils fonctionnent).
    Dans la classe DatagramSocket, il y a la méthode setBroadcast() : elle sert à quoi exactement car ça fonctionne sans l'utiliser ?
    PS : dans mon ennoncé j'ai mélangé broadcast et multicast => c'est bien de broadcast dont je parle (j'ai modifié mon post)


    J'ai un doute : pour fermer mon Thread, ne devrais-je pas plutot utiliser la methode .Interrupt() plutot que de créer une methode close => il faudrait donc que ma classe hérite de la classe Thread plutot que d'implementer Runnable, non ? ... j'ai un peu du mal a savoir quelle est la meilleure méthode...

Discussions similaires

  1. Indy 10 & protocole UDP
    Par Hiker's dans le forum Web & réseau
    Réponses: 2
    Dernier message: 22/01/2009, 14h24
  2. des informations sur le protocole udp
    Par hanou88 dans le forum Matériel
    Réponses: 2
    Dernier message: 21/12/2008, 23h02
  3. Protocole UDP (séquence/acquittement/temporisateur)
    Par hbhhhbhh dans le forum Réseau
    Réponses: 4
    Dernier message: 31/03/2008, 16h55
  4. Protocole UDP, adresse MAC distante
    Par rockt13 dans le forum Réseau
    Réponses: 6
    Dernier message: 08/02/2007, 15h55
  5. Réponses: 10
    Dernier message: 10/01/2006, 09h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo