Laden...

Eingehnde Daten werden nicht in Variable übernommen

Erstellt von Loofsy vor 2 Jahren Letzter Beitrag vor 2 Jahren 1.060 Views
L
Loofsy Themenstarter:in
32 Beiträge seit 2020
vor 2 Jahren
Eingehnde Daten werden nicht in Variable übernommen

Hallo liebe Mitentwickler.

Ich habe meine Serverklasse soweit fertig (funktioniert im wesentlichen auch). Allerdings mit einer kleinen aber problematischen Einschränkung.

Nachdem der Socket die Verbindung angenommenhat, sollen die werte von _socket1.Available in int chach1 geschrieben werden (int cache1 = _socket1.Available😉

Im Debugmodus von VS 2019 funktioniert dies solange man mit haltepunkten schrit für schritt über diese zeile geht. Nimmt man die Haltepunkte weg oder lässt das Programm so durchlaufen werden die werte aus _socket1.Available nicht übernommen (obwohl sie da sind). Weiss einer woran das liegt bzw wie man das beheben kann?

Ich habe bereits versucht mit Thread.Sleep(1000); mehrere "Wartepunkte" zu erstellen weil ich vermute dass das programm zu schnell abgearbeitet wird aber daran liegt es nicht.

Nachfolgend der ganzze code und danke im Vorraus.


public ServerEngine()
        {
            IPHostEntry ipHostInfo = Dns.Resolve("MUSTER-PC");
            IPAddress ipAddress = ipHostInfo.AddressList[2];
            Controller._serverIPEndPoint = new IPEndPoint(ipAddress, 9090);
            Controller._listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        }

        public void ServerRun()
        {

            try
            {
                Controller._listener.Bind(Controller._serverIPEndPoint);
                Controller._listener.Listen(10000);

                Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                Protocoll.Write($"");
                Protocoll.Write($"PRTW-Server gestartet!");
                Protocoll.Write($"");
                Protocoll.Write($"##########################################################");

                Thread run = new Thread(() =>
                {
                byte[] _receivePufferSize;

                    while (true)
                    {


                        Socket _socket1 = Controller._listener.Accept(); // wartet auf eingehende Verbindungy
                        int cache1 = _socket1.Available; // Legt Empfangswert in zwischenspeicher
                        if (cache1 == _socket1.Available) // Prüfung ab Daten korrekt empfangen wurden.
                        {
                            _receivePufferSize = new byte[cache1];// festlegen des Empfangsspeichers
                            _receivePuffer = _socket1.Receive(_receivePufferSize); // empfangen der Daten
                            _content = Encoding.ASCII.GetString(_receivePufferSize, 0, _receivePuffer); // Übersetzen in String

                            #region Zerlegen der eingehenden Information (sofern das Format stimmt)
                            //Format ClientName:ServiceName:Identifier:Command
                            string[] values;
                            string clientName;
                            string serviceName;
                            string identifier;
                            string command;
                            string param = _content;
                            string connectParam;
                            values = param.Split(':');

                            if (values.Length == 4) // Prüft ob das Format korrekt ist
                            {
                                // Weisst die Arraywwerte den Variablen zu
                                clientName = values[0];
                                serviceName = values[1];
                                identifier = values[3];
                                command = values[2];

                                #endregion
                                #region Eingehende Anfrage wird gefiltert und sortiert
                                if (identifier == "195c40c4-842d-4e72-ad29-fd6b16c9e4aa" && clientName != "PRTG_Client")
                                {
                                    Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                    Protocoll.Write($"");
                                    Protocoll.Write($"Der Dienst -> {serviceName} <- möchte sich anmelden!");
                                    Protocoll.Write($"");
                                    Protocoll.Write($"##########################################################");


                                    if (ClientLister._TWPro_ClientRequestList.ContainsKey(serviceName)) // Prüft ob TWPro_Dienst bereits angemeldet ist.
                                    {
                                        Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"Der Dienst -> {serviceName} <- hat sich bereits angemeldet!");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"##########################################################");
                                    }
                                    else // Wenn nicht, melde Dienst an
                                    {

                                        Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"Der Dienst -> {serviceName} <- wurde angemeldet!");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"##########################################################");
                                        ClientLister._TWPro_ClientRequestList.Add(serviceName, _socket1);
                                    }

                                }


                                if (identifier == "195c40c4-842d-4e72-ad29-fd6b16c9e4aa" && clientName == "PRTG_Client")
                                {
                                    Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                    Protocoll.Write($"");
                                    Protocoll.Write($"PRTG ruft {serviceName}!");
                                    Protocoll.Write($"");
                                    Protocoll.Write($"##########################################################");


                                    if (ClientLister._TWPro_ClientRequestList.ContainsKey(serviceName))
                                    {
                                        Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"Der Dienst -> {serviceName} <- wurde gefunden...");
                                        Protocoll.Write($"{command} wurde übertragen!");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"##########################################################");


                                        Socket ip = (Socket)ClientLister._TWPro_ClientRequestList[serviceName];



                                        try
                                        {
                                            if (ip.Connected) // Prüfe ob verbindung zum TWPro-Dienst besteht
                                            {
                                                // Sende Anfage an TWPro Dienst
                                                byte[] sendPuffer = Encoding.ASCII.GetBytes(command);
                                                ip.Send(sendPuffer);

                                                Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                                Protocoll.Write($"");
                                                Protocoll.Write($"{command} wurde an {ip.RemoteEndPoint} gesendet!");
                                                Protocoll.Write($"Warten auf antwort.......");
                                                Protocoll.Write($"");
                                                Protocoll.Write($"##########################################################");

                                                // Empfange Antwort vom TWPro Dienst
                                                int cache = ip.Available;
                                                _receivePufferSize = new byte[cache];
                                                _receivePuffer = ip.Receive(_receivePufferSize);
                                                string receiveMsg = Encoding.ASCII.GetString(_receivePufferSize, 0, _receivePuffer);

                                                Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                                Protocoll.Write($"");
                                                Protocoll.Write($"{receiveMsg} wurde von {ip.RemoteEndPoint} empfangen!");
                                                Protocoll.Write($"Sende antwort an PRTG");
                                                Protocoll.Write($"");
                                                Protocoll.Write($"##########################################################");
                                                // Sende Antwort an PRTG_Client
                                                _socket1.Send(_receivePufferSize);
                                                // byte[] sendPuffer2 = Encoding.ASCII.GetBytes(_receivePuffer);
                                            }
                                            else // wenn nicht sende Fehler und entferne Dienst aus der Liste
                                            {
                                                byte[] sender = Encoding.ASCII.GetBytes("false:2:TWPro-Dienst antwortet nicht!");
                                                _socket1.Send(sender);
                                                ClientLister._TWPro_ClientRequestList.Remove(serviceName);
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                            Protocoll.Write($"");
                                            Protocoll.Write($"Fehler bei der kommunikation!");
                                            Protocoll.Write($"");
                                            Protocoll.Write($"##########################################################");
                                        }
                                    }
                                    else
                                    {
                                        Protocoll.Write($"######### Protokoll { DateTime.Now.ToString("G")}#########");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"Der Dienst -> {serviceName} <- wurde nicht gefunden!");
                                        Protocoll.Write($"Sende Fehler an PRTG");
                                        Protocoll.Write($"");
                                        Protocoll.Write($"##########################################################");
                                        string cont = "false:" + PRTG_Code.ReturnInfo((short)PRTG_Code.PRTG_Code_Enum.WARNING) + "," + SystemMessages.ServerMessages((short)SystemMessages.ServerCode.ClientNotConnect) + "";
                                        byte[] sendPuffer = Encoding.ASCII.GetBytes(cont);
                                        _socket1.SendTo(sendPuffer, _socket1.RemoteEndPoint);
                                    }
                                }
                                #endregion
                            }
                            else
                            {
                                byte[] errSend = Encoding.ASCII.GetBytes("false:4:Ungültiges Format!");
                                _socket1.Send(errSend);
                            }
                        }
                        else
                        {
                            byte[] errSend = Encoding.ASCII.GetBytes("false:4:Fehler beim Datenempfang!");
                            _socket1.Send(errSend);
                        }
                    }
                });
                run.Start();
            }
            catch (Exception e)
            {
                Protocoll.Write($"{e.Message}");
            }
        }

T
2.219 Beiträge seit 2008
vor 2 Jahren

Sendet dein Client den irgendwelche Daten?
Available ist nur gefüllt, wenn auch Daten vom Client an den Server gesendet wurden.
Mir ist aber nicht klar, warum die cache1 nochmal auf Available prüfst.
Hier sollte eher ein Prüfung rein ob Daten vorhanden sind also größer 0.

Dein Coe ist ehrlich gesagt alles andere als ansehnlich oder verständlich.
Du arbeitest scheinbar mit einer sehr rudimentären Art der Authentifizierung mit Magic Strings.
Diese solltest du, wenn schon in Konstanten ober für eine nachträgliche Änderbarkeit in eine Config auslagern.
Die empfangenen Daten solltest du am besten in einer Paket Klasse kapseln und nicht mit einzelnen Variablen im Code arbeiten.
Dadurch kannst du auch gleich den Part zum prüfen der Pakete auslagern.
Das alles in eine Klasse zu quetschen pumpt den Code auf und vermischt auch die Zuständigkeiten.
Deine Klasse muss such dann um alle Belange kümmern, was die zukünftige Warte unnötig erschwert.

Nachtrag:
Aktuell hat dein Server keine sichtbare Logik um die Verarbeitung deines Threads zu beenden.
Da du hier eine while(true) Schleife hast, würde der Thread endlos laufen.
Hier solltest du den Code umbauen um den Server per End/Close/Shutdown auch sauber runterzufahren und die Schleife im Thread zu beenden.

Nachtrag 2:
Ebenfalls solltest du den Socket von deiner Seite auch richtig schließen.
Auch davon ist im aktuellen Code nichts zu sehen.

Bzw. wäre es sogar sinnvoller auf die Wrapper Klassen TcpListener bzw. für die Clients auf TcpClient umzustellen.
Diese kümmern sich dann intern um den Socket, was die Arbeit und den Code auch für dich verständlicher macht.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

4.931 Beiträge seit 2008
vor 2 Jahren

Schau dir nochmal deinen Code an:


int cache1 = _socket1.Available; // Legt Empfangswert in zwischenspeicher
if (cache1 == _socket1.Available) // Prüfung ab Daten korrekt empfangen wurden.
{
   // ...
}

Was stimmt da wohl nicht?

PS: Außerdem solltest du die gesamte Thread-Methode als eigene Klassenmethode anlegen (anstatt als ultralange Lambda-Methode).
Und die gesamten Protocol-Ausgaben könntest du auch über eine parametrisierte Methode umsetzen, damit die Logik deines Codes lesbarer wird.
Überlege auch mal, was du an deinem Code alles ändern müßtest, um es mehrsprachig zu gestalten.

PPS: Und weißt du, daß du mittels catch (Exception e) nicht den Thread-Code fangen kannst, da dieser ja in einem anderen Thread läuft!?
Dafür brauchst du in dem Thread-Code eine eigene try...catch-Anweisung.

16.806 Beiträge seit 2008
vor 2 Jahren

Ist wirklich nur fachlich und nicht persönlich gemeint; aber ich muss wirklich loswerden, dass ich schon lang nicht mehr solch einen Quellcode voller ungünstigen Umsetzungen und potentiellen Fehlerquellen auf so wenig Inhalt gesehen hab. Aber das Thema ist halt auch durchaus komplex, wenn man es richtig machen will.
Das ist riesig weit weg von dem, wie man das generell mit Sockets tun sollte und Lichtjahre weit weg, wie man sowas in 2021 machen würde 🙂
Wie im anderen Thread schon von mehreren gesagt worden ist: nutz doch einfach die ASP.NET Pipeline für Dein Vorhaben.
10 Zeilen Code und Du hast was stabiles.

In Deinem Code stimmt fast nichts; weder im Aufbau des Listenings noch in der parallele Verarbeitung, die Du haben wolltest (Wie mache ich einen Server Multitaskingfähig?) .... und auch ganz weit weg von der Doku. Es wirkt fast so, dass Du aus verschiedenen Quellen zeug zusammen kopiert hast, das in seiner Funktionsweise aber gar nicht zusammen passt.
Da solltest Du nochmal schauen, wie das ganze Zeug funktioniert. Du wirst ansonsten was bauen, was niemals stabil funktionieren wird.
Und ich sag Dir das wirklich in der Deutlichkeit, dass Du vielleicht doch erkennst, das was stabileres als Basis die bessere Lösung >für Dich< ist.

Wie es grob funktionieren sollte:

  • Du erstellst einen Listener und wartest auf Verbindungen
  • Sobald eine Verbindung kommt nimmst Du diese an; Verarbeiten tust Du sie aber nicht im gleichen Thread, sonst blockiert alles
  • Du hörst auf weitere Verbindungen

Wie Du das erreichen kannst: im Endeffekt 80% Deines Codes wegwerfen und folgendes korrigieren

  • Nach Listen() auf einen Port wird sofort zugehört, der Thread danach ist quatsch
  • Das Threading ist hier völlig falsch eingesetzt; verwende BeginAccept() und arbeite mit Callbacks
  • Lass am besten den ganzen Thread-Quatsch weg und arbeite mit Tasks

Aber wie im anderen Thread gesagt:
Du versuchst das Rad neu zu erfinden und das leider sehr instabil statt bestehendes zu nutzen.