2012-12-29 1 views
0

Un client doit créer simultanément plusieurs connexions tcp au serveur. Le code de mon serveur est ci-dessous.Plusieurs clients Tcpclient se connectent au serveur

while (_running) 
{ 
    if (!_listener.Pending()) 
    { 
     Thread.Sleep(100); 
     continue; 
    } 

    TcpClient client = _listener.AcceptTcpClient(); 
} 

Et le code de mon client est ci-dessous.

for (int i = 0; i < num; i++) 
{ 
    TcpClient tcp = new TcpClient(); 
    tcp.Connect(_server); 
} 

La première connexion est réussie. Mais la deuxième connexion est échouée en raison de la non-réponse du serveur (En fait, le serveur écoute la connexion tcp).
Cependant, si j'ajoute Thread.Sleep(1500) après chaque tcp.Connect(), toutes les connexions sont réussies. Mais cette situation n'est vraie que s'il y a un client et un serveur. S'il y a beaucoup de clients, comment puis-je m'assurer que chaque connexion peut être acceptée par le serveur? Aussi pourquoi je ajoute Thread.Sleep peut faire de telles connexions réussir?

Répondre

0

J'avais la même tâche. J'ai cherché l'implémentation canonique de cette tâche pour .Net sans chance. L'approche que j'utilise maintenant est décrite ci-dessous.

idée principale

Nous avons besoin auditeur de recevoir connexion, donner la connexion au gestionnaire, et dès départ possible écouter une nouvelle connexion.

mise en œuvre

AutoResetEvent _stopEvent = new AutoResetEvent(false); 
object _lock = new object(); 

public void StartListening() 
{ 
    _listener.BeginAcceptTcpClient(ConnectionHandler, null); 
    _stopEvent.WaitOne();//this part is different in my original code, I don't wait here 
} 

public void StopListening() 
{ 
    lock(_lock) 
    { 
     listener.Stop(); 
     listener = null;     
    } 

    _stopEvent.Set();//this part is different in my original code 
} 

void ConnectionHandler(IAsyncResult asyncResult) 
{ 
    lock(_lock) 
    { 
     if(_listener == null) 
      return; 

     var tcpClient = _listener.EndAcceptTcpClient(asyncResult); 
     var task = new MyCustomTask(tcpClient); 
     ThreadPool.QueueUserWorkItem(task.Execute); 

     _listener.BeginAcceptTcpClient(ConnectionHandler,null);    
    } 
} 

Je ne suis toujours pas très confiant pour appeler _listener.BeginAcceptTcpClient en ConnectionHandler, mais je ne l'ai pas trouvé autre moyen.

0

Puisqu'il n'y a toujours pas de réponses satisfaites et j'utilise finalement une approche différente pour gérer mon cas. J'ai découvert que l'utilisation de la classe Socket est plus rapide et plus stable que l'utilisation TcpListener et TcpClient. J'ai essayé une approche différente pour utiliser TcpListener et TcpClient. Tout d'abord, j'ai utilisé TcpListener.AcceptTcpClient pour écouter le client avec et sans TcpListener.Pending mais il est possible que j'ignore une connexion client. Sencondly, j'ai utilisé la méthode asynchrone, TcpListener.BeginAcceptTcpClient et TcpListener.EndAcceptTcpClient mais toujours pas réussi, ignorant toujours une connexion client. Enfin en utilisant Socket.Accept au lieu de TcpListener.AcceptTcpClient, l'ancien n'a presque pas de délai et très rapide à la réponse au client.

+3

Le retard dans l'acceptation des clients était dû à la perte de sommeil dans votre code, pas à toute lacune dans l'API. – EJP

Questions connexes