Bonjour à tous,
Je poste ici le code d'un tchat en java que j'ai implémenté.
Partie cliente :
package graphic; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JPanel; public class ConnectionPanel extends JPanel { private static final long serialVersionUID = 1L; private JButton mButtonTchatter; public ConnectionPanel() { setLayout(new BorderLayout()); JPanel vEmptyPanel = new JPanel(); vEmptyPanel.setPreferredSize(new Dimension(200, 220)); mButtonTchatter = new JButton("Tchatter"); add(vEmptyPanel, BorderLayout.PAGE_START); add(mButtonTchatter, BorderLayout.CENTER); } public void addListenerToButtonTchatter(ActionListener pListener) { mButtonTchatter.addActionListener(pListener); } }
package graphic; import graphic.ConnectionPanel; import graphic.TchatPanel; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.JFrame; import javax.swing.JOptionPane; import bean.TchatMessage; import net.TchatClient; import net.TchatClient.StatusClient; public class TchatMainWindow extends JFrame { private static final long serialVersionUID = 1L; private TchatPanel mTchatPanel; private ConnectionPanel mConnectionPanel; private Map<String,TchatWindow> mPrivatesTchatsWindows; private TchatClient mTchatClient; private String mClientNom; public TchatMainWindow() { setTitle("Connexion au Tchat"); setSize(550, 550); initConnectionPanel(); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent pEvent) { mTchatClient.setStatusClient(StatusClient.stopped); for (TchatWindow vPrivateTchatWindowTmp : mPrivatesTchatsWindows.values()) { vPrivateTchatWindowTmp.dispose(); } } }); mTchatClient = new TchatClient(); mPrivatesTchatsWindows = new HashMap<String, TchatWindow>(); setVisible(true); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } private void initConnectionPanel() { setLayout(new FlowLayout()); mConnectionPanel = new ConnectionPanel(); mConnectionPanel.addListenerToButtonTchatter(new ActionListener() { public void actionPerformed(ActionEvent e) { mClientNom = JOptionPane.showInputDialog(TchatMainWindow.this, "Veuillez entrer un pseudo pour tchatter :"); mTchatClient.launchTchatClient(mClientNom); checkAuthentificationClientStatus(); } }); add(mConnectionPanel); } private void initTchatPanel() { setTitle("Bienvenue " + mClientNom); remove(mConnectionPanel); setLayout(new BorderLayout(5, 5)); mTchatPanel = new TchatPanel(); mTchatPanel.addListenerToSendMessageButton(new ActionListener() { public void actionPerformed(ActionEvent arg0) { TchatMessage vTchatMessage = new TchatMessage(); vTchatMessage.setEmetteur(mClientNom); vTchatMessage.setMessage(mTchatPanel.getMessageTextArea().getText()); mTchatClient.getMessagesToSend().add(vTchatMessage); mTchatPanel.displayTchatMessageInTchatArea(vTchatMessage); mTchatPanel.getMessageTextArea().setText(""); } }); mTchatPanel.addListenerToClientsConnected(new MouseAdapter() { public void mouseClicked(MouseEvent pEvent) { if (pEvent.getClickCount() > 1) { final String vSelectedDestinataire = new String((String) mTchatPanel.getClientsConnected().getSelectedValue()); if (vSelectedDestinataire != null && !mClientNom.equals(vSelectedDestinataire) && !mPrivatesTchatsWindows.containsKey(vSelectedDestinataire)) { createPrivateTchatWindow(vSelectedDestinataire); } } } }); add(mTchatPanel, BorderLayout.CENTER); mTchatPanel.updateUI(); checkTchatClientStatus(); } private void createPrivateTchatWindow(final String pDestinataire) { TchatWindow vTchatWindow = new TchatWindow(); vTchatWindow.setTchatClient(mTchatClient); vTchatWindow.setClientNom(mClientNom); vTchatWindow.setPrivateDestinataire(pDestinataire); vTchatWindow.changeTitle(); vTchatWindow.displayClientsConnected(); vTchatWindow.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent pEvent) { mPrivatesTchatsWindows.remove(pDestinataire); } }); mPrivatesTchatsWindows.put(pDestinataire, vTchatWindow); } private void displayMessagesReceived() { Map<String, List<TchatMessage>> vMessagesReceived = mTchatClient.sortMessagesReceivedByEmetteur(); mTchatPanel.displayTchatsMessagesInTchatArea(vMessagesReceived.get("all")); vMessagesReceived.remove("all"); for (String vDestinataireTmp : vMessagesReceived.keySet()) { if (!mPrivatesTchatsWindows.containsKey(vDestinataireTmp)) { createPrivateTchatWindow(new String(vDestinataireTmp)); } mPrivatesTchatsWindows.get(vDestinataireTmp).getTchatPanel().displayTchatsMessagesInTchatArea(vMessagesReceived.get(vDestinataireTmp)); } mTchatClient.getMessagesReceived().clear(); } private void displayClientsConnected() { List<String> vClientsConnected = new ArrayList<String>(mTchatClient.getClientsConnected()); mTchatPanel.displayClientsConnected(vClientsConnected); for (String vDestinataireTmp : mPrivatesTchatsWindows.keySet()) { if (!vClientsConnected.contains(vDestinataireTmp)) { mPrivatesTchatsWindows.get(vDestinataireTmp).removePrivateDestinataire(); mPrivatesTchatsWindows.get(vDestinataireTmp).getTchatPanel().getButtonSendMessage().setEnabled(false); } } } private void checkAuthentificationClientStatus() { Thread vThread = new Thread() { public void run() { while (true) { if (mTchatClient.getStatusClient() == StatusClient.success) { initTchatPanel(); return; } else if (mTchatClient.getStatusClient() == StatusClient.connectionFailed) { JOptionPane.showMessageDialog(TchatMainWindow.this, "Connection au serveur impossible !", "Erreur", JOptionPane.ERROR_MESSAGE); return; } else if (mTchatClient.getStatusClient() == StatusClient.authentificationFailed) { JOptionPane.showMessageDialog(TchatMainWindow.this, "Ce nom existe deja ou est incorrect !", "Warning", JOptionPane.WARNING_MESSAGE); return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }; vThread.start(); } private void checkTchatClientStatus() { Thread vThread = new Thread() { public void run() { while (mTchatClient.getStatusClient() == StatusClient.success) { displayMessagesReceived(); displayClientsConnected(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } if (mTchatClient.getStatusClient() == StatusClient.connectionFailed) { JOptionPane.showMessageDialog(TchatMainWindow.this, "Connection au serveur interrompue !", "Erreur", JOptionPane.ERROR_MESSAGE); } } }; vThread.start(); } }
package graphic; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionListener; import java.awt.event.MouseListener; import java.util.List; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import bean.TchatMessage; public class TchatPanel extends JPanel { private static final long serialVersionUID = 1L; private JTextArea mTchatTextArea; private JTextArea mMessageTextArea; private JList mClientsConnected; private JButton mButtonSendMessage; public TchatPanel() { setPreferredSize(new Dimension(500, 500)); setLayout(new BorderLayout(5, 5)); JPanel vPanelVerticalSeparation = new JPanel(); vPanelVerticalSeparation.setPreferredSize(new Dimension(5, 500)); /**/ JPanel vPanelLeft = new JPanel(); vPanelLeft.setPreferredSize(new Dimension(350, 450)); vPanelLeft.setLayout(new BorderLayout()); mTchatTextArea = new JTextArea(); mTchatTextArea.setEditable(false); JScrollPane vScrollPaneTchatTextArea = new JScrollPane(mTchatTextArea); vScrollPaneTchatTextArea.setPreferredSize(new Dimension(350, 350)); mMessageTextArea = new JTextArea(); JScrollPane vScrollPaneMessageTextArea = new JScrollPane(mMessageTextArea); vScrollPaneMessageTextArea.setPreferredSize(new Dimension(350, 100)); vPanelLeft.add(vScrollPaneTchatTextArea, BorderLayout.CENTER); vPanelLeft.add(vScrollPaneMessageTextArea, BorderLayout.PAGE_END); /**/ JPanel vPanelRight = new JPanel(); vPanelRight.setPreferredSize(new Dimension(150, 450)); vPanelRight.setLayout(new BorderLayout()); mClientsConnected = new JList(); mClientsConnected.setPreferredSize(new Dimension(150, 350)); mButtonSendMessage = new JButton("Envoyer"); vPanelRight.add(mClientsConnected, BorderLayout.CENTER); vPanelRight.add(mButtonSendMessage, BorderLayout.PAGE_END); add(vPanelLeft, BorderLayout.CENTER); add(vPanelRight, BorderLayout.LINE_END); } public void addListenerToClientsConnected(MouseListener pListener) { mClientsConnected.addMouseListener(pListener); } public void displayTchatsMessagesInTchatArea(List<TchatMessage> pMessages) { for (TchatMessage vMessageTmp : pMessages) { displayTchatMessageInTchatArea(vMessageTmp); } } public void displayTchatMessageInTchatArea(TchatMessage pMessage) { mTchatTextArea.append(pMessage.getEmetteur() + " : " + pMessage.getMessage()); mTchatTextArea.append(System.getProperty("line.separator")); mTchatTextArea.append(System.getProperty("line.separator")); } public void displayClientsConnected(List<String> pClientsConnected) { DefaultListModel vModel = new DefaultListModel(); for (String vClientConnectedTmp : pClientsConnected) { vModel.addElement(vClientConnectedTmp); } mClientsConnected.setModel(vModel); } public void addListenerToSendMessageButton(ActionListener pListener) { mButtonSendMessage.addActionListener(pListener); } public JTextArea getMessageTextArea() { return mMessageTextArea; } public JList getClientsConnected() { return mClientsConnected; } public JButton getButtonSendMessage() { return mButtonSendMessage; } }
package graphic; import graphic.TchatPanel; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import javax.swing.JFrame; import bean.TchatMessage; import net.TchatClient; public class TchatWindow extends JFrame { private static final long serialVersionUID = 1L; private TchatPanel mTchatPanel; private TchatClient mTchatClient; private String mPrivateDestinataire; private String mClientNom; public TchatWindow() { setSize(350, 350); setLayout(new BorderLayout(5, 5)); mTchatPanel = new TchatPanel(); mTchatPanel.addListenerToSendMessageButton(new ActionListener() { public void actionPerformed(ActionEvent e) { TchatMessage vTchatMessage = new TchatMessage(); vTchatMessage.setEmetteur(mClientNom); vTchatMessage.setDestinataire(mPrivateDestinataire); vTchatMessage.setMessage(mTchatPanel.getMessageTextArea().getText()); mTchatClient.getMessagesToSend().add(vTchatMessage); mTchatPanel.displayTchatMessageInTchatArea(vTchatMessage); mTchatPanel.getMessageTextArea().setText(""); } }); add(mTchatPanel, BorderLayout.CENTER); setVisible(true); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } public TchatPanel getTchatPanel() { return mTchatPanel; } public void setTchatClient(TchatClient tchatClient) { mTchatClient = tchatClient; } public void setClientNom(String clientNom) { mClientNom = clientNom; } public void setPrivateDestinataire(String privateDestinataire) { mPrivateDestinataire = privateDestinataire; } public void changeTitle() { setTitle("Conversation avec " + mPrivateDestinataire); } public void displayClientsConnected() { ArrayList<String> vClientsConnected = new ArrayList<String>(); vClientsConnected.add(mClientNom); vClientsConnected.add(mPrivateDestinataire); mTchatPanel.displayClientsConnected(vClientsConnected); } public void removePrivateDestinataire() { ArrayList<String> vClientsConnected = new ArrayList<String>(); vClientsConnected.add(mClientNom); mTchatPanel.displayClientsConnected(vClientsConnected); } }
package net; import io.ConfigReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import bean.TchatMessage; public class TchatClient { private Socket mClientSocket; private List<TchatMessage> mMessagesToSend; private List<TchatMessage> mMessagesReceived; private List<String> mClientsConnected; private StatusClient mStatusClient; public TchatClient() { mClientsConnected = new ArrayList<String>(); mMessagesToSend = Collections.synchronizedList(new ArrayList<TchatMessage>()); mMessagesReceived = Collections.synchronizedList(new ArrayList<TchatMessage>()); } private void connectToServer() throws Exception { mStatusClient = StatusClient.none; int vPortServeur = Integer.parseInt(ConfigReader.getInstance("client.properties").getProperty("serveur.port")); String vIpServeur = ConfigReader.getInstance("client.properties").getProperty("serveur.ip"); mClientSocket = new Socket(vIpServeur, vPortServeur); } private boolean authentificateClientNameToServer(String pClientName) throws Exception { ObjectOutputStream vObjectOutputStream = new ObjectOutputStream(mClientSocket.getOutputStream()); vObjectOutputStream.writeObject(pClientName); vObjectOutputStream.flush(); ObjectInputStream vObjectInputStream = new ObjectInputStream(mClientSocket.getInputStream()); if ("OK".equals((String) vObjectInputStream.readObject())) { return true; } return false; } private boolean checkClientName(String pClientName) { if (pClientName == null || pClientName.equals("") || pClientName.equals("all")) { return false; } return true; } private void echangeMessagesWithServeur() throws Exception { ObjectOutputStream vObjectOutputStream = new ObjectOutputStream(mClientSocket.getOutputStream()); vObjectOutputStream.writeObject(mMessagesToSend); vObjectOutputStream.flush(); mMessagesToSend.clear(); // On recupère les messages du serveur ObjectInputStream vObjectInputStream = new ObjectInputStream(mClientSocket.getInputStream()); mMessagesReceived.addAll((List<TchatMessage>) vObjectInputStream.readObject()); // On recupère la liste des connectés dpuis le serveur mClientsConnected = (List<String>) vObjectInputStream.readObject(); } public Map<String, List<TchatMessage>> sortMessagesReceivedByEmetteur() { HashMap<String, List<TchatMessage>> vResult = new HashMap<String, List<TchatMessage>>(); vResult.put("all", new ArrayList<TchatMessage>()); for (TchatMessage vTchatMessage : mMessagesReceived) { if (vTchatMessage.getDestinataire() == null) { vResult.get("all").add(vTchatMessage); } else { if (!vResult.containsKey(vTchatMessage.getEmetteur())) { vResult.put(vTchatMessage.getEmetteur(), new ArrayList<TchatMessage>()); } vResult.get(vTchatMessage.getEmetteur()).add(vTchatMessage); } } return vResult; } public void launchTchatClient(final String pClientName) { if (!checkClientName(pClientName)) { mStatusClient = StatusClient.authentificationFailed; return; } Thread vThread = new Thread() { public void run() { try { connectToServer(); if (authentificateClientNameToServer(pClientName) ){ mStatusClient = StatusClient.success; while (mStatusClient != StatusClient.stopped) { echangeMessagesWithServeur(); Thread.sleep(1000); } } else { mStatusClient = StatusClient.authentificationFailed; } } catch (Exception e) { mStatusClient = StatusClient.connectionFailed; e.printStackTrace(); } finally { try { if (mClientSocket != null) { mClientSocket.close(); } } catch (Exception e) { e.printStackTrace(); } } } }; vThread.start(); } public StatusClient getStatusClient() { return mStatusClient; } public void setStatusClient(StatusClient pStatusClient) { mStatusClient = pStatusClient; } public List<TchatMessage> getMessagesToSend() { return mMessagesToSend; } public List<TchatMessage> getMessagesReceived() { return mMessagesReceived; } public List<String> getClientsConnected() { return mClientsConnected; } public enum StatusClient { none, connectionFailed, success, authentificationFailed, stopped } }
Lanceur de la partie client :
import graphic.TchatMainWindow; public class TchatWindowLauncher { public static void main(String[] args) { new TchatMainWindow(); } }
Partie serveur :
package net; import io.ConfigReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import bean.TchatMessage; public class TchatServer { public Map<String, List<TchatMessage>> mClientsTchatsMessages; public void launchServer() { mClientsTchatsMessages = Collections.synchronizedMap(new HashMap<String, List<TchatMessage>>()); try { int vPortServeur = Integer.parseInt(ConfigReader.getInstance("serveur.properties").getProperty("serveur.port")); ServerSocket vServerSocket = new ServerSocket(vPortServeur); while(true) { final Socket vSocket = vServerSocket.accept(); Thread vThread = new Thread() { String vCurrentThreadClientNom = null; public void run() { try { if ((vCurrentThreadClientNom = authentificateClient(vSocket)) != null) { while (true) { echangeMessagesWithClient(vSocket, vCurrentThreadClientNom); } } } catch (Exception e) { mClientsTchatsMessages.remove(vCurrentThreadClientNom); e.printStackTrace(); } finally { try { vSocket.close(); } catch (Exception e) { e.printStackTrace(); } } } }; vThread.start(); } } catch (Exception e) { e.printStackTrace(); } } private String authentificateClient(Socket pSocket) throws Exception { ObjectInputStream vObjectInputStream = new ObjectInputStream(pSocket.getInputStream()); String vClientName = (String) vObjectInputStream.readObject(); String vReponse = null; if (mClientsTchatsMessages.containsKey(vClientName)) { vReponse = "KO"; vClientName = null; } else { vReponse = "OK"; mClientsTchatsMessages.put(vClientName, new ArrayList<TchatMessage>()); } ObjectOutputStream vObjectOutputStream = new ObjectOutputStream(pSocket.getOutputStream()); vObjectOutputStream.writeObject(vReponse); vObjectOutputStream.flush(); return vClientName; } private void echangeMessagesWithClient(Socket pSocket, String vCurrentThreadClientNom) throws Exception { ObjectInputStream vObjectInputStream = new ObjectInputStream(pSocket.getInputStream()); List<TchatMessage> vTchatMessagesReceived = (List<TchatMessage>) vObjectInputStream.readObject(); addMessageToClientsMessages(vTchatMessagesReceived); ObjectOutputStream vObjectOutputStream = new ObjectOutputStream(pSocket.getOutputStream()); vObjectOutputStream.writeObject(mClientsTchatsMessages.get(vCurrentThreadClientNom)); vObjectOutputStream.flush(); vObjectOutputStream.writeObject(new ArrayList<String>(mClientsTchatsMessages.keySet())); vObjectOutputStream.flush(); mClientsTchatsMessages.get(vCurrentThreadClientNom).clear(); } private void addMessageToClientsMessages(List<TchatMessage> pTchatsMessages) { for (TchatMessage vTchatMessageTmp : pTchatsMessages) { try { // Cas message prive if (vTchatMessageTmp.getDestinataire() != null) { mClientsTchatsMessages.get(vTchatMessageTmp.getDestinataire()).add(vTchatMessageTmp); // Cas message general } else { for (String vClientConnectedTmp : mClientsTchatsMessages.keySet()) { if (!vClientConnectedTmp.equals(vTchatMessageTmp.getEmetteur())) { mClientsTchatsMessages.get(vClientConnectedTmp).add(vTchatMessageTmp); } } } } catch (NullPointerException e) { // NOBREAK e.printStackTrace(); } } } }
Lanceur de la partie serveur :
import net.TchatServer; public class TchatServerLauncher { public static void main(String[] args) { new TchatServer().launchServer(); } }
Partie "communes" :
package bean; import java.io.Serializable; public class TchatMessage implements Serializable { private static final long serialVersionUID = 1L; private String mMessage; private String mEmetteur; private String mDestinataire; public String getMessage() { return mMessage; } public void setMessage(String pMessage) { mMessage = pMessage; } public String getEmetteur() { return mEmetteur; } public void setEmetteur(String pEmetteur) { mEmetteur = pEmetteur; } public String getDestinataire() { return mDestinataire; } public void setDestinataire(String pDestinataire) { mDestinataire = pDestinataire; } }
package io; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class ConfigReader { private Properties mProperties; private static ConfigReader sInstance; private ConfigReader(String pFilePropertiesName) throws IOException { readConfig(pFilePropertiesName); } public static ConfigReader getInstance(String pFilePropertiesName) { if (sInstance == null) { try { sInstance = new ConfigReader(pFilePropertiesName); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Impossible de lire le fichier " + pFilePropertiesName); } } return sInstance; } private void readConfig(String pFilePropertiesName) throws IOException { mProperties = new Properties(); FileInputStream vFileInputStream = new FileInputStream(pFilePropertiesName); mProperties.load(vFileInputStream); vFileInputStream.close(); } public String getProperty(String pKey) { return mProperties.getProperty(pKey); } public Properties getProperties() { return mProperties; } public static String getClasspathResource(String pResourcePath) { String vPath = pResourcePath; if (vPath.startsWith("/")) { vPath = vPath.substring(1); } try { return Thread.currentThread().getContextClassLoader().getResource(vPath).getPath().replaceAll("%20", " "); } catch (Exception pException) { throw new RuntimeException("La ressource " + pResourcePath + " n est pas dans le classpath !"); } } }
Pour fonctionner le client a besoin d un fichier "client.properties" "dans le répertoire d execution" avec les proprietes suivantes
serveur.port=3500 serveur.ip=localhost
Pour fonctionner le serveur a besoin d un fichier "serveur.properties" "dans le répertoire d execution" avec les proprietes suivantes
serveur.port=3500
J'espère que je n'ai rien oublié, n'oubliez pas de mettre les classes dans les bons packages :)
Bonne chance,
Niroken