Hlavní navigace

Sokety a C/C++: Urgentní data

Radim Dostál 16. 6. 2003

Kromě "normálních" dat, která jsme doposud přenášeli od odesílatele k příjemci, existují také tak zvaná urgentní data, která jsou "nenormální", "výjimečná". I ve světě soketů platí, že všechna data jsou si rovna, ale některá jsou si rovnější. Urgentní data (zkratkou označována jako OOB - Out Of Band) jsou data, která při odesílání označíme jako urgentní. Informace o tom, zda se jedná, nebo nejedná o urgentní data, je součástí hlavičky TCP segmentu.

V rámci otevřeného spojení mám k dispozici proud dat. V jednom spojení můžeme krom tohoto „hlavního“ proudu dat vytvořit virtuální kanál obsahující jiný proud (urgentních) dat, který je na „hlavním“ proudu nezávislý.

Jak si vlastně pojem urgentních dat představit? V jednom z úvodních článků seriálu věnovaného základům práce se sokety jsem komunikaci TCP serveru a TCP klienta popsal velice obrazně pomocí potrubí (nebo hadice), kterým jsou oba počítače spojeny. Vysvětlil jsem tak pojem soket. Představme si, že trubka v sobě obsahuje jinou menší trubku. Ve vložené trubce také proudí data. Tento proud je nezávislý na proudu dat, který proudí ve vnější trubce, ale mimo vnořenou trubku. Vnořená trubka je vlastně virtuální nezávislý kanál pro přenos urgentních dat v rámci spojení, kterým proudí jinak „normální“ data.

Mechanismus urgentních dat se obvykle používá k přenosu dat, která jsou nějak významná. Představme si situaci, kdy server přijímá od klienta velké množství dat a nad těmito daty průběžně provádí nějaký náročný výpočet. Klient odešle mnoho dat, a proto je na straně serveru také mnoho dat v příchozí frontě ještě nevyzvednuto (nepřečteno). Vtom ale klient zjistí, že výsledek, který si chtěl nechat serverem spočítat, už vlastně vůbec nepotřebuje. Protože se jedná o slušného klienta, chce dát serveru jasně najevo, že má přestat počítat a zpracovávat nepřečtená data (a tím snížit zátěž serveru), protože výsledek je již k ničemu. Jak to ale udělat? Kdyby odeslal nějaký předem dohodnutý byte nebo bloku bytů, po jehož přečtení má server přestat počítat, bude tento byte zařazen na serveru na konec fronty. Server bude stejně číst data, která obdržel před příchodem pokynu přestat počítat (ten bude na konci fronty) a bude stejně všechna dříve doručená data zpracovávat. Zde se přímo nabízí použití urgentních dat. Můžeme označit onen pokyn „Přestaň počítat“ za urgentní a poslat ho oním virtuálním kanálem, který přenáší data nezávisle na kanálu „hlavním“.

Ve skutečnosti (neurčíme-li jinak) jsou urgentní data vkládána do jiné fronty příchozích dat než „normální“ data. Proto je příjemce může přečíst okamžitě.

Odeslání a příjem urgentních dat

Data, která mají být urgentní, musíme při odeslání za urgentní označit. Když jsem hovořil o funkci send, zmínil jsem se o posledním parametru udávajícím příznaky. Doposud jsme vždy zadávali 0. Chceme-li data označit za urgentní, zadáme jako příznak hodnotu makra MSG_OOB. Chceme-li přečíst urgentní data ze soketu, zadáme jako poslední parametr (příznak) funkce recv rovněž hodnotu makra MSG_OOB. Tento postup je shodný ve WinSock API i v klasickém Socket API.

Odeslání urgentních dat

recv(soc, buffer, size, MSG_OOB);

Událost příchodu urgentních dat

V souvislosti s funkcí select jsme si uváděli tři množiny. V první jsou sokety, kde select hlídá, zda je možné číst. V druhé select hlídá, zda je možné zapisovat. A ve třetí (jsem nepřesně napsal) select hlídá, zda nedošlo k chybě. To jsem neuvedl úplnou pravdu. Funkce selecthlídá, zda nedošlo na soketu k výjimečné situaci. Příchod urgentních dat výjimečná situace je. Chceme-li si selectem pohlídat urgentní data, vyplníme množinu a ukazatel na ni předáme selectu jako čtvrtý parametr.

Příjem urgentních dat

fd_set normalSet, extraSet;
// Zaplním dvě množiny. Jednu pro čtení, druhou pro výjimečné situace.
FD_ZERO(&normalSet);
FD_SET(soc, &normalSet);
FD_ZERO(&extraSet);
FD_SET(soc, &extraSet);
// Čekám, jestli nepřijdou normální data nebo urgentní data
select(soc + 1, &normalSet, NULL, &extraSet, NULL);
if (FD_ISSET(soc, &extraSet))
{
    recv(soc, buffer, size, MSG_OOB);
}
if (FD_ISSET(soc, &normalSet))
{
    recv(soc, buffer, size, 0);
}

Jsou-li v přijímací frontě urgentní data, která nejsou přečtená, a přijdou další urgentní data, „stará“ urgentní data budou zařazena do fronty k „normálním“ datům. Takže přijdou-li novější urgentní data, stará nepřečtená urgentní data se stanou normálními daty.

V tomto a v minulých dvou článcích jsme si vlastně ukázali využití všech tří množin, které se zadávají funkci select.

Příklad

Jako příklad si ukážeme server, který po jednotlivých bytech čte příchozí data. Postupně s každým byte provádí časově náročný výpočet. Až narazí mezi příchozími byty na 0, odešle všechny výsledky, které spočítal, najednou klientovi. Jako urgentní data může server obdržet počet všech čísel, které od klienta obdržel od posledního předání výsledku. V případě doručení urgentních dat klient již nechce výsledek. Server přeruší výpočet a klientovi nic neodesílá. Čeká na další posloupnost čísel. Server se ukončí v případě, že klient uzavře spojení. Takto jednoduše napsaný server není schopen obsluhovat více klientů najednou.

Všimněte si na příkladu menšího nedostatku. Ve všech příkladech v dřívějších článcích jsem posílal a přijímal textová data. Nyní posílám binární data. Problém ale je, že nijak neošetřuji situaci, kdy odesílatel a přijímající budou běžet na různých architekturách, které mají jinou reprezentaci čísla. Na podobné věci je potřeba vždy myslet.

Tabulka č. 440
Soubor OS
lin15.tgz Linux
win15.zip MS WindowsŽ

Existuje možnost, aby urgentní data a „normální“ data byla vkládána do jedné příchozí fronty. Museli bychom nastavit volbu SO_OOBINLINE. O tom si povíme příště. Podíváme se na volby soketů.

Našli jste v článku chybu?

19. 6. 2003 10:48

John (neregistrovaný)

Diky za info. IMO Windows i Linux jsou BSD kompatibilni. Shanim tedy nekompatibilni platformu, abych to mohl otestovat meziplatforme :-).

Nejde mi ani tak o OOB data jako spise o signal SIGURG, ktery je snad mozno odchytavat, a kterym bych mohl merit presnou zpozdeni kanalu. Timto kanalem chci zaroven posilat i normalni data.



18. 6. 2003 15:12

Radim Dostál (neregistrovaný)

O tom problému jsem už něco slyšel, ale ještě jsem se s ním nesetkal (Možná o to horší to bude, až se s ním opravdu setkám :-) ). Jde o to, že podle starší specifikace normy není jasné, jestli ukazatel na konec urgentních dat (který je součástí hlavičky TCP) má ukazovat na poslední byte urgentních dat, nebo na první byte za posledním bytem urgentních dat.
V každém případě příklady pod článkem fungují i při komuniakci Linux - Win. Linux by měl mít BSD kompatibilní socket API.


Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Lupa.cz: Seznam mění vedení. Pavel Zima v čele končí

Seznam mění vedení. Pavel Zima v čele končí

Root.cz: 250 Mbit/s po telefonní lince, když máte štěstí

250 Mbit/s po telefonní lince, když máte štěstí

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Podnikatel.cz: Na poslední chvíli šokuje výjimkami v EET

Na poslední chvíli šokuje výjimkami v EET

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život