Zum Hauptinhalt springen

2. Blockweise Übertragungen

Wie in der Einführung erörtert, gibt es gute Gründe, die Größe von Datagrammen in eingeschränkten Netzwerken zu begrenzen:

  • durch die maximale Datagrammgröße (~ 64 KiB für UDP)

  • durch den Wunsch, IP-Fragmentierung zu vermeiden (MTU von 1280 für IPv6)

  • durch den Wunsch, Fragmentierung auf der Anpassungsschicht zu vermeiden (60-80 Bytes für 6LoWPAN [RFC4919])

Wenn eine Ressourcenrepräsentation größer ist, als sie bequem in der Nutzlast eines einzelnen CoAP-Datagramms übertragen werden kann, kann eine Block-Option verwendet werden, um eine blockweise Übertragung anzuzeigen. Da Nutzlasten sowohl mit Anfragen als auch mit Antworten gesendet werden können, bietet diese Spezifikation zwei separate Optionen für jede Richtung der Nutzlastübertragung. Bei der Benennung dieser Optionen (für blockweise Übertragungen sowie in Abschnitt 4) verwenden wir die Zahl 1 ("Block1", "Size1"), um uns auf die Übertragung der Ressourcenrepräsentation zu beziehen, die sich auf die Anfrage bezieht, und die Zahl 2 ("Block2", "Size2"), um uns auf die Übertragung der Ressourcenrepräsentation für die Antwort zu beziehen.

Im Folgenden wird der Begriff "Nutzlast (payload)" für den eigentlichen Inhalt einer einzelnen CoAP-Nachricht verwendet, d. h. einen einzelnen Block, der übertragen wird, während der Begriff "Körper (body)" für die gesamte Ressourcenrepräsentation verwendet wird, die blockweise übertragen wird. Die Content-Format-Option gilt für den Körper, nicht für die Nutzlast; insbesondere können die Grenzen zwischen den Blöcken an Stellen liegen, die keine ganzen Einheiten in Bezug auf die Struktur, Codierung oder Inhaltscodierung trennen, die vom Content-Format verwendet werden. (Ebenso gilt die in Abschnitt 5.10.6 von [RFC7252] definierte ETag-Option für die gesamte Repräsentation der Ressource und somit für den Körper der Antwort.)

In den meisten Fällen haben alle Blöcke, die für einen Körper übertragen werden (mit Ausnahme des letzten), die gleiche Größe. (Wenn die erste Anfrage eine größere Blockgröße verwendet, als der Empfänger bevorzugt, verwenden nachfolgende Anfragen die bevorzugte Blockgröße.) Die Blockgröße ist nicht durch das Protokoll festgelegt. Um die Implementierung so einfach wie möglich zu halten, unterstützen die Block-Optionen nur einen kleinen Bereich von Blockgrößen in Zweierpotenzen, von 2**4 (16) bis 2**10 (1024) Bytes. Da Körper oft nicht gleichmäßig in die gewählte Zweierpotenz-Blockgröße unterteilt werden können, muss die Größe im letzten Block nicht erreicht werden (aber selbst für den letzten Block wird die gewählte Zweierpotenzgröße immer noch im Blockgrößenfeld der Block-Option angegeben).

2.1. Die Block2- und Block1-Optionen

+-----+---+---+---+---+--------+--------+--------+---------+
| No. | C | U | N | R | Name | Format | Length | Default |
+-----+---+---+---+---+--------+--------+--------+---------+
| 23 | C | U | - | - | Block2 | uint | 0-3 | (keine) |
| | | | | | | | | |
| 27 | C | U | - | - | Block1 | uint | 0-3 | (keine) |
+-----+---+---+---+---+--------+--------+--------+---------+

Tabelle 1: Block-Optionsnummern

Sowohl Block1- als auch Block2-Optionen können sowohl in den Anfrage- als auch in den Antwortnachrichten vorhanden sein. In beiden Fällen bezieht sich die Block1-Option auf die Anfragenutzlast und die Block2-Option auf die Antwortnutzlast.

Daher ist Block1 für die in [RFC7252] definierten Methoden bei den nutzlasttragenden POST- und PUT-Anfragen und ihren Antworten nützlich. Block2 ist nützlich bei GET-, POST- und PUT-Anfragen und ihren nutzlasttragenden Antworten (2.01, 2.02, 2.04 und 2.05 -- siehe Abschnitt 5.5 von [RFC7252]).

Wo Block1 in einer Anfrage oder Block2 in einer Antwort vorhanden ist (d. h. in der Nachricht, auf deren Nutzlast sie sich bezieht), zeigt sie eine blockweise Übertragung an und beschreibt, wie diese spezifische blockweise Nutzlast Teil des gesamten übertragenen Körpers ist ("beschreibende Verwendung"). Wo sie in der entgegengesetzten Richtung vorhanden ist, bietet sie zusätzliche Kontrolle darüber, wie diese Nutzlast gebildet wird oder verarbeitet wurde ("Kontrollverwendung").

Die Implementierung jeder Block-Option ist als optional vorgesehen. Wenn sie jedoch in einer CoAP-Nachricht vorhanden ist, MUSS sie verarbeitet werden (oder die Nachricht abgelehnt werden); daher wird sie als kritische (Critical) Option identifiziert. Jede Block-Option DARF NICHT mehr als einmal in einer einzelnen Nachricht vorkommen.

2.2. Struktur einer Block-Option

Drei Informationselemente müssen möglicherweise in einer Block-Option (Block1 oder Block2) übertragen werden:

  • die Größe des Blocks (SZX);

  • ob weitere Blöcke folgen (M);

  • die relative Nummer des Blocks (NUM) innerhalb einer Sequenz von Blöcken mit der gegebenen Größe.

Der Wert der Block-Option ist eine variable (0 bis 3 Byte) vorzeichenlose Ganzzahl (uint, siehe Abschnitt 3.2 von [RFC7252]). Dieser ganzzahlige Wert codiert diese drei Felder, siehe Abbildung 1. (Aufgrund der CoAP-uint-Codierungsregeln wird, wenn NUM, M und SZX alle Null sind, eine Null-Byte-Ganzzahl gesendet.)

     0
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| NUM |M| SZX |
+-+-+-+-+-+-+-+-+

0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUM |M| SZX |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

0 1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NUM |M| SZX |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Abbildung 1: Block-Optionswert

Die Blockgröße wird unter Verwendung einer vorzeichenlosen Drei-Bit-Ganzzahl codiert (0 für 2**4 Bytes bis 6 für 2**10 Bytes), die wir "SZX" ("Größenexponent") nennen; die tatsächliche Blockgröße beträgt dann "2**(SZX + 4)". SZX wird in den drei niedrigstwertigen Bits des Optionswerts übertragen (d. h. "val & 7", wobei "val" der Wert der Option ist).

Das vierte niedrigstwertige Bit, das M- oder "More"-Bit ("val & 8"), zeigt an, ob weitere Blöcke folgen oder ob die aktuelle blockweise Übertragung der letzte übertragene Block ist.

Der durch sechzehn geteilte Optionswert (das NUM-Feld) ist die Sequenznummer des aktuell übertragenen Blocks, beginnend bei Null. Die aktuelle Übertragung betrifft daher die "size" Bytes, beginnend bei Byte "NUM << (SZX + 4)".

Implementierungshinweis: Als Implementierungserleichterung gibt "(val & ~0xF) << (val & 7)", d. h. der Optionswert, bei dem die letzten 4 Bits ausmaskiert sind, nach links verschoben um den Wert von SZX, die Byteposition des ersten Bytes des übertragenen Blocks an.

Genauer gesagt ist die Bedeutung der Optionsfelder innerhalb des Optionswerts einer Block1- oder Block2-Option wie folgt definiert:

NUM: : Blocknummer, die die angeforderte oder bereitgestellte Blocknummer angibt. Blocknummer 0 gibt den ersten Block eines Körpers an (d. h. beginnend mit dem ersten Byte des Körpers).

M: : More-Flag ("nicht letzter Block"). Für die beschreibende Verwendung zeigt dieses Flag, wenn es nicht gesetzt ist, an, dass die Nutzlast in dieser Nachricht der letzte Block im Körper ist; wenn es gesetzt ist, zeigt es an, dass ein oder mehrere zusätzliche Blöcke verfügbar sind. Wenn eine Block2-Option in einer Anfrage verwendet wird, um eine bestimmte Blocknummer abzurufen ("Kontrollverwendung"), MUSS das M-Bit als Null gesendet und beim Empfang ignoriert werden. (In einer Block1-Option in einer Antwort wird das M-Flag verwendet, um Atomizität anzuzeigen, siehe unten.)

SZX: : Blockgröße. Die Blockgröße wird als vorzeichenlose Drei-Bit-Ganzzahl dargestellt, die die Größe eines Blocks als Zweierpotenz angibt. Somit ist Blockgröße = 2**(SZX + 4). Die zulässigen Werte von SZX sind 0 bis 6, d. h. die minimale Blockgröße ist 2**(0+4) = 16 und das Maximum ist 2**(6+4) = 1024. Der Wert 7 für SZX (der eine Blockgröße von 2048 anzeigen würde) ist reserviert, d. h. er DARF NICHT gesendet werden und MUSS beim Empfang in einer Anfrage zu einem Antwortcode 4.00 Bad Request führen.

Es gibt keinen Standardwert für die Block1- und Block2-Optionen. Das Fehlen einer dieser Optionen entspricht einem Optionswert von 0 in Bezug auf den Wert von NUM und M, der in der Option angegeben werden könnte, d. h. es zeigt an, dass der aktuelle Block der erste und einzige Block der Übertragung ist (Blocknummer 0, M-Bit nicht gesetzt). Im Gegensatz zum expliziten Wert 0, der ein SZX von 0 und damit einen Größenwert von 16 Bytes anzeigen würde, wird durch das Fehlen der Option jedoch keine spezifische explizite Größe impliziert -- die Größe bleibt unspezifiziert. (Wie bei jedem uint wird der explizite Wert 0 effizient durch eine Option mit Nulllänge angezeigt; dies unterscheidet sich daher semantisch vom Fehlen der Option.)

2.3. Block-Optionen in Anfragen und Antworten

Die Block-Optionen werden in einer von drei Rollen verwendet:

  • In beschreibender Verwendung, d. h. eine Block2-Option in einer Antwort (wie eine 2.05-Antwort für GET) oder eine Block1-Option in einer Anfrage (ein PUT oder POST):

    • Das NUM-Feld im Optionswert beschreibt, welche Blocknummer in der Nutzlast dieser Nachricht enthalten ist.

    • Das M-Bit zeigt an, ob weitere Blöcke übertragen werden müssen, um die Übertragung dieses Körpers abzuschließen.

    • Die durch SZX implizierte Blockgröße MUSS mit der Größe der Nutzlast in Bytes übereinstimmen, wenn das M-Bit gesetzt ist. (SZX regelt nicht die Nutzlastgröße, wenn M nicht gesetzt ist). Für Block2, wenn die Anfrage einen größeren Wert von SZX vorgeschlagen hat, MUSS die nächste Anfrage SZX auf die in der Antwort angegebene Größe reduzieren. (Der Effekt ist, dass, wenn der Server die kleinere von (1) seiner bevorzugten Blockgröße und (2) der angeforderten Blockgröße verwendet, alle Blöcke für einen Körper die gleiche Blockgröße verwenden.)

  • Eine Block2-Option in Kontrollverwendung in einer Anfrage (z. B. GET):

    • Das NUM-Feld in der Block2-Option gibt die Blocknummer der Nutzlast an, deren Rückgabe in der Antwort angefordert wird.

    • In diesem Fall hat das M-Bit keine Funktion und MUSS auf Null gesetzt werden.

    • Die angegebene Blockgröße (SZX) schlägt eine Blockgröße vor (im Fall von Blocknummer 0) oder wiederholt die Blockgröße vorheriger empfangener Blöcke (im Fall einer Blocknummer ungleich Null).

  • Eine Block1-Option in Kontrollverwendung in einer Antwort (z. B. eine 2.xx-Antwort für eine PUT- oder POST-Anfrage):

    • Das NUM-Feld der Block1-Option zeigt an, welche Blocknummer bestätigt wird.

    • Wenn das M-Bit in der Anfrage gesetzt war, kann der Server wählen, ob er auf jeden Block separat ohne Gedächtnis reagiert oder ob er die Anfrage für den gesamten Körper atomar behandelt oder eine Mischung aus beidem.

      • Wenn das M-Bit auch in der Antwort gesetzt ist, zeigt dies an, dass diese Antwort nicht den endgültigen Antwortcode auf die Anfrage trägt, d. h. der Server sammelt weitere Blöcke vom selben Endpunkt und plant, die Anfrage atomar zu implementieren (z. B. handelt erst nach Empfang des letzten Nutzlastblocks). In diesem Fall DARF die Antwort KEINE Block2-Option tragen.

      • Umgekehrt, wenn das M-Bit nicht gesetzt ist, obwohl es in der Anfrage gesetzt war, zeigt dies an, dass die blockweise Anfrage jetzt speziell für diesen Block durchgeführt wurde und die Antwort die endgültige Antwort auf diese Anfrage (und auf alle vorherigen mit dem M-Bit in der Block1-Option der Antwort in dieser Sequenz von blockweisen Übertragungen) trägt; es wird erwartet, dass der Client weiterhin weitere Blöcke sendet, deren Anfragemethode ebenfalls pro Block durchgeführt werden kann oder auch nicht. (Beachten Sie, dass sich die Ressource jetzt in einem teilweise aktualisierten Zustand befindet; dieser Ansatz ist nur angemessen, wenn das Offenlegen eines solchen Zwischenzustands akzeptabel ist. Der Client kann das Fenster reduzieren, indem er die Aktualisierung der Ressource schnell fortsetzt oder im Fehlerfall die Aktualisierung neu startet.)

    • Schließlich zeigt die in einer Kontroll-Block1-Option angegebene SZX-Blockgröße die größte vom Server bevorzugte Blockgröße für Übertragungen zur Ressource an, die gleich oder kleiner als die im ursprünglichen Austausch verwendete ist; der Client SOLLTE diese Blockgröße oder eine kleinere in allen weiteren Anfragen in der Übertragungssequenz verwenden, auch wenn dies bedeutet, dass die Blockgröße ab jetzt geändert wird (und die Blocknummer möglicherweise entsprechend skaliert wird).

Unter Verwendung einer oder beider Block-Optionen kann eine einzelne REST-Operation in mehrere CoAP-Nachrichtenaustausche aufgeteilt werden. Wie in [RFC7252] spezifiziert, verwendet jeder dieser Nachrichtenaustausche seine eigene CoAP-Nachrichten-ID.

Die mit den Anfragen oder Antworten gesendete Content-Format-Option MUSS das Content-Format des gesamten Körpers widerspiegeln. Wenn Blöcke eines Antwortkörpers mit unterschiedlichen Content-Format-Optionen ankommen, liegt es am Client, wie er diesen Fehler behandelt (er wird normalerweise jede laufende blockweise Übertragung abbrechen). Wenn Blöcke einer Anfrage mit nicht übereinstimmenden Content-Format-Optionen bei einem Server ankommen, DARF der Server sie NICHT zu einer einzelnen Anfrage zusammensetzen; dies führt normalerweise zu einer Fehlerantwort 4.08 (Request Entity Incomplete, Abschnitt 2.9.2) auf den nicht übereinstimmenden Block.

2.4. Verwendung der Block2-Option

Wenn eine Anfrage mit einer Antwort beantwortet wird, die eine Block2-Option mit gesetztem M-Bit trägt, kann der Anforderer zusätzliche Blöcke der Ressourcenrepräsentation abrufen, indem er weitere Anfragen mit denselben Optionen wie die ursprüngliche Anfrage und einer Block2-Option sendet, die die gewünschte Blocknummer und Blockgröße angibt. In einer Anfrage MUSS der Client das M-Bit einer Block2-Option auf Null setzen und der Server MUSS es beim Empfang ignorieren.

Um die in einer Antwort verwendete Blockgröße zu beeinflussen, KANN der Anforderer auch die Block2-Option in der ursprünglichen Anfrage verwenden und die gewünschte Größe, eine Blocknummer von Null und ein M-Bit von Null angeben. Ein Server MUSS die angegebene Blockgröße oder eine kleinere Größe verwenden. Alle weiteren blockweisen Anfragen für Blöcke nach dem ersten MÜSSEN dieselbe Blockgröße angeben, die vom Server in der Antwort auf die erste Anfrage verwendet wurde, die eine gewünschte Größe unter Verwendung einer Block2-Option angab.

Sobald die Block2-Option vom Anforderer verwendet wird und eine erste Antwort mit einer möglicherweise angepassten Blockgröße empfangen wurde, konvergieren alle weiteren Anfragen in einer einzelnen blockweisen Übertragung schließlich zur Verwendung derselben Größe, außer dass möglicherweise nicht genügend Inhalt vorhanden ist, um den letzten Block (der mit nicht gesetztem M-Bit zurückgegeben wird) zu füllen. (Beachten Sie, dass der Client möglicherweise erst in einer zweiten Anfrage mit der Verwendung der Block2-Option beginnt, nachdem eine erste Anfrage ohne Block2-Option zu einer Block2-Option in der Antwort geführt hat.) Der Server verwendet die in der Anfrageoption angegebene Blockgröße oder eine kleinere Größe, aber der Anforderer MUSS die tatsächliche Blockgröße beachten, die in der Antwort verwendet wird, die er auf seine ursprüngliche Anfrage erhält, und sie in nachfolgenden Anfragen weiter verwenden. Das Serververhalten MUSS sicherstellen, dass dieses Clientverhalten zu derselben Blockgröße für alle Antworten in einer Sequenz führt (mit Ausnahme der letzten mit nicht gesetztem M-Bit und möglicherweise der ersten, wenn die ursprüngliche Anfrage keine Block2-Option enthielt).

Blockweise Übertragungen können verwendet werden, um Ressourcen abzurufen (GET), deren Repräsentationen vollständig statisch sind (sich im Laufe der Zeit überhaupt nicht ändern, wie z. B. in einem Schema, das ein Gerät beschreibt), oder für sich dynamisch ändernde Ressourcen. Im letzteren Fall SOLLTE die Block2-Option in Verbindung mit der ETag-Option ([RFC7252], Abschnitt 5.10.6) verwendet werden, um sicherzustellen, dass die wieder zusammengesetzten Blöcke aus derselben Version der Repräsentation stammen: Der Server SOLLTE in jede Antwort eine ETag-Option aufnehmen. Wenn eine ETag-Option verfügbar ist, MUSS der Client beim Wiederzusammensetzen der Repräsentation aus den ausgetauschten Blöcken die ETag-Optionen vergleichen. Wenn die ETag-Optionen bei einer GET-Übertragung nicht übereinstimmen, hat der Anforderer die Möglichkeit, zu versuchen, frische Werte für die Blöcke abzurufen, die er zuerst abgerufen hat. Um die resultierende Ineffizienz zu minimieren, KANN der Server den aktuellen Wert einer Repräsentation für eine laufende Sequenz von Anfragen zwischenspeichern. (Der Server kann die Sequenz durch die Kombination aus anforderndem Endpunkt und URI identifizieren, die bei jeder blockweisen Anfrage gleich ist.) Beachten Sie wohl, dass diese Spezifikation keine Anforderung an den Server stellt, irgendeinen Zustand herzustellen; Server, die schnell wechselnde Ressourcen anbieten, können es einem Client jedoch dadurch unmöglich machen, jemals einen konsistenten Satz von Blöcken abzurufen. Clients, die alle Blöcke einer Ressource abrufen möchten, SOLLTEN bestrebt sein, dies ohne unangemessene Verzögerung zu tun. Server können voll und ganz erwarten, dass sie jeden zwischengespeicherten Zustand nach einem Zeitraum von EXCHANGE_LIFETIME ([RFC7252], Abschnitt 4.8.2) nach dem letzten Zugriff auf den Zustand verwerfen können, es besteht jedoch keine Anforderung, den Zustand immer so lange zu behalten.

Die Block2-Option bietet keine Möglichkeit für einen einzelnen Endpunkt, mehrere gleichzeitig ablaufende blockweise Antwortnutzlastübertragungsoperationen (z. B. GET) auf dieselbe Ressource durchzuführen. Dies ist selten eine Anforderung, aber als Workaround kann ein Client den Cache-Schlüssel variieren (z. B. durch Verwendung einer von mehreren URIs, die auf Ressourcen mit derselben Semantik zugreifen, oder durch Variieren einer Proxy-sicheren Wahloption).

2.5. Verwendung der Block1-Option

In einer Anfrage mit einer Anfragenutzlast (z. B. PUT oder POST) bezieht sich die Block1-Option auf die Nutzlast in der Anfrage (beschreibende Verwendung).

Als Antwort auf eine Anfrage mit einer Nutzlast (z. B. eine PUT- oder POST-Übertragung) zeigt die in der Block1-Option angegebene Blockgröße die Blockgrößenpräferenz des Servers für diese Ressource an (Kontrollverwendung). Offensichtlich wurde zu diesem Zeitpunkt der erste Block bereits vom Client ohne diesen Wissen übertragen. Dennoch SOLLTE der Client die angegebene Präferenz beachten und für alle weiteren Blöcke die vom Server bevorzugte Blockgröße oder eine kleinere verwenden. Beachten Sie, dass jede Reduzierung der Blockgröße bedeuten kann, dass die zweite Anfrage mit einer Blocknummer größer als eins beginnt, da die erste Anfrage bereits mehrere Blöcke übertragen hat, wie in der kleineren Größe gezählt.

Um den Auswirkungen der Fragmentierung auf der Anpassungsschicht auf die Paketzustellungswahrscheinlichkeit entgegenzuwirken, möchte ein Client möglicherweise auf die erneute Übertragung einer Anfrage mit einer relativ großen Nutzlast verzichten, noch bevor MAX_RETRANSMIT erreicht ist, und versuchen, die Anfrage als blockweise Übertragung mit einer kleineren Nutzlast neu zu formulieren. Beachten Sie, dass dieser neue Versuch dann eine neue Nachrichtenschichttransaktion ist und eine neue Nachrichten-ID erfordert. (Aufgrund der Unsicherheit darüber, ob die Anfrage oder die Bestätigung verloren gegangen ist, ist diese Strategie meist für idempotente Anfragen nützlich.)

Bei einer blockweisen Übertragung einer Anfragenutzlast (z. B. PUT oder POST), die auf dem Server atomar implementiert werden soll, findet die eigentliche Erstellung/Ersetzung zu dem Zeitpunkt statt, an dem der letzte Block, d. h. ein Block mit nicht gesetztem M-Bit in der Block1-Option, empfangen wird. In diesem Fall tragen alle Erfolgsantworten auf nicht finale Blöcke den Antwortcode 2.31 (Continue, Abschnitt 2.9.1). Wenn zum Zeitpunkt der Verarbeitung des letzten Blocks nicht alle vorherigen Blöcke auf dem Server verfügbar sind, schlägt die Übertragung fehl und der Fehlercode 4.08 (Request Entity Incomplete, Abschnitt 2.9.2) MUSS zurückgegeben werden. Ein Server KANN auch einen 4.08-Fehlercode für jede (finale oder nicht finale) Block1-Übertragung zurückgeben, die nicht in der Reihenfolge ist; daher SOLLTEN Clients, die keine spezifischen Mechanismen zur Behandlung dieses Falls haben, immer mit Block Null beginnen und die folgenden Blöcke in der Reihenfolge senden.

Ein Grund, warum ein Client auf einen 4.08-Fehlercode stoßen könnte, ist, dass der Server bereits eine Zeitüberschreitung hatte und den teilweise zusammengesetzten Anfragekörper verworfen hat. Clients SOLLTEN bestrebt sein, alle Blöcke einer Anfrage ohne unangemessene Verzögerung zu senden. Server können voll und ganz erwarten, dass sie jeden teilweise zusammengesetzten Anfragekörper verwerfen können, wenn ein Zeitraum von EXCHANGE_LIFETIME ([RFC7252], Abschnitt 4.8.2) nach der Übertragung des letzten Blocks vergangen ist; es besteht jedoch keine Anforderung an einen Server, den teilweise zusammengesetzten Anfragekörper immer so lange zu behalten.

Der Fehlercode 4.13 (Request Entity Too Large) kann jederzeit von einem Server zurückgegeben werden, der derzeit nicht über die Ressourcen verfügt, um Blöcke für eine blockweise Anfragenutzlastübertragung zu speichern, die er atomar implementieren möchte. (Beachten Sie, dass eine 4.13-Antwort auf eine Anfrage, die Block1 nicht verwendet, ein Hinweis für den Client ist, zu versuchen, Block1 zu senden, und eine 4.13-Antwort mit einem kleineren SZX in ihrer Block1-Option als angefordert ein Hinweis ist, einen kleineren SZX zu versuchen.)

Eine blockweise Übertragung einer Anfragenutzlast, die auf dem Server zustandslos implementiert wird, hinterlässt wahrscheinlich die Ressource, auf der operiert wird, in einem inkonsistenten Zustand, während die Übertragung noch läuft oder wenn der Client die Übertragung nicht abschließt. Diese Eigenschaft ähnelt eher der von Remote-Dateisystemen als der von HTTP, wo der Zustand während einer Übertragung immer auf dem Server gehalten wird. Techniken, die aus dem gemeinsamen Dateizugriff bekannt sind (z. B. clientspezifische temporäre Ressourcen), können verwendet werden, um diesen Unterschied zu HTTP zu mildern.

Die Block1-Option bietet keine Möglichkeit für einen einzelnen Endpunkt, mehrere gleichzeitig ablaufende blockweise Anfragenutzlastübertragungsoperationen (z. B. PUT oder POST) auf dieselbe Ressource durchzuführen. Das Starten einer neuen blockweisen Sequenz von Anfragen an dieselbe Ressource (bevor eine alte Sequenz vom selben Endpunkt beendet wurde) überschreibt einfach den Kontext, den der Server möglicherweise noch behält. (Dies ist wahrscheinlich genau das, was man in diesem Fall will -- der Client hat möglicherweise einfach neu gestartet und sein Wissen über die vorherige Sequenz verloren.)

2.6. Kombination von blockweisen Übertragungen mit der Observe-Option

Die Observe-Option bietet eine Möglichkeit für einen Client, über Änderungen einer Ressource im Laufe der Zeit benachrichtigt zu werden [RFC7641]. Von Clients beobachtete Ressourcen können größer sein, als sie in einer CoAP-Nachricht bequem verarbeitet oder übertragen werden können. Die folgenden Regeln gelten für die Kombination von blockweisen Übertragungen mit Benachrichtigungen.

Beobachtungsbeziehungen gelten immer für eine gesamte Ressource; die Block2-Option bietet keine Möglichkeit, einen einzelnen Block einer Ressource zu beobachten.

Wie bei grundlegenden GET-Übertragungen kann der Client seine gewünschte Blockgröße in einer Block2-Option in der GET-Anfrage angeben, die die Beobachtungsbeziehung herstellt oder erneuert. Wenn der Server blockweise Übertragungen unterstützt, SOLLTE er die Blockgröße beachten und sie als maximale Größe auf alle Benachrichtigungen/Antworten anwenden, die aus der GET-Anfrage resultieren (bis der Client aus der Liste der Beobachter entfernt wird oder der Eintrag in dieser Liste durch den Server aktualisiert wird, der eine neue GET-Anfrage für die Ressource vom Client erhält).

Beim Senden einer 2.05 (Content)-Benachrichtigung sendet der Server nur den ersten Block der Repräsentation. Der Client ruft den Rest der Repräsentation ab, als hätte er diese erste Antwort durch eine GET-Anfrage verursacht, d. h. durch Verwendung zusätzlicher GET-Anfragen mit Block2-Optionen, die NUM-Werte größer als Null enthalten. (Dies führt zur Übertragung der gesamten Repräsentation, auch wenn sich nur einige der Blöcke in Bezug auf eine vorherige Benachrichtigung geändert haben.)

Wie bei anderen sich dynamisch ändernden Ressourcen SOLLTE der Server, um sicherzustellen, dass die wieder zusammengesetzten Blöcke aus derselben Version der Repräsentation stammen, in jede Antwort eine ETag-Option aufnehmen, und der wieder zusammensetzende Client MUSS die ETag-Optionen vergleichen (Abschnitt 2.4). Mehr noch als im allgemeinen Fall von Block2 SOLLTEN Clients, die alle Blöcke einer Ressource abrufen möchten, über die sie mit einem ersten Block benachrichtigt wurden, bestrebt sein, dies ohne unangemessene Verzögerung zu tun.

Siehe Abschnitt 3.4 für Beispiele.

2.7. Kombination von Block1 und Block2

Bei PUT- und insbesondere bei POST-Austauschen können sowohl der Anfragekörper als auch der Antwortkörper groß genug sein, um die Verwendung von blockweisen Übertragungen zu erfordern. Zuerst verläuft die Block1-Übertragung des Anfragekörpers wie gewohnt. Beim Austausch des letzten Stücks dieser blockweisen Übertragung trägt die Antwort das erste Stück der Block2-Übertragung (NUM ist Null). Um diese Block2-Übertragung fortzusetzen, sendet der Client weiterhin Anfragen ähnlich den Anfragen in der Block1-Phase, lässt jedoch die Block1-Optionen weg und fügt eine Block2-Anfrageoption mit NUM ungleich Null ein.

Block2-Übertragungen, die den Antwortkörper für eine Anfrage abrufen, die Block1 verwendet hat, MÜSSEN in sequenzieller Reihenfolge durchgeführt werden.

2.8. Kombination von Block2 mit Multicast

Ein Client kann die Block2-Option in einer Multicast-GET-Anfrage mit NUM = 0 verwenden, um die Größe der Antwort zu begrenzen.

Ebenso kann eine Antwort auf eine Multicast-GET-Anfrage eine Block2-Option mit NUM = 0 verwenden, wenn die Repräsentation groß ist oder um die Größe der Antwort weiter zu begrenzen.

In beiden Fällen ruft der Client alle weiteren Blöcke unter Verwendung von Unicast-Austauschen ab; in den Unicast-Anfragen SOLLTE der Client alle Blockgrößenpräferenzen beachten, die vom Server in der Antwort auf die Multicast-Anfrage angegeben wurden.

Andere Verwendungen der Block-Optionen in Verbindung mit Multicast-Nachrichten sind Gegenstand weiterer Studien.

2.9. Antwortcodes

Über die in [RFC7252] definierten Antwortcodes hinaus definiert diese Spezifikation zwei Antwortcodes und erweitert die Bedeutung eines.

2.9.1. 2.31 Continue

Dieser neue Erfolgsstatuscode zeigt an, dass die Übertragung dieses Blocks des Anfragekörpers erfolgreich war und dass der Server das Senden weiterer Blöcke fördert, dass jedoch ein endgültiges Ergebnis der gesamten blockweisen Anfrage noch nicht bestimmt werden kann. Mit diesem Antwortcode wird keine Nutzlast zurückgegeben.

2.9.2. 4.08 Request Entity Incomplete

Dieser neue Client-Fehlerstatuscode zeigt an, dass der Server die Blöcke des Anfragekörpers nicht empfangen hat, die er zum Fortfahren benötigt. Der Client hat nicht alle Blöcke gesendet, sie nicht in der vom Server geforderten Reihenfolge gesendet oder sie vor so langer Zeit gesendet, dass der Server sie bereits verworfen hat.

(Beachten Sie, dass ein Grund dafür, dass die erforderlichen Blöcke nicht zur Hand sind, eine Content-Format-Nichtübereinstimmung sein kann, siehe Abschnitt 2.3. Implementierungshinweis: Ein Server kann eine Block1-Übertragung mit diesem Code ablehnen, wenn NUM != 0 und ein anderes Content-Format angegeben ist als vom aktuellen Zustand der Ressource erwartet. Wenn er die Übertragung zustandslos implementiert, kann er das Content-Format des Blocks mit dem der vorhandenen Ressource abgleichen. Wenn er die Übertragung atomar implementiert, kann er den Block mit dem teilweise wieder zusammengesetzten Stück Repräsentation abgleichen, das den Zustand der Ressource ersetzen soll.)

2.9.3. 4.13 Request Entity Too Large

In Abschnitt 5.9.2.9 von [RFC7252] ist der Antwortcode 4.13 (Request Entity Too Large) wie HTTP 413 "Request Entity Too Large" definiert. [RFC7252] empfiehlt außerdem, dass diese Antwort eine Size1-Option (Abschnitt 4) enthalten SOLLTE, um die maximale Größe der Anfrageentität anzugeben, die der Server verarbeiten kann und will, es sei denn, der Server ist nicht in der Lage, diese Informationen zur Verfügung zu stellen.

Die vorliegende Spezifikation erlaubt es dem Server, diesen Antwortcode jederzeit während einer Block1-Übertragung zurückzugeben, um anzuzeigen, dass er derzeit nicht über die Ressourcen verfügt, um Blöcke für eine Übertragung zu speichern, die er atomar implementieren möchte. Sie erlaubt es dem Server auch, eine 4.13-Antwort auf eine Anfrage zurückzugeben, die Block1 nicht verwendet, als Hinweis für den Client, zu versuchen, Block1 zu senden. Schließlich ist eine 4.13-Antwort auf eine Anfrage mit einer Block1-Option (Kontrollverwendung, siehe Abschnitt 2.3), bei der die Antwort einen kleineren SZX in ihrer Block1-Option trägt, ein Hinweis, diesen kleineren SZX zu versuchen.

2.10. Caching-Überlegungen

Diese Spezifikation versucht, eine Vielzahl von Implementierungsstrategien für Caches offen zu lassen, insbesondere solche in Caching-Proxys. Zum Beispiel steht es einem Cache frei, Blöcke einzeln zwischenzuspeichern, er könnte aber auch warten, bis er die vollständige Repräsentation erhalten hat, bevor er Teile davon bedient. Teilweises Caching kann in einem Cross-Proxy (entspricht einem Streaming-HTTP-Proxy) effizienter sein. Ein zwischengespeicherter Block (teilweise zwischengespeicherte Antwort) kann anstelle einer vollständigen Antwort verwendet werden, um eine blockweise Anfrage zu erfüllen, die einem Cache präsentiert wird. Beachten Sie, dass verschiedene Blöcke unterschiedliche Max-Age-Werte haben können, da sie zu unterschiedlichen Zeiten übertragen werden. Eine Antwort mit einem Block aktualisiert die Frische der vollständigen Repräsentation. Einzelne Blöcke können validiert werden, und die Validierung eines einzelnen Blocks validiert die vollständige Repräsentation. Eine Antwort mit einer Block1-Option in Kontrollverwendung mit gesetztem M-Bit macht zwischengespeicherte Antworten für die Ziel-URI ungültig.

Ein Cache oder Proxy, der Antworten kombiniert (z. B. um Blöcke in einer Anfrage aufzuteilen oder die Blockgröße in einer Antwort zu erhöhen, oder ein Cross-Proxy), muss möglicherweise 2.31- und 2.01/2.04-Antworten kombinieren; ein zustandsloser Server antwortet möglicherweise nur auf dem ersten übertragenen Block1-Block mit 2.01, was alle 2.04-Antworten für spätere Blöcke dominiert.

If-None-Match funktioniert nur bei Block1-Anfragen mit (NUM=0) und DARF NICHT bei Block1-Anfragen mit NUM != 0 verwendet werden.