Comment rendre AcceptTcpClient non bloquant dans un thread ?

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je voulais savoir s'il y avait des objets qui seraient déjà sécurisés ? Notemment TcpListener ?

Imaginons un de mes threads est 'bloqué' à la méthode AcceptTcpClient() alors qu'un autre thread décide d'appeler la méthode Close sur ce même TcpListener. Le comportement devrait être le suivant : AcceptTcpClient lance une SocketException que je peux gérer; mais y a t-il une zone critique ? Si oui, comment protèger mon TcpListener tout en laissant la possibilité de débloquer AcceptTcpClient ?

Merci d'avance !

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace ServerModel
{
  public class ClientListener
  {
      const string THREAD_NAME = "TCP Client listening thread";
      private TcpListener _Server;
      private event Action<ClientListener, TcpClient> _OnClientConnected;
      private Thread _ListeningThread;
      private bool _IsListening;

      public event Action<ClientListener, TcpClient> OnClientConnected
      {
          add
          {
              lock (this)
              {
                  this._OnClientConnected += value;
              }
          }

          remove
          {
              lock (this)
              {
                  this._OnClientConnected -= value;
              }
          }
      }

      public bool IsListening
      {
          get
          {
              bool isListening;
              lock (this)
              {
                  isListening = this._IsListening;
              }
              return isListening;
          }
      }

      private bool _IsThreadStopped
      {
          get
          {
              return this._ListeningThread == null ||
                     this._ListeningThread.IsAlive == false;
          }
      }

      public ClientListener(int port)
      {
          IPAddress localAddr = IPAddress.Any;

          this._Server = new TcpListener(localAddr, port);
          this._IsListening = false;
      }

      public bool Start()
      {
          bool retval = false;

          lock (this)
          {
              if (this._IsThreadStopped)
              {
                  this._Server.Start();
                  this._ListeningThread = new Thread(this.Listen);
                  this._ListeningThread.Name = THREAD_NAME; // Debug purposes
                  this._IsListening = true;
                  this._ListeningThread.Start();

                  retval = true;
              }
          }

          return retval;
      }

      public void Stop()
      {
          // lock (this)
          // {
              this._IsListening = false;
              this._Server.Stop();
              this._WaitsUntilStopped();
          // }
      }

      private void _WaitsUntilStopped()
      {
          while(!this._IsThreadStopped)
          {
              Thread.Sleep(1000);
          }
      }

      private void Listen()
      {
          TcpClient client;

          while (this.IsListening)
          {
              try
              {
                  lock (this)
                  {
                      client = _Server.AcceptTcpClient();
                      if (_OnClientConnected != null)
                      {
                          _OnClientConnected(this, client);
                      }
                  }
              }
              catch (SocketException e)
              {
                  if (this.IsListening)
                  {
                      throw e;
                  }
              }
          }
      }

  }
}

+0 -0

Je pense avoir trouvé ma réponse. Je n'avais pas vu la méthode Pending non bloquante qui indique s'il y a des clients qui attendent à être acceptés. Pas besoin de Close pour débloquer AcceptTcpClient. Cela implique que ça peut (doit, je pense) être protégé.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace ServerModel
{
  public class ClientListener
  {
      const int TIMEOUT = 500;
      const string THREAD_NAME = "TCP Client listening thread";
      private TcpListener _Server;
      private event Action<ClientListener, TcpClient> _OnClientConnected;
      private Thread _ListeningThread;
      private bool _IsListening;

      public event Action<ClientListener, TcpClient> OnClientConnected
      {
          add
          {
              lock (this)
              {
                  this._OnClientConnected += value;
              }
          }

          remove
          {
              lock (this)
              {
                  this._OnClientConnected -= value;
              }
          }
      }

      public bool IsListening
      {
          get
          {
              bool isListening;
              lock (this)
              {
                  isListening = this._IsListening;
              }
              return isListening;
          }
      }

      private bool _IsClientThreadStopped
      {
          get
          {
              return this._ListeningThread == null ||
                     this._ListeningThread.IsAlive == false;
          }
      }

      public ClientListener(int port)
      {
          IPAddress localAddr = IPAddress.Any;

          this._Server = new TcpListener(localAddr, port);
          this._IsListening = false;
      }

      public bool Start()
      {
          bool retval = false;

          lock (this)
          {
              if (this._IsClientThreadStopped)
              {
                  this._Server.Start();
                  this._ListeningThread = new Thread(this.Listen);
                  this._ListeningThread.Name = THREAD_NAME; // Debug purposes
                  this._IsListening = true;
                  this._ListeningThread.Start();

                  retval = true;
              }
          }

          return retval;
      }

      public void Stop()
      {
          if (this.IsListening)
          {
              lock (this)
              {
                  this._IsListening = false;
              }

              this.main_WaitsUntilStopped();
              this._Server.Stop();
          }
      }

      private void main_WaitsUntilStopped()
      {
          while (!this._IsClientThreadStopped)
          {
              Thread.Sleep(TIMEOUT);
          }
      }

      private void Listen()
      {
          TcpClient client;

          while (this.IsListening)
          {
              lock (this)
              {
                  if (_Server.Pending())
                  {
                      client = _Server.AcceptTcpClient();
                      if (_OnClientConnected != null)
                      {
                          _OnClientConnected(this, client);
                      }
                  }
              }

              Thread.Sleep(TIMEOUT);
          }
      }

  }
}


Edit : Je vais renommer le topic de "Que faut-il sécuriser avec lock ?" à "Comment rendre AcceptTcpClient non bloquant dans un thread".. pour la recherche..

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte