LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Free Pascal (4) - Sockety (dokončení)

Minule jsme si ukázali server komunikující s klienty v rámci jednoho unixového stroje, dnes si tedy ukážeme odpovidající klientský program a také se koukneme na to, jak tuto ukázku upravit, aby používala TCP/IP.

5.5.2004 08:00 | Aleš Hakl | Články autora | přečteno 10427×

Náš klient bude ještě jednodušší než server. Jednoduše se připojí k serveru a pak střídavě čte řádky ze standardního vstupu a socketu a vypisuje je do socketu respektive na standardní výstup. Pokud se na standardním vstupu objeví prázdný řádek, klient spojení uzavře a skončí.

Stejně jako v případě serveru začínáme vytvořením socketu:

s:=socket(AF_UNIX,SOCK_STREAM,PF_UNIX);
if s=-1 then begin
  halt(1);
end;

Voláme naprosto stejnou funkci socket(2), která naprosto stejně buďto vrací deskriptor socketu nebo -1 v případě chyby.

Nyní vytvoříme spojení:

if not connect(s,fileName,sin,sout) then halt(2);

Funkce connect(2) vytvoří proudové spojení k jinému programu resp. počítači (kdo by to byl řekl, že? ^_~). Opět voláme formu specifickou pro Free Pascal, jenž přijímá jako adresu rovnou cestu ve filesystému a v posledních dvou parametrech vrací pascalské "soubory" pro náš socket.

Dále se "soubory" sin a sout naprosto běžně pracujeme a nakonec je zavřeme funkcí close.

Ukažme si, jak může vypadat použití naší jednoduché ukázky použití socketů:

$ ./unix-server &
[1] 21522
$ ./unix-client
Server: prichozi spojeni od:
Mnauu
foobar
raboof
quux
xuuq

$ ps
  PID TTY       TIME CMD
21110 pts/6 00:00:00 bash
21522 pts/6 00:00:00 unix-server
21524 pts/6 00:00:00 unix-server <defunct>
21550 pts/6 00:00:00 ps
$ killall unix-server
[1]+ Terminated ./unix-server
$

Nejprve jsem pomocí shellového operátoru &, který způsobí start procesu na pozadí, spustil server. Dále jsem spustil klienta, ten se připojil k serveru a vypsal první řádek,který od něho přišel (Mnauu). Poté jsem zadal dvě řádky (foobar a quux) a od serveru přišly odpovídající odpovědi, které klient vypsal (raboof a xuuq). Všimněte si ve výstupu příkazu ps procesu s číslem 21524, jedná se o proces zombie, o němž jsme mluvili ve druhém dílu. Vzniká tak, že proces, který obsluhoval klienta, sice skončil, ale jeho rodičovský proces(21522) si nevyzvedl jeho návratovou hodnotu.


Protokol TCP/IP se po stránce obsluhy socketů příliš neliší od Unix Domain Sockets, jediným rozdílem je, že musíme řešit převod adres a čísel portů do tzv. síťového pořadí bytů (tj. big-endian, zatímco procesory x86 používají little-endian). Také je nanejvýše vhodné umožnit uživateli zadávat adresy jako jména počítačů a nikoli jejich číselné adresy. Oba tyto problémy řeší jednotka inet.

Tato jednotka obaluje většinu funkcí specifických pro sockety v doméně AF_INET. Tedy funkce pro převod jmen počítačů na adresy a naopak, funkce pro převod názvů služeb na čísla portů a naopak a také funkce pro převod pořadí bytů mezi tzv. hostitelským(tj. takovým, které používá cílová platforma) a výše zmíněným síťovým pořadím.

O TCP/IP a socketech v doméně INET by se dalo teoretizovat jistě ještě dlouho, ale vrhněme se na vlastní přepis pro použití TCP/IP. Provedl jsem několik úprav předchozího příkladu. Forma patche nám umožní si jednoduše ukázat změny oproti variantě s Unix Domain Sockets.

Změny proběhly logicky v obou částech našeho programu. Pro komunikaci nejdůležitější části kódu jsou ovšem víceméně duplikovány jak v serverové tak klientské části. Protože klient je jednodušší, začnu popis úprav tam:

s:=socket(AF_UNIX,SOCK_STREAM,PF_UNIX);
if paramcount<>1 then begin
  writeln('Usage: ',paramstr(0),' <address>');
  halt(4)
end;
s:=socket(AF_INET,SOCK_STREAM,0);

Na začátku programu si pro jistotu zkontrolujeme, jestli uživatel zadal právě jeden parametr a případně uživatele poučíme, že chceme jeden parametr. Poté vytvoříme socket v doméně AF_INET, což není nic jiného než IPv4, konkrétně v případě SOCK_STREAM protokol TCP.

Nyní ještě musíme zpracovar vstup od uživatele, tj. převést jméno počítače na jeho číselnou adresu. A poté vytvoříme spojení.

if not connect(s,fileName,sin,sout) then halt(2);
host.NameLookup(paramstr(1));
addr.family:=AF_INET;
addr.port:=ShortHostToNet(port);
addr.addr:=HostToNet(LongInt(host.IPAddress));
host.done;
if not connect(s,addr,sin,sout) then halt(2);

V jednotce inet je definováno několik objektů, jež obalují funkce pro převod jmen na adresy a naopak, čísel portů na názvy služeb a podobně. Zde právě vytváříme voláním konstruktoru NameLookup instanci objektu (úmyslně neříkám třídy, jedná se totiž o datový typ object) THost tak, že zadáme jméno počítače, který nás zajímá. Samozdřejmě je možno použít i IP adresu. Dále vyplníme strukturu TInetSockAddr, což je stejná struktura jako sockaddr_in v C. Zadáme tedy adresní doménu (AF_INET) a adresu a port protější strany v síťovém pořadí bytů. Poté tuto instanci opět zrušíme destruktorem done. A dále opět použití pro Free Pascal specifické varianty funkce connect(2), tentokráte pro datový typ TInetSockAddr.

A další kód klienta je naprosto identický jako v předchozí variantě, myslím, že na tom je krásně vidět o čem sockety vlastně jsou: ve skutečnosti jsme změnili dvě volání funkcí a máme fungující TCP klient. Zbytek úprav je zejména pro pohodlí uživatelů (převod jmen na adresy) a lepší přenositelnost našeho programu(převod na síťové pořadí bytů, to by totiž bylo možné implementovat aritmetickými operacemi a nebo dokonce ponechat na uživateli).

V serverové části již nebudu popisovat všechny úpravy, pouze se zaměřím na některé zajímavé:

function getName(addr :longint ):string;
var
  h : THost;
  a : longint;
begin
  a:=NetToHost(addr);
  h.AddressLookup(THostAddr(a));
  getName:=h.Name;
  h.done;
end;

Tato funkce slouží k převodu IP adresy příchozího spojení na jméno připojujícího se počítače. Jedná se vlastně o inverzi toho, co s instancí objektu THost děláme v klientské části.

addr.addr:=0;
if not bind(s,addr,sizeof(addr)) then halt(1);

Zde vyplňjeme položku addr naší vlastní IP adresou na, které chceme naslouchat klientům, speciální hodnota 0.0.0.0 (0 bez oddělení jednotlivých byte, vcelku nezávisle na jejich pořadí ^_~) znamená, že chceme použít všechny adresy rozhraní daného počítače.

Ostatní úpravy jsou většinou pouze o záměnách proměnných, a proto nepovažuji za nutné, je nějak dále rozebírat. Po upgradu na fpc 1.0.10 jsem na dvouch počítačích narazil na to, že program používající jednotku inet nešel zkompilovat a dostal jsem chybové hlášení linkeru o neexistenci proměnné h_errno. FPC 1.0.10 nainstalovaný apt-getem na debian unstable to nedělá, ale na gentoo instalované fpc z binárního balíčku to dělá. Není mě jasné co přesně toto chování způsobuje. Jednoduchým (a poněkud diskutabilním) řešením je ve zdrojovém kódu jednotky inet odstranit z definice promšnné GetDNSError část external name 'h_errno';, toto řešení ma ovšem ten důsledek, že poznáme že nastala chyba, nikoli už jaká.. Tím bych i uzavřel téma socketů a pomalu se přesuneme od obalů kolem knihovny jazyka C k programování v Pascalu.

Screenshot

Příště bych rád začal s knihovnou FCL, která ač je zatím neuplná a nedokončená, již nyní obsahuje mnoho zajímavých a užitečných tříd.

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

18.6.2018 0:43 /František Kučera
Červnový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 21. 6. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát na téma: F-Droid, aneb svobodný software do vašeho mobilu. Kromě toho budou k vidění i vývojové desky HiFive1 se svobodným/otevřeným čipem RISC-V.
Přidat komentář

23.5.2018 20:55 /Ondřej Čečák
Od pátku 25.5. proběhne na Fakultě informačních technologií ČVUT v Praze openSUSE Conference. Můžete se těšit na spostu zajímavých přednášek, workshopů a také na Release Party nového openSUSE leap 15.0. V na stejném místě proběhne v sobotu 26.5. i seminář o bezpečnosti CryptoFest.
Přidat komentář

20.5.2018 17:45 /Redakce Linuxsoft.cz
Ve čtvrtek 31. května 2018 připravuje webový magazín BusinessIT ve spolupráci s Best Online Média s.r.o. pátý ročník odborné konference Firemní informační systémy 2018. Akce proběhne v kongresovém centru Vavruška (palác Charitas), Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00 hod. dopoledne do cca 15 hod. odpoledne. Konference je zaměřena na efektivní využití firemních informačních systémů a na to, jak plně využít jejich potenciál. Podrobnější informace na webových stránkách konfrence.
Přidat komentář

14.5.2018 7:28 /František Kučera
Květnový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 17. 5. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát na téma: Audio – zvuk v GNU/Linuxu.
Přidat komentář

7.5.2018 16:20 /František Kučera
Na stránkách spolku OpenAlt vyšla fotoreportáž Pražské srazy 2017 dokumentující srazy za uplynulý rok. Květnový pražský sraz na téma audio se bude konat 17. 5. 2018 (místo a čas ještě upřesníme).
Přidat komentář

17.4.2018 0:46 /František Kučera
Dubnový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 4. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tématem tohoto srazu bude OpenStreetMap (OSM) aneb svobodné mapy.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

20.2.2018 18:48 / Ivan Majer
portal

20.2.2018 15:57 / Jan Havel
Jak využíváte služby cloudu v podnikání?

16.1.2018 1:08 / Ivan Pittner
verejna ip od o2 ubuntu

15.1.2018 17:26 / Mira Harvalik
Re: Jak udělat HTML/Javascript swiping gallery do mobilu?

30.12.2017 20:16 / Michal Knoll
odmocnina

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2018) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze