Entwickler-Ecke

Netzwerk - TCPListener: Problem in Schleife


Xzeer - So 31.10.10 12:37
Titel: TCPListener: Problem in Schleife
Hi,

Ich habe ein Problem mit dem TCPListener.
Und zwar programmiere ich einen einfachen thread-basierten Netzwerkserver, der die Kommunikation mit mehreren Clients abwickeln kann.

Dazu habe ich eine Methode geschrieben, welche ständig auf neue Clients wartet (und natürlich in einem eigenen Thread ausgeführt wird):

C#-Quelltext
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:
        private void warteAufClient()
        {
            //listener starten
            listener.Start();

            //client erstellen
            TcpClient client = new TcpClient();

            while (isActive)
            {
                //auf client warten
                try
                {
                    client = listener.AcceptTcpClient();
                }
                catch
                {
                    //test
                }
                finally
                {
                    //test
                }

                //client in client-liste speichern
                clients.Add(client);

                //bearbeitungsschleife erstellen
                Thread clientLoop = new Thread(new ParameterizedThreadStart(bearbeiteClient));

                //bearbeitungsschleife starten
                clientLoop.Start(client);
            }
        }


Nun habe ich aber ein Problem den Server wieder zu beenden, da AcceptTCPClient() den Thread ja bis zur nächsten Verbindung anhält.
Dadurch zeigt meine Laufbedingung für die While-Schleife keine Auswirkung. Diesem Effekt mit try-catch-finally entgegenzuwirken funktioniert leider nicht.

Gibt es da eine schicke Möglichkeit?

//EDIT:

Hab es jetzt so gelöst:

C#-Quelltext
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:
        private void warteAufClient()
        {
            //listener starten
            listener.Start();

            //client erstellen
            TcpClient client = new TcpClient();

            while (true)
            {
                //auf client warten
                try
                {
                    client = listener.AcceptTcpClient();
                }
                catch 
                {
                    //loop beenden
                    break;
                }
                
                //client in client-liste speichern
                clients.Add(client);

                //bearbeitungsschleife erstellen
                Thread clientLoop = new Thread(new ParameterizedThreadStart(bearbeiteClient));

                //bearbeitungsschleife starten
                clientLoop.Start(client);
            }
        }


Über die ServerBeenden Methode schließe ich den listener mit listener.stop(). Dabei wirft die AccptTCPCClient Methode allerdings eine Exception, die ich (unschönerweise) einfach abfange und aus der schleife springe.

Wenn jemand eine bessere Lösung hat, kann er sie gerne posten... :wink:


huuuuuh - So 31.10.10 13:19

listener.Pending() ist true, sobald eine Verbindung anliegt.
habe es also, kurz gesagt, so gemacht:

C#-Quelltext
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:
while (true)
{
   while (!listener.Pending())
   {
      if (!(IsActive))
      {
          return;
      }
      Thread.Sleep(200);
   }
   //auf client warten
   try
   {
       client = listener.AcceptTcpClient();

       //client in client-liste speichern
      clients.Add(client);

       //bearbeitungsschleife erstellen
       Thread clientLoop = new Thread(new ParameterizedThreadStart(bearbeiteClient));

       //bearbeitungsschleife starten
       clientLoop.Start(client);
    }
    catch
    {
                    //test
    }
    finally
    {
                    //test
    }

      
}

In der while (!listener.Pending()) -Schleife wird auf eine neue Verbindung gewartet. Alle 200ms (Die 200ms sind Variabel, sollten aber für die meisten Anwendungsfälle ausreichen) wird abgefragt, ob eine Verbindung anliegt. wenn diese da ist wird sie angenommen.
Wenn der Wert IsActive false ist, wird die gesamte Methode abgebrochen.


Xzeer - So 31.10.10 14:22

cool, danke :zustimm:
pending war mir noch nicht bekannt...


Kha - So 31.10.10 14:27

Warum nicht einfach die Schleife in ebenfalls in einen eigenen Thread auslagern? Mit BeginAcceptClient wäre es noch schöner, da der zusätzliche Thread vermieden wird, aber auch etwas komplizierter.