Autor Beitrag
Flitzs
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Mi 05.11.08 22:34 
Hey,
mein Problem:

Ich schreibe gerade eine Consolenanwendung, in der ich in einem, von mir gestartet Thread, auf eingehene TCP Clients warte (also der Thread ist blockiert).
Nur lässt sich dieser Thread nicht mehr beenden, Thread.Abort() funktioniert nicht (die ThreadAbortException wird nicht ausgelöst).
Wie beende ich den Thread dann?

mfg Flitzs
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 05.11.08 22:49 
Wie sieht denn dein TCP-Code aus? Es sollte eigentlich möglich sein, diesen auch non-blocking zu schreiben.

_________________
>λ=
Flitzs Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Do 06.11.08 15:19 
Hey,

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:
  
static void MailServer()
        {
            try
            {
                TcpListener Server;
                   try
                       {
                           Server = new TcpListener(IPA, 25);
                        
                       }
                       catch
                       {
                          Console.WriteLine("Server kann nicht gestartet werden!");
                          return;
                       }
                Server.Start();
                while (true)
                {
                    Thread T = new Thread(new ParameterizedThreadStart(ClientTalk));                    
                    T.Start(Server.AcceptTcpClient());
                }
            }
            catch (ThreadAbortException)
            {
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Server wird wegen Fehler beended: " + ex.Message);
                return;
            }
            
        }

Die Funktion MailServer wird in einem extra Thread ausgeführt die für jeden neuen TCP Client einen neun Thread start, in dem dann mit den Client interagiert.

mfg Flitzs


Zuletzt bearbeitet von Flitzs am Do 06.11.08 15:50, insgesamt 1-mal bearbeitet
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 06.11.08 15:33 
Das asynchrone Gegenstück ist TcpListener.BeginAcceptSocket. Einen eigenen Thread brauchst du dann wahrscheinlich gar nicht mehr.

_________________
>λ=
Flitzs Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Do 06.11.08 16:33 
Hey, mein momentaner Code sieht so aus:
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:
static void MailServer()
        {
            try
            {
                TcpListener Server;
                try
                {
                    Server = new TcpListener(IPA, 25);

                }
                catch
                {
                    Console.WriteLine("Server kann nicht gestartet werden!");
                    return;
                }
                Server.Start();
                while (true)
                    Server.BeginAcceptTcpClient(new AsyncCallback(ClientTalk),Server);                
            }
            catch (ThreadAbortException)
            {
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Server wird wegen Fehler beended: " + ex.Message);
                return;
            }

        }     
         
        static void ClientTalk(IAsyncResult  ar)
        {               
            TcpListener listener = (TcpListener)ar.AsyncState;            
            TcpClient Client = listener.EndAcceptTcpClient(ar);


Doch funktioniert das natürlich nicht, da ich die Methode ja immer wieder aufrufe. Nun stellt sich mir die Frage, wie ich die Schleife ersetze. Ich könnte ein weiteres  Server.BeginAcceptTcpClient nach dem TcpClient Client = listener.EndAcceptTcpClient(ar); in der Funktion ClientTalk schreiben, aber irgendwie kommt mir das nicht so vor als wäre das die Beste Lösung oder?

mfg Flitzs
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 06.11.08 17:04 
user profile iconFlitzs hat folgendes geschrieben Zum zitierten Posting springen:
Ich könnte ein weiteres  Server.BeginAcceptTcpClient nach dem TcpClient Client = listener.EndAcceptTcpClient(ar); in der Funktion ClientTalk schreiben, aber irgendwie kommt mir das nicht so vor als wäre das die Beste Lösung oder?
Ich denke, das ist schon der richtige Weg. Du musst die Schleife in eine (Pseudo-)Rekursion umwandeln:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
void AcceptClients(TcpListener listener)
{
  listener.BeginAcceptTcpClient(ar => {
    var client = listener.EndAcceptTcpClient(ar);
    [...]// neuen Thread für client abspalten...
    // auf nächsten Client warten
    AcceptClients(listener);
  }, null);
}

_________________
>λ=
Gom_Uni
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Sa 06.12.08 20:04 
Hallo leute,

mir gehts genauso, ich habe einen Blockierenden Thread welcher aufgrund der TCP Server Datenanbindung nicht mehr zu terminieren ist.

Gibt es irgendeine saubere Lösung dafür?
Problem tritt in Zeile 13 auf, weil die blokierende Funktion BLOCKIERT
ausblenden C#-Quelltext
1:
 Socket sock = listen.AcceptSocket();					


Ablauf:

Create Listening Thread
Listen
Accept
Create Next Listening Thread
...
...
while(Receiving data)

Dies wurde deshalb so implementiert weil ein Client über den gesamten Zeitraum hinweg immer mit dem Server verbunden bleibt. Dies ist nötig da der Server auch asynchrone meldungen an alle clients senden können muss.

Nachdem ich C# erst seit 4 Tagen in Verwendung habe kann es sein dass die klasse etwas zusammengeflickt aussieht, aber bis jetzt funzts

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:
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:
class Server
    {
        static int mListen = 0;
        static int mConnection = 0;
        static List<Thread> mCrtTreads = new List<Thread>();

        static void DoListen()
        {
            IPAddress[] IPs = Dns.GetHostAddresses("localhost");
            TcpListener listen = new TcpListener(IPs[0], 22025);
            listen.Start();
            
            Socket sock = listen.AcceptSocket();
            StartListen();

            long size = 0;
            List<byte> buf = new List<byte>();

            do
            {
                size = sock.Receive(buf.ToArray());
                if (size > 0)
                {

                }
                else
                {
                    sock.Disconnect(true);
                    sock.Close();
                }
            }
            while (size > 0);
            Console.WriteLine("Communication Thread terminated / client disconnected");
        }

        public static void StartListen()
        {
            Thread t = new Thread(new ThreadStart(DoListen));
            t.Name = "Listenthread " + (mListen++).ToString();
            Console.WriteLine("[started] " + t.Name.ToString());
            mCrtTreads.Add(t);
            t.Start();
        }

        public static void Kill()
        {
            Console.WriteLine("Killing Threads... " + mCrtTreads.Count.ToString());
            foreach (Thread i in mCrtTreads)
            {
                //if (i.ThreadState == ThreadState.WaitSleepJoin)
                    i.Interrupt();

                // Zweifelhafter versuch diesen Thread zu killen :-)

                Console.WriteLine("..." + i.Name.ToString());
                i.Abort();

            }
            mCrtTreads = null;
        }
    }


mfg george
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 06.12.08 20:20 
:welcome:

Ich sehe leider keine andere Möglichkeit als meine etwas gewöhnungsbedürftige Rekursion von oben.
Falls du übrigens keine speziellen Socket-Features benötigst, würde ich unbedingt (Begin)AcceptTcpClient benutzen

_________________
>λ=
Gom_Uni
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Sa 06.12.08 20:36 
hy danke für deine mühe,

habe endlich das richtige gefunden. ich habe ne schleife mit
ausblenden C#-Quelltext
1:
 while(!listen.Pending) {Sleep(1000);}					

am laufen. Damit funzt alles.

mfg & thx