Hallo zusammen,
ich habe eine Prinzipfrage zur Auswertung eines beliebigen Protokolls
(ohne RTOS), das in Schichten Aufgebaut ist,Physical -> Data Link ->
Network usw. (zb. TCP)
Das Ergebnis der Auswertung jeder Schicht wird die in einem eigenen
Buffer abgespeichert auf die die nächste Schicht zugreift oder wird ein
und derselbe Buffer von allen Layern bearbeitet?
Wie ich mir das so Vorstelle am Beispiel einer seriellen uart
Schnittstelle als Physical Layer:
1. (Physical Layer)
alle ankommenden Bytes werden in einen Ringbuffer geschrieben (ISR)
2. (Data Link Layer, Network Layer)
Funktion untersucht alle neuen Bytes und Schreibt das zusammenhängende
Protokoll Frame in einen Linearbuffer, wenn die Checksumme, Adresse etc.
stimmt, hier wird oft ein ACK gefordert, jetzt müsste diese Funktion
also auch in der ISR abgearbeitet werden umd Zeitgerecht zu Antworten
oder sehe ich das falsch? Je nach Fuktionsumfang könnte das aber relativ
Zeitintensiv werden was in einer ISR dann nicht so toll ist.
3. (Transport Layer)
Funktion extrahiert die Nutzdaten aus dem Protokoll Frame und kopiert
diese in einen weiteren Ringbuffer welcher dann aus den reinen Nutzdaten
Frames (APDU) besteht.
4.
Zeitlich unkritische Abarbeitung der Daten
Meine Frage ist jetzt wie weit bin ich mit meiner Vorstellung von der
Realität entfernt bzw. wie wird so etwas normal gemacht?
Problematisch für mich ist der Zeitliche Ablauf um keine Daten zu
verlieren bzw. Bufferüberläufe zu verhindern und dennoch Zeit für die
Restliche Applikation zu haben....
Danke schonmal für den Versuch mich aufzuklären :) Bin auch dankbar
dafür wenn mir jemand sagen kann wo man sich über solche Sachen schlau
machen kann, hab nicht wirklich was gefunden bzw. weiß ich nicht wonach
ich suchen soll, unter Protokoll Stack Entwicklung finde ich nur sehr
Allgemein gehaltene Infos bzw Infos.
Gruß
Franz
Du sprichst hier einen Sonderfall an -- Du erwartest auf einem PhyLayer,
der per se keine Pakete unterstützt, ebensolche...
Dein Hauptproblem ist also erst einmal, möglichst effizient die Daten
der einzelnen Pakete voneinander zu trennen, damit sie dann paketweise
weiterverarbeitet, gespeichert, quittiert, usw. werden können.
Falls das auf Grund der Struktur der Daten möglich ist, empfiehlt es
sich, die Paketierung der Streamdaten schon im Interrupt zu machen, z.B.
durch eine Zustandsmaschine; die fertigen Pakete werden dann nach oben
an den Stack weitergereicht. Dadurch wird die Interrupt-Rate erheblich
verringert. Ist allerdings die Erkennung der Paketgrenzen bereits
aufwendig, dann ist ein (hoch-priorer) Task besser geeignet.
Ansonsten gibt es beide genannten Methoden, die Daten durch einen
Protokoll-Stack durchzureichen: Jeweils weiterkopieren, oder im
originalen Puffer der untersten Schicht belassen und darin
weiterarbeiten.
Die Kopier-Varianten hat den offensichtlichen Nachteil, daß die Daten
jeweils kopiert werden müssen -> Speicher- und Zeitaufwand. Der
Hauptvorteil ist, daß der Datenumfang von Schicht zu Schicht abnimmt --
normalerweise muß man ja hauptsächlich die Nutzlast der
darunterliegenden Schicht übernehmen. Müssen nun in einer Schicht
mehrere Pakete gepuffert werden, dann kann der reduzierte Speicherbedarf
wesentlich sein.
Quittungen sollten immer in dem Level des Stacks erzeugt werden, zu dem
sie gehören; oft genug gehören sie ja auch zu den Puffermechanismen
dieser Schicht.
So long,
Tillomar
Danke für deine Erklärung, hilft mir schon mal weiter :)
Diesen Teil verstehe ich nicht ganz, was genau ist damit gemeint?
Tillomar Sondermann schrieb:> Quittungen sollten immer in dem Level des Stacks erzeugt werden, zu dem> sie gehören; oft genug gehören sie ja auch zu den Puffermechanismen> dieser Schicht.
Gibt es vielleicht einfache Beispiele wo so eine Stack Implementierung
umgesetzt wird?
Es gibt auch noch die Möglichkeit für jeden Frame, Speicher dynamisch zu
allokieren. Die Frames dann per verkettete Liste durch die Schichten zu
reichen.
Gerade auf einem µC sollte man da natürlich den Speicherverbrauch im
Auge behalten. Sollte man feststellen das nicht mehr genügend Speicher
für den nächsten Frame zur Verfügung steht sollte man die Übertragung am
besten auf den Physical Layer unterbinden, bei RS232 könnte man z.B.
Handshake-Leitungen nutzen.
Bietet der Physical Layer keine solche Möglichkeit kann man versuchen
das auf eine der nächsten Layer zu verschieben, bei I2C z.B. die
eingehenden Pakete mit NAK beantworten.
> Diesen Teil verstehe ich nicht ganz, was genau ist damit gemeint?>> Tillomar Sondermann schrieb:>> Quittungen sollten immer in dem Level des Stacks erzeugt werden, zu dem>> sie gehören; oft genug gehören sie ja auch zu den Puffermechanismen>> dieser Schicht.
Eine Quittung ist üblicherweise nicht Bestandteil der Nutzlast; daher
muß sie im Rahmen transportiert werden. Dieser Rahmen ist aber für die
darunterliegende Schicht die Nutzlast -> ergo darf eine Schicht niemals
durch eine andere hindurchgreifen, auch wenn sie das in einem
NoCopy-Stack prinzipiell könnte.
> Gibt es vielleicht einfache Beispiele wo so eine Stack Implementierung umgesetzt
wird?
Sorry, muß ich passen -- ich liebe komplizierte Beispiele... :)
Scherz beiseite, ich habe gerade nix zur Hand, was als Beispiel geeignet
wäre UND was ich herausgeben dürfte.
Mögen die edlen Mitstreiter in die Bresche springen. ;)
So long,
Tillomar
AVR-Frickler schrieb im Beitrag #3124973:
> Die Frames dann per verkettete Liste durch die Schichten zu> reichen.
Wie genau kann ich mir das Vorstellen?
Tillomar Sondermann schrieb:> -> ergo darf eine Schicht niemals> durch eine andere hindurchgreifen, auch wenn sie das in einem> NoCopy-Stack prinzipiell könnte.
Ich nehme an das Selbe gilt für Prüfsummen Auswertung etc.?
Warum eigentlich? Um die "Norm" einzuhalten oder gibt es da auch
technische Gründe, auf Anhieb würde mir da nichts einfallen was dagegen
spricht, im Gegenteil teilweise könnte man sogar fühzeitig illegale,
defekte Frames aus dem Verkehr ziehen?
Tillomar Sondermann schrieb:> Mögen die edlen Mitstreiter in die Bresche springen. ;)
ich hoffe :)
Franz schrieb:> Allerdings verstehe ich noch nicht wie man damit Frames durch die> Schichten reicht?
Und ich auch nicht.
Ein verkettete Liste benötigt man dann, wenn wenn die Menge oder
insbesondere die Reihenfolge von Objekten jederzeit mit geringem Aufwand
ändern können muß.
Diese Anwendung sehe ich hier nicht; freilich kann sich die Anzahl der
wartenden Buffer ändern, normalerweise aber nicht die Reihenfolge, daher
wäre ein Array mit Buffern, sowie deren Verwaltung mit Pointern oder
Indices effizienter.
So long,
Tillomar
Ich war jahrelang in einer Firma für den Protokollrahmen verantwortlich
und habe auch meine Diplomarbeit in diesem Zusammenhang gemacht.
Unter dem Begriff verteckt sich eben ziemlich genau die Maschinerie Die
Du selbst ganz oben beschrieben hast.
Einer der Vorteile war, das sich ca. 90 % aller seriellen Protokoll auf
diese Weise zur Applikation hin gleich verhielten und ein Ko-Prozessor
auf 8031-Basis auf verschiedenen Steckkarten sich für einem Zoo von
Rechnern für PC, SUN, 19-Zoll Bussysteme usw. skalieren ließ.
Die meisten Feldbussysteme kamen damit Klar: z.B. BITBUS, DIN66348,
MODBUS, SEAB, DIN19244 und eine weitere Menge die ich inzwischen
vergessen habe...
Einige Protokolle wie etwa Profibus hatten damit auch Ihre
Schwierigkeiten, da Sie an das reduzierte OSI - Modell (1,2 -7)
Angepasst sind und seperate Abfragepunkte bereitstellen sollen, die
sozusagen als "schnelle" Messwertanfrage dienen sollten, die Messwerte
beiinhalten.
CAN z.B. wäre für einen Einsatz in einem voll ausdekodierten OSI-Modell
sicher fehl am Platz. Es sei den als Visualisierungszentrale.
Generell sind Protoklle ungeeignet, die quasi als Antwort auf eine
Aktion die Schicht 7 erledigen soll, Daten erwarten. Z.B. reine Punkt zu
Punkt Protokolle sind dafür ungeeignet.
Gruß Thilo
Tillomar Sondermann schrieb:> Diese Anwendung sehe ich hier nicht; freilich kann sich die Anzahl der> wartenden Buffer ändern, normalerweise aber nicht die Reihenfolge, daher> wäre ein Array mit Buffern, sowie deren Verwaltung mit Pointern oder> Indices effizienter.
Über die konkrete Anwendung hat Franz ja noch nicht viel geschrieben.
Wenn man einen festen Puffer für alle Schichten als das eine Ende
ansieht, wollte ich nur das andere Ende aufzeigen.
Franz schrieb:> Allerdings verstehe ich noch nicht wie man damit Frames durch die> Schichten reicht?
1. Layer
Ein ganze normale serielle Verbindung mit 1 Starbit 8 Datenbits 1
Stopbit. Womit das Protokoll eigentlich schon spezifiziert ist.
2. Layer
Hier kommt jetzt deine ISR ins Spiel, hier müssen je nach Protokoll
schon die ersten Daten ausgewertet werden.
a. Feste Framelänge
a-1. Speicher in der ISR reservieren
a-2. die main-Schleife sorgt von alleine dafür das immer ein
Listenelement verfügbar ist
b. Das Protokoll sieht vor, dass in den ersten Bytes mitgeteilt wie viel
Bytes folgen (Daten + Prüfsumme). Die ersten Bytes müssten dann in einem
kleinen Puffer zwischengespeichert werden.
b-1. Speicher in der ISR reservieren
b-2. Über globale Variablen der main-Schleife mitteilen wie viel
Speicher reserviert werden soll.
Sobald die Daten vollständig sind und eine eventuell vorhandene
Prüfsumme stimmt, bestätigt die ISR den Datenempfang und hängt das
Listenelement in die Liste ein oder fordert zum erneuten senden auf.
3. Layer
Hier gibt es nun mehrere Möglichkeiten, die main-Schleife prüft selbst
ständig ob ein neues Listenelement verfügbar ist oder die ISR teilt über
weitere globale Variablen mit dass neue Daten verfügbar sind.
Was in der main-Schleife mit den Daten nun passiert bleibt dir
überlassen, entweder hast du auch hier noch mehrere Layer oder im
einfachsten Fall eine einzelne Funktion welche die Daten auswertet.
Franz schrieb:> Gibt es vielleicht einfache Beispiele wo so eine Stack Implementierung> umgesetzt wird?
Einfache Beispiele habe ich leider auch nicht zu bieten, du kannst aber
mal versuchen den IP-Stack in Ulrich Radigs Webserver zu verstehen.
http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex
Der Stack verwendet einen globalen Puffer für alle Schichten.
Fast :) Nein aber ich muss die ganzen Infos erst aufnehmen, verarbeiten
und dann etwas sitzen lassen um nacher die richtigen Fragen stellen zu
können ;)
Stehe hier ganz am Anfang und will nur das Prizip mit Bezug auf die
praktische Umsetzung verstehen. Dank euerer Hilfe bin ich auch schon
wesentlich vorangekommen :)
M. K. schrieb:> b-1. Speicher in der ISR reservieren> b-2. Über globale Variablen der main-Schleife mitteilen wie viel> Speicher reserviert werden soll.
warum muss der main Schleife mittgeteilt werden wie viel Speicher
reserviert werden soll wenn dieser doch in der ISR ermittelt und
reserviert wird? Denke du meinst hier den Pointer auf den in der ISR
reservierten und befüllten Speicherbereich?
M. K. schrieb:> Einfache Beispiele habe ich leider auch nicht zu bieten, du kannst aber> mal versuchen den IP-Stack in Ulrich Radigs Webserver zu verstehen.> http://www.ulrichradig.de/home/index.php/avr/eth_m32_ex
Danke für den Tip, hat mir sehr geholfen!
AVR-Frickler schrieb im Beitrag #3124973:
> Es gibt auch noch die Möglichkeit für jeden Frame, Speicher dynamisch zu> allokieren. Die Frames dann per verkettete Liste durch die Schichten zu> reichen.
Hab das jetzt so verstanden:
es gibt für jede Schicht eine Queue (verkettete Liste) und jedes Frame
wird dann von queue zu queue weitergereicht....also in der unteren
Schicht ausgehängt und in der nächsten Schicht nach verarbeitung wieder
eingehängt. Vorteil hier ist das einzelne Frames nicht zwingend der
Reihe nach weiter bearbeitet werden müssen sonder je nach priorität auch
dazwischen entnommen werden können etc. Sind die Daten nicht regelmäßig
segmentiert ist das für Layer 4 eigentlich fast zwingend erfoderlich.
Hab ich das soweit richtig versanden?
Nächste Frage :)
Die ankommenden Frames können aus meiner Sicht in 2 unterschiedlichen
Varianten auf Schicht 7 "enden"
Variante1: Frame löst direkt eine Funktion aus die aus den enthaltenen
Daten etwas macht.
Variante2: FrameDaten werden in einer Queue gepuffert und die Anwendung
schaut dort regelmäßig nach und verarbeitet sie dann bei Gelegenheit.
Im Beispiel von Ulrich Radig wird soweit ich das verstanden habe
Variante1 verwendet und breits in Schicht 3 die dazugehörige Funktion
verlinkt.
Generell werden die Frames in Schicht 3 ja auf die einzelnen
registrierten Adressen, Ports etc. aufgeteilt. Heißt das dann, das es
für jeden registrierten Port etc. eine eigene Queue gibt? Würde bedeuten
das alle darauf folgenden Schichten für jeden Port etc. separat
existieren, also zb. mehrere Schicht 4 Elemente parallel, kann das sein?
Wenn Variante2 verwendet wird muss in Schicht 3 eigentlich auch keine
Funktion zugeordnet werden oder?
Gar nicht mal so einfach, wo lernt man so etwas im Normalfall? Verstehe
nicht ganz warum es hier keine Informationen zu finden gibt obwohl das
ja eine sehr verbreitete Methode ist!?
Danke nochmal für eure Hilfe :)
Franz schrieb:> warum muss der main Schleife mittgeteilt werden wie viel Speicher> reserviert werden soll wenn dieser doch in der ISR ermittelt und> reserviert wird? Denke du meinst hier den Pointer auf den in der ISR> reservierten und befüllten Speicherbereich?
Hängt davon ab, wie man es implementiert.
Ich würde einen Pool-Service einrichten, der auch aus dem interrupt
aufrufbar ist, und Funktionen zum Anfordern und freigeben von Puffern
zur Verfügung stellt. Dann braucht die ISR das fertige Paket nur noch in
einen frisch angforderten Puffer zu stecken, und einen Descriptor für
diesen Puffer in die Warteschlange einzuhängen. Kommt main() mal wieder
vorbei, ist gleich erkennbar, daß da wieder was wartet. Am Ende wird der
Puffer mit dem gleichen Service zurückgegeben, oder man behält ihn
gleich für die Antwort -- das kann in jeder Schicht geschehen, nicht nur
in 7.
Franz schrieb:> Hab das jetzt so verstanden:> es gibt für jede Schicht eine Queue (verkettete Liste) und jedes Frame> wird dann von queue zu queue weitergereicht....also in der unteren> Schicht ausgehängt und in der nächsten Schicht nach verarbeitung wieder> eingehängt. Vorteil hier ist das einzelne Frames nicht zwingend der> Reihe nach weiter bearbeitet werden müssen sonder je nach priorität auch> dazwischen entnommen werden können etc.
Natürlich kannst Du einen Puffer aus einer Queue aushängen, um ihn in
der Queue der nächsten Schicht wieder einzuhängen -- aber Du kannst auch
mehrere Queues gleichzeitig über den gleichen Satz von Puffern legen,
wenn Du mehr als einen Zugriffspfad (z.B. Sortierung) benötigst.
Franz schrieb:> Sind die Daten nicht regelmäßig> segmentiert ist das für Layer 4 eigentlich fast zwingend erfoderlich.> Hab ich das soweit richtig versanden?
Sorry, daß verstehe ich jetzt nicht...
Meinst Du segmentiert oder fragmentiert? Bist Du jetzt bei TCP/IP?
Franz schrieb:> Im Beispiel von Ulrich Radig wird soweit ich das verstanden habe> Variante1 verwendet und breits in Schicht 3 die dazugehörige Funktion> verlinkt.
Nennt man Callbacks...
> Generell werden die Frames in Schicht 3 ja auf die einzelnen> registrierten Adressen, Ports etc. aufgeteilt. Heißt das dann, das es> für jeden registrierten Port etc. eine eigene Queue gibt? Würde bedeuten> das alle darauf folgenden Schichten für jeden Port etc. separat> existieren, also zb. mehrere Schicht 4 Elemente parallel, kann das sein?
Jain.
Das Problem ist natürlich, genügend viele bzw. differenzierte "Ausgänge"
aus dem Stack zu haben. Deshalb läuft das normalerweise durch den
Socket-Layer (was jetzt aber kein Stack-Layer ist ;), bei dem die
Applikation Sockets öffnet (wie File-Handles); dadurch weiß der Socket
Layer dann, wem er ein Packet überreichen muß. Ist mit echten Threads
natürlich wesentlich eleganter zu implementieren...
So long,
Tillomar
Tillomar Sondermann schrieb:> Sorry, daß verstehe ich jetzt nicht...> Meinst Du segmentiert oder fragmentiert? Bist Du jetzt bei TCP/IP?
fragmentiert, also Schicht 4 baut ja evtl. aus mehreren Paketen einen
zusammenhängenden Datenstrom für die höheren Schichten und diese Pakete
müssen ja nicht in der richtigen Reihenfolge daher kommen, könnten
zwischenzeitlich ja Pakete für einen anderen "Port" sein.
Den Übergang von Schicht 3 zu 4 hab ich noch nicht richtig verstanden,
Schicht 3 teilt die Frames ja auf die einzelnen "Ports" auf d.h. ab hier
verläuft der weg der einzelnen Frames ja auseinander und muss
zwangsläufig separat behandelt werden?
Franz schrieb:> fragmentiert, also Schicht 4 baut ja evtl. aus mehreren Paketen einen> zusammenhängenden Datenstrom für die höheren Schichten und diese Pakete> müssen ja nicht in der richtigen Reihenfolge daher kommen, könnten> zwischenzeitlich ja Pakete für einen anderen "Port" sein.
Soweit richtig, nur hat das nichts mit Fragemtierung zu tun, denn die
findet von Schicht 3 zur Schicht 2 statt, bzw. das Reassembly in Schicht
3.
Du must die Ebenen richtig unterscheiden:
Ebene 3 macht empfangsseitig das Reassembly, d.h. fügt fragemntierte
IP-Pakete wieder zusammen.
Ebene 4 bekommt vollständige TCP-Pakete, diese können aber ebenfalls
noch in der falschen Reihenfolge sein; sie werden im Sliding Window
Buffer zu einem vollständigen Datenstrom assembliert.
Ob die Daten dann in einen Stream-Puffer umkopiert werden, oder in den
TCP-Paket-Puffern verbleiben, bis der Inhalt gelesen wurde, ist
implementierungsabhängig.
Franz schrieb:> Den Übergang von Schicht 3 zu 4 hab ich noch nicht richtig verstanden,> Schicht 3 teilt die Frames ja auf die einzelnen "Ports" auf d.h. ab hier> verläuft der weg der einzelnen Frames ja auseinander und muss> zwangsläufig separat behandelt werden?
Nicht zwangsläufig. Die Implementierung des Sliding Window Buffer könnte
durchaus auch als zusätzliche Schicht auf den normalen Puffer-Pool
gelegt werden. Ich würde allerdings wohl auch zu jedem Port eine Queue
machen.
TCP ist ja verbindungsorientiert, und die Verbindung hat einen Besitzer;
im Zweifelsfall kommt der Speicher aus dessen Kontext.
Gruß,
Tillomar
Tillomar Sondermann schrieb:> Ich glaube, wir haben den TO überfahren... ;)>> So long,> TillomarFranz schrieb:> Fast :) Nein aber ich muss die ganzen Infos erst aufnehmen, verarbeiten> und dann etwas sitzen lassen um nacher die richtigen Fragen stellen zu> können ;)
Hehe 6 Tage um durch Ulrich Radigs Webserver durchblicken braucht man
wirklich. Wie gut das ich ihm nicht den Link zu Ethersex gepostet habe.
Tillomar Sondermann schrieb:> Franz schrieb:>> Hab das jetzt so verstanden:>> es gibt für jede Schicht eine Queue (verkettete Liste) und jedes Frame>> wird dann von queue zu queue weitergereicht....also in der unteren>> Schicht ausgehängt und in der nächsten Schicht nach verarbeitung wieder>> eingehängt. Vorteil hier ist das einzelne Frames nicht zwingend der>> Reihe nach weiter bearbeitet werden müssen sonder je nach priorität auch>> dazwischen entnommen werden können etc.>> Natürlich kannst Du einen Puffer aus einer Queue aushängen, um ihn in> der Queue der nächsten Schicht wieder einzuhängen -- aber Du kannst auch> mehrere Queues gleichzeitig über den gleichen Satz von Puffern legen,> wenn Du mehr als einen Zugriffspfad (z.B. Sortierung) benötigst.
Ich nicht ob ich Tillomar richtig verstanden habe, wahrscheinlich meinst
du aber dasselbe was ich gleich beschreibe.
Anstelle von mehreren Listen kannst du auch wirklich nur eine einzige
verwenden und mehrere Zeiger in die Liste zeigen lassen. Du kannst dir
für jede Schicht einen Zeiger machen.
Vielleicht wird es etwas klarer wenn ich dir mal eine Struktur für ein
Listenelement zeige.
1
typedefstruct{
2
uint8_tstate// Status des Listen-Elements
3
uint8_tfromLayer// Aus welcher Schicht stammen die Daten
4
uint8_ttoLayer// Für welche Schicht sind die Daten
5
uint16_tbufferlen// Länge des Zeichenpuffers
6
uint8_t*buffer;// Zeiger auf den Zeichenpuffer
7
structitem*next;// Zeiger auf das nächste Element.
8
}item;
Das wichtigste: Wie du siehst enthält die Struktur einen Zeiger auf den
Datenspeicher (buffer) diesen Zeiger kannst du natürlich in mehreren
Listenelementen verwenden. Wenn eine Schicht die Daten an die nächste
Schicht weitergeben möchte erzeugt sie ein neues Listenelement und setzt
den Zeiger (buffer) auf dieselbe Adresse des Datenspeichers der in
dieser Schicht verarbeitet wurde.
Ich habe der Struktur noch die Elemente state, fromLayer und toLayer
gegeben.
state kann verwendet werden wenn du die verwaltung der Liste zentral
abwickeln möchtest, z.B durch eine Art Garbage-Collector. Eine andere
Möglichkeit besteht darin dass jede Schicht ihre eigenen Listenelemente
selbst aus der Liste entfernt. Allerdings muss man hier höllisch
aufpassen die Liste nicht zu zerstören, wenn Schichten sich in der Liste
'überholen' können. Auch mit der ISR muss man aufpassen, dass das
ein-/aushängen atomar passiert.
fromLayer und toLayer kann verwendet werden um in den Schichten
entscheiden zu können welche Richtung die Pakte nehmen, so kannst du
z.B. bei TCP/IP die Datenspeicher solange weiter verwenden bis eine
Transaktion abgeschlossen ist.
Wenn du dir den Datenfluss in Ulrich Radigs Webserver anschaust wirst du
sehen das er vom Ethernet-Controller immer ein Ethernet-Frame mit 1500
Bytes ausliest und dann komplett durch alle Schichten schiebt und beim
antworten teilweise durch alle Schichten durchgreift und dann direkt mit
dem Ethernet-Controller arbeitet. Das wurde weiter oben schon erwähnt
das dies nicht gerade optimal ist.
Ein weiterer Nachteil dabei ist, wenn eine Schicht sehr lange braucht um
die Pakete zu verarbeiten, kann es schon mal passieren das trotz 8Kb
Puffer im Ethernet-Controller Pakete verloren gehen können.
M. K. schrieb:> Hehe 6 Tage um durch Ulrich Radigs Webserver durchblicken braucht man> wirklich.
Leider steht wie bei jedem Hobby immer zu wenig Zeit dafür zur Verfügung
;)
M. K. schrieb:> Anstelle von mehreren Listen kannst du auch wirklich nur eine einzige> verwenden und mehrere Zeiger in die Liste zeigen lassen. Du kannst dir> für jede Schicht einen Zeiger machen.
OK hab ich verstanden aber das wird doch ziemlich unübersichtlich wenn
in ein und der selben Liste alle Schichten gemischt sind und wie du
selbst schreibst muss man dann höllisch aufpassen, da sind getrennte
Listen schon übersichtlicher und unproblematischer oder nicht?
M. K. schrieb:> fromLayer und toLayer kann verwendet werden um in den Schichten> entscheiden zu können welche Richtung die Pakte nehmen, so kannst du> z.B. bei TCP/IP die Datenspeicher solange weiter verwenden bis eine> Transaktion abgeschlossen ist.
das verstehe ich nicht?
Tillomar Sondermann schrieb:> Nicht zwangsläufig. Die Implementierung des Sliding Window Buffer könnte> durchaus auch als zusätzliche Schicht auf den normalen Puffer-Pool> gelegt werden.
wäre das dann nicht auch ein durchgreifen durch die Schicht? Schicht 4
sieht doch nur mehr die Pakete für den entsprechenden "Port" und muss
daher ja für eben alle vorkommenden "Ports" separat behandelt werden?
Tillomar Sondermann schrieb:> Ob die Daten dann in einen Stream-Puffer umkopiert werden, oder in den> TCP-Paket-Puffern verbleiben, bis der Inhalt gelesen wurde, ist> implementierungsabhängig.
Und das wird bei der Registrierung des "Ports" bereits festgelegt oder?
Sprich bei ankommenden Frames weiß ich ab Schicht 3 ob direkt eine
Funktion ausgeführt wird oder ob die Daten in einem Puffer landen.
Franz schrieb:> OK hab ich verstanden aber das wird doch ziemlich unübersichtlich wenn> in ein und der selben Liste alle Schichten gemischt sind und wie du> selbst schreibst muss man dann höllisch aufpassen, da sind getrennte> Listen schon übersichtlicher und unproblematischer oder nicht?
Einfacher wird es sicher sein, der Verwaltungsaufwand ist halt etwas
höher.
Wie gesagt jede Schicht kann ihre 'eigenen' Listenelemente nur als
bearbeitet markieren. Am Ende der main-Schleife gehst du einmal die
komplette Liste durch und löschst dann alle markierten Elemente. Das
meinte ich mit Garbage-Collector.
Franz schrieb:> M. K. schrieb:>> fromLayer und toLayer kann verwendet werden um in den Schichten>> entscheiden zu können welche Richtung die Pakte nehmen, so kannst du>> z.B. bei TCP/IP die Datenspeicher solange weiter verwenden bis eine>> Transaktion abgeschlossen ist.>> das verstehe ich nicht?
Bei TCP/IP musst du ja nicht nur von Schicht 0 rauf auf Schicht 4 sonder
auch wieder zurück um eine Bestätigung (Ack) zu senden das die Daten
korrekt empfangen wurden. Dazu werden auch Informationen aus dem
empfangen Paket benötigt.
Es muss das richtige ACK zum passenden SEGMENT gesendet werden. In dem
oben verlinkten Webserver wird einfach in der letzten Schicht ein
komplettes Paket geschnürt und direkt dem Ethernet-Controller übergeben.
Die anderen Schichten bekommen davon also nichts mit.
Wenn du der Funktion für Schicht 3 nun einfach Daten überreichst und
sagst '''mach''', stellt sich danach die Frage und wohin jetzt mit dem
Paket? Ist das jetzt ein Paket für Schicht 4 oder versucht Schicht 4 nun
das letzte Paket zu beantworten?
Bei UDP-Verbindungen wirst du dies allerdings nicht benötigen, weil hier
keine Bestätigung gesendet wird.
Franz schrieb:> Tillomar Sondermann schrieb:>> Ob die Daten dann in einen Stream-Puffer umkopiert werden, oder in den>> TCP-Paket-Puffern verbleiben, bis der Inhalt gelesen wurde, ist>> implementierungsabhängig.>> Und das wird bei der Registrierung des "Ports" bereits festgelegt oder?> Sprich bei ankommenden Frames weiß ich ab Schicht 3 ob direkt eine> Funktion ausgeführt wird oder ob die Daten in einem Puffer landen.
Dies hat mit Ports erst einmal nichts zu tun, das ist eine Grundlegende
Entscheidung die du beim Programmieren des Stacks triffst.
In Ulrich Radigs Webserver hast du keine andere Möglichkeit als die
Daten umzukopieren, weil das nächste Paket den Puffer gnadenlos
überschreibt.
Mit der Liste kannst du dir das ersparen, du kannst die Daten solange
halten bis dir der RAM oder die Anzahl der reservierten Puffer ausgeht.
Ah ok klingt logisch, danke :)
Wenn ich jetzt der Einfachheit halber alles in eine eigene Queue packe
dann gibt es ab Schicht 3 aber für jeden "Port" eine eigene Queue und
Schicht 4 muss jede dieser Queues durchlaufen?
Muss jetzt mal die callback Geschichte genauer unter die Lupe nehmen....