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

📄 chatserverthread.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.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;

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

/**
 * Exercice d'application sur l'utilisation de JDBC (TP8).<br/> Thread
 * serveur de l'application de chat, gérant la communication avec un client
 * (i.e. réception et traitement des messages émis par le client). <br/><br/>
 * 
 * Commentaires à sebastien.jean@iut-valence.fr
 * 
 * @author Sébastien JEAN, IUT Valence, oct. 2006
 * @version 1.0
 */
public class ChatServerThread extends Thread
{
	/**
	 * Le socket utilisé pour la communication avec le client.
	 */
	private Socket socket;

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

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

	/**
	 * Constructeur avec paramètres. Initialisation d'un thread serveur
	 * communicant avec un client donné.
	 * 
	 * @param pseudo le pseudonyme du client = le nom du thread.
	 * @param sock le socket permettant la communication avec le client.
	 * @param disp le distributeur de messages associé au serveur.
	 * @param manager le gestionnaire d'informations utilisateurs associé au
	 *        serveur.
	 */
	public ChatServerThread(String pseudo, Socket sock,
			ChatServerDispatcher disp, UsersInfoManager manager)
	{
		super(pseudo);

		// Passage de la tâche en démon pour ne pas empécher l'arrêt propre du
		// serveur
		this.setDaemon(true);

		// Initialisation du socket et du distributeur
		this.socket = sock;
		this.dispatcher = disp;
		this.infoManager = manager;
	}

	/**
	 * Affichage d'un message sur la console du serveur et terminaison de la
	 * tâche.
	 * 
	 * @param s le message à afficher sur la console du serveur.
	 */
	private void end(String s)
	{
		if (s != null)
		{
			System.out.println(s);
		}

		try
		{
			this.socket.close();
		}
		catch (IOException e)
		{}

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

	/**
	 * Méthode interne gérant le traitement des messages reçus
	 * 
	 * @param message le message reçu du client.
	 * @throws InformationAccessException si l'accès aux informations
	 *         utilisateurs a échoué.
	 */
	private void processMessage(String message)
			throws InformationAccessException
	{
		// Si message privé, envoi en unicast via le distributeur de messages
		if (message.startsWith("#TELL "))
		{
			String tellParams = message.substring(6).trim();
			int indexEndPseudo = tellParams.indexOf(' ');
			String tellPseudo = tellParams.substring(0, indexEndPseudo);
			String tellMessage = tellParams.substring(indexEndPseudo).trim();
			this.dispatcher.unicastMessage(this.getName(), tellPseudo,
					tellMessage);
			return;
		}

		// Si notification d'absence, mise à jour des informations utilisateurs
		// et envoi d'un message d'avertissement en diffusion
		if (message.startsWith("#AWAY"))
		{
			try
			{
				// Si le client s'est déjà déclaré absent, le message est sans
				// effet
				boolean hasEffect = false;
				synchronized (this.infoManager)
				{
					if (!this.infoManager.getAwayState(this.getName()))
					{
						this.infoManager.setAwayState(this.getName(), true);
						hasEffect = true;
					}
				}
				if (hasEffect)
					this.dispatcher.broadCastMessage("ChatServer", this
							.getName()
							+ " s'absente");
			}
			catch (Exception e)
			{
				// Remarque : les 2 exceptions possibles
				// UnknownUserException et NotConnectedException
				// ne peuvent pas survenir
			}
			return;
		}

		// Si notification de retour, mise à jour des informations utilisateurs
		// et envoi d'un message d'avertissement en diffusion
		if (message.startsWith("#BACK"))
		{

			try
			{
				// Si le client n'est pas déclaré absent, le message est sans
				// effet
				boolean hasEffect = false;
				synchronized (this.infoManager)
				{
					if (this.infoManager.getAwayState(this.getName()))
					{
						this.infoManager.setAwayState(this.getName(), false);
						hasEffect = true;
					}
				}
				if (hasEffect)
					this.dispatcher.broadCastMessage("ChatServer", this
							.getName()
							+ " est de retour");
			}
			catch (Exception e)
			{
				// Remarque : les 2 exceptions possibles
				// UnknownUserException et NotConnectedException
				// ne peuvent pas survenir
			}
			return;

		}

		// Sinon (message en diffusion), envoi en diffusion via le distributeur
		// de messages
		this.dispatcher.broadCastMessage(this.getName(), message);
	}

	/**
	 * Corps de la tâche.
	 */
	public void run()
	{
		// Obtention d'un flot de lecture de lignes de texte UTF-8 sur le socket
		BufferedReader br = null;

		try
		{
			InputStream is = this.socket.getInputStream();
			InputStreamReader isr = new InputStreamReader(is);
			br = new BufferedReader(isr);
		}
		catch (IOException e)
		{
			this.end("<ChatServer> [" + this.getName() + "] problème d'IO, "
					+ "fermeture de la connexion");

			return;
		}

		// Diffusion d'un message d'alerte aux autres clients
		this.dispatcher.broadCastMessage("ChatServer", this.getName()
				+ " connecté");

		// Boucle réception/diffusion tant que la connexion reste établie
		while (true)
		{
			// Attente bloquante de la réception d'un message à diffuser
			String message = null;

			try
			{
				message = br.readLine();
				if (message == null)
					throw new IOException();
			}
			catch (IOException e)
			{
				this.dispatcher.broadCastMessage("ChatServer", this.getName()
						+ " déconnecté");
				this.end("<ChatServer> [" + this.getName() + "] "
						+ this.getName() + " déconnecté");

				return;
			}

			// Traitement du message
			try
			{
				this.processMessage(message);
			}
			catch (InformationAccessException e)
			{
				System.err.println("<ChatServer> [" + this.getName()
						+ "] accès aux informations utilisateurs "
						+ "impossible, le message spécial n'a pas été traité");
			}
		}
	}
}

⌨️ 快捷键说明

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