using System; using System.IO; using System.Threading; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Collections; using System.Configuration; namespace Document_Server { class Server { // Settings reader AppSettingsReader ConfigReader = new AppSettingsReader(); // Déclaration des variables ArrayList acceptList = new ArrayList(); //liste utilisée par socket.select ArrayList readList = new ArrayList(); //contiendra le message envoyé aux autres clients string msgString=null; //Message sous forme de bytes pour socket.send et socket.receive byte[] msg; //booleen permettant de logger le processing dans un fichier log public bool useLogging=false; //Flag aidant à la synchronisation public bool readLock=false; // Port value int port = int.MinValue; // Lancement du serveur TCP public void ServerStart() { // On lit sur le port port = (int)ConfigReader.GetValue("port", port.GetType()); //réception de l'adresse IP locale IPHostEntry ipHostEntry = Dns.GetHostEntry(Dns.GetHostName()); // Adresse IP IPAddress ipAddress = ipHostEntry.AddressList[0]; // p'ti message sympathique Console.WriteLine("IP="+ipAddress.ToString()); // flush Socket CurrentClient=null; //Création de la socket Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { //On lie la socket au point de communication ServerSocket.Bind(new IPEndPoint(ipAddress, port)); //On la positionne en mode "écoute" ServerSocket.Listen(10); //Démarrage du thread avant la première connexion client Thread getReadClients = new Thread(new ThreadStart(getRead)); getReadClients.Start(); //Démarrage du thread vérifiant l'état des connexions clientes Thread pingPongThread = new Thread(new ThreadStart(CheckIfStillConnected)); pingPongThread.Start(); //Boucle infinie while (true) { Console.WriteLine("Attente d'une nouvelle connexion..."); //L'exécution du thread courant est bloquée jusqu'à ce qu'un //nouveau client se connecte CurrentClient = ServerSocket.Accept(); Console.WriteLine("Nouveau client:" + CurrentClient.GetHashCode()); //Stockage de la ressource dans l'arraylist acceptlist acceptList.Add(CurrentClient); } } catch(SocketException e) { Console.WriteLine("Probème lors de la creation du serveur tcp " + e); if (useLogging) { Logging("Probème lors de la creation du serveur tcp"); } } } //Méthode permettant de générer du logging //dans un fichier log selon que le membre useLogging //soit à true ou false private void Logging(string message) { using (StreamWriter sw = File.AppendText("Server.log")) { sw.WriteLine(DateTime.Now + ": " + message); } } //Cette méthode est exécutée dans un thread à part //Elle lit en permanence l'état des sockets connectées et //vérifie si celles-ci tentent d'envoyer quelque chose //au serveur. Si tel est le cas, elle réceptionne les paquets //et appelle DictionnaryExplorer pour executer des instructions //les autres clients. private void getRead() { try { while (true) { // Vide la table des sockets readList.Clear(); for (int i = 0; i < acceptList.Count; i++) { readList.Add((Socket)acceptList[i]); } if (readList.Count > 0) { // Ont prend un socket Socket.Select(readList, null, null, 1000); for (int i = 0; i < readList.Count; i++) { if (((Socket)readList[i]).Available > 0) { readLock = true; while (((Socket)readList[i]).Available > 0) { // Récupération des données msg = new byte[((Socket)readList[i]).Available]; ((Socket)readList[i]).Receive(msg, msg.Length, SocketFlags.None); // voila le jolie flux xml :) msgString = System.Text.Encoding.UTF8.GetString(msg); if (useLogging) { Logging("Connexion : ok" + msgString); } // Attibution des données pour le traitement ThreadHandle threadHandle = new ThreadHandle(msgString, (Socket)readList[i]); // Lancement d'un nouveau thread Thread DictionnaryThread = new Thread(new ThreadStart(threadHandle.ThreadLoop)); DictionnaryThread.Start(); } readLock = false; } } } // dodo l'enfant do l'enfant dormira bientot Thread.Sleep(10); } } catch (ThreadAbortException e) { Console.WriteLine("Thread Abort " + e); } catch (ThreadInterruptedException e) { Console.WriteLine("Thread interrupt " + e); } catch (ThreadStartException e) { Console.WriteLine("Thread start " + e); } catch (ObjectDisposedException e) { Console.WriteLine("Disposed exception at getread()"); if (useLogging) { Logging("Disposed: " + e); } } catch (Exception e) { Console.WriteLine("Generic exeption " + e); } } // Supprime du tableau les sockets mort !!! private void CheckIfStillConnected() { try { while (true) { for (int i = 0; i < acceptList.Count; i++) { if (((Socket)acceptList[i]).Poll(10, SelectMode.SelectRead) && ((Socket)acceptList[i]).Available == 0) { if (!readLock) { Console.WriteLine("Client " + ((Socket)acceptList[i]).GetHashCode() + " déconnecté"); ((Socket)acceptList[i]).Close(); acceptList.Remove(((Socket)acceptList[i])); i--; } } } Thread.Sleep(5); } } catch (ThreadAbortException e) { Console.WriteLine("Thread Abort " + e); } catch (ThreadInterruptedException e) { Console.WriteLine("Thread interrupt " + e); } catch (ThreadStartException e) { Console.WriteLine("Thread start " + e); } catch (ObjectDisposedException e) { Console.WriteLine("Disposed exception"); if (useLogging) { Logging("Disposed: " + e); } } catch (Exception e) { Console.WriteLine("Generic exeption " + e); } } } }