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 13157×
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.
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
|
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ů
28.11.2018 23:56 /František Kučera Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1
12.11.2018 21:28 /Redakce Linuxsoft.cz 22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář
6.11.2018 2:04 /František Kučera Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
4.10.2018 21:30 /Ondřej Čečák LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář
18.9.2018 23:30 /František Kučera Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
9.9.2018 14:15 /Redakce Linuxsoft.cz 20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business.
Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář
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ář
Více ...
Přidat zprávičku
Poslední diskuze
31.7.2023 14:13 /
Linda Graham iPhone Services
30.11.2022 9:32 /
Kyle McDermott Hosting download unavailable
13.12.2018 10:57 /
Jan Mareš Re: zavináč
2.12.2018 23:56 /
František Kučera Sraz
5.10.2018 17:12 /
Jakub Kuljovsky Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?
Více ...
|