Entwickler-Ecke
Open Source Projekte - TNBFPA v1.12 - SocketKompos mit Protokollfunktionen
Narses - Do 22.03.07 01:09
Titel: TNBFPA v1.12 - SocketKompos mit Protokollfunktionen
Socket-Komponenten mit integriertem Protokoll-Adapter
Wer das
Binär-Protokoll-Tutorial [
http://www.delphi-library.de/topic_66706.html] kennt, wird den verwendeten
TProtocolAdapter bestimmt wiedererkennen (der allerdings hier bereits in einer weiterentwickelten Form vorliegt). Kenntnis des Tutorials wäre sicher sehr hilfreich bei der Verwendung der hier vorgestellten Komponenten, ist aber nicht zwingend notwendig.
- TNBFPAClient
Entspricht einem TClientSocket mit integriertem TProtocolAdapter
- TNBFPAServer
Entspricht einem TServerSocket mit integriertem TServerPA
Die Komponenten werden in die Palette der IDE installiert, können aber auch dynamisch verwendet werden. Im Projekt-Archiv ist eine ausführliche Anleitung zur Installation der Komponenten enthalten. Es ist übrigens nicht notwendig, die
Socket-Komponenten [
http://www.delphi-library.de/topic_64438.html] (
TClientSocket und
TServerSocket) in der IDE installiert zu haben (somit stellen diese beiden Komponenten eine Möglichkeit dar, auch in PE-Delphi-Versionen wieder IDE-Integration für Sockets-basierte Komponenten zu bekommen).
Fortgeschrittene mit Kenntnis des oben erwähnten Binär-Protokoll-Tutorials werden sich sicherlich darüber freuen, die Anbindung an die Sockets nicht mehr "von Hand" machen zu müssen.
Aber auch Anfänger in Sachen Netzwerk könn(t)en mit den vorgestellten Komponenten eine einfache Lösung für klassische Probleme bei der Kommunikation finden (
Daten-Typen/-Pakete auseinanderhalten, Ereignisse korrekt handhaben [
http://www.delphi-library.de/topic_56194.html]), ohne den kompletten Hintergrund in allen Details kennen und beherrschen zu müssen.
Das Projekt-Archiv im Anhang dieses Beitrags enthält:
- Den Quelltext der Komponenten TNBFPAClient und TNBFPAServer mit deren Hilfsklassen und Deklarationen in der Datei NarsesBFPA.pas
- Eine Referenz-Dokumentation der Komponenten-API mit integriertem Quickstart-Tutorial und ausführlicher Installationsanleitung als PDF
- Die Beispielprojektdateien des Quickstart-Tutorials und die fertigen Demo-Programme zum direkten Ausprobieren
Die nächsten netzwerkprogrammierungsbezogenen Tutorials von mir werden auf diesen Komponenten aufbauen, da hiermit die Netzwerkkommunikation über ein (proprietäres) Protokoll "kinderleicht" ist. ;)
History:
Änderungen in
TNBFPA v1.20, Doku v1.06 vom 24.02.2010:
- Nur Anpassungen für D2010 (Unicode, s.u.); Die Komponente sollte in D2k9 besser nicht verwendet werden, da hier dem Hersteller noch Fehler bei der Umstellung auf Unicode unterlaufen sind! Für Delphi-Versionen vor D2k9 sollte weiterhin die Version 1.12 verwendet werden!
- Eine (wichtige) funktionale Änderung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| procedure TServerMain.NBFPAServer1ConnectionsChange(Sender: TObject); begin NBFPAServer1.Connections.AssignTo(Clients.Items); end; |
Da das Connections[]-Array jetzt kein Nachfahre von TStringList mehr ist (sondern von TAnsiStrList, was ja nicht kompatibel ist), muss man die Zuweisung per .Assign "umdrehen", s.o.
Änderungen in
TNBFPA v1.12, Doku v1.06 vom 27.08.2008:
- FIX: in TBaseCmdSeq.AddBuf() nur dann System.Move() aufrufen, wenn Size > 0 (ist eigentlich kein Fehler, aber löst eine Exception aus, wenn RangeCheck in den Compiler-Optionen aktiviert ist)
- FIX: Schreiben auf TNBFPAServer.Active nicht an den internen ServerSocket weitergeben, sondern selbst in Open; und Close; auflösen --> führte dazu, dass das Connections-Array nicht geleert wurde
Änderungen in
TNBFPA v1.11, Doku v1.06 vom 21.08.2007:
- FIX: Anpassungen für D5, keine funktionalen Änderungen
Komplette Version-History im Quelltext.
cu
Narses
Bullweih - Do 29.03.07 12:33
Titel: Fehler in Delphi 6
Moin Moin
Habe Deine Komponente gezogen und mit Delphi 6 getestet.
Bekomme beim Compilieren den Fehler das er
FConnectionsRef.NameValueSeparator nicht kennt.
Ich gehe mal davon aus das es sich auch um FConnectionsRef.Delimiter handelt oder zumindestens ersetzt werden kann.
MfG
Bulli
Narses - Do 29.03.07 22:07
Moin!
Bullweih hat folgendes geschrieben: |
mit Delphi 6 getestet.
Bekomme beim Compilieren den Fehler das er
FConnectionsRef.NameValueSeparator nicht kennt.
Ich gehe mal davon aus das es sich auch um FConnectionsRef.Delimiter handelt oder zumindestens ersetzt werden kann. |
Nein, damit ist das Standard-Trennzeichen für den Zugriff über
TStrings.Values[] gemeint (hat das D6 etwa noch nicht... :gruebel: muss mal am anderen Rechner forschen gehen... :oops:). Im Zweifel einfach
FConnectionsRef.NameValueSeparator durch ein
'=' ersetzen (tritt 2x auf: Zeile #1667 und #2432).
Ich lass mir mal was dazu einfallen... :?
cu
Narses
chrisdrury - Fr 30.03.07 06:30
Ist vielleicht auch an eine Version für Delphi 5 gedacht?
:wink:
Bullweih - Fr 30.03.07 07:30
Titel: Jo Danke ...
für die schnelle Antwort.
Die Komponente funzt einwandfrei. Hatte noch keine Probleme damit auch mit sehr großen Datenmengen.
Was vorher leider nicht ging oder nur mit sehr großem Aufwand zu bewerkstelligen war.
Feine Sache das ...
MfG
Bullweih
Narses - Fr 30.03.07 10:05
Moin!
chrisdrury hat folgendes geschrieben: |
Ist vielleicht auch an eine Version für Delphi 5 gedacht? :wink: |
Ich hab kein D5... :? Hast du´s schon probiert? Wir können ja mal sehen, ob wir´s da auch zum Laufen kriegen. ;)
Bullweih hat folgendes geschrieben: |
Jo Danke ... für die schnelle Antwort. |
Bitte, war ja nur ein kleiner Eingriff für D6. ;)
Bullweih hat folgendes geschrieben: |
Die Komponente funzt einwandfrei. Hatte noch keine Probleme damit auch mit sehr großen Datenmengen.
Was vorher leider nicht ging oder nur mit sehr großem Aufwand zu bewerkstelligen war.
Feine Sache das ... |
Danke für das Lob! :D
cu
Narses
BenBE - So 01.04.07 21:32
Narses hat folgendes geschrieben: |
Moin!
chrisdrury hat folgendes geschrieben: | Ist vielleicht auch an eine Version für Delphi 5 gedacht? :wink: |
Ich hab kein D5... :? Hast du´s schon probiert? Wir können ja mal sehen, ob wir´s da auch zum Laufen kriegen. ;) |
Wenn der besagte Fehler unter D6 gefixt ist, sollte die Komponente auch problemlos auf D5 laufen. Hab auch zum Testen D4 da. Falls also die Kompatibilität soweit getrieben werden sollte ;-)
@Narses: NameValueSeparator gibt's unter D5 UND D6 nicht.
Narses hat folgendes geschrieben: |
Bullweih hat folgendes geschrieben: | Jo Danke ... für die schnelle Antwort. |
Bitte, war ja nur ein kleiner Eingriff für D6. ;) |
D.h. müsste jetzt auch mit D5 laufen.
Narses hat folgendes geschrieben: |
Bullweih hat folgendes geschrieben: | Die Komponente funzt einwandfrei. Hatte noch keine Probleme damit auch mit sehr großen Datenmengen.
Was vorher leider nicht ging oder nur mit sehr großem Aufwand zu bewerkstelligen war.
Feine Sache das ... |
Danke für das Lob! :D
cu
Narses |
Naja ... Werd wahrscheinlich demnächst auch ein kleines Protokoll darauf aufsetzen ... (Naja ... Mischung aus RFC2440 und dem Proto der Kompo ;-)
chrisdrury - Mo 02.04.07 07:11
Narses hat folgendes geschrieben: |
Moin!
chrisdrury hat folgendes geschrieben: | Ist vielleicht auch an eine Version für Delphi 5 gedacht? :wink: |
Ich hab kein D5... :? Hast du´s schon probiert? Wir können ja mal sehen, ob wir´s da auch zum Laufen kriegen. ;) |
Hallo Narses,
ich habe jetzt mal versucht, Deine Komponente unter D5 zu installieren.
Erste Fehlermeldung: siehe fehler.jpg im Anhang
Bei ftKeepAlive = 0 nur ftKeepAlive gesetzt, weiter geht's:
Zweite Fehlermeldung: siehe fehler1.jpg
PCardinal in Cardinal geändert, weiter:
Dritte Fehlermeldung: siehe fehler2.jpg
Undefinierter Bezeichner: GUIDToString, ComObj in uses eingefügt, weiter:
vierte Fehlermeldung: siehe fehler3.jpg
Zeigertyp erwartet, wat nu?:gruebel:
chrisdrury - Mo 02.04.07 07:12
Anbei noch der vierte Fehler: :wink:
BenBE - Mo 02.04.07 07:34
PCardinal ist, wie der Name sagt, ein Zeiger auf einen Cardinal ...
Also:
Delphi-Quelltext
1:
| type PCardinal = ^Cardinal; |
einfügen am Anfang der Unit und deine eine Ersetzung rückgängig machen.
Born-to-Frag - Mo 02.04.07 08:48
Moin!
Hast du wieder super gemacht, Narses :zustimm:
Werde es bei Gelegenheit mal ausführlich testen, hab im Moment leider nicht so viel Zeit (auch kaum aktiv hier :()
greetz
//Bin schon bissl am testen, und was mir natürlich gleich auffällt: Ich habe einen Client connecten lassen mit deinem altem BFPA -> Exception :shock:
Macht mir nix aus, nur eine Anmerkung ;)
Narses - Mo 02.04.07 09:34
Moin!
chrisdrury hat folgendes geschrieben: |
Bei ftKeepAlive = 0 nur ftKeepAlive gesetzt |
Jo, ist klar, vermerkt. ;)
chrisdrury hat folgendes geschrieben: |
PCardinal in Cardinal geändert |
Argh! :shock: Hat D5 etwa keinen PCardinal im Angebot... Auf jeden Fall nicht durch Cardinal ersetzen, ist ja ein Zeigertyp (siehe
BenBEs Beitrag)!
Ich werd mich drum kümmern.
chrisdrury hat folgendes geschrieben: |
Undefinierter Bezeichner: GUIDToString, ComObj in uses eingefügt |
OK, vermerkt. ;)
chrisdrury hat folgendes geschrieben: |
Zeigertyp erwartet |
Folgefehler, s.o., ist damit erledigt. ;)
Born-to-Frag hat folgendes geschrieben: |
Hast du wieder super gemacht, Narses :zustimm: |
Danke, scheint aber noch etwas zu kinderkränkeln... :? ;)
Born-to-Frag hat folgendes geschrieben: |
Bin schon bissl am testen, und was mir natürlich gleich auffällt: Ich habe einen Client connecten lassen mit deinem altem BFPA -> Exception :shock: |
Uff, hatte ich auch probiert (klar, eigentlich ;) aber ohne Exception)... Details... wo genau... :?:
cu
Narses
chrisdrury - Mo 02.04.07 09:34
Danke @ BenBE!
Jetzt läuft's auch unter Delphi 5!! 8) :P :dance2:
Born-to-Frag - Mo 02.04.07 13:28
Narses hat folgendes geschrieben: |
Born-to-Frag hat folgendes geschrieben: | Bin schon bissl am testen, und was mir natürlich gleich auffällt: Ich habe einen Client connecten lassen mit deinem altem BFPA -> Exception :shock: |
Uff, hatte ich auch probiert (klar, eigentlich ;) aber ohne Exception)... Details... wo genau... :?: |
Hi,
war mein Fehler, funktioniert super! :autsch:
// es liegt daran, dass ich keinen client connecten lassen kann der das BFPA mit extra Socket Komponenten benutzt (zu alt schon? :D) Wenn du willst guck ich trotzdem nochmal genau wo der Fehler lag..
greetz
Narses - Mo 02.04.07 14:28
Moin!
Born-to-Frag hat folgendes geschrieben: |
war mein Fehler, funktioniert super! :autsch: |
Schwitz... 8) OK, Danke für den Test. ;)
Born-to-Frag hat folgendes geschrieben: |
es liegt daran, dass ich keinen client connecten lassen kann der das BFPA mit extra Socket Komponenten benutzt (zu alt schon? :D) |
Ja, das steht aber auch in der Doku... :zwinker: rtfm... (duck weg) :P
Transportprotokoll-Header-Versionen:
BinProtoTut:
'NBFP10'
Kompo-Version:
'NBFP20'
:idea:
Born-to-Frag hat folgendes geschrieben: |
Wenn du willst guck ich trotzdem nochmal genau wo der Fehler lag. |
Wenn du Zeit hast; würde mich schon interessieren (ggfs. -> PN, scheint ja was spezifisches zu sein).
cu
Narses
hui1991 - Di 03.04.07 11:22
Hi,
diese Komponente funktioniert auf meinem Delphi 7 eigentlich garnicht.
Der Fehler ist ich installiere es wie normal.
Schaue im Internet Register ob es da ist.
Sehe es ist da.
Danach schließe ich es.
Öffne eine neue Form und aufeinmal fehlt die Komponente.
Was soll ich tun das sie dauert da bleibt?
Neue installieren geht auch nicht.
Und ich weis net wo ich des Deinstallieren soll.
mfg
hui1991
Narses - Di 03.04.07 11:30
Moin!
hui1991 hat folgendes geschrieben: |
Was soll ich tun das sie dauert da bleibt?
Neue installieren geht auch nicht.
Und ich weis net wo ich des Deinstallieren soll. |
Das sieht mir doch stark danach aus, dass sie bereits installiert ist, aber evtl. in einem anderen Registerbereich? :gruebel:
Du bist nach Anleitung in Kapitel 2 vorgegangen und hast auch eine Meldung der Art: "Als Ergebnis des Neucompilierens des installierten Packages..." bekommen?
cu
Narses
hui1991 - Di 03.04.07 11:48
Nein das kam nicht:
"Als Ergebnis des Neucompilierens des installierten Packages..."
Hätte mir ja jemand sagen können das der Download unvollständig war.
Die PDF war bei mir garnet dabei.
Ich habe es etz runter geladen.
Und habe die PDF geöffnet.
Ich habe es nicht so gemacht.
Ich habe ein neues Package gemacht und die dort eingefügt und dann auf Installieren gedrückt.
Dann war sie da.
Nach delphi neustart war sie dann wieder weg.
Keine Ahnung warum das aufeinmal net geht.
Ich habe etz es so wie in der Anleitung gemacht und dann kam das hier:
"Als Ergebnis des Neucompilierens des installierten Packages..."
Blos in englisch ^^
Naja dann habe ich auf JA gedrückt und dann kam die Meldung das erfolgreich installiert ist
Ich habe es geschlossen und dann neue Application ausgewählt und siehe da es ist drin.
Naja Danke für deine Antwort hat mir eigentlich geholfen ^^
Ich teste es dann mal Später ^^
MfG
hui1991
Narses - Mi 04.04.07 11:12
Moin!
Neue Version TNBFPA v1.03, Doku v1.01, Details siehe oben im 1. Beitrag.
Da ich kein D5 habe, wäre ich über einen Hinweis dankbar, ob es jetzt so "durchläuft". ;)
cu
Narses
BenBE - Fr 06.04.07 14:08
Wünschenswerte Funktion für neue Releases:
- Protokoll-ID und Version über OI einstellbar (Sonst wären ja theoretisch alle Anwendungen miteinander kompatibel ;-))
- OnEncryptData \ OnDecryptData pro Datenblock (feste größe einstellbar \ an Framegrenzen) decodierbar (um z.B. teilweise verschlüsselte Kommunikation zu realisieren)
- Einstellbare adaptive Framegrößen-Übertragung (um ähnlich RFC2440 die für die Größenangabe benötigten Informationen zu reduzieren)
//Edit: Feature-Wunschliste ergänzt
Narses - Fr 06.04.07 23:33
Moin!
BenBE hat folgendes geschrieben: |
Protokoll-ID und Version über OI einstellbar (Sonst wären ja theoretisch alle Anwendungen miteinander kompatibel ;-)) |
Du hast den Transportprotokoll-Header in den "falschen Hals" gekriegt,
BenBE. ;) Es geht nämlich genau darum: die Komponente soll mit anderen Kompos, egal wo kompiliert, "reden" können. Es ist also ein Komponenten-Standard, der da etabliert werden soll. :mahn: Was du möchtest, muss erst im Anwendungsprotokoll definiert und behandelt werden: Anwendungsidentifikation und Versionierung! :idea:
BenBE hat folgendes geschrieben: |
OnEncryptData \ OnDecryptData pro Datenblock (feste größe einstellbar \ an Framegrenzen) decodierbar (um z.B. teilweise verschlüsselte Kommunikation zu realisieren) |
Ja, da hatte ich auch schon drüber nachgedacht... ;) aber den Gedanken wieder verworfen, weil mir das so schnell so komplex wurde (das interne Caching ist da nicht ganz unproblematisch), dass ich mir nicht mehr sicher war, ob ich die Kompo noch 2007 veröffentlicht kriege... 8) Fazit: mal sehen, vielleicht mal, wenn ich vieeel Zeit und Langeweile habe... :zwinker: Ansatz: definiere für verschlüsselte Frames entsprechende Token, dann geht das auch so. :D
BenBE hat folgendes geschrieben: |
Einstellbare adaptive Framegrößen-Übertragung (um ähnlich RFC2440 die für die Größenangabe benötigten Informationen zu reduzieren) |
Hehe, du gibst aber auch nicht auf :mrgreen: wenn du das unbedingt haben willst, dann mach dir mal Gedanken, wie dann das Transportprotokoll dafür aussehen soll und schick mir eine PN mit dem Vorschlag... (das ist nicht soo einfach, wie du dir das Vorstellst) :P Abgesehen davon: was willst du denn da aktuell einsparen? 1 Byte, wenn die Datenmenge < 255 Zeichen im Frame ist? Was soll das bringen? :gruebel: ;)
cu
Narses
Narses - So 03.06.07 18:27
Moin!
Neue Version (v1.04, Bugfixes und neue Funktionen), Details im ersten Beitrag. ;)
cu
Narses
Narses - Mo 04.06.07 14:20
Moin!
Neue Version 1.05 (FIX in der Ereignisreihenfolge des TNBFPAServer), Details im ersten Beitrag. ;)
cu
Narses
Narses - Sa 23.06.07 20:27
Moin!
Neue Komponenten- (v1.06) und Doku-Versionen (v1.04), Details - wie immer - im ersten Beitrag. ;)
//EDIT: Update der Komponente auf v1.07 (Bugfix)
cu
Narses
Sko - Do 05.07.07 10:21
Hallo Narses,
ich habe mit deinen Komponenten einen Chat gebastelt und wollte nun die Verschlüsselungsereignisse benutzen. Dazu habe ich eine RCx-Unit von negaH benutzt. Das ganze sieht jetzt auf beiden Seiten(Client und Server) so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure TMainForm.ClientEncryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); var ARCx: TRCxContext; begin RCxInit(ARCx,'<Passwort>'); RCxEncode(ARCx,Buffer,Buffer,Size); RCxDone(ARCx); end;
procedure TMainForm.ClientDecryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); var ARCx: TRCxContext; begin RCxInit(ARCx,'<Passwort>'); RCxDecode(ARCx,Buffer,Buffer,Size); RCxDone(ARCx); end; |
Allerdings kommen manchmal 2 gesendete Pakete als ein Paket beim Empfänger an, wodurch die Entschlüsselung nicht funktioniert.
Beispiel:
Server sendet
1B4BA8037D0EF2119A8E9FE15BF94E2B3EEBB6EA und
53E3DD9B62D668F41801ED0B8C336B98AECB77542B0D0720D8358D96D14C
Client empfängt
1B4BA8037D0EF2119A8E9FE15BF94E2B3EEBB6EA53E3DD9B62D668F41801ED0B8C336B98AECB77542B0D0720D8358D96D14C
BenBE - Do 05.07.07 10:52
Das ist kein Fehler der Komponente, sondern eine bewusste Eigenart der TCP API. Um die Trennung der Pakete musst Du dich ggf. selber probieren.
Einzige Möglichkeit hier ist, einen Block-Chiffre zu nutzen, der Positionsuabhängig\Block-Unabhängig ist.
Edit: Bzw. dafür sorgen, dass Du nach jedem Paket den Status des Chiffre speicherst und mit diesem beim nächsten Paket fortsetzt. Damit hast Du dann nämlich den Fall, dass du einen langen Datenstrom hast und Sender\Empfänger synchron laufen.
Narses - Do 05.07.07 11:00
Moin!
(Auf die Frage hab´ ich schon gewartet... ;))
Sko hat folgendes geschrieben: |
ich habe mit deinen Komponenten einen Chat gebastelt und wollte nun die Verschlüsselungsereignisse benutzen. Dazu habe ich eine RCx-Unit von negaH benutzt. |
Du verwendest also eine kontextabhängige Verschlüsselung; dabei ist wichtig zu wissen, dass diese Verschlüsselungen bei Streams positionsabhängig sind, also immer einen kompletten Stream mit einem Kontext verschlüsseln müssen, sonst klappt´s nicht! :mahn: ;)
Es gibt 2 grundsätzlich verschiedene Ansätze, wie man mit den TNBFPAs Verschlüsselung betreiben kann:
(1) Ohne die Encryption-Ereignisse: die Nutzdaten bereits verschlüsselt an Kommandosequenzen anfügen, dabei wird dann das Transportprotokoll im Klartext übertragen und die Daten sind separat verschlüsselt
(2) Mit den Encryption-Ereignissen: hier wird die gesamte Sitzung als Stream betrachtet, der dann auch (im Kontext) verschlüsselt werden muss, es wird damit also auch das Transportprotokoll verschlüsselt
Du hast nun die Variante 1,5 verwendet ;) weil du in den Ereignissen immer wieder einen neuen Kontext generierst. :idea: Und das klappt dann nicht, weil damit die Entschlüsselung nicht mehr klar kommt (durch das interne Caching der Komponente). :mahn:
Deshalb: entweder (1) verwenden und nur die Nutzdaten verschlüsseln (das kannst du dann wie schon von dir vorgestellt mit jeweils separatem Kontext machen) oder (2) korrekt verwenden. ;) Nämlich:
im Server:
- beim OnCreatePA den Kontext erstellen
- in den Ereignissen verwenden
- beim OnDestroyPA den Kontext freigeben
im Client:
- im OnReset den Kontext anlegen
- in den Ereignissen verwenden
- im OnDisconnect den Kontext freigeben
Fazit: für kontextabhängige Verschlüsselungen muss der Konktext auch für die gesamte Sitzungsdauer beibehalten werden. :mahn: ;)
cu
Narses
Sko - Do 05.07.07 11:10
Danke für eure Antworten :zustimm:
Also brauche ich für jeden Client einen eigenen TRCxContext ? Dann werd ich den an den ProtokollAdapter mit dran hängen, oder hab ich was falsch verstanden?
Narses - Do 05.07.07 11:25
Moin!
Sko hat folgendes geschrieben: |
Also brauche ich für jeden Client einen eigenen TRCxContext ? Dann werd ich den an den ProtokollAdapter mit dran hängen, oder hab ich was falsch verstanden? |
Yip, genau so hab´ ich mir das gedacht. ;)
cu
Narses
Sko - Do 05.07.07 13:07
Hmm, das wollte auch nicht so richtig, darum hab ich mich jetzt für Variante 1 entschieden, das geht ganz gut, danke für deine Hilfe.
BenBE - Do 05.07.07 13:10
@NArses: Kannst Du für die Variante 2 mal ein ganz kleines Demo schreiben???
Wünschenswert dabei wäre mit Beispiel, wie man während der Verbindung die Verschlüsslung an- und ausschalten kann (d.h. über einen Protokoll-Befehl dynamisch festlegen kann, was verschlüsselt wird und was nicht ...
Narses - Do 05.07.07 13:55
Moin!
Sko hat folgendes geschrieben: |
Hmm, das wollte auch nicht so richtig, |
Hm, OK, ist auch nicht soo ganz einfach, geb ich zu. :?
Sko hat folgendes geschrieben: |
darum hab ich mich jetzt für Variante 1 entschieden, das geht ganz gut, danke für deine Hilfe. |
Fein, viel Erfolg noch. :zustimm:
BenBE hat folgendes geschrieben: |
Kannst Du für die Variante 2 mal ein ganz kleines Demo schreiben? |
Ja, ich merk´ schon, das wird wohl nötig sein. :? Ich mach mal eins. ;)
BenBE hat folgendes geschrieben: |
Wünschenswert dabei wäre mit Beispiel, wie man während der Verbindung die Verschlüsslung an- und ausschalten kann (d.h. über einen Protokoll-Befehl dynamisch festlegen kann, was verschlüsselt wird und was nicht ... |
Das geht nicht :arrow: Variante (1) nehmen. Wenn (2), dann über die gesamte Verbindung. :mahn:
cu
Narses
Sko - Do 05.07.07 20:55
Narses hat folgendes geschrieben: |
BenBE hat folgendes geschrieben: |
Kannst Du für die Variante 2 mal ein ganz kleines Demo schreiben? |
Ja, ich merk´ schon, das wird wohl nötig sein. :? Ich mach mal eins. ;) |
Ja, das wäre super :D
Narses - Fr 06.07.07 01:04
Moin!
:oops: Leider war im
TProtocolAdapter noch ein sehr fieser kleiner Bug, der allerdings nur bei Verschlüsselung und mehr als einer Verbindung zum Tragen kam... :twisted: (da ich bisher die Verschlüsselung als "nice-to-have-feature" nicht wirklich verwendet habe und in meinem Testprojekt immer nur eine Verbindung verwendet wird, ist mir das bisher leider nicht aufgefallen :|). Togal, neue Version v1.08 der Komponente im ersten Beitrag zum Download; bei der Gelegenheit auch gleich noch was zu Verschlüsselung in die Doku (v1.05) eingepflegt. ;)
Jetzt zum versprochenen Beispiel für verschlüsselte Kommunikation (das komplette Projekt ist auch im Download-Archiv enthalten, s. erster Beitrag). Dazu werden wir diese kleine kontextsensitive Doof-Verschlüsselung verwenden, um jetzt nicht auch noch mit einem "komplizierten" Verfahren zu kämpfen: :zwinker:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| type TDemoCipher = class(TObject) private FEncryptionKey: Byte; FDecryptionKey: Byte; procedure DoEncryption(var Buffer; const Size: Integer; var Key: Byte); public procedure Reset; procedure Encrypt(var Buffer; const Size: Integer); procedure Decrypt(var Buffer; const Size: Integer); end;
implementation
procedure TDemoCipher.Reset; begin FEncryptionKey := 0; FDecryptionKey := 0; end;
procedure TDemoCipher.DoEncryption(var Buffer; const Size: Integer; var Key: Byte); var i: Integer; begin for i := 0 to Size-1 do begin TByteArray(Buffer)[i] := TByteArray(Buffer)[i] xor Key; Inc(Key); end; end;
procedure TDemoCipher.Encrypt(var Buffer; const Size: Integer); begin DoEncryption(Buffer,Size,FEncryptionKey); end;
procedure TDemoCipher.Decrypt(var Buffer; const Size: Integer); begin DoEncryption(Buffer,Size,FDecryptionKey); end; |
Folgender Code ist im Server des Chat-Demos, das als Basis dient, zu ergänzen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TServerMain.NBFPAServer1CreatePA(Sender: TObject; PA: TProtocolAdapter); begin PA.RefObject := TDemoCipher.Create; PA.OwnsRefObject := TRUE; end;
procedure TServerMain.NBFPAServer1EncryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin TDemoCipher(PA.RefObject).Encrypt(Buffer,Size); end;
procedure TServerMain.NBFPAServer1DecryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin TDemoCipher(PA.RefObject).Decrypt(Buffer,Size); end; |
Und hier die Änderungen/Ergänzungen im Client-Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| procedure TClientMain.FormCreate(Sender: TObject); begin FDemoCipher := TDemoCipher.Create; NBFPAClient1ConnectionStateChange(Self); end;
procedure TClientMain.NBFPAClient1Reset(Sender: TObject; PA: TProtocolAdapter); begin FDemoCipher.Reset; end;
procedure TClientMain.NBFPAClient1EncryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin FDemoCipher.Encrypt(Buffer,Size); end;
procedure TClientMain.NBFPAClient1DecryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin FDemoCipher.Decrypt(Buffer,Size); end;
procedure TClientMain.FormDestroy(Sender: TObject); begin FDemoCipher.Free; end; |
Mit diesen Ergänzungen läuft die Kommunikation jetzt verschlüsselt ab.
cu
Narses
Narses - Mo 09.07.07 18:45
Moin!
Tja :| das Thema Verschlüsselung hätte wohl noch etwas intensivere Aufarbeitung vertragen können... :oops: Leider war noch ein Bug diesbezüglich drin :arrow: neue Version v1.09 der Komponente im ersten Beitrag. ;)
Aber als "Entschädigung" :zwinker: hier noch ein Vorschlag, wie man eine vollduplex-symmetrische RC4-Verschlüsselung integrieren könnte. Zunächst die RC4-Adapter-Klasse, um eine RC4-Unit an den Protokoll-Adapter anzuknoten (die Aufrufe der RC4-Unit sind ggfs. entsprechend anzupassen, je nach Unit eben):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| uses ..., RC4;
type TRC4Adapter = class(TObject) private FEncryptionContext: TRC4Context; FDecryptionContext: TRC4Context; public constructor Create(const AKey: String); destructor Destroy; override; procedure Reset(const AKey: String); procedure Encrypt(var Buffer; const Size: Integer); procedure Decrypt(var Buffer; const Size: Integer); end;
implementation
constructor TRC4Adapter.Create(const AKey: String); begin inherited Create; Reset(AKey); end;
destructor TRC4Adapter.Destroy; begin RC4Done(FEncryptionContext); RC4Done(FDecryptionContext); inherited; end;
procedure TRC4Adapter.Reset(const AKey: String); begin RC4Init(FEncryptionContext,AKey); RC4Init(FDecryptionContext,AKey); end;
procedure TRC4Adapter.Encrypt(var Buffer; const Size: Integer); begin RC4Code(FEncryptionContext,Buffer,Buffer,Size); end;
procedure TRC4Adapter.Decrypt(var Buffer; const Size: Integer); begin RC4Code(FDecryptionContext,Buffer,Buffer,Size); end; |
Die Einbindung ins Demo-Server-Projekt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TServerMain.NBFPAServer1CreatePA(Sender: TObject; PA: TProtocolAdapter); begin PA.RefObject := TRC4Adapter.Create('*geheim*'); PA.OwnsRefObject := TRUE; end;
procedure TServerMain.NBFPAServer1EncryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin TRC4Adapter(PA.RefObject).Encrypt(Buffer,Size); end;
procedure TServerMain.NBFPAServer1DecryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin TRC4Adapter(PA.RefObject).Decrypt(Buffer,Size); end; |
Und hier noch der Client:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| procedure TClientMain.FormCreate(Sender: TObject); begin FRC4Adapter := TRC4Adapter.Create(''); NBFPAClient1ConnectionStateChange(Self); end;
procedure TClientMain.NBFPAClient1Reset(Sender: TObject; PA: TProtocolAdapter); begin FRC4Adapter.Reset('*geheim*'); end;
procedure TClientMain.NBFPAClient1EncryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin FRC4Adapter.Encrypt(Buffer,Size); end;
procedure TClientMain.NBFPAClient1DecryptData(Sender: TObject; PA: TProtocolAdapter; var Buffer; const Size: Integer); begin FRC4Adapter.Decrypt(Buffer,Size); end;
procedure TClientMain.FormDestroy(Sender: TObject); begin FRC4Adapter.Free; end; |
Viel Erfolg! :zustimm:
cu
Narses
//EDIT: hatte vergessen, den RC4-Kontext im Destruktor der Adapterklasse wieder zu leeren, ist jetzt aber mit drin. ;)
Sko - Di 10.07.07 06:34
Super, werd ich gleich mal ausprobieren, Danke :zustimm:
Narses - Di 10.07.07 09:16
Moin!
Sko hat folgendes geschrieben: |
Super, werd ich gleich mal ausprobieren, Danke :zustimm: |
Bitte ;) Rückmeldung erwünscht. :les: :)
cu
Narses
Sko - Di 10.07.07 20:19
Funktioniert super, keine Probleme, alles läuft wie´s soll, vielen Dank nochmal :zustimm:
Narses - Fr 13.07.07 08:33
Moin!
(Abgetrennt von
hier [
http://www.delphi-forum.de/viewtopic.php?p=451216#451216])
Neotracer64 hat folgendes geschrieben: |
Wie könnte ich jetzt am einfachsten mit den Kompos Datenübertragungen zwischen Server <> Client realisieren?
[...]
Es macht schon Sinn, wenn man als Server eine Datei an mehrere Clients oder nur an einen schicken möchte.
Von Client zu Server macht es schon weniger Sinn, aber ich hatte da so eine Art CVS Idee im Kopf, wo jeder seine Projekt-Dateien auch an den Server schickt, der sie dann verwaltet und mit anderen synchronisiert. Sozusagen als Sammelstelle.
[...]
Vlt. hast du eine Idee für mich, wie ich also einen Server <> Client DateiTransfer mit deinen Komponenten am besten hinbekomme? |
Die Idee ist die gleiche, wie im BinProtoTut-Chat, nur dass du im Server nicht den Code verwendest, um die FileStreamChunks weiterzuleiten, sondern dort zu speichern. Ich mache mal ein konkretes Beispiel dazu, dauert aber etwas (evtl. heute Abend). ;)
cu
Narses
Narses - Fr 13.07.07 23:26
Moin!
Hier das versprochene Demo-Projekt für einen minimalen Filetransfer. Der Client verbindet sich sofort mit dem Server (Host auf "localhost" in der Komponente voreingestellt, ggfs. ändern) und kann dann auf Buttonklick und Dateiauswahlbox eine Datei an den Server senden (der Button bleibt solange deaktiviert, bis der Transfer fertig ist). Der Server speichert alle Dateien, die er von Clients erhält, im Verzeichnis der EXE ab, der Name wird aus der Anzahl der bisher gesendeten Dateien und ".txt" gebildet (ggfs. also umbenennen). Es findet keine Fehlererkennung oder sonstiges statt, das Beispiel ist wirklich sehr minimal gehalten. Im Anhang befindet sich das komplette Projekt zum selbst Ausprobieren.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82:
| unit UClient;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, NarsesBFPA, UProtocol;
type TfrmClient = class(TForm) OpenDialog: TOpenDialog; BtnSend: TButton; NBFPAClient: TNBFPAClient; procedure FormShow(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure BtnSendClick(Sender: TObject); procedure NBFPAClientRequestData(Sender: TObject; PA: TProtocolAdapter); procedure FormCreate(Sender: TObject); private FOutStream: TFileStream; public end;
var frmClient: TfrmClient;
implementation
{$R *.dfm}
procedure TfrmClient.FormCreate(Sender: TObject); begin FOutStream := NIL; end;
procedure TfrmClient.FormShow(Sender: TObject); begin NBFPAClient.SessionName := DateTimeToStr(Now); NBFPAClient.Connect; end;
procedure TfrmClient.BtnSendClick(Sender: TObject); begin if OpenDialog.Execute then begin BtnSend.Enabled := FALSE; FOutStream := TFileStream.Create(OpenDialog.FileName, fmOpenRead or fmShareDenyWrite); NBFPAClient.Send; end; end;
procedure TfrmClient.NBFPAClientRequestData(Sender: TObject; PA: TProtocolAdapter); const CHUNK_SIZE = 2048; var Remaining: Integer; Cmd: TCmdSeq; begin if Assigned(FOutStream) then begin Remaining := FOutStream.Size -FOutStream.Position; if (Remaining > CHUNK_SIZE) then Remaining := CHUNK_SIZE; Cmd := TCmdSeq.Create(CMD_CHUNK); Cmd.Add(FOutStream,Remaining); NBFPAClient.SendAndFree(Cmd); if (FOutStream.Position = FOutStream.Size) then begin FreeAndNil(FOutStream); Cmd := TCmdSeq.Create(CMD_STOP); NBFPAClient.SendAndFree(Cmd); BtnSend.Enabled := TRUE; end; end; end;
procedure TfrmClient.FormClose(Sender: TObject; var Action: TCloseAction); begin FreeAndNil(FOutStream); NBFPAClient.Disconnect; end;
end. |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70:
| unit UServer;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, NarsesBFPA, UProtocol;
type TfrmServer = class(TForm) NBFPAServer: TNBFPAServer; ListBox: TListBox; procedure NBFPAServerConnectionsChange(Sender: TObject); procedure FormShow(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure NBFPAServerClientExecute(Sender: TObject; PA: TProtocolAdapter); private public end;
var frmServer: TfrmServer;
implementation
{$R *.dfm}
procedure TfrmServer.NBFPAServerConnectionsChange(Sender: TObject); begin ListBox.Items.Assign(NBFPAServer.Connections); end;
procedure TfrmServer.FormShow(Sender: TObject); begin NBFPAServer.Open; end;
procedure TfrmServer.NBFPAServerClientExecute(Sender: TObject; PA: TProtocolAdapter); begin case PA.CurrentToken of CMD_CHUNK: begin if (PA.RefObject = NIL) then begin PA.RefObject := TFileStream.Create( ExtractFilePath(Application.ExeName)+ IntToStr(frmServer.Tag)+'.txt', fmCreate); PA.OwnsRefObject := TRUE; frmServer.Tag := frmServer.Tag +1; end; TFileStream(PA.RefObject).Write(PA.Inbound.Data[1]^, PA.Inbound.FrameSize[1]); end; CMD_STOP: begin TFileStream(PA.RefObject).Free; PA.RefObject := NIL; end; end; end;
procedure TfrmServer.FormClose(Sender: TObject; var Action: TCloseAction); begin NBFPAServer.Close; end;
end. |
cu
Narses
Neotracer64 - Sa 14.07.07 11:03
Danke für deine Mühen Narses. :D
Wenn ich noch Fragen habe, melde ich mich wieder hier. ;)
Narses - Mo 16.07.07 00:38
Moin!
Neue Version der Kompo (v1.10) und der Doku (v1.06), Details und Download - wie immer - im ersten Beitrag. ;)
cu
Narses
MrOuzo - Di 21.08.07 13:51
Hallo Narses,
bei mir kommt bei der Installation unter Delphi5 Ent. UpdPack.1 folgende Fehlermldung:
[Fehler] NarsesBFPA.pas(430): Eine statische Methode kann nicht überschrieben werden
dabei handelt es sich um diese QuellCodeZeile
procedure InsertObject(Index: Integer; const S: string; AObject: TObject); override;
Gruß
MrOuzo
Narses - Di 21.08.07 14:28
Moin!
MrOuzo hat folgendes geschrieben: |
bei mir kommt bei der Installation unter Delphi5 Ent. UpdPack.1 folgende Fehlermldung:
Delphi-Compiler hat folgendes geschrieben: | [Fehler] NarsesBFPA.pas(430): Eine statische Methode kann nicht überschrieben werden |
dabei handelt es sich um diese QuellCodeZeile
Delphi-Quelltext 1:
| procedure InsertObject(Index: Integer; const S: string; AObject: TObject); override; | |
Ich schau´s mir mal an; ich melde mich wieder (kann etwas dauern, da ich kein D5 habe; was spricht gegen D7? :?)
cu
Narses
MrOuzo - Di 21.08.07 15:09
Hi Narses,
ich hab halt leider nur D5
Gruß
MrOuzo
Narses - Di 21.08.07 20:30
Moin!
MrOuzo hat folgendes geschrieben: |
ich hab halt leider nur D5 |
Nunja, ich empfehle mal pauschal D7, besser ist das. :zustimm:
Mit Hilfe von
BenBE, der freundlicherweise für mich unter D5 "gesucht" hat, gibt es eine neue Version mit den notwendigen Anpassungen für D5 :arrow: wie immer im ersten Beitrag. :les: Sollte jetzt laufen. :)
cu
Narses
BenBE - Di 21.08.07 20:33
@Narses: Ob der Bug allerdings unter D4 oder D6 auch auftritt, hab ich nicht untersucht ;-)
Narses - Di 21.08.07 20:38
Moin!
BenBE hat folgendes geschrieben: |
Ob der Bug allerdings unter D4 |
Unterhalb von D5 supporte ich die Kompo nicht; und D5 auch nur, weil du mir dabei hilfst, sonst wäre das auch Essig. :nixweiss:
BenBE hat folgendes geschrieben: |
oder D6 auch auftritt, hab ich nicht untersucht ;-) |
Ich teste die Tage mal D6, unter D7pro hab ich´s grad selbst getestet. :D
cu
Narses
MrOuzo - Mi 22.08.07 13:45
Hallo Narses, BenBE,
Superservice, danke, jetzt gehts zu installieren. Werde es dann gleich mal testen. :D
D7 werde ich auch einsetzen, habe aber noch soooo viele Kompos von D5 die ich nicht umheben möchte.
Gruß
MrOuzo
Boldar - Do 26.06.08 16:47
Hallo, Ich weiss, dass der Threat uralt ist, aber ich habe keine Ahnung, wie ich die Komponenten installieren soll. Ich benutze Delphi 2006, und da gibt es die in dem PDF beschriebenen Menüpunkte nicht. Kann mir villeicht jemand sagen, wie es geht??
Narses - Do 26.06.08 17:12
Moin!
Boldar hat folgendes geschrieben: |
aber ich habe keine Ahnung, wie ich die Komponenten installieren soll. Ich benutze Delphi 2006, |
Was spricht gegen D7? Ich sehe zu D2006 keine Vorteile... :nixweiss:
Boldar hat folgendes geschrieben: |
und da gibt es die in dem PDF beschriebenen Menüpunkte nicht. Kann mir villeicht jemand sagen, wie es geht?? |
Du könntest probieren ein neues Package zu erstellen und die Komponenten dann da rein zu installieren. :idea:
cu
Narses
DelphiMarkus - Fr 27.06.08 07:32
Hallo!
Ich wollte das hier auch mal probieren, aber leider meldet sich bei mir AntiVir. Er meint, bei der "Server.exe" etwas gefunden zu haben.
Ist das schon bekannnt, ich habe auf die schnelle nichts darüber in diesem Thema gefunden.
Ich glaube nicht das da wirklich was dran ist.
Ich kann das Programm auch nicht starten, AntiVir verweigert das. :cry:
Narses - Fr 27.06.08 10:08
Moin!
DelphiMarkus hat folgendes geschrieben: |
Ich wollte das hier auch mal probieren, aber leider meldet sich bei mir AntiVir. Er meint, bei der "Server.exe" etwas gefunden zu haben.
Ist das schon bekannnt, ich habe auf die schnelle nichts darüber in diesem Thema gefunden. |
Was für eine Server.exe? :gruebel: Mein Code und meine EXEn sind idR geprüft, wenn ich was rausgebe. Allerdings schlägt häufig die Heuristik zu, wenn man Server-Sockets in UPX-gepackten EXEn öffnet, vielleicht ist es das schon. :nixweiss:
cu
Narses
DelphiMarkus - Mo 30.06.08 07:37
Die EXE liegt unter diesem Pfad:
"TNBFPA_v111\Code\Server.exe"
AntiVir meint einen Virus oder ein anderes unerwünschtes Programm gefunden zu haben.
Hier ist der Text aus AntiVir dazu:
Zitat: |
In der Datei '...\TNBFPA_v111\Code\Server.exe'
wurde ein Virus oder unerwünschtes Programm 'TR/ATRAPS.Gen' [trojan] gefunden.
Ausgeführte Aktion: Zugriff verweigern |
Narses hat folgendes geschrieben: |
Mein Code und meine EXEn sind idR geprüft, wenn ich was rausgebe. Allerdings schlägt häufig die Heuristik zu, wenn man Server-Sockets in UPX-gepackten EXEn öffnet, vielleicht ist es das schon. :nixweiss: |
Ich weiß es leider auch nicht...
Narses - Mo 30.06.08 08:22
Moin!
DelphiMarkus hat folgendes geschrieben: |
AntiVir meint einen Virus oder ein anderes unerwünschtes Programm gefunden zu haben. |
Das ist eine False-Positive-Meldung; das ist definitiv kein Tojaner. ;) (schätze, Serversocket+UPX schlagen da zu)
Lösch das Ding einfach nach dem Auspacken und übersetz´ dir das Demoprojekt selbst nochmal neu, dann hast du das Ganze "clean". :idea:
cu
Narses
DelphiMarkus - Mo 30.06.08 08:48
Danke für den Tipp, jetzt klappt es! :zustimm:
Vielen Dank,
Maxi
Sirke - Mo 30.06.08 09:11
Hey Narses,
Danke für diese schöne Komponente! Habe bisher noch keine Bugs gefunden, außer dass meine Anti-Viren Software die Server.exe nicht mag ;-)
Finde jedoch, dass die Angabe "Verschlüsselung" ein Witz ist und man für spätere Versionen - solltest du das geplant haben - eine stärkere Verschlüsselung verwenden sollte. Außerdem wäre eine asymmetrischer Schlüsselaustauch bzw. Hybride-Verschlüsselung sinnvoll!
Zusätzlich wäre eine Daten-Kompression noch sinnvoll!
Narses - Mo 30.06.08 09:19
Moin!
Sirke hat folgendes geschrieben: |
Danke für diese schöne Komponente! Habe bisher noch keine Bugs gefunden, |
Danke. ;)
Sirke hat folgendes geschrieben: |
Finde jedoch, dass die Angabe "Verschlüsselung" ein Witz ist [...] eine stärkere Verschlüsselung verwenden sollte |
Die Komponenten verschlüsseln doch gar nix... :gruebel: sondern stellen dir Ereignisse bereit, um diese Verschlüsselung selbst in der gewünschten "stärke" auszuführen! :idea: Es liegt also allein an dir, wie "witzhaft" diese Verschlüsselung ausfällt. :nixweiss:
Sirke hat folgendes geschrieben: |
Außerdem wäre eine asymmetrischer Schlüsselaustauch bzw. Hybride-Verschlüsselung sinnvoll! |
Siehe oben, das ist nicht Aufgabe der Komponenten. ;)
Sirke hat folgendes geschrieben: |
Zusätzlich wäre eine Daten-Kompression noch sinnvoll! |
Klar wäre das sinnvoll; ist doch open-source, wir warten auf deinen Vorschlag. :)
cu
Narses
Sirke - Mo 30.06.08 10:09
Narses hat folgendes geschrieben: |
Sirke hat folgendes geschrieben: | Finde jedoch, dass die Angabe "Verschlüsselung" ein Witz ist [...] eine stärkere Verschlüsselung verwenden sollte | Die Komponenten verschlüsseln doch gar nix... :gruebel: sondern stellen dir Ereignisse bereit, um diese Verschlüsselung selbst in der gewünschten "stärke" auszuführen! :idea: Es liegt also allein an dir, wie "witzhaft" diese Verschlüsselung ausfällt. :nixweiss:
Sirke hat folgendes geschrieben: | Außerdem wäre eine asymmetrischer Schlüsselaustauch bzw. Hybride-Verschlüsselung sinnvoll! | Siehe oben, das ist nicht Aufgabe der Komponenten. ;) |
Okay, habe mir das ganze nun noch einmal genauer angesehen und festgestellt, dass ich etwas voreilig war ;-) Damit wird die Komponente immer Interessanter für mich!
Narses hat folgendes geschrieben: |
Sirke hat folgendes geschrieben: | Zusätzlich wäre eine Daten-Kompression noch sinnvoll! | Klar wäre das sinnvoll; ist doch open-source, wir warten auf deinen Vorschlag. :) |
Ich werde mich dran setzen. Hoffentlich müsst ihr nicht zu lange warten ;-)
MfG Sirke
BenBE - Mo 30.06.08 10:26
Sirke hat folgendes geschrieben: |
Narses hat folgendes geschrieben: | Sirke hat folgendes geschrieben: | Zusätzlich wäre eine Daten-Kompression noch sinnvoll! | Klar wäre das sinnvoll; ist doch open-source, wir warten auf deinen Vorschlag. :) | Ich werde mich dran setzen. Hoffentlich müsst ihr nicht zu lange warten ;-)
MfG Sirke |
Kannst das ganze ja auch gleich als Tutorial schreiben, wie man für sowas vorgehen muss.
Narses - Do 04.09.08 19:08
Moin!
Update auf Version 1.12 der Komponente (Bugfixes), Details - wie immer - im ersten Beitrag. ;)
cu
Narses
smallsmoker - Fr 19.09.08 18:57
ich hoffe das ich mit einer bedankung (die ja eigenlich nix zum thema beiträgt) nicht gegen die foren regeln hier verstoße aber ich kann nicht anders :)
Ich finde einfach fantastisch was du hier leistest !
bitte mach weiter so !
mfg smallsmoker (der sich grad durch dein binär protokoll tut arbeitet)
Narses - Fr 19.09.08 19:17
Moin und :welcome: im Forum!
smallsmoker hat folgendes geschrieben: |
Ich finde einfach fantastisch was du hier leistest ! |
Oh, danke. :beer:
smallsmoker hat folgendes geschrieben: |
(der sich grad durch dein binär protokoll tut arbeitet) |
Viel Erfolg! :zustimm:
cu
Narses
smallsmoker - Fr 19.09.08 19:30
ich habe gerade versucht TNBFPA zu installieren (also die visuellen kompos) aber leider gibt es in delphi 2007 kein "Komponente Installieren" (siehe screenshot)
ich weiß ich könnte sie auch dynamisch erzeugen aber das möchte ich nicht so gerne (bin faul -.-)
gibt es dafür eine lösung ?
mfg smallsmoker
Narses - Fr 19.09.08 19:35
Moin!
smallsmoker hat folgendes geschrieben: |
ich habe gerade versucht TNBFPA zu installieren (also die visuellen kompos) aber leider gibt es in delphi 2007 kein "Komponente Installieren" (siehe screenshot) |
Sorry, ich habe kein D2007 und kenne es daher nicht; deshalb kann ich hier nicht wirklich gut helfen... :nixweiss:
smallsmoker hat folgendes geschrieben: |
gibt es dafür eine lösung ? |
Ich habe mal gehört, dass man ein neues Package anlegen und dann die Kompos da rein installieren kann. Ob und wie das geht, keine Ahnung. :?
cu
Narses
smallsmoker - Fr 19.09.08 19:48
smallsmoker hat folgendes geschrieben: |
Ich habe mal gehört, dass man ein neues Package anlegen und dann die Kompos da rein installieren kann. Ob und wie das geht, keine Ahnung. :? |
hat perfekt geklappt damit alle was davon haben habe ich einfach ein kleines video < 1.5 mb davon gemacht wies geht :)
mfg smallsmoker
smallsmoker - Di 23.09.08 17:04
erstmal sorry für den doppelpost, ich finde es ja eingentlich ziemlich dreißt wenn leute nach fertigem code fragen aber ich hoffe du bisst mir nicht böse narses.
Also du hast ja gepostet wie man (mit minimalen mitteln) eine datei vom clienten zum server senden kann, das funktioniert auch wunderbar.
Ich habe es nun so für mich umfunktioniert das der dateiname mitgesendet wird und man auch vom server zum clienten senden kann, aber wenn der client (oder der server) während einer übertragung disconnectet gibt es ein riesiges chaos ... könntest du vieleicht (wenn du zeit und lust hast) eine ausführlichere demo (muss nich kommentiert sein) für dateiübertragung mit deiner komponente posten ?
mfg smallsmoker
smallsmoker - Di 23.09.08 17:27
ich trau mich kaum das zu schreiben aber, da wird doch von client -> server -> client gesendet ... (die demo nach der ich gefragt habe wäre
client -> server & server -> client)
:duck: sry ich bin so faul :D, ich arbeite den mal-chat zu client -> server & server -> client selber um, mach dir keine arbeit xD
mfg smallsmoker
edit: mir ist grade noch etwas eingefallen, wie kann ich felhler die auftreten verwerfen ? so wie bei den normalen winsockets ? einfach ErrorCode = 0 ?
Narses - Di 23.09.08 20:38
Moin!
smallsmoker hat folgendes geschrieben: |
wie kann ich felhler die auftreten verwerfen ? so wie bei den normalen winsockets ? einfach ErrorCode = 0 ? |
RTFM :mrgreen: TNBFPA-Doku, Seite 10 unten... ;)
cu
Narses
smallsmoker - Sa 11.10.08 02:54
ist eigenlich eine delphi 2009 version geplant ?
Narses - Sa 11.10.08 18:52
Moin!
smallsmoker hat folgendes geschrieben : |
ist eigenlich eine delphi 2009 version geplant ? |
Nein.
Ich will ganz ehrlich sein: ich habe ein D7pro gekauft und bezweifle sehr, dass ich jemals wieder Geld für eine andere/neuere (Delphi-)Version ausgeben werde. :| Wenn mein Code mit neueren Delphi-Versionen kompatibel ist, dann ist das schön. :) Wenn nicht, Pech gehabt. :nixweiss: Zum Win32-Programmieren reicht D7pro mehr als aus.
cu
Narses
Narses - So 28.02.10 23:21
Moin!
Dank eines kleinen Tricks war die Umstellung auf D2010 (D2k9 empfehle ich nicht, das ist unicode-mäßig noch zu buggy) gar nicht so viel Arbeit, wie gedacht. :nixweiss:
Es gibt also jetzt eine D2010-fähige Version zum Download im ersten Beitrag. ;)
cu
Narses
matze - Mo 01.03.10 08:59
Narses hat folgendes geschrieben : |
(D2k9 empfehle ich nicht, das ist unicode-mäßig noch zu buggy) |
Inwiefern das?
Narses - Mo 01.03.10 12:48
Moin!
matze hat folgendes geschrieben : |
Narses hat folgendes geschrieben : | (D2k9 empfehle ich nicht, das ist unicode-mäßig noch zu buggy) | Inwiefern das? |
Insofern dass Methoden AnsiStrings entgegen nehmen und Unicode-Strings abliefern (.SendText/.ReceiveText) oder dass einige AnsiXxx-Funktionen Unicode-Strings zurückgeben (OK, das gilt auch für D2010). :nixweiss: Ich kann
Martok nur zustimmen, eine Umstellung, bei der die VCL inkompatibel zu sich selbst wird, naja... :|
cu
Narses
Daniel775 - Do 15.09.11 18:45
Guten Abend allerseits.
Bin durch Zufall auf diesen Thread gestossen und wollte mal fragen, ob ich hier richtig bin. Ich würde gerne Einstellungen von einem Clientprogramm zum Serverprogramm schicken.
In anderen Threads hab ich gelesen, das man keine records wählen sollte um das zu realisieren bzw. man sollte keine records über das socket schieben. Weil man nie weiss was, wann, wieviel ankommt.
Ist es mit diesem Protokoll hier realisierbar?
Das ich beim clienten ein record in ein Memorystream verpacke diesen über das Socket zum Server schicke und der Server aus dem stream wieder ein record macht.
Hoffe auf zahlreiche Reaktionen und evtl Beispiele ...
Narses - Do 15.09.11 21:56
Moin und :welcome: in der Entwickler-Ecke!
Daniel775 hat folgendes geschrieben : |
Ich würde gerne Einstellungen von einem Clientprogramm zum Serverprogramm schicken. |
Grundsätzlich geht das, ja. ;)
Daniel775 hat folgendes geschrieben : |
In anderen Threads hab ich gelesen, das man keine records wählen sollte um das zu realisieren bzw. man sollte keine records über das socket schieben. Weil man nie weiss was, wann, wieviel ankommt. |
Daniel775 hat folgendes geschrieben : |
Das ich beim clienten ein record in ein Memorystream verpacke |
Das Problem ist das Serialisieren des records, nicht das Transportieren eines Bytestreams. :idea:
Daniel775 hat folgendes geschrieben : |
Ist es mit diesem Protokoll hier realisierbar? |
Solange da ein record im Spiel ist, wird das mit jeder Transportart Probleme geben. :nixweiss: Die Kunst ist also die Vermeidung des records, nicht der Einsatz des Protokolls (da kommst du eh nicht drum rum, irgendwie musst du die Daten ja wieder auseinanderpflücken). :)
Daniel775 hat folgendes geschrieben : |
diesen über das Socket zum Server schicke und der Server aus dem stream wieder ein record macht. |
Ganz anderer Ansatz (sofern du auf dieser Kompo aufsetzen willst): Mach aus deinen Einstellungen ein Objekt, diesem verpasst du eine Methode, welche die Eigenschaften an ein TCmdSeq-Objekt übergeben kann. Dann brauchst du noch eine Methode, welche die Eigenschaften wieder aus einem Protokolladapter lesen kann. Dann sollte das klappen.
cu
Narses
Daniel775 - Do 15.09.11 22:17
Hallo Narses,
danke für deine Antwort.
Zitat: |
Mach aus deinen Einstellungen ein Objekt
|
Sollte kein Problem sein.
Zitat: |
diesem verpasst du eine Methode
|
Ist auch kein Problem
Zitat: |
welche die Eigenschaften an ein TCmdSeq-Objekt übergeben kann
|
Da wird es hapern. Ich hab mir die .add Procedure mal angesehen. Ich kann da kein Objekt übergeben, oder? Wie kann ich da ansetzen?
Zitat: |
Dann brauchst du noch eine Methode, welche die Eigenschaften wieder aus einem Protokolladapter lesen kann
|
Die Frage die ich mir da stelle ist, wie kommt das Objekt dann im Adapter an um es abzuholen?
Narses - Do 15.09.11 22:30
Moin!
Daniel775 hat folgendes geschrieben : |
Da wird es hapern. Ich hab mir die .add Procedure mal angesehen. Ich kann da kein Objekt übergeben, oder? Wie kann ich da ansetzen? |
Der "Witz" an dem TCmdSeq-Objekt ist ja, dass es keine strukturierten Daten annimmt, sondern immer nur einfache Datentypen. Kennst du die Methode und das Konzept von TPersistent.Assign() und .AssignTo()? Hier ist das genau so: in der Methode, die das Objekt übergeben soll gehst du jede Eigenschaft durch und schreibst sie in das TCmdSeq-Objekt. Das ist die einzige Möglichkeit bei einer Änderung des Objekts keinen Datenmatsch zu produzieren. Ändert sich das Objekt, muss auch ein entsprechend geändertes Transport-Verfahren benutzt werden (hier: ein anderes Token).
Alternative wäre die Delphi-eigene Methode zum De-/Serialisieren von Objekte, so wie es die VCL/IDE mit den Komponenten tut. Ist aber bischen frickelig. :?
Noch ein anderer Ansatz ist die Transformation in das INI-Format, dieses als Text transportieren und auf der anderen Seite wieder aus dem INI-Format lesen.
Du merkst schon, egal was man macht, wenn man einfach nur "auf der einen Seite rein und auf der anderen genau so wieder raus" haben will, geht das gar nicht so einfach... jedenfalls nicht, wenn es "sauber" sein soll. :nixweiss:
cu
Narses
Daniel775 - Fr 16.09.11 12:38
Zitat: |
...gehst du jede Eigenschaft durch und schreibst sie in das TCmdSeq-Objekt. |
Das heisst Praktisch für jede Eigenschaft in meinem Objekt ein neues Token und wenn sich die Eigenschaft oder das Objekt verändert diesse Änderung wieder über die Methode an das TCmdSeq-Objekt schicken. Hab ich das richtig verstanden?
Ich mache das im Moment mit einer .ini Datei. Und suche jetzt eine Client <> Server Lösung. Das würde bedeuten, das auch das Terminatorzeichen Protokoll für diese Aufgabe völlig ausreichend wäre!?
Narses - Fr 16.09.11 12:59
Moin!
Daniel775 hat folgendes geschrieben : |
Zitat: | ...gehst du jede Eigenschaft durch und schreibst sie in das TCmdSeq-Objekt. | Das heisst Praktisch für jede Eigenschaft in meinem Objekt ein neues Token und wenn sich die Eigenschaft oder das Objekt verändert diesse Änderung wieder über die Methode an das TCmdSeq-Objekt schicken. Hab ich das richtig verstanden? |
Ähm, nein. :? Machen wir mal ein Beispiel:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| type TSettings = class(TObject) private FStr: String; FInt: Integer; public function AsCmdSeq: TCmdSeq; property Str: String read FStr write FStr; property Int: Integer read FInt write FInt; end;
TForm1 = class(TForm) NBFPAClient1: TNBFPAClient; NBFPAServer1: TNBFPAServer; Button1: TButton; procedure Button1Click(Sender: TObject); procedure NBFPAServer1ClientExecute(Sender: TObject; PA: TProtocolAdapter); public Settings: TSettings; end;
implementation
function TSettings.AsCmdSeq: TCmdSeq; begin Result := TCmdSeq.Create(123); Result.Add(FStr); Result.Add(FInt); end;
procedure TForm1.Button1Click(Sender: TObject); begin NBFPAClient1.SendAndFree(Settings.AsCmdSeq); end;
procedure TForm1.NBFPAServer1ClientExecute(Sender: TObject; PA: TProtocolAdapter); begin case PA.CurrentToken of 123: begin Settings.Str := PA.Inbound.Strings[1]; Settings.Int := PA.Inbound.AsInt[2]; end; 122: begin Settings.Str := PA.Inbound.Strings[1]; end; end; end; |
Daniel775 hat folgendes geschrieben : |
Ich mache das im Moment mit einer .ini Datei. Und suche jetzt eine Client <> Server Lösung. Das würde bedeuten, das auch das Terminatorzeichen Protokoll für diese Aufgabe völlig ausreichend wäre!? |
Jedes Protokoll ist für die Übertragung geeignet, egal welches. Damit wird ja nur Transportiert. Wie du die Einstellungen verwaltest, also als Objekt, Record, INI-Text, etc. ist doch davon unabhängig. :nixweiss:
Um die Frage zu beantworten: ja, das Terminatorzeichen-Protokoll wäre dafür auch ausreichend. ;)
Machen wir das mal anders: was soll das denn werden und worauf legst du Wert bei der Sache? :lupe:
cu
Narses
Daniel775 - Fr 16.09.11 19:20
Zitat: |
Machen wir das mal anders: was soll das denn werden und worauf legst du Wert bei der Sache?
|
Mein aktuelles Projekt ist eine Datenbankgestützte Zeiterfassung. Oder einfach gesagt, eine Stempeluhr. Mit Mitarbeiter, Urlaubs -und Fehlzeitenverwaltung. Es gibt ein UserFront-End als eigenständiges Programm wo halt eingestempelt wird und ein Admintool. Das Admintool möchte ich halt mit gewissen Funktionen ausstatten.
Wartungsmodus ein/aus, Anzeigedauer der letzten Einstempelungen usw.
Diese möchte ich mittels Client/Serververbindung an die Stempeluhr schicken. In Form einer Datei die dann beim start immer eingelesen wird. Dein Beispiel wird mir sehr helfen das umzusetzen .... vielen lieben Dank. :D
Das mit den Versionen in der ClientExecute Procedure gefällt mir und ist ein sehr guter Tipp.
Grüße
Martok - Mo 05.03.12 23:13
Hallo,
ich baue momentan ein RPC-Interface rund um NBFPA. Das ganze läuft so ab, dass man dann z.B. ein OnEntityCall-Event bekommt, mit den Parametern: (Connection, EntityRef, Function, Parameter). Die kann man dann in Anwendungs-Code weiterverteilen an die richtigen Handler.
Das Problem ist jetzt, die Parameter richtig zu zerpflücken. Wenn ich einfach nur die TInboundFrameList übergebe, ist das unhandlich, da ja die ersten paar Argumente "intern" sind: Entity,FunctionCode etc.
Einfach die verarbeiteten ArgumentFrames aus der Liste löschen (damit die Paremter vorwandern) geht nicht, das kollidiert mit der NBFPA-Internen Verarbeitung. Ich würde die also gerne vorher zerpflücken und eventuell in ein Array of Const oder Variant reinschieben. Das ist an sich auch okay, aber die Überdeckung der damit darstellbaren Datentypen zu den mit NBFPA übertragbaren Formate ist gelinde gesagt gering. Selbst mit Auto-Konvertierung (Datentypen kann man ja mitsenden) wird das entweder nicht einfach oder bandbreitentechnisch eher schlecht.
Hat mit sowas jemand Erfahrung? Ich bin auch für Alternativkonzepte immer offen. Alles, was im Endeffekt einfach zu verwenden ist.
Narses - Di 06.03.12 23:54
Moin!
An einem Stück Dispatcher-Code im OnExecute oder einer auf´s Nötige reduzierten Kopie der Parameter aus der InboundFrameList wird wohl irgendwie kein Weg vorbeiführen... :nixweiss:
Aber, ehrlich gesagt, mir ist sowieso schleierhaft, wie du den Methoden-Call (abstrahiert) "durchreichen" willst. :gruebel: Das geht doch immer nur für bekannte Methoden, oder klemmt mir da wieder ein Synapse? :lupe:
cu
Narses
BenBE - Mi 07.03.12 00:04
*Mit Zaun wedel* array of const AKA array of TVarRec :mrgreen:
Martok - Mi 07.03.12 00:16
Hallo, danke für die Antwort.
Ja, Dispatcherkrams ist da. Geht nur noch darum wie die aussehen soll ;)
Kurzfassung: es gibt z.B. auf dem Client eine Funktion:
EntityCall(EntityID: Cardinal; Function: Word; Params: ????).
Die baut daraus eine TCmdSeq mit PacketID ENTITY_CALL und den Argumenten EntityID, Function, Param1, Param2, ..., ParamN
Auf dem Server wird im OnExecute das zerpflückt und ein OnEntityCall(Entity, Func, ???) aufgerufen.
Dort bindet der User seinen Dispatcher zu den Entities an und diese wiederum machen dann je nach Function-Code was.
Die Parameter kann man als array of const reinschieben und auf der anderen Seite wieder so parsen. Das geht, Problem ist, dass da nur eine kleine Auswahl von Datentypen möglich ist. Byte/Word/Cardinal/Integer ist da alles eins. Variant wäre weniger problematisch, aber es passt immer noch nicht alles (Extended fehlt und ByteArrays z.B. sind sehr seltsam).
Ich hab schon überlegt, Parameterobjekte zu nehmen, die sich selbst serialisieren. Ohne anonyme Klassen (Hallo, Java) bedeutet das aber, dass haufenweise Klassen zu deklarieren und zu implementieren sind. Ich will ja grade sowas vereinfachen, nicht eine "Menge Code" durch eine andere "Menge Code" erledigen.
Wenn Delphi assoziative Arrays mit TypInfo hätte... *träum* :roll:
BenBE hat folgendes geschrieben : |
Mit Zaunpfahl wedel* array of const AKA array of TVarRec :mrgreen: |
Lesen. Hirn anschalten. Nochmal lesen. Dann
vielleicht posten.
Narses - So 11.03.12 02:33
Moin!
Jaa, nach intensivem Überlegen ;) würde ich zu einer (weiteren, nur für die Weiterverarbeitung benötigten) TInboundFrameList als Parameter-Konvention raten, eben genau so, wie es auch reinkommt, datentypenfrei. Das hat zwar den doofen "Nachteil", dass du dann die Parameter jedes mal kopieren musst, das sollte aber nicht so schlimm sein, da die Strings auf dem Heap ja referenzgezählt sind und nicht dupliziert werden sollten. Damit "überlässt" du ja quasi der Zielmethode die Wahl, was das für Parameter und wie sie handzuhaben sind. :idea: :nixweiss: Sobald du das typensicher haben willst, wird das mit Delphi wohl nicht so lustig werden... :?
Also kurz: OnEntityCall(Entity, Func, Params: TInboundFrameList)
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!