⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chatserver.java

📁 enable to do work a local chat in java using UDP
💻 JAVA
字号:
package fr.iutvalence.java.tp8.chat.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;

import fr.iutvalence.java.tp8.chat.server.exceptions.InformationAccessException;
import fr.iutvalence.java.tp8.chat.server.exceptions.UnknownUserException;

/**
 * Exercice d'application sur l'utilisation de JDBC (TP8).<br/> Partie serveur
 * de l'application de chat, attente et validation des connexions. <br/><br/>
 * 
 * Commentaires à sebastien.jean@iut-valence.fr
 * 
 * @author Sébastien JEAN, IUT Valence, oct. 2006
 * @version 1.0
 */
public class ChatServer
{
	/**
	 * Le couple (IP,port) auquel le serveur doit s'attacher (bind).
	 */
	private InetSocketAddress address;

	/**
	 * Le socket de bienvenue.
	 */
	private ServerSocket serverSocket;

	/**
	 * Le distributeur de messages associé au serveur.
	 */
	private ChatServerDispatcher dispatcher;

	/**
	 * Le gestionnaire d'informations utilisateurs associé au serveur.
	 */
	private UsersInfoManager infoManager;

	/**
	 * Constructeur avec paramètre. Initialisation d'un serveur avec attachement
	 * local donné.
	 * 
	 * @param a le couple (IP,port) auquel le serveur doit s'attacher.
	 * @param manager le gestionnaire d'informations utilisateurs associé au
	 *        serveur.
	 */
	public ChatServer(InetSocketAddress a, UsersInfoManager manager)
	{
		// Initialisation de l'adresse de niveau transport associée au serveur
		this.address = a;

		// Initialisation du gestionnaires d'informations utilisateurs
		this.infoManager = manager;

		// Création et démarrage d'un nouveau distributeur de messages
		this.dispatcher = new ChatServerDispatcher();
		this.dispatcher.start();
	}

	/**
	 * Méthode interne utilisée pour initialiser le socket de bienvenue
	 * (création + bind).
	 * 
	 * @throws IOException si l'initialisation du socket serveur échoue.
	 */
	private void initServerSocket() throws IOException
	{
		// Création du socket serveur
		this.serverSocket = new ServerSocket();

		// Attachement local du serveur au couple (IP,port)
		this.serverSocket.bind(this.address);
	}

	/**
	 * Méthode interne utilisée pour fermer un socket (typiquement le socket
	 * client).
	 * 
	 * @param s le socket à fermer.
	 */
	private void closeSocket(Socket s)
	{
		try
		{
			s.close();
		}
		catch (IOException f)
		{}
	}

	/**
	 * Méthode interne gérant l'établissement de la connexion
	 * 
	 * @param s le socket permettant la communication avec le client se
	 *        connectant.
	 * @return le pseudonyme du client connecté si la connexion est acceptée,
	 *         <tt>null</tt> sinon.
	 * @throws IOException si la communication échoue.
	 * @throws InformationAccessException si l'accès aux informations
	 *         utilisateurs échoue.
	 */
	private String acceptUser(Socket s) throws IOException,
			InformationAccessException
	{
		String pseudo = null;

		// Envoi d'une demande d'identification au client
		// (il s'agit de lui envoyer une chaîne de caractères UTF-8
		// exprimant qu'il doit saisir son pseudonyme)
		// Il faut donc écrire une ligne de texte UTF-8 sur le socket, en
		// utilisant une chaîne de flots constituée d'un
		// PrintStream écrivant des caractères UTF-8 à travers le flot
		// d'écriture binaire associé au socket
		PrintStream ps = new PrintStream(s.getOutputStream(), true, "UTF-8");
		ps.println("Bienvenue ! Entrez votre pseudo "
				+ "(chaîne de caractères terminée"
				+ " par un retour à la ligne)");

		// Lecture du pseudo du client (ligne de texte UTF-8)
		// Pour lire une ligne de texte UTF-8 sur le socket,
		// il faut utiliser une chaîne de flots constituée d'un
		// BufferedReader lisant des lignes de texte à travers un
		// InputStreamReader lisant des caractères UTF-8 à travers le flot
		// de lecture binaire associé au socket
		BufferedReader br = new BufferedReader(new InputStreamReader(s
				.getInputStream(), "UTF-8"));
		pseudo = br.readLine();
		if (pseudo == null)
			throw new IOException();

		// Envoi d'une demande d'authentification au client
		// (il s'agit de lui envoyer une chaîne de caractères UTF-8
		// exprimant qu'il doit saisir son mot de passe)
		ps.println("Entrez votre mot de passe "
				+ "(chaîne de caractères terminée"
				+ " par un retour à la ligne)");

		// Lecture du mot de passe du client (ligne de texte UTF-8)
		String pass = br.readLine();
		if (pass == null)
			throw new IOException();

		// Vérification des informations d'authentification et de l'état de
		// connexion du client en utilisant le gestionnaire d'informations
		// utilisateurs. Un refus de connexion est notifié au client le cas
		// échéant
		try
		{
			if (!(pass.trim().equals(this.infoManager.getPassword(pseudo))))
			{
				ps.println("Mot de passe erroné, connexion refusée.");
				return null;
			}
			if (this.infoManager.getConnectionState(pseudo))
			{
				ps.println("Client, déjà connecté, connexion refusée.");
				return null;
			}
		}
		catch (UnknownUserException e1)
		{
			// Envoi d'une notification de refus de connexion au client
			ps.println("Pseudonyme inconnu, connexion refusée.");
			return null;
		}

		// Enregistrement d'un nouveau client auprès du distributeur de
		// messages
		// remarque : ici, on est sûr que l'association ne contient pas déjà
		// une entrée correspondant au client.
		this.dispatcher.addClient(pseudo, s);

		// Mise à jour de l'état de connexion du client (et de l'état "away")
		try
		{
			this.infoManager.setConnectionState(pseudo, true);
			this.infoManager.setAwayState(pseudo, false);
		}
		catch (Exception e)
		{
			// Remarque : les 2 exceptions possibles
			// UnknownUserException et NotConnectedException
			// ne peuvent pas survenir
		}

		// Envoi au client d'un message de bienvenue indiquant également le
		// nombre d'utilisateurs connectés
		String welcome = "ChatServer> Bienvenue " + pseudo + " !\n";
		int connectes = this.dispatcher.getClientCount();
		welcome += "ChatServer> " + connectes;
		if (connectes > 1)
		{
			welcome += " utilisateurs connectés";
		}
		else
		{
			welcome += " utilisateur connecté";
		}
		ps.println(welcome);

		return pseudo;
	}

	/**
	 * Démarrage du serveur.
	 */
	public void start()
	{
		// Vérification du support du jeu de caractères UTF-8 sur la plateforme
		if (!(Charset.availableCharsets().containsKey("UTF-8")))
		{
			System.err.println("<ChatServer> Le jeu de caractères UTF-8 "
					+ "n'est pas supporté par la platforme");
			return;
		}

		// Initialisation du socket serveur
		try
		{
			this.initServerSocket();
		}
		catch (IOException e)
		{
			System.err
					.println("<ChatServer> Démarrage du serveur "
							+ "impossible : problème lors de l'initialisation du socket serveur");

			// Fermeture du socket de bienvenue
			try
			{
				this.serverSocket.close();
			}
			catch (IOException e1)
			{}

			System.out.println("<ChatServer> Arrêt du serveur");
			return;
		}

		System.out.println("<ChatServer> Serveur démarré>");

		while (true)
		{
			Socket s = null;

			try
			{
				// Attente bloquante d'une connexion
				s = this.serverSocket.accept();
			}
			catch (IOException e)
			{
				// Si une erreur se produit, on termine le serveur
				System.err.println("<ChatServer> Echec lors de la connexion"
						+ " d'un client");
				break;
			}

			// Dialogue initial avec le client pour valider la connection
			String pseudo;
			try
			{
				pseudo = this.acceptUser(s);
				if (pseudo == null)
					throw new IOException();
			}
			catch (IOException e)
			{
				System.err
						.println("<ChatServer> Connexion avec le client interrompue !");
				this.closeSocket(s);
				continue;
			}
			catch (InformationAccessException e)
			{
				System.err
						.println("<ChatServer> Accès aux informations utilisateurs impossible !");
				break;
			}

			// Affichage dans la console du serveur du pseudo,
			// de l'adresse IP et du port associés au client
			System.out.println("<ChatServer>" + pseudo + " connecté depuis "
					+ s.getRemoteSocketAddress().toString());

			// Lancement d'une nouvelle tâche pour la gestion de la
			// communication avec ce client
			new ChatServerThread(pseudo, s, this.dispatcher, this.infoManager)
					.start();
		}

		// Fermeture du socket serveur
		try
		{
			this.serverSocket.close();
		}
		catch (IOException e)
		{}

		System.out.println("<ChatServer> Arrêt du serveur");
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -