C# Auf Nachrichten über TCP warten

Thaxll'ssillyia

Captain
Registriert
Dez. 2007
Beiträge
3.501
Hallo Community!

Ich progge zuzeit an einem Client-Server-basierten Chatprogramm.

Mein Code sieht bisher so aus:
Code:
           public static void StartListening()
            {
                Server_Listener = new TcpListener(Lokal, Port) ; 
                Server_Listener.Start();
                thrListening = new Thread(KeepListening);
                thrListening.Start();
            }
            public static void KeepListening()
            {
                
                while (Server_Running == true)
                {                    
                    tcpClient = Server_Listener.AcceptTcpClient();
                    for (int i = 0; i < Variables.const_Max_Clients; i++)
                    {
                        if (Variables.m_Client[i].TCPclient == null)
                        {
                            Variables.m_Client[i].TCPclient = tcpClient;
                            Variables.m_CurrentUsers++;
                            break;
                        }
                    }
                    if (Variables.m_CurrentUsers == 1)
                    {
                        HoldConnection = new Thread(Connection.ConnectionToTCP);
                        HoldConnection.Start();
                    }
                }                               
            }


                public static void ConnectionToTCP()
                {
                    while (Server_Running == true)
                    {
                        for (int i = 0; i < Variables.const_Max_Clients; i++)
                        {
                            try
                            {
                                StreamReader Nachricht = new StreamReader(Variables.m_Client[i].TCPclient.GetStream());
                                if (Nachricht.ReadLine() == "Login")
                                {
                                    CheckClient(tcpClient);
                                }
                            }
                            catch { }
                        }
                    }
                }

Wie selbst ein Laie sehen kann, wird ein neuer tcpClient (Akzeptiert durch TCP-Listener) einem freien Eintrag vom Typ TCPClient zugewiesen.
Nun empfange ich eine Nachricht vom Client.
Mein Problem ist, dass ich gerne auf Nachrichten über TCP warten würde, und sobald eine eingeht, diese Auswerten.
Kennt da jemand eine Lösung?

Auch hatte ich nach einer Möglichkeit gesucht, Nachrichten nicht TCPClientspezifiziert zu empfangen, sondern überhaupt über eine Verbindung. Von welchem Client das dann kommt, könnte ich ja der Nachricht entnehmen.

Vielen Dank für Hilfe!

Gruß Thax
 
danke für die schnelle Antwort. :)

Aber ist das hier,

Code:
            while ((true))
            {
                try
                {
                    requestCount = requestCount + 1;
                    NetworkStream networkStream = clientSocket.GetStream();
                    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                    dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    Console.WriteLine(" >> " + "From client-" + clNo + dataFromClient);

                    rCount = Convert.ToString(requestCount);
                    serverResponse = "Server to clinet(" + clNo + ") " + rCount;
                    sendBytes = Encoding.ASCII.GetBytes(serverResponse);
                    networkStream.Write(sendBytes, 0, sendBytes.Length);
                    networkStream.Flush();
                    Console.WriteLine(" >> " + serverResponse);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(" >> " + ex.ToString());
                }
            }
wenn es für jeden Client (bei mir 20) gleichzeitig (jeder ein Thread) ausgeführt wird, nicht der gleiche Rechenaufwand (unter Annahme, das grade 20 Clients online sind)wie meine Lösung (siehe unten)?

Code:
                public static void ConnectionToTCP()
                {
                    while (Server_Running == true)
                    {
                        for (int i = 0; i < Variables.const_Max_Clients; i++)
                        {
                            try
                            {
                                StreamReader Nachricht = new StreamReader(Variables.m_Client[i].TCPclient.GetStream());
                                if (Nachricht.ReadLine() == "Login")
                                {
                                    CheckClient(tcpClient);
                                }
                            }
                            catch { }
                        }
                    }
                }

Bei mir wird halt nur ein Thread ausgeführt, un in diesem für jeden Client versucht ein Stream zu empfangen...trotzdem liegt CPU-Last bei 70 %.

Oder verstehe ich etwas falsch?

Gruß Thax
 
Probiers mal so:
Code:
                public static void ConnectionToTCP()
                {
                    while (Server_Running == true)
                    {
                        for (int i = 0; i < Variables.const_Max_Clients; i++)
                        {
                            NetworkStream networkStream = Variables.m_Client[i].TCPclient.GetStream();

                            if (networkStream.DataAvailable)
                            {
                                StreamReader Nachricht = new StreamReader(networkStream);
                                if (Nachricht.ReadLine() == "Login")
                                {
                                    CheckClient(tcpClient);
                                }
                            }
                        }
                    }
                }
Dabei wird keine (sehr unperformante) Exception ausgelöst, wenn keine Daten vorhanden sind.
 
danke, ich probiers aus.

Gibts da noch ein Lösung, die sich nicht auf einen TCPClient bezieht, sondern auf einen Socket oder so?
Also sobald eine Nachricht über Port XXXXX auf IP XXX.XXX.XX.XX ankommt, ein Event behandelt wird?

Vielen Dank für weitere Hilfe.

MfG Thax
Ergänzung ()

Dabei wird keine (sehr unperformante) Exception ausgelöst, wenn keine Daten vorhanden sind.

mhh, Prozessorauslastung ist jetzt von 70% auf 50 % gesunken, aber ist wirklich soviel nötig? Ich versuch mal die Threadpriority zu senken
 
Also:

die hohe CPU auslastung kommt daher, dass du in der ConnectionToTCP() kein blockierendes Element hast, ein einfacher Sleep(1); reicht hier schon aus. Damit geht die Auslastung gleich runter.

Also folgendermaßen (mit Verbesserungen)

Code:
public static void ConnectionToTCP()
                {
                    while (Server_Running == true)
                    {
                        for (int i = 0; i < Variables.m_Client.Count; i++)  //Count oder Lenght, denn const_Max_Clients ist in vielen fällen großer als die tatsächliche Anzahl von verbundenen Clients.
                        {
                            NetworkStream networkStream = Variables.m_Client[i].TCPclient.GetStream();

                            if (networkStream.DataAvailable)
                            {
                                StreamReader Nachricht = new StreamReader(networkStream);
                                if (Nachricht.ReadLine() == "Login")
                                {
                                    CheckClient(tcpClient);
                                }
                            }
                        }
                     Thread.Sleep(10); //Damit nimmst du die hohe CPU Auslastung weg.
                    }
                }

2. Ein weiteres Problem ist, wenn du jetzt 2 verbundene Clients hast, kann es zu einem Blockieren des 2ten Clients kommen.

Wenn der 1 Client einen Login machen soll, dann muss er schicken "Login/0", wenn er das "/0" nicht schicken (ist der String Terminierer), dann bleibt dein Programm in der ReadLine() hängen, bis es das Zeichen geschickt bekommt. Somit wird der 2. Client niemals sich einloggen können.

Dieses Problem kann auch passieren, wenn sich Client 1 einloggt, aber seine internetverbidnung abbricht wenn er "Log" geschickt hat. Dann wird dein Server niemals ein "in/0" erhalten und immer da stecken bleiben.

NACHTRAG:

Sehe du gibst jedem Client einen eigenen Thread, dann wird der 2. Punkt hinfällig und die Verbesserung m_Client.Count ist egal.
 
Zuletzt bearbeitet:
Zurück
Oben