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++: Množina soketů

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.

Školení: PostgreSQL efektivně

Akademie Root
  • administrace PostgreSQL
  • členění souborů, struktura databáze
  • instalace a inicializace clusteru, postinstalační nastavení
  • zálohování, obnova, export a import dat

Detailní informace o kurzu...

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

Přehled názorů

Proč přesun na roota?
Honza 26. 5. 2003 07:37
└ 
Re: Proč přesun na roota?
Radim Dostál 26. 5. 2003 09:07
malo :(
NoOne 26. 5. 2003 10:35
holt někdy musíš povýšit na ten správnej server
bogart 26. 5. 2003 14:09
dobre
optik 26. 5. 2003 23:12
Supr
Michal 27. 5. 2003 08:00
Chyba!
PaJaSoft 27. 5. 2003 13:19
└ 
Re: Chyba!
Radim Dostál 27. 5. 2003 13:57
C++?
Milan PIzik 27. 5. 2003 14:29
├ 
Re: C++?
Petr Ferschmann 28. 5. 2003 17:39
└ 
Re: C++?
Radim Dostál 29. 5. 2003 09:18
select(2) superseded by poll(2)
Jan "Lace" Kratochvil 27. 5. 2003 19:42
├ 
Re: select(2) superseded by poll(2)
Radim Dostál 29. 5. 2003 09:10
└ 
Re: select(2) superseded by poll(2)
Freza 30. 5. 2003 14:24
zacatecnik
choke 6. 4. 2008 14:36
       

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