12.5. Megbízhatóság – sorszámok, ACK-k, újraküldések¶
A keretezési réteg a CRC-k segítségével észleli a sérülést. A megbízhatósági réteg az „észlelt sérülést” azzá alakítja, hogy „az alkalmazás soha nem lát hibás adatot”, úgy, hogy újraküldéseket egyeztet minden alkalommal, amikor egy csomag nem érkezik meg sértetlenül.
12.5.1. Sorszámok¶
Minden csomag fejléce egy egybájtos sorszámot hordoz, külön mindkét haladási irányhoz. A küldő az átvitel előtt növeli a számlálót; a fogadó ellenőrzi, hogy minden beérkező csomag sorszáma az előzőnél eggyel nagyobb-e (modulo 256).
Három dolog jelenhet meg a fogadónál egy tiszta, sorrendben érkező csomag helyett:
A várt sorszám, érvényes CRC-vel. A csomagot a rendszer továbbítja a következő rétegnek.
A várt sorszám, hibás CRC-vel. A fogadó eldobja a csomagot, és (ha ACK-k vannak egyeztetve) NAK-ot küld újraküldést kérve.
Egy a vártnál eggyel nagyobb sorszám, érvényes CRC-vel. A fogadó tudja, hogy az előző csomag elveszett; NAK-ot küld a kimaradt sorszámra hivatkozva, és eltárolja az újat.
A duplikátum esetét (egy újraküldés érkezik azután, hogy az eredeti végül átért) a várt számlálóval való összevetés kezeli: ha a sorszám a vártnál hátrébb van, a csomag duplikátum, és a fogadó eldobja, miután elküldte azt az ACK-ot, amelyet a küldő nyilvánvalóan nem kapott meg első alkalommal.
12.5.2. ACK és NAK¶
A csomag fejlécében két jelzőbit hordozza magát a megbízhatósági forgalmat:
Egy kimenő csomagra beállított
ACK_REQazt jelenti: „Visszaigazolást kérek.” Az adatcsomagok ezt általában beállítják; az állapot-pingek és az egyszeri események esetleg nem.Egy csomagra beállított
ACKazt jelenti: „ez a csomag a fejlécben szereplő sorszám visszaigazolása.” Saját hasznos adatot nem hordoz.A beállított
NAKazt jelenti: „ez a csomag elutasít egy korábbit” – általában hibás CRC vagy sorszám-hézag miatt. A fejléc megmutatja a küldőnek, melyik sorszámot kell újraküldeni.
A küldő stop-and-wait ciklust futtat: elküld egy visszaigazolást igénylő csomagot, majd a következő küldése előtt megvárja a hozzá tartozó ACK-ot (vagy NAK-ot). Az egyetlen-úton-lévő modell korlátok között tartja a küldő állapotát – néhány száz bájt a legkisebb kamerákon –, és illeszkedik a protokoll szerepéhez, amely két végpont közötti vezérlőcsatorna, nem pedig átviteli teljesítményre optimalizált adatfolyam. NAK esetén a küldő ugyanazt a csomagot a RTX jelzővel beállítva küldi újra, hogy a fogadó tudja, ez egy újrapróbálkozás.
12.5.3. Újraküldés időzítése¶
Ha sem ACK, sem NAK nem érkezik az újraküldési időkorláton belül, a küldő magától küldi újra az úton lévő csomagot. Az időkorlát alapértelmezett értéke 500 ms, és minden egymást követő újrapróbálkozásnál megduplázódik (1 s, 2 s, …). A beállított számú újrapróbálkozás után – alapértelmezésben három – a küldő feladja, és transzporthibát jelent az alkalmazásnak.
Az időkorlát megduplázása a szabványos exponenciális visszalépés (exponential backoff) minta. A rövid első időkorlát gyorsan elkapja az elveszett csomagokat; a duplázás azt jelenti, hogy egy néhány száz milliszekundumig elfoglalt gazdagép nem indít be egy duplikátumokból álló rohamot, amely tovább növelné a terhelést.
12.5.4. A megbízhatóság konfigurálása¶
Mindkét végpont kikapcsolhat a megbízhatósági réteg egyes részeit – megegyezés alapján –, ha az alkalmazás megengedheti magának az adatvesztést:
A
protocol.init(ack=False)letiltja a csomagonkénti ACK-kat. A küldő elküldi és elfelejti; a fogadó kézbesíti azt, ami megérkezik. Jó olyan érzékelőadatok streameléséhez, ahol egy elavult minta elfogadható.A
protocol.init(seq=False)kikapcsolja a sorszámkövetést, ami egyúttal az ACK-k kikapcsolását is jelenti. Csak tökéletesen megbízható transzportokon hasznos.A
protocol.init(crc=False)kikapcsolja a CRC-ellenőrzést, de a keretezés többi részét érintetlenül hagyja. Csak akkor érdemes, ha maga a transzport elég robusztus ahhoz, hogy CRC-hibák ne forduljanak elő.
Az alapértelmezések – minden bekapcsolva – a megfelelő kiindulópont bármilyen gazdagép-kamera hibakeresési munkamenethez. Amint az alkalmazás éles üzembe kerül, a kompromisszumok az adataira és a transzportjára nézve specifikussá válnak.
12.5.5. Az állapotkódok¶
Amikor egy transzporthiba felbukkan az alkalmazás kódjáig, állapotkódként érkezik. A protokollkönyvtár tízet definiál:
SUCCESS– a művelet sikeresen befejeződött.FAILED– a parancs meghatározatlan okból meghiúsult.INVALID– a fogadó elutasította a parancsot vagy annak egyik argumentumát.TIMEOUT– egy újrapróbálkozási időzítő lejárt.BUSY– a kamera foglalt (jellemzően egy zárolt csatorna).CHECKSUM– a fejléc vagy a hasznos adat CRC-je nem egyezett.SEQUENCE– a sorszám olyan mértékben volt sorrenden kívül, amelyből a réteg már nem tud helyreállni.OVERFLOW– egy hasznos adat túllépte az egyeztetett maximumot.FRAGMENT– egy több fragmensből álló üzenet hiányzó darabokkal érkezett.UNKNOWN– egy védekező gyűjtőkód a valóban váratlan helyzetekre.
A channel_read() metódust hívó gazdagép-kód ezeket Python-kivételekként látja; az egyedi hibakezelést választó kamera-oldali alkalmazáskód pedig a backend visszahívásokból visszatérési értékekként kapja meg őket. A legtöbb kameraalkalmazásnak egyáltalán nem kell az állapotkódokat figyelnie – a könyvtár kezeli az újrapróbálkozást, és csak a valóban helyrehozhatatlan hibák (pl. maga a transzport eltűnt) érik el az alkalmazást.
Most, hogy a keretezés a sérülés észlelésére, a megbízhatóság pedig a helyreállításra a helyén van, a vezetékszintű munka kész. Az alkalmazáskód keretezett, rendezett, sértetlen csomagokat lát; a bennük lévő bájtok szabadon jelenthetnek bármit, amit a fölöttük lévő csatorna szán nekik.