56
VILNIAUS GEDIMINO TECHNIKOS UNIVERSITETAS Dr. Andrius Ušinskas Dr. Arūnas Šaltis TINKLINIS PROGRAMAVIMAS Paskaitų medžiaga Vilnius 2010

Tinklinis programavimas

  • Upload
    thx1155

  • View
    244

  • Download
    17

Embed Size (px)

Citation preview

Page 1: Tinklinis programavimas

VILNIAUS GEDIMINO TECHNIKOS UNIVERSITETAS

Dr. Andrius Ušinskas

Dr. Arūnas Šaltis

TINKLINIS PROGRAMAVIMAS

Paskaitų medžiaga

Vilnius 2010

Page 2: Tinklinis programavimas

A. Ušinskas, A. Šaltis. Tinklinis programavimas: paskaitų medžiaga.Vilnius: 2010.

© Ušinskas, A., 2010© Šaltis, A., 2010

Page 3: Tinklinis programavimas

TURINYS

1. Įvadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52. Pradinės sąvokos . . . . . . . . . . . . . . . . . . . . . . 6

2.1. Lygmeninis tinklų modelis . . . . . . . . . . . . . . 62.1.1. OSI modelis . . . . . . . . . . . . . . . . . . . 72.1.2. Interneto modelis . . . . . . . . . . . . . . . . 102.1.3. Transporto lygmens protokolai . . . . . . . . 112.1.4. Tinko lygmens protokolai . . . . . . . . . . . 112.1.5. Kanalo lygmens protokolai . . . . . . . . . . . 12

2.2. Kompiuterių tinklas . . . . . . . . . . . . . . . . . . 122.2.1. Klasifikavimas . . . . . . . . . . . . . . . . . . 12

2.3. Tinklų tinklas . . . . . . . . . . . . . . . . . . . . . 142.4. Aparatinė tinklo įranga . . . . . . . . . . . . . . . . 14

2.4.1. Siejiklis . . . . . . . . . . . . . . . . . . . . . 142.4.2. Kartotuvas . . . . . . . . . . . . . . . . . . . 142.4.3. Šakotuvas . . . . . . . . . . . . . . . . . . . . 142.4.4. Tiltas . . . . . . . . . . . . . . . . . . . . . . 142.4.5. Perjungiklis . . . . . . . . . . . . . . . . . . . 152.4.6. Maršruto parinktuvas . . . . . . . . . . . . . 152.4.7. Sietuvas . . . . . . . . . . . . . . . . . . . . . 15

3. Pradinės žinios . . . . . . . . . . . . . . . . . . . . . . . 163.1. IP adresas . . . . . . . . . . . . . . . . . . . . . . . 163.2. Potinklis . . . . . . . . . . . . . . . . . . . . . . . . 19

4. Kliento ir serverio programavimas . . . . . . . . . . . . 214.1. Ryšio schema . . . . . . . . . . . . . . . . . . . . . 214.2. Serverio programavimas . . . . . . . . . . . . . . . 21

4.2.1. Nuoseklusis serveris . . . . . . . . . . . . . . . 254.2.2. Lygiagretusis serveris . . . . . . . . . . . . . . 254.2.3. IPv6 serveris . . . . . . . . . . . . . . . . . . 334.2.4. UDP serveris . . . . . . . . . . . . . . . . . . 34

4.3. Kliento programavimas . . . . . . . . . . . . . . . . 364.3.1. UDP klientas . . . . . . . . . . . . . . . . . . 36

4.4. Sudėtingų jungčių programavimas . . . . . . . . . . 384.4.1. Neblokuojantis serveris . . . . . . . . . . . . . 384.4.2. Neblokuojantis klientas . . . . . . . . . . . . . 424.4.3. Daugelio protokolų serveris . . . . . . . . . . 44

3

Page 4: Tinklinis programavimas

4.4.4. Transliavimas . . . . . . . . . . . . . . . . . . 47

Literatūra 50

Priedai 51

4

Page 5: Tinklinis programavimas

1. ĮVADAS

Medžiagos rengimas:

• Lygmeninis tinklų modelis – A. Šaltis ir A. Ušinskas

• IP adresas – A. Ušinskas

• Potinklis – A. Ušinskas

• Kliento ir serverio programavimas – A. Ušinskas

5

Page 6: Tinklinis programavimas

2. PRADINĖS SĄVOKOS

2.1. Lygmeninis tinklų modelis

Tinklinio programavimo uždavinys kurti taikomąsias progra-mines priemones informacijos perdavimui telekomunikaciniu tink-lu tarp jame veikiančių tinklinių mazgų. Informacijos perdavimuiiš vieno taško į kitą yra sukurta keletas architektūrų: trečios ei-lės architektūra, n-tosios eilės architektūra, išskirstytų objektų,tvirto sukabinimo ir t.t., tačiau plačiausia naudojama yra klientoserverio architektūra, pagal kurią vienas iš tinklo mazgų veikiakaip centrinis, t.y. serveris, o kitas mazgas kaip klientas. Klientastinklu siunčia užklausą serveriui, kuris ją apdoroja ir siunčia atgalatsakymą. Tad šiuo atveju atitinkamai tenka kurti dvi skirtingasprogramas. Kad klientas galėtų perduoti savo užklausą serveriui,o pastarasis atsiųsti atsakymą klientas ir serveris turi būti sujung-ti į bendrą tinklą. Tinklas gali būti įvairaus dydžio, nuo dviejųmazgų sujungimo skirtine linija iki kliento ir serverio sujungimonaudojant Internetą. Taigi informaciją perduodant tinklu yrasprendžiami ne tik pačios užklausos ar atsakymo formavimo irperdavimo uždaviniai, bet ir keletas kitų, pagalbinių uždavinių,kurių sprendimas užtikrina duomenų perdavimą tinklu. Šiuos už-davinius sprendžia ne pati taikomoji programa, o papildomomsprogramos, dažniai veikiančioms kaip dalis operacinės sistemos.Pavyzdžiui, naujai diegiama interneto naršyklė kompiuteryje ne-reikalauja specifinės tinklo sąsajos, nes visos tinklinės programosdirba su bet kuria iš tinklo sąsajų, svarbu tik kad kompiute-ris būtų prijungtas prie tinklo, kuriuo norima siųsti duomenis.Kadangi taikomoji tinklinė programa naudojasi operacinės siste-mos turimomis priemonėmis darbui tinkle, tai palengvina pačiosprogramos kūrimą. Tuo metu, kai buvo pradėtos naudoti tinkli-nės programos, skirtingų operacinių sistemų gamintojai gaminotarpusavyje nesuderinamas sistemas, o tai stabdė tinklinių prog-ramų naudojimą. Kad spręsti šią problemą buvo svarbu sukurtibendrus protokolus, kuriais ir būtų perduodama informacija. Otam reikėjo tipizuoti veiksmus, reikalingus informacijos perdavi-mui tinkle. Taip visas duomenų perdavimo procesas tinklu buvo

6

Page 7: Tinklinis programavimas

suskaldytas į atskiras posistemes lygmenis, kurie atsakingi tik užvieną ar keletą specifinių funkcijų. Tokios funkcijos yra tinklomazgų adresavimas ir kelio radimas, programų adresavimas, pa-tikimas duomenų perdavimas prastais ryšio kanalais ir daugeliskitų. Taip buvo sukurti tinklo modeliai, iš kurių šiuo metu yranaudojami vienas teoriniais OSI/ISO modelis ir vienas praktinisTCP/IP tinklo modelis. Abiejų šių modelių veikimas pagrįs-tas duomenų enkapsuliacija per vertikaliai išdėstytus lygmenis.Vartotojo programinė įranga bendrauja tik su aukščiausiu lyg-menimi, o prieš informaciją išsiunčiant fiziniu kanalu, ji nuosek-liai perduodama per visus lygmenis iki žemiausio. Kiekvienamelygmenyje yra pridedama papildoma informaciją antraštės. Kiek-viena antraštėje esanti informacija atlieka tam tikrą papildomąfunkciją. Informacija fiziniu kanalu siunčia tik pats apatinis lyg-muo, informacijai pasiekus gavėją, gauta duomenų struktūra ke-liauja iš apačios į viršų per visus lygmenis nuosekliai, apdorojantantraštes ir atiduodant aukščiau esančiam lygmeniui duomenis,be antraštės, taip viršutinis lygmuo gauna tuos pačius duomenis,kurie buvo siunčiami. Taigi vartotojo taikomoji programa buvoatsakinga tik už kliento serverio protokolo palaikymą, o visi kitiuždaviniai buvo sprendžiami žemesniuose lygmenys.

2.1.1. OSI modelis

Tai pirmas tinklo modelis, kuris stengėsi pirmiausia išspręstiskirtingų gamintojų tarpusavio suderinamumo problemą. Mo-delis buvo pradėtas kurti praeito amžiaus aštuntajame dešimt-metyje ISO tarptautinės standartų organizacijos. Šiuo metu šismodelis patvirtintas kaip ISO-7498 standartas. Šiame modely-je aprašomas septinių lygmenų tinklo modelis, kuriame lygmuoteikia paslaugas tik virš savęs esančiam lygmeniui ir kartu naudo-jasi žemiau savęs esančio lygmens paslaugomis (2.1 pav.). Kiek-vienas iš lygmenų turėjo griežtas aprašytas ir tik jų atliekamasfunkcijas. Sistemų kūrimo supaprastinimui, modelyje numatyta,tik kaimyninių lygmenų komunikavimas. Reikia pabrėžti, kadOSI/ISO modelis yra viso labo abstraktus duomenų perdavimoproceso aprašymas, o ne konkrečių standartų rinkinys. Tačiauvisos šiuo metu mūsų gyvenime naudojamos duomenų perdavi-

7

Page 8: Tinklinis programavimas

mo sistemos buvo kuriamos prisilaikant OSI modelyje suskirsty-to darbo organizavimo padalinimo. Žemiau pateiktas glaustuskiekvieno iš lygmens aprašymas. Fizinis lygmuo (FL, angl. phy-sical layer) atsakingas už individualaus bito perdavimą. Šiamelygmenyje esantys protokolai aprašo atskiro bito perdavimui rei-kalingas elektrines, mechanines ir funkcines specifikacijas. Šislygmuo apsprendžia maksimalią įmanomą duomenų perdavimospartą, įtampos, srovės reikšmes, bito kodavimą ir kitus duo-menis, kurie aprašo fizinę duomenų perdavimo liniją. Aukščiaufizinio yra kanalų lygmuo (KL, angl. data-link layer), kuris yraatsakingas už bitų grupės kadro perdavimo iš vieno tinklo maz-go kitam, artimiausiam duomenų perdavimo grandinėje, tinklomazgui, kuris nebūtinai turi būti siunčiamos informacijos gavė-ju. Šiame lygmens esminis uždavinys suformuoti kadro struktūrąir užtikrinti patikimą jo perdavimą. Kadras tai kanalų lygmensduomenų perdavimo vienetas turintis antraštę, naudingąją blokoįkrovą bei kontrolinės sumos laukus. Kanalų lygmens protokolaiaprašo kadrų formavimo procedūras, kadro antraštės formatą,

7. TPL

6. PL

5. SL

4. TrL

2. KL

1. FL

Paketai

Segmentai

Kadrai

Bitai

7. TPL

6. PL

5. SL

3. TiL

2. KL

1. FL

Duomenys

Duomenys

Duomenys

Klientas Serveris

3. TiL

4. TrL

2.1 pav. Lygmeninis tinklų modelis

8

Page 9: Tinklinis programavimas

nusako fizinę tinklinių įrenginių adresavimą, klaidų prieigos beisrauto kontrolę. Kontrolinė suma skirta klaidų aptikimui, kuriosatsiranda fiziniame ryšio kanale. Tinklo lygmuo (TL, angl. ne-twork layer), esantis virš kanalų lygmens, lyginant su kitais lyg-menimis, turi tik kelias užduotis. Esminė iš jų yra individualauspaketo pristatymas iš siuntėjo gavėjui. Lyginant su kanalų lyg-meniu, tinklo lygmuo atsakingas už visą perdavimo kelio, kurįgali sudaryti įvairus skaičius tarpinių mazgų, kurie savo ruožtuformuoja tinklą, suradimą, tuo tarpu kanalų lygmuo atsakingastik už iki artimiausio mazgo kadro perdavimą. Be kelio suradi-mo kitas sprendžiamas uždavinys yra loginis mazgų adresavimas.Kaip jau buvo minėta tinklo lygmenyje bazinis perdavimo viene-tas yra paketas. Transporto lygmuo (TrL, angl. transport layer)OSI modelyje yra atsakingas už pranešimų perdavimą tarp at-skirų procesų. Todėl šio lygmens sprendžiami uždaviniai yra šie:paslaugos taško arba tinklo programos adresavimą, srauto kont-rolę bei klaidų kontrolę visame perdavimo kelyje. Kaip jau buvominėta kanalų lygmuo taip pat atlieka klaidų kontrolę, tačiau tikiki gretimo mazgo, tačiau jei paketas dingo pačiame tarpiniameįrenginyje, pavyzdžiui dėl buferio persipildymo, kanalų lygmuotokios klaidos neištaisys. Tuo tarpu tinklinis lygmuo visiškai ne-atsakingas už klaidų kontrolę, nes ši funkcija perkelta transportolygmeniui, kuris geba aptikti perdavimo klaidas visame perdavi-mo maršrute. Tam, kad atlikti savo uždavinius transporto lyg-muo sukuria sesiją tarp siuntėjo ir gavėjo. Sesijos lygmenyje (SL,angl. session layer) esantys protokolai kuria, uždaro bei val-do sesijas tarp galutinio vartotojo taikomųjų programų, pusiauskaidriame dialoge. Sesijos lygmuo atsakingas už procesų dialo-go kontrolę bei sinchronizaciją Pateikimo lygmuo (PL, angl. pre-sentation layer) nustato duomenų kodavimo taisykles duomenųperdavimo sesijos metu. Tai gali būti informacijos kodavimo, šif-ravimo, glaudinimo algoritmai. Taikomasis lygmuo (TPL, angl.application layer), tai pats aukščiausias lygmuo, kuriame dirbavartotojo arba sisteminė programinė įranga, kuria reikia perduotiarba priimti informaciją tinklu. Šis lygmuo tiesiogiai bendraujasu vartotoju arba sistema todėl neaptarnauja jokio kito OSI lyg-mens. Pagal ISO/OSI tinklo modelį buvo sukurta ISO duomenų

9

Page 10: Tinklinis programavimas

perdavimui skirtų protokolų rinkinys, iš kurių bene žymiausiasyra NetBIOS ir SMB protokolai, kurie buvo plačiai naudojamirinkmenų mainams. Tačiau plačiau šios šeimos protokolai nebu-vo naudojami, nes didžiausią rinkos dalį populiarėjant internetuiužėmė TCP/IP protokolų rinkinys.

2.1.2. Interneto modelis

Interneto modelis1 aprašo duomenų perdavimą internetu. Taiyra supaprastintas OSI modelis, sujungiant TPL, PL ir SL į vie-ną TPL ir KL bei FL į vieną KL. TrL aprašomi TCP, UDP arbaRAW protokolai, o TiL lygmenyje – IPv4 ir IPv6 protokolai.

Riba tarp TPL ir TrL yra programinė jungtis, kuri dar va-dinama API2 sąsaja. Virš programinės jungties veikia vartotojoprocesai, o žemiau jos – operacinės sistemos procesai.

Kaip ir OSI modelyje, interneto modelyje kiekvienas lyg-muo papildo aukštesnio sluoksnio duomenis. Pavyzdžiui, prog-1Kitaip TCP/IP modelis2Angl. application programming interface

7. TPL

6. PL

5. SL

4. TrL

2. KL

1. FL

OSI modelis

3. TiL

Programinėjungtis

3. TrL

2. TiL

Interneto modelis

1. KL

4. TPL

2.2 pav. Interneto modelis

10

Page 11: Tinklinis programavimas

Duomenys

DuomenysAntraštė

Duomenys

Duomenys Poraštė

TrL

TPL

KL

TiL

Antraštė

Antraštė

2.3 pav. Duomenų srautas interneto modelyje

ramuotojui pasirinkus UDP ir IPv4 protokolus, maksimalus tai-komosios programos siunčiamų duomenų dydis yra 64 kB, UDPprotokolo antraštė yra 8 B, IPv4 protokolo antraštė 12 B. KLprotokolas ir jo kadro antraštė bei poraštė priklauso nuo to, kaipfiziškai prie interneto yra prijungtas kompiuteris. Taikomosiosprogramos programuotojas negali nustatyti kanalo lygmens pa-rametrų.

2.1.3. Transporto lygmens protokolai

UDP

Vartotojo duomenų paketų protokolas (angl. user datagramprotocol – UDP).

TCP

Transporto valdymo protokolas (angl. transport control pro-tocol – TCP)

RAW

Neapdoroti duomenys

2.1.4. Tinko lygmens protokolai

IPv4

32 bitų11

Page 12: Tinklinis programavimas

IPv6

128 bitų

2.1.5. Kanalo lygmens protokolai

2.2. Kompiuterių tinklas

Kompiuterių tinklas (angl. – computer network) yra tarpu-savyje sujungtų kompiuterių visuma.

2.2.1. Klasifikavimas

Dydis

Pagal kompiuterių tinklo dydį, skiriami tokie tinklai:

1. asmeninis tinklas (angl. personal area network – PAN ),

2. vietinis tinklas (angl. local area network – LAN ),

3. universiteto/miestelio tinklas (angl. campus area network– CAN 1),

4. didmiesčio tinklas (angl. metropolitan area network – MAN ),

5. platusis tinklas (angl. wide area network – WAN ).

6. globalusis tinklas (angl. global area network – GAN ).

Sujungimas

Pagal sujungimą:

1. šviesolaidinis (angl. optical fiber),

2. eternetinis (angl. ethernet) taiko fizines jungtis - laidus.

3. bevielis (angl. wireless),

4. namų (angl. home),1Tai nėra valdiklių tinklas (angl. controller area network – CAN )

12

Page 13: Tinklinis programavimas

5. įmonės (angl. enterprise),

6. elektros tinklo (angl. power line).

Funkcinis ryšys

Funkcinis ryšys (architektūra): klientas-serveris, lygiarangiai(angl. peer to pier)

Topologija

1. šynos tinkas (bus network),

2. žvaigždės tinkas (star network),

3. žiedo tinkas (ring network),

4. visiško junglumo tinkas (mesh network),

5. hierarchinis tinkas (hierarchical network),

Protokolus

Pagal protokolus: TCP, UDP, SCTP

Paskirtį

Pagal paskirtį:

1. valstybiniai,

2. akademiniai,

3. komerciniai,

4. kariniai.

Pavyzdžiui, JAV interneto srities pavadinimo galūnės gov,edu ir mil yra rezervuotos kaip aukščiausiojo lygio sritis (angl.top level domain – TLD); Jungtinėje Karalystėje šių galūnių ati-tikmenys yra gov.uk, ac.uk ir mod.uk.

13

Page 14: Tinklinis programavimas

2.3. Tinklų tinklas

Tinklų tinklas (angl. internetwork) gaunamas sujungus keliskompiuterinius tinklus. Pagal tokio tinklo vartotojus ir jo admi-nistratorius tinklų tinklas skirstomas į:

1. intranetą (angl. intranet)

2. ekstranetą (angl. extranet)

3. internetą (angl. internet)

Intranetas yra apribota kompiuterinių tinklų visuma, pavyz-džiui, kompiuterių tinklas įmonės viduje. Intranete teikiamospašto, žiniatinklio, bylų persiuntimo ir kitos paslaugos tik nusta-tytiems vartotojams.

Ekstranetas yra intraneto dalis, kuri yra prieinama iš iš-orės. Pavyzdžiui, banko klientams suteikiama teisė internetugauti duomenis apie klientų sąskaitas. Tokiu būdu identifikuo-tiems vartotojams intraneto paslauga pasiekiama iš interneto.

Internetas yra tinklų tinklas.

2.4. Aparatinė tinklo įranga

[1]

2.4.1. Siejiklis

Siejiklis (angl. network interface card – NIC )

2.4.2. Kartotuvas

Kartotuvas (angl. repeater) [2]

2.4.3. Šakotuvas

Šakotuvas (angl. hub)

2.4.4. Tiltas

Tiltas (angl. bridge) [2]14

Page 15: Tinklinis programavimas

2.4.5. Perjungiklis

Perjungiklis (angl. switch)

2.4.6. Maršruto parinktuvas

Maršruto parinktuvas (angl. router)

2.4.7. Sietuvas

Sietuvas (angl. gateway)Sąvokos: valdiklių tinklas (Controller Area Network) visiško

junglumo tinklas (mesh network) (backbone)[3]

15

Page 16: Tinklinis programavimas

0 1 2 3 4 7 8 15 16 23 24 31A klasė 0 TA KA

B klasė 1 0 TA KA

C klasė 1 1 0 TA KA

D klasė 1 1 1 0 DTA

E klasė 1 1 1 1 Rezervuota

3.1 pav. Interneto adresų klasės(TA – tinklo adresas, KA – kompiuterio adresas tame tinkle,

DTA – daugiaabonentinio transliavimo adresas)

3. PRADINĖS ŽINIOS

3.1. IP adresas

1981 metais buvo nutarta1, kad kiekvienam interneto kom-piuteriui (angl. – host) priskiriamas unikalus 32 bitų adresas,vadinamas internetiniu arba IP (angl. – internet protocol) adre-su. Galima įsivaizduoti, kad kompiuterio IP adresas yra telefo-no numeris. Internete tarpusavyje gali bendrauti tik IP adresusturintys ir prie tinklo prijungti kompiuteriai. 32 bitų adresas(232 = 4 294 967 296 vertės) sudarytas iš keturių 8 bitų skaičių(oktetų, angl – octet) atskirtais tašku, pavyzdžiui,193.219.149.210 = 11 000 001.11 011 011.10 010 101.00 000 0102.

Pirmieji IP adreso bitai (prefiksas) nusako tinklo klasę, priekurios yra prijungtas kompiuteris. Egzistuoja 5 interneto adresųklasės: A, B, C, D ir E. Iš 3.1. paveikslo matyti, kad IP adresas,kurio pirmasis bitas yra 0, priklauso A klasei; B klasei priklausoIP adresas, kurio pirmieji 2 bitai yra 1 ir 0; C klasei priklauso IPadresas, kurio pirmieji 3 bitai yra 1, 1 ir 0 ir t.t. [2].

IP adresas yra tinklo adreso (TA, angl. – netid) ir kompiu-terio adreso (KA, angl. – hostid) pora. TA parodo IP adresu1standartas

16

Page 17: Tinklinis programavimas

aprašomų galimų tinklų kiekį, o KA parodo IP adresu aprašomųkompiuterių kiekį. Tinklų ir kompiuterių adresų santykį apibūdi-na adresų klasė. A klasės tinklo adresui apibrėžti skiriami 7 bitai(3.1. pav.), o kompiuterio adresui tame tinkle apibrėžti – 24 bitai.B klasei tinklų kiekis didėja – jam skiriama 14 bitų, o kompiuteriųkiekis mažėja – skiriama 16 bitų. C klasei atitinkamai skiriamas21 bitas tinklų adresui ir 8 bitai kompiuterių adresui. Pavyzdžiui,jei du pirmieji IP adreso bitai yra 1 ir 0, tuomet tinklo adresą irkompiuterio adresą tame tinkle apibrėžiančių bitų riba yra tarp15-o ir 16-o IP adreso bito.

Pastaruoju metu tinklo adresas yra vadinamas tinklo prefiksu(angl. – network prefix), [4]. Tuomet A klasės tinklas žymimasprie IP adreso pridėjus sufiksą „/8“, pavyzdžiui, 127.0.0.0/8; Bklasės – pridėjus sufiksą „/16“; C klasės – pridėjus sufiksą „/24“.

A klasės tinklo (/8) IP adreso pirmasis oktetas apibūdinatinklo prefiksą (adresą). Likę trys oktetai aprašo kompiuterioadresą tame tinkle. Pavyzdžiui, IP adresas 101.102.103.104 api-brėžia prie tinklo, kurio prefiksas (adresas) yra 101, prijungtąkompiuterį, kurio adresas yra 102.103.104. Daugiausiai A klasėstinkle gali būti apibrėžti 27 −2 = 126 tinklai. Čia iš skaičiaus 128atimti du tinkle nenaudojami prefiksai: 0 ir 127. Tinklo prefiksas127 yra taikomas kompiuterio tinklinei įrangai tikrinti. Pavyz-džiui, IP adresas 127.0.0.1 rezervuotas kilpos1 (angl. – loopback)funkcijai ir jam priskirtas localhost pavadinimas. Daugiausiai Aklasės tinkle gali būti apibrėžti 224 −2 = 16 777 214 kompiuteriai.Čia taip pat yra atimami du kompiuterių adresuose nenaudojamiadresai: 0.0.0 ir 255.255.255. Visi nuliai kompiuterio adrese pa-rodo „šitą“ tinklą. Pavyzdžiui, IP adresas 101.0.0.0 negali būtipriskirtas kompiuteriui, tačiau tuo adresu nurodoma, kad nagri-nėjamas tinklas, kurio prefiksas 101. Visi vienetai (dešimtainėjesistemoje 255) kompiuterio adresui taip pat negali būti priskirti,nes toks adresas naudojamas daugiaabonentiniam transliavimui.Pavyzdžiui, kadrą siųstą IP adresu 101.255.255.255 gaus visi prietinklo, kurio prefiksas yra 101, prijungti kompiuteriai. A klasėsadresų sritis yra 231 = 2 147 483 648 adresai ir tai sudaro 50 %visų galimų IP adresų kiekio 232 = 4 294 967 296.1IPv6 atveju adresas yra ::1

17

Page 18: Tinklinis programavimas

B klasės tinklo (/16) IP adreso pirmasis ir antrasis oktetaiapibūdina tinklo prefiksą. Likę du oktetai aprašo kompiuterioadresą tame tinkle. Pavyzdžiui, IP adresas 168.102.103.104 api-brėžią prie tinklo, kurio prefiksas yra 168, prijungtą kompiuterį,kurio adresas yra 102.103.104. Daugiausiai B klasės tinkle galibūti apibrėžti 214 = 16 384 tinklai ir 216 − 2 = 65 534 kompiute-riai. B klasės adresų sritis 230 = 1 073 741 842 sudaro 25 % IPadresų visumos.

C klasės tinklo (/24) IP adreso pirmasis, antrasis ir trečia-sis oktetai apibūdina tinklo prefiksą. Likęs vienas oktetas ap-rašo kompiuterio adresą tame tinkle. Pavyzdžiui, IP adresas193.102.103.104 apibrėžią prie tinklo, kurio prefiksas yra 193,prijungtą kompiuterį, kurio adresas yra 102.103.104. Daugiau-siai C klasės tinkle gali būti apibrėžti 221 = 2 097 152 tinklai ir28−2 = 254 kompiuteriai. C klasės adresų sritis 229 = 536 870 912sudaro 12,5 % IP adresų visumos.

Adresų klasės D ir E paprastai nevartojamos. D klasė skirtadaugiaabonentiniam transliavimui (transliavimas grupiniu adre-su, angl. – multicast), o E klasė yra rezervuota eksperimentams.

3.1 lentelėje apibendrintos pagrindinės klasės ir jų charakte-ristikos.

Kompiuteriams, kuriems nereikia globalių IP adresų, priski-riami privatūs IP adresai. A klasėje privačių adresų sritis yra10.x.x.x, B klasėje – nuo 172.16.x.x iki 172.31.x.x ir C klasėje –nuo 192.168.0.x iki 192.168.255.x. Pavyzdžiui dauguma bevielioryšio stotelių ir DSL modemų naudoja adresų sritį 192.168.1.x.

3.1 lentelė. Apibendrintos pagrindinės interneto tinklo klasės

Klasė Pirmojo Tinklų Kompiuterių Adresų laukookteto ribos kiekis kiekis dalis, %

A 1-126 126 16 777 214 50B 128-191 16 384 65 534 25C 192-223 2 097 152 254 12,5

18

Page 19: Tinklinis programavimas

3.2. Potinklis

Sparčiai vystantis interneto tinklui, atsirado poreikis tiksliaupadalinti IP adresą į tinklo ir kompiuterio adresų dalis. Pavyz-džiui, jei reikia sukurti tinklą tik iš 5 kompiuterių, tačiau C klasėleidžia prijungti daug daugiau – 254 kompiuterius. Tokiu atvejunaudojama 1993 sukurtas metodas, pagrįstas adreso kauke (angl.– mask).

Adreso kaukė kaip ir IP adresas yra 32 bitų skaičius, padalin-tas į oktetus. Pritaikius loginę operaciją IR IP adresui ir kaukei,yra nustatoma tinklo adreso dalis ir kompiuterio adreso dalis.Pavyzdžiui, pradinė C klasės tinklo kaukė yra 255.255.255.0, nesC klasės tinklo prefiksas yra 24. Tačiau pakeitus tą kaukę į,pavyzdžiui 255.255.255.192, kompiuterio adresui skirta sritis darpadalinama į potinklio adresą ir kompiuterio adresą (3.2 pav.)

3.2 lentelėje parodytas C klasės (/24) IP adreso padalinimasį 4 potinklius taikant kaukę255.255.255.19210 = 11 111 111.11 111 111.11 111 111.11 000 0002.Iš paskutinio šios kaukės okteto skaičiaus dvejetainėje sistemo-je matyti, kad iš kompiuterio adreso yra paimami 2 bitai, su-kuriantys 22 = 4 potinklius. Tuomet tinklo prefiksas tampa24 + 2 = 26 bitai, o kompiuterio adresui lieka 32 − 26 = 6 bi-tai. Tokiam tinkle yra 26 = 64 adresai, iš kurių 64 − 2 = 62gali būti priskirti kompiuteriams. Pavyzdžiui, privatus IP adre-sas 192.168.1.64/26 rodo, kad tinklas, kurio adresas 192.168.1.64yra antrasis potinklis iš 4 potinklių IP adreso 192.168.1.0/24.Tokio antrojo potinklio daugiaabonentinio transliavimo adresasyra 64 + 64 − 1 = 127. Prie potinklio 192.168.1.64/26 prijungtųkompiuterių adresai gali būti nuo 192.168.1.65 iki 192.168.1.126

KATA

TA KAPA

3.2 pav. Kompiuterio adreso dalinimas į potinklio adresą irkompiuterio adresą

19

Page 20: Tinklinis programavimas

(iš viso 126 − 65 + 1 = 62 kompiuteriai). Taigi IP adresas192.168.1.64 nurodo antrąjį tinklo 192.168.1.0 potinklį, o IP ad-resas 192.168.1.65 nurodo prie to potinklio prijungtą kompiuterį.

3.2 lentelė. IP adresas 192.168.1.0/24 padalintas įpotinklius taikant kaukę 255.255.255.192

PA TA TA paskutinis DAdešimtainis oktetas dvejetainis dešimtainis

0 192.168.1.0/26 00 000 000 192.168.1.631 192.168.1.64/26 01 000 000 192.168.1.1272 192.168.1.128/26 10 000 000 192.168.1.1913 192.168.1.192/26 11 000 000 192.168.1.255

20

Page 21: Tinklinis programavimas

4. KLIENTO IR SERVERIO PROGRAMAVIMAS

4.1. Ryšio schema

4.1 paveiksle pavaizduota kliento ir serverio ryšio schema.Joje parodytas klientas yra aktyvus – jis užmezga ryšį su serve-riu (angl. active open). Tuomet serveris paprastai yra pasyvus– jis laukia, kol klientas užmegs su juo ryšį (angl. passive open).Tiek klientas, tiek serveris pirmiausia sukuria programinę jung-tį taikydami funkciją socket(), kurios vertė yra jungties aprašas.Toliau klientas mezga ryšį su serveriu taikydamas funkciją con-nect(), kurios vertė yra užmegzto ryšio aprašas. Tačiau prieš taiserveris turi susieti IP adresą ir prievadą su jungties aprašu tai-kydamas funkciją bind() ir laukti kliento kreipinio taikydamasfunkciją listen().

Užmegzto ryšio aprašo vertę serveris gauna taikydamas funk-ciją accept(), kuri atitinką funkciją connect() kliento pusėje. Poto klientas ir serveris keičiasi duomenimis, juos siųsdami funkcijasent() ir priimdami funkcija recv(). Baigęs apsikeitimą duome-nimis, klientas nutraukia jungtį su serveriu funkcija close(), oserveris nutraukia ryšį funkcija close() užmegzto ryšio aprašui irta pačia funkcija close() jungties aprašui.

Paprastai ryšys tarp kliento ir serverio užmezgamas taikantTCP arba UDP protokolus ir 32 bitų (IPv4 ) arba 128 bitų (IPv6 )adresus. TCP atveju ryšys vadinamas connection-oriented, oUDP atveju – connectionless.

Tolimesniuose poskyriuose nagrinėsime serverio ir kliento prog-ramavimo ypatumus.

4.2. Serverio programavimas

Serverio programavimą pradėsime nuo paprasto IPv4 TCPserverio, kuris užmezgęs ryšį su klientu, priima iš jo žinutę ir,tą žinutę gražinęs atgal, nutraukia ryšį. 4.2 paveiksle parodytastokio serverio pirminis tekstas parašytas C programavimo kalba.Programa kompiliuojama Linux operacijų sistemoje taikant gcckompiliatorių:

21

Page 22: Tinklinis programavimas

socket()

close()

socket()

close()

close()

recv()

send()

connect() accept()

listen()

bind()

recv()

send()

Klientas Severis

4.1 pav. Kliento ir serverio ryšio schema

$ gcc pirminis_tekstas.c -Wall -o serverisSukompiliuota serverio programa vykdoma prieš jos pavadi-

nimą pridėjus simbolius „./“:$ ./serveris

Serverio veikimą patogu patikrinti taikant universalią klientoprogramą Telnet:$ telnet localhost 50000Čia localhost atitinka tame pačiame kompiuteryje veikiančio ser-verio IP adresą 127.0.0.1, o skaičius 50 000 – prievado, kuriameserveris laukia kliento prisijungimo, numerį.

Išnagrinėkime 4.2 paveiksle parodytą pirminį tekstą. Prieva-do numeris, kuriame serveris lauks prisijungimo nurodomas SER-VER_PORT konstanta 8 teksto eilutėje. 12 eilutėje apibrėžiamiprograminės jungties listen_sd ir užmegzto ryšio accept_sd ap-rašai. 13 eilutėje apibrėžiamas simbolių buferis, į kurį bus įrašy-tas priimtas iš kliento ir jam išsiųstas pranešimas.

22

Page 23: Tinklinis programavimas

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <unistd.h>5 #include <sys/socket.h>6 #include <netinet/in.h>78 #define SERVER_PORT 500009

10 int main (void)11 {12 int listen_sd, accept_sd, d;13 char buffer[80];14 struct sockaddr_in addr;1516 /* Sukuriama programinė jungtis */17 listen_sd = socket(AF_INET, SOCK_STREAM, 0);1819 /* Nustatomi saitai su jungtimi */20 memset(&addr, 0, sizeof(addr));21 addr.sin_family = AF_INET;22 addr.sin_addr.s_addr = htonl(INADDR_ANY);23 addr.sin_port = htons(SERVER_PORT);24 bind(listen_sd,

(struct sockaddr *)&addr, sizeof(addr));2526 /* Pradedamas jungties stebėjimas */27 listen(listen_sd, 5);28 printf("Serveris pasiruoses rysiui su klientu \n");2930 /* Užmezgamas ryšys tarp serverio ir kliento */31 accept_sd = accept(listen_sd, NULL, NULL);32 printf("Klientas sekmingai prisijunge\n");3334 /* Iš kliento priimama žinutė */35 printf("Serveris laukia kliento zinutes\n");36 d = recv(accept_sd, buffer, sizeof(buffer), 0);37 printf("Is kliento priimta zinute \n");38 printf("%s", buffer);3940 /* Klientui siunčiama žinutė */41 printf("Priimta zinute grazinama klientui\n");42 send(accept_sd, buffer, d, 0);4344 /* Užbaigiamas ryšys su klientu */45 printf("Baigiamas rysys su klientu\n");46 close(accept_sd);4748 /* Užbaigiamas jungties stebėjimas */49 printf("Serveris uzbaigia darba\n");50 close(listen_sd);5152 return(0);53 }

4.2 pav. Pirminis IPv4 TCP serverio tekstas

Programinė jungtis sukuriama 17 eilutėje. Funkcijos soc-ket() argumentas AF_INET reiškia IPv4 protokolą, argumentasSOCK_STREAM – srautinę jungtį (TCP protokolas). Funkcijos

23

Page 24: Tinklinis programavimas

vertė yra jungties aprašas listen_sd.Saitai su programine jungtimi nustatomi funkcija bind() 24

eilutėje. Šios funkcijos argumentai yra programinės jungties ap-rašas listen_sd (17 eilutė) ir adreso parametrai struktūrinio kin-tamojo addr pavidalu (14 eilutė). Pastarasis sudarytas iš tokiųpagrindinių narių: sin_family, sin_addr ir sin_port. Pirmo-jo nario sin_family (21 eilutė) vertė yra AF_INET, kuri reiš-kia IPv4 protokolą. Antrasis sockaddr_in tipo kintamojo naryssin_addr taip pat yra struktūrinis kintamasis, kurio tipas yrastruct in_addr. Šio kintamojo nario s_addr (22 eilutė) vertėINADDR_ANY yra esamo serverio adresas. Paskutinis svar-bus addr kintamojo narys yra sin_port (23 eilutė), reiškian-tis prievado numerį, kuriame serveris lauks kliento prisijungimo.Nagrinėjamoje programoje prievadas nustatomas konstanta SER-VER_PORT, kuri yra apibrėžiama 8 eilutėje ir yra lygi 50 000.

22 ir 23 eilutėse funkcijos htonl() ir htons() užtikrina reikia-mą baitų eiliškumą (angl. byte order). htonl() (angl. Host TONetwork Long) pakeičia IPv4 serverio adreso 16 baitų eiliškumąiš kompiuteryje taikomo baitų eiliškumo (angl. host byte order)pavadinimu little-endian1 į internete taikomą eiliškumą pavadini-mu big-endian2, kuris dar vadinamas tinklo baitų eiliškumu (angl.network byte order). htons() (angl. Host TO Network Short) pa-keičia prievado numerio 8 baitų eiliškumą iš Little-Endian į Big-Endian eiliškumą. Pavyzdžiui, dvi raidės TP ASCII koduotėjeatitinka šešioliktainius skaičius 54 ir 50, kurie sudaro 2 baitų seką5450 interneto formatu (aukščiausias baitas adreso pradžioje) ir5054 kompiuterio formatu (žemiausias baitas adreso pradžioje).

Sukurtos ir nustatytos jungties stebėjimas vykdomas 27 eilu-tėje listen() funkcija. 31 eilutėje užmezgamas ryšys tarp serverioir kliento funkcija accept(). Jeigu klientas neužmezga ryšio suserveriu, serverio programos vykdymas sustoja 31 eilutėje. Pag-rindiniai šių funkcijų argumentai yra jungties aprašas listen_sd.accept() funkcijos vertė yra užmegzto ryšio aprašas accept_sd(31 eilutė).

Užmezgus ryšiui, serveris laukia ir priima žinutę iš kliento1Kitaip, didėjantys baitai. Vartojami Intel, AMD etc.2Kitaip, mažėjantys baitai. Vartojami Motorola, HP, Sun etc.

24

Page 25: Tinklinis programavimas

taikydamas funkciją recv() (36 eilutė). Pagrindiniai funkcijosargumentas yra užmegzto ryšio aprašas accept_sd, buferis buffer,į kurį bus patalpinta priimta žinutė, ir buferio dydis (80 baitų).Funkcijos vertė yra priimtų simbolių (baitų) kiekis d.

Po to serveris gražina klientui gautą žinutę funkcija send()(42 eilutė). Pagrindiniai funkcijos parametrai yra užmegzto ry-šio aprašas accept_sd, buferis buffer, kurio turinys bus išsiųstasklientui, ir buferio dydis d.

Galiausiai serveris baigia ryšį su klientu funkcija close() suargumentu accept_sd (46 eilutė) ir atjungia programinę jungtįtokia pačia funkcija close() su argumentu listen_sd (50 eilutė).

Serverio programa baigia darbą 52 eilutėje funkcija retur(0).Tolimesniuose poskyriuose nagrinėsime nuoseklaus ir lygia-

gretaus serverio programavimą.

4.2.1. Nuoseklusis serveris

4.3 paveiksle parodytas pirminio teksto fragmentas, įgyvendi-nantis nuoseklųjį serverį. Toks serveris suteikia galimybę klientuikreiptis ne vieną kartą. Tam jungties aprašas nustatomas daug-kartiniam naudojimui funkcija setsockopt() (20 eilutė). Svarbiau-sias jos argumentas yra programinės jungties aprašas listen_sd.

Daugkartiniam jungimuisi taikomas ciklas, kuris apima funk-cijas nuo užmegzto ryšio aprašo accept_sd sukūrimo (accept())iki jo užbaigimo (close()). Nagrinėjamos programos atveju tai yra35 eilutėje aprašytas for ciklas, užtikrinantis galimybę prisijungtiprie serverio iš eilės 3 kartus.

Uždavinys. Papildykite nuoseklaus serverio pirminį tekstą pranešimaisapie užmegzto ryšio eilės numerį serverio ir kliento pusėje.

4.2.2. Lygiagretusis serveris

Dukteriniai procesai

Lygiagretaus serverio darbą patogu kurti taip, kad kiekvie-nam klientui būtų sukurtas atskiras dukterinis procesas. 4.4 pa-

25

Page 26: Tinklinis programavimas

1 #include <stdio.h>:

10 int main (void)11 {12 int listen_sd, accept_sd, on = 1, d, i;:

1516 /* Sukuriama programinė jungtis */17 listen_sd = socket(AF_INET, SOCK_STREAM, 0);1819 /* Jungties aprašas nustatomas daugkartiniam naudojimui */20 setsockopt(listen_sd,21 SOL_SOCKET, SO_REUSEADDR,22 (char *)&on, sizeof(on));2324 /* Nustatomi saitai su jungtimi */25 memset(&addr, 0, sizeof(addr));:

3031 /* Pradedamas jungties stebėjimas */32 listen(listen_sd, 5);33 printf("Serveris pasiruoses rysiui su klientu \n");3435 for (i = 1; i <= 3; i++)36 {37 printf("Serveris laukia kliento prisijungimo \n");38 /* Užmezgamas ryšys tarp serverio ir kliento */39 accept_sd = accept(listen_sd, NULL, NULL);40 printf("Klientas sekmingai prisijunge \n");4142 /* Iš kliento priimama žinutė */43 printf("Serveris laukia kliento zinutes\n");44 d = recv(accept_sd, buffer, sizeof(buffer), 0);45 printf("Is kliento priimta zinute \n");46 printf("%s", buffer);4748 /* Klientui siunčiama žinutė */49 printf("Priimta zinute grazinama klientui\n");50 send(accept_sd, buffer, d, 0);5152 /* Užbaigiamas ryšys su klientu */53 printf("Baigiamas rysys su klientu\n");54 close(accept_sd);55 }5657 /* Užbaigiamas jungties stebėjimas */58 printf("Serveris uzbaigia darba\n");59 close(listen_sd);6061 return(0);62 }

4.3 pav. Pirminio teksto fragmentas, įgyvendinantis nuoseklųjįIPv4 TCP serverį

veiksle parodytas programos pasidalijimas į pagrindinį ir dukteri-nį procesus. Pastarojo paskirtis yra tik priimti ir siųsti duomenis.

4.5 paveiksle parodytas pirminio teksto fragmentas, įgyvendi-

26

Page 27: Tinklinis programavimas

nantis lygiagretųjį tokį serverį. Išlygiagretinimui taikoma fork()funkcija (43 eilutė). Šios funkcijos vertė yra pid_t tipo (15 ei-lutė) kintamasis cpid, kuris parodo, ar procesas yra dukterinis,ar pagrindinis. Jei cpid yra 0, tuomet procesas yra dukterinis.Priešingu atveju, nagrinėjamas procesas yra pagrindinis.

Tuomet nuo 44 eilutės programos vykdymas yra padalina-mas į pagrindinio proceso vykdymą ir dukterinio proceso vykdy-mą. Pagrindinis procesas užbaigia ryšį su klientu (67 eilutė), odukterinis procesas priima, išsiunčia ir tik tuomet užbaigia ryšį

socket()

bind()

close()

close()

exit()

recv()

send()

accept()

while

fork()

listen()

close()

procesasPagrindinis

procesasDukterinis

4.4 pav. Dukterinius procesus taikančio serverio veikimo schema

27

Page 28: Tinklinis programavimas

1 #include <stdio.h>:

10 int main (void)11 {12 int listen_sd, accept_sd, on = 1, d;13 char buffer[80];14 struct sockaddr_in addr;15 pid_t cpid;:

36 while(1)37 {38 printf("Serveris laukia kliento prisijungimo \n");39 /* Užmezgamas ryšys tarp serverio ir kliento */40 accept_sd = accept(listen_sd, NULL, NULL);41 printf("Klientas sekmingai prisijunge\n");4243 cpid = fork();44 if (cpid == 0)45 /* Dukterinis procesas */46 {47 close(listen_sd);48 /* Is kliento priimama žinutė */49 printf("Serveris laukia kliento zinutes\n");50 d = recv(accept_sd, buffer, sizeof(buffer), 0);51 printf("Is kliento priimta zinute \n");52 printf("%s", buffer);5354 /* Klientui siunčiama žinutė */55 printf("Priimta zinute grazinama klientui\n");56 send(accept_sd, buffer, d, 0);5758 /* Užbaigiamas ryšys su klientu */59 printf("Baigiamas rysys su klientu\n");60 close(accept_sd);61 exit(0);6263 }6465 /* Užbaigiamas ryšys su klientu */66 printf("Baigiamas rysys su klientu\n");67 close(accept_sd);68 }697071 return(0);72 }

4.5 pav. Pirminio teksto fragmentas, įgyvendinantis lygiagretųjįIPv4 TCP serverį taikant dukterinius procesus

su klientu ir baigia savo vykdymą (46–61 eilutės). Naujo klien-to prisijungimas užtikrinamas begaliniu ciklu while 36 eilutėje.Tuomet pagrindinis procesas užmezga ryšį ir nuo jo atskyla duk-terinis procesas, kuris, aptarnavęs klientą, baigia savo vykdymąfunkcija exit(0) 61 eilutėje.

28

Page 29: Tinklinis programavimas

Uždavinys. Taikydami getppid() ir getpid() funkcijas, papildykite ly-giagretaus serverio pirminį tekstą pranešimais apie pagrindinio ir dukteriniųprocesų identifikatorius (PPID ir PID) serverio ir kliento pusėje.

Serverio pagrindinio ir dukterinių procesų buvimą operacijų sistemojestebėkite programa ps su parinktimi -al.

29

Page 30: Tinklinis programavimas

Gijos

4.6 paveiksle parodyta gijas taikančio lygiagretaus serverioveikimo schema. Pagal ją klientą aptarnauja tik gijos funkcija.

4.7 paveiksle parodytas pirminio teksto fragmentas, įgyven-dinantis tokį lygiagretųjį serverį. Programa kompiliuojama įtrau-kiant POSIX gijų biblioteką:$ gcc pirminis_tekstas.c -Wall -o serveris -lpthread

Nagrinėjamame serveryje kiekvieną klientą aptarnauja atski-ra gija, įgyvendinta funkcija gijos_funkcija 67 eilutėje. Gija su-kuriama funkcija pthread_create, kurios pagrindiniai parametraiyra pthread_t tipo kintamasis gija_id (23 eilutė), gijos funkcija

socket()

bind()

accept()

while

listen()

pt.._create

recv()

send()

close()

pt.._exit()

Procesas Gija

4.6 pav. Gijas taikančio serverio veikimo schema

30

Page 31: Tinklinis programavimas

1 #include <stdio.h>:7 #include <pthread.h>89 #define SERVER_PORT 50000

1011 struct gijos_argumentai12 {13 int nr;14 int accept_sd;15 };1617 void *gijos_funkcija(void *argumentai);1819 int main(void)20 {21 int listen_sd, accept_sd, on = 1, gijos_nr=0;22 struct sockaddr_in addr;23 pthread_t gija_id;24 struct gijos_argumentai gija_arg;:

51 printf("Klientas sekmingai prisijunge\n");5253 /* Paruošiami gijos funkcijos argumentai */54 gija_arg.nr = gijos_nr;55 gija_arg.accept_sd = accept_sd;5657 /* Sukuriama gija*/58 pthread_create(&gija_id, NULL, gijos_funkcija,

&gija_arg);5960 gijos_nr++;:

6465 /*******************************************************/6667 void *gijos_funkcija(void *argumentai)68 {69 int d;70 int accept_sd, gijos_nr;71 char s[80], buffer[80];7273 struct gijos_argumentai *p =

(struct gijos_argumentai *)argumentai;74 gijos_nr = p->nr;75 accept_sd = p->accept_sd;7677 /* Klientui siunčiamas gijos numeris */78 sprintf(s,"As esu serverio gija Nr. %d \n",

gijos_nr);79 send(accept_sd, s, strlen(s), 0);:

94 pthread_exit(EXIT_SUCCESS);95 }

4.7 pav. Pirminio teksto fragmentas, įgyvendinantis lygiagretųjįIPv4 TCP serverį taikant gijas

gijos_funkcija (17 eilutė) ir gijos funkcijos argumentai gija_arg(58 eilutė). Gijos argumentai yra paruošiami 54 ir 55 programos

31

Page 32: Tinklinis programavimas

eilutėse. Gijos funkcijai perduodamas gijos numeris gijos_nr,kuris padidėja vienetu (60 eilutė) prisijungus naujam klientui, iružmegzto ryšio aprašas accept_sd. Šie perduodami duomenysyra struktūrinio kintamojo gija_arg (24 eilutė) nariai nr ir ac-cept_sd, kurie yra apibrėžti struktūroje gijos_argumentai (11eilutė).

Uždavinys. Taikydami mutex_lock(&lock) ir mutex_unlock(&lock)funkcijas, čia lock yra mutex_t tipo kintamasis, papildykite gijas naudo-jančio serverio pirminį tekstą pranešimais apie užmegzto ryšio eilės numerįserverio ir kliento pusėje. Aptarnavęs 5 klientus, serveris baigia darbą.

Serverio gijų buvimą operacijų sistemoje stebėkite programa ps su pa-rinktimi -eLf.

32

Page 33: Tinklinis programavimas

4.2.3. IPv6 serveris

Anksčiau IP adresas buvo skiriamas serveriams, darbo kom-piuteriams, asmeniniams kompiuteriams. 4 milijardų IP adresųtokius poreikius patenkino. Tačiau šiais laikais IP adresas ski-riamas ne tik kompiuteriams, bet ir vaizdo kameroms, automobi-liams, telefonams, reklamos švieslentėms ir kitiems su informacijasusijusiems objektams. Taigi 1981 metais sukurto 32 bitų adresųlaukas netolimoje ateityje bus nepakankamas. 1998 metais pri-statyto IPv6 unikalaus 128 bitų adreso 2128 verčių turėtų pakaktilabai ilgam laikui ne tik Žemėje.

IPv6 adresas sudarytas iš 8 šešioliktainių skaičių porų. Po-rose esančius nulius prieš skaičius galima praleisti. Verčiant IPv4adresą į IPv6, prieš IPv4 adresą prirašomas priešdėlis „::ffff:“.

Pavyzdžiui, kilpos IPv4 adreso 127.0.0.1 atitikmuo IPv6 ad-rese yra ::11 arba ::ffff:127.0.0.1 Patikrinti ar kompiuteryje veikiaIPv6 adresai, nesunku įvykdžius ping programą terminalo lange:$ ping6 ::1

Automatinis tinklo parametrų parinkimas

IPv4 aprašymui taikėme sockaddr_in struktūrą. Šiuo metuyra naudojama bendresnė struktūra addrinfo, sudaryta iš tokiųsvarbiausių narių tipų: ai_family, si_socktype ai_flags, ai_protocol,ai_addr, kuris yra sockaddr struktūra ir ai_addrlen.

Tuomet prieš sukuriant programinę jungtį ir nustatant saitussu ja, iškviečiama funkcija getaddrinfo (22 eilutė), kuri apibrėžiareikiamus jungties parametrus: tinklo adresų lauką, protokoląir serverio IP adresą (4.8 pav. 25 ir 28 eilutės). Šios funkci-jos argumentas yra prievado numeris (9 eilutė) ir addr struk-tūrinis kintamasis (15 eilutė), kurio svarbiausi nariai yra pradi-niai tinklo parametrai (19–21 eilutės). Čia vertė AF_UNSPECnurodo, kad adresų laukas bus pasirinktas automatiškai, vertėSOCK_STREAM, nurodo TCP protokolą ir vertė AI_PASSIVE,nurodo, kad serverio IP adresas bus nustatytas automatiškai.Gautas funkcijos getaddrinfo rezultatas saugojamas struktūrinia-me kintamajame servinfo (15 eilutė), kurį sudaro konkretūs nariai1Kitaip, 0000:0000:0000:0000:0000:0000:0000:0001

33

Page 34: Tinklinis programavimas

1 #include <stdio.h>:7 #include <netdb.h>89 #define SERVER_PORT "50000"

1011 int main (void)12 {13 int listen_sd, accept_sd, d;14 char buffer[80];15 struct addrinfo addr, *servinfo;1617 /* Apibrėžiami jungties parametrai */18 memset(&addr, 0, sizeof addr);19 addr.ai_family = AF_UNSPEC;20 addr.ai_socktype = SOCK_STREAM;21 addr.ai_flags = AI_PASSIVE;22 getaddrinfo(NULL, SERVER_PORT, &addr, &servinfo);2324 /* Sukuriama programine jungtis */25 listen_sd = socket(servinfo->ai_family,

servinfo->ai_socktype,servinfo->ai_protocol);

2627 /* Nustatomi saitai su jungtimi */28 bind(listen_sd, servinfo->ai_addr,

servinfo->ai_addrlen);2930 /* Pradedamas jungties stebėjimas */31 listen(listen_sd, 5);32 printf("Serveris pasiruoses rysiui su klientu \n");

4.8 pav. Pirminio teksto fragmentas įgyvendinantisIPv4/IPv6 TCP serverį

ai_family, ai_socktype, ai_protocol, ai_addr ir ai_addrlen.Taigi taikant getaddrinfo funkciją, serveris gali veikti tiek

IPv4, tiek IPv6 tinkle.

Uždavinys. Taikydami getpeername() ir gethostname() funkcijas, pa-pildykite serverio pirminį tekstą pranešimais apie prisijungusio kliento IPadresą bei serverio ir prisijungusio kliento pavadinimais (angl. hostname).

4.2.4. UDP serveris

Programuojant TCP serverį pastebėjome, klientas pirmiau-sia užmezga ryšį su serveriu, o tik paskui siunčia duomenis. Taipyra laimimas duomenų persiuntimo patikimumas. Gavėjas visa-da gaus jam adresuotą žinutę. Tačiau yra atvejų, kai „lėtas“ TCPprotokolas nėra naudingas, o prarastų duomenų apskritai nereikia

34

Page 35: Tinklinis programavimas

socket() socket()

bind()

Klientas Severis

send() recv()

close() close()

4.9 pav. Kliento ir serverio ryšio schema taikant UDP protokolą

laukti. Pavyzdžiui, telefonijos paslauga internetu siunčia realauslaiko vaizdo duomenis. Natūralu, kad tokiems duomenims siųstinereikia ryšio užmezgimo tarp kliento ir serverio ar pakartotinoduomenų perdavimo. Vaizdas perduodamas realiu laiku. Adresa-to nepasiekusi žinutė ignoruojama, nes ji greitai besikeičiančiamvaizdui turi nedaug įtakos. Toks „lengvas“ protokolas vadinamasUDP (angl. user datagram protocol). Taikant šį protokolą, tink-lu siunčiami ne segmentai, bet nedalomos duomenų porcijos. 334.9 paveiksle pavaizduota kliento ir serverio ryšio schema taikantUDP protokolą. Matome, kad klientas paprasčiau siunčia žinutęserveriui net nebūdamas garantuotas, kad serveris pasirengęs tąžinutę priimti. Tačiau jei serveris gaus žinutę, jis bus tikras, kadta žinutė buvo išsiųsta iš konkretaus kliento.

4.10 paveiksle parodytas UDP serverio pirminis tekstas. Šisnuoseklus serveris sukuria programinę jungtį (19 eilutė), nustatosaitus su jungtimi (22-27 eilutės) ir jau yra pasiruošęs priimti ži-nutę. Tokie TCP protokolo žingsniai kaip jungties stebėjimas irryšio užmezgimas yra praleidžiami. 30 eilutėje esančioje funkci-joje recvfrom kintamasis client_addr nurodo kliento IP adresą.Tokiu būdu, jei serveris priima žinutę, yra nustatomas ir parodo-mas (33-34 eilutės) )jos siuntėjas – klientas. Tačiau jei klientasišsiunčia žinutę, nustatytas serveris nebūtinai tą žinutę priima.

35

Page 36: Tinklinis programavimas

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <unistd.h>5 #include <sys/socket.h>6 #include <arpa/inet.h>78 #define SERVER_PORT 500009 #define MAXBUFLEN 80

1011 int main(void) {12 int listen_sd, n;13 socklen_t len;14 char buffer[MAXBUFLEN];15 struct sockaddr_in server_addr;16 struct sockaddr_in client_addr;1718 /* Sukuriama programine jungtis */19 listen_sd = socket(AF_INET, SOCK_DGRAM, 0);2021 /* Nustatomi saitai su jungtimi */22 memset(&server_addr, 0, sizeof (server_addr));23 server_addr.sin_family = AF_INET;24 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);25 server_addr.sin_port = htons(SERVER_PORT);26 bind(listen_sd, (struct sockaddr *) &server_addr,27 sizeof (server_addr));2829 len = sizeof (client_addr);30 n = recvfrom(listen_sd, buffer, MAXBUFLEN, 0,31 (struct sockaddr *) &client_addr, &len);32 buffer[n] = 0;33 printf("Is kliento (%s) priimta zinute ’%s’\n",34 inet_ntoa(client_addr.sin_addr), buffer);3536 /* Užbaigiamas ryšys su klientu */37 printf("Baigiamas rysys su klientu\n");38 close(listen_sd);3940 return (EXIT_SUCCESS);41 }

4.10 pav. Pirminis IPv4 UDP serverio tekstas

4.3. Kliento programavimas

4.3.1. UDP klientas

Kliento, veikiančio UDP protokolu, pirminis tekstas parody-tas 4.11 paveiksle. Šis klientas sukuria programinę jungtį (18eilutė), nustato saitus su jungtimi (21-24 eilutės) ir, išsiuntęs ži-nutę (30 eilutė), užbaigia darbą (34 eilutė). Kaip matome, toksUDP klientas neužmezga ryšio su serveriu kaip TCP klientas, otiesiai serveriui siunčia žinutę taikydamas funkciją sendto. Kli-

36

Page 37: Tinklinis programavimas

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <unistd.h>5 #include <sys/socket.h>6 #include <arpa/inet.h>78 #define SERVER_ADDR "127.0.0.1"9 #define SERVER_PORT 50000

10 #define BUFFER "Labas"1112 int main(void) {13 int send_sd;14 socklen_t len;15 struct sockaddr_in server_addr;1617 /* Sukuriama programinė jungtis */18 send_sd = socket(AF_INET, SOCK_DGRAM, 0);1920 /* Nustatomi saitai su jungtimi */21 memset(&server_addr, 0, sizeof (server_addr));22 server_addr.sin_family = AF_INET;23 server_addr.sin_port = htons(SERVER_PORT);24 inet_pton(AF_INET, SERVER_ADDR, &server_addr.sin_addr);2526 /* Į serverį siunčiama žinutė */27 printf("I serveri (%s) siunciama zinute ’%s’\n", SERVER_ADDR,28 BUFFER);29 len = sizeof (server_addr);30 sendto(send_sd, BUFFER, strlen(BUFFER), 0,31 (struct sockaddr *) &server_addr, len);3233 /* Užbaigiamas jungties darbas */34 close(send_sd);3536 return (EXIT_SUCCESS);37 }

4.11 pav. Pirminis IPv4 UDP kliento tekstas

entui nėra žinoma, ar siųsta žinutė pasiekė adresatą ar nepasiekė.

37

Page 38: Tinklinis programavimas

4.4. Sudėtingų jungčių programavimas

Ankstesniuose skyriuose buvo pristatytas elementarių jung-čių programavimas. Serveris laukdavo kliento prisijungimo, po toiš kliento priimdavo žinutę ir tą žinutę grąžindavo atgal. Klien-tas jungdavosi prie serverio, siųsdavo jam žinutę ir laukdavo josgrįžtančios atgal. Kliento ir serverio programos dirbo sinchroniš-kai. Tačiau sprendžiant aktualius tinklinio programavimo užda-vinius, susiduriama su asinchronišku kliento ir serverio bendra-vimu. Pavyzdžiui, tik klientui susijungus su serveriu, nutrūkstaryšys. Tuomet serveris lauktų kliento žinutės begalybę laiko. Ki-tas klientas taip pat lauktų, siekdamas prisijungti prie užstrigusioserverio.

Taigi anksčiau taikytas pavaizduotas kliento ir serverio su-sijungimo modelis nėra praktiškas. Įvykdęs accept() funkciją,toliau serveris vykdo recv() funkciją tol, kol klientas neįvykdyssend() funkcijos. Serverio programa sustabdyta, ji tampa pri-klausoma nuo kliento programos vykdymo.

Dėl to praktikoje taikomi sudėtingų jungčių (angl. advan-ced socket), programavimas. Tuomet su tinklo resursais dirbantiprograma valdo jungtį ir yra nuo tos jungties nepriklausoma.

4.4.1. Neblokuojantis serveris

Šiame skyrelyje aptarsime realaus IPv4 TCP serverio pirminįprogramos tekstą (4.12 ir 4.13 pav.). Tai yra sudėtingas serveris(angl. nonblocking server), kadangi jame taikomas jungties ne-blokavimo rėžimas (funkcijos fcntl() argumentas O_NONBLOCK,55 eilutė).

Serveris nustatytą laiko tarpą (konstanta TIME_OUT) tik-rina ar nebuvo gautas pranešimas iš kliento (58–65 eilutės). Jeinebuvo (66 eilutė), tuomet užbaigiamas užmegztas ryšys ir lau-kiama naujo kliento prisijungimo. Jeigu serveris gavo žinutę,tuomet joje panaikinami netekstiniai simboliai (70–74 eilutės) iržinutė pavaizduojame serverio lange (75–76 eilutės). Jeigu žinu-tės turinys yra žodis STOP, tuomet serveris baigia programosvykdymą (80–87 eilutės).

Tam, kad prie serverio galėtų nuosekliai prisijungti daugy-38

Page 39: Tinklinis programavimas

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <unistd.h>5 #include <sys/socket.h>6 #include <arpa/inet.h>7 #include <fcntl.h>8 #include <errno.h>9

10 #define SERVER_PORT 5000011 #define TIME_OUT 101213 int main(void) {14 int listen_sd, accept_sd;15 int recv_value, laukimas, on = 1, addr_len, i;16 char buffer[80];17 struct sockaddr_in addr;1819 /* Sukuriama programinė jungtis */20 listen_sd = socket(AF_INET, SOCK_STREAM, 0);2122 /* Jungties aprašas nustatomas daugkartiniam naudojimui */23 setsockopt(listen_sd,24 SOL_SOCKET, SO_REUSEADDR,25 (char *) &on, sizeof (on));2627 /* Nustatomi saitai su jungtimi */28 memset(&addr, 0, sizeof (addr));29 addr.sin_family = AF_INET;30 addr.sin_addr.s_addr = htonl(INADDR_ANY);31 addr.sin_port = htons(SERVER_PORT);32 bind(listen_sd,33 (struct sockaddr *) &addr, sizeof (addr));3435 /* Pradedamas jungties stebėjimas */36 listen(listen_sd, 5);37 printf("Serveris pasiruoses rysiui su klientu\n");3839 /* Begalinis ciklas */40 while (1) {41 printf("\nServeris laukia kliento prisijungimo\n");42 /* Užmezgamas ryšys tarp serverio ir kliento */43 accept_sd = accept(listen_sd, NULL, NULL);4445 /* Nustatomas kliento IP adresas */46 addr_len = sizeof (addr);47 getpeername(accept_sd, (struct sockaddr*) &addr,48 &addr_len);4950 printf("Klientas (%s) prisijunge. ",51 inet_ntoa(addr.sin_addr));52 printf("Rysiui skirta %d s\n", TIME_OUT);5354 /* Neblokavimo rėžimo pasirinkimas */55 fcntl(accept_sd, F_SETFL, O_NONBLOCK);56

4.12 pav. Pirminio teksto fragmentas įgyvendinantis neblokuojantįIPv4 TCP serverį (tęsinys kitame puslapyje)

39

Page 40: Tinklinis programavimas

57 /* Iš kliento priimama žinutė */58 recv_value = -1;59 laukimas = 0;60 while ((recv_value < 0) && (laukimas < TIME_OUT)) {61 recv_value = recv(accept_sd,buffer,sizeof(buffer),0);62 if (errno == EAGAIN)63 laukimas++;64 sleep(1);65 }66 if (laukimas == TIME_OUT)67 printf("Zinutes gauti is kliento nepavyko\n");68 else {69 /* Naikinami netekstiniai simboliai žinutėje */70 i = recv_value;71 while ((buffer[i] < 32) || (buffer[i] > 126)) {72 buffer[i] = 0;73 i--;74 }75 printf("Priimta %d B zinute ’%s’\n",76 recv_value, buffer);77 }7879 /* Serverio išjungimas per klientą */80 if (!strcmp(buffer, "STOP")) {81 // Užbaigiamas serverio darbas82 printf("Serveris uzbaigia rysi\n");83 close(accept_sd);84 printf("Serveris uzbaigia darba\n");85 close(listen_sd);86 return (EXIT_SUCCESS);87 }8889 /* Užbaigiamas ryšys */90 printf("Serveris uzbaigia rysi\n");91 close(accept_sd);92 }93 }

4.13 pav. Pirminio teksto fragmentas įgyvendinantis neblokuojantįIPv4 TCP serverį (tęsinys, pradžia 39 puslapyje)

bė klientų, serverio programoje taikomas begalinis ciklas ryšiuiužmegzti ir žinutei priimti (40–92 eilutės). Taigi šio sudėtingoserverio programoje apibrėžiami keli aprašai: jungties aprašaslisten_sd ir užmegzto ryšio aprašas accept_sd. 23–25 eilutėsejungties aprašas nustatomas daugkartiniam naudojimui, o 55 ei-lutėje ryšio aprašas nustatomas neblokavimo rėžimas. Tuometįvykdžius recv() funkciją (61 eilutė), yra tikrinama errno1 kinta-mojo vertė (62 eilutė). Jei ji lygi konstantai EAGAIN2, didinamakintamojo laukimas vertė ir programa laukia dar 1 s (63, 64 eilu-1GNU C bibliotekos kintamasis klaidos kodui saugoti (antraštė errno.h)2konstantų EAGAIN ir EWOULDBLOCK vertės yra vienodos

40

Page 41: Tinklinis programavimas

tės). Gavus žinutę iš kliento arba išsekus nustatytam laikotarpiui,žinutės gavimo ciklas (58–65 eilutės) baigiamas ir serveris toliauvykdo savo programą atvaizduoja gautą žinutę arba laukia naujokliento prisijungimo.

47–48 eilutėse serveris nustato prisijungusio kliento IP adre-są, kurį atvaizduoja savo ekrane (50–51 eilutės).

4.20 paveiksle parodyti serverio pranešimai, iš kurių maty-ti, kad vienas klientas (IP 192.168.0.10) atsiuntė žinutę LABAS,kitas klientas (IP 192.168.0.20) užmezgė ryšį, tačiau žinutės ne-atsiuntė, o trečias klientas, vietinis (IP 127.0.0.1) išjungė serverįatsiųsdamas žinutę STOP. Atkreipkime dėmesį, kad penkių sim-bolių žinutė LABAS siunčiama 7 baitais – prie žinutės galo telnetprograma prideda du naujos eilutės simbolius „\r“ ir „\n“, kurieatitinka Enter klavišo paspaudimą.

Serveris pasiruoses rysiui su klientu

Serveris laukia kliento prisijungimoKlientas (192.168.0.10) prisijunge. Rysiui skirta 10 sPriimta 7 B zinute ’LABAS’Serveris uzbaigia rysi

Serveris laukia kliento prisijungimoKlientas (192.168.0.20) prisijunge. Rysiui skirta 10 sZinutes gauti is kliento nepavykoServeris uzbaigia rysi

Serveris laukia kliento prisijungimoKlientas (127.0.0.1) prisijunge. Rysiui skirta 10 sPriimta 6 B zinute ’STOP’Serveris uzbaigia rysiServeris uzbaigia darba

4.14 pav. Neblokuojančio serverio pranešimai

41

Page 42: Tinklinis programavimas

4.4.2. Neblokuojantis klientas

Neblokuojantis klientas (angl. nonblocking client)

42

Page 43: Tinklinis programavimas

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <unistd.h>5 #include <sys/socket.h>6 #include <arpa/inet.h>7 #include <fcntl.h>8 #include <errno.h>9

10 #define SERVER_ADDR "127.0.0.1"11 #define SERVER_PORT 5000012 #define send_buf "Labas\n"13 #define TIME_OUT 51415 int main(void) {16 int send_sd, return_value, n;17 char recv_buf[80];18 struct sockaddr_in addr;1920 /* Sukuriama programinė jungtis */21 send_sd = socket(AF_INET, SOCK_STREAM, 0);2223 /* Neblokavimo rėžimo pasirinkimas */24 fcntl(send_sd, F_SETFL, O_NONBLOCK);2526 /* Nustatomi saitai su jungtimi */27 memset(&addr, 0, sizeof (addr));28 addr.sin_family = AF_INET;29 addr.sin_port = htons(SERVER_PORT);30 inet_aton(SERVER_ADDR, &addr.sin_addr);3132 /* Užmezgamas ryšys su serveriu */33 printf("Jungiamasi prie serverio.\n");34 return_value = -1;35 n = 0;36 while ((return_value < 0) && (n < TIME_OUT)) {37 return_value = connect(send_sd, (struct sockaddr *) &38 addr, sizeof(struct sockaddr_in));39 if (errno == ECONNREFUSED) {40 n++;41 if (n == 1)42 printf("Serveris siuo metu nepasiekiemas\n");43 if (n < TIME_OUT)44 printf("bandome jungtis dar %d s\n",45 TIME_OUT - n);46 } else if (errno != EINPROGRESS) {47 perror("Sistemos klaida");48 printf("Klientas uzbaigia darba\n");49 exit(EXIT_FAILURE);50 }51 sleep(1);52 }53 if (n == TIME_OUT) {54 printf("Prisijungti nepavyko. "55 "Klientas uzbaigia darba\n");56 exit(EXIT_FAILURE);57 }58 printf("Prisijungimas pavyko\n");59

4.15 pav. Pirminis neblokuojančio IPv4 TCP kliento tekstas(tęsinys kitame puslapyje)

43

Page 44: Tinklinis programavimas

60 /* Į serverį siunčiama žinutė */61 printf("I serveri siunciama zinute \n");62 printf("%s", send_buf);63 return_value = send(send_sd, send_buf, strlen(send_buf), 0);64 printf("Issiustos zinutes ilgis yra %d B.\n", return_value);6566 /* Iš serverio gaunama žinutė */67 return_value = -1;68 n = 0;69 while ((return_value < 0) && (n < TIME_OUT)) {70 return_value = recv(send_sd, recv_buf,71 sizeof (recv_buf), 0);7273 if (errno == EWOULDBLOCK) {74 n++;75 if (n == 1)76 printf("Is serverio zinute negauta\n");77 if (n < TIME_OUT)78 printf("duomenys laukiami dar %d s\n",79 TIME_OUT - n);80 } else {81 perror("Sistemos klaida");82 printf("Klientas uzbaigia darba\n");83 exit(EXIT_FAILURE);84 }85 sleep(1);86 }87 if (n == TIME_OUT) {88 printf("Zinutes gauti nepavyko. "89 "Klientas uzbaigia darba\n");90 exit(EXIT_FAILURE);91 }9293 printf("Is serverio gauta zinute \n");94 printf("%s", recv_buf);95 printf("Gautos zinutes ilgis yra %d B.\n", return_value);9697 /* Užbaigiamas jungties darbas */98 printf("Uzbaigiamas rysys su serveriu\n");99 close(send_sd);

100101 return (EXIT_SUCCESS);102 }103

4.16 pav. Pirminis neblokuojančio IPv4 TCP kliento tekstas(tęsinys, pradžia 43 puslapyje)

4.4.3. Daugelio protokolų serveris

Daugelio protokolų (angl. multiprotocol) serveris.

44

Page 45: Tinklinis programavimas

1 #include <stdio.h>:7 #include <time.h>89 #define SERVER_ADDR "127.0.0.1"

10 #define SERVER_PORT_TCP 500001112 #define SERVER_PORT_UDP 5000513 #define MAXBUFLEN 801415 int main(void) {16 /* TCP jungtis */17 int listen_sd, accept_sd, on = 1;18 struct sockaddr_in addr;19 /* UDP jungtis */20 int udp_sd;21 socklen_t len;22 struct sockaddr_in server_addr;23 struct sockaddr_in client_addr;24 /* Laikas */25 struct tm *local;26 time_t t;27 /* Kita */28 pid_t cpid;29 char buffer[MAXBUFLEN];30 int n;3132 printf("Serveris pasiruoses rysiui su klientu\n");33 printf("Laukiamas kliento TCP prisijungimas į %d prievadą\n",34 SERVER_PORT_TCP);35 printf("Laukiama kliento UDP žinute į %d prievadą\n\n",36 SERVER_PORT_UDP);3738 /* Sukuriamas dukterinis procesas */39 cpid = fork();4041 if (cpid) {42 /* Dukterinis procesas */4344 /* Sukuriama programinė TCP jungtis */45 listen_sd = socket(AF_INET, SOCK_STREAM, 0);46 /* TCP jungtis nustatoma daugkartiniam naudojimui */47 setsockopt(listen_sd,48 SOL_SOCKET, SO_REUSEADDR,49 (char *) &on, sizeof (on));50 /* Nustatomi saitai su TCP jungtimi */:

58 /* Pradedamas jungties stebejimas */59 listen(listen_sd, 5);

4.17 pav. Pirminio teksto fragmentas įgyvendinantisIPv4 TCP ir UDP serverį (tęsinys kitame puslapyje)

Uždavinys. Sumažinkite IPv4 TCP ir UDP serverio užimamą atmintįtaikydami gijas.

45

Page 46: Tinklinis programavimas

6061 /* TCP jungties amžinas ciklas */62 while (1) {63 /* Užmezgamas ryšys tarp serverio ir kliento */64 accept_sd = accept(listen_sd, NULL, NULL);65 /* Nustatomas kliento IP adresas */66 len = sizeof (addr);67 getpeername(accept_sd, (struct sockaddr*) &addr,68 &len);69 printf("Klientas (%s) prisijunge TCP protokolu\n",70 inet_ntoa(addr.sin_addr));7172 /* Gaunamas sistemos laikas */73 t = time(NULL);74 local = localtime(&t);75 memset(buffer, 0, MAXBUFLEN);76 sprintf(buffer, asctime(local),77 sizeof (asctime(local)));7879 /* Klientui siunčiama žinutė */80 printf("Klientui siunciamas laikas TCP protokolu\n");81 printf("%s", buffer);82 send(accept_sd, buffer, sizeof (buffer), 0);8384 /* Užbaigiamas ryšys su klietu */85 printf("Baigiamas TCP rysys su klientu\n\n");86 close(accept_sd);87 }88 }8990 /* Pagrindinis procesas */9192 /* Sukuriama programinė UDP jungtis */93 udp_sd = socket(AF_INET, SOCK_DGRAM, 0);94 /* Nustatomi saitai su UDP jungtimi */:

102 /* UDP jungties amžinas ciklas */103 while (1) {104 // Iš kliento priimama žinutė105 len = sizeof (client_addr);106 n = recvfrom(udp_sd, buffer, MAXBUFLEN, 0,107 (struct sockaddr *) &client_addr, &len);108 buffer[n] = 0;109 printf("Is kliento (%s) priimta UDP zinute ’%s’\n",110 inet_ntoa(client_addr.sin_addr), buffer);111112 /* Gaunamas sistemos laikas */

:117 /* Klientui siunčiamas laikas */118 printf("Klientui siunciamas laikas UDP protokolu\n");119 printf("%s\n", buffer);120 sendto(udp_sd, buffer, strlen(buffer), 0,121 (struct sockaddr *) &client_addr, len);122 }123 }

4.18 pav. Pirminio teksto fragmentas įgyvendinantisIPv4 TCP ir UDP serverį (tęsinys, pradžia 45 puslapyje)

46

Page 47: Tinklinis programavimas

4.4.4. Transliavimas

Pranešimo siuntimas vienu metu į visus tinkle esančius ad-resatus bendru adresu (angl. broadcast).

Transliavimas grupiniu adresu (angl. multicast) yra praneši-mo siuntimas tinklo pasirinktiems adresatams bendru adresu.

Transliavimas individualiu adresu (angl. unicast) yra pra-nešimo siuntimas pasirinktiems tinklo adresatams atskirais adre-sais.

Pranešimo siuntimas bendru adresu visiems adresatams tai-komas serverio radimui tinkle (angl. resource discovery) arbaduomenų srauto mažinimui. Pavyzdžiui, DHCP1 paslaugos klien-tas siunčia užklausą bendru adresu 255.255.255.255, nes jis darnežino savo IP adreso ir kitų tinklo parametrų. Arba oro sąlygasanalizuojanti sistema (serveris) siunčia bendrą užklausą visiemstemperatūros ir drėgmės jutikliams (klientai) vienu metu.

1angl. dynamic host configuration protocol47

Page 48: Tinklinis programavimas

:10 #define BROADCAST_ADDR "158.129.200.255"11 #define SERVER_PORT 5000012 #define MAXBUFLEN 8013 #define BUFFER "Sveiki, serveriai"14 #define TIME_OUT 51516 int main(void) {17 int mysocket, on = 1, n, laukimas;18 socklen_t len;19 struct sockaddr_in server_addr;20 char buffer[MAXBUFLEN];2122 /* Sukuriama programinė jungtis */23 mysocket = socket(AF_INET, SOCK_DGRAM, 0);2425 /* Transliavimas bendru adresu */26 setsockopt(mysocket, SOL_SOCKET, SO_BROADCAST,27 (char*) &on, sizeof (on));2829 /* Nustatomi saitai su jungtimi */:

35 /* Neblokavimo rėžimo pasirinkimas */36 fcntl(mysocket, F_SETFL, O_NONBLOCK);3738 /* Į serverius siunčiama žinutė */39 printf("Grupiniu adresu (%s) siunciama zinute ’%s’\n\n",40 BROADCAST_ADDR, BUFFER);41 len = sizeof (server_addr);42 sendto(mysocket, BUFFER, strlen(BUFFER), 0,43 (struct sockaddr *) &server_addr, len);4445 /* Iš serverių priimamos žinutės */46 while (1) {47 n = -1;48 laukimas = 0;49 while ((n < 0) && (laukimas < TIME_OUT)) {50 n = recvfrom(mysocket, buffer, MAXBUFLEN, 0,51 (struct sockaddr *) &server_addr, &len);52 if (errno == EAGAIN)53 laukimas++;54 sleep(1);55 }56 if (laukimas == TIME_OUT) {:

61 } else {62 buffer[n] = 0;63 printf("Is serverio (%s) priimta zinute ’%s’\n",64 inet_ntoa(server_addr.sin_addr), buffer);65 }66 }67 }

4.19 pav. Kliento, įgyvendinančio UDP pranešimų siuntimą bendru adresu,pirminio teksto fragmentas

48

Page 49: Tinklinis programavimas

Grupiniu adresu (192.168.0.255) siunciama zinute ’Sveiki, serveriai’

Is serverio (192.168.0.20) priimta zinute ’Labas, kliente’Is serverio (192.168.0.21) priimta zinute ’Labas, kliente’

Zinuciu priemimo laikas baigesiKlientas uzbaigia darba

4.20 pav. Bendru adresu pranešimą siunčiančio kliento žinutės

49

Page 50: Tinklinis programavimas

LITERATŪRA

[1] Radia Perlman. Interconnections: Bridges, Routers, Swi-tches, and Internetworking Protocols. Addison-Wesley Long-man Publishing Co., Inc., 2 edition, 2000.

[2] Douglas E. Comer. Internetworking with TCP/IP Principles,Protocols, and Architecture, volume 1. Prentice-Hall PTR, 4edition, 2000.

[3] Douglas E. Comer and David L. Stevens. Internetworkingwith TCP/IP: Client-Server Programming and Applications,Linux/Posix Sockets Version. Prentice Hall PTR, 2000.

[4] Understanding IP addressing – everything you ever wantedto know. White paper, 3Com Corporation, 2001.

Page 51: Tinklinis programavimas

PRIEDAI

51

Page 52: Tinklinis programavimas

E. SĄVOKŲ ŽODYNAS

big-endian – mažėjantys baitaihostid – kompiuterio adresashost – prie tinklo prijungtas kompiuterishost byte order – kompiuteryje taikomas baitų eiliškumashost name – kompiuterio pavadinimaslittle-endian – didėjantys baitailoopback – kilpamulticast – daugiaabonementinis transliavimas,

transliavimas grupiniu adresunetid – tinklo adresas, tinklo prefiksasnetwork byte order – tinkle taikomas baitų eiliškumassource – pirminis tekstas

52

Page 53: Tinklinis programavimas

F. SUTARTINIAI ŽYMENYS

53

Page 54: Tinklinis programavimas

G. SANTRUMPOS

IP – Internet ProtocolPID – Process numeric IDentifierPPID – Parent Process numeric IDentifierAF – Address Family

54

Page 55: Tinklinis programavimas

H. PAVARDŽIŲ RODYKLĖ

55

Page 56: Tinklinis programavimas

Andrius UŠINSKAS

Arūnas ŠALTIS

TINKLINIS PROGRAMAVIMAS

Paskaitų medžiaga