mecano14
Messages postés35Date d'inscriptionsamedi 26 février 2005StatutMembreDernière intervention12 août 2006
-
29 juil. 2006 à 14:06
xankow
Messages postés10Date d'inscriptionmardi 17 juin 2008StatutMembreDernière intervention 8 juillet 2008
-
19 juin 2008 à 16:19
Bonjour,
Je travaille en ce moment sur un petit programme de chat
Je recontre un problème pour la connection de plusieurs clients
Lorsqu'un seul client se connecte ca fonctionne bien mais lorsqu'un deuxieme essai, ses messages ne sont pas pris en compte.
Je me pose la question suivante:
Est ce que je dois instancier un TcpListener pour chaque client du coté serveur ou un seul suffit pour tous?
Voici ce que je fais du coté serveur
Lorsqu'il demarre
IPEndPoint ipServerEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
// initialisation de la socket d'ecoute
socket_ecoute = new TcpListener(ipServerEndPoint);
// Mise en marche de la socket
socket_ecoute.Start();
// Creation d'une thread au chargement associé a la fontion Ecoute()
th = new Thread(new ThreadStart(Ecoute));
th.Start() ;
Console.WriteLine("Chat demarré et sur ecoute");
public void Ecoute()
{
MySocket = socket_ecoute.AcceptSocket();
//attente de donnée arrivant du Client avec une boucle infinie
while(stop)
{
// on met les bytes recuperé dans le tableau
// Creation d'un tableu de byte pour contenir les donnés reçu
Byte[] buffer = new Byte[1024];
MySocket.Receive(buffer);
//On traduit les Bytes en caractère ASCII lisible
string data = Encoding.ASCII.GetString(buffer).TrimEnd('\0');
// On envoi le texte aux clients
if (data != "")
{
Console.WriteLine(data);
MorpionMx
Messages postés3466Date d'inscriptionlundi 16 octobre 2000StatutMembreDernière intervention30 octobre 200857 29 juil. 2006 à 15:30
Salut
C'est normal. La facon dont tu as structuré le serveur te permet d'accepter qu'un seul client
En fait tu n'as besoin de qu'un TCPListener.
Cependant, il faut boucler sur le AcceptSocket();
Quand un Client se connecte, AcceptSocket te retourne un socket, qui te permet de connecter avec le client. Il faut que tu stockes ce Socket (tableau, List<Socket>, ou autre).
Mais il faut ensuite que tu rappelles AcceptSocket(); pour tous les clients qui se connecteront par la suite.
Donc en gros, il te faut un Thread d'ecoute de connexion des clients et qui ne fait que ca, en boucle, et un autre thread (ou plusieurs) qui te permettent la communication avec ces clients
Petite fonction d'exemple dans un de mes codes
J'avais une Classe Client qui me permettait de stocker toutes les infos sur eux (Socket, identifiants, ...)
Je stockait chaque client dans une List<Client>
Cette fontion etait appelée dans un Thread de la meme facon que toi tu le fais dans ton code.
<hr />
private
void ListenToClients()
{
Console.WriteLine(
"En attente de clients...");
while (listen)
{
// La méthode AcceptSocket est bloquante, donc tant qu'il n'y a pas de connexion
// l'execution de la méthode s'arrete a cette ligne
Socket socket =
this.tcpListener.AcceptSocket();
Console.WriteLine(
string.Format(
"Connexion du client {0}",
this.idClient));
lock (
this.clientsList)
{
// On cree un nouveau client
Client client =
new
Client(socket, idClient++);
// On l'ajoute a notre liste de clients
this.clientsList.Add(client);
}
}
}
<hr />
mecano14
Messages postés35Date d'inscriptionsamedi 26 février 2005StatutMembreDernière intervention12 août 2006 29 juil. 2006 à 20:30
Je reposte ma nouvelle fonction Ecoute()
public void Ecoute()
{
//ajout du nouveau socket dans la liste
this.ListSocket.Add(socket_ecoute.AcceptSocket());
//creation d'un socket temporaire pour les traitements
Socket MySocket = (Socket)this.ListSocket[this.ListSocket.Count-1];
while(stop)
{
Console.WriteLine("Ecoute()");
Byte[] buffer = new Byte[1024];
MySocket.Receive(buffer);
string data = Encoding.ASCII.GetString(buffer).TrimEnd('\0');
// On envoi le texte aux clients
if (data != "")
{
Console.WriteLine(data);
for (int i = 0; i < this.socketJoueurs.Count; i++)
{
EnvoieAuClient((Socket)this.ListSocket[i], data);
}
}
}
}
MorpionMx
Messages postés3466Date d'inscriptionlundi 16 octobre 2000StatutMembreDernière intervention30 octobre 200857 29 juil. 2006 à 20:49
Sépare l'acceptation des clients (là ou se trouve ton AcceptSocket()), et la communication avec eux.
2 méthodes, qui tournent dans 2 threads différents.
Relis mon premier message.
Fais, comme je t'ai montré. Une méthode qui accepte les clients, fais-en ta méthode Ecoute(), fais la tourner dans un thread.
Fais une autre méthode, qui fait tes socket.Receive(), etc. Et fais la tourner dans un autre Thread.
Sinon, je pourrais aussi te parler de l'ecoute asynchrone, la reception asynchrone, et l'envoi asynchrone, mais j'ai pas envie de t'embrouiller plus... ^^
mecano14
Messages postés35Date d'inscriptionsamedi 26 février 2005StatutMembreDernière intervention12 août 2006 29 juil. 2006 à 21:11
Snif j'ai vraiment du mal aujourd'hui :D
J'ai donc fait mes deux Thread, un pour la connection des nouveaux clients
public void connecte() {
this.socketJoueurs.Add(socket_ecoute.AcceptSocket());
}
Et un autre chargé de la reception et de l'emission des messages clients
for (int i = 0; i < this.socketJoueurs.Count; i++) {
//reception du message d'un client
Byte[] buffer = new Byte[1024];
Socket MySocket = (Socket)this.socketJoueurs[i];
MySocket.Receive(buffer);
string data = Encoding.ASCII.GetString(buffer).TrimEnd('\0');
//diffusion du message vers tous les clients
if (data != "")
{
Console.WriteLine(data);
for (int j = 0; j < this.socketJoueurs.Count; j++)
{
EnvoieAuClient((Socket)this.socketJoueurs[i], data);
}
MorpionMx
Messages postés3466Date d'inscriptionlundi 16 octobre 2000StatutMembreDernière intervention30 octobre 200857 29 juil. 2006 à 21:18
Il faut que tu boucles avec un while() dans ta méthode connecte..
Sinon, tu n'auras qu'un seul client qui va se connecter....
Voila commence ca se passe :
- Tu lance ton Thread qui appele la méthode connecte()
- Ta fonction se bloque sur AcceptSocket().
- Un client se connecte, le socket est ajouté a ta liste.
Et ensuite ? telle qu'elle est, ta méthode connecte (et donc ton thread) va se terminer.
Entoure ton AcceptSocket avec un while. De cette facon, dès qu'un client est connecté, son socket stocké, hop, il repart sur AcceptSocket, et est pres pour la connexion d'un nouveau client (et comme le socket du client precedent est stocké dans ta liste, il n'est pas perdu, ni remplacé par le nouveau).
mecano14
Messages postés35Date d'inscriptionsamedi 26 février 2005StatutMembreDernière intervention12 août 2006 29 juil. 2006 à 21:27
Donc j'ai une evolution
Mon deuxième client arrive enfin à envoyer des messages
Je vois bien dans ma console serveur ce que raconte mon deuxieme client
Par contre mes envois ne fonctionnent pas encore.
Je vais chercher encore un peu, je devrai trouver ce qui ne colle pas.
mecano14
Messages postés35Date d'inscriptionsamedi 26 février 2005StatutMembreDernière intervention12 août 2006 31 juil. 2006 à 16:43
J'aurai deux questions
Dois-je créer un Thread() pour ecouter chaque client ou est-il possible de faire tourner un seul Thread() qui prendrait en charge toutes les ecoutes clients.
J'ai remarqué que lorsque je faisais tourner deux clients sur la même machine ca marchait très mal (les messages s'envoient par alternance : concurrence?) alors que sur deux machines differente ca se passe bien. Je n'arrive pas à m'expliquer ce comportement.
Captain_Bomber
Messages postés36Date d'inscriptionlundi 4 septembre 2006StatutMembreDernière intervention 4 mai 2007 21 déc. 2006 à 09:26
Salut!!
Je suis également en train de faire un chat client-serveur, mais en Windows Application et non en console (pas d'énormes changements) et j'ai eut à peu près les mêmes problèmes que toi.
Maintenant, mon serveur accepte tous les clients qui se connectent,
tous les clients peuvent recevoir les messages du serveur,
mais le serveur ne reçoit que les messsges du 1er client connecté.
Pourtant, ma fonction d'écoute (sur le serveur) est dans un Thread et utilise la fonction foreach() pour récupérre le flux de chaque clients stockés dans un ArrayList[].
PS: mes clients sont des objets constitués d'un nom, d'un TCPClient, et d'un NetworkStream;
xankow
Messages postés10Date d'inscriptionmardi 17 juin 2008StatutMembreDernière intervention 8 juillet 2008 19 juin 2008 à 16:19
Salut,
je suis en train de faire un serveur avec plusieurs clients.
je developpe un serveur en console qui voit bien tous ces clients et recoit des message de chacun.
MAIS il ne peut pas ecrire a un en particulier, tous les client recoivent le meme message. C'est tres genant dans mon application.
Si quelqu'un a du code qui fonctionne un peu, je suis prenneur.