Multi Threading en utilisant TCP

Signaler
Messages postés
3
Date d'inscription
mercredi 8 septembre 2004
Statut
Membre
Dernière intervention
15 septembre 2004
-
Messages postés
6
Date d'inscription
vendredi 22 novembre 2002
Statut
Membre
Dernière intervention
22 janvier 2006
-
Bonjour,
je suis entrain d'écrire un programme (client et serveur).
Le serveur fonctionne comme ceci:
1. Le serveur écoute sur un port fixé.
2. Lorsqu'un client se connecte, il lance un thread qui va lire les données du client et les écrire sur une fenêtre dos.

Le client:
1. Le client se connecte sur un port défini par le serveur.
2. Lorsque le client est connecté, il envoie des données.

Pour que je puisse gérer la connection de plusieurs clients à la fois, chaque fois qu'un client se connecte, une socket est crée. J'ai donc un tableau de socket (fonction comme une pile). Lorsqu'un client se déconnecte, la socket se ferme et peu être réutilisée.

J'ai le problème suivant du côté serveur:

Lorsqu'une socket a été fermée par close (ou Stop avec TcpListener), elle ne peut pas être réouverte (Cannot access a disposed object...) Si je ne ferme pas la socket (Close()), je peux la réutiliser mais elle n'est plus utilisable (socket.available() = false). Pourriez-vous me donner une solution pour que je puisse réinitialiser une socket ou détruire un objet afin de le recréer.

En résumé:

Une fois qu'une socket tcplistener a été fermée, elle ne peut plus être lancée à nouveau en utilisant Start().

Voici mon code du côté serveur:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net.Sockets;
using System.Text;
using System.IO ;
using System.Net ;
using System.Threading ;

namespace ServerNS
{
public class ServerC
{

private int port = 2564; (fixe)
private bool stop = true;
private TcpListener socketListen;
private Thread threadServer;
private int numberSocket = 0;
private Socket[] socketListenerList = new Socket[100];

public void ServerM()
{
// Creation d'une thread au chargement associer a la fontion Ecoute()
threadServer = new Thread(new ThreadStart(Listen));
threadServer.Start() ;
Console.WriteLine("thread started");
}

public void Listen()
{
try
{
// initialisation de la socket d'ecoute
socketListen = new TcpListener(port);
socketListen.Start();
Console.WriteLine("Wait data");
// On accepte un client si celui ce presente a l'aide d'une autre socket
// clientSocket est donc associer au client

while(true){
// Block until a client is connected
socketListenerList[numberSocket] = socketListen.AcceptSocket();
Console.WriteLine("Socket Accepted");

Thread receiveThread;

// Call the thread receiveData when a remote socket is connected

receiveThread = new Thread(new ThreadStart(receiveData));
receiveThread.Start();

//Mettre en suspend le thread principal
threadServer.Suspend();
// Socket crée, incrémente ID
numberSocket++;
}
}
catch(Exception e)
{
Console.WriteLine("{0}",e);
stop = false;
socketListen.Stop();
socketListenerList[0].Close();
}
}

public void receiveData()
{
int SID = numberSocket;
Console.WriteLine("ID: {0}",SID);
// Resume le thread principal
threadServer.Resume();

// socket bloquant socketListenerList[SID].Blocking = true;
//attente de donnée arrivant du Client avec une boucle infinie
// Creation d'un tableau de byte pour contenir les donnés reçu
Byte[] buffer = new Byte[1024];

Console.WriteLine("available ?");

// Regarde si des données sont en attente
while(socketListenerList[SID].Available == 0);
Console.WriteLine("Yes");

// on met les bytes recuperé dans le tableau
socketListenerList[SID].Receive(buffer);

//On traduit les Bytes en caractère ASCII lisible
string data = Encoding.ASCII.GetString(buffer);

int length = buffer.Length;

for( int i = 0 ; i < length ; i++){
Console.Write(data[i]);
// Ecrit données sur stdout
if(buffer[i] == 0){
break;
}
}

//socketListenerList[SID].Shutdown(SocketShutdown.Both);
// Faut-il fermer la socket ?
socketListenerList[SID].Close();
// Socket fermée donc décrément ID
numberSocket--;
}

[STAThread]
static void Main()
{
ServerC serv = new ServerC();
serv.ServerM();
}

}
}

1 réponse

Messages postés
6
Date d'inscription
vendredi 22 novembre 2002
Statut
Membre
Dernière intervention
22 janvier 2006

Problème de synchronisation de threads, si tu déplace ton Resume à la fin de receivedata, tu as plus le problème. De plus :

receiveThread.Start();

//Mettre en suspend le thread principal

threadServer.Suspend();

public void receiveData()
{
int SID = numberSocket;
Console.WriteLine("ID: {0}",SID);
// Resume le thread principal
threadServer.Resume();

Comment etre sur que tu fait bien le suspend avant le resume ?