Entwickler-Ecke
Internet / Netzwerk - Protokoll selbst implementieren
matze - Mi 27.02.08 11:13
Titel: Protokoll selbst implementieren
Hallo.
Ich stehe im Moment vor der Aufgabe, dass ich das UDP Protokoll des Mac-Programmes Growl implementieren muss.
Leider habe ich sowas noch nie gemacht und bin im Moment auch ein bisschen hilflos.
Das sind meine bisherigen Bemühungen. Der Code ist grauselig, aber ich wollte einfach mal nur einen Test programmieren.
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:
| var Form1: TForm1; Growl_App_Name: String = 'Matze'; Growl_Notification_Name: String = 'Hinweis'; const Growl_Protocol_version: byte = 1; Growl_Type_Registration: byte = 5; Growl_Type_Notification: byte = 1;
procedure Send; var buf: TStringStream; len: integer; sbuf:string; begin Growl_App_Name := AnsiToUtf8(Growl_App_Name); Growl_Notification_Name := AnsiToUtf8(Growl_Notification_Name); buf := TStringStream.Create(''); try buf.WriteBuffer(Growl_Protocol_version,SizeOf(Growl_Protocol_version)); buf.WriteBuffer(Growl_Type_Registration,SizeOf(Growl_Type_Registration)); len := length(Growl_App_Name); buf.WriteBuffer(len,2); len := 1; buf.WriteBuffer(len,1); buf.WriteBuffer(len,1); buf.WriteBuffer(Growl_App_Name,length(Growl_App_Name)); buf.WriteBuffer(len,2); buf.WriteBuffer(Growl_Notification_Name,length(Growl_Notification_Name)); buf.WriteBuffer(len,2);
sbuf := buf.DataString;
IdUDPClient1.Send('192.168.0.37',9887,sbuf);
finally buf.Free; end; end; |
Die Protokoll-Spezifiationen sind
hier [
http://growl.info/documentation/developer/protocol.php]. Das soll angeblich auch recht einfach gehen, aber anscheinend bin ich zu blöd dazu.
Es gibt auch einige Implementierungen in PHP (z.b.
hier [
http://php-growl.googlecode.com/svn/trunk/class.growl.php]), aber dazu kann ich zu wenig PHP um das nach Delphi portieren zu können.
Kann mir jemand bei meinem Problem helfen!
Danke schon mal im voraus !
opfer.der.genauigkeit - Mi 27.02.08 11:52
Wo scheitert es denn genau?
Evtl. entspricht der Ausgabebuffer nicht dem Protokoll? *tipp ins blaue*
matze - Mi 27.02.08 11:58
ja vermutlich. Also das Programm, das ich ansprechen möchte (Growl) zeigt auf jeden Fall keine Reaktion. Ich habe zum Test mal die PHP Implementierungen ausprobiert. Da geht es.
Also vermutlich setzt ich die Protokollspezifikationen nicht richtig um.
Die Frage ist jetzt: Wie macht man das richtig ?
opfer.der.genauigkeit - Mi 27.02.08 12:28
Ich kann es leider nicht testen, den PHP-Code kann ich dir aber gerne übersetzen, wenn dir das weiterhelfen würde.
Bezweifel ich aber irgendwie. :)
Meine Vorgehensweise wäre folgende.
Ich würde ein packed record definieren und die Werte schreiben, die ich an den jeweiligen Protokolldefinitionen haben moechte.
Dann würde ich das Ergebnis in einen Bytearray kopieren (imho ist das aber nicht mal noetig)...
Da ich leider auch nicht testen kann, kann ich nur theoretische Ansätze bieten.
Was mir im PHP-Code aufgefallen ist, für
pack [
http://at.php.net/pack] werden noch zusaetzliche Formatierungsangaben gemacht. Evtl. gibt dir das weiteren Aufschluß darüber, was evtl. nicht stimmt.
Und vergleiche dochmal den Buffer vom PHP-Code mit deinem. :gruebel:
//Edit: Wenn du mit anderen Sprachen besser bewandert bist (z.B. C++), dann schau doch mal bei koders.com, ob du da den Code findest.
Sinspin - Mi 27.02.08 13:01
Was mir auffällt ist, das du TStringStream verwendest.
Eigentlich stört es nicht sonderlich was für einen Stream man nimmt aber könnte es sein das bei dieser Variante irgendwas vor oder hinter den Daten steht das da nicht hinsoll?
Delphi hat ja die Angewohnheit vor Strings immer die Länge schreiben zu müssen. Oder einen Zeilenumbruch am Ende anzufügen.
matze - Mi 27.02.08 13:07
Den StringStream habe ich genommen, weil die Indy UDP Komponente nur Strings annimmt...
@Opfer.der.genaugkeit: Wie soll ich denn meinen Output mit dem von dem PHP Script vergleichen?
opfer.der.genauigkeit - Mi 27.02.08 13:22
Z.B.: echo oder var_dump und anzeigen lassen.
Xentar - Mi 27.02.08 13:33
Man könnte auch mit diversen Tools, z.B. WireShark, den Netzwerktraffic mitschneiden, und dann die Pakete, die das PHP Script sendet, mit deinen vergleichen.
Edit: Ich seh grad, du sendest keine MD5 Checksumme mit? Vllt. liegts schon daran?
matze - Mi 27.02.08 13:34
Das bringt mir nichts, da seh ich nur Kauderwelsch (ist ja auch ein binär Protokoll)
Die Checksumme kann ich ja laut dem Protokoll auch weg lassen, wenn ich den Typ 5 (NoAuth) nehme.
Narses - Mi 27.02.08 14:12
Moin!
Mir ist aufgefallen: Ich kann in der Doku nix über den byte-sex finden. :gruebel:
Die MAC-Jungs stehen ja auf msb (aus Motorola-Zeiten, von mir aus auch network-byte-order, was einem besser gefällt), aber du schreibst in deinem Code lsb (eben Intel-typisch). Da schonmal nach geschaut? :nixweiss:
cu
Narses
matze - Mi 27.02.08 14:23
na gut, aber so an sich: wäre das Protokoll denn technisch richtig implementiert?
Also mache ich das richtig mit dem WriteBuffer Zeug und dem Versenden mit dem String?
Narses - Mi 27.02.08 14:33
Moin!
matze hat folgendes geschrieben: |
na gut, aber so an sich: wäre das Protokoll denn technisch richtig implementiert? |
Sieht so aus (hab´s aber auch nicht im Detail nachgezählt und abgehakt...) :nixweiss:
matze hat folgendes geschrieben: |
Also mache ich das richtig mit dem WriteBuffer Zeug und dem Versenden mit dem String? |
Schick´s dir doch einfach mal selbst und mach einen HEX-Dump, den vergleichst du dann mit der Doku. Wenn die Anzahlen/Positionen stimmen, dann kannste nochmal die ByteOrder tauschen. :idea:
cu
Narses
matze - Mi 27.02.08 14:40
OK ich habe mir jetzt mal WireShark geladen und damit die beiden Pakete verglichen:
Das von PHP, das funktioniert:
Quelltext
1: 2: 3:
| 00000000 01 00 00 05 01 01 4d 61 74 7a 65 00 07 57 61 72 ......Ma tze..War 00000010 6e 69 6e 67 00 89 c8 e4 35 33 a8 e8 08 19 f0 d5 ning.... 53...... 00000020 62 d9 cd 7f 88 b.... |
Meins, das nicht funktioniert:
Quelltext
1: 2:
| 00000000 01 05 05 00 01 01 28 c3 aa 00 c0 01 00 c0 20 ac ......(. ...... . 00000010 00 01 8d 40 01 00 ...@.. |
Sagt das den Experten was?
Also immerhin sehe ich, dass der Name der Application (Matze) nicht mitgesendet wird, bei meinem Output...
Narses - Mi 27.02.08 15:00
Moin!
matze hat folgendes geschrieben: |
Sagt das den Experten was? |
Jup. ;)
matze hat folgendes geschrieben: |
Das von PHP, das funktioniert:
Quelltext 1: 2: 3:
| 00000000 01 00 00 05 01 01 4d 61 74 7a 65 00 07 57 61 72 ......Ma tze..War 00000010 6e 69 6e 67 00 89 c8 e4 35 33 a8 e8 08 19 f0 d5 ning.... 53...... 00000020 62 d9 cd 7f 88 b.... | |
Also, wie ich schon vermutete: msb! :idea: Das schreibst du also schonmal "falsch rum".
matze hat folgendes geschrieben: |
Also immerhin sehe ich, dass der Name der Application (Matze) nicht mitgesendet wird, bei meinem Output... |
Stimmt... :? Passiert mir auch immer wieder, du schreibst den String-Pointer, nicht den Inhalt: ;)
Delphi-Quelltext
1:
| buf.WriteBuffer(PChar(Growl_App_Name)^,length(Growl_App_Name)); |
cu
Narses
matze - Mi 27.02.08 15:12
Ah. verdammt. Da hätte ich aber auch selber drauf kommen können !
Und wie macht man das mit dem MSB?
Narses - Mi 27.02.08 15:28
Moin!
matze hat folgendes geschrieben: |
Ah. verdammt. Da hätte ich aber auch selber drauf kommen können ! |
:D
matze hat folgendes geschrieben: |
Und wie macht man das mit dem MSB? |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| uses ..., WinSock;
function htonl; external winsocket name 'htonl'; function htons; external winsocket name 'htons'; function ntohl; external winsocket name 'ntohl'; function ntohs; external winsocket name 'ntohs'; |
cu
Narses
matze - Mi 27.02.08 15:31
Äääähhh... Ich steh aufm Schlauch.
Wie wendet man das an?
Narses - Mi 27.02.08 15:35
Moin!
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| var HostBytes, NetBytes: Word; begin HostBytes := 7; NetBytes := htons(HostBytes); ShowMessage(IntToHex(HostBytes,4)+#13+IntToHex(NetBytes,4)); |
Vorsicht Falle, die Anzeige ist genau andersrum, als die Bytefolge im Speicher! :mahn:
cu
Narses
matze - Mi 27.02.08 15:59
Quelltext
1: 2:
| 00000000 01 05 00 05 01 01 4d 61 74 7a 65 00 07 57 61 72 ......Ma tze..War 00000010 6e 69 6e 67 ning |
Mein neuer 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: 35:
| var buf: TStringStream; len: byte; app_length: Word; sbuf:string; begin Growl_App_Name := AnsiToUtf8(Growl_App_Name); Growl_Notification_Name := AnsiToUtf8(Growl_Notification_Name); buf := TStringStream.Create(''); try buf.WriteBuffer(Growl_Protocol_version,SizeOf(Growl_Protocol_version)); buf.WriteBuffer(Growl_Type_Registration,SizeOf(Growl_Type_Registration)); app_length := htons(length(Growl_App_Name)); buf.WriteBuffer(app_length,SizeOf(app_length)); len := 1; buf.WriteBuffer(len,1); buf.WriteBuffer(len,1); buf.WriteBuffer(PChar(Growl_App_Name)^,length(Growl_App_Name)); app_length := htons(length(Growl_Notification_Name)); buf.WriteBuffer(app_length,SizeOf(app_length)); buf.WriteBuffer(PChar(Growl_Notification_Name)^,length(Growl_Notification_Name)); buf.WriteBuffer(pos,sizeOf(pos));
sbuf := buf.DataString; IdUDPClient1.Send('192.168.0.37',9887,sbuf); finally buf.Free; end; |
Also soweit schaut das schon gut aus. Danke mal an alle bis hierher !!
Ich bin jetzt in der Spezifikation so weit, dass ich eine "Notification" schreiben kann. So.
Laut Spezifikation kann man dann noch mehrere Warnungen wiederholen, was ich aber nicht mache. Am Ende soll man aber noch einen Index auf die Warnung schreiben. (Der DEFAULTS Block). Da muss ich ehrlich sagen, dass ich nicht verstehe, wie ich das machen soll...
matze - Do 28.02.08 10:06
Hallo.
OK. Nach einer langen Nacht habe ich alles hinbekommen und kann jetzt mal die Basis-Kommandos an den Growl-Client senden!
Ich möchte mich ganz herzlich bei allen Bedanken, die mich gestern ertragen haben und mir geholfen haben. Wenn das Projekt dann fertig ist, werde ich eine Klasse draus bauen und das dann hier im Forum veröffentlichen.
Nochmal danke !
Matze
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 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!