2016-03-15 1 views
0

J'ai un programme de conversation serveur TCP/client utilisant C#. Le serveur qui reçoit les messages du client et les envoie à nouveau à la cible.Problème de multi-threading dans l'application de conversation client/serveur C#

Lorsque le client se connecte au serveur, le serveur crée un nouveau thread pour lui.

Mon problème est que le serveur doit recevoir un seul message du client ne reçoit aucun nouveau message de lui. Lorsque je fais le débogage, j'ai remarqué que le serveur reçoit le message et se bloque dans le thread client, mais ne fonctionne pas à nouveau.

Le code du serveur:

namespace server 
{ 
public partial class Form1 : Form 
{ 
    private ArrayList alSockets; 
    private delegate void UpdateLogCallback(string strMessage); 


    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 

     IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName()); 
     textBox1.Text = "my ip is " + IPHost.AddressList[0].ToString(); 
     alSockets = new ArrayList(); 
     Thread thdListener = new Thread(new ThreadStart(listenerThread)); 
     thdListener.Name = "thdListener"; 

     thdListener.Start(); 

    } 
    public void listenerThread() 
    { 
     TcpListener tcpc = new TcpListener(IPAddress.Any,6666); 
     tcpc.Start(); 

     while (true) 
     { 
      Socket HndSoc = tcpc.AcceptSocket(); 
      if (HndSoc.Connected) 
      { 
       string str2 = "\n" + HndSoc.RemoteEndPoint.ToString() + " connected"; 
       this.Invoke(new UpdateLogCallback(this.update2),new object[] {str2}); 

       lock (this) 
       { 
        alSockets.Add(HndSoc); 

       } 
       ThreadStart thdstHandler = new ThreadStart(handlerThread); 
       Thread thdHandler = new Thread(thdstHandler); 
       thdHandler.Name = "thdHandler"; 
       thdHandler.Start(); 

      } 
      else if(!HndSoc.Connected) 
      { 
       string str2 = "\n" + HndSoc.RemoteEndPoint.ToString() + " desconnected"; 
       this.Invoke(new UpdateLogCallback(this.update2), new object[] { str2 }); 

      } 

      } 
     } 
    public void handlerThread() 
    { 
     byte [] rx = new byte [1024]; 
     Socket hanso = (Socket) alSockets[alSockets.Count-1]; 
     NetworkStream ns = new NetworkStream(hanso); 
     // NetworkStream ns = hanso. 
     ns.Read(rx,0,rx.Length); 
    //  textBox1.Text = "\n"; 
    // textBox1.Text = Encoding.ASCII.GetString(rx); 
     string str = Encoding.ASCII.GetString(rx); 
     // update(str); 
     this.Invoke(new UpdateLogCallback(this.update), new object[] { str }); 
     // ns.Close(); 
     // hanso = null; 
     rx = new byte[1024]; 
     ns.Read(rx, 0, rx.Length); 

    } 

Et ce code est client si nécessaire:

namespace simple_clint 
{ 
public partial class Form1 : Form 
{ 
    byte[] tx = new byte[1024]; 
    // IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"),6666); 

    TcpClient tcp1 = new TcpClient("127.0.0.1", 6666); 


    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void send_Click(object sender, EventArgs e) 
    { 
     tx = Encoding.ASCII.GetBytes(textBox1.Text); 
     try 
     { 
      NetworkStream ns = tcp1.GetStream(); 
      ns.Write(tx, 0, tx.Length); 
      // ns.Close(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 

    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     try 
     { 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 
} 
} 
+1

D'un rapide coup d'œil, il semble que vous devez ajouter une boucle dans 'handlerThread () '. – kajacx

+0

merci beaucoup à votre aide .. cela fonctionne. la boucle doit être avant cette ligne: NetworkStream ns = new NetworkStream (hanso); et je devrais supprimer les deux dernières lignes –

+0

En outre, votre code serveur n'est pas thread-safe. Vous ne pouvez pas simplement modifier et lire une 'ArrayList' à partir de plusieurs threads sans synchronisation. Vous ne pouvez pas supposer que lorsque le thread du gestionnaire se déplace pour lire le socket, le bon est toujours le dernier dans la liste. Aussi aussi, pourquoi utilisez-vous 'ArrayList'? Êtes-vous coincé sur .NET 1.1 ou quelque chose? Utilisez juste 'List '. Et passez le socket accepté directement à la méthode du thread du gestionnaire. Les E/S asynchrones peuvent également être un meilleur choix que le multi-threading - inutile de gaspiller des threads en ne faisant rien. – Luaan

Répondre

0

Merci à kajacx. Je dois ajouter boucle dans handlerThread() le nouveau code:

public void handlerThread() 
    { 

      byte[] rx = new byte[1024]; 
      Socket hanso = (Socket)alSockets[alSockets.Count - 1]; 
      while (true) 
      { 
      NetworkStream ns = new NetworkStream(hanso); 
      ns.Read(rx, 0, rx.Length); 
      string str = Encoding.ASCII.GetString(rx); 
      this.Invoke(new UpdateLogCallback(this.update), new object[] { str }); 

     } 

    } 

et je supprimer deux dernières lignes