Zeiger Problem
-
Hallo,
hab ein etwas komplizierteres Problem, wo ich hoffe dass mir jmd weiterhelfen kann.
In meinem Programm bekomme ich über einen Socket einen Paketbuffer angeliefert, aus dem ich einzelne Werte auslese etc. Nachdem dieser Buffer keine feste Struktur aufweist, kann ich nicht direkt eine vordefinierte struct auf diesen buffer legen, sondern habe eine "externe" struct von der ich mittels pointer auf die richtigen elemente zeige. Das funktioniert auch sehr gut.
Tritt ein Fehler auf - z.B. dass ein Element im Buffer nicht die richtige Codierung besitzt, soll eine Response geschickt werden, in der es ein Feld gibt, welches auf das Feld zeigen soll wo der Fehler statt gefunden hat. Für die Response wird ein neuer Buffer verwendet, der eine ähnliche Struktur wie der Empfangsbuffer besitzt, aber verschoben.
Hier ein Bsp:
struct bstruct { unsigned int *ptr1; unsigned int *ptr2; //usw -> zeigen alle auf elemente im empfangsbuffer };
Empfangsbuffer: Codierung (Type des Wert | Länge des Wertes | Wert) Empfangsbuffer: Struktur - ErrorWert = 0 - (TypWert1 | LängeWert1 | Wert1) - (TypWert2 | LängeWert2 | Wert2) - (usw..)
Der ErrorWert ist im Empfangsbuffer 0, da kein Fehler vorhanden ist. Die Wert1, Wert2 Felder sind ebenfalls 0. In der Response stehen nun in den Wert1, Wert2 Felder Werte drinnen vom jeweiligen Typ TypWert (werden aus einer Datenbank ausgelesen).
Handelt es sich z.B. um einen String, der eine bestimmte Länge L hat, verschiebt sich die Struktur gegenüber dem Empfangsbuffer, so dass ich einen neuen Buffer anlege für die Response.
Tritt ein Fehler auf (bei der Bearbeitung der Werte im Empfangsbuffer - z.B. Wert konnte in der Datenbank nicht gefunden werden), weiß ich wo der Fehler im Empfangsbuffer aufgetreten ist - z.B. im TypWert2.
Jedoch weiß ich zu diesem Zeitpunkt noch nicht, wo sich der Wert TypWert2 genau im Response-Pkt befinden wird, wo der Pointer ErroWert in der fälligen response hinzeigen soll. Das hängt damit zusammen, da ich nicht weiß, wie viel Speicherplatz der TypWert1 etc. benötigt.
Ich hoffe ich konnte mein Problem einigermaßen verständlich erläutern.
gruß
patrick
-
patrick meier schrieb:
Empfangsbuffer: Codierung (Type des Wert | Länge des Wertes | Wert) Empfangsbuffer: Struktur - ErrorWert = 0 - (TypWert1 | LängeWert1 | Wert1) - (TypWert2 | LängeWert2 | Wert2) - (usw..)
das format schimpft sich TLV (type-length-value). weil anzahl und länge der werte variabel ist, kannst du da keine structs drauf mappen, sondern musst es von vorn bis hinten durchparsen.
-
richtig
binaryXML-freak schrieb:
patrick meier schrieb:
Empfangsbuffer: Codierung (Type des Wert | Länge des Wertes | Wert) Empfangsbuffer: Struktur - ErrorWert = 0 - (TypWert1 | LängeWert1 | Wert1) - (TypWert2 | LängeWert2 | Wert2) - (usw..)
das format schimpft sich TLV (type-length-value). weil anzahl und länge der werte variabel ist, kannst du da keine structs drauf mappen, sondern musst es von vorn bis hinten durchparsen.
richtig, dass mach ich auch (und funktioniert auch). Wenn jetzt jedoch ein Fehler auftritt soll ebend in der Error-Response ein Pointer vom Feld ErrorWert auf den entsprechendne Wert zeigen in der Response... Zu dem Zeitpunkt wo ich den Fehler bemerke hab ich jedoch nur einen Pointer auf den Wert im Empfangsbuffer.
patrick
-
patrick meier schrieb:
Zu dem Zeitpunkt wo ich den Fehler bemerke hab ich jedoch nur einen Pointer auf den Wert im Empfangsbuffer.
naja, dann verschick doch erst die error-response wenn der wert vollständig da ist, oder verstehe ich dich völlig falsch?
-
pingpong-freak schrieb:
patrick meier schrieb:
Zu dem Zeitpunkt wo ich den Fehler bemerke hab ich jedoch nur einen Pointer auf den Wert im Empfangsbuffer.
naja, dann verschick doch erst die error-response wenn der wert vollständig da ist, oder verstehe ich dich völlig falsch?
also ich parse die incoming message von vorne nach hinten durch und bemerke z.B. beim Object TypWert1, dass dieses Element nicht in der Datenbank vorhanden ist, somit ist ein Fehler aufgetreten, der in der Response vermerkt werden muss. D.h. zu diesem Zeitpunkt besitze ich einen Pointer auf diesen Fehler (aber halt im Eingangsbuffer).
Jetzt muss ich mir einen zweiten Buffer anlegen, in dem ich die Error-Response eintrage. Gut jetzt kann ich bei jedem Feld abfragen ob die Adresse die gleiche ist wie vom Pointer, der auf den Fehler zeigt - aber gibt es nicht noch eine bessere Lösung?
patrick
-
^^da fehlen ein paar informationen, z.b:
aus wie vielen TLVs besteht so eine nachricht?
willst du für jeden fehler eine error-response erzeugen oder die fehler sammeln?
hast du zu wenig speicher oder wieso willste nichts kopieren?die mir bekannten systeme, die mit TLVs arbeiten, machen das ungefähr so:
- eine nachricht setzt sich aus 1...n TLVs zusammen
- unbekannte TLVs werden einfach ignoriert, also übersprungen
- dann wird irgendwas mit der nachricht gemacht...
- ... und die rückantwort bezieht sich auf die ganze nachricht, also ein positives ergebnis (auch aus TLVs bestehend) oder eine fehlermeldung.
-
protocol-freak schrieb:
^^da fehlen ein paar informationen, z.b:
aus wie vielen TLVs besteht so eine nachricht?
willst du für jeden fehler eine error-response erzeugen oder die fehler sammeln?
hast du zu wenig speicher oder wieso willste nichts kopieren?die mir bekannten systeme, die mit TLVs arbeiten, machen das ungefähr so:
- eine nachricht setzt sich aus 1...n TLVs zusammen
- unbekannte TLVs werden einfach ignoriert, also übersprungen
- dann wird irgendwas mit der nachricht gemacht...
- ... und die rückantwort bezieht sich auf die ganze nachricht, also ein positives ergebnis (auch aus TLVs bestehend) oder eine fehlermeldung.
aus wievielen TLVs die Nachricht besteht ist unterschiedlich - von 1 bis 10 TLVs sind normal. Die einzige Begrenzung liegt in der MTU, für ein IP Paket. Sobald ein Fehler auftritt wird eine Fehlermeldung geschickt, und die restlichen noch nicht verarbeiteten TLVs werden discarded.
hast du zu wenig speicher oder wieso willste nichts kopieren?
Speicher habe ich schon vorhanden, weiß aber nicht wie ich da was kopieren soll. Im Prinzip arbeite ich bis jetzt so: ich suche mir den richtigen Wert aus der Datenbank raus und setze einen Zeiger auf diesen Wert. In der Response hole ich mir dann diesen Wert (vom Pointer) und setze ihn ein - z.B. einen ganzen String. Danach kommt der nächste TLV-Wert drann. Wenn jetzt z.B. der TLV-Wert kommt, in dem ein Fehler aufgetreten ist, muss ich dies ja irgendwie wissen... kopieren wüsste ich nicht wie, da ich ja erst beim codieren der Response weiß, wo überhaupt welcher TLV-Wert genau hinkommt.
ein kleines Bsp nochmal
TLV-Wert Empfangsbuffer: 0x04 (WertType1) 0x00 (WertLänge1) 0x04(WertType2)
TLV-Wert Response: 0x04(WertType1) 0x05(WertLänge) 0x00 0x01 0x02 0x03 0x04 (Wert1) -> dann kommt erst WertTyp2...
patrick
-
okay, aber du baust ja die response in abhängigkeit von der eingangsnachricht auf. vielleicht bin ich zu doof dafür, aber ich kann da kein problem erkennen.
receive input message if something received reset input pointer reset output pointer while input message has tlvs handle current tlv if success append postive response to output buffer else append negative response to output buffer end if update input pointer update output pointer end while transmit output message end if
-
ah sehr gut.. so ein ablauf ist hervorragend...
if success append postive response to output buffer else append negative response to output buffer
hier steckt das problem: man läuft zuerst alle TLVs des Empfangsbuffers durch und füllt nicht gleich nach jedem TLV dieses gleich der Response zu -> das Problem ist nämlich: der Eingangsbuffer wird von oben (erste TLV) bis zur letzten durchgelesen (wenn kein Problem Fehler auftritt) -> die Response wird genau anders herum angefertigt; sprich du fängst mit der Erstellung der Response nicht oben an, sondern ganz unten beim letzten Element des Eingangsbuffers und arbeitest dich dann rückwärts zum ersten Element vor...
patrick
-
patrick meier schrieb:
...die Response wird genau anders herum angefertigt; sprich du fängst mit der Erstellung der Response nicht oben an, sondern ganz unten beim letzten Element des Eingangsbuffers und arbeitest dich dann rückwärts zum ersten Element vor...
und warum? willst du mehrere fehler zusammenfassen, die paketgrösse möglichst klein halten?
-
optimier-freak schrieb:
patrick meier schrieb:
...die Response wird genau anders herum angefertigt; sprich du fängst mit der Erstellung der Response nicht oben an, sondern ganz unten beim letzten Element des Eingangsbuffers und arbeitest dich dann rückwärts zum ersten Element vor...
und warum? willst du mehrere fehler zusammenfassen, die paketgrösse möglichst klein halten?
ist vom protokol snmp so vorgeschrieben... laut RFC. Warum, weiß ich nicht - kann man bestimmt auch anders herum ganz gut hinbekommen...
patrick