Hlavní navigace

Sokety a C/C++: Množina soketů

Radim Dostál 26. 5. 2003

Tímto článkem a sérií dalších článků bych chtěl navázat na nedokončený seriál článků o soketech, který vycházel na serveru Builder.cz, jenž ukončil svoji činnost. Články byly určené čtenářům, kteří znají jazyk C++ (nebo alespoň C) a chtějí se naučit používat sokety a zabývaly se jednak "klasickým" soketovým API ze systému BSD, které mimo jiné používá i Linux, jednak soketovým API WinSock, které používají MS Windows.

prvních jedenácti dílech seriálu jsme se seznámili se základy práce se sokety. V článcích jsou jednoduše popsány základy pro posílání a příjem dat v operačních systémech Linux a MS WindowsŽ v takzvaném blokovacím režimu. Další díly seriálu „Sokety a C++“ začnou vycházet na ROOTovi.

Protože server root je zaměřen na operační systémy unixového typu, nebudu zde psát kapitoly věnující se operačnímu systému MS WindowsŽ (knihovně WinSock). Pouze se v každém článku okrajově zmíním, jaké jsou rozdíly mezi klasickými sokety a knihovnou WinSock.

Proč seskupovat sokety?

V dosud napsaných článcích jsem popisoval situace, kdy nějaké dva programy spolu komunikují. Programy posílají a přijímají data. Zavoláním funkce recv (nebo obdobné recvfrom) program začne čekat na příchozí data. Až po jejich příchodu se ukončí volání funkcí recv a recvfrom. Tyto funkce program zablokují. Tak, jak jsme se sokety pracovali doposud, je možné pouze v banálních ukázkových příkladech. Obvykle chceme, aby program kromě čekání na data ještě prováděl nějakou činnost. Řešením je použít neblokovací režim nebo více vláken. Ne vždy je ale takové řešení vhodné. Například chceme-li pracovat s více sokety najednou, ještě nemusíme nutně používat neblokovací režim nebo vlákna. Můžeme sokety (v blokovacím režimu) seskupit do takzvané množiny soketů a množinu nechat zpracovávat jedním vláknem. Na to se ale podíváme příště. Dnes si ukážeme, jak množinu soketů vytvořit a jak s ní pracovat.

Množina soketů

Pro práci s množinou budeme používat makra. V Linuxu jsou všechna makra, která zde použiji, definována v hlavičkovém souboru sys/types.h. V MS WindowsŽ stačí použít hlavičkový soubor windows.h. Obecně nelze říci, jak jsou makra definována (implementována). Jednotlivé implementace mohou být systém od systému jiné. Makra a funkce, které je používají, jsou navrženy tak, aby programátor nemusel znát vnitřní implementaci.

Vytvoření množiny

Makro fd_set lze použít jako název datového typu. Jedná se o typ „množina“.

  • FD_ZERO(fd_set *set); makro sloužící k vyprázdnění množiny. Parametrem makra je ukazatel na „datový typ“ množina.
  • FD_SET(int fd, fd_set *set); makro sloužící k vložení prvku do množiny. Prvním parametrem je samotný vkládaný prvek, druhým parametrem je ukazatel na „datový typ“ množina.
  • FD_CLR(int fd, fd_set *set); makro sloužící k odebrání prvku z množiny. Prvním parametrem je samotný prvek, druhým parametrem je ukazatel na „datový typ“ množina.
  • FD_ISSET(int fd, fd_set *set); makro sloužící k otestování množiny na přítomnost nějakého prvku. První parametr je prvek, o kterém chceme zjistit, zda je obsažen v množině. Druhým parametrem je ukazatel na samotnou množinu. Makro se rozbalí na výraz, který vrací 0 (false) v případě, že prvek v množině není. V opačném případě vrátí jakoukoliv nenulovou hodnotu (true) .

Psal jsem tady o množině nějakých prvků. Co jsou ale ty prvky? Podle deklarací, které jsem zde napsal, se jedná o proměnné typu int. Doopravdy se jedná o množinu celých čísel, jenomže my budeme množiny používat jako parametry funkcí (například funkce select), které nebudou očekávat jako parametr množinu jakýchkoliv čísel. Bude se jednat o platné identifikátory souborů (file descriptor) v Linuxu nebo o sokety v MS WindowsŽ. O tom si ale povíme příště.

Ještě jen zbývá podotknout, že v MS WindowsŽ jsou prvky, se kterými se pracuje, typu SOCKET, nikoliv int. Není to ale žádný velký rozdíl, protože již dříve jsem psal, že SOCKET je nové pojmenování (pomocí typedef) typu int. Některé překladače by na případnou záměnu mohly upozornit warningem. Přesný popis maker pro MS WindowsŽ

Ukázkový příklad

Uvedeme si jednoduchý příklad práce s množinou.

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
using namespace std;
int main()
{
  // Vytvoření množiny
  fd_set mySet;
  // Vyprázdnění množiny
  FD_ZERO(&mySet);
  int a = 10, b = 1000;
  // Vložím prvky do množiny
  FD_SET(a, &mySet);
  FD_SET(b, &mySet);
  // Zjistím, jestli tam doopravdy jsou
  if (FD_ISSET(a, &mySet))
  {
    cout << "A je tam" <<endl;
  }
  if (FD_ISSET(a, &mySet))
  {
    cout << "B je tam" <<endl;
  }
  if (!FD_ISSET(3, &mySet))
  {
    cout << "Trojka tam není" <<endl;
  }
  // Odeberu jeden prvek
  FD_CLR(a, &mySet);
  if (!FD_ISSET(a, &mySet))
  {
    cout << "A tam už není" <<endl;
  }
  return 0;
}

Zdrojový text je určen pro Linux. Přepsat jej pro MS WindowsŽ by neměl být problém. Stačí vyměnit hlavičkové soubory za windows.h a typ prvků z int na SOCKET.

Tímto jsme si ukázali, jak pracovat s množinou fd_set. V příštím článku si ukážeme, jak použít takovou množinu v souvislosti se sokety. Vytvoříme si množinu soketů a pomocí funkce select budeme čekat na nějakou událost (například doručení dat) na jakémkoliv soketu v množině. Tím budeme moci pracovat s více sokety v jednom vláknu. Jako příklad si ukážeme server, který bude poslouchat na více portech najednou.

Dalo by se říci, že makro fd_set lze využít, kdykoliv potřebujeme v programu datový typ „množina celých čísel“. Je to sice pravda, ale C++ nám nabízí daleko pohodlnější práci s množinou. Pomocí šablony set.

Počátek seriálu je na adresehttp://www­.builder.cz/se­rial147.html.

Našli jste v článku chybu?

20. 9. 2016 12:44

Původní seriál je dostupný na adrese: http://www.builder.cz/rubriky/c/c--/sokety-a-c--156186cz
(Dole jsou odkazy na ostatní články seriálu.)


30. 5. 2003 14:24

Freza (neregistrovaný)

btw, vedle poll(2) je tez zajimava alternativa kqueue(2):

http://people.freebsd.org/~jlemon/papers/kqueue.pdf

k dispozici je na {Free,Net}BSD.





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

EET: Totálně nezvládli metodologii projektu

DigiZone.cz: ČRo rozšiřuje DAB do Berouna

ČRo rozšiřuje DAB do Berouna

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

Přehledná titulka, průvodci, responzivita

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

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

Recenze Westworld: zavraždit a...

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

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

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

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

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

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

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

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

Sony KD-55XD8005 s Android 6.0

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

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

Podnikatelům dorazí varování od BSA

Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

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: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

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

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

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET

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

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