Serveur multi client très simple

Soyez le premier à donner votre avis sur cette source.

Vue 17 332 fois - Téléchargée 1 400 fois

Description

Voici encore une source de serveur ... Hééé oui mais j'espere qu'elle permettra de vous simplifier la vie. Ce serveur gére plusieurs clients, vous envoie un message quand un client se connecte ou se deconnecte. Jusque la rien de très compliqué en effet mais vous géré vos client a partir de cette classe. Je suis encore en train de travailler dessus c'est pour cela qu'il risque d'y avoir encore pas mal de bug, mais le code est, je l'espere assez simple, et facilement modifiable. Merci de me faire parvenir vos commentaire.

Source / Exemple :


using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;

namespace Net_Serveur
{
    public enum Platform
    {
        PocketPC, WindowsCE, Smartphone, Win32NT, Win32S, Win32Windows, Unknown
    }
    // classe avec les evenements a la reception de message
    // FireEventArgs: a custom event inherited from EventArgs.

    #region evenement liée au serveur
    public class EventClientReception : EventArgs
    {
        public EventClientReception(ServeurClient m_Objet)
        {
            Objet = m_Objet;
        }
        public ServeurClient Objet;
    }

    public class EventClientConnection : EventArgs
    {
        public EventClientConnection(ServeurClient m_Objet)
        {
            Objet = m_Objet;
        }
        public ServeurClient Objet;
    }

    public class EventClientDeconnection : EventArgs
    {
        public EventClientDeconnection(ServeurClient m_Objet)
        {
            Objet = m_Objet;
        }
        public ServeurClient Objet;
    }
    #endregion

    public class ServeurClient
    {
        #region declaration des evenements et des delegués
        // création de l'evenement sur le delegué de la classe serveur (evenement public)
        public event Serveur.Reception_Message ReceptionClient;
        public event Serveur.Déconnexion_Client DeconnectionClient;
        public event Serveur.Connexion_Client ConnectionClient;
        #endregion

        #region platform
        public static Platform GetPlatform()
        {
            Platform plat = Platform.Unknown;
            switch (System.Environment.OSVersion.Platform)
            {
                case PlatformID.Win32NT:
                    plat = Platform.Win32NT;
                    break;
                case PlatformID.Win32S:
                    plat = Platform.Win32S;
                    break;
                case PlatformID.Win32Windows:
                    plat = Platform.Win32Windows;
                    break;
                default:
                    plat = Platform.Unknown;
                    break;
            }

            return plat;
        }
        #endregion

        // constructeur
        public ServeurClient(Socket Socket_Client, ArrayList Pt_Clients, Serveur.Reception_Message pReceptionClient, Serveur.Déconnexion_Client pDeconnectionClient, Serveur.Connexion_Client pConnexionClient)
        {
            ListenSocket = Socket_Client;
            Clients = Pt_Clients;
            ReceptionClient = pReceptionClient;
            ConnectionClient = pConnexionClient;
            DeconnectionClient = pDeconnectionClient;

            H_Connection = DateTime.Now;

            AdresseIP = ((IPEndPoint)Socket_Client.LocalEndPoint).Address;
            port = ((IPEndPoint)Socket_Client.LocalEndPoint).Port;
            Nom_Client = ((IPEndPoint)Socket_Client.LocalEndPoint).Address.ToString();

            ListenSocket.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnReceiveQuery), ListenSocket);

            // fonction pour savoir si le client c deconnecté
            Thread th_Déconnection = new Thread(Perte_Connection);
            th_Déconnection.Start();

            // ajoute le client a la liste
            Clients.Add(this);

            if (ConnectionClient != null)
            {
                EventClientConnection ClientConnect = new EventClientConnection(this);
                ConnectionClient(this, ClientConnect);
            }

            Console.WriteLine("Client en ecoute");
        }

        #region Fonctions d'Envoi de message
        public void OnSendQuery(string Query)
        {
            byte[] buff = Encoding.ASCII.GetBytes(Query);
            //ListenSocket.BeginSend(buff, 0, buff.Length, 0,
            //                      new AsyncCallback(Send_Callback), ListenSocket);
            ListenSocket.Send(buff, 0, buff.Length, 0);
        }

        public void OnSendQuery(byte[] Query)
        {
            byte[] buff = Query;
            //ListenSocket.BeginSend(buff, 0, buff.Length, 0,
            //                      new AsyncCallback(Send_Callback), ListenSocket);
            ListenSocket.Send(buff, 0, buff.Length, 0);
        }

        private void Send_Callback(IAsyncResult ar)
        {
            try
            {
                int send = ListenSocket.EndSend(ar);
                //if (send > 0) { }
            }
            catch { }
        }
        #endregion

        #region Fonction de reception de message
        public void OnReceiveQuery(IAsyncResult ar)
        {
            int Ret;
            try
            {
                Ret = ListenSocket.EndReceive(ar);
            }
            catch
            {
                Ret = -1;
            }
            if (Ret <= 0)
            { //Connection is dead :(
                //Dispose();
                return;
            }
            Tampon = Encoding.ASCII.GetString(Buffer, 0, Ret);
            Console.WriteLine(Tampon);
            ListenSocket.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnReceiveQuery), ListenSocket);

            EventClientReception ClientArgs = new EventClientReception(this);
            ReceptionClient(this, ClientArgs);
            //Console.WriteLine("Reception de message + " + Tampon);
        }
        #endregion

        #region Fonctions de deconnection de client
        public bool Deconnect_Client()
        {

            //a revoir
            ListenSocket.Shutdown(SocketShutdown.Both);
            etat = false;
            try
            {
                ListenSocket.BeginDisconnect(true, new AsyncCallback(DisconnectCallback), ListenSocket);
                disconnectDone.WaitOne();
                if (ListenSocket.Connected)
                {
                    return false;
                }
                else
                    return true;
            }
            catch (NotSupportedException e) // erreur si c pas win XP ou ulterieur
            {
                Console.WriteLine(e.ToString());
                ListenSocket.Close();
                ListenSocket = null;
                return true;
            }

        }

        private static void DisconnectCallback(IAsyncResult ar)
        {
            // Complete the disconnect request.
            Socket client = (Socket)ar.AsyncState;
            client.EndDisconnect(ar);
            // Signal that the disconnect is complete.
            disconnectDone.Set();
        }
        #endregion

        #region Fonctions de verification de connection
        void Perte_Connection()
        {
            etat = true;
            while ((etat) && (ListenSocket != null))
            {
                try
                {
                    if (ListenSocket.Poll(1000, SelectMode.SelectRead) && ListenSocket.Available == 0)
                    {

                        H_Deconnection = DateTime.Now;
                        // suppression du client de la liste
                        Clients.Remove(this);
                        etat = false;

                        // envoi du message
                        EventClientDeconnection ClientArgs = new EventClientDeconnection(this);
                        DeconnectionClient(this, ClientArgs);
                    }
                }
                catch
                {
                    EventClientDeconnection ClientArgs = new EventClientDeconnection(this);
                    DeconnectionClient(this, ClientArgs);
                    // suppression du client de la liste
                    Clients.Remove(this);
                    etat = false;
                    H_Deconnection = DateTime.Now;
                }
            }
            Console.WriteLine("deconnecté");
        }
        #endregion

        #region Variables

        static AutoResetEvent disconnectDone = new AutoResetEvent(false);

        #region Socket
        protected Socket ListenSocket
        {
            get
            {
                return m_ListenSocket;
            }
            set
            {
                m_ListenSocket = value;
            }
        }
        #endregion
        #region buffer
        public byte[] Buffer
        {
            get
            {
                return m_Buffer;
            }
            set
            {
                m_Buffer = value;
            }
        }
        #endregion
        #region tampon
        public string Tampon
        {
            get
            {
                return m_Tampon;
            }
            set
            {
                m_Tampon = value;
            }
        }
        #endregion
        #region Nom client
        public string Nom_Client
        {
            get
            {
                return m_Nom;
            }
            set
            {
                m_Nom = value;
            }
        }
        #endregion
        #region adresse ip
        public IPAddress AdresseIP
        {
            get
            {
                return m_AdresseIP;
            }
            set
            {
                m_AdresseIP = value;
            }
        }
        #endregion
        #region port
        public int port
        {
            get
            {
                return m_port;
            }
            set
            {
                m_port = value;
            }
        }
        #endregion
        #region liste des clients
        private ArrayList Clients
        {
            get
            {
                return m_Clients;
            }
            set
            {
                m_Clients = value;
            }
        }
        #endregion
        #region heure deconnexion
        public DateTime HDeconnection
        {
            get
            {
                return H_Deconnection;
            }
            set
            {
                H_Deconnection = value;
            }
        }
        #endregion
        #region heure connexion
        public DateTime HConnection
        {
            get
            {
                return H_Connection;
            }
            set
            {
                H_Connection = value;
            }
        }
        #endregion
        #region ecart de connexion
        public TimeSpan HTempsConnection
        {

            get
            {
                return System.DateTime.Now.Subtract(H_Connection);
            }
        }
        #endregion
        private Socket m_ListenSocket;
        private byte[] m_Buffer = new byte[4096]; //0<->4095 = 4096
        private string m_Tampon;
        private string m_Nom;
        private IPAddress m_AdresseIP;
        private int m_port;
        private ArrayList m_Clients = new ArrayList();
        public bool etat;
        private DateTime H_Deconnection;
        private DateTime H_Connection;
        #endregion
    }

    public class Serveur
    {
        #region delegué et evenements
        // Création du delegué
        public delegate void Reception_Message(object sender, EventClientReception fe);
        // création de l'evenement sur le delegué
        public event Reception_Message ReceptionClient;

        // Création du delegué
        public delegate void Déconnexion_Client(object sender, EventClientDeconnection fe);
        // création de l'evenement sur le delegué
        public event Déconnexion_Client DeconnexionClient;

        // Création du delegué
        public delegate void Connexion_Client(object sender, EventClientConnection fe);
        // création de l'evenement sur le delegué
        public event Connexion_Client ConnexionClient;

        #endregion

        // constructeur
        public Serveur(IPAddress Address, int Port)
        {
            this.Port = Port;
            this.Address = Address;
        }

        #region Lancement du serveur
        public bool Lancement_Serveur()
        {
            try
            {
                ListenSocket = new Socket(Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                ListenSocket.Bind(new IPEndPoint(IPAddress.Any, Port));
                ListenSocket.Listen(100);
                ListenSocket.BeginAccept(new AsyncCallback(OnAccept), ListenSocket);
                return true;
            }
            catch (SocketException e)
            {
                MessageBox.Show(e.Message);
                return false;
            }
            //Console.WriteLine("Serveur en ecoute");
        }
        #endregion

        #region envoi au client
        public void OnSendQuery(int id, string Query)
        {
            ((ServeurClient)Clients[id]).OnSendQuery(Query);
        }
        public void OnSendQuery(int id, byte[] Query)
        {
            ((ServeurClient)Clients[id]).OnSendQuery(Query);
        }

        #endregion

        #region Fonction pour la deconnection du client
        public bool DéconnexionClient()
        {
            while (Client() > 0)
            {
                Client(0).Deconnect_Client();
                Clients.Remove(Client(0));
            }
            return true;
        }

        public bool DéconnexionClient(ServeurClient Pt_ServeurClient)
        {
            if (Pt_ServeurClient.etat)
            {
                Pt_ServeurClient.Deconnect_Client();
                Clients.Remove(Pt_ServeurClient);
            }
            return true;
        }

        public bool DéconnexionClient(int Numero_Client)
        {
            if (Client(Numero_Client).etat)
            {
                Client(0).Deconnect_Client();
                Clients.Remove(Client(0));
            }
            return true;
        }
        #endregion

        #region arret du serveur
        public bool Arret_Serveur()
        {

            while (Client() > 0)
            {
                Client(0).Deconnect_Client();
                Clients.Remove(Client(0));
            }

            ListenSocket.Close();
            return true;

        }
        #endregion

        #region Accepte les clients
        public void OnAccept(IAsyncResult ar)
        {
            //Console.WriteLine("Demande  Client");
            try
            {
                Socket NewSocket = ListenSocket.EndAccept(ar);
                if (NewSocket != null)
                {
                    ServeurClient NewClient = new ServeurClient(NewSocket, Clients, ReceptionClient, DeconnexionClient, ConnexionClient);

                    Console.WriteLine("Nouveau Client");
                }
            }
            catch { }
            try
            {
                //Restart Listening
                ListenSocket.BeginAccept(new AsyncCallback(OnAccept), ListenSocket);
            }
            catch
            {
                //Dispose();
                Console.WriteLine("erreur sur le lancement de l'ecoute asynschrone ");
            }
        }
        #endregion

        #region Variables
        public ServeurClient Client(int Id_Client)
        {
            if (Id_Client < Clients.Count)
                return (ServeurClient)Clients[Id_Client];
            else
                return null;
        }

        public int Client(Object Id_Client)
        {
            if (0 < Clients.Count)
            {

                return Clients.IndexOf(Id_Client);
            }
            else
                return (-1);
        }

        public int Client()
        {
            return Clients.Count;
        }

        public object[] Info_Client(int id_Client)
        {
            object[] info = new object[2];

            info[0] = ((ServeurClient)m_Clients[id_Client]).AdresseIP;
            info[1] = ((ServeurClient)m_Clients[id_Client]).port;
            return info;
        }

        private Socket ListenSocket
        {
            get
            {
                return m_ListenSocket;
            }
            set
            {
                m_ListenSocket = value;
            }
        }
        protected IPAddress Address
        {
            get
            {
                return m_Address;
            }
            set
            {
                if (value == null)
                    throw new ArgumentNullException();
                m_Address = value;
                //Restart();
            }
        }
        protected int Port
        {
            get
            {
                return m_Port;
            }
            set
            {
                if (value <= 0)
                    throw new ArgumentException();
                m_Port = value;
                // Restart();
            }
        }
        protected byte[] Buffer
        {
            get
            {
                return m_Buffer;
            }
        }

        public ArrayList Clients
        {
            get
            {
                return m_Clients;
            }
            set
            {
                m_Clients = value;
            }
        }

        private Socket m_ListenSocket;
        private IPAddress m_Address;
        private int m_Port;
        private byte[] m_Buffer = new byte[4096]; //0<->4095 = 4096
        private ArrayList m_Clients = new ArrayList();
        #endregion
    }
}

Conclusion :


Je n'ai pas trouve de source a peu près identique, j'espere que je n'ai pas travaillé pour rien et que cette source vous aidera.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
18
Date d'inscription
mercredi 13 août 2003
Statut
Membre
Dernière intervention
4 janvier 2007

Je suis désolé de ne pas avoir maintenu la source... Il faut que je mis remette sans vous garantir un résultat parfait. Je mets en ligne les corrections le plus rapidement possible.
Messages postés
1
Date d'inscription
dimanche 4 mai 2003
Statut
Membre
Dernière intervention
15 septembre 2009

Salut,

tout d'abord merci pour avoir fournie cette source qui semble être une bonne base d'implementation d'un serveur TCP.
j'ai le même soucis que Wartix, une erreur en utilisant ce source avec VS 2008.
Ce que je voie c'est que la création des événements de retour ne sont pas créées (d'ou le passage d'objets null). Un soucis sur la déclaration des delegate ou un truc comme ça mais je suis pas assez fort encore pour détecter ou ça merde.

Quelqu'un à une solution?
Messages postés
2
Date d'inscription
samedi 12 avril 2008
Statut
Membre
Dernière intervention
14 septembre 2008

Comment utilser delphi sous réseau local (LAN).
( partage de fichier et ansi de suite ...). Merci
Messages postés
36
Date d'inscription
dimanche 9 mars 2003
Statut
Membre
Dernière intervention
21 mai 2009

Merci l'ami, ca nous évite de réflechir !!
N'as tu pas une petite mise a jour ???
N'y a t'il pas un autre moyen que de pooler l'état de la connection pour etre averti ?

Et dans ta fonction : Arret_Serveur()
Je commencerais pas arreter l'écoute puis par fermer la connection de tous les clients et pas l'inverse. Tu peux avoir une acceptation de connexion entre les deux étapes. Enfin c'est un détail.
Messages postés
1
Date d'inscription
samedi 7 avril 2007
Statut
Membre
Dernière intervention
7 avril 2007

Pour moi la gestion d'event ne marche pas ! Pourrais tu me dire ce que je fais de mal ?
j'ai copié colé ton code et à la ligne 165 il se plein d'un objet null;

A la ligne 504 quand je regarde en mode pas à pas les 3 events passé au constructeur sont null ...

Merci de m'indiquer comment me tiré de là ;)

Bien à vous,
Fabian
Afficher les 8 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.