Laden...

Status von Callback-Kanal prüfen (OperationContext.Current.GetCallbackChannel)

Erstellt von DonC vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.194 Views
D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren
Status von Callback-Kanal prüfen (OperationContext.Current.GetCallbackChannel)

Hi Leutz,

ich habe eine Client-Server-Anwendung mit WCF geschrieben, bei der sich die Clients mit ihrem Callback-Kanal beim Server registrieren und später wieder abmelden. Sinn der Sache ist, dass wenn ein Client eine Nachricht an den Server sendet, alle anderen Clients diese Nachricht auch erhalten sollen. Wenn ein Client also eine Nachricht an den Server sendet, geht dieser eine ArrayList mit den gespeicherten Callback-Kanälen der anderen Clients durch und schickt an jeden Client die Nachricht. Den Callback-Kanal, welcher auch in meiner ArrayList gespeichert wird, ermittel ich mit der "OperationContext.Current.GetCallbackChannel"-Funktion.

Folgendes Problem tritt nun aber auf: Normalerweise meldet sich ein beim Server registrierter Client über eine Funktion ab, wenn er geschlossen wird. Dann wird einfach sein Callback-Kanal aus der ArrayList entfernt und gut ist. Wenn eine Client-Applikation jedoch abstürzt und sich somit nicht beim Server abmelden kann, "denkt" der Server weiterhin, der Callback-Kanal ist offen und versucht, die Nachrichten dorthin zu schicken. Das funktioniert natürlich nicht und der Server raucht beim Versuch, die Nachricht zu senden, ab.

Lange Rede, kurzer Sinn: Ich suche eine einfache Möglichkeit zu prüfen, ob ein mit der Funktion "OperationContext.Current.GetCallbackChannel" ermittelter Callback-Kanal noch offen ist.

Wäre super wenn Ihr mir da helfen könntet 😃

Gruß,
Chris

2.223 Beiträge seit 2005
vor 13 Jahren

Hallo DonC,

genau vor dieser Frage stehe ich aktuell auch, da ich selber bisher noch keine bessere Lösung gefunden habe, sende ich aktuell anhand eines Timers, in regelmäßigen abständen eine Art IsAlive Packet (sowohl der Client, als auch der Server senden dieses Paket) das ganze ist natürlich mit einem Try Catch umgeben.
Sobald der Timeout greift, wird vom Client eine Reconnect Timer gestartet.
Dieser Reconnect Timer sorgt dafür, dass die Verbindung dann immer wieder versucht wird herzustellen.

Der Server löscht den betreffenden Client, einfach aus seiner Liste heraus.

Viele Grüße
Lars

D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren

Hi Lars,

vielen Dank für Deine Antwort. Das mit dem Timer ist natürlich ein Ansatz. Allerdings sendet bei mir der Server mitunter mehrmals pro Sekunde Nachrichten an die Clients. Der Abstand der IsAlive-Packages müsste daher bei mir extrem kurz sein, wodurch das ganze dann nicht mehr wirklich Sinn macht. Ich bräuchte daher wirklich eine Lösung mit der der Server den Status der Callback-Känale direkt checken kann. Kann mir fast nicht vorstellen, dass es da keine Funktion für geben soll.

Gruß,
Chris

D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren

Gerade bin ich vielleicht fündig geworden. Habe auf eine Website gerade folgenden Codeausschnitt gefunden:


subscribers.ForEach(delegate(IMessageCallback callback)
    {
        if (((ICommunicationObject)callback).State == CommunicationState.Opened)
        {
            callback.OnMessageAdded(message, DateTime.Now);
        }
        else
        {
            subscribers.Remove(callback);
        }
    });

Offenbar kann man einen Callback-Kanal über die "State"-Eigenschaft prüfen. Habe es selbst noch nicht ausprobiert, werde das aber gleich morgen machen.

@Lars: Vielleicht hilft Dir das ja auch weiter 😉

Gruß,
Chris

S
8.746 Beiträge seit 2005
vor 13 Jahren

Das kannst du knicken. Alles was TCP benutzt, erkennt Abbrüche immer nur dann, wenn Daten zum Empfänger gehen. Wenn TCP keine Bestätigung auf ein Paket bekommt, dann wird wiederholt. Das kann bis zu einer Minite dauern. Erst dann wird die Verbindung als abgebrochen erkannt. Bei Abstürzen sorgt normalerweise die Laufzeitumgebung bzw. das BS für den regulären Abbau des Sockets. Wenn du aber z.B. einen mobilen Client hast, der schlicht seine Verbindung zum Netzwerk verliert, dann ist Essig.

"Sicher" ist so ein Verfahren also grundsätzlich nicht. KeepAlive ist die einzige Rettung. Oder eben gleich davon ausgehen, dass die Verbindung nicht zuverlässig ist.

D
DonC Themenstarter:in
30 Beiträge seit 2007
vor 13 Jahren

@Svenson: Jau, hab mittlerweile auch mitbekommen, dass das nicht funzt 😦

Naja, hab jetzt den Timeout auf 2 Sekunden eingestellt, danach wird der Kanal geshreddert. Das funzt jetzt soweit ganz gut, wobei die Lösung, wie Du ja bereits angemerkt hast, nicht wirklich elegant ist.