Soyez le premier à donner votre avis sur cette source.
Vue 34 759 fois - Téléchargée 3 862 fois
// SOURCES DU PROJET DE TEST DU SERVEUR using System; using System.Drawing; using System.Windows.Forms; using tcpConnections; namespace test { public class MainForm : System.Windows.Forms.Form { private System.Windows.Forms.Label label1; private System.Windows.Forms.Button button1; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.ListBox listBox2; private System.Windows.Forms.ListBox listBox1; // créer une nouvelle instance du serveur private tcpServeur serveur = new tcpServeur(); public MainForm() { InitializeComponent(); } [STAThread] public static void Main(string[] args) { Application.Run(new MainForm()); } #region Windows Forms Designer generated code /// <summary> /// This method is required for Windows Forms designer support. /// Do not change the method contents inside the source code editor. The Forms designer might /// not be able to load this method if it was changed manually. /// </summary> private void InitializeComponent() { this.listBox1 = new System.Windows.Forms.ListBox(); this.listBox2 = new System.Windows.Forms.ListBox(); this.textBox1 = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // listBox1 // this.listBox1.Location = new System.Drawing.Point(8, 40); this.listBox1.Name = "listBox1"; this.listBox1.Size = new System.Drawing.Size(368, 329); this.listBox1.TabIndex = 2; // // listBox2 // this.listBox2.Location = new System.Drawing.Point(384, 40); this.listBox2.Name = "listBox2"; this.listBox2.Size = new System.Drawing.Size(80, 329); this.listBox2.TabIndex = 5; // // textBox1 // this.textBox1.Enabled = false; this.textBox1.Location = new System.Drawing.Point(8, 376); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(376, 20); this.textBox1.TabIndex = 3; this.textBox1.Text = ""; // // button1 // this.button1.Enabled = false; this.button1.Location = new System.Drawing.Point(392, 376); this.button1.Name = "button1"; this.button1.TabIndex = 4; this.button1.Text = "envoyer"; this.button1.Click += new System.EventHandler(this.Button1Click); // // label1 // this.label1.Location = new System.Drawing.Point(8, 8); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(456, 24); this.label1.TabIndex = 0; // // MainForm // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(472, 405); this.Controls.Add(this.listBox2); this.Controls.Add(this.button1); this.Controls.Add(this.textBox1); this.Controls.Add(this.listBox1); this.Controls.Add(this.label1); this.Location = new System.Drawing.Point(10, 10); this.Name = "MainForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.Text = "serveur"; this.Closing += new System.ComponentModel.CancelEventHandler(this.MainFormClosing); this.Load += new System.EventHandler(this.MainFormLoad); this.ResumeLayout(false); } #endregion void MainFormLoad(object sender, System.EventArgs e) { // port d'ecoute du serveur serveur.Port = 11000; // timeout pour les déconnexions des clients serveur.Timeout = 10000; // evenement produit lorsque l'etat de la connexion du serveur change serveur.ConnectionStateEvent += new tcpConnections.ConnectionStateHandler(ConnectionState); // evenement produit lorsque l'etat des connexions clientes change serveur.ClientsConnectionStateEvent += new tcpConnections.ClientsConnectionStateHandler(ClientsConnectionState); // evenement produit lorsque le serveur recoit des données serveur.ClientDataAvailable += new tcpConnections.DataAvailable(ClientDataAvailable); // evenement produit lorsque le serveur envoi un PING? (pas forcement utile) serveur.ClientPingPong += new tcpConnections.PingPong(ClientPingPong); // démarage du serveur serveur.Start(); } void MainFormClosing(object sender, System.ComponentModel.CancelEventArgs e) { // arrete le serveur serveur.Stop(); } // evenement produit lorsque l'etat de la connexion du serveur change private void ConnectionState(object sender, tcpConnections.eConnectionSate state) { // object sender : instance de la classe en cours // tcpConnections.eConnectionSate : enumération de l'etat de la connexion du serveur label1.Text = "Status du serveur: "; switch (state) { // le serveur est déconnecté case tcpConnections.eConnectionSate.Disconnected : label1.Text += "déconnecté"; button1.Enabled = false; textBox1.Text = ""; textBox1.Enabled = false; break; // le serveur à un problème case tcpConnections.eConnectionSate.Error : label1.Text += "une erreur est survenue"; button1.Enabled = false; textBox1.Text = ""; textBox1.Enabled = false; break; // le serveur est en écoute (etat normal) case tcpConnections.eConnectionSate.Listening : label1.Text += "en écoute"; button1.Enabled = true; textBox1.Text = ""; textBox1.Enabled = true; break; } } // evenement produit lorsque l'etat des connexions clientes change private void ClientsConnectionState(object sender, int hashcode, tcpConnections.eClientsConnectionSate state) { // object sender : instance de la classe en cours // int hashcode : identifiant unique du socket client // tcpConnections.eClientsConnectionSate : enumération de l'etat de la connexion du client string message = "-- " + DateTime.Now.ToLongTimeString() + " - "; switch (state) { // un client viend de se connecter case tcpConnections.eClientsConnectionSate.Connected : message += "Bonjour, client " + hashcode.ToString() + " !"; listBox2.Items.Add(hashcode); break; // un client viend de se deconnecter case tcpConnections.eClientsConnectionSate.Disconnected : message += "Le client " + hashcode.ToString() + " nous dit aurevoir !"; listBox2.Items.Remove(hashcode); break; } listBox1.Items.Add(message); if (listBox2.Items.Count > 0) { listBox2.SelectedIndex = listBox2.Items.Count - 1; } } // evenement produit lorsque le serveur recoit des données private void ClientDataAvailable(object sender, int hashcode, int length, byte[] datas) { // object sender : instance de la classe en cours // int hashcode : identifiant unique du socket client // int length : taille des données recues // byte[] datas : données recues // les données recues sont sous forme d'un tableau d'octets pour pouvoir gérer des fichiers // pour savoir si une commande PONG! est recue (pour debuggage) on va tester si les 4 premiers octets correspondent au mot PONG string msgString = System.Text.ASCIIEncoding.ASCII.GetString(datas, 0, length); bool cmd = false; if (msgString.Length == 4) { switch (msgString.ToUpper()) { case "PONG" : listBox1.Items.Add(">> " + DateTime.Now.ToLongTimeString() + " - " + hashcode.ToString() + " Pong!"); listBox1.SelectedIndex = listBox1.Items.Count - 1; cmd = true; break; } } // sinon on affiche le message (pas de gestion de fichiers dans cet exemple) if (!cmd) { listBox1.Items.Add(">> " + DateTime.Now.ToLongTimeString() + " - Le client " + hashcode.ToString() + " a écrit : " + msgString); listBox1.SelectedIndex = listBox1.Items.Count - 1; } } // evenement produit lorsque le serveur envoi un PING? (pas forcement utile) private void ClientPingPong(object sender, int hashcode) { // object sender : instance de la classe en cours // int hashcode : identifiant unique du socket client listBox1.Items.Add("<< " + DateTime.Now.ToLongTimeString() + " - Ping? " + hashcode.ToString()); listBox1.SelectedIndex = listBox1.Items.Count - 1; } void Button1Click(object sender, System.EventArgs e) { // sides clients sont connectés if (listBox2.SelectedItem != null) { // on récupere le hashcode du client cible int index = (int) listBox2.Items[listBox2.SelectedIndex]; // on transforme notre message en un tableau d'octets byte[] msgByte = System.Text.ASCIIEncoding.ASCII.GetBytes(textBox1.Text); // et on l'envoi serveur.SendData(index, msgByte); textBox1.Clear(); } } } } // SOURCES DU PROJET DE TEST DU CLIENT using System; using System.Drawing; using System.Windows.Forms; using tcpConnections; namespace test { public class MainForm : System.Windows.Forms.Form { private System.Windows.Forms.Button button3; private System.Windows.Forms.Button button2; private System.Windows.Forms.Button button1; private System.Windows.Forms.ListBox listBox1; private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.TextBox textBox2; private System.Windows.Forms.CheckBox checkBox1; // nouvelle instance du client private tcpClient client = new tcpClient(); // flag pour la gestion de la reconnexion automatique private bool autorecon = false; public MainForm() { InitializeComponent(); } [STAThread] public static void Main(string[] args) { Application.Run(new MainForm()); } #region Windows Forms Designer generated code /// <summary> /// This method is required for Windows Forms designer support. /// Do not change the method contents inside the source code editor. The Forms designer might /// not be able to load this method if it was changed manually. /// </summary> private void InitializeComponent() { this.checkBox1 = new System.Windows.Forms.CheckBox(); this.textBox2 = new System.Windows.Forms.TextBox(); this.textBox1 = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.listBox1 = new System.Windows.Forms.ListBox(); this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.button3 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // checkBox1 // this.checkBox1.Location = new System.Drawing.Point(136, 32); this.checkBox1.Name = "checkBox1"; this.checkBox1.Size = new System.Drawing.Size(120, 24); this.checkBox1.TabIndex = 7; this.checkBox1.Text = "auto reconnexion"; this.checkBox1.CheckedChanged += new System.EventHandler(this.CheckBox1CheckedChanged); // // textBox2 // this.textBox2.Enabled = false; this.textBox2.Location = new System.Drawing.Point(8, 272); this.textBox2.Name = "textBox2"; this.textBox2.Size = new System.Drawing.Size(344, 20); this.textBox2.TabIndex = 4; this.textBox2.Text = ""; // // textBox1 // this.textBox1.Location = new System.Drawing.Point(8, 32); this.textBox1.Name = "textBox1"; this.textBox1.TabIndex = 0; this.textBox1.Text = "192.168.0.2"; this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // label1 // this.label1.Location = new System.Drawing.Point(8, 8); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(424, 23); this.label1.TabIndex = 6; // // listBox1 // this.listBox1.Location = new System.Drawing.Point(8, 64); this.listBox1.Name = "listBox1"; this.listBox1.Size = new System.Drawing.Size(424, 199); this.listBox1.TabIndex = 3; // // button1 // this.button1.Location = new System.Drawing.Point(360, 32); this.button1.Name = "button1"; this.button1.TabIndex = 1; this.button1.Text = "connecter"; this.button1.Click += new System.EventHandler(this.Button1Click); // // button2 // this.button2.Enabled = false; this.button2.Location = new System.Drawing.Point(272, 32); this.button2.Name = "button2"; this.button2.TabIndex = 2; this.button2.Text = "deconnecter"; this.button2.Click += new System.EventHandler(this.Button2Click); // // button3 // this.button3.Enabled = false; this.button3.Location = new System.Drawing.Point(360, 272); this.button3.Name = "button3"; this.button3.TabIndex = 5; this.button3.Text = "envoyer"; this.button3.Click += new System.EventHandler(this.Button3Click); // // MainForm // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(440, 301); this.Controls.Add(this.checkBox1); this.Controls.Add(this.button3); this.Controls.Add(this.textBox2); this.Controls.Add(this.listBox1); this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Controls.Add(this.textBox1); this.Controls.Add(this.label1); this.Name = "MainForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "client"; this.Closing += new System.ComponentModel.CancelEventHandler(this.MainFormClosing); this.Load += new System.EventHandler(this.MainFormLoad); this.ResumeLayout(false); } #endregion void MainFormLoad(object sender, System.EventArgs e) { // port par lequel le client va se connecter au serveur client.Port = 11000; // adresse IP du serveur. // ATTENTION: les serveur récupère tout seul l'adresse ip locale. // elle n'est pas forcement 127.0.0.1 !!!!! dans le cas d'un reseau local // l'ip locale est l'ip fourni soit par windows dans le cas d'une ip statique // soit l'ip fourni pas le serveur DHCP (machine spécialisée, routeur, etc.) client.Ip = textBox1.Text; // evenement produit lorsque la connexion du client change client.ConnectionStateEvent += new tcpConnections.ConnectionStateHandler(ConnectionState); // evenement produit lorsque des données sont recues client.ClientDataAvailable += new tcpConnections.DataAvailable(ClientDataAvailable); } // evenement produit lorsque la connexion du client change private void ConnectionState(object sender, tcpConnections.eConnectionSate state) { // object sender : instance de la classe en cours // tcpConnections.eConnectionSate state : énumeration de l'etat de la connexion label1.Text = "Status du serveur: "; switch (state) { // le client est déconnecté case tcpConnections.eConnectionSate.Disconnected : label1.Text += "déconnecté"; button1.Enabled = true; button2.Enabled = false; button3.Enabled = false; textBox2.Text = ""; textBox2.Enabled = false; listBox1.Items.Add("-- " + DateTime.Now.ToLongTimeString() + " - déconnecté !"); listBox1.SelectedIndex = listBox1.Items.Count - 1; // si l'auto reconnexion est activée if (autorecon == true) { // alors on attend 10 secondes System.Threading.Thread.Sleep(10000); // et on relance la connexion Button1Click(null, null); } break; // le client percoit une erreur dans la connexion case tcpConnections.eConnectionSate.Error : label1.Text += "une erreur est survenue"; button1.Enabled = true; button2.Enabled = false; button3.Enabled = false; textBox2.Text = ""; textBox2.Enabled = false; listBox1.Items.Add("-- " + DateTime.Now.ToLongTimeString() + " - une erreur est survenue !"); listBox1.SelectedIndex = listBox1.Items.Count - 1; // si l'auto reconnexion est activée if (autorecon == true) { // alors on attend 10 secondes System.Threading.Thread.Sleep(10000); // et on relance la connexion Button1Click(null, null); } break; // le client est connecté, tous va bien case tcpConnections.eConnectionSate.Connected : label1.Text += "connecté"; button1.Enabled = false; button2.Enabled = true; button3.Enabled = true; textBox2.Text = ""; textBox2.Enabled = true; listBox1.Items.Add("-- " + DateTime.Now.ToLongTimeString() + " - connecté au serveur."); listBox1.SelectedIndex = listBox1.Items.Count - 1; break; } } void Button1Click(object sender, System.EventArgs e) { listBox1.Items.Add("-- " + DateTime.Now.ToLongTimeString() + " - Tentative de connexion au serveur ..."); listBox1.SelectedIndex = listBox1.Items.Count - 1; // changement du flag d'auto reconnexion suivant le choix de l'utilisateur autorecon = checkBox1.Checked; // on connecte le client client.Start(); } void Button2Click(object sender, System.EventArgs e) { // pour eviter qu'apres une deco manuelle, le script relance la connexion autorecon = false; // on arrete le client client.Stop(); } void Button3Click(object sender, System.EventArgs e) { // on transforme le texte en tableau d'octets byte[] datas = System.Text.ASCIIEncoding.ASCII.GetBytes(textBox2.Text); // et on l'envoi au serveur client.SendData(datas); textBox2.Clear(); } // evenement produit lorsque des données sont recues private void ClientDataAvailable(object sender, int length, byte[] datas) { // object sender : instance de la classe en cours // int length : taille des données recues // byte[] datas : données recues // on transforme les données recue en chaine de caractères string msgString = System.Text.ASCIIEncoding.ASCII.GetString(datas, 0, length); // et on l'affiche listBox1.Items.Add(">> " + DateTime.Now.ToLongTimeString() + " - " + msgString); listBox1.SelectedIndex = listBox1.Items.Count - 1; } void MainFormClosing(object sender, System.ComponentModel.CancelEventArgs e) { // a la fermeture du formulaire, ne jamais oublier de couper le client ! // et oui, a cause du multuthreading, si on ne lui dit pas de fermer la connexion // celle ci restera indefiniment jusqu'a plantage // pour eviter qu'apres une deco manuelle, le script relance la connexion autorecon = false; // on arrete le client client.Stop(); } void CheckBox1CheckedChanged(object sender, System.EventArgs e) { // on change le flag d'auto reconnexion au choix de l'utilisateur autorecon = checkBox1.Checked; } } }
11 août 2005 à 17:22
faut avouer aussi que c la plus long page de codes-sources lol,bonne continuation.
10 nov. 2005 à 11:02
Connais tu ce problème ? As tu une solution ?
Sinon je vais regarder de mon coté ...
12 nov. 2005 à 21:14
Pour ceux que ca interessent, sur ce code il y a un petit bug qui surcharge le serveur.
Dans la classe Server, et la méthode ReceiveData le Thread.Sleep(10) est placé une } trop basse, remontez le et ca ira mieux pour votre processeur.
A+
14 nov. 2005 à 17:40
29 nov. 2007 à 16:36
- je confirme évidemment la remarque de MR_LAPINOU concernant l'emplacement du Thread.Sleep
- la modification du 31 juillet 2005 17:30:07 n'est pas intégrée dans les sources téléchargeables
- le thread de lecture de données qui fait tourner la méthode ReceiveData pose problème lorsqu'une donnée de taille importante est envoyée sur par un client TCP (image, fichier, etc.) : tant qu'il reste des données à lire, le thread continue de lire sur la même socket client sans même essayer de lire les autres ; il y a risque de perte de données si le tampon d'entrée se remplit pendant ce temps pour les autres sockets...
- cette-même méthode ReceiveData ne possède pas de mécanisme pour rattrapper les exceptions (la méthode jumelle présente dans le client TCP le fait)
- les verrous de lecture et d'écriture auraient tout intérêt à ne pas être globaux au serveur mais spécifiques à chacun des clients : les déconnexions de certains clients risquent de ne pas pouvoir être vues (car pas testées) si l'activité du serveur est importante
- le ping/pong implémenté étant spécifique à ce client/serveur (le "vrai" ping/pong correspond à deux messages ICMP), il devrait pouvoir être désactivé pour que le serveur puisse être utilisé avec un client TCP dont on ne maitrise pas le code (tiers, externe, fermé, etc.). Par exemple, une valeur de 0 en timeout peut indiquer qu'on ne lance pas le thread qui effectue ces pings/pongs
- en tout état de cause, ce serveur TCP est une base qui peut servir dans des cas où la communication est légère : peu de données, peu de clients ; un pool de threads serait bien meilleur si de nombreux clients doivent se connecter, pour éviter trop de latence.
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.