/**
* Chat avance java cote serveur
* 12/11/2003
* Remi Wipliez && Raphael Mariage.
* version 1.0
* La classe comprend le main et la definition des Threads, un thread par client
*/
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.lang.Thread;
import java.util.Enumeration;
import java.util.Vector;
import java.util.GregorianCalendar;
/* l'objet info_client contient toutes les informations "vitales" pour l'identification du client, c'est a dire qu'a chaque client est
* associe un objet Info-client avec tous ces parametres */
class Info_client {
int portcl;
String nick, passwd, groupe;
InetAddress adrcl;
boolean connect;
int cantalk=0, grade=0;
public Info_client(String nickname, String pass, InetAddress adr, int port, boolean connexion, int compteur, int grad) {
nick = nickname;
adrcl = adr;
portcl = port;
passwd = pass;
connect = connexion;
cantalk = compteur;
grade = grad;
}
}
class Group {
String nom, proprio;
Vector membres;
public Group(String name, String creat, Vector members) {
nom = name;
proprio = creat;
membres = members;
}
}
public class ServerUDP {
static int ind1, lg, serv_port, max_cl = 30, taille_buff = 10240, ind=0, cl_port, dest_port, k=0, port2;
static String serv_address, serv_port_tmp, chaine, ligne, adr="", login="", mess_recu="0", date, time, sepa, cmde="", line, pass, fonction;
static String renvoi_exit, user, renvoi, argu="", commande="", argument="", message="", cl, passwd="", cle, port="", nouveaucl, passcrypte;
static String[] info = new String[2];
static char tiret;
static Hashtable table_clients = new Hashtable(), table_groupes = new Hashtable();
static DatagramPacket dp, dpmdp, dpok, dpbadlog, dpexist;
static DatagramSocket ds;
static byte buffer[] = new byte[taille_buff];
static StringTokenizer str_tok, infos;
static InetAddress adr_cl, adr_dest, cl_adr, ia;
static Info_client info_cl, desti, client_t, recup, stock, majinfo, obj_exit;
static boolean pres = false, test=true, connect;
static Enumeration listekeys;
static BufferedReader br;
static Vector client = new Vector();
public static void main(String [] args) {
/* detection d'arguments passes en ligne de commande */
lg = args.length;
if (lg > 0) {
for (int i=0;i<lg;i++)
if (args[i].charAt(0) == '-') {
try {
switch(args[i].charAt(1)) {
case 'p': {
serv_port = Integer.parseInt(args[i+1]);
break;
}
default:{
System.out.println("Option inconnue : " + args[i]);
System.out.println("Options possibles : ");
System.out.println("-p : definir un port ");
System.out.println(args[i].charAt(1));
System.out.println(args[i+1]);
System.exit(0);
}
}
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Argument manquant...");
System.exit(0);
}
}
}
else {
serv_port = 2222;
}
/* fin de la detection des arguments */
table_clients = ControlServer.set_table_clients();
table_groupes = ControlServer.setgroups();
/* creation d'un socket avec le port du server */
ds = ConnectUDP.dsocket(serv_port);
dp = ConnectUDP.dpacket(buffer, taille_buff, null, 0);
/* lancement d'un thread dit de controle, c'est a dire permettant le controle local du server (afficher la table, la remettre a 0,
* kick un client, ... */
new Control(table_clients, ds);
/* boucle infinie de detection d'un nouveau client */
while(true && !mess_recu.equals("")) {
/* on recupere la chaine envoyee par le client */
mess_recu = ConnectUDP.recep(ds, dp);
str_tok = new StringTokenizer(mess_recu,"@");
/* recuperation des informations client : login, InetAddress et port*/
login = "";
cl_port = dp.getPort();
cl_adr = dp.getAddress();
try {
login = str_tok.nextToken();
sepa = str_tok.nextToken();
cmde = str_tok.nextToken();
}
catch(java.util.NoSuchElementException j) {
}
/*on teste la presence du client ds la table clients*/
boolean estpres = table_clients.containsKey(login);
/* s'il est present, c'est qu'il s'est deja identifie au moins une fois */
if (estpres) {
recup = (Info_client)table_clients.get(login);
passcrypte = recup.passwd;
/* s'il n'est pas connecte (c'est a dire la variable connect de l'objet Info-clients = 0*/
if (!recup.connect) {
/* s'il y a un mot de passe, c'est que ke client s'est deja identifie */
if (!recup.passwd.equals("")) {
/* si le debut du pass = new, c'est qu'un nouveau client n'a pas encore confirme son nouveau pass */
if (!recup.passwd.substring(0,3).equals("new")) {
/* le client n'est pas connecte (booleen connecte = false) */
if (!recup.connect) {
/* si le port = 0, c'est une reconnexion */
if (recup.portcl == 0) {
/* on place donc le nouveau port et la nouvelle adresse dans l'objet client */
recup.adrcl = cl_adr;
recup.portcl = cl_port;
buffer = new byte[taille_buff];
fonction = "mdp";
buffer = fonction.getBytes();
dpmdp = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpmdp, cl_adr, cl_port);
}
/* si le port est different de 0, c'est que le client a demande a se connecter
* et il vient de rentrer son mot de passe */
else {
/* si le mot de passe est correct, on connecte le client en passant la variable connect
* a true */
if (recup.passwd.equals(cmde)) {
recup.connect = true;
/* la variable cantalk indique quand le client a totalement fini de s'identifier
* 0 = jamais parle
* 1 = a rentre son login
* 2 = a rentre son login et son mot de passe et peut maintenant discuter sur le chat. */
recup.cantalk = 1;
buffer = new byte[taille_buff];
fonction = "ok";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
/* on a accepte le client, on lui a envoye "ok" donc on peut l'ajouter a la bdd */
table_clients.remove(login);
table_clients.put(recup.nick, recup);
}
/* sinon on envoie un signe comme quoi le pass est faux */
else {
buffer = new byte[taille_buff];
fonction = "badpass";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
}
}
}
}
/* ici, si le debut du pass est new, c'est ke le client vient d'envoyer sa confirmation de mdp */
else {
/* si les 2 pass sont egaux on valide, et on ajoute le client a la table et on le connecte */
String passtmp = recup.passwd;
String passtmp2 = passtmp.substring(3, passtmp.length());
if (passtmp2.equals(cmde)) {
recup.passwd = cmde;
recup.connect = true;
recup.cantalk=1;
fonction = "ok";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
table_clients.remove(login);
table_clients.put(recup.nick, recup);
/* mise a jour du fichier, c'est a dire rajoute une ligne contenant le login et le
* mot de passe du nouveau client */
ControlServer.exec("maj", ds);
}
/* si les 2 pass sont differents, le client s'est trompe on redemande */
else {
recup.passwd = "";
fonction = "bad2pass";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
}
}
}
/* si le mdp est nul, c'est un nouveau client qui vient d'entrer son 1er pass */
/* on lui envoie donc la demande de second mdp */
else {
recup.passwd = "new" + cmde;
fonction = "2ndpass";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
}
}
/* si le client est deja connecte */
else {
/* si le port du client demandeur est different de celui enregistre dans la table (pour le client du
* meme nom), c'est qu'il existe deja un client connecte avec ce login */
if (recup.portcl != cl_port) {
fonction = "connected";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
/* creer un paquet null pour mettre a zero toutes les nouvelles infos, car le client qui a declenche ce message
* (connected) ne PEUT pas se connecter */
recup = new Info_client("", "", null, 0, false, 0, 0);
}
/* si les 2 ports sont egaux, c'est le bon client */
else {
/* si le debut du pass est egal a old, le client vient de donner son ancien mot de passe */
if (recup.passwd.substring(0,3).equals("old")) {
/* l'ancien mot de passe est egal a celui rentre : on demande le nouveau */
if (recup.passwd.substring(3,recup.passwd.length()).equals(cmde)) {
fonction = "newpass1";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
recup.passwd = "vachanger";
recup.cantalk = 0;
}
else {
fonction = "badoldpass";
System.out.println("ancien = " + recup.passwd.substring(3,recup.passwd.length()));
System.out.println("new = " + cmde);
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
}
}
/* si le mot de passe ne commence pas par old, soit il n'y a rien soit il est nul pour un changement */
else {
/* si le debut du pass est nul, le client vient de donner son nouveau mot de passe */
if (recup.passwd.equals("vachanger")) {
recup.passwd = "";
fonction = "newpass2";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
recup.passwd = "new" + cmde;
}
/* si le debut du pass est "new", le client vient de donner sa confirmation de nouveau mot de passe */
else {
if (recup.passwd.substring(0,3).equals("new")) {
/* les 2 nouveaux pass sont egaux, on procede alors au changement du pass */
if (recup.passwd.substring(3,recup.passwd.length()).equals(cmde)) {
fonction = "newpass";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
recup.passwd = cmde;
recup.cantalk=1;
}
/* les 2 nouveaux pass sont differents, ont ne peut proceder au changement et on remet l'ancien*/
else {
fonction = "badnewpass";
buffer = fonction.getBytes();
dpok = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpok, cl_adr, cl_port);
recup.passwd = "old" + passcrypte;
}
}
}
}
}
}
}
/* si le login n'est pas present, on teste si c'est un client qui veut s'identifier pour la 1ere fois
* avec le mot cle new + login. Sinon c'est une erreur de frappe sur le login ou il n'existe pas (encore)*/
else {
if (login.equals("new")) {
/* on verifie ici que le nouveau login entre n'est pas deja utilise */
boolean exist = table_clients.containsKey(cmde);
if (!exist) {
/* les conditions remplies, on peut creer un nouvel objet avec l'adr du client, son port, la variable connect a false
* la variable cantalk a 0, et un pass vierge car il n'en a encore rentre aucun */
info_cl = new Info_client(cmde, "", cl_adr, cl_port, false, 0,0);
table_clients.put(info_cl.nick, info_cl);
// penser ici a mettre le fichier client a jour
buffer = new byte[taille_buff];
fonction = "mdp";
buffer = fonction.getBytes();
dpmdp = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpmdp, cl_adr, cl_port);
}
/* si le login existe, on envoie un message au client */
else {
buffer = new byte[taille_buff];
fonction = "exist";
buffer = new byte[taille_buff];
buffer = fonction.getBytes();
dpexist = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpexist, cl_adr, cl_port);
recup = new Info_client("", "", null, 0, false, 0,0);
}
}
/* si le login n'est pas new le login est mauvais */
else {
buffer = new byte[taille_buff];
fonction = "badlog";
buffer = new byte[taille_buff];
buffer = fonction.getBytes();
dpbadlog = ConnectUDP.dpacket(buffer, buffer.length, cl_adr, cl_port);
ConnectUDP.envoi(ds, dpbadlog, cl_adr, cl_port);
recup = new Info_client("", "", null, 0, false, 0,0);
}
}
/*******************************************/
// fin de la procedure de detection client
//TestClient(login, cl_adr, cl_port);
GregorianCalendar day = new GregorianCalendar();
/* dans chaque ojbet client, la variable cantalk est passe a 2 apres un 1er passage ici, pour etre sur que le pass ou des infos
* de connection ne s'affiche */
if (recup.cantalk == 2) {
/* on teste si le client veut sortir ou pas */
if (cmde.equals("/exit")) {
date = day.getTime().toString();
time = date.substring(11,20);
renvoi_exit = login + " has exit at " + time;
System.out.println(renvoi_exit);
buffer = renvoi_exit.getBytes();
/* creation d'un nouveau packet avec la chaine a renvoyer */
dp = ConnectUDP.dpacket(buffer, buffer.length, null, 1);
/* boucle qui envoit la chaine annoncant la sortie d'un client a chacun des clients connectes */
listekeys = table_clients.keys();
for (ind=0; ind<table_clients.size(); ind++) {
cle = (String)listekeys.nextElement();
desti = (Info_client)table_clients.get(cle);
adr_dest = (InetAddress)desti.adrcl;
dest_port = desti.portcl;
if (dest_port != 0)
ConnectUDP.envoi(ds, dp, adr_dest, dest_port);
}
/* on enleve le client de la bdd info_client */
table_clients.remove(login);
obj_exit = new Info_client(login, recup.passwd, null, 0, false, 0,0);
table_clients.put(obj_exit.nick, obj_exit);
}
/* dans les autres cas, un message normal ou une commande */
else {
/* ne rien faire si la chaine envoyee est nulle */
if (!cmde.equals("")) {
/* test afin de reconnaitre une commande a l'aide du caracteres / (slash) */
if (cmde.charAt(0) != '/') {
System.out.println(login + "> " + cmde);
date = day.getTime().toString();
time = date.substring(11,20);
renvoi = time + " " + login + "> " + cmde;
buffer = renvoi.getBytes();
dp = ConnectUDP.dpacket(buffer, buffer.length, null, 1);
/* c'est un message normal donc on l'envoie a tout le monde */
listekeys = table_clients.keys();
for (int i=0; i<table_clients.size(); i++) {
cle = (String)listekeys.nextElement();
desti = (Info_client)table_clients.get(cle);
login = desti.nick;
adr_dest = desti.adrcl;
dest_port = desti.portcl;
if (dest_port != 0)
ConnectUDP.envoi(ds, dp, adr_dest, dest_port);
}
}
/* il s'agit ici du traitement de la chaine de caracteres contenant l'intitule de la
* commande, le ou les arguments, le login de l'expediteur et le message */
else {
try {
k=0;
/* chaque "partie" (login, argument(s), commande,...)est separee par un espace.
* Ainsi on a 3 boucles while qui recupere chacun des parametres. Puis on reduit
* au fur et a mesure les chaines avec substring jusqu'a obtenir les 3 parametres
* dans des chaines separees */
while(cmde.charAt(k) != ' ') {
commande = commande + cmde.charAt(k);
k++;
}
argu = cmde.substring(k+1,cmde.length());
k=0;
while(argu.charAt(k) != ' ') {
argument = argument + argu.charAt(k);
k++;
}
message = argu.substring(k+1, argu.length());
/* ensuite on lance l'interpretation de la commande */
Cmde.traitement(ds, login, commande, argument, message);
}
catch(java.lang.StringIndexOutOfBoundsException e) {
if (commande.equals("/msg")) {
System.out.println("usage de /msg : ");
System.out.println("/msg dest message");
System.out.println("/msg dest1+dest2+dest3... message");
}
else {
Cmde.traitement(ds, login, commande, argument, message);
login = "";
commande = "";
argument = "";
message = "";
}
}
message = "";
argu = "";
}
}
/* creation d'un nouveau paquet vierge pour reception */
buffer = new byte[taille_buff];
dp = ConnectUDP.dpacket(buffer, taille_buff, null, 1);
}
}
if (recup.cantalk == 1)
recup.cantalk = 2;
}
}
}
/* Thread d'attente d'entree au clavier pour la gestion interne du serveur (commande, sortie, kick, ...) */
class Control extends Thread {
DatagramSocket ds;
DatagramPacket dp;
int taille_buff = 10240, sport, test2;
String adrs, serv_quit, command="", test1, cle, kicke;
InetAddress S_ia;
Hashtable info;
BufferedReader kbr;
byte[] buffer = new byte[taille_buff];
Info_client desti, test;
int dest_port;
InetAddress adr_dest, test3;
Enumeration listekeys;
public Control(Hashtable tbl, DatagramSocket sock) {
info = tbl;
ds = sock;
start();
}
public void run() {
/* boucle infinie qui attend les entrees clavier sur le serveur */
while(true) {
System.out.print("/");
kbr = new BufferedReader(new InputStreamReader(System.in));
try {
command = kbr.readLine();
}
catch(java.io.IOException e) {
System.out.println("erreur IO");
}
ControlServer.exec(command, ds);
}
}
}
# Re: Server chat
Posté par Boa Treize (site web personnel) . Évalué à 4.
[^] # Re: Server chat
Posté par ASpirit . Évalué à 3.
Nan, pas si naje que cha, parche que on peut croire qu'ils veulent nous lancher un message... et alors amuche toi bien à analicher le code, du déchut jusqu'à la chin !
(une boucheille à la mer... mocherne !)
# super intéressant
Posté par TazForEver . Évalué à 0.
ça y est t'as bien joué ? t'as découvert les journaux ?
en plus Java ça pue spa libre...
[^] # Re: super intéressant
Posté par kennux . Évalué à 1.
Si tu veux tout savoir, j'ai ecrit aux admins histoire de savoir si CT possible de virer les journaux..
C tt, fo pas s'enflammer pour si peu..
PS : si vous voulez le server java correspondant au client + haut...
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.