Laden...

Auto Reconnect TcpClient

Erstellt von ratalert vor 12 Jahren Letzter Beitrag vor 12 Jahren 8.080 Views
R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren
Auto Reconnect TcpClient

Hallo zusammen,

wie ist der beste Weg eine automatische Reconnect Funktionalität bei einem TcpClient zu implementieren für den Fall dass die Verbindung abbricht (Netzwerkkabel gezogen, Server aus, etc)

Hier ein Aussschnitt aus meinem derzeigen code:


public void ClientWork()
{
        TcpClient client = new TcpClient();

        try
        {
            try
            {
                client.Connect(ip, port);
            }
            catch(Exception ex)
            {
                logger.ErrorFormat("client.Connect: {0}", ex.Message);
                return false;
            }

            NetworkStream ns = client.GetStream();
            byte[] buff;

            while (__bRunning)
            {
                buff = new byte[1000];
                ns.Read(buff, 0, 1000);

                string line = System.Text.Encoding.Default.GetString(buff);
                //tu was mit line...
            }

            //ns.Close();
            client.Close();
        }
        catch(Exception e)
        {
            //Reconnect?
            client.Close();
            client = null;

            return false;
        }
}

G
538 Beiträge seit 2008
vor 12 Jahren

Ein "normales" vorgehen wäre eventuell die Funktion mehrmals mit einem bestimmten Zeitabstand aufzurufen (Retrys + Maximum Retry Count).

Realisieren könntest du das ganze mit nem Timer der die Funktion wieder aufruft .. oder indem du die Funktion selbst wieder aufrufst ...

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren

ich hab mittlerweile nun was von polling gelesen. am besten in einem eigenen thread der immer wieder überpüft ob die verbindung noch am leben ist.

wir würde man das am besten realisieren?

L
53 Beiträge seit 2007
vor 12 Jahren

Der Punkt ist, dass es eine "abgebrochene Verbindung" in dem Sinne nicht gibt. Es gibt eher "Timeouts". Insofern wird bei den Protokollen, bei denen eine dauerhafte Verbindung gehalten werden muss in der Regel "IDLE"-Kommandos implementiert. Beim IRC z.B. der "PING"-Befehl, auf den der Server mit "PONG" antwortet.

Insofern sendet man dann alle X Minuten diesen Befehl - und wenn nicht innerhalb von X Sekunden eine Antwort bekommt, dann schließt man die Verbindung und baut die Verbindung neu auf.

Transparent - also so "nebenher" ohne dass die restliche Anwendung davon etwas mitbekommt - funktioniert das ganze nicht.

R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren

würdest du dann einen extra (zb workerthread) machen der alle offenen verbindungen "pingt" und wenn eine nicht antwortet nach 10 sek dann diese zumacht und neu öffnet?

4.221 Beiträge seit 2005
vor 12 Jahren

Im Prinzip muss man nicht mal eine Antwort von der Gegenstelle erhalten.

Wenn die Verbindung irgendwo unterbrochen ist, dann kann man genau einmal etwas ohne Fehler senden... beim nächsten Send gibts dann einen Laufzeitfehler.

Um bei Ping/Pong zu bleiben (kommt mir bekannt vor)...

  1. Ping ... läuft durch... keine Antwort (da Daten im Datennirvana gelandet).
  2. Ping ... ergibt auffangbare Exception.

Statt Ping kann man z.B: ein Ascii-Null oder irgendwas schicken (muss aber auf der Empfangsseite immer wieder rausgefriemelt werden)

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

Z
403 Beiträge seit 2007
vor 12 Jahren

Warum nicht eine Schicht tiefer gehen ?

Da braucht man keine ASCII zeichen.

Packete einfach in etwa so aufbauen:

1 Int32 => Size der nachfolgenden bytes
1 Byte => Packet ID
Byte[Size-1] => Rest

Durch die Packet ID kannst du dann z.b. entscheiden was es ist ob z.b. Chat, Ping, Pong oder was auch immer.

R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren

ich kann aber nicht entscheiden wie die pakete aussehen die ich empfange. darauf habe ich keinen einfluss...

L
53 Beiträge seit 2007
vor 12 Jahren

In dem Fall kannst du nur warten, ob du Exceptions bekommst und dann die Verbindung neu aufbauen. Das wird dann aber erst nach einem vom Betriebssystem definierten Zeitraum sein.

Oder wenn du nur empfängst musst du halt selber einen Timeout definieren.

Du kannst nicht "eine Verbindung anpingen" oder sowas.

R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren

bedeutet ich muss an die stelle die ich im codeausschnitt schon mit //Reconnect?? markiert habe?

würdet ihr dann eine Rekursion an der Stelle machen oder wie das Wiederverbinden lösen?

156 Beiträge seit 2010
vor 12 Jahren

Moin,


while(!ende)
{
    if (!connected)
    {
        connectUnit();
    } else {
        readData();
    }
}


private void readData()
{
    try {
        // Daten lesen
    } catch(Exception ex) {
        connected=false;
    }
}


private void connectUnit()
{
    try {
        // Verbindung aufbauen
        connected = true;
    } catch(Exception ex) {
        connected=false;
    }
}

R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren

und einfach so geht nicht?

public void ClientWork()
{
        TcpClient client = new TcpClient();

        try
        {
            try
            {
                client.Connect(ip, port);
            }
            catch(Exception ex)
            {
                logger.ErrorFormat("client.Connect: {0}", ex.Message);
                return false;
            }

            NetworkStream ns = client.GetStream();
            byte[] buff;

            while (__bRunning)
            {
                buff = new byte[1000];
                ns.Read(buff, 0, 1000);

                string line = System.Text.Encoding.Default.GetString(buff);
                //tu was mit line...
            }

            //ns.Close();
            client.Close();
        }
        catch(Exception e)
        {
            //Reconnect?
            client.Close();
            client = null;

            ClientWork();  <<----???

            return false;
        }
}
1.820 Beiträge seit 2005
vor 12 Jahren

Hallo!

@ratalert:
Wenn du dann aber ein größeres Netzwerk-Problem hast, kommst du ganz schnell an einen StackOverflow.

Nobody is perfect. I'm sad, i'm not nobody 🙁

R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren

vielleicht mit kurzem sleep dazwischen? irgendwie find ich nicht so die wirklich schöne lösung bei der ich nicht alles umbauen muss...

156 Beiträge seit 2010
vor 12 Jahren

vielleicht mit kurzem sleep dazwischen?

lies bitte was ein StackOverflow ist und wie er funktioniert bzw. ausgelöst wird ... dann überlege nochmal ob Dir ein schnödes Sleep wirklich hilft

irgendwie find ich nicht so die wirklich schöne lösung bei der ich nicht alles umbauen muss...

ist schon Mist wenn man nochmal von vorne anfangen muss um es richtig zu machen

4.221 Beiträge seit 2005
vor 12 Jahren

ist schon Mist wenn man nochmal von vorne anfangen muss um es richtig zu machen

Willkommen in der Wirklichkeit 😃

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

R
ratalert Themenstarter:in
22 Beiträge seit 2009
vor 12 Jahren

sehr ihr also keine lösung in meinen bestehenden code den reconnect noch einzubauen?
oder ihn so zu verändern dass ich ihn einbauen kann?

4.221 Beiträge seit 2005
vor 12 Jahren

sehr ihr also keine lösung in meinen bestehenden code den reconnect noch einzubauen?
oder ihn so zu verändern dass ich ihn einbauen kann?

Wieso ? Hat das jemand behauptet ?

Das kriegst Du schon selber hin 😃 Im Prinzip kannst Du entscheiden welchen Tod du sterben willst... (im Moment wirst Du früher oder später einen StackOverflow kriegen)... Du könntest es so ändern, dass du den Caller nicht mehr aus der Methode rauslässt wenn es nicht funktioniert hat (dann stirbst Du den "Meine App hängt-Tod")

Oder du machst es sauber und wirfst Exception und behandelst das Problem beim Aufrufer.

Das Optimum dürfte irgendwo dazwischen sein... wenn Du die Daten nicht versenden kannst, dann versuche 1 mal die Verbindung ab und neu aufzubauen... und wenn das nicht funzt, dann wirfst Du Exception und behandelst diese beim Caller (um ein Hang zu vermeiden).

Und bitte ein wenig mehr Eigeninitiative sonst machen die lieben Kollegen den Thread hier schneller zu als Du aus dem Stack rausfliegst.

[Edit] Wer noch mehr Schreibfehler findet darf sie behalten[/Edit]

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

U
1.688 Beiträge seit 2007
vor 12 Jahren

Hilfreich sind dabei sicherlich auch die asynchronen Methoden (Begin/EndConnect, Begin/EndRead, usw.)