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
Keiner der irgendwelche Anregungen für mich hat, oder hab ich mich unklar Ausgedrückt? Bitte fragen!
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: > AVR-Frickler schrieb im Beitrag #3124973: >> Die Frames dann per verkettete Liste durch die Schichten zu >> reichen. > > Wie genau kann ich mir das Vorstellen? schon was gefunden :) http://de.wikibooks.org/wiki/C-Programmierung:_Verkettete_Listen
Allerdings verstehe ich noch nicht wie man damit Frames durch die Schichten reicht?
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, > Tillomar Franz 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 | typedef struct { |
2 | uint8_t state // Status des Listen-Elements |
3 | uint8_t fromLayer // Aus welcher Schicht stammen die Daten |
4 | uint8_t toLayer // Für welche Schicht sind die Daten |
5 | uint16_t bufferlen // Länge des Zeichenpuffers |
6 | uint8_t* buffer; // Zeiger auf den Zeichenpuffer |
7 | struct item* 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....
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.