Laden...

Forenbeiträge von MeisterM Ingesamt 17 Beiträge

23.02.2017 - 15:24 Uhr

Hallo Leute,

ich benötige mal Fachwissen im Bereich TLS / Zertifikate.

Und zwar baue ich eine Verbindung zu einem TLS Server auf. Dies klappt auch bei den meisten Servern.
Nun habe ich einen Server der bricht den TLS Handshake ab, nachdem ich das Client Zertifikat gesendet habe. Hierbei ist nicht das Client Zertifikat an sich das Problem, sondern dass mein .Net Client mit der SSLStream Klasse im TLS Handshake nur das Client Zertifikat, aber nicht das zugehörige Root Zertifikat mit überträgt. Dies erwartet der Remote Server jedoch.

Andere Tests mit Linuxservern oder z.B. einem Python Script haben ergeben, dass diese immer das CA Zertifikat mit übertragen. (Durch entsprechende Wireshark Mitschnitte analysiert)

Handshake Beispiel ohne CA Zertifikat (Schlägt fehl, .Net sslstream)


Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Multiple Handshake Messages
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 2064
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 1470
            Certificates Length: 1467
            Certificates (1467 bytes)
                Certificate Length: 1464
                Certificate: 308205b43082039ca003020102020107300d06092a864886... (pkcs-9-at-emailAddress=***,id-at-commonName=***,id-at-organizationalUnitName=***,id-at-organizationName=***,id-at-localityName=Frankfurt,id-at-state

Handshake Beispiel mit CA Zertifikat (Klappt wunderbar, Python Script)


Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Certificate
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 2968
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 2964
            Certificates Length: 2961
            Certificates (2961 bytes)
                Certificate Length: 1464
                Certificate: 308205b43082039ca003020102020107300d06092a864886... (pkcs-9-at-emailAddress=***,id-at-commonName=***,id-at-organizationalUnitName=***,id-at-organizationName=***,id-at-localityName=Frankfurt,id-at-state
                Certificate Length: 1491
                Certificate: 308205cf308203b7a003020102020101300d06092a864886... (pkcs-9-at-emailAddress=***,id-at-commonName=***,id-at-organizationalUnitName=***,id-at-organizationName=***,id-at-localityNa

Ich übergebe in der AuthenticateAsClient Methode eine X509Certificate2Collection, die auch aus der P12 Datei importiert habe. Diese P12 Datei enthält das eigene Zertifikat, den Schlüssel für das eigene Zertifikat und das CA Zertifikat. Es ist also alles vorhanden und an den SSL Stream übergeben.

Gibt es hier Experten in dieser Tiefe?

Gruß
MeisterM

17.01.2015 - 13:09 Uhr

Hallo Leute,

ich habe eine konzeptionelle Frage. Und zwar habe ich eine Reihe von Viewmodels, die grafische Elemente widerspiegeln sollen wie z.B. Rectangle, Ellipse, Line, Polyline und Polygon.
Diese sollen durch den Anwender frei gezeichnet werden dürfen.

Mein erster Ansatz:
Ein ItemsControl dass ein Canvas als ItemsPanel enthält. An dieses werden meine ViewModels gebunden und mittels DataTemplate der Style für die grafische Darstellung festgelegt. Mittels Canvas.Left und Canvas.Top auf dem ContentPresenter, der ja um die Elemente gewrappt wird, positioniere ich die Elemente auf dem Canvas.

Nun möchte ich einen Adorner auf das selektierte Element legen, um dieses verschieben zu können. Leider klappt das z.B. bei der Linie nicht, da durch verschieben der Start und Endpunkte der ContentPresenter die Größe nicht mit ändert. Ändere ich die Größe per Hand wird auch die Linie innerhalb des ContentPresenters verschoben.

Hier ist mein Canvas:

<ItemsControl ItemsSource="{Binding GraphicElements}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <c:DesignerCanvas MinHeight="800" MinWidth="800" Background="White" AllowDrop="True" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.Resources>
                <DataTemplate DataType="{x:Type vm:GraphicLine}">
                    <Line Stroke="Black" X1="{Binding Start.X}" X2="{Binding Ende.X}" Y1="{Binding Start.Y}" Y2="{Binding Ende.Y}" />
                </DataTemplate>
                <DataTemplate DataType="{x:Type vm:GraphicRectangle}">
                    <Rectangle Fill="Black" Height="{Binding Rect.Height}" Width="{Binding Rect.Width}" />
                </DataTemplate>
            </ItemsControl.Resources>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Left" Value="{Binding Rect.Left}" />
                    <Setter Property="Canvas.Top" Value="{Binding Rect.Top}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>

Hier ist mein Adorner:

class ResizingAdornerLine: Adorner
    {
        // Resizing adorner uses Thumbs for visual elements.  
        // The Thumbs have built-in mouse input handling.
        Thumb thumbX1, thumbX2;

        // To store and manage the adorner's visual children.
        VisualCollection visualChildren;

        // Initialize the ResizingAdorner.
        public ResizingAdornerLine(Line adornedElement)
            : base(adornedElement)
        {
            visualChildren = new VisualCollection(this);

            // Call a helper method to initialize the Thumbs
            // with a customized cursors.
            BuildAdornerCorner(ref thumbX1, Cursors.SizeAll);
            BuildAdornerCorner(ref thumbX2, Cursors.SizeAll);

            // Add handlers for resizing.
            thumbX1.DragDelta += new DragDeltaEventHandler(HandleX1);
            thumbX2.DragDelta += new DragDeltaEventHandler(HandleX2);
            //topLeft.DragDelta += new DragDeltaEventHandler(HandleTopLeft);
            //topRight.DragDelta += new DragDeltaEventHandler(HandleTopRight);
        }

        // Handler for resizing from the bottom-right.
        void HandleX1(object sender, DragDeltaEventArgs args)
        {
            FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
            Thumb hitThumb = sender as Thumb;

            if (adornedElement == null || hitThumb == null) return;
            FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;

            // Ensure that the Width and Height are properly initialized after the resize.
            EnforceSize(adornedElement);

            Line line = (Line)adornedElement;
            line.X1 = line.X1 + args.HorizontalChange;
            line.Y1 = line.Y1 + args.VerticalChange;
        }

        // Handler for resizing from the top-right.
        void HandleX2(object sender, DragDeltaEventArgs args)
        {
            FrameworkElement adornedElement = this.AdornedElement as FrameworkElement;
            Thumb hitThumb = sender as Thumb;

            if (adornedElement == null || hitThumb == null) return;
            FrameworkElement parentElement = adornedElement.Parent as FrameworkElement;

            // Ensure that the Width and Height are properly initialized after the resize.
            EnforceSize(adornedElement);

            Line line = (Line)adornedElement;
            line.X2 = line.X2 + args.HorizontalChange;
            line.Y2 = line.Y2 + args.VerticalChange;

        }
        
        // Arrange the Adorners.
        protected override Size ArrangeOverride(Size finalSize)
        {

            Line selectedLine = (Line)AdornedElement;

            double left = Math.Min(selectedLine.X1, selectedLine.X2);
            double top = Math.Min(selectedLine.Y1, selectedLine.Y2);

            var startRect = new Rect(selectedLine.X1 - (thumbX1.Width / 2), selectedLine.Y1 - (thumbX1.Width / 2), thumbX1.Width, thumbX1.Height);
            thumbX1.Arrange(startRect);

            var endRect = new Rect(selectedLine.X2 - (thumbX2.Width / 2), selectedLine.Y2 - (thumbX2.Height / 2), thumbX2.Width, thumbX2.Height);
            thumbX2.Arrange(endRect);

            // Return the final size.
            return finalSize;
        }

        // Helper method to instantiate the corner Thumbs, set the Cursor property, 
        // set some appearance properties, and add the elements to the visual tree.
        void BuildAdornerCorner(ref Thumb cornerThumb, Cursor customizedCursor)
        {
            if (cornerThumb != null) return;

            cornerThumb = new Thumb();

            // Set some arbitrary visual characteristics.
            cornerThumb.Cursor = customizedCursor;
            cornerThumb.Height = cornerThumb.Width = 10;
            cornerThumb.Opacity = 0.40;
            cornerThumb.Background = new SolidColorBrush(Colors.MediumBlue);

            visualChildren.Add(cornerThumb);
        }

        // This method ensures that the Widths and Heights are initialized.  Sizing to content produces
        // Width and Height values of Double.NaN.  Because this Adorner explicitly resizes, the Width and Height
        // need to be set first.  It also sets the maximum size of the adorned element.
        void EnforceSize(FrameworkElement adornedElement)
        {
            Line selectedLine = (Line)AdornedElement;

            if (adornedElement.Width.Equals(Double.NaN))
                adornedElement.Width = Math.Max(selectedLine.X1, selectedLine.X2);
            if (adornedElement.Height.Equals(Double.NaN))
                adornedElement.Height = Math.Max(selectedLine.Y1, selectedLine.Y2);


            FrameworkElement parent = VisualTreeHelper.GetParent(AdornedElement) as FrameworkElement; 

            if (parent != null)
            {
                parent.Width = Math.Max(selectedLine.X1, selectedLine.X2);
                parent.Height = Math.Max(selectedLine.Y1, selectedLine.Y2);
            }
        }
        // Override the VisualChildrenCount and GetVisualChild properties to interface with 
        // the adorner's visual collection.
        protected override int VisualChildrenCount { get { return visualChildren.Count; } }
        protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
    }

Habt ihr einen anderen Ansatz, wie ich direkt mit den Grafikobjekten, ohne ContentPresenter, arbeiten könnte?

Gruß
Meister

18.11.2014 - 14:32 Uhr

Hallo Leute,

ich möchte mir einen RTP Mixer bauen, der eingehende RTP Streams empfängt, zusammenfügt und wieder weitersendet.

Dabei stehe ich nun vor dem Problem, die eingehenden Streams zu synchronisieren und eine Art Jitter Buffer einzubauen, um unterschiedliche Paketlaufzeiten im Netzwerk auszugleichen. Hat da jemand eine Idee wie das umgesetzt werden kann?
Für die Sortierung und Synchronisierung steht ja das SequenceNumber Feld sowie das Timestamp Feld (Enthält immer eine hochlaufende Zahl die die Anzahl an Samples seit dem letzten Paket übergibt. Startwert ist zufällig)

Meine Fragen sind jetzt:*Welche Datenstruktur ist für die Sortierung der Pakete sinnvoll? *Wie wartet man auf weitere Pakete? (Jitter) (Timer laufen lassen, alle x ms prüfen ob das Paket letztePaketnummer+1 vorhanden ist, wenn nicht leeres Paket weitergeben?) *Wie bekommt man das mit den Überläufen der Timestamp und SequenceNumber Felder in den Griff? Die laufen ja irgendwann wieder bei 0 los.

06.02.2014 - 10:45 Uhr

Hallo Leute,

ist es mit C# möglich einen TAPI Treiber zu erstellen. Also eine eigene "Line" in Windows zu registrieren um dann bei Anwahl durch eine TAPI nutzende Applikation bestimmte Dinge tun zu können?

Wenn ihr eine Idee habt wie so etwas gehen könnte, wäre ich dankbar.

Gruß
MeisterM

28.09.2013 - 12:21 Uhr

Hallo Leute,

ich grübel derzeit über ein Konzept um Daten zwischen verschiedenen Mesh Nodes (Wifi Tablets) innerhalb eines Wifi Meshs zu synchronisieren. Die Geräte sind dabei so verbunden, dass sie bereits auf Netzwerkebene über das Meshnetzwerk mit allen Knoten (also nicht nur den direkten Nachbarn) kommunizieren können.

In meiner Anwendung machen sich dann alle Peers über Broadcasts miteinander bekannt. Dies ist kein weiteres Problem. Meine Anwendung soll nun aber einen Datenspeicher enthalten, der über alle Nodes synchronisiert wird. D.h. kommt ein neuer Node dazu erhält er direkt die aktuellen Daten. Verschwindet ein Node und macht Änderungen müssen diese beim Wiedereintritt in das Mesh mit allen anderen abgeglichen werden. Dies ist jetzt leider nicht mehr so trivial und ich bin an der Überlegung wie der Nachrichtenfluss aussehen könnte.

Die Datenstruktur soll eine UniqueID (GUID) sowie ein Objekt enthalten (Hashtable). Der Inhalt des Objekts ist immer das, was zuletzt geschrieben wurde. (Also hier dann zusätzlich noch den Timestamp der letzten Änderung) Gelöschte Objekte müssen natürlich auch auf allen Nodes gelöscht werden.

Ich habe mir jetzt einige Dinge angeschaut und überlegt weiß aber bei manchen Themen nicht weiter:

  • Wenn ein Node betritt, mit wem synchronisiert er sich? Schickt er ein Broadcast mit z.B. einem Hash seiner aktuellen Daten und die Gegenstellen antworten, wenn sie einen anderen Wert haben? Wer sendet dann die aktuellen Daten? Sollte es dann in jedem Teil-Mesh einen Master geben?
  • Wie werden gelöschte Daten mitgeteilt? Müssen alle Nodes eine History vorhalten um auch den Zeitpunkt der Löschung an alle übertragen zu können? Denn ein nicht vorhandener Eintrag (UniqueID) bei einem Peer muss ja nicht bedeuten, dass der Eintrag gelöscht wurde, sondern kann ja auch bedeuten dass der Eintrag neu ist.

Habt ihr schonmal versucht so etwas zu Implementieren?
Welchen Ansatz würdet ihr weiterverfolgen?

Viele Grüße
MeisterM

21.02.2013 - 12:17 Uhr

Also nur mit recht komplexen Möglichkeiten. Aber es funktioniert!

Super, Danke!!

21.02.2013 - 11:44 Uhr

Hallo Leute,

ich arbeite mich derzeit in das MVVM Konzept ein. Dabei habe ich mir nun eine ListView erstellt und fülle diese mittels einer ObservableCollection mit meinen ModelView Instanzen.

Nun möchte ich ein ICommand des ModelViews bei Doppelklick ausführen. Ich habe es jedoch bisher nicht geschafft, das Binding in XAML umzusetzen.
Der Umweg über das SelectedItem und dem Doppelklick Event der Listview führt leider dazu, dass der ICommand nur ausgeführt wird, wenn man einen Doppelklick auf einen freien Teil der Listview (Also auf kein Item) macht.

Auch Google konnte da bisher nicht wirklich weiterhelfen. Ist das so kompliziert, dass sich das überhaupt noch lohnt?

Gruß
Holger

10.01.2013 - 09:40 Uhr

Hallo Leute,

ich bräuchte mal wieder eure Hilfe.

Und zwar habe ich folgendes vor:

Ein Endgerät verfügt über WLAN und UMTS Verbindung zu einem Server. (Also einmal LAN einmal WAN) Nun möchte ich Nachrichten mit dem Server austauschen. Dies sollte am Besten in der Form einer MessageQueue geschehen.

Anforderung ist nun: Das Endgerät versucht grundsätzlich über WLAN eine Verbindung zum Server herzustellen (interne IP) und darüber die Nachrichten auszutauschen. Schlägt dies fehl, soll immer die WAN Verbindung verwendet werden.
Zusätzlich müssten die Nachrichten priorisiert werden können, sodass wichtige Nachrichten vor unwichtigen übertragen werden und sogar unwichtige Nachrichten gar nicht übertragen werden, wenn die WAN Verbindung genutzt wird.

Kann man für diesen Anwendungszweck ein fertiges MQ Framework verwenden oder ist da handarbeit angesagt?

Viele Grüße

25.09.2012 - 18:36 Uhr

Hallo Leute,

ich suche nach einem Panel, welches den (gleichgroßen) Inhalt zentriert darstellt und automatisch versucht, die Zeilen und Spalten gleich zu füllen.
Zusätzlich soll die Größe der Elemente, je mehr Platz noch zur Verfügung steht vergrößert bzw. je weniger, verkleinert werden. Bis auf die jeweilige Min und Max Height/Width Angaben.

Im Anhang habe ich eine Skizze gemacht, die die Aufteilung verdeutlichen soll. Die Größenänderung ist dort jedoch noch nicht berücksichtigt.

Gibt es solche Panel? Wenn nein, wie kann man so etwas hin bekommen? Das hier habe ich bereits gelesen: WPF Tutorial - Creating A Custom Panel Control ist für den Anfang aber recht kompliziert...

06.08.2012 - 11:49 Uhr

Alles klar. Und wie kann ich die selbst gebastelten Klassen wieder zurück führen in ein Entity Objekt um die neuen Werte zu speichern? Oder muss ich dass dann mit einem eigenen Mapper wieder zurück führen und eine entsprechende Add, Update, Remove Funktionalität einbauen und habe somit die Vorteile von EF wieder verspielt?

Es geht nicht um eine WebAPI sondern um eine WCF TCPBinding Verbindung zwischen meinem eigenen Server und meinem eigenen Client.

Die Frage war jetzt wenn ich eigene Klassen verwendee kann ich ja wohl mit

IQueryable<EmittelEinsatz> x = from c in REVServer.Env.DBContext.EinsatzmittelImEinsatzMenge
                                                   where c.Einsatz.ID == EinsatzID
                                                   select new EmittelEinsatz {
                                                       ID = c.ID ,
                                                       ZeitAlarm = c.ZeitAlarm,
                                                       ZeitDispo = c.ZeitDispo                                                   };

´
ein Objekt vom Typ EMittelEinsatz direkt mit den Werten befüllen. Nun besteht aber die Entity EinsatzmittelImEinsatz noch aus einem weiteren Feld StatusZeit. Dies ist ein Array von weiteren Entities. Wie kann ich nun dieses Array in eine weitere, extra dafür angelegte Klasse füllen?

Also irgendwie etwas wie:

select new EmittelEinsatz {
                                                       ID = c.ID ,
                                                       ZeitAlarm = c.ZeitAlarm,
                                                       ZeitDispo = c.ZeitDispo,
StatusZeit[] = new StatusZeiten {
Zeit = c.StatusZeit.Zeit,
Manuell = c.StatusZeit.Manuell
}                                                   };

05.08.2012 - 23:04 Uhr

Ja das ist ja wunderbar.

Laut dem vorherigen Post sollte TableEntity als Klasse sowohl für die "neue" Klasse als auch als Typenidentifier für die zu lesende Entity verwendet werden, daher habe ich das in meinem Beispiel auch so gemacht. Entsprechend war dies dann eine Klasse und keine Variable.

Kann ich mir auch eine Klasse bauen die eine Liste von Unterklassen enthält die wieder rum mit Daten aus der Entity gefüllt werden?

PS: Ziel des ganzen ist es, den Traffic der durch den Transfer der Entity Klassen über WCF generiert wird zu minimieren.

Problematisch sind hier dann nämlich DataEntities die wiederrum Verweise auf große andere Entities enthalten. Diese würde ich dann gerne einfach beim Abrufen ausschließen.

Habe nun herausgefunden, dass man LazyLoading deaktivieren muss und dann kann man per Hand bestimmen welche Abhängigkeiten mit geladen werden.

05.08.2012 - 15:40 Uhr

Nein ich schreibe keine Extension Method, sondern führe einfach die Methode aus um die Objekte dafür zu erhalten.

        public List<EinsatzmittelImEinsatz> Einsatz_GetEinsatzmittel(Int64 EinsatzID)
        {
            IQueryable<EinsatzmittelImEinsatz> x = from EinsatzmittelImEinsatz c in REVServer.Env.DBContext.EinsatzmittelImEinsatzMenge
                                                   where c.Einsatz.ID == EinsatzID
                                                   select new EinsatzmittelImEinsatz{
                                                       ID = c.ID ,
                                                       ZeitAlarm = c.ZeitAlarm,
                                                       ZeitDispo = c.ZeitDispo,                                                       
                                                       StatusZeit = c.StatusZeit
                                                   };

            return x.ToList<EinsatzmittelImEinsatz>();
        }

Die Fehlermeldung wird erst zur Ausführzeit geworfen.

05.08.2012 - 15:13 Uhr

Das wäre natürlich die super Lösung. Allerdings erhalte ich bei folgendem Code:


            IQueryable<EinsatzmittelImEinsatz> x = from EinsatzmittelImEinsatz c in REVServer.Env.DBContext.EinsatzmittelImEinsatzMenge
                                                   where c.Einsatz.ID == EinsatzID
                                                   select new EinsatzmittelImEinsatz{
                                                       ID = c.ID ,
                                                       ZeitAlarm = c.ZeitAlarm,
                                                       ZeitDispo = c.ZeitDispo,
                                                   
                                                       StatusZeit = c.StatusZeit
                                                   };

            return x.ToList<EinsatzmittelImEinsatz>();

Kommt die folgende Meldung:

Fehlermeldung:
Die Entität bzw. der komplexe Typ 'DataModel.EinsatzmittelImEinsatz' kann nicht in einer 'LINQ to Entities'-Abfrage konstruiert werden.

Eine Idee? Muss noch etwas eingestellt werden?

05.08.2012 - 13:34 Uhr

verwendetes Datenbanksystem: PostgreSQL 9.1

Hi Leute,

ich verwendet EntityFramework 4.1 und stehe nun vor einem "Problem": Ich lade die Objekte und verschicke Sie mit WCF an den Client. Nun habe ich recht Komplexe Objekte mit vielen Verknüpfungen. Von denen ich aber nur eine Teilmenge an Eigenschaften bei der Übertragung benötige.

Wie kann ich es realisieren, nur bestimmte Eigenschaften zu laden. Oder muss ich dafür neue Objekte anlegen die auf die gleichen Felder gemappt sind? Ich benutze das Model-First Prinzip.

Gruß
Holger

18.07.2012 - 22:19 Uhr

Alles klar, dann weiß ich Bescheid, bis auf:

Ist mit dem obigen Vorschlag gar nicht nötig, da es ja nur um die Referenz geht. Diese wird von den gängigen O/R-Mappern* automatisch beim SaveChanges (od. wie die Methode heißen mag) gepflegt.

Was das ist kann ich mir grob vorstellen, gibt es da bereits etwas auf .Net?
Der nimmt also die Daten des Objekts und schreibt bzw. liest diese von der Datenbank. Und der schafft dann auch Änderungen in der Datenbank mitzubekommen oder muss ich das dann noch irgendwie triggern. Also z.B. nach dem Aufruf der Methode "AddFahrzeugToEinsatz" muss ja das Einsatzobjekt neu geladen werden bzw. ein weiteres Fahrzeug in die Liste "Einsatz.Fahrzeuge" eingefügt werden.

Gruß und danke für die Antworten
MeisterM

18.07.2012 - 20:38 Uhr

Super, vielen Dank für deine Antwort. Die WCF Dataservices sind nicht ganz das was ich mir vorgestellt habe.
Habe nun mal einen WCF Duplex Service mit TCPBinding erstellt und habe so eine Serviceklasse, dessen Methoden ich aufrufen und umgekehrt Events auslösen kann. Soweit so gut.

Ich könnte jetzt also in meinem Beispiel die Klasse Einsatz erstellen mit x Attributfeldern (Einsatznummer, Datum, Uhrzeit, Adresse...) und kann diese dann wie auch immer in die Datenbank speichern und lesen. Und diese Klasse kann ich dann per WCF an die Clients senden.
Methoden lassen sich in den Klassen allerdings nicht mit versenden sodass sie dann auf dem Server aufgerufen werden. (Das wäre ja die Krönung 😉 )
Also muss ich das über die Methoden der Serviceklasse machen. Wie ist da die Empfehlung. Mehrere Serviceklassen und somit auch mehrere Services erstellen, oder eine Serviceklasse die dann verschiedene Unterklassen instanziert die dann die notwendigen Funktionen bereitstellen. z.B.:
MyService.AddFahrzeugToEinsatz(Einsatz e, Fahrzeug f) oder eine Unterklasse MyService.Einsatzhandler.AddFahrzeug(Einsatz e, Fahrzeug f). Diese Methode müsste ja dann die Klasse Einsatz die lokal im Server gespeichert ist (wurde ja vorher an den Client übertragen) raussuchen und dort die entsprechende Funktion in dem Businessobjekt aufrufen? Soweit so kompliziert, oder gehts auch einfacher?

Gruß
MeisterM

PS: Wenn man lieber die generic Collections nehmen soll, wo ich dir definitiv zustimme, dann ist das HashSet die Alternative zur Hashtable?

18.07.2012 - 15:14 Uhr

Hi Leute,

ich bräuchte mal ein paar Ratschläge zum Thema Architektur von einem verteilten System.
Ich habe noch nicht all zu viel mit WCF gemacht daher ein paar Fragen:

Ich möchte mittels TCP Verbindung eine WCF Session zu einem Server aufbauen. Dort sollten Methoden aufgerufen werden können als auch Events vom Server ausgelöst. Entsprechend sollen dann auch Objekte übertragen werden, dessen Daten der Server aus einer angeschlossenen Datenbank holt.

Angenommen es existiert eine Tabelle "Einsatz" mit mehreren Zeilen. Für jede der Zeile soll ein Business Objekt angelegt und an den Client gesendet werden. Der Client hält diese Objekte dann in z.B. einer Hashtable vor. Wird nun ein Attribut geändert, soll diese Änderungen an den Server zurück gesendet werden, damit dieser die Änderung in die Datenbank schreibt und die anderen Clients darüber informiert.

Wie macht man das am geschicktesten? Sendet man das gesamte BusinessObjekt zurück an den Server auch wenn sich nur ein Attribut geändert hat?
Muss man für jedes Attribut auf dem Server eine Methode anlegen, die dann bei einer Änderung aufgerufen wird und der Server dann wiederrum Events bei den Clients für den Aktualisierungsvorgang aufruft?

Oder kann ich irgendwie Änderungen an den Objekten automatisch dem Server mitteilen und der wiederrum diese Änderungen direkt im Objekt bei den anderen Clients aktualisiert? Oder müsste das alles selbsständig implementiert werden und der Server übergibt nur die ID des geänderten Objekts und der Client müsste dies dann neu anfordern wenn er es benötigt.

Was würdet ihr für diese Aufgabenstellung verwenden?

PS: Derzeit verwendet jeder Client eine direkte Datenbankanbindung und schickt TCP Nachrichten (ASCII) und daraufhin lädt der Client die Daten dann neu aus der Datenbank. Dies ist natürlich nicht sehr sauber und deshalb will ich nun hin zu BusinessObjects.

Viele Grüße
MeisterM