Simplemessenger : messagerie (presque !) instantanée via udp

Description

Cette petite application permet de communiquer via un réseau local en s'envoyant des messages textes. Bien sur, elle serai largement améliorable(en ajoutant du texte en couleur, une liste de contactes, etc ...). Ici, je pose simplement les bases réseaux (j'utilise un marqueur de fin de message, car dans le cas contraire il serai affiché des "carrés" (signe binaire) remplissant les espaces vides. Je n'ai pas passé du temp à imaginer une autre technique.

Source / Exemple :


package yann.reseau;

import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

/* Dans un version plus récente(la finale) située malheuresement sur mon autre ordinateur, j'avais implementé un marqueur de fin de ligne(du genre [END]) car lors de l'affichage, on s'aperçois de l'apparition de caractères [] pour chaque octet vide reçus, soit 2048 moins la longueur du message, ce qui fait beaucoup... */

public class Conversation implements Runnable, ActionListener {
   GridBagConstraints gbc = new GridBagConstraints();
   JTextArea area = new JTextArea(); //affichage des messages
   int port = 5000; //port par défaut
   String destinataire = "OEMComputer"; //destinataire par defaut(en fait le nom de ma machine)
   JTextField field = new JTextField(15); //champ où entrer le message
   Thread thread;
   JFrame frame = new JFrame("Yann Messenger v1.0");
   JButton button2; 
   
   //renvoi le nom local
   public String localHost() {
      try {
         return InetAddress.getLocalHost().getHostName();
      }
      catch (UnknownHostException uhe) {
         return "moi";
      }
   }

   //méthode ajoutant des composants aux coordonnées souhaités
   private void addGB(Container cont, Component comp, int x, int y) {
      gbc.gridx = x; gbc.gridy = y;
      cont.add(comp, gbc);
   }

   //methode envoyant un message
   private void sendMessage(String msg) {
      try {
         byte data[] = msg.getBytes(); //transormation en octets
         InetAddress addresse = InetAddress.getByName(destinataire);
         DatagramPacket pack =
           new DatagramPacket(data, data.length, addresse, port);
         DatagramSocket socket = new DatagramSocket();
         socket.send(pack);
         socket.close();
         area.append("\n" + localHost() + " : " + msg);
      }
      catch (UnknownHostException e) {
         JOptionPane.showMessageDialog(frame, "Erreur : impossible de trouver la machine", "Erreur de Connexion", JOptionPane.ERROR_MESSAGE);
         //on demande la saisi d'un autre destinataire
         String passMsg2 = "Saisissez le nom de la machine du destinataire";
         JTextField hostField2 = new JTextField(); 
         hostField2.setText(destinataire);
         int result2 = JOptionPane.showOptionDialog(frame, new Object[] { passMsg2, hostField2 }, "Connexion - destinataire", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
         if(result2 == JOptionPane.OK_OPTION) {
            destinataire = hostField2.getText();
         }
      }
      catch (SocketException e2) {
         JOptionPane.showMessageDialog(frame, "Erreur interne : echec de l'envoi du message", "Erreur de Connexion", JOptionPane.ERROR_MESSAGE);
         System.out.println(e2); //log
      }
      catch (IOException e3) {
          JOptionPane.showMessageDialog(frame, "Erreur interne : echec de l'envoi du message", "Erreur de Connexion", JOptionPane.ERROR_MESSAGE);
         System.out.println(e3); //log
      }
   }

   private void ecouter() {
      try {
         DatagramSocket s =  new DatagramSocket(port);
   //capacité de 2048 caractères
         DatagramPacket pack = 
            new DatagramPacket(new byte[2048], 2048);
         s.receive(pack);
         String message = new String(pack.getData());
         area.append("\n" + pack.getAddress().getHostName() + " : " + message);
      }
      catch (SocketException e4) {
         JOptionPane.showMessageDialog(frame, "Erreur interne : echec de la réception d'un message", "Erreur de Connexion", JOptionPane.ERROR_MESSAGE);
         System.out.println(e4);
      }
      catch (IOException e5) {
          JOptionPane.showMessageDialog(frame, "Erreur interne : echec de la réception d'un message", "Erreur de Connexion", JOptionPane.ERROR_MESSAGE);
         System.out.println(e5);
      }
   }

   public Conversation() {
      area.setEditable(false);
      Container content = frame.getContentPane();
      content.setLayout(new GridLayout(2,1));
      content.add(new JScrollPane(area));
      JPanel panel = new JPanel();
      panel.setLayout(new GridBagLayout());
      gbc.gridwidth = 3;
      addGB(panel, field, 0, 4);
      gbc.gridwidth = 1;
      JButton button;
      button2 = new JButton("Envoyer");
      addGB(panel, button2, 0, 5);
      button2.addActionListener(this);
      addGB(panel, button = new JButton("port ..."), 1, 5);
      button.addActionListener(this);
      addGB(panel, button = new JButton("destinataire ..."), 2, 5);
      button.addActionListener(this);
      content.add(panel);
      thread = new Thread(this);
      thread.start();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setLocation(200, 200);
      frame.pack();
      frame.show();
   }

   public void actionPerformed(ActionEvent e) {
      if(e.getSource() == button2) {
         sendMessage(field.getText());
      }
      else if(e.getActionCommand().equals("port ...")) {
        String portMsg = "Indiquez le port";
        JTextField portField = new JTextField();
        portField.setText(new String(new StringBuffer().append(port)));
        int result = JOptionPane.showOptionDialog(frame, new Object[] { portMsg, portField }, "Connexion - destinataire", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
        if(result == JOptionPane.OK_OPTION) {
           try {
              int newPort = Integer.parseInt(portField.getText());
              if(newPort > 1024)
                 port = newPort;
           }
           catch (Exception pe) { }
        }
      } else if(e.getActionCommand().equals("destinataire ...")) {
         String passMsg = "Saisissez le nom de la machine du destinataire";
         JTextField hostField = new JTextField(); 
         hostField.setText(destinataire);
         int result = JOptionPane.showOptionDialog(frame, new Object[] { passMsg, hostField }, "Connexion - destinataire", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
         if(result == JOptionPane.OK_OPTION) {
            destinataire = hostField.getText();
         }
      }
   }

   public void run() {
      while(true) {
        ecouter();
      }
   }

   public static void main(String args[]) {
      new Conversation();
   }
}

Conclusion :


voila, il suffit de lancer l'application et de spécifier le destinataire et le port, et deux applications situées sur deux ordi différent (avec réseau locale) peuvent communiquée. Testé et compiler avec JSE 1.4.1 et testé sur un réseau locale 10/100 mégabits. J'ai seulement été impressionné de la lenteur de l'application sur portable 1.1 giga hertz et 60 giga de disque dur et paramétré pour de nombreux réseaux locale, ce qui provoquait peut-être la lenteur mais un oridnateur de bureau récent envoye et receptionne preque instantanément les messages

Codes Sources

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.