V oblasti počítačových sítí rozumíme pod pojmem protokol souhrn určitých sémantických a syntaktických pravidel dohodnutých jako způsob komunkace mezi stanicemi. Mezi syntaktická pravidla patří zejména dohodnuté formáty paketů, do pravidel sémantických spadají "algoritmy" komunikace, jako např. postupy pro zřizování a ukončování spojení, které musí respektovat všichni vzájemně komunikující partneři.
V dalším se budeme podrobně zabývat komunikací pomocí protokolu IPX, který je používán ve vemi rozšířených sítích Novell. Již na počátku však zdůrazněme, že jeho použítí není na sítě Novell nijak vázáno - můžeme jej použít pro komunikaci peer-to-peer v síti bez jakéhokoli standardního síťového software. Výhodou hovořící pro protokol IPX je skutečnost, že ovladače, které nás odstíní od hardwarově závislých detailů jsou dnes dodávány prakticky s každým síťovým adaptérem a my je můžeme napojit na standardní hardwarově nezávislý modul IPX, čímž poskytneme aplikacím definované softwarové rozhraní. Právě způsob používání tohoto rozhraní bude diskutován v následující kapitole.
Komunikační protokol IPX (Internetwork Packet Exchange) je nespojově orientovaným (datagramovým) protokolem, který zaručuje předávání nezávislých paketů v intersíti. Pohybujeme se tedy na úrovni síťové vrstvy OSI modelu. Každý paket se sítí šíří samostatně bez vazby na ostatní pakety a bez garance, že vůbec bude doručen. Z principu vzájemné nezávislosti paketů plyne, že obecně nemůžeme spoléhat na to, že pořadí, v jakém byly pakety odeslány bude nutně odpovídat pořadí, v jakém budou přijaty. Může rovněž dojít k duplikaci paketu, to znamená, že jednou vyslaný paket přijmeme dva i vícekrát. Problémy duplikace a změny pořadí se ovšem mohou vyskytnout pouze v sítích obsahujících alternativní cesty - paket může být přebrán více routery a pokud se cesty opět spojí, dojde tím k jeho duplikaci. Změna pořadí paketů rovněž připadá v úvahu v sítích s více cestami, protože cesty mohou mít obecně různé zpoždění a každý paket se může k příjemci pohybovat jinou cestou. Je tedy možné, že paket vyslaný později se k přijemci dostane cestou s nižším zpožděním dříve než předcházející paket, který byl ovšem směrován "pomalejší" cestou.
Protokol IPX byl odvozen ze standardu XNS zavedeného firmou Xerox.
Než přikročíme k vysvětlení chování protokolu IPX, je nutné objasnit, jakým způsobem jsou jednotlivé uzly sítě identifikovány. Učiňmě proto na tomto místě krátkou vsuvku o adresaci v intersítích používajících protokol IPX.
Adresa každého uzlu v síti s IPX protokolem je dána jednak dvaatřicetibitovou adresou sítě (Network Address] a osmačtyřicetibitovou adresou uzlu v rámci této sítě (Node Address]. Adresa sítě je přidělována administrátorem a musí být samozřejmě v rámci celé intersítě jednoznačná. Jako adresa uzlu na úrovni síťové vrstvy se téměř vždy přebírá hardwarová adresa adaptéru (z linkové vrstvy]. V případě sítí Ethernet je takovéto mapování adres přímé, zatímco u sítí s adresami sestávajícími z nižšího počtu bitů (ArcNet, Token Ring] jsou zbývající významnější bity doplněny nulami. Adresa uzlu s hodnotou 0xFFFFFFFFFFFF je vyhrazena pro všesměrové vysílání (broadcast], hodnota 0 síťové adresy označuje implicitní síť, tj. síť, ke které je stanice přímo připojena (default network).
Mimo adres uzlů jsou komunikující procesy navíc identifikovány tzv. číslem socketu. Na každé komunikující stanici (uzlu) totiž může současně běžet celá řada procesů, které budou chtít nezávisle na sobě komunikovat. Proto je každému procesu (službě) přiděleno 16-bitové číslo socketu, které jej v rámci stanice jednoznačně identifikuje. Všechny pakety vyslané tímto procesem pak spolu s adresou odesílatele ponesou i číslo socketu vysílajícího procesu. Naopak při příjmu paketu stanicí zaručí ovladače síťového adaptéru, že paket bude doručen právě jen procesu, jenž je identifikován číslem soketu příjemce v hlavičce IPX paketu. Některá čísla socketů mohou být uživatelem používána libovolně (0x4000-0x8000], zatímco jiná jsou vyhrazena pro standardní síťové služby (Novell) nebo rezervována jednotlivými výrobci síťových aplikací (hodnoty 0x8000-0xFFFF]. Tak například příjde-li Novell file serveru paket s číslem socketu 453, okamžitě z toho pozná, že se jedná o paket nesoucí informaci pro budování směrovacích tabulek (RIP) a podle toho s ním naloží.
Není podmínkou, aby proces přijímal pouze pakety s jediným číslem soketu
- může zaregistrovat zájem o celou řadu čísel. Podrobněji se sockety budeme
zabývat při popisu jednotlivých funkcí pro komunikaci prostřednictvím IPX.
Dobrým vodítkem k pochopení práce protokolu IPX je znalost významů jednotlivých polí hlavičky paketu. Zopakujme, že paket je obsahem datové části rámce druhé vrstvy a během šíření sítí není (s výjimkou jednoho pole hlavičky) modifikován.
Každý paket sestává z hlavičky (header) a datové části. Hlavička obsahuje servisní informace, jako je adresa odesílatele a adresa příjemce, zatímco v datové části jsou uživatelská data. Během šíření paketu sítí je routery analyzována pouze hlavička paketu, uživatelská data zůstávájí netknuta.
Celková délka paketu IPX je maximálně 576 bajtů, takže s ohledem na velikost hlavičky 30 B zbývá 546 bajtů na užitečnou informaci. Poznamenejme, že implementace IPX dodávané spolu s novějšími verzemi Novellu umožňují nakonfigurovat i větší délku paketu (v terminologii Novellu označovaných zkratkou LIP - Large Internet Packet). Tím dosáhneme lepšího využití sítě, jelikož se zvýší poměr přenášené užitečné informace k informaci servisní. Při konfigurování větších maximálních velikostí paketů než standardních 576 byte však musíme být opatrní s ohledem na to, že starší verze routerů nemusí být schopny takto dlouhé pakety zpracovat a v horším případě routeru s méně robustním software může teoreticky dojít i k jeho zhroucení. V případě použití LIP nesmíme pochopitelně překročit maximální délku rámce linkové vrstvy žádné ze sítí, jimiž mají takovéto pakety procházet, protože IPX nepodporuje (narozdíl např. od protokolu IP) fragmentaci a znovusestavování (reassembling) paketů.
Podívejme se nyní podrobněji na jednotlivé položky hlavičky paketů IPX, která je vyobrazena na obr. I.1.
Offset | Obsah |
0 | Checksum |
2 | Length |
4 | Transport Control |
5 | Packet Type |
6 | Destination Network |
10 | Destination Node |
16 | Destination Socket |
18 | Source Network |
22 | Source Node |
28 | Source Socket |
Checksum kontrolní součet. Je-li paket IPX nesen přímo v rámci ETHERNET_802.3 (bez pole LLC), je zde hodnota 0xFFFF. Zabezpečení dat se provádí také na úrovni linkové vrstvy nebo uživatelsky (tedy ve vyšších vrstvách).
Length délka paketu včetně záhlaví. Z tohoto pole můžeme vyčíst délku přijatého paketu. Délka vysílaného paketu se do tohoto pole doplní na základě součtu délek z deskriptorů fragmentů v ECB (viz. dále)
Transport Control pole používané směrovači pro likvidaci bloudivých paketů (někdy označované TTL - Time to Live). Před vysláním paketu se nastaví na nulu (to učiní driver IPX). Při průchodu směrovačem se hodnota zvýší o jedničku a když dosáhne určité hranice (zpravidla 16, ale lze i nastavit), paket se zruší se. Tím se zamezuje cyklickému předávání paketů a zahlcení sítě zbloudilými pakety. Je si však nutné uvědomit, že rozsah sítě (co do počtu směrovačů mezi nejvzdálenějšími stanicemi) je omezen maximální hodnotou TTL.
Packet Type typ paketu, blíže definuje určení údajů v datové
části paketu. Některé hodnoty jsou shrnuty v tab. I.1
0 | Neznámý paket |
1 | RIP Paket (Routing Information Protocol] |
4 | Packet Exchange Packet |
5 | SPX (Sequenced Packet Exchange ] |
16-31 | experimentální protokoly |
17 | NCP (NetWare Core Protocol ] |
Pro účely experimentování bychom měli používat hodnoty 0 nebo 4.
Destination Network - adresa sítě, na níž je připojen uzel příjemce
Destination Node - adresa uzlu příjemce
Destination Socket číslo socketu příjemce, HI-LO format
Source Network - adresa sítě odesílatele
Source Node - adresa uzlu odesílatele
Source Socket - číslo socketu odesílatele, HI-LO
Je třeba upozornit, že v souladu s konvencemi používanými v počítačových sítích jsou vícebajtové binární hodnoty ukládány v pořadí významnější_bajt-méně_významný_bajt (HI-LO], což je opačný způsob, než je zvykem např. na mikroprocesorech INTEL. Tato konvence se samozřejmě vztahuje jen da číselné hodnoty určené pro předávání přes síť. Musíme s ní tedy počítat při sestavování hlavičky IPX, nikoliv však např. při předávání parametrů dále popisovaným funkcím.
Z hlediska programátorského se jednotlivé funkce, jako je žádost o vyslání paketu nebo čekání na paket realizují zadáváním požadavků prostřednictvím řídící struktury událostí - ECB (Event Control Block]. Jednotlivé položky struktury podávají doplňující parametry k požadované akci, samotné funkce realizující jednotlivé činnosti se volají s parametrem, jímž je odkaz na strukturu ECB. Protože zde pracujeme se službami, které mohou trvat obecně libovolnou dobu (jako je např. čekání na příjem paketu), je jejich zpracování řešeno asynchronně. Jednotlivé požadavky si ovladač ukláda do fronty a vyřizuje je v pořadí, v jakém je to možné. Každý proces může vydat libovolné množství takovýchto požadavků zároveň (ve skutečnosti je maximální hodnota konfiguračním parametrem ovladače IPX). Poznamenejme, že pořadí zpracování událostí není garantováno, tedy např. při vydání více žádostí o vyslání paketu mohou být tyto pakety vyslány v různém pořadí. Tomu je samozřejmě možné předejít tím, že program vydá v jednom okamžiku jen jeden požadavek na vysílání a před vydáním dalšího počká na dokončení požadavku předchozího.
O dokončení události svázané s jistým požadavkem (definovaným konkrétní instancí struktury ECB] je uživatel informován nastavením položky ECB InUse na nulu. Z položky CompletionCode se může dozvědět, jak požadovaná akce skončila. Nulová hodnota znamená úspěch, ostatní hodnoty identifikují chybu.
Existuje ještě i jiný způsob, kterým se mohou programy o ukončení provádění
požadavku dozvědět. Je jím vyvolání obslužné rutiny přerušení - ESR (Event Service
Routine]. Jednou z položek struktury ECB je totiž položka ESR Address,
do níž je možné vložit (32-bitovou,segment:offset) adresu rutiny, která
má být při (úspěšném či neúspěšném) dokončení akce vyvolána. Je-li zde
uvedena hodnota NULL, žádná rutina se nevyvolává a program musí ukončení
akce testovat pollingem, tj. periodickým testováním hodnoty položky InUse
příslušné struktury ECB.
Podívejme se nyní podrobněji na strukturu ECB, jejíž rozložení můžeme vysledovat z I.2. Některé položky jsme již diskutovali.
Offset | Obsah | Řazení |
0 | Link Address | offset-segment |
4 | ESR Address | offset-segmnent |
8 | In Use Flag | |
9 | Completion Code | |
10 | Socket Number | HI-LO |
12 | IPX Workspace | |
16 | Driver Workspace | |
28 | Immediate Address | |
34 | Fragment Count | LO-HI |
36 | Fragment Address 1 | |
40 | Fragment Size 1 | LO-HI |
42 | Fragment Address N | |
46 | Fragment Size N | LO-HI |
Význam jednotlivých položek ECB je následující:
Link Address - Slouží pro vnitřní potřebu IPX, (používá jako link na další ECB strukturu ve zřetězeném seznamu]
ESR Address far adresa rutiny, která se provede po ukončení události definované příslušným ECB. NULL pokud se žádná rutina nemá provádět
In Use Flag- příznak, který určuje, zda se ECB stále vede v patrnosti (nenulová hodnota) nebo je požadovaná akce již ukončena (nula) a ECB struktura může být zrušena.
Z nenulové hodnoty můžeme blíže rozpoznat činnost, která je právě prováděna
(viz Tab. I.2).
Hodnota In Use Flag | Odpovídající činnost |
FBh | vyslání nebo přijetí proběhlo, ale ECB dočasně čeká na dodatečné zpracování |
FDh | Událost byla naplánována a IPX čeká na vypršení intervalu - při použití AES |
FEh | Čeká se na příchod paketu |
FFh | Probíhá vysílání paketu |
FAh | ECB je právě zpracováván ovladačem IPX |
Completion Code - Po ukončení akce (tedy po nastavení příznaku InUse na nulu) určuje hodnota tohoto pole výsledek operace. Nulová hodnota znamená úspěch, nenulová hodnota chybový kód.
Socket - představuje číslo socketu, se kterým má být událost popsaná ECB strukturou svázaná. Socket musí být nejprve otevřen funkcí IPXOpenSocket(). IPX Workspace slouží pro vnitřní potřebu ovladače IPX. Po dobu InUse<>0 se nesmí měnit.
Driver Workspace - slouží pro vnitřní potřebu ovladače síťového adaptéru. Po dobu InUse<>0 se nesmí měnit.
Immediate Address - adresa uzlu, jehož směrem se bude vysílat nebo z jehož směru má být přijat paket. V případě lokální sítě je to přímo adresa příjemce, resp. odesílatele. Složitější situace nastává u intersítí, kde se do této položky vkládá adresa nejvhodnějšího routeru, který je nejbližší na cestě k partnerské stanici (popř. k síti v případě všesměrového vysílání na určitou síť)
Je třeba si ujasnit, že se zde v podstatě jedná o adresu použitou pro
přenos paketu rámcem linkové vrstvy. Všimněme si, že pole ImmediateAddress
sestává pouze se šesti bajtů, tedy adresy uzlu - předpokládá se totiž,
že adresa bude použita linkovou vrstvou, která zajišťuje přenos rámců pouze
v rámci jediné sítě. Pokud je adresát na společné síti s odesílatelem,
zašle se rámec přímo jemu. V opačném případě se rámec zašle na vhodný router,
ten z něj vybalí IPX paket (jenž ve své hlavičce nese informaci o adresátovi)
a na základě svých směrovacích tabulek paket opět zabalí do rámce odpovídající
síťové technologie výstupního interface a směruje jej na další směrovač
v cestě nebo na cílovou stanici, pokud je připojena ke stejné síti. Nejvhodnější
router pro směrování rámce je možné zjistit pomocí funkce IPXGetLocalTarget(),
která si k tomu účelu vyžádá informace od protokolu RIP.
Zbývající položky již pouze definují buffer, v němž je připraven paket určený k vyslání, resp. buffer, do nějž má být uložen příchozí paket. Jak můžeme předpokládat, je buffer určen adresou a délkou. V bloku ECB se buffer zadává poněkud obecněji a to tak, že máme možnost sestavit buffer z několika nezávislých paměťových bloků obecně různých délek - fragmentů. Každý fragment je v ECB reprezentován dvěma položkami - deskriptorem fragmentu, jenž vždy sestává z adresy (Fragment Address) a délky (Fragment Size) bloku. Počet fragmentů zadaných deskriptory fragmentů určuje položka Fragment Count, z jejíž hodnoty takto plyne i celková velikost ECB struktury. Paket bude sestaven z obsahu paměťových bloků v pořadí, v jakém jsou uvedeny jejich deskriptory. Je třeba pamatovat na to, že první fragment musí pojmout celou hlavičku IPX (tedy 30 bajtů], hlavička nesmí být rozdělena do více fragmentů.
Koncept fragmentace bufferu má sloužit pro omezení přesunů dat v paměti. Představme si například, že chceme poslat paket, jehož datová část má sestávat z obsahu několika objektů umístěných na různých místech v paměti. Pokud by fragmentace bufferu nebyla implementována, museli bychom nejprve sami alokovat buffer pro paket patřičné délky, do něj nakopírovat všechny požadované objekty a poté jej předat k vyslání. Jelikož můžeme předpokládat, že i samotný ovladač karty provádí kopírování dat do vnitřních bufferů, procesor by byl zbytečně zatěžován mnohonásobným zbytečným kopírovním dat mezi buffery.
Pro jednoduchost budeme v následujících příkladech pracovat vždy s jediným
fragmentem.
V předchozím textu jsme se zmínili o rutině ESR, která se může vyvolávat po ukončení akce spojené s určitým zadaným požadavkem. Je třeba si uvědomit, že rutina ESR je vyvolávána jako reakce na asynchronní událost (přerušení od adaptéru] a jako s obslužnou rutinou přerušení s ní je také třeba zacházet. V okamžiku vstupu do rutiny jsou zakázána přerušení a registrový pár ES:SI ukazuje na ECB, ke kterému se ohlašovaná událost váže. V tomto ECB jsou již doplněny položky InUseFlag=0 a CompletionCode. Registr AL indikuje, zda k vyvolání obslužné rutiny došlo v důsledku události ovladače IPX (0xFF) nebo modulu AES (0x00). Zkratkou AES je v terminologii Novellu označován tzv. asynchronní plánovač událostí (Asynchronous Event Scheduller), který slouží jako podpora pro vytváření síťových aplikací. O AES se ještě později stručně zmíníme.
Při výstupu z ESR rutiny se předpokládají zakázaná přerušení a návrat se provádí instrukcí RETF.
V souvislosti s ESR ještě poznamenejme, že všechny funkce IPX jsou reentrantní a že je lze s výjimkou funkce IPXCloseSocket()volat z ESR. V souvislosti s tím však musíme zvažovat nutnost povolení přerušení a z toho případně vyplývající požadavek na reentrantnost naší obslužné rutiny.
V následujících odstavcích si objasníme programátorské rozhraní ovladače protokolu IPX v jeho verzi pro MS-DOS. Verze pro MS-Windows či např. OS/2 jsou velmi podobné, pouze způsob volání jednotlivých funkcí je odlišný (jelikož jde o DLL)-
Služby ovladače IPX pro DOS je možné volat několika způsoby. Firma Novell doporučuje použít při vytváření nových aplikací následující způsob:
Všechny služby poskytované modulem IPX se volají přes společný vstupní bod, s tím, že konkrétní služba, jež má být vyvolána, se určí hodnotou v určeném registru. Počet a rozložení ostatních parameterů se u jednotlivých služeb liší.
Po návratu ze služby bychom vždy měli ověřit chybový kód umístěny službou do registru AL. Hodnota nula indikuje úspěch, nenulové hodnoty charakterizují příčinu neúspěchu. Konkrétní hodnoty chybových kódů, které můžeme z volání jednotlivých služeb obdržet, jsou vždy uvedeny u popisů těchto služeb.
Prvotním problémem při přístupu ke službám IPX je tedy získání adresy vstupního bodu do modulu IPX. To lze provést pomocí DOSovské multiplexační služby INT 2F: do registru AX připravíme hodnotu 7A00h (identifikace Novell IPX], voláme přerušení INT 2F a testujeme návratovou hodnotu v registru AL. Pokud není modul IPX instalován, bude v AL hodnota 0 - vložil ji tam původní obslužný program INT 2F. Jestliže je však IPX instalován, přesměruje vektor INT 2Fh na sebe a filtruje volání s hodnotou AH-7A00h. Volání s ostatními hodnotami předává původní rutině. Při detekci volání s jemu odpovídající hodnotou IPX zajistí naplnění registrového páru ES:DI adresou vstupního bodu pro volání služeb IPX a registr AL nenulovou hodnotou, která indikuje volajícímu programu, že zjištění vstupního bodu proběhlo úspěšně.
Ve starší dokumentaci se můžeme také setkat ještě s jiným způsobem volání služeb IPX a to prostřednictvím vektoru přerušení 7Ah. Rozložení parametrů v registrech je naprosto stejné jako v případě volání prostřednictvím vstupního bodu získaného výše popisovaným způsobem. Použití tohoto způsobu volání však firma Novell nedoporučuje.
Abychom získali základní představu o způsobu implementace programů pro
přenos paketů, naznačíme nejprve filosofii typických programů přijímače
a vysílače a až poté podrobně rozebereme jednotlivé použité funkce.
Řekli jsme si, že pakety jsou jednotlivým procesů doručovány podle čísla socketu obsaženého v hlavičce IPX paketu. Náš proces tedy musí nejprve u ovladače zaregistrovat všechna čísla socketu, na nichž hodlá pakety přijímat - otevřít sockety. K tomu slouží funkce OpenSocket(), jejímž parametrem je požadované číslo socketu. Programy běžně otevírají i více socketů současně, v našem ukázkovém případě však postačí jediný. Před vysláním paketu je rovněž nutné otevřít socket - jeho číslo bude umístěno do hlavičky IPX jako identifikace socketu odesílatele. Na společném socketu lze současně přijímat i vysílat, proto nám v nejjednodušším případě postačí jediný socket.
Předpokládejme nyní, že hodláme implementovat vysílač. Nejprve tedy musíme v paměťovém bufferu zkonstruovat rámec IPX, který hodláme odeslat a to včetně vyplnění některých polí hlavičky. Hlavička musí odpovídat struktuře z obr. I.1; je nezbytné vyplnit položky jednoznačně identifikující adresáta (Destination Network,Node,Socket] a typ paketu (Packet Type]. Za hlavičku připojíme uživatelská data . Informaci o celkové délce paketu pro položku Length získá IPX ze struktury ECB. Zbývající položky (zejména adresu odesílatele) doplní IPX
Nyní musíme vytvořit řídící blok události (ECB), kterým ovladači IPX sdělíme náš požadavek na vyslání paketu. V instanci struktury ECB vyplníme položku FragmentCount=1 a deskriptor prvního fragmentu se odkážeme na buffer s připraveným paketem. V ECB musíme dále vyplnit položky Socket, Immediate Address a ESR Address. Poté již můžeme předat požadavek ke zpracování IPX voláním služby IPXSendPacket().
Dále už zbývá jen počkat, až bude paket skutečně odeslán - buď se o tom dozvíme prostřednictvím ESR rutiny nebo čekáme ve smyčce, až položka InUse příslušného ECB dosáhne nulové hodnoty. Poté již zbývá jen z položky Completion Code ověřit, zda vyslání paketu proběhlo úspěšně, nebo se zde nachází kód některé chyby.
Odpovídající sekvenci můžeme nalézt i na straně přijímače. Nejprve se otevře soket, na kterém se budou očekávat příchozí pakety (funkcí IPXOpenSocket()]. Poté je třeba registrovat u IPX požadavek na příjem paketu, což opět vede k zadání tohoto požadavku prostřednictvím ECB. V ECB musíme vyplnit InUse=0xFF, číslo socketu, adresu ESR rutiny (nebo NULL pokud není požadována) a alespoň jeden deskriptor fragmentu nastavit na předem naalokovaný buffer určený pro uložení přijatého paketu. Pak již můžeme požadavek o přijetí paketu zaslat ovladači IPX prostřednictvím funkce IPXListenForPacket(). Čekání na dokončení akce se provede stejně jako v případě vysílání paketu (testování položky InUse) s tím, že musíne počítat s možností, že žádný vhodný paket nebude přijat a k nastavení InUse na nulu nikdy nedojde. Čekání na paket můžeme kdykoli zrušit voláním IPXCancelEvent().
Jestliže již nehodláme na socketu dále komunikovat, musíme jej jak na
straně vysílače, tak na straně přijímače uzavřít voláním služby IPXCloseSocket()..
int IPXOpenSocket(BYTE* socketNumber, BYTE socketType);
ustup: BX: 00h DX: požadované číslo socketu (HI-LO) AL: Příznak trvání socketu 00h - socket se uzavře při ukončení aplikace nebo po volání služby IPXCloseSocket FFh - socket se uzavře jedině explicitně voláním IPXCloseSocket(). Výstup: AL - Chybový kód DX - Přiřazený socket
Služba otevře zadaný IPX socket. Pokud použijeme namísto čísla socketu
hodnotu 0, IPX vybere vhodný volný socket, jehož číslo umístí do registru
DX. Příznakem trvání socketu můžeme řídit, zda se socket automaticky uzavře
při ukončení aplikace. Automatickému uzavření můžeme chtít předejít například
v případech některých TSR programů, které během instalace otevřou socket
a dále na něm hodlají komunikovat.
Počet současně otevřených socketů na jedné stanici lze konfigurovat,
implicitní hodnota je 20.
Možné chybové kódy:
FFh - Socket je již otevřen (můžeme ignorovat) FEh - Tabulka socketů je plná (příliš mnoho současně otevřených socketů)
void IPXCloseSocket(WORD socketNum);
Vstup: BX: 01h DX: číslo socketu - HI-LO Výstup: žádný
Uzavře zadaný otevřený socket a zruší všechny případné požadavky svázané s tímto socketem. Každý ze zrušených požadavků obdrží v položce CompletionCode struktury ECB hodnoty FCh indikující násilné zrušení požadavku, položka InUse se překlopí do nuly. ESR rušených požadavků se nevyvolává.
Tato služba se nesmí volat z těla ESR.
Před ukončením programu je nutné zabezpečit korektní uzavření všech socketů, které byly otevřeny.
void IPXSendPacket(ECB* ecb);
Vstup: BX: 03h ES:SI: Adresa ECB Výstup: žádný
Volání předá do fronty IPX požadavek na vyslání paketu, popsaný obsahem položek předávaného ECB. Řízení je okamžitě vráceno volajícímu a IPX se pokouší o vyslání paketu na pozadí. V ECB musí být vyplněny položky ESR Address, Socket, Immediate Address, Fragment Count a alespoň jeden deskriptor fragmentu, který musí obsahovat zkonstruovaný IPX paket, v jehož hlavičce budou vyplněna pole sítě, uzlu a socketu adresáta a Packet Type. IPX doplní položky Checksum, Transport Control a položky identifikující odesílatele.
Po uskutečnění pokusu o vyslání paketu IPX překlopí hodnotu položky InUse příslušného ECB do nuly a nastaví odpovídajícím způsobem kód CompletionCode:
00h- Úspěšné vyslání. Je nutné připomenout, že tento stav neznačí také úspěšné přijetí (paket mohl být zkreslen nebo ztracen na přenosové cestě)
FCh - žádost zrušena aplikací (službou IPXCancelEvent()) FDh - Chybný formát paketu (kratší než 30B, delší než 576B, nulový počet fragmentů nebo první fragment kratší než 30B) FEh - Paket nedoručitelný FFh - Paket se nepodařilo vyslat z důvodu hardwarové chyby
void IPXListenForPacket(ECB* ecb);
Vstup: BX: 04h ES:SI: Adresa ECB Výstup: AL - chybový kód Chybove kódy: FFh - Neexistuje čekající socket
Volání zařadí do fronty ovladače IPX žádost na příjem paketu, specifikovanou předaným ECB. V ECB musí být předem vyplněny položky ESR Address, Socket, Fragment Count a alespoň jeden deskriptor fragmentu.
IPX nastaví položku InUse v příslušném ECB na hodnotu FEh indikující, že se čeká na přijetí paketu. Počet žádostí o přijetí paketu na jednom socketu není omezen. V okamžiku příchodu paketu IPX vybere některý ECB popisující požadavek na příjem paketu a použije informací z něj pro umístění příchozích dat a případně vyvolání ESR rutiny. Předtím však odpovídajícím způsobem nastaví položky InUse a CompletionCode a vyplní položku ImmediateAddress adresou odesílatele, resp. posledního směrovače v cestě k naší stanici.
V případě zaslání více požadavků na příjem neni garantováno, že se ECB budou pro příchozí pakety vybírat nutně v pořadí, ve kterém byly modulu IPX předány.
CompletionCode v ECB může nabýt následujících hodnot:
00h úspěšně přijatý paket FCh Požadavek na příjem zrušen aplikací (IPXCancelEvent()) FDh Byl přijat paket, ale poskytnutý buffer nepostačuje k umístění přijatých dat FFh Socket definovaný v ECB není otevřen
void IPXGetLocalTarget(BYTE* netAddress, BYTE* immediateAddress, int* transportTime);
Vstup: BX: 02h ES:SI - ukazatel na buffer žádostí (tab. I.4) ES:DI - ukazatel na buffer odpovědi (tab I.5) Výstup: AL - chybový kód: FAh - žádná cesta k cíli nebyla nalezena CX - odhadovaná doba přenosu rámce (Transport Time), v počtu tiků
Služba vrátí k zadané IPX adrese vzdálené stanice nejbližšího prostředníka,
který je připojen s lokální stanicí na společnou sít. Je-li vzdálená stanice
připojena na stejnou síť jako lokální, vrátí se přímo její adresa, v opačném
případě adresa nejvhodnějšího směrovače pro daný směr. Služba navíc vrací
odhad doby, kterou trvá přenos 576-bytového paketu k cílové stanici. Tato
doba je měřena v počtech tiků (tj. asi 1/18 sekundy).
Offset | Obsah | Typ | Řazení |
0 | Destination Network | byte[4] | HI-LO |
4 | Destination Node | byte[6] | HI-LO |
10 | Destination Socket | byte[2] | HI-LO |
Offset | Obsah | Typ |
0 | Local Target Node Address | byte[6] |
Adresa prostředníka se použije pro vyplnění pole ImmediateAddress struktury
ECB při vysílání paketu. Služba nesmí být volána z obslužné rutiny přerušení.
void IPXGetInternetworkAddress(BYTE* netAddress);
Vstup: BX: 09h Výstup: ES:SI - ukazatel na buffer odpovědi (tab. I.6)
Služba vrátí adresu uzlu a sítě lokální stanice.
Offset | Obsah | Typ |
0 | Network Address | byte[4] |
4 | Node Address | byte[6] |
int IPXCancelEvent(ECB* ecb);
Vstup: BX: 06h ES:SI - adresa rušeného ECB Výstup: AL - chybový kód F9 - Událost nemůže být zrušena FF - ECB není v používání
Volání zruší požadavek dříve zadaný modulu IPX prostřednictvím bloku
ECB. Při úspěšném zrušení se příznak InUse v ECB překlopí do nuly a nastaví
se kód CompletionCode na hodnotu FCh. Narozdíl od korektního vyřízení požadavku
se nevolá rutina ESR.
void IPXDisconnectFromTarget(BYTE* netAddress);
Této služby se využívá pro informování specifikovaného čekajícího (listening) socketu, že již žádná další data nebudou vyslána.
Vstup: BX 0Bh ES:SI: ukazatel na buffer žádostí, tab. I.7 Výstup: žádný
Offset | Obsah | Uložení |
0 | Destination network | |
4 | Destination Node | |
10 | Destination socket | HI-LO |
Služba IPXDisconnectFromTarget() napomáhá při komunikaci v některých sítích, kde jsou použity dvoubodové spoje na fyzické úrovni. Tato informace dovoluje síťovému ovladači iniciovat rozpad spojení, pokud adaptér takovouto službu podporuje. V případě běžných lokálních sítí není její volání nutné a uvádíme ji pouze pro úplnost.
Služba nesmí být volána zevnitř rutiny ESR
Než přistoupíme k popisu několika zbývajících služeb pro podporu programování
IPX komunikace, vraťme se alespoň stručně k již zmíněnému plánovači asynchronních
událostí AES (Asynchronous Event Scheduler). Tento podpůrný prostředek
napomáhá při vytváření aplikací, které vyžadují periodické provádění nějaké
akce s tím, že vyvoláváním pravidelné činnosti nechceme zatěžovat strukturu
hlavního programu. AES nám v zásadě dovolí naplánovat interval, po kterém
má být vyvolána určená obslužná rutina přerušení a ve stanoveném čase ji
také vyvolá. Komunikace s AES se děje s využitím ECB bloků. AES je významným
pomocníkem při programování síťových aplikací, jelikož se zde často musíme
potýkat se sledováním mnoha časových limitů souvisejících například s limity
pro přijem potvrzení, nebo s dobami platností různých dat nestálého charakteru
(směrovací tabulky, cache atd). Následující služby slouží právě k podpoře
vykonávání asynchronních událostí.
unsigned IPXGetIntervalMarker(void);
Vstup: BX: 08h Výstup: AX: Interval Marker
Vrací hodnotu neustále se inkrementujícího 16-bitového čítače. Čítač se inkrementuje od tiku hodin, tedy asi každou 1/18 sekundy. Dvojím voláním a odečtením hodnot můžeme změřit dobu mezi dvěmi časově blízkými událostmi.
void IPXScheduleIPXEvent(WORD timeUnits, ECB* ecb); /P>
Vstup: BX: 05h AX: Delay Time (délka intervalu v počtu tiků) ES:SI: Adresa ECB Výstup: žádný
Služba pro naplánování události . Parametrem DelayTime je udán počet tiků hodin do uskutečnění požadované události. V okamžiku vypršení zadaného časového limitu se nastaví položka InUse předaného ECB na nulu a vyvolá se příslušná ESR, je-li definována. Po dobu dekrementování čítače časového limitu je hodnota InUse rovna FDh.
Služba může být volána i z obslužné rutiny přerušení. Je tak možné například
požádat o vyvolání určité obsluhy po zadaném čase, tam provést patřičné
testy a pokud je třeba, událost přeplánovat (resp. naplánovat znovu) na
pozdější dobu. K tomu pochopitelně můžeme využít stejného ECB, protože
po vypršení časového intervalu již není v používání modulem IPX.
void IPXRelinquishControl(void);
Netware - System Interface Technical Overview, Novell Inc., Provo, Utah
Jeger,D.: Přímá komunikace prostřednictvím IPX/SPX , LANcom 5-11/92