Compare commits

..

7 commits

Author SHA1 Message Date
Cavailles Kevin
b5a1bbae96 changements communication 2020-12-05 19:06:21 +01:00
m-gues
54999b3184 Connexion vers locale terminée 2020-12-04 22:09:47 +01:00
m-gues
69392477dd package messages v1 terminé + quelques modifs de communication pour utiliser avec des Message 2020-12-02 15:16:17 +01:00
m-gues
f0c08d59c0 fin sceance 3 : package messages commence 2020-11-30 18:17:58 +01:00
m-gues
059b513f0a relation controleur/vue terminee 2020-11-26 10:53:35 +01:00
m-gues
06357235ca test commit 2020-11-23 17:08:24 +01:00
Cavailles Kevin
5edb39bd52 debut connexion 2020-11-23 16:39:13 +01:00
31 changed files with 769 additions and 18 deletions

View file

@ -0,0 +1,78 @@
package communication;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import main.Utilisateur;
/*import main.VueStandard;*/
public class Communication extends Thread{
protected static ArrayList<Utilisateur> users = new ArrayList<Utilisateur>();
protected static boolean containsUserFromID(String id) {
for(Utilisateur u : Communication.users) {
if(u.getId().equals(id) ) {
return true;
}
}
return false;
}
public static boolean containsUserFromPseudo(String pseudo) {
for(Utilisateur u : Communication.users) {
if(u.getPseudo().equals(pseudo) ) {
return true;
}
}
return false;
}
protected static int getIndexFromID(String id) {
for(int i=0; i < Communication.users.size() ; i++) {
if(Communication.users.get(i).getId().equals(id) ) {
return i;
}
}
return -1;
}
protected static synchronized void addUser(String idClient, String pseudoClient, InetAddress ipClient) throws UnknownHostException {
Communication.users.add(new Utilisateur(idClient, pseudoClient, ipClient));
/*VueStandard.userList.addElement(pseudoClient);*/
}
protected static synchronized void changePseudoUser(String idClient, String pseudoClient, InetAddress ipClient) {
int index = Communication.getIndexFromID(idClient);
Communication.users.get(index).setPseudo(pseudoClient);
/*VueStandard.userList.set(index, pseudoClient);*/
}
protected static int getIndexFromIP(InetAddress ip) {
for(int i=0; i < Communication.users.size() ; i++) {
if(Communication.users.get(i).getIp().equals(ip)) {
return i;
}
}
return -1;
}
protected static synchronized void removeUser(String idClient, String pseudoClient,InetAddress ipClient) {
int index = Communication.getIndexFromIP(ipClient);
if( index != -1) {
Communication.users.remove(index);
//VueStandard.userList.remove(index);
}
}
public static void removeAll(){
int oSize = Communication.users.size();
for(int i=0; i<oSize;i++) {
Communication.users.remove(0);
}
}
}

View file

@ -0,0 +1,114 @@
package communication;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import main.Utilisateur;
import messages.*;
public class CommunicationUDP extends Communication {
// public enum Mode {PREMIERE_CONNEXION, CHANGEMENT_PSEUDO, DECONNEXION};
private UDPClient client;
private int portServer;
private ArrayList<Integer> portOthers;
public CommunicationUDP(int portClient, int portServer, int[] portsOther) throws IOException {
this.portServer = portServer;
this.portOthers = this.getArrayListFromArray(portsOther);
new UDPServer(portServer, this).start();
this.client = new UDPClient(portClient);
}
private ArrayList<Integer> getArrayListFromArray(int ports[]) {
ArrayList<Integer> tmp = new ArrayList<Integer>();
for (int port : ports) {
tmp.add(port);
}
tmp.remove(Integer.valueOf(portServer));
return tmp;
}
public void sendMessageConnecte() throws UnknownHostException, IOException {
for(int port : this.portOthers) {
try {
this.client.sendMessageUDP_local(new MessageSysteme(Message.TypeMessage.JE_SUIS_CONNECTE), port, InetAddress.getLocalHost());
} catch (MauvaisTypeMessageException e) {/*Si ça marche pas essayer là*/}
}
}
// Send the message "add,id,pseudo" to localhost on all the ports in
// "portOthers"
// This allows the receivers' agent (portOthers) to create or modify an entry with the
// data of this agent
//Typically used to notify of a name change
public void sendMessageInfoPseudo() throws UnknownHostException, IOException {
Utilisateur self = Utilisateur.getSelf();
String pseudoSelf =self.getPseudo();
String idSelf = self.getId();
Message msout = null;
try {
msout = new MessageSysteme(Message.TypeMessage.INFO_PSEUDO, pseudoSelf, idSelf);
for(int port : this.portOthers) {
this.client.sendMessageUDP_local(msout, port, InetAddress.getLocalHost());
}
} catch (Exception e) {
e.printStackTrace();
}
}
//Same, but on only one port
//Typically used to give your current name and id to a newly arrived host
public void sendMessageInfoPseudo(int portOther) throws UnknownHostException, IOException {
Utilisateur self = Utilisateur.getSelf();
try {
Message msout = new MessageSysteme(Message.TypeMessage.INFO_PSEUDO, self.getPseudo(), self.getId());
this.client.sendMessageUDP_local(msout, portOther, InetAddress.getLocalHost());
} catch (MauvaisTypeMessageException e) {e.printStackTrace();}
}
// Send the message "del,id,pseudo" to localhost on all the ports in
// "portOthers"
// This allows the receivers' agent (portOthers) to delete the entry
// corresponding to this agent
public void sendMessageDelete() throws UnknownHostException, IOException {
for(int port : this.portOthers) {
try {
this.client.sendMessageUDP_local(new MessageSysteme(Message.TypeMessage.JE_SUIS_DECONNECTE), port, InetAddress.getLocalHost());
} catch (MauvaisTypeMessageException e) {/*Si ça marche pas essayer là*/}
}
}
//Pas encore adapte message
// private void sendIDPseudo_broadcast(String prefixe) throws UnknownHostException, IOException {
// Utilisateur self = Utilisateur.getSelf();
// String idSelf = self.getId();
// String pseudoSelf = self.getPseudo();
//
// String message = prefixe+","+idSelf + "," + pseudoSelf;
//
//
// this.client.sendMessageUDP_broadcast(message, this.portServer);
//
// }
// public synchronized void createSenderUDP(int port, Mode mode) throws SocketException {
// new SenderUDP(mode, port).start();
// }
}

View file

@ -0,0 +1,41 @@
package communication;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import messages.*;
public class UDPClient {
private DatagramSocket sockUDP;
private InetAddress broadcast;
public UDPClient(int port) throws SocketException, UnknownHostException {
this.sockUDP = new DatagramSocket(port);
InetAddress localHost = InetAddress.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
this.broadcast = networkInterface.getInterfaceAddresses().get(0).getBroadcast();
}
//Send a message casted as string to the specified port on localhost
protected void sendMessageUDP_local(Message message, int port, InetAddress clientAddress) throws IOException {
String messageString=message.toString();
DatagramPacket outpacket = new DatagramPacket(messageString.getBytes(), messageString.length(), clientAddress, port);
this.sockUDP.send(outpacket);
}
// protected void sendMessageUDP_broadcast(String message, int port) throws IOException{
// String messageString=message.toString();
// DatagramPacket outpacket = new DatagramPacket(messageString.getBytes(), messageString.length(), this.broadcast, port);
// this.sockUDP.send(outpacket);
// }
}

View file

@ -0,0 +1,70 @@
package communication;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Arrays;
import messages.*;
public class UDPServer extends Thread {
private DatagramSocket sockUDP;
private CommunicationUDP commUDP;
private byte[] buffer;
public UDPServer(int port, CommunicationUDP commUDP) throws SocketException {
this.commUDP = commUDP;
this.sockUDP = new DatagramSocket(port);
this.buffer = new byte[256];
}
@Override
public void run() {
while (true) {
try {
DatagramPacket inPacket = new DatagramPacket(buffer, buffer.length);
this.sockUDP.receive(inPacket);
String msgString = new String(inPacket.getData(), 0, inPacket.getLength());
Message msg = Message.stringToMessage(msgString);
switch(msg.getTypeMessage()) {
case JE_SUIS_CONNECTE :
//System.out.println("first co");
int portClient = inPacket.getPort();
int portServer = portClient+1;
this.commUDP.sendMessageInfoPseudo(portServer);
break;
case INFO_PSEUDO :
if (Communication.containsUserFromID(((MessageSysteme) msg).getId())) {
Communication.changePseudoUser(((MessageSysteme) msg).getId(), ((MessageSysteme) msg).getPseudo(), inPacket.getAddress());
}
else {
Communication.addUser(((MessageSysteme) msg).getId(), ((MessageSysteme) msg).getPseudo(), inPacket.getAddress());
System.out.println(((MessageSysteme) msg).getId()+", "+((MessageSysteme) msg).getPseudo());
}
break;
case JE_SUIS_DECONNECTE :
Communication.removeUser( ((MessageSysteme) msg).getId() , ((MessageSysteme) msg).getPseudo(), inPacket.getAddress() );
break;
default : //Others types of messages are ignored because they are supposed to be transmitted by TCP and not UDP
}
} catch (IOException e) {
System.out.println("receive exception");
}
}
}
}

View file

@ -0,0 +1,101 @@
package main;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.UnknownHostException;
import communication.*;
public class ControleurConnexion implements ActionListener {
private enum Etat {DEBUT, ID_OK};
private VueConnexion vue;
private Etat etat;
private CommunicationUDP comUDP;
private String id;
private String pseudo;
public ControleurConnexion(VueConnexion vue) {
this.vue = vue;
this.etat = Etat.DEBUT;
this.id="";
//Pour les tests, changer pour un truc plus général quand on change CommunicationUDP
try {
this.comUDP = new CommunicationUDP(2208, 2209, new int[] {2906});
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void actionPerformed(ActionEvent e) {
boolean inputOK = false;
if (this.etat == Etat.DEBUT) {
id=vue.getValeurTextField();
//Recherche dans la liste des utilisateurs enregistres, report sur inputOK
inputOK = id.contentEquals("idvalide");
if (inputOK) {
this.etat=Etat.ID_OK;
//Envoi broadcast du message "JeSuisActif" et, attente du retour de la liste des utilisateurs actifs
try {
comUDP.sendMessageConnecte();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(2);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//Mise en place de la demande du pseudo
vue.setTexteLabelInput("Veuillez entrer votre nom");
vue.resetValeurTextField();
inputOK=false;
}
else vue.setTexteLabelInput("Identifiant invalide, veuillez réessayer");
}
else {
pseudo=vue.getValeurTextField();
//Recherche dans la liste locale des utilisateurs connectes, report sur inputOK
inputOK = !Communication.containsUserFromPseudo(pseudo);
if (inputOK) {
//Reglage de l'utilisateur
try {
Utilisateur.setSelf(id, pseudo, "localhost");
} catch (UnknownHostException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
//Broadcast du pseudo
try {
comUDP.sendMessageInfoPseudo();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//Creation de la vue principale
vue.setTexteLabelInput("Congrations you done it");
}
else vue.setTexteLabelInput("Ce nom est déjà utilisé, veuillez en choisir un autre");
}
}
}

15
POO/src/main/Main.java Normal file
View file

@ -0,0 +1,15 @@
package main;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel{
public static void main(String[] args) {
Vue vc = new VueConnexion();
}
}

View file

@ -0,0 +1,28 @@
package main;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import communication.*;
public class Main2tests {
public static void main(String[] args) {
try {
Utilisateur.setSelf("idrandom", "RandomPersonne", "localhost");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Communication comUDP = new CommunicationUDP(2905, 2906, new int[] {2209});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {}
}
}

View file

@ -0,0 +1,51 @@
package main;
import java.io.Serializable;
import java.net.*;
public class Utilisateur implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String id;
private String pseudo;
private InetAddress ip;
private static Utilisateur self;
public Utilisateur(String id, String pseudo, InetAddress ip) throws UnknownHostException {
this.id = id;
this.pseudo = pseudo;
this.ip = ip;
System.out.println(InetAddress.getLocalHost());
}
public String getId() {
return id;
}
public String getPseudo() {
return pseudo;
}
public void setPseudo(String pseudo) {
this.pseudo = pseudo;
}
public InetAddress getIp() {
return ip;
}
public static void setSelf(String id, String pseudo,String host) throws UnknownHostException {
if(Utilisateur.self == null) {
Utilisateur.self = new Utilisateur(id, pseudo, InetAddress.getByName(host));
}
}
public static Utilisateur getSelf() {
return Utilisateur.self;
}
}

15
POO/src/main/Vue.java Normal file
View file

@ -0,0 +1,15 @@
package main;
import javax.swing.JPanel;
public class Vue extends JPanel{
public Vue() {
// TODO Auto-generated constructor stub
}
public void reduireAgent() {}
public void fermerAgent() {}
}

View file

@ -0,0 +1,79 @@
package main;
//Importe les librairies
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class VueConnexion extends Vue {
//Penser à regler la taille de la fenetre et a la centrer !
//Elements vue
private JFrame frame;
private JPanel panel;
private JButton boutonValider;
private JTextField input;
private JLabel labelInput;
//Controleur
ControleurConnexion controle;
public VueConnexion() {
super();
controle = new ControleurConnexion(this);
//Creation fenetre
frame = new JFrame("Connexion");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 100);
frame.setLocationRelativeTo(null);
//Creation panel
panel = new JPanel(new GridLayout(3,1));
//Ajout elements
ajouterElements();
//Regle le bouton par défaut
frame.getRootPane().setDefaultButton(boutonValider);
//Ajoute le panel a la fenetre
frame.getContentPane().add(panel, BorderLayout.CENTER);
//Affiche la fenetre
frame.setVisible(true);
}
private void ajouterElements() {
//Cree les elements
input = new JTextField();
labelInput = new JLabel("Veuillez entrer votre identifiant unique");
boutonValider = new JButton("Valider");
//Le controleur guette les evenements du bouton
boutonValider.addActionListener(controle);
//Ajoute les elements
panel.add(labelInput);
panel.add(input);
panel.add(boutonValider);
labelInput.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
}
//Getters et setters
public void setTexteLabelInput(String text) {
labelInput.setText(text);
}
public String getValeurTextField() {
return input.getText();
}
public void resetValeurTextField() {
input.setText("");
}
}

View file

@ -0,0 +1,8 @@
package messages;
public class MauvaisTypeMessageException extends Exception {
private static final long serialVersionUID = 1L;
}

View file

@ -0,0 +1,69 @@
package messages;
import java.io.Serializable;
import java.lang.instrument.Instrumentation;
import java.util.Arrays;
import messages.Message.TypeMessage;
public abstract class Message implements Serializable {
public enum TypeMessage {JE_SUIS_CONNECTE, JE_SUIS_DECONNECTE, INFO_PSEUDO, TEXTE, IMAGE, FICHIER, MESSAGE_NUL}
protected TypeMessage type;
private static final long serialVersionUID = 1L;
private static Instrumentation inst;
public TypeMessage getTypeMessage() {
return this.type;
}
protected abstract String attributsToString();
public String toString() {
return this.type+"###"+this.attributsToString();
}
public static Message stringToMessage(String messageString) {
try {
String[] parts = messageString.split("###");
switch (parts[0]) {
case "JE_SUIS_CONNECTE" :
return new MessageSysteme(TypeMessage.JE_SUIS_CONNECTE);
case "JE_SUIS_DECONNECTE" :
return new MessageSysteme(TypeMessage.JE_SUIS_DECONNECTE);
case "INFO_PSEUDO" :
return new MessageSysteme(TypeMessage.INFO_PSEUDO, parts[1], parts[2]);
case "TEXTE" :
return new MessageTexte(TypeMessage.TEXTE, parts[1]);
case "IMAGE" :
return new MessageFichier(TypeMessage.IMAGE, parts[1], parts[2]);
case "FICHIER" :
return new MessageFichier(TypeMessage.FICHIER, parts[1], parts[2]);
}
} catch (MauvaisTypeMessageException e) {}
return null;
}
//tests ici
public static void main(String[] args) throws MauvaisTypeMessageException {
Message m1 = new MessageSysteme(TypeMessage.JE_SUIS_CONNECTE);
Message m2 = new MessageSysteme(TypeMessage.JE_SUIS_DECONNECTE);
Message m3 = new MessageSysteme(TypeMessage.INFO_PSEUDO, "pseudo156434518", "id236");
Message m4 = new MessageTexte(TypeMessage.TEXTE, "blablabla");
Message m5 = new MessageFichier(TypeMessage.FICHIER, "truc", ".pdf");
System.out.println(Message.stringToMessage(m1.toString()));
System.out.println(Message.stringToMessage(m2.toString()));
System.out.println(Message.stringToMessage(m3.toString()));
System.out.println(Message.stringToMessage(m4.toString()));
System.out.println(Message.stringToMessage(m5.toString()));
}
}

View file

@ -0,0 +1,33 @@
package messages;
import messages.Message.TypeMessage;
public class MessageFichier extends Message {
private static final long serialVersionUID = 1L;
private String contenu;
private String extension;
public MessageFichier(TypeMessage type, String contenu, String extension) throws MauvaisTypeMessageException{
if ((type==TypeMessage.IMAGE)||(type==TypeMessage.FICHIER)) {
this.type=type;
this.contenu=contenu;
this.extension=extension;
}
else throw new MauvaisTypeMessageException();
}
public String getContenu() {
return this.contenu;
}
public String getExtension() {
return this.extension;
}
@Override
protected String attributsToString() {
return this.contenu+"###"+this.extension;
}
}

View file

@ -0,0 +1,39 @@
package messages;
public class MessageSysteme extends Message {
private static final long serialVersionUID = 1L;
private String pseudo;
private String id;
public MessageSysteme(TypeMessage type) throws MauvaisTypeMessageException{
if ((type==TypeMessage.JE_SUIS_CONNECTE)||(type==TypeMessage.JE_SUIS_DECONNECTE)||(type==TypeMessage.MESSAGE_NUL)) {
this.type=type;
this.pseudo="";
this.id="";
}
else throw new MauvaisTypeMessageException();
}
public MessageSysteme(TypeMessage type, String pseudo, String id) throws MauvaisTypeMessageException {
if (type==TypeMessage.INFO_PSEUDO) {
this.type=type;
this.pseudo=pseudo;
this.id=id;
}
else throw new MauvaisTypeMessageException();
}
public String getPseudo() {
return this.pseudo;
}
public String getId() {
return this.id;
}
@Override
protected String attributsToString() {
return this.pseudo+"###"+this.id;
}
}

View file

@ -0,0 +1,27 @@
package messages;
import messages.Message.TypeMessage;
public class MessageTexte extends Message {
private static final long serialVersionUID = 1L;
private String contenu;
public MessageTexte(TypeMessage type, String contenu) throws MauvaisTypeMessageException{
if (type==TypeMessage.TEXTE) {
this.type=type;
this.contenu=contenu;
}
else throw new MauvaisTypeMessageException();
}
public String getContenu() {
return this.contenu;
}
@Override
protected String attributsToString() {
return this.contenu;
}
}

View file

@ -1,20 +1,3 @@
# Projet_COO_POO # Projet_COO_POO
Projet de 4ème année : Conception et programmation orientée objet d'un systeme de clavardage distribué interactif multi-utilisateur temps réel Projet de 4ème année : Conception et programmation orientée objet d'un systeme de clavardage distribué interactif multi-utilisateur temps réel
Contenu (branche master):
Dossier rapports : rapports de conception et de projet
Dossier application : archives .jar permettant d'exécuter l'application (version classique)
Dossier serveur_presence : archives .jar et .war permettant d'exécuter respectivement l'application (version compatible avec le serveur) et le serveur de présence
Pour récupérer les codes sources :
- De l'application classique : branche application
- Du serveur et de l'application modifiée : branche serveur_presence (l'application est dans le projet POO, le servlet dans le projet POO_Server)
Toutes les autres branches concernent des versions obsolètes de l'application, merci de ne pas en tenir compte.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.