Laden...

[gelöst] Problem bei 2 Socketverbindungen

Erstellt von Raorkon vor 9 Jahren Letzter Beitrag vor 9 Jahren 2.608 Views
R
Raorkon Themenstarter:in
9 Beiträge seit 2009
vor 9 Jahren
[gelöst] Problem bei 2 Socketverbindungen

Hallo zusammen.

ich habe hier ein problem bei einer Anwendung bzw. 2 Anwendungen
Folgende Situation:

ich habe 2 Barcodescanner die über Netzwerk angebunden sind.
Diese sollen über 2 unterschiedliche Dienste die Daten der Scanner auswerten.
Dafür habe ich eine Socketverbindung aufgebaut:


        // neuer Socket zur Verbindung zum Scanner
        private static Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        // IP Adresse des Scanners
        private static IPAddress hostAddress = new IPAddress(new byte[4] { 10, 200, 10, 25 });
        // Port des Scanners
        private static int conPort = 2112;
        // Endpunkt des Scanners
        private static IPEndPoint hostEndPoint = new IPEndPoint(hostAddress, conPort);
        // Empfangsarray
        private static byte[] RecvBytes = new byte[4096];
        private static Timer isAlive = new Timer(10000);
        
        private static bool isreachable = false;
        protected override void OnStart(string[] args)
        {

            
            #region Scanner initialisieren
            try
            {
                //überprüfen wir erst einmal ob der Scanner überhaupt erreichbar ist


                if (!s.Connected)
                {
                    raiseException.write(new string[] { "Onstart", "starte Verbindung" });
                    // Verbindung zu Scanner aufbauen
                    s.Connect(hostEndPoint);
                }
                // wenn Verbindung fehlgeschlagen
                if (!s.Connected)
                {
                    isreachable = false;
                    return;
                }
                else
                {
                    // Event für Empfang zuordnen
                    s.BeginReceive(RecvBytes, 0, RecvBytes.Length, SocketFlags.Peek, new AsyncCallback(onDataReceive), s);
                    isreachable = true;
                }

                

            }
            catch (Exception ex)
            {
                // Programm beenden
                isreachable = false;
                raiseException.write(new string[] { "Onstart", ex.Message });
                return;
                //  Environment.Exit(0);

            }
            finally
            {
                // zeitliche Prüfung ob Verbindung zum Scanner besteht
                isAlive.Elapsed += isAlive_Tick;
                isAlive.Start();
            }
            #endregion
        }

Dann habe ich mir ein Methode gebaut die zeitlich überprüft ob der Scanner noch erreichbar ist:




                private void isAlive_Tick(object sender, EventArgs e)
        {
            Ping ping = new Ping();
            #region Scanner initialisieren
            try
            {
                isAlive.Stop();
                if (!isreachable)
                {
                    if (ping.Send(hostAddress).Status == IPStatus.Success)
                    {
                        s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                        OnStart(null);
                    }
                }
                else
                {                    
                    if (ping.Send(hostAddress).Status != IPStatus.Success)
                    {
                        isreachable = false;
                        s = null;
                    }
                }
            }
            catch (Exception ex)
            {
                raiseException.write(new string[] { "isAlive", ex.Message });
                isreachable = false;
            }
            finally
            {
                ping = null;
                GC.Collect();
                isAlive.Start();
            }
            #endregion
        }

und natürlich meine Datareceive-Methode:




        private static void onDataReceive(IAsyncResult ar)
        {
            Socket client = null;
            try
            {             
                
                client = (Socket)ar.AsyncState;
                
                client.Receive(RecvBytes, RecvBytes.Length, 0);
                string materialIdentification = Encoding.ASCII.GetString(RecvBytes, 0, RecvBytes.Length);


                RecvBytes = new byte[4096];

            }
            catch (Exception ex)
            {
                raiseException.write(new string[] { "onDataReceive " + ex.Message });               
            }
            finally
            {
                client = null;
                ar.AsyncWaitHandle.Close();
                ar = null;
                
                // Event für Empfang neu zuordnen
                s.BeginReceive(RecvBytes, 0, RecvBytes.Length, SocketFlags.Peek, new AsyncCallback(onDataReceive), s);                
            }
        }


Soweit ganz gut und funktioniert auch mit einem Scanner.
Jedoch sobald ich einen 2. Scanner mit einer anderen IP Adresse und gleichen Port ansprechen möchte reagiert der 1. und der 2. nur noch sproadisch auf mein DataReceive-Ereignis.

Einen 2. Dienst habe ich inzwischen nur noch aus Verzweiflung geschrieben um die beiden Scanner komplett zu trennen.

Was mach ich falsch ?

2.298 Beiträge seit 2010
vor 9 Jahren

Ich bin jetzt nicht sicher ob ichs in deinem Code nur übersehen habe, aber erstellst du auch für beide Scanner jeweils einen Socket?

Bisher entnehme ich deinem Code nämlich nur einen Socket auf dem du horchst.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

R
Raorkon Themenstarter:in
9 Beiträge seit 2009
vor 9 Jahren

im 2. Programm habe ich den gleichen Code nur mit einer anderen IP

2.298 Beiträge seit 2010
vor 9 Jahren

Mir ging es jetzt aber um dein Hauptproblem. Denn dein erstes Ziel war ja, beide Scanner im gleichen Dienst anzusprechen.

Wie äußerst sich das ganze denn, dass es nur sporadisch funktioniert?

// EDIT: Funktioniert es denn in 2 getrennten Diensten?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

R
Raorkon Themenstarter:in
9 Beiträge seit 2009
vor 9 Jahren

Hallo das Hauptproblem ist, dass Daten des Scanner über die Socketverbindung nicht empfange,
sobald ich den 2. Scanner anschliesse. Sporadisch heißt ich kann dieses Verhalten nicht provozieren, sondern muss immer warten bis der Fall wieder auftritt.

Statistisch wird 1 von 3 Scans nicht übertragen und ich weiß nicht warum. Wenn ich mir per Telnet eine Socketverbindung aufbaue kann ich alle Scans sehen, d.h. es geht nichts verloren.

Habe ich ein Fehler im Programmcode bzw. in den Parametern?

W
872 Beiträge seit 2005
vor 9 Jahren

Ich würde Deinen Code mal so ändern, daß Du die Parameter IP-Adresse und Port in den Konstruktor für die Klasse übernimmst und dann mit zwei Instanzen arbeitest.

M
171 Beiträge seit 2012
vor 9 Jahren

Und vor allem jeden Scanner in einem eigenen Thread abhören. Nicht, dass ein Paket verloren geht, weil Du zum Zeitpunkt des Eintreffens gerade mit dem anderen Scanner beschäftigt bist.

R
Raorkon Themenstarter:in
9 Beiträge seit 2009
vor 9 Jahren

ich hatte in der ursprünglichen Version 2 Threads aufgebaut und habe dann aufgrund der Probleme mit dern verlorenen Daten das in 2 eigene Programme ausgelagert.

R
Raorkon Themenstarter:in
9 Beiträge seit 2009
vor 9 Jahren

so nun habe ich eine stabile Verbindung geschafft.

recht einfach, leider kann ich mir es mir aber nicht ganz erklären:

ich habe statt


        private static void onDataReceive(IAsyncResult ar)
        {
            Socket client = null;
            try
            {

                client = (Socket)ar.AsyncState;

                client.Receive(RecvBytes, RecvBytes.Length, 0);
...

...

folgendes geändert:


        private static void onDataReceive(IAsyncResult ar)
        {
            Socket client = null;
            try
            {

                client = (Socket)ar.AsyncState;

                client.Receive(RecvBytes);
...

das heißt ich lege einerseits die Länge des Datenpakets nicht fest, das kann ich noch nachvollziehen.

Jedoch das State-Flag habe ich nicht verstanden bzw. dessen Auswirkung kann ich nicht nachvollziehen. (Google habe ich auch schon bemüht)

Thx an die Helfer, vlt. kann mir jemand noch sagen was das Stateflag für Auswirkungen hat.

16.835 Beiträge seit 2008
vor 9 Jahren

Was meinst Du mit State-Flag?
Redest Du von AsyncState ?

Das hat nichts mit Status zutun oder ähnliches, das ist einfach der Socket, zu dem das Event gehört.
Du kannst ja beliebig viele Quellen auf ein Eventhandler ansetzen. Und damit Du eben weißt, welcher das ist, steck das in AsyncState drin.

Du hast Dich ja hier für einen asynchronen Socket entschieden, der bereits Threads nutzt. Bei einem synchronen Socket hättest Du das alles selbst übernehmen müssen.

Du lernst da wirklich am meisten, wenn Du nicht (nur) rum probierst sondern Dir auch mal die Beispiele von Microsoft rein ziehst.
Dann am besten den Debugger nutzen, damit Du den Workflow verstehst. Du kannst da ja dann super nachvollziehen, was in welcher Reihenfolge passiert.
Multi-Threading ist halt schon ein Level höher 😉