Autor Beitrag
Xzeer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 62



BeitragVerfasst: So 31.10.10 12:37 
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):
ausblenden volle Höhe 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:
ausblenden volle Höhe 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:

_________________
Xzeer
huuuuuh
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 665
Erhaltene Danke: 19

win xp, (win vista), win 7
VS 2008 Express Edition, VS 2010 Express Edition, VS 2010 Professionell
BeitragVerfasst: So 31.10.10 13:19 
listener.Pending() ist true, sobald eine Verbindung anliegt.
habe es also, kurz gesagt, so gemacht:
ausblenden volle Höhe 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 62



BeitragVerfasst: So 31.10.10 14:22 
cool, danke :zustimm:
pending war mir noch nicht bekannt...

_________________
Xzeer
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: 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.

_________________
>λ=