Laden...

Forenbeiträge von mutzel Ingesamt 40 Beiträge

09.07.2008 - 16:54 Uhr

Du machst es mir irgendwie nicht leicht, oder ich drück mich irgendwie nicht richtig aus, aber ich geb nicht locker 😉

Du mir aber auch nicht 😁 .. ich glaub je mehr wir schreiben desto weniger versteh wir was der andere will.

Ja das ist richtig, solltest Du aber zuvor eine Serialisierung selbst vornehmen, dann wird das serialisierte Objekt durch den WebService nochmals über XML-Serialisierung in ein SOAP Format gebracht.

Genau das will ich ja nicht machen. Also ich will schon die WebService Technik nutzen so wie sie ist.

Na hoffentlich doch nicht. Du erstellst doch das Objekt folgendermaßen:

new MyList() { List = new string[] { "Test1", "Test2", "muh" } }  

Ich meinte ich erstelle das Objekt nicht auf der Client-Seite. Das macht ja der WebService intern.

Es liegt also in Deiner Hand was Du mit diesem Objekt machst. Wenn die automatische Serialisierung über SOAP und dem WebService nicht funktioniert, dann hast Du 2 Möglichkeiten:

  • Du implementierst IXmlSerializable für Dein Objekt, so dass das automatische Serialisieren von Dir beeinflusst wird

Ich weiß echt nicht was mir das IXmlSerializable Interface da bringen soll. Mit dieser Schnittstelle kann man ja nur beeinflussen was mit den Daten passiert. Die serialisierung und deserialisierung der Daten ist ja wunderbar so wie sie ist nur der Fakt das die Typen auf der Server-Seite nicht denen der Client-Seite entsprechen stört mich.

  • Du serialisierst selbst und übergibst in der WebService-Methode nicht Deinen komplexen Typ, sondern den serialisierten Strom (z.B. als String)

Vorteil bei erster Variante ist, dass der Client wohl keine besondere Logik benötigen würde, aber die XML-Serialisierung ist in einigen Fällen sehr schwierig, weil alle vererbten Typen auch XML-Serialisiert werden können muss.

Also die zweite Variante ist auf alle fälle nicht das was ich will und bei der ersten hab ich wie gesagt keinen Plan was das mit der Sache zutun hat. (natürlich weiß ich wozu IXmlSerializable da ist und wie man es benutzt .. nich das wir uns da missverstehen)

Ich würde wie gesagt vom partial hier abweichen, und eine gemeinsame Assembly mit Interfaces bereitstellen (also sowohl für den Server als auch für den Client), weil BEIDE Beteiligten Kenntnisse über den Typ brauchen, da führt kein Weg daran vorbei!

Wenn das irgendwie ohne einen Wrapper im Client möglich wäre würde ich das gerne so machen.
Vielleicht kannst du mein beispiel Projekt nehmen (oder ein neues erstellen) und daran deine theoretische Lösung umsetzten dann hätte das hier ein ende und wir müssten nicht mehr aneinander vorbei reden 😉

Also ich beschreibe das ganze nochmal aus der Sicht des Clients:*man macht einen WebVerweis auf den Webservice *dabei wird u.a. der code für komplexe Typen aus dem WebService anhand der WSDL generiert *rufe ich jetzt die Funktion GetList auf bekomme ich eine Instanz des generierten Typen von MyList (der natürlich nur die Daten beinhaltet) zurück *jetzt würde ich gerne die Assembly in der der originale Type MyList implementiert ist zum Client hinzufügen *und dem WebService sagen .. anstatt in den generierten "dummen" Typen sollst du mir bitte in den MyList Typen aus der Assembly rein deserialisieren

Würde man im Client einen Wrapper um die Funktionen des WebServices schreiben der die Daten von dem einen in die andere Typen kopiert wäre das Problem gelöst. Aber das würde bedeuten das der Aufwand der Lösung parallel mit der Anzahl der Funktionen im WebService wächst und das will ich nicht.

lg mutzel

08.07.2008 - 14:13 Uhr

schaue doch mal hier:

>

Sieht für mich nicht so aus als ob das viel mit meinem Problem zutun hat.
In dem Thread wird die Serialisierung mit den Klassen aus System.Runtime.Serialization gemacht. Ein WebService arbeitet aber mit den Klassen aus System.Xml.Serialization

Interfaces lassen sich nicht serialisieren, richtig, muss man ja auch nicht. Aber ich meine, bevor ich eine Klassendefinition in einer Assembly an den Client gebe versuche ich nur Interfaces zu übergeben, und dann ein Objekt zu erstellen, das nur über das Interface angesprochen werden kann.

Erstmal erstell ich das Objekt mal nicht das macht ja der WebService. Außerdem gebe ich in dem Beispiel nicht die Assembly sondern den Code weiter weil es mit der Assembly nicht funktioniert. Außerdem muss ich ja immer noch die Daten und die Funktionen irgendwie verbinden was ja der eigentlich kritische Punkt ist.

Ja, das liegt daran, weil sowohl dem Server als auch dem Clienten durch das .NET Framework der vollqualifizierte Namensraum vorliegt ("System.Data.DataSet"). Durch die gemeinsame Assembly ist das zwischen Deinem Server und Deinem Client auch gewährleistet.

Wie gesagt hab ich ja keine gemeinsamme Assembly weil das bei mir angewendete partial nicht über Assembly grenzen funktioniert (wird ja beim kompilieren aufgelöst). Müsste man also nur eine gemeinsame Assembly besitzen wäre das ganze ja ziemlich einfach.

lg mutzel

08.07.2008 - 12:34 Uhr

[...] Das löst man eleganter Weise besser mit Interfaces. Interfaces definieren hierbei den Funktionsumfang einer Klasse ohne Daten. Dann übergibt man das Objekt nur als Interface und der Client kennt dann den Funktionsumfang. Der WebService wäre dann für den konkreten Datentransport zuständig.[...]

Wie soll das denn funktionieren? .. also erstmal kann man ein Interface nicht serialisieren und selbst wenn müsste man ja beim Client immernoch die Verbindung von Daten und Funktionen wiederherstellen.

[...]Der Namespace muss gleich sein, das gibt die Typsicherheit des Frameworks so vor.[...]

Man kann einen WebService beim Client in einen belibigen Namespace stecken. Wäre das nicht der Fall wäre es nicht so ein großes Problem.

[...]Eine allgemeine Lösung, die von beliebigen Clients konsumiert werden kann, muss sich auf primitive Datentypen beschränken, dann dürfen keine eigenen oder komplexe Datentypen übergeben werden.[...]

Eine Klasse und damit einen komplexen Datentyp über einen WebService zuversenden ist ja kein Problem. Mir fehlt nur eine simple Funktion im WebService Framework wo ich bestimmen kann welche Typen wo hineindeserialisiert werden.

Beim DataSet scheint genau das was ich meine zu funktionieren. Gibt eine Funktion im WebService einen Wert vom Typen DataSet zurück so wird beim Client dieser rückgabewert nicht in einen neuen Typen sondern in das richtig System.Data.DataSet hineindeserialisiert.
Also irgendwie muss man das beeinflussen können.

08.07.2008 - 10:28 Uhr

Also ich hab eben ne Möglichkeit gefunden wie man es machen könnte... so 100% zufrieden bin ich damit aber auch noch nicht.
Bei der Lösung gibt es 3 Projekte:*eine ClassLibrary mit dem MyList Typen wo Funktionen und Daten mit Hilfe von partial voneinander getrennt sind *den WebService der einen Verweis auf die ClassLibrary und die MyList zurück gibt *eine Console Anwendung als Client die einen WebVerweis auf den WebService hat und einen Link auf die Funktionen Quellcodedatei der MyList besitzt

Und hier noch der Code von den drei Projekten:

ClassLibrary

MyListData.cs

namespace ConsoleApplication.WebService
{
    public partial class MyList
    {        
        public string[] List { get; set; }
    }
}

MyListFunctions.cs


namespace ConsoleApplication.WebService
{
    public partial class MyList
    {        
        public string Find(string search)
        {
            foreach (string s in List) { if (s.Contains(search)) return s; }
            throw new Exception();
        }
    }
}

WebService


namespace WebService
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    public class Service : System.Web.Services.WebService
    {
        [WebMethod]
        public MyList GetList()
        {
            return new MyList() { List = new string[] { "Test1", "Test2", "muh" } };
        }
    }
}

Client (mit einem Link auf die MyListFunctions.cs)


namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {            
            WebService.Service service = new WebService.Service();
            Console.WriteLine(service.GetList().Find("Test"));
            Console.ReadKey();
        }
    }    
}

Das ganze hat aber mehrere Nachteile:*der Namespace der MyList Klasse muss mit dem Namespace der WebService Klasse im Client übereinstimmen *man kann die Lösung nicht ohne den Quellcode einem Dritten anbieten

08.07.2008 - 09:54 Uhr

[...] Das Deserialisieren funktioniert nur, wenn die gleiche Klasse aus derselben Assembly dafür verwendet wird. Dann sind selbstverständlich auch die Funktionen vorhanden.[..]

Ich serialisiere und deserialisiere ja nicht selbst .. das macht das Framework mit dem WebServices ja im Hintergrund. Davon will ich ja auch nix mitbekommen weil das die Sache mit den WebServices ja so schön einfach macht.

08.07.2008 - 08:21 Uhr

[...] wenn Du Objekte per WebService übergeben möchtest, dann funktioniert das nur mittels (De-)Serialisieren. Dass das langsam ist sollte klar sein (Von Objekt->Serialisierter Datenstrom->XML->HTTP->und vice versa). [...]

Das ist mir schon klar und ist ja auch okay so.

[...] Dabei bleibt nicht aus, dass der Datentyp sowohl Server als auch Client bekannt sein muss. [...]

Und genau an dieser Stelle würde ich gern einen anderen Weg gehen als es normalerweise der Fall ist.
Die Datenstruktur wird ja ohne die Funktionen in die WSDL reinserialisiert und aus der WSDL wird dann der Code für den WebService generiert.
Da man die Funktionen schlecht serialisieren kann wäre es ja schön wenn man beim client sagen könnte: "Der generierte Datentyp MyList entspricht dem Datentyp MyList aus Assembly XYZ" So das die Daten nicht erst in den generierten Datentyp MyList hineinserialisiert werden sondern gleich in den echten Datentyp aus der Assembly.

lg martin

07.07.2008 - 17:09 Uhr
  1. erstelle eine neue Konsole-Anwendung
  2. füge eine WebReference zu "http://webservices.imacination.com/validate/Validate.jws?wsdl" hinzu
  3. kopiere folgenden code in deine Main funktion

            Console.WriteLine("validateNumber returned '{0}'",
                new com.imacination.webservices.ValidateService() 
                { Url = "http://webservices.imacination.com/validate/Validate.jws" }
                .validateNumber("muh")
                );

  1. find raus warum es funktioniert hat

(falls das nicht funktioniert findest du im Anhang das Projekt mit dem ich es getestet habe)

07.07.2008 - 16:58 Uhr

Ich hab mal eben mit Hilfe von grep im Web References Verzeichnis nach einem Description-Text gesucht und man findet ihn nur in der WSDL Datei.
Das bedeutet das das Visual Studio von haus aus die Beschreibung der Funktionen nicht in den generierten code mit embedded.
Also sind sie so ohne weiteres vom code aus auch nicht erreichbar.

07.07.2008 - 16:35 Uhr

Hi,

also ich hab schon seit ner Ewigkeit eine Sache die mich an den WebServices stört und zwar die Tatsache das beim Transport der Daten sämtliche Funktionalität verloren geht und am anderen Ende ein vollkommen neuer Type erstellt wird.

Gibt es eine Möglichkeit das zu unterbinden?

Hier ein Beispiel:

  • im WebService gibt es eine funktion GetList dies gibt ein objekt vom type MyList zurück was wie folgt aussieht:

        public class MyList
        {
            public string[] List { get; set; }
            public string Find(string search)
            {
                foreach (string s in List) { if (s.Contains(search)) return s; }
                throw new Exception();
            }
        }

  • sowohl der Server als auch der Client wollen die funktion MyList.Find aufrufen
  • da der Client aber die Klasse aus der XML vom WebService generiert bekommt, werden nur die Daten und nicht die Funktionen übermittelt

Wie schafft man es also ohne die Funktion bzw. Klasse zwei mal zu schreiben die Funktionalität auf Client und Server nutzbar ist?

Eine unschöne Lösung hätte ich da schon. Dabei nimmt man einfach eine Assembly in der der Type MyList implementiert ist. Diese Assembly bekommen dann Server und Client. Wenn der Client ein MyList object aus vom Server bekommt könnte er dieses object deserialisieren und in ein echtes MyList object reinserialisieren.
Das ist aber langsam und man müsste jeden WebService nochmal wrappen was nich wirklich im sinne des Erfinders ist.

Das ganze sollte wenn möglich mit dem .NET 2.0 funktionieren.

LG mutzel

25.10.2007 - 13:07 Uhr

Hi..

hab grad ein ganz ominöses verhalten von VS 2005 beobachtet und kann mir nicht erklären wie es dazu kommt..

Ich habe ein gefülltes GridView welches beim aufruf des RowCommand Event den gewählten DataKey auslesen soll.

das Ganze sieht dann so aus:


protected void GridViewResult_RowCommand(object sender, GridViewCommandEventArgs e)
    {
        GridView grid = sender as GridView;
        DataKeyArray data = grid.DataKeys;
        object o = data[Convert.ToInt32(e.CommandArgument)].Value;
    }

wenn ich das jetzt laufen lasse bekomm ich eine ArgumentOutOfRangeException ..

jetzt kommt das ominöse .. wenn ich mir einen Breakpoint im Eventhandler setze und dann bevor 'data' zugewiesen wird mir grid.DataKeys anschaue ist es auf einmal gefüllt und ich bekomme keine Exception. Setze ich den Breakpoint nachdem 'data' zugewiesen wurde sind 'data' und grid.DataKeys leer.

Das einzige was ein wenig anders ist als bei einem normalen GridView ist das mein GridView mit der funktion RenderControl ausgegeben wird.

Ich würde mich ja damit abfinden zusagen "das geht nicht wenn das GridView mit RenderControl ausgegeben wird" .. aber anscheinend geht es ja doch da der Debugger die Werte ja sieht und dann sogar für den Rest des Codes zur verfügung stellt.

Kann sich irgendeiner erklären wie so etwas zustande kommt.. oder vielleicht sogar wie ich das ganze lösen kann?

lg mutzel

12.10.2007 - 13:53 Uhr

hi,

ich experimentiere gerade mit dem Befüllen eines ASP GridView über ein ObjectDataSource herum und habe die folgenden 2 Wege erfolgreich begehen können:

  1. GridView über einen ObjectDataSource und einer IEnumerable<MeineKlasse> füllen
  2. GridView über einen ObjectDataSource und einer DataTable (mit dynamischen Spalten) füllen

Da ich teilweise Objekte benutzen will wo die Spalten aus einer XML geladen werden (mit Dictionary<string,string>), kann ich keine fest definierte Klasse benutzen (wie bei 1.). Also müsste ich eine DataTable benutzen weil ich da beliebig neue Spalten hinzufügen kann.
Da ich aber nicht das gesamte Objekt immer in eine DataTable umwandeln will, würde ich diese dynamischen Felder gerne direkt in meiner Klasse anbieten. So wie es auch die DataTable macht.
Ich konnte aber nicht herrausfinden wie die DataTable diese dynamischen Felder anbietet (vielleicht über irgendeins der Interfaces) bzw. wie das GridView in den Objekten danach fragt.
Könnte mir da jemand weiterhelfen?

lg mutzel

24.11.2006 - 10:43 Uhr

also .. ich hab das jetzt mal mit Ethereal probiert

const wird nie übertragen -> nützt mir aber nix weil klassen nicht konstant sein können
readonly und/oder static wird immer übertragen

gibt es nun irgendwelche möglichkeiten mit denen man dem .NET sagen kann ... meine Klasse bleibt vom Inhalt wie sie ist und braucht nur einmal an jeden client verteilt werden ... so das der client dann nur noch mit referenzen auf schon vorhandene inhalte arbeitet...

22.11.2006 - 14:28 Uhr

nehmen wir mal an ich hab eine klasse wie diese...


public class test 
{
  int i;
  public test(int i)
  {
     this.i=i;
  }

  public int I { get { return i; } }
}

kann ich die denn überhaupt konstant anlegen? oder kann ich da nur einen static readonly draus machen?

22.11.2006 - 10:09 Uhr

Hallo..

ich würde gern wissen wie sich readonly und const variablen beim remoting verhalten .. merkt das .NET das die daten sich nicht verändern können oder holt er sich bei jeder abfrage dir daten neu?

bzw. gibt es möglichkeiten mit den ich nachvollziehen kann wann welche zugriffe oder serializierungen für das remoting gemacht werden.. also so eine art remoting logger?

lg mutzel

16.11.2006 - 13:30 Uhr

Original von Golo
Muss man ja auch nicht ... einfach in jede UI-Methode einen MethodInvoker rein, der den eigentlichen Code als anonymen Delegate aufruft und gut ist.

dann müsste man ja das control verändern und die methoden würden auch über ein delegate aufgerufen werden auch wenn das garnicht nötig ist

ich will das invoke aber in meiner component machen und nicht erst im control .. so das die methode des controls beim klick auf einen button ohne invoke auskommt und beim zugriff von der multithread component per invoke gestartet wird ..

.. mal ganz davon abgesehen das ein invoke mit einem anonymen delegate garnich geht (glaube ich zumindest) EDIT: ok hab mich geirrt

lg martin

16.11.2006 - 12:31 Uhr

hab mir das beispiel grade angeguckt und ausprobiert .. das problem ist das das gnze nur läuft wenn man noch im designer ist .. sobald man das projekt startet ist der host immmer null... mach ich irgend etwas falsch oder ist das beispiel nur für den designer gedacht ... wenn ja kann man das parent control auch während der laufzeit herausfinden?


        public override ISite Site
        {
            get
            {
                return base.Site;
            }
            set
            {
                base.Site = value;
                if (this.Site!=null)
                {
                    System.ComponentModel.Design.IDesignerHost host = (System.ComponentModel.Design.IDesignerHost)value.GetService (typeof (System.ComponentModel.Design.IDesignerHost));
                    if (host!=null)      //    <-  Host ist zur laufzeit null 
                    {
                        Control ctrlParent = host.RootComponent as Control;
                        if (ctrlParent!=null)
                        {
                            this._SynchronizingObject=ctrlParent;
                        }
                    }
                }
            }
        }

lg mutzel

15.11.2006 - 15:18 Uhr

hm ... schade..

gibt es einfache möglichkeiten derartige dinge auch bei ganz normalen threads mitzubekommen? oder muss man sich da ganz genau überlegen was man tut?

lg mutzel

15.11.2006 - 13:19 Uhr

hallo..

ich bin gerade darüber gestolpert das mich das VS2005 warnt wenn man threadübergreifende aktionen ausführt die so nicht zulässig sind .. hab dann die folgende meldung in der exception bekommen:

"Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement label1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde."

da ich aus der vergangenheit (mit BCB 6) mitbekommen hab das das mit der threadsicherheit nur schwer nachzuvollziehen ist würde ich gern wissen ob das VS2005 jede nicht threadsichere aktion bemerkt oder ob das nur bei zugriffen auf die GUI funktioniert?

lg mutzel

15.11.2006 - 10:43 Uhr

hier gibts auch noch ein etwas genaueres beispiel

26.07.2006 - 15:21 Uhr

hab ein wenig mit remoting rumgespielt und wollte gern wissen ob das remoting objekt immer vom server kommen muss...
... was ich will: einen server öffnen und dann warten bis sich ein oder mehrere clients verbinden... die clients geben ihre objekte frei und der server kann diese dann ansteuern.. funktioniert so etwas?

thx

lg mutzel

26.06.2006 - 10:01 Uhr

is beides nich so das optimale ... aber trotzdem danke für die antworten...

hab noch ein wenig gesucht und bei microsoft einen artikel über das ausdrucken einer RichTextBox gefunden ... das dort beschriebene richtext control kann mit ein paar veränderungen in ein Graphics-Objekt drucken...

http://support.microsoft.com/kb/812425/

23.06.2006 - 17:05 Uhr

hallo

ich suche eine möglichkeit den Inhalt einer RichTextBox in ein Image um zuwandeln...

wie stellt man sowas am besten an?

lg mutzel

15.06.2006 - 13:16 Uhr

hallo..

... ich habe mir eine Component erstellt die eine Liste<> als öffentliche eingenschaft zur verfügung stellt... das ganze läuft auch zur entwurfszeit (d.h. der auflistungs editor erscheint und man kann die werte ändern und hinzufügen)

..mein problem besteht darin das die liste nicht in die Form1.Designer.cs geschrieben wird (wie bei den anderen normalen eigenschaften) und so das initialisieren und speichern der datensätze nicht erfolgt... also wie kann man eine Liste zur entwurfszeit speichern so das sie beim laufen wieder geladen werden kann?

lg mutzel

09.06.2006 - 08:45 Uhr

Original von herbivore
Daher bin ich davon ausgegangen, dass die Komponenten visuelle Komponenten (also quasi Controls) sind. Nach dem was du jetzt schreibst, scheinen es aber Komponenten für Daten zu sein. Das passt für mich dann aber nicht mehr zu der ursprünglichen Frage.

ich hatte gedacht des es eindeutig ist das Komponenten gleich Component und nicht gleich Control (Steuerelemente) ist .. schon alleine weil sich das so schön 1:1 übersetzen lässt...
.. wobei es dann eigentlich egal ist ob ich Component mit Component oder Component mit Control verbinde... was mir jedoch nie in den sinn kommen würde: ein Control mit einem Control zu verbinden (wozu auch) ...

.. zu meinem ursprünglichen problem zurück (das wegen der frage darf ich verbinden oder darf ich nicht ein wenig in den hintergrunde getreten ist):

unabhängig davon ob es gut ist oder nicht interessiert es mich ob es möglich ist, im formular-designer von VS.NET 2005, beim auswahlfeld einer eigenschaft, die den typ einer anderen Component class hat, auf ein anderes form zu verweisen das eine Component des gewünschten Typs beinhaltet?

08.06.2006 - 17:47 Uhr

ich verbind ja nich die vorschau- und die detailansicht sondern nur die ansichten mit den datenlieferanten....

08.06.2006 - 15:24 Uhr

Original von herbivore
Hallo mutzel,

dabei ist ImageList ein untergeordnetes Objekt. Wenn aber bei Controls eins dem anderen unterordnet ist, dann gehört es in dessen Controls-Collection.

herbivore

das versteh ich jetzt nicht.... ist meine Compo2 dann nicht auch ein untergeordnetes objekt?

vielleicht hilft es wenn ich meine reale situation mal erkläre...

ich hab mehrere komponenten die alle verschiedene daten zur verfügung stellen... diese komponenten haben alle das gleiche interface implementiert über die die daten zur verfügung gestellt werden... um die daten anzuzeigen gibt es 2 verschiedene controls ein control das als vorschau dient und ein zweites das alle daten anzeigt...

...nun kann ich die verknüpfungen untereinander festlegen und so ein programm erstellen ohne eine zeile code zu schreiben..

steckt da nicht die selbe ideologie wie bei Label und ImageList drin?

08.06.2006 - 14:34 Uhr

Original von herbivore
Hallo mutzel,

ich denke, dass der Weg schon bei einem Form nicht so gut ist. Besser wird die Kommunikation über Events sein.

was ist daran so schlecht? schließlich macht microsoft das auch wenn man z.b. einem Label eine ImageList zuweisen will...

08.06.2006 - 12:27 Uhr

hallo...

hab in letzter zeit mit dem entwickeln von komponenten (VS.NET 2005) herumgespielt ... dabei ist mir aufgefallen das es sehr einfach ist 2 verschiedene komponenten miteinander zu verknüpfen in dem man einfach eine öffentliche eigenschaft vom typ der anderen komponente implementiert...
z.b. so:


public class Compo1 : Component
{
        Compo2 _compo;

        public Compo2 Compo {
            get { return _compo; } set { _compo = value; }
        }
}

public class Compo2 : Component
{
}

... das ermöglicht das man im form-designer die komponenten miteinander verknüpfen kann...
.. leider funktioniert das ganze nicht mehr wenn die komponenten auf verschiedenen forms liegen... gibt es da eine möglichkeit das auch die komponenten anderer forms mit beachtet werden?

16.05.2006 - 09:24 Uhr

hallo ...

hab da ma ne kleine frage...

was ist der unterschied zwichen

button1.Click += new EventHandler<EventArgs>(button1_Click);

und

button1.Click += button1_Click;

?

soweit ich das mitbekommen habe verhalten sich beide varianten gleich oder?

09.03.2006 - 11:09 Uhr

Original von ikaros
Fin ist Teil Telnet-Protokoll. Der Client muss es interpretieren können.

@mutzel
Dein Client muss also das Fin empfangen(tut er sowieso) und daraufhin die Verbindung beenden(implementieren)(tut er derzeit nicht).

Das klingt nicht so als ob du dich besonders gut mit TCP auskennst.


>

FIN
Dieses Finish-Flag dient zur Freigabe der Verbindung und zeigt an, dass keine Daten mehr vom Sender kommen. Die FIN- und SYN-Flags haben Sequenznummern, damit diese in der richtigen Reihenfolge abgearbeitet werden.

Ich hab das Problem jetzt gelöst. Mein Fehler war das ich dachte wenn ich mir ein TCPClient schnappe und ihn mit einem StreamReader auslese wird alles ganz einfach .. kling gut .. war aber nich so... also greif ich vor dem Lesen wieder auf den normalen Socket zu .. irgendwie doof aber geht anscheinend nicht anders...

hier meine Lösung:


if(Client.Available==0 && this.Client.Poll(1000, SelectMode.SelectRead)
{
// Socket ist abgestorben und ein Read gibt nur nullen aus
}

Wenn Poll mir also sagt der er lesen kann und keine Daten verfügbar sind weiss ich die Serverseite das FIN gesendet hat.

Trotzdem Danke für die Antworten! Vielleicht hat ja noch jemand ne idee wie ich auch ohne einen zugriff auf den Socket den Abbruch erkenne.

LG mutzel

ps.

Original von ikaros
In geschlossenen (Test-)Netzwerken ist der Einsatz ok, in Firmennetzwerken kanns zur Kündigung und noch mehr Konsequenzen führen.
Also nicht unbedingt relevant, aber vielleicht erwähnenswert(deinen Hintergrund kenn ich nicht, hab ja keinen Scanner auf den Forumsserver laufen...)

ich würde stark bezweifeln das ich mich strafbar mache wenn ich mit meinem "Debugtool" unverschlüsselte Daten empfange die automatisch weggefiltert werden und nie irgendwo geloggt werden.

Das wäre ja wie wenn ich vor ner gerade überfallenen Bank stehe und mir der Bankräuber den sack mit dem geld in die Hand drückt, ich ihn aber fallen lasse weil ich garkein Bock auf ne runde Katz und Maus mit den bullen hab.

08.03.2006 - 08:12 Uhr

Die verbindung wird vom Server getrennt ... da der Server aber ein eigenständiges gerät ist, kann ich an der Firmware dort nix ändern...

mal davon abgesehen das der Server ja ein FIN sendet .. das problem ist nur das mir c# nicht sagt das ich das FIN bekommen hab ... denn beim Windows Telnet läuft das ganze ja auch einwandfrei .. der bekommt das FIN und antwortet mit einem FIN .. ohne mein Telnet-Protokoll wirklich zu kennen.

Ich hab früher mit Borland Builder programmiert dor hat das ganze auch einwandfrei geklappt ... war aber andere Socket Komponenten

Original von ikaros
Ich vermute, im Heimnetzwerk geht der Einsatz eines Sniffers glimpflich aus...

Was meinst du damit?

Original von Franknstein

Richtig. Evlt. muss man auch quasi sowas wie Pings implementiert, um den Server wissen zu lassen, welche der Clients jetzt weg sind.

Das Problem liegt meiner Meinung nicht beim Server da der ja ein FIN sendet.. Das heisst wenn dann muss man ein Ping auf dem Server einbauen damit der Client bescheit weiss .. aber das kann/will ich ja eben nicht ..

lg mutzel

07.03.2006 - 16:04 Uhr

hallo...

Wenn meine Vebindung (TCPClient) vom Server aus getrennt wird, so bekommt das der TCPClient aus mir unbekannten Gründen nicht mit... ein Verbindungsabbruch durch Ziehen des LAN-Steckers funktioniert jedoch einwandfrei...

Ich hab das ganze dann mit Ethereal mal beobachtet und habe folgendes rausgefunden:

mit dem Windows Telnet Tool:_
No. Time Source Destination Protocol Info
1 0.000000 192.168.0.3 192.168.0.2 TCP 2581 > telnet [SYN] Seq=0 Ack=0 Win=16384 Len=0 MSS=1460
2 0.002906 192.168.0.2 192.168.0.3 TCP telnet > 2581 [SYN, ACK] Seq=0 Ack=1 Win=16 Len=0 MSS=1460
3 0.002929 192.168.0.3 192.168.0.2 TCP 2581 > telnet [ACK] Seq=1 Ack=1 Win=17520 Len=0
4 0.005531 192.168.0.2 192.168.0.3 TELNET Telnet Data ...
5 0.107361 192.168.0.3 192.168.0.2 TCP 2581 > telnet [ACK] Seq=1 Ack=47 Win=17474 Len=0
6 29.578807 192.168.0.2 192.168.0.3 TCP telnet > 2581 [FIN, ACK] Seq=47 Ack=1 Win=16 Len=0
7 29.578864 192.168.0.3 192.168.0.2 TCP 2581 > telnet [ACK] Seq=1 Ack=48 Win=17474 Len=0
8 29.579147 192.168.0.3 192.168.0.2 TCP 2581 > telnet [FIN, ACK] Seq=1 Ack=48 Win=17474 Len=0
9 29.581371 192.168.0.2 192.168.0.3 TCP telnet > 2581 [ACK] Seq=48 Ack=2 Win=16 Len=0_

hier sendet der server ein FIN an den Client... und der Client sendet brav ein FIN zurück .. und schon ist die Verbindung geschlossen

Mit dem auf TCPClient basierenden Tool
No. Time Source Destination Protocol Info
1 0.000000 192.168.0.3 192.168.0.2 TCP 2849 > telnet [SYN] Seq=0 Ack=0 Win=16384 Len=0 MSS=1460
2 0.002229 192.168.0.2 192.168.0.3 TCP telnet > 2849 [SYN, ACK] Seq=0 Ack=1 Win=16 Len=0 MSS=1460
3 0.002261 192.168.0.3 192.168.0.2 TCP 2849 > telnet [ACK] Seq=1 Ack=1 Win=17520 Len=0
4 0.004516 192.168.0.2 192.168.0.3 TELNET Telnet Data ...
5 0.108918 192.168.0.3 192.168.0.2 TCP 2849 > telnet [ACK] Seq=1 Ack=47 Win=17474 Len=0
6 29.133158 192.168.0.2 192.168.0.3 TCP telnet > 2849 [FIN, ACK] Seq=47 Ack=1 Win=16 Len=0
7 29.133193 192.168.0.3 192.168.0.2 TCP 2849 > telnet [ACK] Seq=1 Ack=48 Win=17474 Len=0

Hier fehlt die antwort auf das FIN vom Client...

...nun meine Frage... gibt es eine Möglichkeit herrauszufinden ob der socket ein FIN bekommen hat?
Wenn ich das nicht mitbekommen kann so denkt der TCPClient die ganze zeit das er noch verbunden ist.

07.03.2006 - 12:22 Uhr

Original von Programmierhans
Ich arbeite mit
>

Und das Teil ist wie ein VW-Käfer.... es läuft und läuft und läuft (in einem harten industriellen Umfeld)

Meinst du das Rapid OPC Connection Kit (ROCKit)?

Wenn ja.. weisst du ob man davon ne Demo herunterladen kann?

07.03.2006 - 10:43 Uhr

ah jetzt ja ... hab mich auf der Advosol seite umgeguckt und hab alles gefunden was ich brauch...

mir ist nur eben aufgefallen das am anfang des threads nach nem Client gefragt wurde ich aber einen Server bauen will... Advosol bietet jedoch auch ein Server Toolkit an...
und das beste .. das ganze läuft sogar einwandfrei... 🙂

im prinzip ist das warscheinlich auch nix anderes als das industrial dot net das Pulpapex gepostet hat... is beides nich kostenlos 😁

aber .. noch eine allerletzte frage... da du ja bestimmt schon eine weile damit arbeitet würd ich gern wissen ob die Toolkits von Advosol stabiel lauf oder ob es da probleme gibt und ob du schon mit anderen Toolkits erfahrungen gemacht hast..

nochma vielen dank!

06.03.2006 - 17:33 Uhr

Original von Programmierhans
Jungs ihr müsst doch nur das OpcDaNet.dll in das Projekt einbinden und schon habt Ihr Zugriff auf die OPC-Funktionalität

Mehr Hilfe darf ich aber nicht geben (man konkurrenziert sich ja nicht gerne selber ) 😉

hierm ... kann das sein das du die OpcNetApi.dll meinst? ... hab unter OpcDaNet.dll nirgends was gefunden...

und falls es die OpcNetApi.dll is .... befindet die sich glaube ich in der "OPC .NET API 1.30 SDK" die man nur als mitglied der OPC Foundation downloaden darf .. oder?

und wenn man das teil nur als mitglied der OPC Foundation bekommt .. ist es schwer bzw. kostet es was mitglied zu werden?

danke für die mühe ..

ps. ich werd versuchen jeglichen konkurrenzkampf mit dir zu vermeiden 😉

06.03.2006 - 13:20 Uhr

Original von george
Hallo,

ich möchte mit .NET einen OPC - Client erstellen. Hat da von euch schon mal jemand Erfahrungen gesammelt ???
Wenn ja, wären ein paar nützliche Tipps und Links sehr hilfreich.

Danke george

ich interessiere mich auch für dieses thema..

... hast du mittlerweile schon etwas herausgefunden?

06.03.2006 - 07:51 Uhr

im übrigen hab ich die antwort deiner frage sehr schnell mit google gefunden

also für das nächste mal: erst googlen dann fragen 😁

03.03.2006 - 12:42 Uhr

hab noch ein beispiel-code auf ner anderen seite gefunden...


            ManagementObjectSearcher query = new ManagementObjectSearcher("SELECT * FROM Win32_Battery"); 
            ManagementObjectCollection queryCollection = query.Get(); 
            foreach (ManagementObject mo in queryCollection)
            {
                Trace.WriteLine(mo.Path.ToString());
                foreach (PropertyData pd in mo.Properties)
                {
                    Trace.WriteLine("    " + pd.Name + " = " + pd.Value);
                }
            }

hab ihn getestet ... und er geht sogar

[edit]
hab mal getestet was sich ändert wenn ich das netzteil rausziehe

mit netzteil:

Availability = 2 (Unknown)  
BatteryStatus = 2 (Unknown)  
DesignVoltage = 16669  

ohne netzteil:

Availability = 3 (Running/Full Power)  
BatteryStatus = 1 (Other)  
DesignVoltage = 16348  

nach ner weile geht dann auch EstimatedChargeRemaining von 100 auf 99

03.03.2006 - 12:34 Uhr

hab das selber nich nie gemacht .. aber guck mal hier http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/win32_battery.asp

vielleicht is es das was du suchst

03.03.2006 - 11:14 Uhr

hallo...

ich bin grad am rumprobieren wie ich ein TcpClient dazu bringe in einer single-thread anwendung ordnungsgemäß zeilenweise zu lesen und zu schreiben...

ich hab mir also ein TcpClient, ein StreamWriter und ein StreamReader geschnappt und gehofft das ich damit relativ einfach die sache realisieren kann...

das schreiben funktionier soweit ganz gut... ich hab nur noch ein probleme..

das lesen


		public string ReadLine()
		{
            ReceiveTimeout = 1;
            try { return _reader.ReadLine(); }
            catch (IOException e) {

                SocketException se = ((SocketException)(e.InnerException));
                if (se != null)
                {
                    System.Diagnostics.Debug.WriteLine(se.ErrorCode.ToString() + ": " + se.Message);
                }
                else
                {
                    throw e;
                }
                return null;
            }	
		}

das lesen funzt eigentlich auch ... aber wenn ich mehr zeilen lese als ich empfangen hab bekomme ich eine exception .. was erstmal ganz in ordnung is den schließlich habe ich ja das ReceiveTimeout auf 1 gesetzt... das problem besteht darin das ich nicht ein SocketError 10035 bekomme sondern ein SocketError 10060 .. nach diesem einen SocketError folgen dann nur noch die 10035 .. leider ist dann aber auch der status von Connected auf false. die kommunikation geht aber trotzdem noch weiter... warum gibt mir der Socket aber den 10060er fehler... sollten nicht normalerweise nur die 10035er fehler kommen?

hier noch die fehlermeldungen
_
"10060: Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht ordnungsgemäß reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat"

"10035: Ein nicht blockierender Socketvorgang konnte nicht sofort ausgeführt werden" _