Passa al contenuto principale

3. Esempi

Questa sezione fornisce una serie di brevi esempi con flussi di messaggi per un GET a blocchi e per un PUT o POST. Questi esempi dimostrano il funzionamento di base, il funzionamento in presenza di ritrasmissioni ed esempi per il funzionamento della negoziazione delle dimensioni dei blocchi.

In tutti questi esempi, un'opzione Block viene mostrata in modo scomposto indicando il tipo di opzione Block (1 o 2) seguito da due punti, quindi il numero di blocco (NUM), bit more (M) e l'esponente della dimensione del blocco (2**(SZX+4)) separati da barre. Ad esempio, un valore di opzione Block2 di 33 verrebbe mostrato come 2:2/0/32) e un valore di opzione Block1 di 59 verrebbe mostrato come 1:3/1/128.

Come in [RFC7252], "MID" viene utilizzato come abbreviazione di "Message ID" (ID Messaggio).

3.1. Esempi Block2

Il primo esempio (Figura 2) mostra una richiesta GET suddivisa in tre blocchi. Il server propone una dimensione di blocco di 128 e il client accetta. I primi due ACK contengono un payload di 128 byte ciascuno e il terzo ACK contiene un payload compreso tra 1 e 128 byte.

CLIENT                                                     SERVER
| |
| CON [MID=1234], GET, /status ------> |
| |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/128 |
| |
| CON [MID=1235], GET, /status, 2:1/0/128 ------> |
| |
| <------ ACK [MID=1235], 2.05 Content, 2:1/1/128 |
| |
| CON [MID=1236], GET, /status, 2:2/0/128 ------> |
| |
| <------ ACK [MID=1236], 2.05 Content, 2:2/0/128 |

Figura 2: GET a Blocchi Semplice

Nel secondo esempio (Figura 3), il client anticipa il trasferimento a blocchi (ad esempio, a causa di un'indicazione delle dimensioni nella descrizione del formato del collegamento [RFC6690]) e invia una proposta di dimensione del blocco. Tutti i messaggi ACK tranne l'ultimo trasportano 64 byte di payload; l'ultimo ne trasporta tra 1 e 64 byte.

CLIENT                                                     SERVER
| |
| CON [MID=1234], GET, /status, 2:0/0/64 ------> |
| |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/64 |
| |
| CON [MID=1235], GET, /status, 2:1/0/64 ------> |
| |
| <------ ACK [MID=1235], 2.05 Content, 2:1/1/64 |
: :
: ... :
: :
| CON [MID=1238], GET, /status, 2:4/0/64 ------> |
| |
| <------ ACK [MID=1238], 2.05 Content, 2:4/1/64 |
| |
| CON [MID=1239], GET, /status, 2:5/0/64 ------> |
| |
| <------ ACK [MID=1239], 2.05 Content, 2:5/0/64 |

Figura 3: GET a Blocchi con Negoziazione Anticipata

Nel terzo esempio (Figura 4), il client è sorpreso dalla necessità di un trasferimento a blocchi e insoddisfatto della dimensione scelta unilateralmente dal server. Poiché non ha inviato inizialmente una proposta di dimensione, la negoziazione influenza solo la dimensione dal secondo scambio di messaggi in poi. Poiché il client ha già ottenuto sia il primo che il secondo blocco da 64 byte nel primo scambio da 128 byte, continua richiedendo il terzo blocco da 64 byte ("2/0/64"). Niente di tutto ciò viene (o deve essere) compreso dal server, che risponde semplicemente alle richieste nel miglior modo possibile.

CLIENT                                                     SERVER
| |
| CON [MID=1234], GET, /status ------> |
| |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/128 |
| |
| CON [MID=1235], GET, /status, 2:2/0/64 ------> |
| |
| <------ ACK [MID=1235], 2.05 Content, 2:2/1/64 |
| |
| CON [MID=1236], GET, /status, 2:3/0/64 ------> |
| |
| <------ ACK [MID=1236], 2.05 Content, 2:3/1/64 |
| |
| CON [MID=1237], GET, /status, 2:4/0/64 ------> |
| |
| <------ ACK [MID=1237], 2.05 Content, 2:4/1/64 |
| |
| CON [MID=1238], GET, /status, 2:5/0/64 ------> |
| |
| <------ ACK [MID=1238], 2.05 Content, 2:5/0/64 |

Figura 4: GET a Blocchi con Negoziazione Tardiva

In tutti questi (e nei seguenti) casi, le ritrasmissioni sono gestite dal livello di scambio dei messaggi CoAP, quindi non influenzano le operazioni di blocco (Figure 5 e 6).

CLIENT                                                     SERVER
| |
| CON [MID=1234], GET, /status ------> |
| |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/128 |
| |
| CON [MID=1235], GE///////////////////////// |
| |
| (timeout) |
| |
| CON [MID=1235], GET, /status, 2:2/0/64 ------> |
| |
| <------ ACK [MID=1235], 2.05 Content, 2:2/1/64 |
: :
: ... :
: :
| CON [MID=1238], GET, /status, 2:5/0/64 ------> |
| |
| <------ ACK [MID=1238], 2.05 Content, 2:5/0/64 |

Figura 5: GET a Blocchi con Negoziazione Tardiva e CON Perso
CLIENT                                                     SERVER
| |
| CON [MID=1234], GET, /status ------> |
| |
| <------ ACK [MID=1234], 2.05 Content, 2:0/1/128 |
| |
| CON [MID=1235], GET, /status, 2:2/0/64 ------> |
| |
| //////////////////////////////////tent, 2:2/1/64 |
| |
| (timeout) |
| |
| CON [MID=1235], GET, /status, 2:2/0/64 ------> |
| |
| <------ ACK [MID=1235], 2.05 Content, 2:2/1/64 |
: :
: ... :
: :
| CON [MID=1238], GET, /status, 2:5/0/64 ------> |
| |
| <------ ACK [MID=1238], 2.05 Content, 2:5/0/64 |

Figura 6: GET a Blocchi con Negoziazione Tardiva e ACK Perso

3.2. Esempi Block1

I seguenti esempi dimostrano uno scambio PUT; uno scambio POST appare uguale, con requisiti diversi su atomicità/idempotenza. Si noti che, analogamente al GET, le risposte alle richieste che hanno un bit more nell'opzione Block1 della richiesta sono provvisorie e portano il codice di risposta 2.31 (Continue); solo la risposta finale indica al client che il PUT è riuscito.

CLIENT                                                     SERVER
| |
| CON [MID=1234], PUT, /options, 1:0/1/128 ------> |
| |
| <------ ACK [MID=1234], 2.31 Continue, 1:0/1/128 |
| |
| CON [MID=1235], PUT, /options, 1:1/1/128 ------> |
| |
| <------ ACK [MID=1235], 2.31 Continue, 1:1/1/128 |
| |
| CON [MID=1236], PUT, /options, 1:2/0/128 ------> |
| |
| <------ ACK [MID=1236], 2.04 Changed, 1:2/0/128 |

Figura 7: PUT a Blocchi Atomico Semplice

Un server senza stato che semplicemente costruisce/aggiorna la risorsa sul posto (senza stato) può indicarlo non impostando il bit more nella risposta (Figura 8); in questo caso, i codici di risposta sono validi separatamente per ogni blocco aggiornato. Questo è ovviamente un comportamento accettabile del server solo se la potenziale inconsistenza presente durante l'esecuzione della sequenza di scambio di messaggi non porta a problemi, ad esempio perché la risorsa creata o modificata non è ancora o non è attualmente in uso.

CLIENT                                                     SERVER
| |
| CON [MID=1234], PUT, /options, 1:0/1/128 ------> |
| |
| <------ ACK [MID=1234], 2.04 Changed, 1:0/0/128 |
| |
| CON [MID=1235], PUT, /options, 1:1/1/128 ------> |
| |
| <------ ACK [MID=1235], 2.04 Changed, 1:1/0/128 |
| |
| CON [MID=1236], PUT, /options, 1:2/0/128 ------> |
| |
| <------ ACK [MID=1236], 2.04 Changed, 1:2/0/128 |

Figura 8: PUT a Blocchi Semplice Senza Stato

Infine, un server che riceve un PUT o POST a blocchi potrebbe voler indicare una preferenza per una dimensione di blocco più piccola (Figura 9). In questo caso, il client DOVREBBE continuare con una dimensione di blocco più piccola; se lo fa, DEVE regolare il numero di blocco per contare correttamente in quella dimensione più piccola.

CLIENT                                                     SERVER
| |
| CON [MID=1234], PUT, /options, 1:0/1/128 ------> |
| |
| <------ ACK [MID=1234], 2.31 Continue, 1:0/1/32 |
| |
| CON [MID=1235], PUT, /options, 1:4/1/32 ------> |
| |
| <------ ACK [MID=1235], 2.31 Continue, 1:4/1/32 |
| |
| CON [MID=1236], PUT, /options, 1:5/1/32 ------> |
| |
| <------ ACK [MID=1235], 2.31 Continue, 1:5/1/32 |
| |
| CON [MID=1237], PUT, /options, 1:6/0/32 ------> |
| |
| <------ ACK [MID=1236], 2.04 Changed, 1:6/0/32 |

Figura 9: PUT a Blocchi Atomico Semplice con Negoziazione

3.3. Combinazione di Block1 e Block2

Le opzioni Block possono essere utilizzate in entrambe le direzioni di un singolo scambio. L'esempio seguente dimostra una richiesta POST a blocchi, che risulta in una risposta a blocchi separata.

CLIENT                                                     SERVER
| |
| CON [MID=1234], POST, /soap, 1:0/1/128 ------> |
| |
| <------ ACK [MID=1234], 2.31 Continue, 1:0/1/128 |
| |
| CON [MID=1235], POST, /soap, 1:1/1/128 ------> |
| |
| <------ ACK [MID=1235], 2.31 Continue, 1:1/1/128 |
| |
| CON [MID=1236], POST, /soap, 1:2/0/128 ------> |
| |
| <------ ACK [MID=1236], 2.04 Changed, 2:0/1/128, 1:2/0/128 |
| |
| CON [MID=1237], POST, /soap, 2:1/0/128 ------> |
| (no payload for requests with Block2 with NUM != 0) |
| (could also do late negotiation by requesting, |
| e.g., 2:2/0/64) |
| |
| <------ ACK [MID=1237], 2.04 Changed, 2:1/1/128 |
| |
| CON [MID=1238], POST, /soap, 2:2/0/128 ------> |
| |
| <------ ACK [MID=1238], 2.04 Changed, 2:2/1/128 |
| |
| CON [MID=1239], POST, /soap, 2:3/0/128 ------> |
| |
| <------ ACK [MID=1239], 2.04 Changed, 2:3/0/128 |

Figura 10: POST a Blocchi Atomico con Risposta a Blocchi

Questo modello fornisce un input di negoziazione anticipata per il trasferimento a blocchi Block2, come mostrato di seguito.

CLIENT                                                     SERVER
| |
| CON [MID=1234], POST, /soap, 1:0/1/128 ------> |
| |
| <------ ACK [MID=1234], 2.31 Continue, 1:0/1/128 |
| |
| CON [MID=1235], POST, /soap, 1:1/1/128 ------> |
| |
| <------ ACK [MID=1235], 2.31 Continue, 1:1/1/128 |
| |
| CON [MID=1236], POST, /soap, 1:2/0/128, 2:0/0/64 ------> |
| |
| <------ ACK [MID=1236], 2.04 Changed, 1:2/0/128, 2:0/1/64 |
| |
| CON [MID=1237], POST, /soap, 2:1/0/64 ------> |
| (no payload for requests with Block2 with NUM != 0) |
| |
| <------ ACK [MID=1237], 2.04 Changed, 2:1/1/64 |
| |
| CON [MID=1238], POST, /soap, 2:2/0/64 ------> |
| |
| <------ ACK [MID=1238], 2.04 Changed, 2:2/1/64 |
| |
| CON [MID=1239], POST, /soap, 2:3/0/64 ------> |
| |
| <------ ACK [MID=1239], 2.04 Changed, 2:3/0/64 |

Figura 11: POST a Blocchi Atomico con Risposta a Blocchi,
Negoziazione Anticipata

3.4. Combinazione di Observe e Block2

Nell'esempio seguente, il server invia prima una risposta diretta (numero di sequenza Observe 62350) alla richiesta GET iniziale (il trasferimento a blocchi risultante è come nella Figura 4 ed è stato quindi omesso). Il secondo trasferimento viene avviato da una notifica 2.05 che contiene solo il primo blocco (numero di sequenza Observe 62354); il client quindi procede a ottenere il resto dei blocchi.

    CLIENT  SERVER
| |
+----->| Header: GET 0x41011636
| GET | Token: 0xfb
| | Uri-Path: status-icon
| | Observe: (empty)
| |
|<-----+ Header: 2.05 0x61451636
| 2.05 | Token: 0xfb
| | Block2: 0/1/128
| | Observe: 62350
| | ETag: 6f00f38e
| | Payload: [128 bytes]
| |
| | (Usual GET transfer left out)
...
| | (Notification of first block)
| |
|<-----+ Header: 2.05 0x4145af9c
| 2.05 | Token: 0xfb
| | Block2: 0/1/128
| | Observe: 62354
| | ETag: 6f00f392
| | Payload: [128 bytes]
| |
+- - ->| Header: 0x6000af9c
| |
| | (Retrieval of remaining blocks)
| |
+----->| Header: GET 0x41011637
| GET | Token: 0xfc
| | Uri-Path: status-icon
| | Block2: 1/0/128
| |
|<-----+ Header: 2.05 0x61451637
| 2.05 | Token: 0xfc
| | Block2: 1/1/128
| | ETag: 6f00f392
| | Payload: [128 bytes]
| |
+----->| Header: GET 0x41011638
| GET | Token: 0xfc
| | Uri-Path: status-icon
| | Block2: 2/0/128
| |
|<-----+ Header: 2.05 0x61451638
| 2.05 | Token: 0xfc
| | Block2: 2/0/128
| | ETag: 6f00f392
| | Payload: [53 bytes]

Figura 12: Sequenza Observe con Risposta a Blocchi

(Si noti che la scelta del token 0xfc in questo esempio è arbitraria; i token vengono mostrati solo in questo esempio per illustrare che le richieste di blocchi aggiuntivi non possono utilizzare il token della relazione di Osservazione. Come commento generale sui token, non c'è altra menzione dei token in questo documento, poiché i trasferimenti a blocchi gestiscono i token come qualsiasi altro scambio CoAP. Come al solito, il client è libero di scegliere i token per ogni scambio come preferisce.)

Nell'esempio seguente, il client utilizza anche la negoziazione anticipata per limitare la dimensione del blocco a 64 byte.

    CLIENT  SERVER
| |
+----->| Header: GET 0x41011636
| GET | Token: 0xfb
| | Uri-Path: status-icon
| | Observe: (empty)
| | Block2: 0/0/64
| |
|<-----+ Header: 2.05 0x61451636
| 2.05 | Token: 0xfb
| | Block2: 0/1/64
| | Observe: 62350
| | ETag: 6f00f38e
| | Max-Age: 60
| | Payload: [64 bytes]
| |
| | (Usual GET transfer left out)
...
| | (Notification of first block)
| |
|<-----+ Header: 2.05 0x4145af9c
| 2.05 | Token: 0xfb
| | Block2: 0/1/64
| | Observe: 62354
| | ETag: 6f00f392
| | Payload: [64 bytes]
| |
+- - ->| Header: 0x6000af9c
| |
| | (Retrieval of remaining blocks)
| |
+----->| Header: GET 0x41011637
| GET | Token: 0xfc
| | Uri-Path: status-icon
| | Block2: 1/0/64
| |
|<-----+ Header: 2.05 0x61451637
| 2.05 | Token: 0xfc
| | Block2: 1/1/64
| | ETag: 6f00f392
| | Payload: [64 bytes]
....
| |
+----->| Header: GET 0x41011638
| GET | Token: 0xfc
| | Uri-Path: status-icon
| | Block2: 4/0/64
| |
|<-----+ Header: 2.05 0x61451638
| 2.05 | Token: 0xfc
| | Block2: 4/0/64
| | ETag: 6f00f392
| | Payload: [53 bytes]

Figura 13: Sequenza Observe con Negoziazione Anticipata