Hlavní navigace

Sokety a C/C++: volby soketů

Radim Dostál 23. 6. 2003

Dnes si ukážeme volby (options) soketů, které definují hodnoty různých parametrů soketu. K nastavování a čtení parametrů soketu slouží dvojice funkcí setsockopt a getsockopt. V "klasickém" soketovém API a ve WinSock API se s nimi pracuje v podstatě stejně, jen se nepatrně liší typem parametrů.

Práce s volbami soketů v Linuxu

  • int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); – funkce zjistí hodnotu nějaké volby soketu. Prvním parametrem je identifikátor soketu, druhým parametrem je úroveň volby. Třetím parametrem je název volby. Tyto dva parametry přesně určují atribut, jehož hodnotu se snažíme přečíst. Čtvrtým parametrem je ukazatel na blok paměti, ve kterém se po zavolání funkce bude nacházet požadovaný výsledek. Posledním parametrem je ukazatel na číslo udávající velikost alokované paměti, na kterou se odkazuje předposlední parametr. Před zavoláním funkce musí ukazovat ukazatel optval na souvislý blok alokované paměti. Velikost paměti musí být uložena v čísle, na které se odkazuje poslední ukazatel. Po zavolání funkce může blok paměti daný předposledním parametrem změnit velikost. Nová velikost alokované paměti je uložena v čísle, na které se odkazuje poslední parametr. Funkce vrací 0 v případě úspěchu. V opačném případě vrací –1.
  • int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); – funkce nastaví hodnotu nějaké volby soketu. Prvním parametrem je identifikátor soketu, druhým parametrem je úroveň volby. Třetím parametrem je název volby. Tyto dva parametry přesně určují atribut, jehož hodnotu se snažíme nastavit. Čtvrtým parametrem je ukazatel na blok paměti, ve kterém se nachází zadávaná hodnota. Posledním parametrem je velikost alokované paměti, na kterou se odkazuje předposlední parametr. Funkce vrací 0 v případě úspěchu. V opačném případě vrací –1.

Práce s volbami soketů v MS WindowsŽ

Význam parametrů funkcí ve WinSock je v podstatě stejný jako v „klasickém“ soketovém API. Jen typy parametrů se trochu liší.

  • int getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen); – funkce zjistí hodnotu nějaké volby soketu. Prvním parametrem je identifikátor soketu, druhým parametrem je úroveň volby. Třetím parametrem je název volby. Tyto dva parametry přesně určují atribut, jehož hodnotu se snažíme přečíst. Čtvrtým parametrem je ukazatel na blok paměti, ve kterém se po zavolání funkce bude nacházet požadovaný výsledek. Posledním parametrem je ukazatel na číslo udávající velikost alokované paměti, na kterou se odkazuje předposlední parametr. Před zavoláním funkce musí ukazovat ukazatel optval na souvislý blok alokované paměti. Velikost paměti musí být uložena v čísle, na které se odkazuje poslední ukazatel. Po zavolání funkce může blok paměti určený předposledním parametrem změnit velikost. Nová velikost alokované paměti je uložena v čísle, na které se odkazuje poslední parametr. Funkce vrací 0 v případě úspěchu. V opačném případě vrací SOCKET_ERROR.
  • int setsockoptSOCKET s, int level, int optname, const char* optval, int optlen); – funkce nastaví hodnotu nějaké volby soketu. Prvním parametrem je identifikátor soketu, druhým parametrem je úroveň volby. Třetím parametrem je název volby. Tyto dva parametry přesně určují atribut, jehož hodnotu se snažíme nastavit. Čtvrtým parametrem je ukazatel na blok paměti, ve kterém se nachází zadávaná hodnota. Posledním parametrem je velikost alokované paměti, na kterou se odkazuje předposlední parametr. Funkce vrací 0 v případě úspěchu. V opačném případě vrací hodnotu makra SOCKET_ERROR.

Úrovně voleb

Parametry soketu lze měnit na různých vrstvách síťového modelu. Druhým parametrem funkcí setsockopt a getsockopt určujeme, na které vrstvě se nachází vlastnost, s níž chceme pracovat. Nejčastěji budeme asi používat následující úrovně (za parametr level budeme dosazovat):

  • SOL_SOCKET – obecné vlastnosti soketu
  • SOL_TCP (ve WinSock IPPROTO_TCP) – vlastnosti související s protokolem TCP
  • SOL_IP (ve WinSock IPPROTO_IP) – vlastnosti související s IP protokolem

Názvy úrovní (stejně jako názvy voleb) jsou makra. Chceme-li pracovat s úrovní SOL_TCP, musíme vložit (include) hlavičkový soubornetinet/tcp­.h.

Příklady

Existuje mnoho voleb pro různé protokoly. My si tady jako příklad uvedeme pět voleb.

Urgentní a „normální“ data v jedné frontě

Existuje možnost, jak zajistit, aby příchozí urgentní data byla vkládána společně s daty „normálními“ do jedné fronty. S volbou se pracuje v úrovni SOL_SOCKET. Název volby je SO_OOBINLINE. Hodnota volby je typu

int. Je-li hodnota nenulová, jsou urgentní data vkládána společně s neurentnímy daty do jedné fronty. Lze je přečíst bez příznaku MSG_OOB. Je-li hodnota 0, jsou příchozí urgentní data vkládána do jiné fronty než data neurgentní. K jejich přečtení je potřeba použít příznak MSG_OOB. Protože datový typ bool reprezentuje hodnotu false jako 0 a hodnotu true jako 1, lze pracovat s typem bool místo int.

/* soc je vytvořený soket. */
bool oob;
socklen_t l = sizeof(int);
/* Zjistím, zda jsou urgentní společně s neurg. v jedné frontě. */
if (getsockopt(soc, SOL_SOCKET, SO_OOBINLINE, &oob, &l) != 0)
{
   // Problém
}
if (oob)
{
   cout << "Jsou v jedné frontě" << endl;
}
else
{
   cout << "Jsou odděleně" << endl;
}
/* Nastavím opačnou hodnotu. */
oob = !oob;
if (setsockopt(soc, SOL_SOCKET, SO_OOBINLINE, &oob, sizeof(int)) != 0)
{
  // Problém
}

Nastavení bufferu

Jako další příklad práce s vlastnostmi na úrovni SOL_SOCKET si uvedeme přečtení a nastavení velikosti přijímacího a odesílacího bufferu. Volba určující velikost přijímacího bufferu má název SO_RCVBUF. Volba určující velikost odesílacího bufferu má název SO_SNDBUF.

/* soc je vytvořený soket. */
int bufferSize = 0;
socklen_t l = sizeof(bufferSize);
/* Zjistím velikost bufferu pro odchozí data */
if (getsockopt(soc, SOL_SOCKET, SO_SNDBUF, &bufferSize, &l) != 0)
{
   // Problém
}
cout << "Velikost odchozího bufferu je " << bufferSize << endl;
bufferSize = 10000;
/* Nastavím velikost bufferu pro odchozí data. */
setsockopt(soc, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
/* Nastavím velikost bufferu pro příchozí data. */
setsockopt(soc, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));

Maximální velikost TCP segmentu

Jako příklad práce s vlastností na úrovni SOL_TCP si ukážeme přečtení maximální velikosti odchozích TCP segmentů.

/* soc je vytvořený soket. */
int sizeSeg = 0;
socklen_t l = sizeof(size);
if (getsockopt(soc, SOL_TCP, TCP_MAXSEG, &sizeSeg, &l) != 0)
{
   // Problém
}
cout << "Maximální velikost odchozího tcp segmentu je " << sizeSeg << endl;

Položka TTL v hlaviččce IP paketu – doba životnosti paketu

V hlaviččce IP datagramu existuje položka nazývaná TTL (Time To Live). Jedná se o celé číslo, které udává, kolika směrovači ještě může paket projít. Každý směrovač sníží hodnotu TTL o 1. V případě, že nová hodnota je 0, dojde k zahození paketu. Položka TTL slouží k tomu, aby v síti do nekonečna nekolovaly „zbloudilé“ pakety. Zjištění hodnoty TTL u všech IP paketů odesílaných pomocí daného soketu lze provést pomocí volby IP_TTL. Úroveň vlastnosti je SOL_IP.

/* soc je vytvořený soket. */
int ttl = 0; lenght = sizeof(ttl);
if (getsockopt(soc, SOL_IP, IP_TTL, &ttl, &lenght) != 0)
{
   // Problém
}
cout << "Doba životnosti odchozího IP paketu je " << ttl << endl;

Je zřejmé, že ne všechny volby lze použít na všechny typy soketů. Vždy je nutné dostatečně prostudovat dokumentaci k jednotlivým komunikačním protokolům. Příště se podíváme na takzvané „RAW“ sokety.

Našli jste v článku chybu?

16. 9. 2003 16:07

Jozef Behran (neregistrovaný)

Za normalnych okolnosti ked ste jednoduchy TCP server z clanku "TCP server pod Linux" skusili spustit dvakrat za sebou, pri druhom pokuse oznamil "Chyba pri pomenovani soketu". Ale po urcitom case bolo opat vsetko v poriadku a server sa spustil bez problemov. Z manualovej stranky ip(7) sa mozno docitat, ze toto cudo je normalne a ze sa to da potlacit pomocou volby SO_REUSEADDR. Parametrom tejto volby je obycajny int, ktory ak je nenulovy, sposobi potlacenie docasneho blokovania adresy priradenej…

26. 6. 2003 9:14

Radim Dostál (neregistrovaný)

Celé soketové API je možné používat v čistém C. Já ale kromě proudů a operátorů << >> také používám jednořádkové komentáře, typ bool, šablonu String a v příkladech ke stažení také někdy šablony z STL.

Protože jsou připomínky na téma C++ časté, budou se články dále jmenovat "Sokety a C/C++".



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

Přehledná titulka, průvodci, responzivita

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

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

Vitalia.cz: Jak vybrat ořechy do cukroví a kde mají levné

Jak vybrat ořechy do cukroví a kde mají levné

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

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

Rakovina oka. Jak ji poznáte?

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Vitalia.cz: Mondelez stahuje rizikovou čokoládu Milka

Mondelez stahuje rizikovou čokoládu Milka

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

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

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

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

Podnikatelům dorazí varování od BSA

120na80.cz: Jak oddálit Alzheimera?

Jak oddálit Alzheimera?

DigiZone.cz: Flix TV má set-top box s HEVC

Flix TV má set-top box s HEVC

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

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

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

DigiZone.cz: ČRa DVB-T2 ověřeno: Hisense a Sencor

ČRa DVB-T2 ověřeno: Hisense a Sencor

Podnikatel.cz: Babiš: E-shopy z EET možná vyjmeme

Babiš: E-shopy z EET možná vyjmeme

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

Vitalia.cz: Znáte „černý detox“? Ani to nezkoušejte

Znáte „černý detox“? Ani to nezkoušejte