Internet Info, s.r.o. Lupa Root Měšec Podnikatel DigiZone Slunečnice Vitalianew Bomba Navrcholu Weblogy Jagg Woko Dobrý web Computer.cz SK: MojeLinky

Hlavní navigace

Sokety a C/C++: volby soketů

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.

Školení: Návrh a používání MySQL databáze

Akademie Root
  • struktura tabulek a jejich vzájemné propojení
  • SQL příkazy pro manipulaci a definici dat
  • využití novinek MySQL 5
  • použití MySQL v jazyce PHP

Detailnější informace o kurzu...

Ohodnoťte jako ve škole: 12345
Průměrná známka 3,03

Přehled názorů

C++?
Martin Slouf 23. 6. 2003 11:31
└ 
Re: C++?
ufik 23. 6. 2003 15:48
 
└ 
Re: C++?
Jaroslav Aster 23. 6. 2003 19:57
 
 
└ 
Re: C++?
Radim Dostál 26. 6. 2003 09:14
A co SO_REUSEADDR ???
Jozef Behran 16. 9. 2003 16:07
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem