Question

Lorsque vous utilisez Net.Sockets.TcpListener, quel est le meilleur moyen de gérer les connexions entrantes (.AcceptSocket) dans des threads séparés?

L'idée est de démarrer un nouveau thread quand une nouvelle connexion entrante est acceptée, pendant que le tcplistener reste ensuite disponible pour d'autres connexions entrantes (et pour chaque nouvelle connexion entrante, un nouveau thread est créé). Toutes les communications et les terminaisons avec le client à l'origine de la connexion seront traitées dans le thread.

L'exemple C # de code VB.NET est apprécié.

Était-ce utile?

La solution

Le code que j'ai utilisé ressemble à ceci:

class Server
{
  private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false);

  public void Start()
  {
    TcpListener listener = new TcpListener(IPAddress.Any, 5555);
    listener.Start();

    while(true)
    {
      IAsyncResult result =  listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
      connectionWaitHandle.WaitOne(); // Wait until a client has begun handling an event
      connectionWaitHandle.Reset(); // Reset wait handle or the loop goes as fast as it can (after first request)
    }
  }


  private void HandleAsyncConnection(IAsyncResult result)
  {
    TcpListener listener = (TcpListener)result.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(result);
    connectionWaitHandle.Set(); //Inform the main thread this connection is now handled

    //... Use your TcpClient here

    client.Close();
  }
}

Autres conseils

Je pense que vous le faites de la même manière que toute autre opération asynchrone dans .NET: vous appelez la version BeginXxx de la méthode, dans le cas présent BeginAcceptSocket. Votre rappel s'exécutera sur le pool de threads.

En règle générale, les threads regroupés sont bien meilleurs que les threads par connexion: une fois que vous avez effectué plusieurs dizaines de connexions, le système travaille beaucoup plus fort pour basculer entre les threads que pour le travail à effectuer. En outre, chaque thread a sa propre pile, dont la taille est généralement de 1 Mo (bien que cela dépende des indicateurs de lien), qui doit être trouvée dans l'espace d'adressage virtuel de 2 Go (sur les systèmes 32 bits); dans la pratique, cela vous limite à moins de 1000 threads.

Je ne sais pas si le pool de threads de .NET l'utilise actuellement, mais Windows possède un objet de noyau appelé Port de complétion E / S qui facilite les E / S évolutives. Vous pouvez associer des threads à cet objet et y associer des demandes d'E / S (y compris l'acceptation de connexions entrantes). Lorsqu'une E / S est terminée (par exemple, une connexion est établie), Windows libère un thread en attente, mais uniquement si le nombre de threads pouvant être exécutés (non bloqués pour une autre raison) est inférieur à la limite d'évolutivité configurée pour le port d'achèvement. En règle générale, vous définissez cette option sur un petit multiple du nombre de cœurs.

Je voudrais suggérer une approche différente: Ma suggestion utilise seulement deux threads.   * Un thread vérifie les connexions entrantes.   * Lorsqu'une nouvelle connexion est ouverte, cette information est écrite dans une structure de données partagée qui contient toutes les connexions ouvertes actuelles.   * Le second thread énumère cette structure de données et reçoit pour chaque connexion ouverte les données envoyées et les réponses envoyées.

Cette solution est plus évolutive en threads et, si elle est mise en œuvre correctement, elle devrait offrir de meilleures performances que d'ouvrir un nouveau thread par connexion ouverte.

Le livre de recettes O'Reilly C # 3.0 contient un excellent exemple. Vous pouvez télécharger la source d'accompagnement à partir de http://examples.oreilly.com/9780596516109/ CSharp3_0CookbookCodeRTM.zip

Je voudrais utiliser un pool de threads, de cette façon vous n’aurez pas à commencer un nouveau thread à chaque fois (car c’est un peu cher). Je ne voudrais pas non plus attendre indéfiniment pour des connexions supplémentaires, car les clients ne peuvent pas fermer leurs connexions. Comment envisagez-vous d'acheminer le client vers le même thread à chaque fois?

Désolé, vous n'avez pas d'échantillon.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top