Itifaki na soketi tcp ip. Soketi Seva ya mwangwi ya TCP na UDP kwa kutumia kitendakazi cha kuchagua

Soketi

Soketi ni sehemu moja ya njia ya mawasiliano ya njia mbili kati ya programu mbili zinazoendeshwa kwenye mtandao. Kwa kuunganisha soketi mbili pamoja, unaweza kuhamisha data kati michakato tofauti(ya ndani au ya mbali). Utekelezaji wa tundu hutoa encapsulation ya mtandao na itifaki ya safu ya usafiri.

Soketi zilitengenezwa kwa UNIX katika Chuo Kikuu cha California, Berkeley. Katika UNIX, njia ya mawasiliano ya I/O inafuata kanuni ya kufungua/kusoma/kuandika/funga/funga. Kabla ya rasilimali kutumika, lazima ifunguliwe kwa ruhusa zinazofaa na mipangilio mingine. Mara rasilimali inapofunguliwa, data inaweza kusomwa kutoka au kuandikwa kwa. Baada ya kutumia rasilimali, mtumiaji lazima aite njia ya Funga () ili kuashiria mfumo wa uendeshaji kwamba imefanywa na rasilimali.

Je, vipengele viliongezwa lini kwenye mfumo wa uendeshaji wa UNIX? Inter-Process Communication (IPC) na ubadilishanaji wa mtandao, muundo unaojulikana wa pembejeo-pato ulikopwa. Rasilimali zote zilizofunuliwa kwa mawasiliano katika UNIX na Windows zinatambuliwa na vipini. Maelezo haya, au Hushughulikia, inaweza kuelekeza kwenye faili, kumbukumbu, au njia nyingine ya mawasiliano, lakini kwa hakika kuelekeza kwenye muundo wa data wa ndani unaotumiwa na mfumo wa uendeshaji. Tundu, kuwa rasilimali sawa, pia inawakilishwa na maelezo. Kwa hiyo, kwa soketi, maisha ya kushughulikia yanaweza kugawanywa katika awamu tatu: kufungua (kuunda) tundu, kupokea kutoka au kutuma kwenye tundu, na hatimaye kufunga tundu.

Kiolesura cha IPC cha mawasiliano kati ya michakato mbalimbali kimejengwa juu ya mbinu za I/O. Hurahisisha soketi kutuma na kupokea data. Kila lengo linatajwa na anwani ya tundu, hivyo anwani hii inaweza kutajwa katika mteja ili kuanzisha uhusiano na lengo.

Aina za soketi

Kuna aina mbili kuu za soketi - soketi za mkondo na soketi za datagram.

Soketi za mkondo

Soketi ya mtiririko ni tundu linalotegemea muunganisho linalojumuisha mtiririko wa baiti ambazo zinaweza kuelekezwa pande mbili, kumaanisha kuwa programu inaweza kutuma na kupokea data kupitia sehemu hii ya mwisho.

Soketi ya mtiririko huhakikisha urekebishaji wa makosa, hushughulikia uwasilishaji na kudumisha uwiano wa data. Inaweza kutegemewa kutoa data iliyopangwa, iliyorudiwa. Soketi ya mkondo pia inafaa kwa kuhamisha kiasi kikubwa cha data, kwa kuwa uendeshaji wa kuanzisha muunganisho tofauti kwa kila ujumbe unaotumwa unaweza kuwa marufuku kwa kiasi kidogo cha data. Soketi za mtiririko hufikia kiwango hiki cha ubora kwa kutumia itifaki Itifaki ya Udhibiti wa Usambazaji (TCP). TCP inahakikisha kwamba data inafika upande mwingine katika mlolongo sahihi na bila makosa.

Kwa aina hii ya tundu, njia huundwa kabla ya ujumbe kutumwa. Hii inahakikisha kwamba pande zote mbili zinazohusika katika mwingiliano zinakubali na kujibu. Ikiwa programu itatuma ujumbe mbili kwa mpokeaji, inahakikishiwa kuwa ujumbe utapokelewa kwa mlolongo sawa.

Hata hivyo, ujumbe wa mtu binafsi inaweza kugawanywa katika pakiti, na hakuna njia ya kuamua mipaka ya rekodi. Wakati wa kutumia TCP, itifaki hii inachukua huduma ya kuvunja data iliyopitishwa kwenye pakiti za ukubwa unaofaa, kuzituma kwenye mtandao na kuziunganisha tena kwa upande mwingine. Programu tunajua inatuma kwa nini Kiwango cha TCP idadi fulani ya ka na upande mwingine hupokea ka hizi. Kwa upande mwingine, TCP inavunja data hii kwa ukubwa unaofaa, inapokea pakiti hizi kwa upande mwingine, kutoa data kutoka kwayo, na kuzichanganya pamoja.

Mitiririko inategemea miunganisho dhahiri: soketi A huomba muunganisho kwenye soketi B, na soketi B inakubali au kukataa ombi la muunganisho.

Ikiwa data lazima ihakikishwe kuwasilishwa kwa upande mwingine au saizi ya data ni kubwa, soketi za mtiririko ni bora kuliko soketi za datagram. Kwa hivyo, ikiwa mawasiliano ya kuaminika kati ya programu mbili ni muhimu sana, chagua soketi za mkondo.

Seva ya barua pepe ni mfano wa programu ambayo lazima iwasilishe maudhui kwa mpangilio sahihi, bila kurudia au kuachwa. Soketi ya mtiririko inategemea TCP ili kuhakikisha kuwa ujumbe unawasilishwa kwenye maeneo yao.

Soketi za datagram

Soketi za Datagram wakati mwingine huitwa soketi zisizo na uhusiano, yaani, hakuna uhusiano wa wazi ulioanzishwa kati yao - ujumbe hutumwa kwenye tundu maalum na, ipasavyo, inaweza kupokea kutoka kwa tundu maalum.

Ikilinganishwa na soketi za datagram, soketi za mkondo hutoa zaidi njia ya kuaminika, lakini kwa baadhi ya programu sehemu ya juu inayohusishwa na kuanzisha muunganisho dhahiri haikubaliki (kwa mfano, seva ya siku inayotoa maingiliano ya saa kwa wateja wake). Baada ya yote, kuanzisha muunganisho wa kuaminika kwa seva huchukua muda, ambayo inaleta ucheleweshaji wa huduma na kazi ya programu ya seva inashindwa. Ili kupunguza juu, unapaswa kutumia soketi za datagram.

Utumiaji wa soketi za datagram unahitaji kwamba uhamishaji wa data kutoka kwa mteja hadi kwa seva ushughulikiwe Itifaki ya Datagram ya Mtumiaji (UDP). Katika itifaki hii, vizuizi vingine vimewekwa kwa saizi ya ujumbe, na tofauti na soketi za mkondo, ambazo zinaweza kutuma ujumbe kwa seva lengwa, soketi za datagramu hazitoi kuegemea. Ikiwa data itapotea mahali fulani kwenye mtandao, seva haitaripoti makosa.

Mbali na aina mbili zilizojadiliwa, pia kuna aina ya jumla ya soketi, ambayo inaitwa haijachakatwa au mbichi.

Soketi mbichi

Kusudi kuu la kutumia soketi mbichi ni kupitisha utaratibu ambao kompyuta inashughulikia TCP/IP. Hili linafanikiwa kwa kutoa utekelezaji maalum wa mrundikano wa TCP/IP ambao unabatilisha utaratibu uliotolewa na mrundikano wa TCP/IP kwenye kernel - pakiti hupitishwa moja kwa moja kwa programu na kwa hivyo huchakatwa kwa ufanisi zaidi kuliko wakati wa kupitia mteja. safu kuu ya itifaki.

Kwa ufafanuzi, tundu mbichi ni soketi inayokubali pakiti, hupita tabaka za TCP na UDP kwenye mkusanyiko wa TCP/IP, na kuzituma moja kwa moja kwa programu.

Wakati wa kutumia matako hayo, pakiti haipiti kupitia chujio cha TCP / IP, i.e. haijachakatwa kwa njia yoyote, na inaonekana katika hali yake mbichi. Katika hali hii, ni wajibu wa programu inayopokea kuchakata vizuri data yote na kutekeleza vitendo kama vile kung'oa vichwa na sehemu za uchanganuzi - kama vile kujumuisha rundo ndogo la TCP/IP kwenye programu.

Walakini, si mara nyingi unaweza kuhitaji programu inayohusika na soketi mbichi. Isipokuwa unaandika programu ya mfumo au programu ya kunusa ya pakiti, hutahitaji kwenda kwa undani kama huo. Soketi ghafi hutumiwa kimsingi katika uundaji wa utumizi maalum wa itifaki ya kiwango cha chini. Kwa mfano, huduma mbalimbali za TCP/IP kama vile njia ya kufuatilia, ping, au arp hutumia soketi ghafi.

Kufanya kazi na soketi mbichi kunahitaji maarifa thabiti ya itifaki za msingi za TCP/UDP/IP.

Bandari

Bandari inafafanuliwa ili kuruhusu tatizo la mwingiliano wa wakati mmoja na programu nyingi. Kimsingi, inapanua dhana ya anwani ya IP. Kompyuta inayoendesha programu nyingi kwa wakati mmoja, ikipokea pakiti kutoka kwa mtandao, inaweza kutambua mchakato unaolengwa kwa kutumia nambari ya kipekee bandari iliyoainishwa wakati wa kuanzisha muunganisho.

Soketi ina anwani ya IP ya mashine na nambari ya mlango inayotumiwa na programu ya TCP. Kwa sababu anwani ya IP ni ya kipekee kwenye Mtandao na nambari za bandari ni za kipekee kwenye mashine ya kipekee, nambari za soketi pia ni za kipekee kwenye mtandao mzima. Tabia hii inaruhusu mchakato wa kuwasiliana kwenye mtandao na mchakato mwingine kulingana na nambari ya tundu pekee.

Nambari za bandari zimehifadhiwa kwa huduma fulani - hizi ni nambari za bandari zinazojulikana, kama vile bandari 21, zinazotumiwa katika FTP. Programu yako inaweza kutumia nambari yoyote ya mlango ambayo haijahifadhiwa na bado haijatumika. Wakala Mamlaka ya Nambari Zilizopewa Mtandao (IANA) hudumisha orodha ya nambari za bandari zinazojulikana.

Kwa kawaida programu-tumizi ya seva-teja inayotumia soketi huwa na programu mbili tofauti - mteja anayeanzisha muunganisho kwa lengwa (seva) na seva inayosubiri muunganisho kutoka kwa mteja.

Kwa mfano, kwa upande wa mteja, programu lazima ijue anwani inayolengwa na nambari ya bandari. Kwa kutuma ombi la uunganisho, mteja anajaribu kuanzisha muunganisho na seva:

Ikiwa matukio yatafanikiwa, mradi seva imeanza kabla ya mteja kujaribu kuunganisha kwayo, seva inakubali muunganisho. Baada ya kutoa idhini, programu ya seva huunda tundu mpya ili kuingiliana haswa na mteja aliyeanzisha muunganisho:

Sasa mteja na seva wanaweza kuingiliana na kila mmoja, kusoma ujumbe kutoka kwa tundu lao na, ipasavyo, kuandika ujumbe.

Kufanya kazi na soketi katika .NET

Usaidizi wa soketi katika .NET hutolewa na madarasa katika nafasi ya majina System.Net.Soketi- hebu tuanze na maelezo yao mafupi.

Madarasa ya kufanya kazi na soketi
Darasa Maelezo
Chaguo la Multicast Darasa la MulticastOption huweka thamani ya anwani ya IP ya kujiunga au kuondoka kwenye kikundi cha IP.
NetworkStream Darasa la NetworkStream hutekeleza darasa la msingi la mtiririko ambalo data hutumwa na kupokelewa. Hiki ni kifupisho cha hali ya juu ambacho kinawakilisha muunganisho kwenye chaneli ya mawasiliano ya TCP/IP.
TcpClient Darasa la TcpClient hujengwa kwenye darasa la Soketi ili kutoa huduma za kiwango cha juu za TCP. TcpClient hutoa mbinu kadhaa za kutuma na kupokea data kupitia mtandao.
TcpListener Darasa hili pia hujengwa juu ya darasa la Soketi la kiwango cha chini. Kusudi lake kuu ni maombi ya seva. Inasikiliza maombi ya muunganisho yanayoingia kutoka kwa wateja na kuarifu utumizi wa miunganisho yoyote.
UdpClient UDP ni itifaki isiyo na muunganisho, kwa hivyo utendakazi tofauti unahitajika ili kutekeleza huduma ya UDP katika .NET.
SocketException Ubaguzi huu hutupwa wakati hitilafu inatokea kwenye tundu.
Soketi Darasa la mwisho katika nafasi ya majina ya System.Net.Sockets ni darasa la Soketi lenyewe. Inatoa utendaji wa msingi wa programu ya tundu.

Darasa la soketi

Darasa la Soketi linacheza jukumu muhimu katika programu ya mtandao, kuhakikisha utendakazi wa mteja na seva. Kimsingi, simu kwa mbinu katika darasa hili hufanya ukaguzi muhimu unaohusiana na usalama, ikiwa ni pamoja na kuangalia ruhusa za usalama, na kisha hutumwa kwa wenzao wa mbinu katika API ya Soketi za Windows.

Kabla ya kugeukia mfano wa kutumia darasa la Soketi, wacha tuangalie mali na njia muhimu za darasa hili:

Sifa na njia za darasa la Soketi
Mali au mbinu Maelezo
AnwaniFamilia Hutoa familia ya anwani ya tundu - thamani kutoka kwa hesabu ya Socket.AddressFamily.
Inapatikana Hurejesha kiasi cha data kinachopatikana kwa kusoma.
Kuzuia Hupata au kuweka thamani inayoonyesha kama soketi iko katika hali ya kuzuia.
Imeunganishwa Huleta thamani inayoonyesha kama soketi imeunganishwa kwa seva pangishi ya mbali.
LocalEndPoint Inatoa mwisho wa ndani.
Aina ya Itifaki Inatoa aina ya itifaki ya tundu.
RemoteEndPoint Hutoa mwisho wa tundu la mbali.
Aina ya Soketi Inatoa aina ya tundu.
Kubali () Huunda soketi mpya kushughulikia ombi la muunganisho linaloingia.
Bind() Hufunga soketi kwenye mwisho wa karibu ili kusikiliza maombi ya muunganisho yanayoingia.
Funga() Hulazimisha tundu kufunga.
Unganisha () Huanzisha muunganisho na seva pangishi ya mbali.
GetSocketOption() Hurejesha thamani ya SocketOption.
IOControl() Inaweka njia za uendeshaji za kiwango cha chini kwa tundu. Njia hii hutoa ufikiaji wa kiwango cha chini kwa darasa la msingi la Soketi.
Sikiliza() Inaweka tundu katika hali ya kusikiliza (kusubiri). Njia hii ni ya programu tumizi za seva.
Pokea() Hupokea data kutoka kwa soketi iliyounganishwa.
Kura () Huamua hali ya tundu.
Chagua() Hukagua hali ya soketi moja au zaidi.
Tuma () Hutuma data kwenye soketi iliyounganishwa.
SetSocketOption() Inaweka chaguo la tundu.
Kuzimisha() Inalemaza kutuma na kupokea shughuli kwenye tundu.

35 majibu

Muhtasari

Soketi ya TCP ni mfano wa mwisho, iliyofafanuliwa na anwani ya IP na mlango katika muktadha wa muunganisho maalum wa TCP au hali ya kusikiliza.

Mlango ndio kitambulisho cha uboreshaji, ambayo hubainisha mwisho wa huduma (kinyume na mwisho wa mfano wa huduma au kitambulisho cha kipindi chake).

Soketi ya TCP sio muunganisho, huu ndio mwisho wa muunganisho maalum.

Kunaweza kuwa na miunganisho ya wakati mmoja kwenye sehemu ya mwisho ya huduma, kwa kuwa muunganisho unatambuliwa na ncha za ndani na za mbali, kuruhusu trafiki kuelekezwa kwa mfano maalum wa huduma.

Kunaweza kuwa na soketi moja tu ya msikilizaji kwa anwani fulani na mchanganyiko wa mlango.

Maonyesho

Hili lilikuwa swali la kufurahisha ambalo lilinifanya nifikirie tena baadhi ya mambo ambayo nilifikiri nilijua kwa ndani. Ungefikiria jina kama "tundu" litapewa: inaonekana imechaguliwa ili kuibua picha za sehemu ya mwisho ambayo unachomeka kebo ya mtandao, kuna ulinganifu thabiti wa utendaji hapo. Hata hivyo, katika lugha ya mitandao, neno "tundu" hubeba mizigo mingi sana kwamba uchunguzi upya wa makini ni muhimu.

Katika sana kwa maana pana, bandari ni mahali pa kuingilia au kutoka. Neno la Kifaransa porte, ingawa halitumiki katika muktadha wa mtandao, kwa kweli linamaanisha mlango au lango, na kusisitiza zaidi ukweli kwamba bandari ni sehemu za mwisho za usafiri, iwe unatuma data au vyombo vikubwa vya chuma.

Kwa madhumuni ya mjadala huu, nitapunguza uzingatiaji wa muktadha mitandao ya TCP-IP. Mfano wa OSI ni mzuri sana, lakini haujawahi kutekelezwa kikamilifu, chini sana kupelekwa katika mazingira ya high-voltage, high-trafiki.

Mchanganyiko wa anwani ya IP na bandari inajulikana sana kama sehemu ya mwisho na wakati mwingine huitwa tundu. Matumizi haya yanahusiana na RFC793, vipimo asili vya TCP.

Muunganisho wa TCP unafafanuliwa na ncha mbili aka soketi.

Sehemu ya mwisho (tundu) imedhamiriwa na mchanganyiko wa anwani ya mtandao na kitambulisho cha bandari. Kumbuka kuwa anwani/bandari haitambulishi kikamilifu tundu (zaidi kuhusu hili baadaye).

Madhumuni ya bandari ni kutofautisha kati ya ncha nyingi kwenye anwani fulani ya mtandao. Tunaweza kusema kwamba bandari ni sehemu ya mwisho iliyoboreshwa. Uboreshaji huu hufanya kadhaa miunganisho sambamba kwenye kiolesura kimoja cha mtandao.

Hii ni jozi ya soketi (tuple 4 inayojumuisha anwani ya IP ya mteja, nambari ya bandari ya mteja, anwani ya IP ya seva, na nambari ya bandari ya seva) ambayo inabainisha ncha mbili ambazo zinatambulisha kwa njia ya kipekee kila muunganisho wa TCP kwenye Mtandao. (TCP-IP Illustrated Volume 1, W. Richard Stevens)

Katika lugha nyingi zenye msingi wa C, miunganisho ya TCP huanzishwa na kushughulikiwa kwa kutumia mbinu kwenye mfano wa darasa la Soketi. Ingawa ni kawaida kufanya kazi kwa kiwango cha juu cha uondoaji, kawaida mfano wa darasa la NetworkStream, kawaida hutoa rejeleo la kitu cha tundu. Kwa kisimbaji, kitu hiki cha tundu kinaonekana kuwakilisha muunganisho kwa sababu muunganisho umeundwa na kudhibitiwa kwa kutumia mbinu za kitu cha tundu.

Katika C#, ili kuanzisha muunganisho wa TCP (kwa msikilizaji aliyepo), kwanza unaunda TcpClient. Ikiwa hutabainisha mwisho wa mjenzi wa TcpClient, hutumia maadili chaguo-msingi - kwa njia yoyote ile sehemu ya mwisho ya ndani imedhamiriwa. Kisha unaita njia ya Unganisha kwenye mfano ulioundwa. Njia hii inahitaji parameta inayoelezea mwisho mwingine.

Hii yote inachanganya kidogo na inakuongoza kuamini kuwa tundu ni kiunganisho ambacho ni kufuli. Nilikuwa nikifanya kazi chini ya kutokuelewana huku hadi Richard Dorman alipouliza swali.

Baada ya kusoma na kufikiria sana, sasa nina hakika kuwa itakuwa na maana zaidi kuwa na darasa la TcpConnection na mjenzi ambaye huchukua hoja mbili: LocalEndpoint na RemoteEndpoint. Labda unaweza kuunga mkono hoja moja ya RemoteEndpoint wakati maadili chaguo-msingi ya mwisho wa ndani yanakubalika. Hili ni gumu kwenye kompyuta za msingi nyingi, lakini utata unaweza kutatuliwa kwa kutumia jedwali la uelekezaji kwa kuchagua kiolesura chenye njia fupi zaidi ya kufikia mwisho wa mbali.

Uwazi utaimarishwa kwa njia zingine pia. Soketi haijatambuliwa na mchanganyiko wa anwani ya IP na bandari:

[...] TCP hutenganisha sehemu zinazoingia kwa kutumia thamani zote nne zilizo na anwani za ndani na nje ya nchi: anwani ya IP lengwa, nambari ya bandari lengwa, anwani ya IP ya chanzo, na nambari ya kituo cha chanzo. TCP haiwezi kubainisha ni mchakato gani unapokea sehemu inayoingia kwa kuangalia tu lango lengwa. Zaidi ya hayo, sehemu moja pekee kati ya [mbalimbali] za mwisho katika [nambari ya bandari iliyotolewa] ambayo itakubali maombi ya muunganisho yanayoingia ni ile iliyo katika hali ya kusikiliza. (p255, TCP-IP Illustrated Volume 1, W. Richard Stevens)

Kama unavyoona, haiwezekani tu, lakini kuna uwezekano, kwamba huduma ya mtandao ina soketi nyingi zilizo na anwani / bandari sawa, lakini tundu moja tu la msikilizaji kwenye anwani fulani / mchanganyiko wa bandari. Utekelezaji wa kawaida wa maktaba ni darasa la soketi, mfano ambao hutumiwa kuunda na kudhibiti muunganisho. Hii ni bahati mbaya sana kwani inaleta mkanganyiko na imesababisha mkanganyiko mkubwa wa dhana hizo mbili.

Khagrawal haniamini (tazama maoni), kwa hivyo hapa kuna sampuli halisi. Niliunganisha kivinjari cha wavuti kwa http://dilbert.com na kisha kukimbia netstat -an -p tcp . Laini sita za mwisho za matokeo zina mifano miwili ya jinsi anwani na mlango hazitoshi kutambua tundu kwa njia ya kipekee. Kuna miunganisho miwili tofauti kati ya 192.168.1.3 (kituo changu cha kazi) na 54.252.92.236:80

TCP 192.168.1.3:63240 54.252.94.236:80 SYN_SENT TCP 192.168.1.3:63241 54.252.94.236:80 SYN_SENT TCP 192.36:1608.168:168. SYN_SENT TCP 192.168.1.3:63243 207.38.110.62:80 SYN_SENT TCP 192.168 .1.3:64161 65.54.225.168:443 IMEANZISHWA

Kwa kuwa tundu ni hatua ya mwisho ya uunganisho, kuna soketi mbili na mchanganyiko wa anwani / bandari 207.38.110.62:80 na mbili zaidi na mchanganyiko wa anwani / bandari 54.252.94.236:80 .

Nadhani kutoelewana kwa Khagrawal kunatokana na matumizi yangu ya uangalifu sana ya neno "inabainisha". Ninamaanisha "tambua kabisa, kipekee na ya kipekee". Katika mfano hapo juu, kuna ncha mbili na mchanganyiko wa anwani / bandari 54.252.94.236:80. Ikiwa una anwani na mlango, huna maelezo ya kutosha kutenganisha viunganishi hivyo. Hakuna maelezo ya kutosha kutambua tundu.

Nyongeza

Aya ya pili ya sehemu ya 2.7 ya RFC793 inasema:

Uunganisho unafafanuliwa kabisa na jozi ya soketi kwenye ncha. Soketi ya ndani inaweza kushiriki katika viunganisho vingi na soketi mbalimbali za kigeni.

Ufafanuzi huu wa tundu sio muhimu kutoka kwa mtazamo wa programu kwa sababu sio sawa na kitu cha tundu, ambacho ni mwisho wa muunganisho maalum. Kwa mtayarishaji programu, na wengi wa watazamaji hawa ni waandaaji programu, hii ni tofauti muhimu ya utendaji.

Viungo

    TCP-IP Illustrated Volume 1 Protocols, W. Richard Stevens, 1994 Addison Wesley

    Soketi inawakilisha muunganisho mmoja kati ya programu mbili za mtandao. Programu hizi mbili zinaendeshwa kwa jina kwenye kompyuta tofauti, lakini soketi pia zinaweza kutumika kwa mawasiliano ya kuchakata kwenye kompyuta moja. Programu zinaweza kuunda soketi nyingi ili kuwasiliana na kila mmoja. Soketi ni za pande mbili, kumaanisha kuwa pande zote za muunganisho zina uwezo wa kutuma na kupokea data. Kwa hiyo, tundu linaweza kuundwa kwa kinadharia katika ngazi yoyote ya mfano wa OSI kutoka ngazi ya 2 hadi juu. Watengenezaji wa programu mara nyingi hutumia soketi katika programu ya mtandao, ingawa sio moja kwa moja. Maktaba za kupanga kama vile Winsock huficha maelezo mengi ya kiwango cha chini cha upangaji wa soketi. Soketi zimetumika sana tangu miaka ya mapema ya 1980.

    Bandari inawakilisha sehemu ya mwisho au "chaneli" ya mawasiliano ya mtandao. Nambari za bandari huruhusu programu tofauti kwenye kompyuta moja kutumia rasilimali za mtandao bila kuingiliana. Nambari za bandari ni za kawaida katika upangaji wa mtandao, haswa katika upangaji wa soketi. Wakati mwingine, hata hivyo, nambari za bandari zinaonekana kwa mtumiaji wa kawaida. Kwa mfano, baadhi ya tovuti ambazo mtu hutembelea kwenye Mtandao hutumia URL ifuatayo:

    Pamoja na mlinganisho fulani

    Ingawa kwa soketi mambo mengi ya kiufundi tayari yametolewa maelezo...ningependa kuongeza jibu langu, endapo tu, ikiwa kuna mtu bado hawezi kuhisi tofauti kati ya ip, bandari na soketi

    Fikiria seva S,

    na tuseme mtu X, Y, Z tunahitaji huduma (wacha tuseme huduma ya gumzo) kutoka kwa hii seva ya S

    Anwani ya IP inasemaWHO? seva hiyo ya gumzo "S" ambayo X, Y, Z inataka kuwasiliana nayo

    sawa, unayo "seva ni nani"

    lakini tuseme seva "S" pia inatoa huduma zingine kwa watu wengine, sema "S" hutoa huduma za uhifadhi kwa watu A, B, C

    bandari inasema ---> ipi? huduma ambayo wewe (X, Y, Z) unahitaji, i.e. huduma ya mazungumzo, si huduma ya kuhifadhi

    sawa.. unafahamisha seva kuwa unahitaji huduma ya gumzo na sio kuhifadhi

    una umri wa miaka mitatu na seva inaweza kutaka kutambua zote tatu tofauti

    huja tundu

    Sasa tundu linasemaAmbayo? uhusiano maalum

    yaani tuseme

    soketi 1 kwa kila mtu X

    soketi 2 kwa mtu Y

    na soketi 3 za mtu Z

    Natumai hii inasaidia mtu ambaye bado alikuwa amechanganyikiwa :)

    Kwanza, nadhani tunapaswa kuanza na uelewa mdogo wa nini inachukua kupata kifurushi cha A hadi B.

    Ufafanuzi wa kawaida kwa mtandao ni kutumia mfano wa OSI, ambao hugawanya mtandao katika tabaka nyingi kulingana na madhumuni yake. Kuna mambo machache muhimu ambayo tutazingatia hapa:

    • Safu ya kiungo cha data. Safu hii ina jukumu la kupokea pakiti za data kutoka kwa kifaa kimoja cha mtandao hadi kingine na hukaa juu ya safu ambayo husambaza. Inazungumza kuhusu anwani za MAC na inajua jinsi ya kupata wapangishaji kulingana na anwani zao za MAC (vifaa), lakini hakuna zaidi.
    • Safu ya mtandao ni safu inayoruhusu data kusafirishwa kwa mashine na kuvuka mipaka halisi kama vile vifaa vya kimwili. Safu ya mtandao lazima kimsingi iunge mkono utaratibu wa ziada wa msingi wa anwani ambao kwa namna fulani unahusiana na anwani halisi; ingiza anwani ya IP (IPv4). Anwani ya IP inaweza kupata kifurushi chako kutoka A hadi B kupitia Mtandao, lakini haijui chochote kuhusu jinsi ya kushughulikia safari za ndege za mtu binafsi. Hii inachakatwa na safu hapo juu kulingana na habari ya uelekezaji.
    • Safu ya usafiri. Safu hii ina jukumu la kufafanua jinsi maelezo yanavyopatikana kutoka A hadi B na vikwazo vyovyote, ukaguzi au hitilafu kwenye tabia hiyo. Kwa mfano, TCP inaongeza Taarifa za ziada kwenye pakiti ili iweze kutolewa ikiwa pakiti zilipotea.

    TCP ina, kati ya mambo mengine, dhana ya bandari. Kwa kweli hizi ni ncha tofauti za data kwenye anwani ile ile ya IP ambayo Soketi ya Mtandao (AF_INET) inaweza kujifunga.

    Jibu fupi fupi.

    A bandari inaweza kuelezewa kama anwani ya ndani ndani ya seva pangishi inayotambulisha programu au mchakato.

    A tundu inaweza kuelezewa kama kiolesura cha programu, kuruhusu programu kuwasiliana na programu au michakato mingine, mtandaoni au ndani ya nchi.

    Kwa kawaida utapata mambo mengi ya kinadharia, lakini moja ya wengi njia rahisi kutofautisha kati ya dhana hizi mbili ni kama ifuatavyo:

    Ili kupokea huduma unayohitaji nambari ya huduma. Nambari hii ya huduma inaitwa bandari. Kama hiyo tu.

    Kwa mfano, HTTP kama huduma inaendeshwa kwenye bandari 80.

    Sasa watu wengi wanaweza kuomba huduma na muunganisho wa seva ya mteja umeanzishwa. Kutakuwa na miunganisho mingi. Kila muunganisho unawakilisha mteja. Ili kusaidia kila muunganisho, seva huunda tundu kwa kila muunganisho ili kusaidia mteja wake.

    Inaonekana kuna majibu mengi kulinganisha tundu na unganisho kati ya PC mbili. Nadhani hii ni uongo kabisa. Soketi imekuwa mwisho kwenye Kompyuta 1, ambayo inaweza au isiunganishwe - bila shaka sote tumetumia vipokezi au soketi za UDP* wakati fulani. Sehemu muhimu ni kwamba inalenga na inafanya kazi. Kutuma ujumbe kwa faili 1.1.1.1:1234 hakuna uwezekano wa kufanya kazi kwa kuwa hakuna tundu la mwisho huo.

    Soketi ni maalum ya itifaki - kwa hivyo utekelezaji wa upekee ni kwamba TCP / na UDP / hutumia * (ipaddress: bandari), tofauti na, kwa mfano, IPX (Mtandao, Node na ... mchezo, tundu - lakini tundu tofauti kuliko chini. neno la jumla "tundu". Nambari za soketi za IPX ni sawa na bandari za IP). Lakini zote hutoa mwisho wa kipekee unaoweza kushughulikiwa.

    Kwa vile IP imekuwa itifaki kuu, bandari (katika masharti ya mtandao) imekuwa umoja huku nambari ya bandari ya UDP au TCP ikiwa sehemu ya anwani ya tundu.

    • UDP haina uhusiano-upande wowote - hii ina maana kwamba mzunguko wa kawaida haujaundwa kati ya ncha mbili. Walakini, kama sehemu ya mwisho bado tunarejelea soketi za UDP. Vipengele vya API weka wazi kuwa zote mbili ni za haki aina tofauti soketi. SOCK_DGRAM ni UDP (inatuma tu ujumbe) na SOCK_STREAM ni TCP (inaunda mzunguko pepe).

      Kitaalam, kichwa cha IP kina anwani ya IP, na itifaki juu ya IP (UDP au TCP) ina nambari ya bandari. Hii inaruhusu matumizi ya itifaki zingine (kama vile ICMP, ambazo hazina nambari za bandari, lakini zina maelezo ya anwani ya IP).

      Haya ni masharti kutoka mawili vikoa tofauti: "bandari" ni dhana kutoka mitandao ya TCP/IP, "soketi" ni API (programu). "Soketi" huundwa (kwa msimbo) kwa kuchukua bandari, jina la mwenyeji, au adapta ya mtandao na kuzichanganya katika muundo wa data ambao unaweza kutumia kutuma au kupokea data.

      Miunganisho ya TCP-IP ni njia mbili zinazounganisha anwani moja: mchanganyiko wa bandari hadi anwani nyingine: mchanganyiko wa bandari. Kwa hivyo wakati wowote unapofungua muunganisho kutoka kwa mashine yako ya karibu hadi kwenye bandari kwenye seva ya mbali (km www.google.com:80), pia unahusisha nambari mpya ya bandari kwenye mashine yako na muunganisho ili seva iweze kutuma vitu nyuma. wewe ( kwa mfano 127.0.0.1:65234). Ni muhimu kutumia netstat kutazama miunganisho yako kwenye kompyuta yako:

      > netstat -nWp tcp (kwenye OS X) Miunganisho Inayotumika ya Mtandao Proto Recv-Q Send-Q Anwani ya Ndani ya Nchi (jimbo) tcp4 0 0 192.168.0.6.49871 17.172.232.57.5223 IMEANZISHWA ...

      Tundu ni aina maalum ya maelezo ya faili ambayo hutumiwa na mchakato wa kuomba huduma za mtandao kutoka kwa mfumo wa uendeshaji. Anwani ya tundu ni mara tatu: (itifaki, anwani-ya-mtaa, mchakato wa ndani) wapi mchakato wa ndani kutambuliwa na nambari ya bandari.

      Katika seti ya TCP/IP, kwa mfano:

      (tcp, 193.44.234.3, 12345)

      Mazungumzo ni njia ya mawasiliano kati ya michakato miwili, hivyo huonyesha uhusiano kati ya hizo mbili. Muungano ni nakala 5 zinazofafanua kikamilifu michakato miwili iliyo na muunganisho: (itifaki, anwani-ya ndani, mchakato wa ndani, anwani ya kigeni, mchakato wa kigeni)

      Katika seti ya TCP/IP, kwa mfano:

      (tcp, 193.44.234.3, 1500, 193.44.234.5, 21)

      inaweza kuwa chama halali.

      Semi-chama: (itifaki, anwani ya eneo, mchakato wa ndani)

      (itifaki, anwani ya kigeni, mchakato wa kigeni)

      ambayo hufafanua kila nusu ya unganisho.

      Kiungo cha nusu pia huitwa tundu au anwani ya usafiri. Hiyo ni, tundu ni mwisho wa mawasiliano ambayo inaweza kutajwa na kushughulikiwa kwenye mtandao. Kiolesura cha tundu ni mojawapo ya violesura vya programu vya programu (API) kwa itifaki za mawasiliano. Iliyoundwa kama kiolesura cha programu cha mawasiliano kwa wote, ilianzishwa kwanza na mfumo wa UNIX 4.2BSD. Ingawa haikuwa sanifu, ikawa kiwango cha tasnia ya ukweli.

      Bandari ilikuwa sehemu rahisi, ni kitambulisho cha kipekee cha tundu. Soketi ni kitu ambacho michakato inaweza kutumia kuanzisha miunganisho na kuwasiliana na kila mmoja. Tall Jeff alikuwa na mlinganisho mzuri wa simu ambao haukuwa kamilifu, kwa hivyo niliamua kuurekebisha:

      Programu ina jozi ya michakato inayowasiliana kupitia mtandao (jozi ya seva ya mteja). Taratibu hizi hutuma na kupokea ujumbe kwenda na kutoka kwa mtandao kupitia kiolesura cha programu tundu. Kuzingatia mlinganisho iliyotolewa katika kitabu "Mtandao wa Kompyuta: Njia ya Juu-Chini". Kuna nyumba ambayo inataka kuwasiliana na nyumba nyingine. Hapa nyumba ni sawa na mchakato na mlango wa plagi. Mchakato wa kutuma unadhania kuwa kuna miundombinu upande wa pili wa mlango ambayo itasambaza data kwenye lengwa. Mara tu ujumbe unapofika kutoka upande wa pili, unapita kupitia mlango wa mpokeaji (tundu) ndani ya nyumba (mchakato). Kielelezo hiki kutoka katika kitabu hicho kinaweza kukusaidia:

      Soketi ni sehemu ya safu ya usafiri, ambayo hutoa mawasiliano ya mantiki na maombi. Hii ina maana kwamba kutoka kwa mtazamo wa maombi, nodi zote mbili zimeunganishwa moja kwa moja, ingawa kuna ruta nyingi na/au swichi kati yao. Kwa hivyo tundu sio kiunganisho yenyewe, ni sehemu ya mwisho ya unganisho. Itifaki za safu ya uchukuzi hutekelezwa tu kwa wapangishaji, sio kwenye vipanga njia vya kati.
      Bandari kutoa njia ya kushughulikia ndani kwa mashine. Lengo kuu ni kuruhusu michakato mingi kutuma na kupokea data kupitia mtandao bila kuingilia michakato mingine (data zao). Soketi zote hutolewa na nambari ya bandari. Sehemu inapofika kwa seva pangishi, safu ya usafiri huchunguza nambari ya bandari lengwa la sehemu hiyo. Kisha huhamisha sehemu kwenye tundu sahihi. Kazi hii ya kutoa data kwenye sehemu ya safu ya usafiri kwenye tundu sahihi inaitwa kudhoofisha. Kisha data ya sehemu hupitishwa kwa mchakato uliowekwa kwenye tundu.

      Soketi ni muundo wako programu. Ni zaidi au chini ya faili; ina shughuli kama vile kusoma na kuandika. Si jambo la kimwili; ni njia ya programu yako kurejelea vitu vya kawaida.

      Bandari ni kitu kama kifaa. Kila mwenyeji ana mtandao mmoja au zaidi (kimwili); mwenyeji ana anwani kwenye kila mtandao. Kila anwani inaweza kuwa na maelfu ya bandari.

      Soketi moja pekee inaweza kutumia mlango kwenye anwani. Soketi hutenga mlango kama vile kutenga kifaa kwa mfumo wa faili wa I/O. Mara bandari inapotolewa, hakuna tundu lingine linaloweza kuunganisha kwenye bandari hiyo. Bandari itatolewa wakati tundu limefungwa.

      Tundu ni ncha moja ya njia mbili za mawasiliano kati ya programu mbili zinazoendeshwa kwenye mtandao. Soketi imefungwa kwa nambari ya bandari ili safu ya TCP iweze kutambua programu ambayo data inakusudiwa kutumwa.

      Istilahi ya jamaa ya TCP/IP nadhani inaashiria swali hili. Kwa maneno ya watu wa kawaida:

      PORT ni nambari ya simu ya nyumba mahususi katika msimbo mahususi wa eneo. Msimbo wa posta wa jiji unaweza kuzingatiwa kama anwani ya IP ya jiji na nyumba zote katika jiji hilo.

      SOCKET, kwa upande mwingine, ni zaidi kama seti simu kati ya simu za jozi ya nyumba wakizungumza. Simu hizi zinaweza kuanzishwa kati ya nyumba katika jiji moja au nyumba mbili katika miji tofauti. Ni ile njia ya muda iliyoanzishwa kati ya simu mbili zinazozungumza ambazo ni SOCKET.

      Bandari na tundu zinaweza kulinganishwa na tawi la benki.

      Nambari ya jengo la Benki ni sawa na anwani ya IP. Benki ina sehemu mbalimbali kama vile:

      1. Idara ya akaunti ya akiba
      2. Idara ya Mikopo ya Kibinafsi
      3. Idara ya mikopo ya nyumba
      4. Idara ya Malalamiko

      Hivyo, 1 (Idara ya Akaunti ya Akiba), 2 (Idara ya Mikopo ya Kibinafsi), 3 (Idara ya Mikopo ya Nyumbani) na 4 (Idara ya Kushughulikia Malalamiko) ni bandari.

      Sasa hebu tukuambie kwamba unaenda kufungua akaunti ya akiba, unaenda benki (anwani ya IP), kisha unaenda "idara ya akaunti ya akiba" (bandari #1), kisha unakutana na mfanyakazi mmoja anayefanya kazi katika "akaunti ya akiba ya idara" ". Hebu tuiite SAVINGACCOUNT_EMPLOYEE1 ili kufungua akaunti.

      SAVINGACCOUNT_EMPLOYEE1 ni mpini wako wa soketi, kwa hivyo inaweza kutoka SAVINGACCOUNT_EMPLOYEE1 hadi SAVINGACCOUNT_EMPLOYEEN. Haya yote ni maelezo ya tundu.

      Vivyo hivyo, idara zingine zitakuwa na kazi chini yao na zinafanana na tundu.

      Tundu ni hatua ya mwisho ya mawasiliano. Soketi haihusiani moja kwa moja na familia ya itifaki ya TCP/IP; inaweza kutumika na itifaki yoyote inayoungwa mkono na mfumo wako. API ya tundu C inatarajia kupokea kwanza kitu tupu cha tundu kutoka kwa mfumo, ambacho kinaweza kufungwa kwa anwani ya tundu ya ndani (kupokea moja kwa moja. trafiki inayoingia kwa itifaki zisizo na muunganisho au ukubali maombi yanayoingia ya muunganisho wa itifaki zinazoelekezwa na muunganisho) au kwamba unaweza kuunganisha kwa anwani ya tundu ya mbali (kwa aina yoyote ya itifaki). Unaweza hata kufanya zote mbili ikiwa unataka kudhibiti zote mbili: anwani ya tundu ya ndani ambayo tundu imefungwa, na anwani ya tundu ya mbali ambayo tundu imefungwa. Kwa itifaki zisizo na muunganisho, kuunganisha tundu sio lazima hata, lakini ikiwa hautafanya hivyo, itabidi pia kupitisha anwani ya marudio na kila pakiti unayotaka kutuma juu ya tundu, ni jinsi gani tundu lingejua mahali pa kutuma? hizo data? Faida ni kwamba unaweza kutumia tundu moja kutuma pakiti kwa anwani tofauti za tundu. Mara baada ya kusanidi tundu na labda hata kuiunganisha, ichukulie kama njia ya mawasiliano ya pande mbili. Unaweza kuitumia kusambaza data kwenye eneo fulani, na eneo lingine linaweza kuitumia kusambaza data kwako. Unachoandika kwenye tundu hutumwa, na kile kilichopokelewa kinasomeka.

      Kwa upande mwingine, bandari ni kitu ambacho itifaki fulani tu kwenye safu ya itifaki ya TCP/IP inayo. Pakiti za TCP na UDP zina bandari. Bandari ni nambari tu. Mchanganyiko wa mlango wa chanzo na lango lengwa hufafanua njia ya mawasiliano kati ya wapangishaji wawili. Kwa mfano, unaweza kuwa na seva ambayo inahitaji kuwa seva rahisi ya HTTP na seva rahisi ya FTP. Ikiwa pakiti sasa itawasili kwa anwani ya seva hii, inajuaje kama ni pakiti ya HTTP au seva ya FTP? Kweli, itajua kwa kuwa seva ya HTTP itakuwa inaendesha kwenye bandari 80 na seva ya FTP itakuwa kwenye bandari 21, kwa hivyo ikiwa pakiti itafika na bandari fikio 80, inakusudiwa kwa seva ya HTTP na sio seva ya FTP . Pia pakiti ina lango la chanzo kwa sababu bila lango la chanzo kama hilo seva inaweza tu kuwa na muunganisho mmoja kwa anwani moja ya IP kwa wakati mmoja. Lango la chanzo huruhusu seva kutofautisha kati ya miunganisho inayofanana: zote zina lango lilelile la kulengwa, kwa mfano lango 80, anwani ile ile ya IP, anwani ya seva sawa na anwani ya IP ya chanzo sawa kwa sababu zote zinatoka kwa mteja mmoja. , lakini kwa kuwa wana bandari tofauti za chanzo, seva inaweza kuwatenganisha. Na seva inapotuma majibu, hufanya hivyo kwenye bandari ambayo ombi lilitoka, kwa njia hii mteja anaweza pia kutofautisha kati ya majibu tofauti anayopokea.

      Lango moja linaweza kuwa na jaketi moja au zaidi zilizounganishwa kwa IP nyingine ya nje, kama vile soketi nyingi.

      TCP 192.168.100.2:9001 155.94.246.179:39255 IMEANZISHWA 1312 TCP 192.168.100.2:9001 171.25.193.9:61832 131832 131832 TCP 1312 TCP 192.168.100.2:9001 171.25.193.9:61832 131832 131832 ESTABLI 131832 ESTABLI. 1 178.62.199.226:37912 IMEANZISHWA 1312 TCP 192.168.100.2:9001 188.193.64.150: 40900 IMEANZISHWA 1312 TCP 192.168.100.2:9001 198.23.194.149:43970 IMEANZISHWA 1312 TCP 192.168.100.2:9001 381298.

      Soketi ni kifupisho kinachotolewa na kernel maombi ya mtumiaji kwa pembejeo / pato la data. Aina ya tundu imedhamiriwa na itifaki yake ya usindikaji, mawasiliano ya IPC, nk. Kwa hivyo ikiwa mtu ataunda tundu la TCP, anaweza kufanya udanganyifu kama kusoma data kwenye tundu na kuiandikia data kwa kutumia njia rahisi na usindikaji wa itifaki ya safu ya chini kama tafsiri za TCP na usambazaji wa pakiti kwa itifaki za chini za mtandao hufanywa na utekelezaji maalum wa soketi kwenye kernel. . Faida ni kwamba mtumiaji hana haja ya kuwa na wasiwasi kuhusu jinsi ya kushughulika na itifaki maalum, na kusoma tu na kuandika data kwenye soketi kama bafa ya kawaida. Vile vile ni kweli katika kesi ya IPC, mtumiaji anasoma tu na kuandika data kwenye tundu na kernel inashughulikia maelezo yote ya kiwango cha chini kulingana na aina ya coz. ya soketi hii.

    Soketi dhidi ya Soketi sehemu ya 2, au sema "hapana" kwa itifaki ya TCP - Hifadhi WASM.RU kwenye kumbukumbu

    Katika sehemu ya kwanza, iliyojitolea kwa misingi ya kutumia soketi za MSWindows katika programu za kusanyiko, tulizungumza juu ya soketi ni nini, jinsi zinaundwa, na ni vigezo gani vilivyoainishwa. Wakati huo huo, ilitajwa katika kupitisha itifaki ya UDP isiyo na uhusiano, ambayo haitoi dhamana ya utoaji wa pakiti, pamoja na utaratibu ambao wanafika kwenye marudio yao. Mfano wa mafunzo kisha ulitumia itifaki yetu tuipendayo ya TCP. Na kila kitu kilikuwa sawa na sisi, lakini mwisho kulikuwa na maswali kadhaa ambayo hayajatatuliwa, haswa, jinsi ya kupanga kubadilishana kati ya kompyuta kadhaa kwenye mtandao, jinsi ya kuhamisha kitu kwa kompyuta nyingi mara moja, nk.

    Kwa ujumla, kusoma sehemu ya kwanza sio lazima kabisa kuelewa ya sasa, ingawa nitairejelea kila wakati njiani. Hivyo huenda. Haha...

    Kwa hivyo, tunaleta shida: tuna mtandao wa ndani wa, sema, kompyuta kadhaa, tunahitaji kuandaa ubadilishanaji wa ujumbe kati ya hizo mbili, na (hiari) kati ya moja na zingine zote.

    Nasikia, nasikia kwaya ya vidokezo vinavyosema, tumia kijengea ndani Vipengele vya Windows, aina:

    wavu tuma 192.168.0.4 Zhenya anatuma salamu kwako!

    net tuma Node4 Inasubiri jibu lako!

    Kuna pingamizi mbili tu kwa hili. Kwanza, hujui nini mfumo wetu wa uendeshaji au mipango mingine iliyopangwa tayari inaweza kufanya, tunataka kujifunza jinsi ya kuandika programu zetu wenyewe, sivyo? Na pili, sio ukweli kwamba ujumbe unatoka mtu hadi mtu. Kwa ujumla, mwendeshaji anaweza hajui chochote ... Au hata haipaswi kujua chochote ...

    Kwa mimi, jambo muhimu zaidi katika kuweka kazi hii ilikuwa kuhakikisha uwezo wa kuhamisha kitu kwenye kompyuta zote kwenye mtandao mara moja. Hebu fikiria kwamba tuliandika programu fulani ... Nani alisema - Trojan? Hapana, hapana na HAPANA! Hakuna Trojans. Programu ndogo tu (sana) ya uhasibu, kwa mfano. Ambayo baada ya muda iliweza kukaa kwenye kompyuta nyingi za yetu mtandao wa ndani. Na sasa wakati uliowekwa unakuja, ni wakati wa kusawazisha usawa, kwa muhtasari, kwa kusema, matokeo ya robo ... Kila kitu lazima kifanyike haraka na ikiwezekana kwa wakati mmoja. Jinsi ya kufanya hivyo ndani ya mfumo wa nyenzo ambazo tulisoma katika sehemu ya kwanza ilibaki wazi.

    Jibu, kama kawaida, linatoka kwa WindowsAPI. Tunatafuta na kupata. Kazi tuma kwa() – hutuma data kwa anwani maalum. Ni nini basi tofauti yake kutoka kwa kazi iliyosomwa tayari katika sehemu ya kwanza? tuma() ? Inageuka kuwa tuma kwa() inaweza kutangaza kwa anwani maalum ya IP. Lakini, tafadhali kumbuka, hii inafanya kazi tu kwa soketi za aina ya SOCK_DGRAM! Na soketi ambazo zilifunguliwa kwa kutumia thamani ya SOCK_DGRAM kama kigezo cha aina ya tundu hufanya kazi kupitia itifaki ya UDP, si TCP! Hii inaweka wazi maana ya kichwa kidogo cha makala hii ... Bila shaka, hii ni kifaa cha fasihi tu, hakuna itifaki iliyo bora au mbaya zaidi kuliko nyingine, wao ni tu ... tofauti, hivyo tu. Ingawa zote mbili ni itifaki za safu ya usafirishaji ambazo "... hutoa uhamishaji wa data kati ya michakato ya programu." Zote mbili hutumia itifaki ya safu ya mtandao kama vile IP kusambaza (kupokea) data. Kwa njia ambayo wao (data) kisha huingia ngazi ya kimwili, i.e. juu ya maambukizi Jumatano ... Na ni aina gani ya Jumatano ni, ni nani anayejua. Labda ni cable ya shaba, au labda sio Jumatano kabisa, lakini Alhamisi, na si cable ya shaba, lakini matangazo ...

    Mpango wa mwingiliano wa itifaki za mtandao.

    UDPU ser D atagram P itifaki

    TCP-T kutolewa C kudhibiti P itifaki

    ICMP-I mtandao C kudhibiti M insha P rotokoli (itifaki ya udhibiti wa kubadilishana ujumbe)

    ARPA anwani R suluhisho P rotokoli (itifaki ya ugunduzi wa anwani)

    Kwa ujumla, ikiwa kuchora hakukusaidia kwa njia yoyote, haijalishi. Ni muhimu kuelewa jambo moja kwamba TCP ni itifaki ya safu ya usafiri ambayo hutoa kuaminika kusafirisha data kati ya michakato ya maombi kwa kuanzisha muunganisho wa kimantiki (msisitizo wangu). Lakini UDP sio. Na zaidi. Mahali fulani pale, juu kiwango cha maombi, programu yetu itapatikana katika mojawapo ya mistatili tupu.

    Tumalizie sehemu ya utangulizi hapa na tuendelee kuangalia jinsi ya kuitumia tangu mwanzo.

    Ili kuonyesha nyenzo zote, kama kawaida, mfano wa mafunzo hutumiwa, ambao unaweza kupakuliwa< >. Tunaruka ile ya kawaida kwa kila mtu Programu za Windows sehemu na ueleze tu kile kinachohusu uendeshaji wa soketi. Kwanza unahitaji kuanzisha Windows Soketi DLL kwa kutumia kazi WSAStartup() , ambayo itarudisha sifuri ikiwa imefanikiwa, au, vinginevyo, mojawapo ya misimbo ya makosa. Kisha, unapoanzisha dirisha kuu la programu, fungua tundu ili kupokea ujumbe:

      omba soketi, AF_INET, \

      SOCK_DGRAM, \ ; inabainisha aina ya tundu - itifaki ya UDP!

      0; aina ya itifaki

      Ikiwa eax != INVALID_SOCKET ; ikiwa hakuna makosa

      mov hSocket, eax ; kumbuka kushughulikia

    Baada ya hayo, kama kawaida, tunahitaji kuwaambia Windows kutuma ujumbe kwa dirisha maalum kutoka kwa tundu tulilofungua:

      omba WSAAsyncSelect, hSocket, hWnd, WM_SOCKET, FD_READ

    Wapi hSoketi- maelezo ya tundu
    hWnd- kushughulikia kwa dirisha ambalo ujumbe wa utaratibu utatumwa
    WM_SOCKET- ujumbe, unaofafanuliwa na sisi katika section.const
    FD_SOMA- kinyago kinachobainisha matukio ya kuvutia kwetu, katika kwa kesi hii huu ndio utayari wa data kutoka kwa soketi ya kusoma.

    Ninasikia, nasikia chorus iliyoshangaa na kukata tamaa kwa sauti yao: waliahidi maombi yaliyofichwa, lakini hapa ni dirisha kuu na yote ... Ukweli ni kwamba huwezi kufanya bila hiyo, kwa sababu ... Mfumo wa uendeshaji hutuma ujumbe wote kwa programu yetu kupitia utaratibu wake wa dirisha. Suluhisho ni rahisi. Ikiwa ni lazima, ficha dirisha hili la programu muhimu zaidi. Vipi? Kwa mfano, toa maoni kwenye mstari:

      omba ShowWindow, hwnd, SW_SHOWNORMAL

    au, kwa usahihi zaidi, tumia:

      omba ShowWindow, hwnd, SW_HIDE

    Baada ya hayo, programu yetu pia itaanza, dirisha kuu litaundwa, ujumbe wa WM_CREATE utatumwa kwake kutoka kwa Windows na matokeo yote ... Dirisha lake pekee halitaonekana ama kwenye desktop au kwenye barani ya kazi. Ikiwa hii ndio ulitaka, nimefurahi. Anyway, tuendelee...

    Ili kufanya hivyo, badilisha nambari ya bandari hadi utaratibu wa mtandao byte kwa kutumia kazi maalum ya API:

      omba htons, Bandari

      mov sin.sin_bandari, shoka

      mov sin.sin_family, AF_INET

      mov sin.sin_addr, INADDR_ANY

    Kicheko kidogo cha sauti, sio lazima kuelewa maana ya nakala hii .

    Nambari za bandari za soketi zetu zilijadiliwa mwishoni mwa sehemu ya kwanza. Ni vigumu kutoa mapendekezo ya nini wanapaswa kuwa. Kitu pekee ambacho kinaweza kusemwa ni kwamba hawawezi kuwa. Sio busara kujaribu kutumia nambari za bandari zilizofafanuliwa kwa huduma zinazotumiwa sana kama vile:

    kupitia itifaki TCP: 20, 21 - ftp; 23 - telnet; 25 - smtp; 80 - http; 139 - huduma ya kikao cha NetBIOS;

    kupitia itifaki UDP: 53 - DNS; 137, 138 - NetBIOS; 161 - SNMP;

    Bila shaka, API ina kazi maalum getservbyport() , ambayo, ikipewa nambari ya bandari, inarudisha jina la huduma inayolingana. Kwa usahihi zaidi, kazi yenyewe inarudisha pointer kwa muundo, ambao ndani yake kuna pointer kwa jina hili ...

    Unaweza kuiita kama hii:

      omba htons, Bandari; badilisha nambari ya bandari kuwa mpangilio wa baiti ya mtandao

      omba getservbyport, shoka, 0;

    Kumbuka kile Marejeleo ya Win32 Programmer inasema kuhusu getservbyport:

    “...hurejesha kielekezi kwenye muundo ambao unasambazwa na Soketi za Windows. Programu haipaswi kamwe kujaribu kurekebisha muundo huu au sehemu zake zozote. Zaidi ya hayo, nakala moja tu ya muundo huu imetengwamtiririko, kwa hivyo ni lazima programu inakili taarifa yoyote inayohitaji kabla ya simu nyingine yoyote kwa kitendakazi cha Soketi za Windows."

    Na hapa kuna muundo yenyewe:

    1. s_jina DWORD ?; pointer kwa kamba yenye jina la huduma

      s_aliases DWORD ?;

      s_port NENO ?; nambari ya bandari

      s_proto DWORD ?;

    API pia ina kazi ya "paired", kwa kusema: getservbyname(), ambayo, kulingana na jina la huduma, inarudi taarifa kuhusu nambari ya bandari iliyotumiwa.

    Kwa bahati mbaya, hatutaweza kupata manufaa ya vitendo kutoka kwa vipengele hivi. Kwa hivyo, jua kuwa zipo na usahau juu yao ...

      omba funga, hSocket, addr sin, size ya dhambi

      Ikiwa eax == SOCKET_ERROR; ikiwa kuna hitilafu

      omba MessageBox, NULL, ongeza ...

    Katika hatua hii, kazi ya maandalizi ya kuunda na kusanidi tundu la kupokea kwa kutumia datagrams inaweza kuchukuliwa kuwa kamili. Hakuna haja ya kuweka tundu ili kusikiliza kwenye bandari kwa kutumia kipengele cha omba sikiliza, kama tulivyofanya kwa soketi ya aina SOCK_STREAM katika sehemu ya kwanza. Sasa katika utaratibu wa dirisha kuu la programu yetu tunaweza kuongeza nambari ambayo itatekelezwa wakati ujumbe wa WM_SOCKET utakapofika kutoka kwa soketi:

      ; ikiwa ujumbe umepokelewa kutoka kwa soketi (hSocket)

      Elseif uMsg == WM_SOCKET

    1. Ikiwa shoka == FD_READ;

    2. Ikiwa shoka == NULL ; hakuna kosa

      ; pokea data (baiti 64) kutoka kwa tundu kwenye bafa ya BytRecu

      omba recv, hSocket, addr BytRecu, 64, 0;

    Sasa hebu tuzungumze kuhusu jinsi ya kufungua tundu kwa kutuma ujumbe. Hapa kuna vitendo vyote muhimu vya programu:

      omba soketi, AF_INET, SOCK_DGRAM, 0

        omba htons, Bandari

        mov sin_to.sin_port, shoka

        mov sin_to.sin_family, AF_INET

        omba inet_addr, addr AddressIP

        mov sin_to.sin_addr, eax

      Linapokuja suala la kuhamisha data, unachohitaji kufanya ni:

        omba sendto, hSocket1, addr BytSend1, 64, 0, \

        addr sin_to, sizeof sin_to

      Thamani za parameta wakati wa kupiga kazi hii ya API ni kama ifuatavyo.

      hSoketi1- kushughulikia kwa tundu lililofunguliwa hapo awali
      addrBytSend1- anwani ya bafa iliyo na data ya usambazaji
      64 - ukubwa wa data katika bafa, katika ka
      0 - kiashiria..., katika mfano wa MSDN ni 0 tu
      addrsin_to- pointer kwa muundo ambao una anwani lengwa
      sizeofsin_to- ukubwa wa muundo huu katika ka.

      Ikiwa, wakati wa kutekeleza kitendakazi tuma kwa() hakuna makosa yaliyotokea, basi inarudisha idadi ya ka zilizohamishwa, vinginevyo matokeo ni SOCKET_ERROR katika eax.

      Sasa ni wakati wa kuzungumza juu ya anwani ile ile ya matangazo ambayo ilitajwa mwanzoni. Katika muundo tulijaza awali shamba na anwani ya IP lengwa, ikionyesha wapi, kwa kweli, kutuma data. Ikiwa anwani hii ni 127.0.0.1 - kwa kawaida, hakuna mahali popote zaidi kompyuta mwenyewe data zetu hazitapotea. Maandishi yanasema wazi kwamba pakiti iliyotumwa kwa mtandao yenye anwani 127.x.x.x haitatumwa kwenye mtandao wowote. Zaidi ya hayo, kipanga njia au lango haipaswi kamwe kueneza habari ya uelekezaji kwa nambari ya mtandao 127 - anwani hii sio anwani ya mtandao. Ili kutuma "usambazaji" kwa kompyuta zote kwenye mtandao wa ndani mara moja, unahitaji kutumia anwani iliyoundwa kutoka kwa anwani yetu ya IP, lakini kwa zote zilizo katika octet ya chini, kitu kama 192.168.0.255.

      Hiyo ndiyo yote, kwa kweli. Wakati programu inafunga, unahitaji kufunga soketi na kutolewa rasilimali za Soketi za DLL; hii inafanywa kwa urahisi:

        omba closesocket, hSocket

        omba closesocket, hSocket1

        omba WSACleanup

      Kwa programu zenye nyuzi nyingi baada ya WSACleanup shughuli za soketi zimekamilika kwa nyuzi zote.

      Jambo gumu zaidi kwangu katika makala hii lilikuwa kuamua jinsi ya kufafanua vizuri zaidi kutumia Windows Soketi API. Labda tayari umeona mbinu moja, ukiwa ndani maombi moja soketi zote mbili za kupokea na tundu la kutuma ujumbe zilitumika kwa wakati mmoja. Njia nyingine inaonekana si ya kuvutia sana, wakati msimbo wa moja na nyingine umetenganishwa wazi, hata kile kilichopo katika matumizi tofauti. Mwishoni, pia nilitekeleza njia hii, ambayo inaweza kuwa rahisi kidogo kwa Kompyuta kuelewa. Katika pili<архиве

      Bila kazi hii tuma () itazalisha SOCKET_ERROR!

      Hatimaye, tunaweza kutambua matatizo ya kawaida yanayotokea wakati wa kufanya kazi na soketi. Ili kushughulikia ujumbe wa dirisha unaoonyesha kuwa hali ya tundu imebadilika, tulitumia ujumbe wa moja kwa moja kutoka Windows hadi dirisha kuu la programu kama kawaida. Kuna mbinu nyingine wakati wa kuunda madirisha tofauti kwa kila tundu.

      Kwa ujumla, usindikaji wa ujumbe wa kati na dirisha kuu ni njia inayoonekana rahisi kuelewa, lakini bado inaweza kuwa shida katika mazoezi. Ikiwa programu inatumia soketi zaidi ya moja kwa wakati mmoja, inahitaji kuhifadhi orodha ya maelezo ya soketi. Wakati ujumbe kutoka kwa soketi unaonekana, utaratibu wa dirisha kuu katika orodha hutafuta taarifa zinazohusiana na maelezo ya soketi na kutuma ujumbe wa mabadiliko ya hali zaidi kwa utaratibu uliokusudiwa kwa hili. Ambayo tayari humenyuka kwa njia moja au nyingine, hufanya kitu pale ... Mbinu hii inalazimisha usindikaji wa kazi za mtandao kuunganishwa kwenye msingi wa programu, ambayo inafanya kuwa vigumu kuunda maktaba ya kazi za mtandao. Kila mara vipengele hivi vya utendakazi vya mtandao vinapotumika, msimbo wa ziada lazima uongezwe kwa kidhibiti kikuu cha dirisha la programu.

      Katika njia ya pili ya usindikaji wa ujumbe, programu inaunda dirisha lililofichwa ili kuzipokea. Inatumika kutenganisha utaratibu wa dirisha kuu la programu kutoka kwa usindikaji wa ujumbe wa mtandao. Mbinu hii inaweza kurahisisha programu kuu na kurahisisha kutumia msimbo uliopo wa mtandao katika programu zingine. Upande mbaya wa njia hii ni matumizi mengi ya Windows - kumbukumbu ya mtumiaji, kwa sababu Kwa kila dirisha iliyoundwa, kiasi kikubwa kinahifadhiwa.

      Njia ipi ya kuchagua ni juu yako. Kitu kimoja zaidi. Wakati wa kujaribu, unaweza kuhitaji kuzima ngome yako ya kibinafsi. Kwa mfano, Outpost Pro 2.1.275 katika hali ya kujifunza ilijibu jaribio la kuhamisha kwenye tundu, lakini wakati uhamisho uliporuhusiwa kwa mikono, data bado haikufika. Sana kwa UDP. Ingawa hii inaweza kuwa sio hivyo. Hakukuwa na shida na ZoneAlarmPro 5.0.590 yangu katika hali sawa.

      P.S. Wakati nikimaliza sehemu ya pili ya kifungu hicho, kwa bahati mbaya nilipata msimbo wa chanzo wa Trojan kwenye Mtandao katika lugha yetu tunayopenda ya MASM. Kila kitu kinajumuisha na kukimbia, jambo moja ni kwamba mteja hataki kuunganisha kwenye seva, na hata chini ya Windows 2000 sp4 wakati mwingine huanguka na kosa, akisema kwamba programu itafungwa na yote ... kama vile Trojan hii ni kwamba programu haiweki tu kumbukumbu ya kubofya , au "kunasua" faili iliyo na manenosiri na kuituma kwa barua pepe, na ina anuwai ya vitendaji vinavyodhibitiwa kwa mbali, vinavyotekelezwa kwa njia asili kabisa. Ikiwa tunasimamia kuleta biashara hii yote kwa maisha, basi labda sehemu ya tatu itaonekana hivi karibuni, inayotolewa kwa maelezo ya utekelezaji maalum ... Kwa wale ambao wamesoma kwa makini makala zote mbili na kuelewa uendeshaji wa kazi za API za tundu, kuna. hakuna kitu kigumu hapo. Inaonekana ... Kwa njia, mwandishi mwenyewe anaandika katika readme kwamba aliandika (Trojan) kwa madhumuni ya elimu. Oh vizuri. Tutatumia hii.

      DirectOr

    Ilisasishwa mwisho: 10/31/2015

    Itifaki ya UDP haihitaji muunganisho wa kudumu, na watu wengi wanaweza kuona ni rahisi kufanya kazi na UDP kuliko kwa TCP. Kanuni nyingi wakati wa kufanya kazi na UDP ni sawa na TCP.

    Kwanza, tundu linaundwa:

    Soketi ya soketi = Soketi mpya(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

    Ikiwa tundu lazima lipokee ujumbe, basi unahitaji kuifunga kwa anwani ya karibu na moja ya bandari kwa kutumia njia ya Bind:

    IPEndPoint localIP = IPEndPoint mpya(IPAddress.Parse("127.0.0.1"), 5555); tundu.Funga(localIP);

    Baada ya hayo, unaweza kutuma na kupokea ujumbe. Ili kupokea ujumbe, tumia njia ya ReceiveFrom():

    Data ya Byte = byte mpya; // bafa ya data iliyopokelewa //anwani ambayo data ilitoka EndPoint remoteIp = IPEndPoint mpya(IPAddress.Any, 0); int bytes = socket.ReceiveFrom(data, ref remoteIp);

    Kama kigezo, njia hupitishwa safu ya baiti ambayo data inapaswa kusomwa, na sehemu ya mbali ambayo data hii inatoka. Njia inarudisha idadi ya baiti zilizosomwa.

    Ili kutuma data, tumia njia ya SendTo():

    Ujumbe wa kamba = Console.ReadLine (); data byte = Encoding.Unicode.GetBytes(ujumbe); EndPoint remotePoint = IPEndPoint mpya(IPAddress.Parse("127.0.0.1"), remotePort); kusikilizaSocket.TumaKwa(data, remotePoint);

    Safu ya data ya kutumwa, pamoja na anwani ambayo data hii inapaswa kutumwa, hupitishwa kwa mbinu.

    Wacha tuunde mpango wa mteja wa UDP:

    Kutumia Mfumo; kwa kutumia System.Text; kwa kutumia System.Threading.Tasks; kutumia System.Net; kwa kutumia System.Net.Sockets; nafasi ya jina SocketUdpClient ( Mpango wa darasa ( static int localPort; // port kwa ajili ya kupokea ujumbe tuli int remotePort; // bandari ya kutuma ujumbe tuli Socket listeningSocket; static void Main(string args) ( Console.Write("Ingiza mlango wa kupokea ujumbe: ") ; localPort = Int32.Parse(Console.ReadLine()); Console.Andika("Ingiza lango ili kutuma ujumbe: "); remotePort = Int32.Parse(Console.ReadLine()); Console.WriteLine("Kwa tuma ujumbe, ingiza ujumbe na ubonyeze Enter"); Console.WriteLine(); jaribu ( listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); Task listeningTask = Task mpya(Sikiliza); ListenTask.Start( ); // kutuma ujumbe kwa bandari mbalimbali huku (kweli) (  string message = Console.ReadLine(); data byte = Encoding.Unicode.GetBytes(ujumbe); EndPoint remotePoint = IPEndPoint mpya(IPAddress.Parse("127.0). 0.1"), remotePort); listeningSocket.SendTo(data, remotePoint); ) ) pata (Isiofuata kanuni) ( Console.WriteLine(ex.Message); ) hatimaye ( Funga(); ) ) // uzi wa kukubali miunganisho ya utupu ya kibinafsi Sikiliza() ( jaribu ( //Sikiliza katika anwani ya IPEndPoint localIP = IPEndPoint mpya(IPAddress.Parse("127.0.0.1")), localPort); listeningSocket .Bind(localIP); wakati (kweli) (// pokea ujumbe StringBuilder builder = new StringBuilder(); int byte = 0; // idadi ya baiti zilizopokelewa data ya byte = byte mpya; // buffer kwa data iliyopokelewa / /anwani, s ambayo data ilikuja EndPoint remoteIp = IPEndPoint mpya(IPAddress.Any, 0); fanya ( bytes = listeningSocket.ReceiveFrom(data, ref remoteIp); builder.Append(Encoding.Unicode.GetString(data, 0, bytes) ); ) wakati (kusikilizaSocket.Inapatikana > 0); // pata maelezo ya muunganisho IPEndPoint remoteFullIp = remoteIp kama IPEndPoint; // chapisha ujumbe Console.WriteLine("(0):(1) - (2)", remoteFullIp.Anwani .ToString() , remoteFullIp.Port, builder.ToString()); ) ) kamata (Ila isipokuwa) ( Console.WriteLine(ex.Message); ) hatimaye ( Close(); ) ) // kufunga tundu la faragha tuli Funga() ( ikiwa (listeningSocket != null) ( listeningSocket.Shutdown(SocketShutdown.Both); kusikilizaSoketi.Funga(); listeningSocket = null; )))

    Kwanza, mtumiaji huingia kwenye bandari kwa kupokea data na kutuma. Inachukuliwa kuwa programu mbili za mteja ambazo zitaingiliana zinaendesha kwenye mashine moja ya ndani. Ikiwa anwani za wateja ni tofauti, unaweza pia kutoa kwa ajili ya kuweka anwani ya kutuma data.

    Baada ya kuingia kwenye bandari, kazi ya kusikiliza ujumbe unaoingia imezinduliwa. Tofauti na seva ya tcp, hakuna haja ya kupiga njia za Sikiliza na Kubali. Katika kitanzi kisicho na kikomo, tunaweza kupokea data moja kwa moja kwa kutumia njia ya ReceiveFrom(), ambayo huzuia mazungumzo ya kupiga simu hadi data inayofuata ifike.

    Njia hii inarudi kupitia parameta ya ref sehemu ya mbali, ambayo data ilipatikana:

    IPEndPoint remoteFullIp = remoteIp kama IPEndPoint;

    Hiyo ni, licha ya ukweli kwamba katika kesi hii mapokezi na utumaji wa ujumbe hutofautishwa na mteja wa sasa hutuma data tu kwenye bandari iliyoingia hapo awali, tunaweza kuongeza kwa urahisi uwezo wa kujibu ujumbe kwa kutumia data ya hatua ya mbali iliyopokelewa ( anwani na bandari).

    Uzi mkuu hutuma ujumbe kwa kutumia njia ya SendTo().

    Kwa hivyo, programu hufanya mara moja kazi za seva na mteja.

    Sasa hebu tuzindue nakala mbili za programu na tuingize data tofauti kwa bandari. Mteja wa kwanza:

    Ingiza mlango wa kupokea ujumbe: 4004 Ingiza bandari ya kutuma ujumbe: 4005 Kutuma ujumbe, ingiza ujumbe na ubonyeze Ingiza 127.0.0.1:4005 - hujambo bandari 4004 mchana mzuri, bandari 4005 hali ya hewa nzuri.

    Mteja wa pili:

    Ingiza mlango wa kupokea ujumbe: 4005 Ingiza bandari ya kutuma ujumbe: 4004 Ili kutuma ujumbe, ingiza ujumbe na ubonyeze Ingiza hello port 4004 127.0.0.1:4004 - habari za mchana, bandari 4005 127.0.0.1:4004 - hali ya hewa nzuri

    Programu zinazotumia TCP na UDP ni tofauti kimsingi kwa sababu UDP ni itifaki ya datagram isiyotegemewa, isiyo na muunganisho na kimsingi ni tofauti na uhamishaji unaoegemea muunganisho, mkondo-wa-kuaminika wa TCP. Hata hivyo, kuna matukio ambapo ni mantiki kutumia UDP badala ya TCP. Tunazingatia kesi kama hizo katika Sehemu ya 22.4. Baadhi programu maarufu imejengwa kwa kutumia UDP, kama vile DNS ( Jina la Kikoa Mfumo - mfumo wa jina la kikoa), NFS (mfumo wa faili wa mtandao - Mtandao Mfumo wa Faili) na SNMP (Itifaki Rahisi ya Usimamizi wa Mtandao).

    Katika Mtini. Mchoro 8.1 unaonyesha wito wa utendakazi kwa mpango wa kawaida wa seva ya mteja wa UDP. Mteja hajaanzisha muunganisho kwenye seva. Badala yake, mteja hutuma tu datagram kwa seva kwa kutumia kitendakazi cha sendto (kilichoelezewa katika sehemu inayofuata), ambayo huchukua anwani ya mpokeaji (seva) kama hoja. Vivyo hivyo, seva haianzishi muunganisho na mteja. Badala yake, seva huita tu kazi ya recvfrom, ambayo inasubiri data kufika kutoka kwa mteja fulani. Chaguo za kukokotoa recvfrom hurejesha anwani ya mteja (kwa itifaki fulani) pamoja na datagram, ili seva iweze kutuma jibu kwa mteja halisi aliyetuma datagramu.

    Mchele. 8.1. Utendakazi wa tundu kwa mfano wa seva ya mteja wa UDP

    Mchoro 8.1 unaonyesha mchoro wa muda wa hali ya kawaida ya kubadilishana data ya UDP kati ya mteja na seva. Tunaweza kulinganisha mfano huu na ubadilishanaji wa kawaida wa TCP ulioonyeshwa kwenye Kielelezo. 4.1.

    Katika sura hii, tutaelezea utendakazi mpya unaotumiwa na soketi za UDP, recvfrom na sendto, na kurekebisha muundo wetu wa seva ya mteja ili Maombi ya UDP. Pia tutaangalia kutumia kitendakazi cha kuunganisha na tundu la UDP na dhana ya makosa ya asynchronous.

    8.2. recvfrom na sendto vitendaji

    Kazi hizi mbili ni sawa na kazi za kawaida za kusoma na kuandika, lakini zinahitaji hoja tatu za ziada.

    ssize_t recvfrom(int sockfd , void * buff , size_t nbytes , bendera za int ,

    struct sockaddr * kutoka , socklen_t * adderlen);

    ssize_t sendto(int sockfd, const void * buff, size_t nbytes, bendera za int,

    const struct sockaddr * to , socklen_t addrlen);

    Chaguo zote mbili za kukokotoa hurejesha idadi ya baiti zilizoandikwa au kusomwa kwenye mafanikio, -1 kwa makosa.

    Hoja tatu za kwanza, sockfd , buff , na nbytes , ni sawa na hoja tatu za kwanza za vipengele vya kusoma na kuandika: mpini, kielekezi cha bafa ya kusoma au kuandikia, na idadi ya baiti za kusoma au kuandika. .

    Tutashughulikia hoja ya bendera katika Sura ya 14, ambapo tunaangalia vitendaji vya recv , send , recvmsg , na sendmsg, kwa sababu kwa sasa tuko katika mfumo wetu. mfano rahisi hazihitajiki. Kwa sasa tutaweka hoja za bendera kuwa sifuri.

    Hoja ya kukokotoa kwa kutuma ni muundo wa anwani ya tundu iliyo na anwani ya itifaki (kama vile anwani ya IP na nambari ya mlango) ya lengwa. Saizi ya muundo huu wa anwani ya tundu imebainishwa na hoja ya addrlen. Chaguo za kukokotoa za recvform hujaza muundo wa anwani ya tundu unaoelekezwa na kutoka kwa hoja na anwani ya itifaki ya mtumaji wa datagram. Idadi ya baiti zilizohifadhiwa katika muundo wa anwani ya tundu pia hurejeshwa kwa mchakato wa kupiga simu kama nambari kamili inavyoelekezwa na hoja ya addrlen. Kumbuka kuwa hoja ya mwisho kwa sendto ni thamani kamili, ilhali hoja ya mwisho kwa recvfrom ni kielekezi cha thamani kamili (hoja ya matokeo ya thamani).

    Hoja mbili za mwisho kwa chaguo za kukokotoa za recvfrom ni sawa na hoja mbili za mwisho za chaguo la kukokotoa la kukubali: yaliyomo katika muundo wa anwani ya soketi baada ya kukamilika hutuambia ni nani aliyetuma datagramu (katika kesi ya UDP) au ni nani aliyeanzisha muunganisho (katika kesi ya TCP). Hoja mbili za mwisho za kazi ya sendto ni sawa na hoja mbili za mwisho za kazi ya kuunganisha: tunajaza muundo wa anwani ya tundu na anwani ya itifaki ya mpokeaji wa datagram (katika kesi ya UDP) au anwani ya mwenyeji ambaye uunganisho utaanzishwa (katika kesi ya TCP).

    Chaguo za kukokotoa zote mbili hurudi kama chaguo za kukokotoa huthamini urefu wa data iliyosomwa au iliyoandikwa. Katika matumizi ya kawaida ya chaguo za kukokotoa za recvfrom na itifaki ya datagram, thamani ya kurejesha ni kiasi cha data ya mtumiaji katika datagramu iliyopokelewa.

    Datagram inaweza kuwa na urefu wa sifuri. Kwa UDP, hii hurejesha datagram ya IP iliyo na kichwa cha IP (kawaida baiti 20 za IPv4 au baiti 40 za IPv6), kichwa cha UDP cha baiti 8, na hakuna data. Hii pia inamaanisha kuwa thamani isiyo na maana iliyorejeshwa kutoka kwa recvfrom inakubalika kikamilifu kwa itifaki ya datagram: haionyeshi kuwa mtu mwingine amefunga muunganisho, kama ingekuwa hivyo wakati wa kurudi. thamani ya sifuri kutoka kwa kazi ya kusoma kwenye tundu la TCP. Kwa kuwa itifaki ya UDP hailengi muunganisho, hakuna tukio kama vile kufungwa kwa muunganisho.

    Ikiwa kutoka kwa hoja hadi recvfrom ni kielekezi kisicho na maana, basi hoja ya urefu inayolingana (addrlen) lazima pia iwe kielekezi kisicho na maana, kumaanisha kwamba hatuvutiwi na anwani ya mtumaji wa data.

    Vitendaji vyote viwili vya recvfrom na sendto vinaweza kutumika na TCP, ingawa kwa kawaida si lazima.

    8.3. Seva ya mwangwi ya UDP: kazi kuu

    Sasa tutarekebisha muundo wetu rahisi wa seva ya mteja kutoka Sura ya 5 kwa kutumia UDP. Mchoro wa simu za utendaji katika mteja wetu wa UDP na programu za seva huonyeshwa kwenye Mtini. 8.1. Katika Mtini. 8.2 inaonyesha vitendaji vilivyotumika. Orodha ya 8.1 inaonyesha kazi kuu ya seva.

    Mchele. 8.2. Mfano rahisi wa seva ya mteja kwa kutumia UDP

    Kuorodhesha 8.1. Seva ya mwangwi ya UDP

    //udpcliserv/udpserv01.с

    1 #pamoja na "unp.h"

    3 nyumba ya ulinzi (int argc, char **argv)

    6 struct sockaddr_in servaddr, cliaddr;

    7 sockfd = Soketi(AF_INET, SOCK_DGRAM, 0);

    8 bzero(&servaddr, sizeof(servaddr));

    9 servaddr.sin_family = AF_INET;

    10 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    12 Bind(sockfd, (SA*)&servaddr, sizeof(servaddr));

    13 dg_echo(sodkfd, (SA*)&cliaddr, sizeof(cliaddr));

    Unda tundu la UDP, funga kwenye mlango unaojulikana kwa kutumia kitendakazi cha kumfunga

    7-12 Tunaunda soketi ya UDP kwa kubainisha SOCK_DGRAM (soketi ya datagram ya IPv4) kama hoja ya pili ya chaguo za kukokotoa tundu. Kama katika mfano Seva ya TCP, anwani ya IPv4 ya kitendakazi cha kumfunga imewekwa kuwa INADDR_ANY, na nambari ya mlango inayojulikana awali ya seva ni SERV_PORT isiyobadilika kutoka kwa kichwa cha unp.h.

    13 Kitendakazi cha dg_echo basi huitwa kushughulikia ombi la mteja na seva.

    8.4. Seva ya mwangwi ya UDP: kazi ya dg_echo

    Orodha ya 8.2 inaonyesha kazi ya dg_echo.

    Kuorodhesha 8.2. dg_echo kazi: kamba za mwangwi kwenye soketi ya datagram

    1 #pamoja na "unp.h"

    3 dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)

    6 socklen_t len;

    7 char mesg;

    10 n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);

    11 Sendto(sockfd, mesg, n, 0, pcliaddr, len);

    Kusoma datagram, kutafakari kwa mtumaji

    8-12 Chaguo hili la kukokotoa ni kitanzi rahisi ambamo datagramu inayofuata inayofika kwenye mlango wa seva inasomwa na chaguo za kukokotoa za recvfrom na kurejeshwa kwa kutumia kitendakazi cha sendto.

    Licha ya unyenyekevu wa kazi hii, kuna idadi ya maelezo muhimu ya kuzingatia. Kwanza, kipengele hiki cha kukokotoa hakimaliziki. Kwa sababu UDP ni itifaki isiyo na muunganisho, hakuna alama sawa na bendera ya mwisho wa faili inayotumika katika TCP.

    Pili, kazi hii hukuruhusu kuunda seva ya serial, badala ya ile inayofanana, ambayo tulipokea katika kesi ya TCP. Kwa kuwa hakuna simu ya kazi ya uma, mchakato mmoja wa seva hushughulikia usindikaji wote wa mteja. Kwa ujumla, seva nyingi za TCP ziko sambamba, na seva nyingi za UDP ni za mfululizo.

    Kwa soketi katika kiwango cha UDP, datagramu zimeakibishwa kwa njia ya foleni. Hakika, kila soketi ya UDP ina bafa ya kupokea, na kila datagramu inayofika kwenye tundu hilo huwekwa kwenye bafa yake ya kupokea. Mchakato unapoita chaguo za kukokotoa recvfrom, datagramu inayofuata kutoka kwa bafa inarejeshwa kwa mchakato katika mpangilio wa FIFO (Kwanza Katika, Kwanza). Kwa hivyo, ikiwa datagramu nyingi hufika kwenye tundu kabla ya mchakato kusoma data iliyopangwa tayari kwa tundu, basi datagramu zinazoingia huongezwa kwa bafa ya tundu. Lakini bafa hii ina ukubwa mdogo. Tulijadili saizi hii na jinsi ya kuiongeza kwa kutumia chaguo la tundu la SO_RCVBUF katika Sehemu ya 7.5.

    Katika Mtini. Mchoro 8.3 unaonyesha ujumuishaji wa muundo wa seva ya mteja wa TCP kutoka Sura ya 5, ambapo wateja wawili huanzisha miunganisho kwenye seva.

    Mchele. 8.3. Ujumla wa mfano wa seva ya mteja wa TCP na wateja wawili

    Kuna soketi mbili zilizoambatishwa hapa, na kila soketi zilizoambatishwa kwenye nodi ya seva ina bafa yake ya kupokea. Katika Mtini. Mchoro 8.4 unaonyesha kisa ambapo wateja wawili wanatuma datagramu kwa seva ya UDP.

    Mchele. 8.4. Ujumla wa mfano wa seva ya mteja wa UDP na wateja wawili

    Kuna mchakato mmoja tu wa seva, na ina soketi moja ambayo seva hupokea datagramu zote zinazoingia na ambayo hutuma majibu yote. Soketi hii ina bafa ya kupokea ambamo datagramu zote zinazoingia huwekwa.

    Kazi kuu katika Orodha ya 8.1 inategemea itifaki (huunda tundu la familia la AF_INET na kisha kutenga na kuanzisha muundo wa anwani ya tundu ya IPv4), lakini kazi ya dg_echo haitegemei itifaki. Sababu kwa nini kitendakazi cha dg_echo kinajitegemea itifaki ni kwa sababu mchakato wa kupiga simu(kwa upande wetu, kazi kuu) lazima itenge muundo wa anwani ya tundu ya ukubwa sahihi katika kumbukumbu, na pointer kwa muundo huu pamoja na ukubwa wake hupitishwa kama hoja kwa kazi ya dg_echo. Kitendaji cha dg_echo kamwe hakichimbui muundo huu: hupitisha kielekezi kwake kwa vitendaji vya recvfrom na sendto. Chaguo za kukokotoa za recvfrom hujaza muundo huu na anwani ya IP ya mteja na nambari ya bandari, na kwa kuwa kielekezi sawa (pcliaddr) hupitishwa kwa kazi ya kutuma kama anwani lengwa, kwa hivyo datagramu huonyeshwa tena kwa mteja aliyetuma datagramu.

    8.5. UDP echo mteja: kazi kuu

    Kazi kuu ya mteja wa UDP imeonyeshwa katika Orodha ya 8.3.

    Kuorodhesha 8.3. UDP echo mteja

    //udpcliserv/udpcli01.c

    1 #pamoja na "unp.h"

    3 kuu (int argc, char **argv)

    6 struct sockaddr_in servaddr;

    7 ikiwa (argc!= 2)

    8 err_quit("matumizi: udpcli");

    9 bzero(&servaddr, sizeof(servaddr));

    10 servaddr.sin_family = AF_INET;

    11 servaddr.sin_port = htons(SERV_PORT);

    12 Inet_pton(AF_INET, argv, &servaddr.sin_addr);

    13 sockfd = Soketi(AF_INET, SOCK_DGRAM, 0);

    14 dg_cli(stdin, sockfd, (SA*)&servaddr, sizeof(servaddr));

    Kujaza muundo wa anwani ya tundu na anwani ya seva

    9-12 Muundo wa anwani ya tundu ya IPv4 umejaa anwani ya IP na nambari ya bandari ya seva. Muundo huu utapitishwa kwa kazi ya dg_cli. Huamua mahali pa kutuma datagrams.

    13-14 Soketi ya UDP imeundwa na kazi ya dg_cli inaitwa.

    8.6. UDP echo mteja: dg_cli kazi

    Orodha ya 8.4 inaonyesha kazi ya dg_cli, ambayo hufanya kazi nyingi kwa upande wa mteja.

    Kuorodhesha 8.4. Kazi dg_cli: kitanzi cha mteja

    1 #pamoja na "unp.h"

    7 huku (Fgets(sendline, MAXLINE, fp) != NULL) (

    8 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

    9 n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);

    10 recvline[n] = 0; /* kubatilisha */

    Fputs 11(recvline, stdout);

    7-12 Kuna hatua nne katika kitanzi cha usindikaji cha upande wa mteja: kusoma kamba kutoka mkondo wa kawaida ingizo kwa kutumia chaguo za kukokotoa za fgets, kutuma mfuatano kwa seva kwa kutumia kitendakazi cha sendto, kusoma jibu lililoakisiwa la seva kwa kutumia chaguo za kukokotoa za recvfrom, na kuweka mfuatano unaoakisiwa kwa pato la kawaida kwa kutumia chaguo za kukokotoa za fputs.

    Mteja wetu hakuuliza kernel kukabidhi mlango uliowekwa kwa nguvu kwenye soketi yake (lakini mteja wa TCP alifanya wakati wa kupiga simu unganisha). Kwa soketi ya UDP, mara ya kwanza sendto inaitwa, kernel huchagua mlango uliowekwa kwa nguvu ikiwa hakuna bandari ya ndani ambayo tayari imehusishwa na tundu hilo. Kama ilivyo kwa TCP, mteja anaweza kupiga simu bind kwa uwazi, lakini hii haifanyiki mara chache.

    Kumbuka kuwa unapoita chaguo za kukokotoa recvfrom, viashiria visivyofaa vinabainishwa kama hoja ya tano na sita. Hii inaambia kokwa kuwa hatuna nia ya kujua ni nani aliyetuma jibu. Kuna hatari kwamba mchakato wowote, iwe kwenye nodi moja au kwa nyingine yoyote, unaweza kutuma datagram kwa anwani ya IP ya mteja na bandari, ambayo itasomwa na mteja, ikizingatiwa kuwa ni jibu kutoka kwa seva. Tutazingatia hali hii katika sehemu ya 8.8.

    Kama ilivyo kwa chaguo la kukokotoa la seva ya dg_echo, kitendakazi cha mteja wa dg_cli hakijitegemei itifaki, lakini kazi kuu ya mteja inategemea itifaki. Kazi kuu hutenga na kuanzisha muundo wa anwani ya tundu unaohusishwa na aina fulani itifaki na kisha kupitisha kazi ya dg_cli pointer kwa muundo pamoja na saizi yake.

    8.7. Datagrams zilizopotea

    Mteja wa UDP na seva katika mfano wetu sio wa kutegemewa. Ikiwa datagramu ya mteja imepotea (tuseme imepuuzwa na kipanga njia fulani kati ya mteja na seva), mteja atazuiwa milele katika simu yake kwa kitendakazi cha recvfrom ndani ya kitendakazi cha dg_cli, akisubiri jibu kutoka kwa seva ambayo kamwe kuja. Vile vile, ikiwa datagramu ya mteja itafika kwenye seva lakini majibu ya seva yamepotea, mteja atazuiwa kabisa katika simu yake ya kitendakazi cha recvfrom. njia pekee Ili kuzuia hali hii, weka muda katika simu ya mteja kwenye kitendakazi cha recvfrom. Tutaangalia hili katika sehemu ya 14.2.

    Kuweka tu muda wa kuisha katika simu ya chaguo la kukokotoa recvfrom bado bado suluhisho kamili. Kwa mfano, ikiwa muda maalum kusubiri kumekwisha na hakuna jibu lililopokelewa, hatuwezi kusema ni nini kibaya - ama datagramu yetu haikufikia seva, au jibu la seva halijarudi. Ikiwa ombi la mteja lilikuwa na ombi kama vile "kuhamisha kiasi fulani cha pesa kutoka kwa akaunti A hadi akaunti B" (kinyume na kesi ya seva yetu rahisi ya mwangwi), basi kungekuwa na tofauti kubwa kati ya kupoteza ombi na kupoteza jibu. . Tutazungumza zaidi kuhusu kuongeza uaminifu kwa muundo wa seva ya mteja wa UDP katika Sehemu ya 22.5.

    8.8. Kuangalia jibu lililopokelewa

    Mwishoni mwa sehemu ya 8.6, tulitaja kuwa mchakato wowote unaojua nambari ya mlango iliyokabidhiwa ya mteja inaweza kutuma datagramu kwa mteja wetu, na zitachanganywa na majibu ya kawaida ya seva. Tunachoweza kufanya ni kurekebisha simu ya kukokotoa kutoka kwa recvfrom katika Orodha 8.4 ili kurudisha anwani ya IP na mlango wa mtumaji wa jibu, na kupuuza datagramu zozote zinazotoka kwa seva zaidi ya ile tunayotuma datagramu. Walakini, kuna mitego kadhaa hapa, kama tutakavyoona.

    Kwanza, tunarekebisha kazi kuu ya mteja (angalia Orodha 8.3) ili kufanya kazi na seva ya kawaida ya echo (tazama Jedwali 2.1). Tunabadilisha mgawo tu

    servaddr.sin_port = htons(SERV_PORT);

    kazi

    servaddr.sin_port = htons(7);

    Sasa tunaweza kutumia nodi yoyote inayoendesha seva ya mwangwi ya kawaida na mteja wetu.

    Kisha tunaandika upya dg_cli chaguo za kukokotoa ili kutenga muundo tofauti wa anwani ya tundu kwenye kumbukumbu ili kushikilia muundo uliorejeshwa na recvfrom . Tunaionyesha katika Orodha 8.5.

    Orodha 8.5. Toleo la chaguo la kukokotoa la dg_cli ambalo hukagua anwani ya tundu iliyorejeshwa

    //udpcliserv/dgcliaddr.c

    1 #pamoja na "unp.h"

    3 dg_cli(FILE *fp, int sockfd, const SA *pseraddr, socklen_t servlen)

    6 char sendline, recvline;

    7 socklen_t len;

    8 struct sockaddr *preply_addr;

    9 preply_addr = Malloc(servlen);

    10 huku (Fgets(sendline, MAXLINE, fp) != NULL) (

    11 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

    12 len = servlen;

    13 n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);

    14 ikiwa (len != servlen || memcmp(pservaddr, preply_addr, len) != 0) (

    15 printf("jibu kutoka kwa %s (limepuuzwa)\n",

    18 recvline[n] = 0; /* kubatilisha */

    Fputs 19(recvline, stdout);

    Kuweka muundo tofauti wa anwani ya tundu kwenye kumbukumbu

    9 Tunatenga muundo mwingine wa anwani ya tundu kwenye kumbukumbu kwa kutumia kazi ya malloc. Kumbuka kuwa chaguo la kukokotoa la dg_cli bado ni itifaki inayojitegemea. Kwa kuwa hatujali ni aina gani ya muundo wa anwani ya tundu tunaoshughulikia, tunatumia ukubwa wake pekee katika simu ya chaguo la kukokotoa malloc.

    Ulinganisho wa anwani zilizorejeshwa

    12-13 Katika simu ya kazi ya recvfrom, tunaiambia kernel kurudisha anwani ya chanzo ya datagram. Kwanza tunalinganisha urefu uliorejeshwa na chaguo za kukokotoa recvfrom kama hoja ya matokeo ya thamani, na kisha kulinganisha miundo ya anwani ya tundu yenyewe kwa kutumia chaguo za kukokotoa za memcmp.

    Toleo jipya la mteja wetu hufanya kazi vizuri ikiwa seva iko kwenye seva pangishi iliyo na anwani moja ya IP. Lakini programu hii haiwezi kufanya kazi ikiwa seva ina miingiliano kadhaa ya mtandao (seva ya multihomed). Tunaendesha programu hii kwa kupata nodi ya freebsd4, ambayo ina miingiliano miwili na anwani mbili za IP:

    macosx% mwenyeji freebsd4

    freebsd4.unpbook.com ina anwani 172.24.37.94

    freebsd4.unpbook.com ina anwani 135.197.17.100

    macosx% udpcli02 135.197.17.100

    jibu kutoka 172.24.37.94:7 (kupuuzwa)

    Kulingana na Mtini. 1.7 unaweza kuona kuwa tumeweka anwani ya IP kutoka kwa subnet tofauti. Hii kawaida inakubalika. Utekelezaji mwingi wa IP unakubali datagramu ya IP inayoingia inayolengwa kwa anwani zozote za IP za mwenyeji, bila kujali kiolesura ambacho inafika. RFC 1122 inaita hii mfano dhaifu wa mfumo wa mwisho. Ikiwa mfumo ungetekeleza kile ambacho hati hii inakiita kielelezo dhabiti cha mfumo wa mwisho, inakubali datagramu inayoingia ikiwa tu datagramu itafika kwenye kiolesura ambacho kinakusudiwa.

    Anwani ya IP iliyorejeshwa na chaguo za kukokotoa recvfrom (anwani ya IP ya chanzo cha datagramu ya UDP) si anwani ya IP ambayo tulituma datagramu. Seva inapotuma majibu yake, anwani ya IP ya mpokeaji ni 172.24.37.94. Kitendaji cha kuelekeza kernel kwenye nodi freebsd4 huchagua 172.24.37.94 kama kiolesura kinachotoka. Kwa kuwa seva haijahusisha anwani ya IP na tundu lake (seva imehusisha anwani ya jumla na tundu lake, ambalo tunaweza kuthibitisha kwa kuendesha programu ya netstat kwenye nodi ya freebsd4), kernel huchagua anwani ya chanzo ya datagram ya IP. Anwani hii inakuwa anwani msingi ya IP ya kiolesura kinachotoka. Ikiwa tutatuma datagramu kwa kitu kingine isipokuwa anwani ya msingi ya IP ya kiolesura (yaani, kwa jina lingine, lakabu), basi jaribio letu lililoonyeshwa katika Orodha ya 8.5 pia litashindwa.

    Suluhisho mojawapo litakuwa kwa mteja kuangalia jina la kikoa la mwenyeji anayejibu badala ya anwani yake ya IP. Ili kufanya hivyo, jina la seva linatafutwa kwenye DNS (angalia Sura ya 11) kulingana na anwani ya IP iliyorejeshwa na chaguo la kukokotoa recvfrom. Suluhisho lingine ni kufanya seva ya UDP kuunda tundu moja kwa kila anwani ya IP iliyosanidiwa kwenye mwenyeji, funga anwani hiyo ya IP kwenye tundu, piga simu kwenye kila soketi hizo zote (kusubiri baadhi yao itakuwa tayari kusoma) na kisha akajibu kutoka kwenye soketi tayari kwa kusoma. Kwa kuwa soketi iliyotumiwa kwa jibu inahusishwa na anwani ya IP ambayo ilikuwa anwani ya mwisho ya ombi la mteja (vinginevyo datagramu haingewasilishwa kwenye tundu), tunaweza kuwa na uhakika kwamba mtumaji wa jibu na mpokeaji anwani ya ombi ni sawa. Tunaonyesha mifano hii katika Sehemu ya 22.6.

    KUMBUKA

    Kwenye mfumo wa Solaris wenye violesura vingi vya mtandao, anwani ya IP ya chanzo cha jibu la seva ni anwani ya IP ya mpokeaji ya ombi la mteja. Hali iliyofafanuliwa katika sehemu hii inatumika kwa utekelezaji unaotokana na Berkeley ambao huchagua anwani ya IP ya chanzo kulingana na kiolesura kinachotoka.

    8.9. Kuanzisha mteja bila kuanzisha seva

    Tutaangalia hali inayofuata ni kuanzisha mteja bila kuanzisha seva. Ikiwa tutafanya hivi na kuingiza mstari mmoja upande wa mteja, hakuna kitakachotokea. Mteja amezuiwa milele katika simu yake ya kukokotoa recvfrom, akisubiri jibu la seva ambalo haliji. Lakini hiyo haijalishi katika mfano huu kwa sababu sasa tunatazamia kupata uelewa wa kina wa itifaki na nini kinaendelea na programu yetu ya mtandao.

    Kwanza tunaendesha tcpdump kwenye mwenyeji wa macosx, na kisha kukimbia mteja kwenye mwenyeji sawa, kuweka seva mwenyeji kwa freebsd4. Kisha tunaingia mstari mmoja, lakini mstari huu hauonyeshwa na seva.

    macosx% udpcli01 172.24.37.94

    Salamu, Dunia tunaingia kwenye mstari huu,

    lakini hatupati chochote katika kujibu

    Orodha ya 8.6 inaonyesha matokeo ya tcpdump.

    Orodha 8.6. tcpdump pato wakati mchakato wa seva haufanyi kazi kwenye nodi ya seva

    01 0.0 arp who- has freebsd4 tell macosx

    02 0.003576 (0.0036) arp jibu freebsd4 ni-saa 0:40:5:42:d6:de

    03 0.003601 (0.0000) macosx.51139 > freebsd4.9877: udp 13

    04 0.009781 (0.0062) freebsd4 >

    Jambo la kwanza tunaloona ni kwamba ombi na jibu la ARP hupokelewa kabla ya seva pangishi kutuma datagramu ya UDP kwa seva pangishi. (Tuliacha ubadilishanaji huu katika matokeo ya programu ili kusisitiza tena kwamba ombi la ARP hutumwa kila wakati na jibu hupokelewa kabla ya datagram ya IP kutumwa.)

    Kwenye mstari wa 3 tunaona kwamba datagram ya mteja imetumwa, lakini seva pangishi hujibu kwenye mstari wa 4 na ujumbe wa ICMP usioweza kufikiwa. (Urefu wa 13 unajumuisha herufi 12 pamoja na ishara mstari mpya.) Hata hivyo, hitilafu hii ya ICMP haijarejeshwa kwa mchakato wa mteja kwa sababu ambazo tutaziorodhesha kwa ufupi hapa chini. Badala yake, mteja amezuiwa kabisa katika simu ya chaguo la kukokotoa recvfrom katika Orodha 8.4. Pia tunakumbuka kuwa ICMPv6 ina hitilafu ya "Port Unreachable" sawa na ICMPv4 (ona Jedwali A.5 na A.6), kwa hivyo matokeo yaliyowasilishwa hapa yanafanana na yale ya IPv6.

    Hitilafu hii ya ICMP ni hitilafu isiyolingana. Hitilafu ilisababishwa na chaguo za kukokotoa za sendto, lakini kitendakazi cha sendto kilikamilishwa kama kawaida. Kumbuka kutoka kwa Sehemu ya 2.9 kwamba kurudi kwa kawaida kutoka kwa operesheni ya matokeo ya UDP inamaanisha tu kwamba datagramu imeongezwa kwenye foleni ya pato. safu ya kiungo. Hitilafu ya ICMP hairudishwi hadi muda fulani upite (4 ms kwa Orodha ya 8.6), ndiyo maana inaitwa asynchronous.

    Kanuni ya msingi ni kwamba makosa ya asynchronous hayarudishwi kwa soketi ya UDP isipokuwa tundu limeambatishwa. Tunaonyesha jinsi ya kupiga kazi ya kuunganisha kwenye tundu la UDP katika Sehemu ya 8.11. Sio kila mtu anaelewa kwa nini uamuzi huu ulifanywa wakati soketi zilitekelezwa kwanza. (Mazingatio ya utekelezaji yanajadiliwa kwenye ukurasa wa 748-749.) Fikiria mteja wa UDP kutuma datagrams tatu kwa seva tatu tofauti (yaani, anwani tatu tofauti za IP) juu ya soketi moja ya UDP. Mteja huingiza kitanzi ambacho huita kitendakazi cha recvfrom ili kusoma majibu. Datagramu mbili zinawasilishwa kwa usahihi (hiyo ni, seva ilikuwa ikifanya kazi kwenye nodi mbili kati ya tatu), lakini nodi ya tatu haikuwa ikiendesha seva, na nodi ya tatu inajibu kwa ujumbe wa bandari ya ICMP usioweza kufikiwa. Ujumbe huu wa hitilafu wa ICMP una kichwa cha IP na kichwa cha UDP cha datagram kilichosababisha hitilafu. (Ujumbe wa hitilafu wa ICMPv4 na ICMPv6 daima huwa na kichwa cha IP na yote au sehemu ya kichwa cha UDP ili kuruhusu mpokeaji ujumbe kubaini ni tundu gani lilisababisha hitilafu. Hii inaonyeshwa katika Mchoro 28.5 na 28.6.) Mteja aliyetuma datagramu tatu anapaswa kujua. mpokeaji wa datagramu iliyosababisha hitilafu ili kubainisha ni ipi hasa kati ya datagramu hizo tatu iliyosababisha hitilafu. Lakini kernel inawezaje kuwasilisha habari hii kwa mchakato? Kitu pekee ambacho recvfrom kinaweza kurudi ni thamani ya utofauti wa errno. Lakini chaguo za kukokotoa za recvfrom haziwezi kurudisha anwani ya IP na nambari ya bandari ya mpokeaji wa datagramu ya UDP kimakosa. Kwa hivyo, imeamuliwa kuwa makosa haya ya asynchronous yanarejeshwa kwa mchakato ikiwa tu mchakato umeambatisha tundu la UDP kwa rika moja tu maalum.

    KUMBUKA

    Linux hurejesha hitilafu nyingi za mlango wa ICMP zisizoweza kufikiwa, hata kwa tundu ambalo halijaambatishwa, isipokuwa chaguo la tundu la SO_DSBCOMPAT limewashwa. Hitilafu zote zisizoweza kufikiwa za wapokeaji zilizoonyeshwa kwenye Jedwali la 1 zinarejeshwa. A.5, isipokuwa makosa ya misimbo 0, 1, 4, 5, 11 na 12.

    Tutarudi kwenye suala la hitilafu zisizo za kawaida na soketi za UDP katika Sehemu ya 28.7 na kuonyesha njia rahisi ya kupata hitilafu hizi kwenye soketi ambayo haijaambatishwa kwa kutumia daemoni yetu wenyewe.

    8.10. Mfano wa mwisho wa seva ya mteja wa UDP

    Katika Mtini. Katika Mchoro 8.5, vitone vikubwa vyeusi vinaonyesha thamani nne zinazopaswa kuwekwa au kuchaguliwa mteja anapotuma datagramu ya UDP.

    Mchele. 8.5. Kufupisha mfano wa seva ya mteja wa UDP kutoka kwa mtazamo wa mteja

    Mteja lazima abainishe anwani ya IP ya seva na nambari ya mlango ili kuita kitendakazi cha sendto. Kwa kawaida anwani ya IP ya mteja na nambari ya bandari huchaguliwa kiotomatiki na kernel, ingawa tulibaini kuwa mteja anaweza kuita kipengele cha kumfunga. Pia tulibaini kuwa ikiwa maadili haya mawili yamechaguliwa kwa mteja na kernel, basi bandari ya mteja iliyokabidhiwa kwa nguvu huchaguliwa mara moja, mara ya kwanza sendto inaitwa, na haibadilishwi tena. Hata hivyo, anwani ya IP ya mteja inaweza kubadilika kwa kila datagramu ya UDP mteja anayotuma, ikizingatiwa kuwa mteja hafungi anwani maalum ya IP kwenye tundu kwa kutumia kipengele cha kukokotoa. Sababu imefafanuliwa katika Mtini. 8.5: Ikiwa node ya mteja ina interfaces kadhaa za mtandao, mteja anaweza kubadili kati yao (katika Mchoro 8.5, anwani moja inahusu safu ya kiungo iliyoonyeshwa upande wa kushoto, nyingine inahusu moja iliyoonyeshwa upande wa kulia). Katika hali mbaya zaidi ya hali hii, anwani ya IP ya mteja, iliyochaguliwa na kernel kulingana na safu ya kiungo inayotoka, ingebadilika kwa kila datagramu.

    Ni nini hufanyika ikiwa mteja atafunga anwani ya IP kwenye tundu lake, lakini kernel itaamua kwamba datagram inayotoka inapaswa kutumwa kutoka kwa safu nyingine ya kiungo? Katika hali hii, datagram ya IP itakuwa na anwani ya IP ya chanzo ambayo ni tofauti na anwani ya IP ya safu ya kiungo inayotoka (ona Zoezi la 8.6).

    Katika Mtini. Mchoro 8.6 unaonyesha maadili manne sawa, lakini kutoka kwa mtazamo wa seva.

    Mchele. 8.6. Kufupisha mfano wa seva ya mteja wa UDP kutoka kwa mtazamo wa seva

    Seva inaweza kujifunza angalau vigezo vinne kwa kila datagramu inayopokea: anwani ya IP ya chanzo, anwani ya IP lengwa, nambari ya kituo cha chanzo, na nambari ya bandari lengwa. Simu zinazorudisha taarifa hii kwa seva za TCP na UDP zinaonyeshwa kwenye Jedwali. 8.1.

    Jedwali 8.1. Taarifa zinazopatikana kwa seva kutoka kwa datagram ya IP inayoingia

    Seva ya TCP daima ina ufikiaji rahisi wa vipande vyote vinne vya habari kwa soketi iliyounganishwa, na maadili haya manne hubaki mara kwa mara kwa maisha ya muunganisho. Hata hivyo, katika kesi ya muunganisho wa UDP, anwani ya IP lengwa inaweza kupatikana tu kwa kuweka chaguo la tundu IP_RECVDSTADDR kwa IPv4 au IPV6_PKTINFO kwa IPv6 na kisha kupiga simu ya kitendakazi cha recvmsg badala ya chaguo la kukokotoa recvfrom. Kwa sababu UDP haina muunganisho, anwani ya IP lengwa inaweza kubadilika kwa kila datagramu inayotumwa kwa seva. Seva ya UDP pia inaweza kupokea datagramu zinazotumwa kwa mojawapo ya anwani za utangazaji za seva pangishi au anwani ya upeperushaji anuwai, ambayo tunajadili katika Sura ya 20 na 21. Tutaonyesha jinsi ya kubainisha anwani lengwa ya datagramu ya UDP katika Sehemu ya 20.2 baada ya kufafanua kipengele cha recvmsg.

    8.11. unganisha kazi ya UDP
    KUMBUKA
    KUMBUKA
    KUMBUKA

    Jedwali 8.2

    KUMBUKA

    Mchele. 8.7. Soketi iliyoambatanishwa ya UDP

    Mchele. 8.8

    Kupiga simu kuunganishwa mara nyingi kwenye soketi ya UDP

    Mchakato ulio na tundu la UDP lililounganishwa linaweza kuita tena kitendakazi cha kuunganisha kwenye tundu hilo kwa:

    c - weka anwani mpya ya IP na bandari;

    c - kata tundu.

    Kesi ya kwanza, inayobainisha rika mpya kwa tundu la UDP lililounganishwa, hutofautiana na kutumia kazi ya kuunganisha na tundu la TCP: kwa tundu la TCP, kazi ya kuunganisha inaweza kuitwa mara moja tu.

    Ili kutenganisha tundu la UDP, tunaita kipengele cha kukokotoa cha kuunganisha, lakini weka kipengele cha familia cha muundo wa anwani ya tundu (sin_family kwa IPv4 au sin6_family kwa IPv6) hadi AF_UNSPEC . Hii inaweza kusababisha hitilafu ya EAFNOSUPPORT, lakini hii ni kawaida. Ni mchakato wa kuita kitendakazi cha kuunganisha kwenye tundu la UDP ambalo tayari limeunganishwa ambayo inaruhusu tundu kukatwa.

    KUMBUKA

    Mwongozo wa BSD wa chaguo la kukokotoa la kuunganisha kwa kawaida ulisema: "Soketi za data zinaweza kuvunja miunganisho kwa kuunganisha kwa anwani zisizo sahihi, kama vile anwani tupu." Kwa bahati mbaya, hakuna mwongozo unaosema ni nini "anwani tupu", wala haisemi kuwa kosa hurejeshwa kama matokeo (ambayo ni ya kawaida). Kiwango cha POSIX kinasema kwa uwazi kwamba familia ya anwani lazima iwekwe kuwa AF_UNSPEC, lakini kisha inasema kwamba simu hii ya kuunganisha inaweza kurudisha au isirudishe hitilafu ya EAFNOSUPPORT.

    Utendaji

    Wakati programu inaita kitendakazi cha sendto kwenye soketi isiyoambatishwa ya UDP, utekelezaji wa kernel inayotokana na Berkeley huunganishwa kwa muda kwenye tundu, kutuma datagram, na kisha kutenganisha kutoka kwenye soketi. Kwa hivyo, kupiga simu kitendakazi cha sendto kutuma datagrams mbili kwa mfuatano kwenye tundu ambalo halijaunganishwa inajumuisha hatua sita zifuatazo zinazofanywa na kernel:

    c - kuunganisha tundu;

    c - pato la datagram ya kwanza;

    c - kukata tundu;

    c - kuunganisha tundu;

    c - pato la datagram ya pili;

    c - kukata tundu.

    KUMBUKA

    Jambo lingine la kuzingatia ni idadi ya utaftaji kwenye jedwali la uelekezaji. Muunganisho wa kwanza wa muda hutafuta anwani ya IP lengwa katika jedwali la kuelekeza na kuhifadhi (kache) maelezo haya. Muunganisho wa pili wa muda unabainisha kuwa anwani ya mpokeaji inalingana na anwani iliyoakibishwa kutoka kwa jedwali la kuelekeza (tunachukulia kuwa vitendaji vyote viwili vya sendto vimepewa mpokeaji sawa) na haihitaji kuangalia tena jedwali la uelekezaji.

    Programu inapojua kuwa itatuma datagramu nyingi kwa programu rika moja, ni bora zaidi kuambatisha kwa uwazi tundu. Simu ya kuunganisha ikifuatiwa na simu mbili za kuandika sasa itahusisha hatua zifuatazo zinazofanywa na kernel:

    c - kuunganisha tundu;

    c - pato la datagram ya kwanza;

    c - matokeo ya datagram ya pili.

    Katika kesi hii, kernel inakili muundo wa anwani ya tundu iliyo na anwani ya IP ya marudio na bandari mara moja tu, na wakati kutuma inaitwa mara mbili, kunakili hufanywa mara mbili. B anabainisha kuwa kuunganisha kwa muda soketi ya UDP iliyokatwa huchangia takriban theluthi moja ya gharama ya kila uhamisho wa UDP.

    8.12. dg_cli kazi (inaendelea)

    Wacha turudi kwenye chaguo la kukokotoa la dg_cli lililoonyeshwa kwenye Orodha 8.4 na tuiandike upya ili kuita kitendakazi cha kuunganisha. Orodha ya 8.7 inaonyesha kipengele kipya.

    Orodha 8.7. Chaguo la kukokotoa la dg_cli kuita kitendakazi cha kuunganisha

    //udpcliserv/dgcliconnect.c

    1 #pamoja na "unp.h"

    3 dg_cli(FILE *fp, int sockfd, const SA *pseraddr, socklen_t servlen)

    6 char sendline, recvline;

    7 Unganisha(sockfd, (SA*)pseraddr, servlen);

    8 huku (Fgets(sendline, MAXLINE, fp) != NULL) (

    9 Andika(sockfd, sendline, strlen(sendline));

    10 n = Soma(sockfd, recvline, MAXLINE);

    11 recvline[n] = 0; /* kubatilisha */

    Fputs 12(recvline, stdout);

    Mabadiliko kutoka kwa toleo la awali ni nyongeza ya simu ya kukokotoa na uingizwaji wa simu za kukokotoa za sendto na recvfrom na simu za kukokotoa za kuandika na kusoma. Chaguo za kukokotoa za dg_cli husalia kuwa itifaki huru kwa sababu haiangalii muundo wa anwani ya tundu iliyopitishwa kwa chaguo la kukokotoa la kuunganisha. Kazi kuu ya mteja wetu, iliyoonyeshwa katika Orodha ya 8.3, inabaki kuwa ile ile.

    Ikiwa tutaendesha programu kwenye mwenyeji wa macosx, tukibainisha anwani ya IP ya mwenyeji wa freebsd4 (ambayo haiendeshi seva yetu kwenye bandari 9877), tunapata matokeo yafuatayo:

    macosx% udpcli04 172.24.37.94

    Salamu, Dunia

    kosa la kusoma: Muunganisho umekataliwa

    Jambo la kwanza tunalogundua ni kwamba hatupati hitilafu tunapoanzisha mchakato wa mteja. Hitilafu hutokea tu baada ya kutuma datagram ya kwanza kwa seva. Ni utumaji wa datagramu hii ambayo husababisha hitilafu ya ICMP kutoka kwa seva pangishi. Lakini mteja wa TCP anapopiga simu connect , ikibainisha nodi ya seva ambayo haiendeshi mchakato wa seva, unganisha hurejesha hitilafu kwa sababu simu ya kuunganisha husababisha pakiti ya kwanza ya kupeana mkono kwa njia tatu ya TCP kutumwa, na ni pakiti hii ambayo husababisha sehemu ya RST ipokewe kutoka kwa rika (tazama sehemu ya 4.3).

    Orodha ya 8.8 inaonyesha matokeo ya tcpdump.

    Orodha 8.8. Pato kutoka kwa tcpdump wakati wa kuendesha kazi ya dg_cli

    macosx% tcpdump

    01 0.0 macosx.51139 > freebsd4 9877:udp 13

    02 0.006180 (0.0062) freebsd4 > macosx: icmp: freebsd4 udp port 9877 isiyoweza kufikiwa

    Katika meza A.5 pia tunaona kwamba kernel inahusisha hitilafu ya ICMP na hitilafu ya ECONNREFUSED, ambayo inalingana na matokeo ya mfuatano wa ujumbe uliokataliwa wa Muunganisho na chaguo za kukokotoa err_sys.

    KUMBUKA

    Kwa bahati mbaya, sio punje zote zinarudi Ujumbe wa ICMP tundu la UDP, kama tulivyoonyesha katika sehemu hii. Kwa kawaida, kokwa zinazotokana na Berkeley hurejesha kosa hili, lakini kokwa za System V hazirudishi. Kwa mfano, ikiwa tutatumia mteja sawa kwenye seva pangishi ya Solaris 2.4 na kutumia chaguo za kukokotoa kuunganisha kwenye seva pangishi ambayo haiendeshi seva yetu, kisha kwa kutumia tcpdump tunaweza kuthibitisha kwamba hitilafu isiyoweza kufikiwa ya mlango wa ICMP inarudishwa na seva pangishi, lakini inayosababishwa na kitendakazi cha kusoma kwa mteja hamalizi kamwe. Hali hii imerekebishwa katika Solaris 2.5. UnixWare hairejeshi hitilafu, wakati AIX, Digital Unix, HP-UX na Linux zinafanya.

    8.13. Ukosefu wa udhibiti wa mtiririko katika UDP

    Orodha 8.9

    //udpcliserv/dgcliloop1.c

    1 #pamoja na "unp.h"

    8char sendline;

    Orodha 8.10

    //udpcliserv/dgecholoop1.c

    1 #pamoja na "unp.h"

    3 hesabu ya int tuli;

    7 socklen_t len;

    8 char mesg;

    11 len = clilen;

    17 recvfrom_int(int signo)

    Kuorodhesha 8.11. Pato kwenye nodi ya seva

    freebsd % netstat -s -p udp

    Datagramu 71208 zimepokelewa

    0 yenye kichwa kisicho kamili

    0 na uga mbaya wa urefu wa data

    0 na hundi mbaya

    0 bila hundi

    832 ilishuka kwa sababu ya kutokuwa na tundu

    0 sio kwa pcb ya haraka

    Pato la data ya 137685

    freebsd % udpser06 zindua seva yetu

    mteja hutuma datagrams

    ^C

    freebsd % netstat -s -p udp

    Datagramu 73208 zimepokelewa

    0 yenye kichwa kisicho kamili

    0 na uga mbaya wa urefu wa data

    0 na hundi mbaya

    0 bila hundi

    832 ilishuka kwa sababu ya kutokuwa na tundu

    Datagramu 16 za utangazaji/upeperushaji nyingi zimeshuka kwa sababu ya kutokuwa na tundu

    0 sio kwa pcb ya haraka

    Pato la data ya 137685

    aix % udpser06

    ^?

    kupokea datagram 2000

    Soketi ya UDP ya kupokea bafa

    Idadi ya datagramu za UDP zilizowekwa kwenye foleni kwa soketi fulani hupunguzwa na saizi ya bafa yake ya kupokea. Tunaweza kubadilisha hii kwa kutumia chaguo la tundu la SO_RCVBUF, kama tulivyoonyesha katika sehemu ya 7.5. Kwenye FreeBSD, soketi chaguo-msingi ya UDP ya kupokea bafa ni baiti 42,080, ambayo inaruhusu datagramu 30 pekee kati ya baiti 1400 kuhifadhiwa. Ikiwa tutaongeza saizi ya bafa ya soketi, tunaweza kutarajia seva kupokea datagramu za ziada. Kuorodhesha 8.12 ni chaguo za kukokotoa za dg_echo zilizorekebishwa kutoka kwa Orodha ya 8.10 ambayo huongeza ukubwa wa bafa ya soketi hadi 240 KB. Ikiwa tutaendesha seva hii kwenye mfumo wa Jua na mteja kwenye mfumo wa RS/6000, hesabu ya datagramu iliyopokewa itakuwa 103. Kwa kuwa hii ni bora kidogo kuliko mfano wa awali wenye saizi chaguomsingi ya bafa, ni wazi kuwa bado tuko. hakupata suluhu la tatizo.

    Orodha 8.12. dg_echo kitendakazi, ambacho huongeza saizi ya bafa ya tundu

    //udpcliserv/dgecholooor2.c

    1 #pamoja na "unp.h"

    2 utupu tuli recvfrom_int(int);

    3 hesabu ya int tuli;

    5 dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)

    8 socklen_t len;

    9 char mesg;

    Mawimbi 10(SIGINT, recvfrom_int);

    11 n = 240 * 1024;

    12 Setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));

    14 len = clilen;

    15 Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);

    20 recvfrom_int(int signo)

    22 printf("\nimepokea %d datagrams\n", count);

    KUMBUKA

    Kwa nini tunaweka saizi ya bafa ya soketi kuwa baiti 240G-1024 katika Orodha ya 8.12? Soketi chaguo-msingi ya upeo wa ukubwa wa bafa katika BSD/OS 2.1 ni baiti 262,144 (256G-1024), lakini kutokana na jinsi bufa inavyogawiwa kwenye kumbukumbu (ilivyoelezwa katika Sura ya 2), kwa kweli ina mipaka ya baiti 246,723. Nyingi zaidi mifumo ya mapema, kulingana na 4.3BSD, ilipunguza ukubwa wa bafa ya soketi hadi takriban baiti 52,000.

    8.14. Kufafanua kiolesura kinachotoka kwa UDP

    Unaweza pia kutumia soketi ya UDP iliyoambatishwa kubainisha kiolesura kinachotoka ambacho kitatumika kutuma datagramu kwa mpokeaji mahususi. Hii ni kwa sababu ya athari ya upande wa kazi ya unganisho inayotumika kwa tundu la UDP: kernel huchagua anwani ya IP ya ndani (ikizingatiwa kuwa mchakato bado haujaita bind ili kuiweka wazi). Anwani ya eneo huchaguliwa kwa kuangalia anwani lengwa kwenye jedwali la kuelekeza, kuchukua anwani ya msingi ya IP ya kiolesura ambacho, kulingana na jedwali, datagramu zitatumwa.

    Orodha ya 8.13 inaonyesha programu rahisi ya UDP inayounganishwa kwa anwani fulani ya IP kwa kutumia chaguo la kukokotoa la kuunganisha na kisha kuita chaguo la kukokotoa la getsockname, ikitoa anwani ya IP ya ndani na mlango.

    Orodha 8.13. Programu ya UDP inayotumia kipengele cha kuunganisha ili kuamua kiolesura kinachotoka

    //udpcliserv/udpcli09.c

    1 #pamoja na "unp.h"

    3 kuu (int argc, char **argv)

    6 socklen_t len;

    7 struct sockaddr_in cliaddr, servaddr;

    8 ikiwa (argc!= 2)

    9 err_quit("matumizi: udpcli");

    10 sockfd = Soketi(AF_INET, SOCK_DGRAM, 0);

    11 bzero(&servaddr, sizeof(servaddr));

    12 servaddr.sin_family = AF_INET;

    13 servaddr.sin_port = htons(SERV_PORT);

    14 Inet_pton(AF_INET, argv, &servaddr.sin_addr);

    15 Unganisha(sockfd, (SA*)&servaddr, sizeof(servaddr));

    16 len = sizeof(cliaddr);

    17 Getsockname(sockfd, (SA*)&cliaddr, &len);

    18 printf("anwani ya eneo %s\n", Sock_ntop((SA*)&cliaddr, len));

    Ikiwa tutaendesha programu kwenye seva pangishi ya freebsd iliyo na miingiliano mingi ya mtandao, tutapata matokeo yafuatayo:

    freebsd % udpcli09 206.168.112.96

    anwani ya ndani 12.106.32.254:52329

    freebsd % udpcli09 192.168.42.2

    anwani ya ndani 192.168.42.1:52330

    freebsd % udpcli09 127.0.0.1

    anwani ya eneo 127.0.0.1:52331

    Kulingana na Mtini. 1.7 unaweza kuona kwamba tunapoendesha programu mara mbili za kwanza, hoja mstari wa amri ni anwani ya IP katika mitandao mbalimbali Ethaneti. Kernel inapeana anwani ya IP ya ndani kwa anwani ya kiolesura cha msingi katika mwafaka Mitandao ya Ethernet. Wakati wa kupiga simu unganisha kwenye soketi ya UDP, hakuna kitu kinachotumwa kwa mwenyeji huyo - ni operesheni ya ndani kabisa ambayo huhifadhi anwani ya IP ya wenzao na bandari. Pia tunaona kuwa kupiga simu kuunganishwa kwenye soketi ya UDP ambayo haijaunganishwa pia inapeana mlango uliowekwa kwa nguvu kwenye tundu.

    KUMBUKA

    Kwa bahati mbaya, teknolojia hii haifanyi kazi katika utekelezaji wote, ambayo ni kweli hasa kwa kernels zinazotokana na SVR4. Kwa mfano, hii haifanyi kazi kwenye Solaris 2.5, lakini inafanya kazi kwenye AIX, Digital Unix, Linux, MacOS X na Solaris 2.6.

    8.15. Seva ya mwangwi ya TCP na UDP kwa kutumia kitendakazi cha kuchagua

    Sasa tutaunganisha seva yetu ya mwangwi ya TCP kutoka Sura ya 5 na seva yetu ya mfululizo ya mwangwi ya UDP kutoka sura hii hadi kwenye seva moja inayotumia chaguo la kukokotoa ili kuzidisha soketi za TCP na UDP. Orodha ya 8.14 inaonyesha sehemu ya kwanza ya seva hii.

    Orodha 8.14. Sehemu ya kwanza ya usindikaji wa seva ya echo ya soketi za TCP na UDP kwa kutumia chaguo la kukokotoa

    //udpcliserv/udpsservselect01.c

    1 #pamoja na "unp.h"

    3 kuu (int argc, char **argv)

    5 int listenfd, connfd, udpfd, nready, maxfdp1;

    6 char mesg;

    7 pid_t childpid;

    10 socklen_t len;

    11 const int on = 1;

    12 struct sockaddr_in cliaddr, servaddr;

    13 batili sig_chld(int);

    14 /* unda soketi ya kusikiliza ya TCP */

    15 listenfd = Soketi(AF_INET, SOCK_STREAM, 0);

    16 bzero(&servaddr, sizeof(servaddr));

    17 servaddr.sin_family = AF_INET;

    18 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    19 servaddr.sin_port = htons(SERV_PORT);

    20 Setsockopt(sikilizafd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(imewashwa));

    21 Bind(sikilizafd, (SA*)&servaddr, sizeof(servaddr));

    22 Sikiliza(sikilizafd, SIKILIZA);

    23 /* tengeneza tundu la UDP */

    24 udpfd = Soketi(AF_INET, SOCK_DGRAM, 0);

    25 bzero(&servaddr, sizeof(servaddr));

    26 servaddr.sin_family = AF_INET;

    27 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    28 servaddr.sin_port = htons(SERV_PORT);

    29 Bind(udpfd, (SA*)&servaddr, sizeof(servaddr));

    Kuunda Soketi ya Kusikiliza ya TCP

    14-22 Soketi ya kusikiliza ya TCP imeundwa na kuhusishwa na mlango unaojulikana awali kwenye seva. Tunaweka chaguo la tundu SO_REUSEADDR ikiwa kuna viunganisho kwenye bandari hii.

    Kuunda tundu la UDP

    23-29 Soketi ya UDP pia imeundwa na kuhusishwa na bandari sawa. Hata kama lango lile lile linatumika kwa soketi za TCP na UDP, hakuna haja ya kuweka chaguo la tundu la SO_REUSEADDR kabla ya simu hii kufunga kwa sababu Bandari za TCP usitegemee bandari za UDP.

    Orodha ya 8.15 inaonyesha sehemu ya pili ya seva yetu.

    Orodha 8.15. Nusu ya pili ya usindikaji wa seva ya echo TCP na UDP kwa kutumia chaguo la kuchagua

    udpcliserv/udpserselect01.c

    30 Ishara(SIGCHLD, sig_chld); /* haja ya kupiga simu waitpid() */

    31 FD_ZERO(&rset);

    32 maxfdp1 = max(sikilizafd, udpfd) + 1;

    34 FD_SET(sikilizafd, &rset);

    35 FD_SET(udpfd, &rset);

    36 ikiwa ((nready = select(maxfdp1, &rset, NULL, NULL, NULL))

    37 ikiwa (errno == EINTR)

    38 kuendelea; /* kurudi kwa () */

    40 err_sys("chagua kosa");

    42 ikiwa (FD_ISSET(sikilizafd, &rset)) (

    43 len = sizeof(cliaddr);

    44 connfd = Kubali(sikilizafd, (SA*)&cliaddr, &len);

    45 ikiwa ((childpid = Uma()) == 0) ( /* mchakato wa mtoto */

    46 Funga(sikilizafd); /* hufunga tundu la kusikiliza */

    47 str_echo(connfd); /* Inachakata ombi */

    50 Funga(connfd); /* mzazi hufunga tundu lililoambatishwa */

    52 ikiwa (FD_ISSET(udpfd, &rset)) (

    53 len = sizeof(cliaddr);

    54 n = Recvfrom(udpfd, mesg, MAXLINE, 0, (SA*)&cliaddr, &len);

    55 Sendto(udpfd, mesg, n, 0, (SA*)&cliaddr, len);

    Inasakinisha kidhibiti cha mawimbi cha SIGCHLD

    30 Kidhibiti kimesakinishwa kwa mawimbi ya SIGCHLD kwa sababu miunganisho ya TCP itashughulikiwa na mchakato wa mtoto. Tulionyesha kidhibiti hiki cha mawimbi katika Orodha ya 5.8.

    Inajitayarisha Kupiga Kazi ya Chagua

    31-32 Tunaanzisha seti ya maelezo kwa kazi ya kuchagua na kuhesabu upeo wa maelezo mawili, ambayo tutasubiri wakati tayari.

    Kupigia simu kitendakazi cha kuchagua

    34-41 Tunaita kipengele cha kuchagua, tukisubiri tundu la TCP au soketi ya UDP tunayosikiliza ili kuwa tayari kusoma. Kwa kuwa kidhibiti chetu cha mawimbi cha sig_chld kinaweza kughairi simu iliyochaguliwa ya kukokotoa, tunashughulikia hitilafu ya EINTR.

    Inashughulikia muunganisho mpya wa mteja

    42-51 Tunatumia kitendakazi cha kukubali kukubali muunganisho mpya wa mteja, na wakati tundu la kusikiliza la TCP liko tayari kusomwa, tunatumia kitendakazi cha uma ili kuibua mchakato wa mtoto na kuita kitendakazi chetu cha str_echo kwenye mchakato wa mtoto. Huu ni mlolongo sawa wa hatua tulizofuata katika Sura ya 5.

    Inachakata datagramu inayoingia

    52-57 Ikiwa tundu la UDP liko tayari kusomwa, datagram imefika. Tunaisoma kwa kutumia kipengele cha recvfrom na kuituma kwa mteja kwa kutumia kitendakazi cha sendto.

    8.16. Muhtasari

    Kubadilisha mteja wetu wa mwangwi na seva ya mwangwi kutumia UDP badala ya TCP ilikuwa rahisi. Lakini wakati huo huo tulipoteza fursa nyingi zilizotolewa Itifaki ya TCP: kugundua pakiti zilizopotea na kutuma tena, kuangalia ikiwa pakiti zinatoka kwa interlocutor sahihi, nk. Tutarejea kwenye mada hii katika Sehemu ya 22.5 na kuona jinsi tunavyoweza kuboresha utegemezi wa ombi la UDP.

    Soketi za UDP zinaweza kutoa makosa ya asynchronous, ambayo ni makosa ambayo yanaripotiwa muda baada ya pakiti kutumwa. Soketi za TCP kila wakati zinaripoti kwa programu, lakini kwa UDP soketi lazima iunganishwe ili kupokea hitilafu hizi.

    UDP haina udhibiti wa mtiririko, ambayo ni rahisi sana kuonyesha. Hili kwa kawaida sio tatizo kwani programu nyingi za UDP hujengwa kwa kutumia kielelezo cha kujibu ombi na hazikusudiwa kusambaza. kiasi kikubwa data.

    Kuna mambo kadhaa ya kuzingatia unapoandika maombi ya UDP, lakini tutayashughulikia katika Sura ya 22 baada ya kuangazia utendakazi wa violesura, utangazaji na utangazaji anuwai.

    Mazoezi

    1. Tuseme tuna maombi mawili, moja inatumia TCP na nyingine inatumia UDP. Bafa ya kupokea kwa soketi ya TCP ina baiti 4096 za data, na bafa ya kupokea kwa soketi ya UDP ina datagramu mbili za baiti 2048. Programu ya TCP huita kitendakazi cha kusoma na hoja ya tatu ya 4096, na programu ya UDP huita kitendakazi cha recvfrom kwa hoja ya tatu ya 4096. Je, kuna tofauti yoyote kati ya simu hizi?

    2. Katika Uorodheshaji 8.2, nini kitatokea ikiwa tutabadilisha hoja ya mwisho ya kitendakazi cha sendto (tulichoipa lebo len) na clilen ya hoja?

    3. Kusanya na kuendesha seva ya UDP kutoka kwenye Orodha 8.1 na 8.4, na kisha mteja kutoka kwenye Orodha 8.3 na 8.4. Hakikisha mteja na seva wanafanya kazi pamoja.

    4. Endesha programu ya ping kwenye dirisha moja, ukibainisha -i chaguo 60 (tuma pakiti moja kila sekunde 60; mifumo mingine hutumia swichi ya I badala ya i), chaguo la -v (chapisha ujumbe wote wa makosa ya ICMP), na uweke. anwani ya kitanzi yenyewe ( kawaida 127.0.0.1). Tutatumia programu hii kuona hitilafu isiyoweza kufikiwa ya mlango wa ICMP iliyorejeshwa na seva pangishi. Kisha endesha mteja wetu kutoka kwa zoezi la awali kwenye dirisha lingine, ukibainisha anwani ya IP ya nodi fulani ambayo haiendeshi seva. Nini kinaendelea?

    5. Kuangalia Mtini. 8.3, tulisema kwamba kila tundu la TCP lililounganishwa lina bafa yake ya kupokea. Je, unadhani soketi ya kusikiliza ina bafa yake ya kupokea?

    6. Tumia programu ya soksi (angalia Sehemu B.3) na zana kama vile tcpdump (angalia Sehemu B.5) ili kuthibitisha taarifa katika Sehemu ya 8.10: ikiwa mteja anatumia kipengele cha kuunganisha ili kufunga anwani ya IP kwenye tundu lake, lakini hutuma datagramu inayotokana na kiolesura tofauti, basi datagramu inayotokana ina anwani ya IP ambayo ilihusishwa na tundu, hata kama hailingani na kiolesura cha asili.

    7. Kukusanya programu kutoka kwa Sehemu ya 8.13 na kukimbia mteja na seva kwenye nodes tofauti. Weka printf kwenye mteja kila wakati datagram inapoandikwa kwenye tundu. Je, hii inabadilisha asilimia ya pakiti zilizopokelewa? Kwa nini? Piga simu printf kutoka kwa seva kila wakati datagramu inasomwa kutoka kwa soketi. Je, hii inabadilisha asilimia ya pakiti zilizopokelewa? Kwa nini?

    8. Ni nini urefu mkubwa zaidi, ambayo tunaweza kupitisha kwa kazi ya sendto kwa tundu la UDP/IPv4, yaani, ni nini idadi kubwa zaidi data inayoweza kutoshea kwenye datagramu ya UDP/IPv4? Ni mabadiliko gani katika kesi ya UDP/IPv6?

    Rekebisha Orodha 8.4 ili kutuma datagramu moja ya UDP ukubwa wa juu, isome tena na uchapishe idadi ya baiti zilizorejeshwa na kitendakazi cha recvfrom.

    9. Rekebisha Orodha ya 8.15 ili ilingane na RFC 1122: IP_RECVDSTADDR inapaswa kutumika kwa soketi ya UDP.

    Mwishoni mwa Sehemu ya 8.9, tulitaja kuwa makosa ya asynchronous hayarudishwi kwenye tundu la UDP ikiwa tundu halijaunganishwa. Tunaweza kuita kiunganishi kwenye tundu la UDP (tazama sehemu ya 4.3). Lakini hii haitasababisha chochote kama muunganisho wa TCP: hakuna kushikana mikono kwa njia tatu. Kernel hukagua tu kuona ikiwa lengwa linajulikana kuwa haliwezi kufikiwa, kisha hurekodi anwani ya IP ya rika na nambari ya bandari, ambayo iko katika muundo wa anwani ya tundu iliyopitishwa kwa kazi ya kuunganisha, na mara moja inarudisha udhibiti kwenye mchakato wa kupiga simu.

    KUMBUKA

    Kupakia kitendakazi cha kuunganisha kwa kipengele hiki kipya kwa soketi za UDP kunaweza kutatanisha. Ikiwa mkataba ni kwamba sockname ni anwani ya itifaki ya ndani na jina la mtumiaji ni anwani ya itifaki ya mbali, basi chaguo hili la kukokotoa lingeitwa vyema setpeername. Vivyo hivyo, chaguo la kukokotoa lingeitwa vyema zaidi jinackname.

    Kwa kuzingatia hili, ni muhimu kuelewa tofauti kati ya aina mbili za soketi za UDP.

    c– Soketi ya UDP ambayo haijaunganishwa ni soketi chaguo-msingi ya UDP iliyoundwa.

    c– Soketi iliyounganishwa ya UDP ni matokeo ya kuita kitendakazi cha unganisho kwenye soketi ya UDP.

    Tundu la UDP lililounganishwa lina tofauti tatu kutoka kwa tundu lisilounganishwa, ambalo linaundwa kwa default.

    1. Hatuwezi tena kuweka anwani ya IP lengwa na mlango kwa ajili ya operesheni ya kutoa. Hiyo ni, tunatumia kitendakazi cha kuandika au kutuma badala ya kitendakazi cha sendto. Chochote kilichoandikwa kwenye soketi ya UDP iliyoambatishwa hutumwa kiotomatiki kwa anwani (kama vile anwani ya IP na mlango) iliyotolewa na kipengele kuunganisha.

    KUMBUKA

    Sawa na TCP, tunaweza kupigia simu kitendakazi cha sendto kwenye soketi ya UDP iliyoambatishwa, lakini hatuwezi kubainisha anwani lengwa. Hoja ya tano kwa kipengele cha kukokotoa kutuma (kielekezi kwa muundo wa anwani ya tundu) lazima iwe kielekezi, na hoja ya sita (ukubwa wa muundo wa anwani ya tundu) lazima iwe batili. Kiwango cha POSIX kinabainisha kuwa wakati hoja ya tano ni kielekezi kisicho na maana, hoja ya sita inapuuzwa.

    2. Badala ya chaguo za kukokotoa recvfrom, tunatumia kitendakazi cha kusoma au recv. Datagramu pekee zilizorejeshwa na kernel kwa operesheni ya ingizo kwenye soketi iliyounganishwa ya UDP ni datagramu zinazotoka kwa anwani iliyobainishwa katika chaguo la kukokotoa la kuunganisha. Datagramu zinazolengwa kwa anwani ya itifaki ya ndani ya soketi ya UDP iliyounganishwa (kama vile anwani ya IP na mlango) lakini inayotoka kwa anwani ya itifaki isipokuwa ile ambayo tundu iliunganishwa kwa kutumia kitendakazi cha kuunganisha hazitumwi kwenye soketi iliyounganishwa. Hii inazuia soketi ya UDP iliyoambatishwa ili kuiruhusu kubadilishana datagramu na rika moja tu.

    KUMBUKA

    Kwa usahihi, datagrams hubadilishwa na anwani moja tu ya IP, na si kwa interlocutor moja, kwa kuwa inaweza kuwa anwani ya IP ya multicast, na hivyo kuwakilisha kundi la interlocutors.

    3. Hitilafu za Asynchronous zinarejeshwa kwa mchakato tu kwa uendeshaji kwenye tundu la UDP lililounganishwa. Kama matokeo, kama tulivyokwisha sema, tundu la UDP ambalo halijaunganishwa haipokei makosa yoyote ya asynchronous.

    Katika meza 8.2 huleta pamoja sifa zilizoorodheshwa katika aya ya kwanza kama inavyotumika kwa 4.4BSD.

    Jedwali 8.2. Soketi za TCP na UDP: anwani ya itifaki lengwa inaweza kubainishwa

    KUMBUKA

    POSIX inabainisha kuwa operesheni ya kipini ambayo haibainishi anwani lengwa kwenye soketi isiyoambatishwa ya UDP lazima irudishe hitilafu ya ENOTCONN badala ya hitilafu ya EDESTADDRREQ.

    Solaris 2.5 huruhusu utendakazi wa sendto, ambao hubainisha anwani lengwa ya soketi ya UDP iliyoambatishwa. POSIX inabainisha kuwa hitilafu ya EISCONN inapaswa kurejeshwa katika hali hii.

    Katika Mtini. Sehemu ya 8.7 inatoa muhtasari wa taarifa kuhusu soketi ya UDP iliyoambatishwa.

    Mchele. 8.7. Soketi iliyoambatanishwa ya UDP

    Maombi huita kazi ya kuunganisha, ikibainisha anwani ya IP na nambari ya bandari ya interlocutor. Kisha hutumia vipengele vya kusoma na kuandika ili kubadilishana data na mhusika mwingine.

    Datagramu zinazotoka kwa anwani ya IP au mlango mwingine wowote (ambao tunaashiria kama "???" kwenye Mchoro 8.7) hazitumwi kwa soketi iliyoambatishwa kwa sababu anwani ya IP ya chanzo au mlango wa UDP hailingani na anwani ya itifaki. imeunganishwa kwa kutumia kitendakazi cha kuunganisha. Datagramu hizi zinaweza kuwasilishwa kwa soketi nyingine ya UDP kwenye seva pangishi. Ikiwa hakuna soketi nyingine inayolingana ya datagramu inayoingia, UDP itaipuuza na kutoa ujumbe wa mlango wa ICMP usioweza kufikiwa.

    Kwa muhtasari wa yaliyo hapo juu, tunaweza kusema kwamba mteja wa UDP au seva inaweza kuita kitendakazi cha kuunganisha ikiwa tu mchakato huo unatumia tundu la UDP kuwasiliana na mpatanishi mmoja tu. Kwa kawaida ni kiteja cha UDP kinachoita kitendakazi cha kuunganisha, lakini kuna programu ambazo seva ya UDP huwasiliana na mteja mmoja kwa muda mrefu (kama vile TFTP), ambapo mteja na seva huita muunganisho. kazi.

    Mfano mwingine wa mwingiliano wa muda mrefu ni DNS (Mchoro 8.8).

    Mchele. 8.8. Mfano wa wateja wa DNS na seva na kazi ya kuunganisha

    Kiteja cha DNS kinaweza kusanidiwa kutumia seva moja au zaidi, kwa kawaida kwa kuorodhesha anwani za IP za seva kwenye faili ya /etc/resolv.conf. Ikiwa kuna seva moja tu iliyoorodheshwa kwenye faili hii (mteja huyo ndiye mstatili wa kushoto kabisa kwenye takwimu), mteja anaweza kupiga simu ya kiunganishi, lakini ikiwa seva nyingi zimeorodheshwa (mstatili wa pili wa kulia kwenye takwimu), mteja hawezi kupiga simu. kazi ya kuunganisha. Kwa kawaida Seva ya DNS hushughulikia maombi yoyote ya mteja pia, kwa hivyo seva haziwezi kuita kazi ya unganisho.

    Sasa tutaangalia jinsi programu inavyoathiriwa na kutokuwepo kwa udhibiti wowote wa mtiririko katika UDP. Kwanza tutabadilisha utendakazi wetu wa dg_cli ili itume idadi maalum ya datagramu. Haitasoma tena kutoka kwa ingizo la kawaida. Orodha ya 8.9 inaonyesha toleo jipya la chaguo la kukokotoa. Chaguo hili la kukokotoa hutuma datagramu 2000 za UDP za baiti 1400 kila moja kwa seva.

    Orodha 8.9. Chaguo la kukokotoa la dg_cli hutuma idadi isiyobadilika ya datagramu kwa seva

    //udpcliserv/dgcliloop1.c

    1 #pamoja na "unp.h"

    2 #fafanua NDG 2000 /* nambari ya data ya kutuma */

    3 #fafanua urefu wa DGLEN 1400 /* wa kila datagramu */

    5 dg_cli(FILE *fp, int sockfd, const SA *pseraddr, socklen_t servlen)

    8char sendline;

    10 Sendto(sockfd, sendline, DGLEN, 0, pservaddr, servlen);

    Kisha tunarekebisha seva ili kupokea datagrams na kuhesabu idadi ya datagramu zilizopokelewa. Seva haionyeshi tena datagramu kwa mteja. Orodha ya 8.10 inaonyesha kazi mpya ya dg_echo. Tunapositisha mchakato wa seva kwa kubonyeza kitufe cha kukatiza kwenye terminal (ambayo husababisha ishara ya SIGINT kutumwa kwa mchakato), seva huchapisha nambari ya data iliyopokelewa na kuondoka.

    Orodha 8.10. Chaguo za kukokotoa za dg_echo, ambazo huhesabu datagramu zilizopokelewa

    //udpcliserv/dgecholoop1.c

    1 #pamoja na "unp.h"

    2 utupu tuli recvfrom_int(int);

    3 hesabu ya int tuli;

    5 dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)

    7 socklen_t len;

    8 char mesg;

    9 Mawimbi(SIGINT, recvfrom_int);

    11 len = clilen;

    12 Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);

    17 recvfrom_int(int signo)

    19 printf("\nkupokea %d datagrams\n", hesabu);

    Sasa tunaendesha seva kwenye nodi freebsd, ambayo ni kompyuta ya polepole ya SPARCStation. Tunaendesha mteja kwenye mfumo wa kasi zaidi wa RS/6000 na mfumo wa uendeshaji wa aix. Wameunganishwa moja kwa moja kwa kila mmoja kupitia kiungo cha 100 Mbit/s Ethernet. Kwa kuongezea, tunaendesha netstat -s kwenye nodi ya seva kabla na baada ya mteja na seva kuanza, kwani matokeo ya takwimu yataonyesha ni data ngapi tulizopoteza. Orodha ya 8.11 inaonyesha matokeo ya seva.

    Kuorodhesha 8.11. Pato kwenye nodi ya seva

    freebsd % netstat -s -p udp

    Datagramu 71208 zimepokelewa

    0 yenye kichwa kisicho kamili

    0 na uga mbaya wa urefu wa data

    0 na hundi mbaya

    0 bila hundi

    832 ilishuka kwa sababu ya kutokuwa na tundu

    Datagramu 16 za utangazaji/upeperushaji nyingi zimeshuka kwa sababu ya kutokuwa na tundu

    1971 ilishuka kwa sababu ya buffers kamili za soketi

    0 sio kwa pcb ya haraka

    Pato la data ya 137685

    freebsd % udpser06 zindua seva yetu

    mteja hutuma datagrams

    ^C Ili kumaliza kazi ya mteja, weka ishara yetu ya kukatiza

    freebsd % netstat -s -p udp

    Datagramu 73208 zimepokelewa

    0 yenye kichwa kisicho kamili

    0 na uga mbaya wa urefu wa data

    0 na hundi mbaya

    0 bila hundi

    832 ilishuka kwa sababu ya kutokuwa na tundu

    Datagramu 16 za utangazaji/upeperushaji nyingi zimeshuka kwa sababu ya kutokuwa na tundu

    3941 imeshuka kwa sababu ya buffers kamili za soketi

    0 sio kwa pcb ya haraka

    Pato la data ya 137685

    Mteja alituma datagrams 2000, lakini programu ya seva ilipokea tu 30 kati yao, ikimaanisha kiwango cha hasara cha 98%. Si seva wala mteja anayepokea ujumbe kwamba datagramu hizi zimepotea. Kama tulivyosema, UDP haina uwezo wa kudhibiti mtiririko - haitegemei. Kama tulivyoonyesha, ni rahisi kwa mtumaji wa UDP kufurika bafa ya mpokeaji.

    Ikiwa tunatazama matokeo ya netstat, tunaona kwamba jumla ya idadi ya datagrams zilizopokelewa na nodi ya seva (sio programu ya seva) ni 2000 (73,208 - 71,208). Kikaunta iliyodondoshwa kwa sababu ya kaunta kamili ya bafa za soketi inaonyesha ni datagram ngapi zilipokelewa na UDP na kupuuzwa kwa sababu bafa ya tundu la kupokea ilikuwa imejaa. Thamani hii ni 1970 (3941 - 1971), ambayo inapoongezwa kwa matokeo ya datagrams za maombi zilizopokelewa (30) husababisha datagrams 2000 zilizopokelewa na nodi. Kwa bahati mbaya, hesabu ya datagramu ya netstat iliyotupwa kwa sababu ya bafa kamili ni pana ya mfumo. Hakuna njia ya kuamua ni programu zipi (km ni bandari gani za UDP) zimeathiriwa.

    Idadi ya datagramu zilizopokelewa na seva katika mfano huu sio ya kuamua. Inategemea mambo mengi, kama vile mzigo wa mtandao, nodi ya mteja na upakiaji wa nodi za seva.

    Ikiwa tunaendesha mteja sawa na seva sawa, lakini wakati huu mteja yuko kwenye mfumo wa polepole wa Jua na seva iko kwenye mfumo wa kasi wa RS/6000, hakuna datagramu zinazopotea.

    aix % udpser06

    ^? baada ya mteja kumaliza kufanya kazi, ingiza ishara yetu ya kukatiza

    kupokea datagram 2000

    Mwishoni mwa Sehemu ya 8.9, tulitaja kuwa makosa ya asynchronous hayarudishwi kwenye tundu la UDP ikiwa tundu halijaunganishwa. Tunaweza kuita kiunganishi kwenye tundu la UDP (tazama sehemu ya 4.3). Lakini hii haitasababisha chochote kama muunganisho wa TCP: hakuna kushikana mikono kwa njia tatu. Kernel hukagua tu kuona ikiwa lengwa linajulikana kuwa haliwezi kufikiwa, kisha hurekodi anwani ya IP ya rika na nambari ya bandari, ambayo iko katika muundo wa anwani ya tundu iliyopitishwa kwa kazi ya kuunganisha, na mara moja inarudisha udhibiti kwenye mchakato wa kupiga simu.

    KUMBUKA

    Kupakia kitendakazi cha kuunganisha kwa kipengele hiki kipya kwa soketi za UDP kunaweza kutatanisha. Ikiwa mkataba ni kwamba sockname ni anwani ya itifaki ya ndani na jina la mtumiaji ni anwani ya itifaki ya mbali, basi chaguo hili la kukokotoa lingeitwa vyema setpeername. Vivyo hivyo, chaguo la kukokotoa lingeitwa vyema zaidi jinackname.

    Kwa kuzingatia hili, ni muhimu kuelewa tofauti kati ya aina mbili za soketi za UDP.

    c– Soketi ya UDP ambayo haijaunganishwa ni soketi chaguo-msingi ya UDP iliyoundwa.

    c– Soketi iliyounganishwa ya UDP ni matokeo ya kuita kitendakazi cha unganisho kwenye soketi ya UDP.

    Tundu la UDP lililounganishwa lina tofauti tatu kutoka kwa tundu lisilounganishwa, ambalo linaundwa kwa default.

    1. Hatuwezi tena kuweka anwani ya IP lengwa na mlango kwa ajili ya operesheni ya kutoa. Hiyo ni, tunatumia kitendakazi cha kuandika au kutuma badala ya kitendakazi cha sendto. Chochote kilichoandikwa kwenye tundu la UDP lililounganishwa hutumwa kiotomatiki kwa anwani (kama vile anwani ya IP na mlango) iliyobainishwa na chaguo la kukokotoa la kuunganisha.

    KUMBUKA

    Sawa na TCP, tunaweza kupigia simu kitendakazi cha sendto kwenye soketi ya UDP iliyoambatishwa, lakini hatuwezi kubainisha anwani lengwa. Hoja ya tano kwa kipengele cha kukokotoa kutuma (kielekezi kwa muundo wa anwani ya tundu) lazima iwe kielekezi, na hoja ya sita (ukubwa wa muundo wa anwani ya tundu) lazima iwe batili. Kiwango cha POSIX kinabainisha kuwa wakati hoja ya tano ni kielekezi kisicho na maana, hoja ya sita inapuuzwa.

    2. Badala ya chaguo za kukokotoa recvfrom, tunatumia kitendakazi cha kusoma au recv. Datagramu pekee zilizorejeshwa na kernel kwa operesheni ya ingizo kwenye soketi iliyounganishwa ya UDP ni datagramu zinazotoka kwa anwani iliyobainishwa katika chaguo la kukokotoa la kuunganisha. Datagramu zinazolengwa kwa anwani ya itifaki ya ndani ya soketi ya UDP iliyounganishwa (kama vile anwani ya IP na mlango) lakini inayotoka kwa anwani ya itifaki isipokuwa ile ambayo tundu iliunganishwa kwa kutumia kitendakazi cha kuunganisha hazitumwi kwenye soketi iliyounganishwa. Hii inazuia soketi ya UDP iliyoambatishwa ili kuiruhusu kubadilishana datagramu na rika moja tu.

    KUMBUKA

    Kwa usahihi, datagrams hubadilishwa na anwani moja tu ya IP, na si kwa interlocutor moja, kwa kuwa inaweza kuwa anwani ya IP ya multicast, na hivyo kuwakilisha kundi la interlocutors.

    3. Hitilafu za Asynchronous zinarejeshwa kwa mchakato tu kwa uendeshaji kwenye tundu la UDP lililounganishwa. Kama matokeo, kama tulivyokwisha sema, tundu la UDP ambalo halijaunganishwa haipokei makosa yoyote ya asynchronous.

    Katika meza 8.2 huleta pamoja sifa zilizoorodheshwa katika aya ya kwanza kama inavyotumika kwa 4.4BSD.

    Jedwali 8.2. Soketi za TCP na UDP: anwani ya itifaki lengwa inaweza kubainishwa

    KUMBUKA

    POSIX inabainisha kuwa operesheni ya kipini ambayo haibainishi anwani lengwa kwenye soketi isiyoambatishwa ya UDP lazima irudishe hitilafu ya ENOTCONN badala ya hitilafu ya EDESTADDRREQ.

    Solaris 2.5 huruhusu utendakazi wa sendto, ambao hubainisha anwani lengwa ya soketi ya UDP iliyoambatishwa. POSIX inabainisha kuwa hitilafu ya EISCONN inapaswa kurejeshwa katika hali hii.

    Katika Mtini. Sehemu ya 8.7 inatoa muhtasari wa taarifa kuhusu soketi ya UDP iliyoambatishwa.

    Mchele. 8.7. Soketi iliyoambatanishwa ya UDP

    Maombi huita kazi ya kuunganisha, ikibainisha anwani ya IP na nambari ya bandari ya interlocutor. Kisha hutumia vipengele vya kusoma na kuandika ili kubadilishana data na mhusika mwingine.

    Datagramu zinazotoka kwa anwani ya IP au mlango mwingine wowote (ambao tunaashiria kama "???" kwenye Mchoro 8.7) hazitumwi kwa soketi iliyoambatishwa kwa sababu anwani ya IP ya chanzo au mlango wa UDP hailingani na anwani ya itifaki. imeunganishwa kwa kutumia kitendakazi cha kuunganisha. Datagramu hizi zinaweza kuwasilishwa kwa soketi nyingine ya UDP kwenye seva pangishi. Ikiwa hakuna soketi nyingine inayolingana ya datagramu inayoingia, UDP itaipuuza na kutoa ujumbe wa mlango wa ICMP usioweza kufikiwa.

    Kwa muhtasari wa yaliyo hapo juu, tunaweza kusema kwamba mteja wa UDP au seva inaweza kuita kitendakazi cha kuunganisha ikiwa tu mchakato huo unatumia tundu la UDP kuwasiliana na mpatanishi mmoja tu. Kwa kawaida ni kiteja cha UDP kinachoita kitendakazi cha kuunganisha, lakini kuna programu ambazo seva ya UDP huwasiliana na mteja mmoja kwa muda mrefu (kama vile TFTP), ambapo mteja na seva huita muunganisho. kazi.

    Mfano mwingine wa mwingiliano wa muda mrefu ni DNS (Mchoro 8.8).

    Mchele. 8.8. Mfano wa wateja wa DNS na seva na kazi ya kuunganisha

    Kiteja cha DNS kinaweza kusanidiwa kutumia seva moja au zaidi, kwa kawaida kwa kuorodhesha anwani za IP za seva kwenye faili ya /etc/resolv.conf. Ikiwa kuna seva moja tu iliyoorodheshwa kwenye faili hii (mteja huyo ndiye mstatili wa kushoto kabisa kwenye takwimu), mteja anaweza kupiga simu ya kiunganishi, lakini ikiwa seva nyingi zimeorodheshwa (mstatili wa pili wa kulia kwenye takwimu), mteja hawezi kupiga simu. kazi ya kuunganisha. Kwa kawaida, seva ya DNS pia inashughulikia maombi yoyote ya mteja, hivyo seva haziwezi kuita kazi ya kuunganisha.

    Sasa tutaangalia jinsi programu inavyoathiriwa na kutokuwepo kwa udhibiti wowote wa mtiririko katika UDP. Kwanza tutabadilisha utendakazi wetu wa dg_cli ili itume idadi maalum ya datagramu. Haitasoma tena kutoka kwa ingizo la kawaida. Orodha ya 8.9 inaonyesha toleo jipya la chaguo la kukokotoa. Chaguo hili la kukokotoa hutuma datagramu 2000 za UDP za baiti 1400 kila moja kwa seva.

    Orodha 8.9. Chaguo la kukokotoa la dg_cli hutuma idadi isiyobadilika ya datagramu kwa seva

    //udpcliserv/dgcliloop1.c

    1 #pamoja na "unp.h"

    2 #fafanua NDG 2000 /* nambari ya data ya kutuma */

    3 #fafanua urefu wa DGLEN 1400 /* wa kila datagramu */

    5 dg_cli(FILE *fp, int sockfd, const SA *pseraddr, socklen_t servlen)

    8char sendline;

    10 Sendto(sockfd, sendline, DGLEN, 0, pservaddr, servlen);

    Kisha tunarekebisha seva ili kupokea datagrams na kuhesabu idadi ya datagramu zilizopokelewa. Seva haionyeshi tena datagramu kwa mteja. Orodha ya 8.10 inaonyesha kazi mpya ya dg_echo. Tunapositisha mchakato wa seva kwa kubonyeza kitufe cha kukatiza kwenye terminal (ambayo husababisha ishara ya SIGINT kutumwa kwa mchakato), seva huchapisha nambari ya data iliyopokelewa na kuondoka.

    Orodha 8.10. Chaguo za kukokotoa za dg_echo, ambazo huhesabu datagramu zilizopokelewa

    //udpcliserv/dgecholoop1.c

    1 #pamoja na "unp.h"

    2 utupu tuli recvfrom_int(int);

    3 hesabu ya int tuli;

    5 dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)

    7 socklen_t len;

    8 char mesg;

    9 Mawimbi(SIGINT, recvfrom_int);

    11 len = clilen;

    12 Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);

    17 recvfrom_int(int signo)

    19 printf("\nkupokea %d datagrams\n", hesabu);

    Sasa tunaendesha seva kwenye nodi freebsd, ambayo ni kompyuta ya polepole ya SPARCStation. Tunaendesha mteja kwenye mfumo wa kasi zaidi wa RS/6000 na mfumo wa uendeshaji wa aix. Wameunganishwa moja kwa moja kwa kila mmoja kupitia kiungo cha 100 Mbit/s Ethernet. Kwa kuongezea, tunaendesha netstat -s kwenye nodi ya seva kabla na baada ya mteja na seva kuanza, kwani matokeo ya takwimu yataonyesha ni data ngapi tulizopoteza. Orodha ya 8.11 inaonyesha matokeo ya seva.

    Kuorodhesha 8.11. Pato kwenye nodi ya seva

    freebsd % netstat -s -p udp

    Datagramu 71208 zimepokelewa

    0 yenye kichwa kisicho kamili

    0 na uga mbaya wa urefu wa data

    0 na hundi mbaya

    0 bila hundi

    832 ilishuka kwa sababu ya kutokuwa na tundu

    Datagramu 16 za utangazaji/upeperushaji nyingi zimeshuka kwa sababu ya kutokuwa na tundu

    1971 ilishuka kwa sababu ya buffers kamili za soketi

    0 sio kwa pcb ya haraka

    Pato la data ya 137685

    freebsd % udpser06 zindua seva yetu

    mteja hutuma datagrams

    ^C Ili kumaliza kazi ya mteja, weka ishara yetu ya kukatiza

    freebsd % netstat -s -p udp

    Datagramu 73208 zimepokelewa

    0 yenye kichwa kisicho kamili

    0 na uga mbaya wa urefu wa data

    0 na hundi mbaya

    0 bila hundi

    832 ilishuka kwa sababu ya kutokuwa na tundu

    Datagramu 16 za utangazaji/upeperushaji nyingi zimeshuka kwa sababu ya kutokuwa na tundu

    3941 imeshuka kwa sababu ya buffers kamili za soketi

    0 sio kwa pcb ya haraka

    Pato la data ya 137685

    Mteja alituma datagrams 2000, lakini programu ya seva ilipokea tu 30 kati yao, ikimaanisha kiwango cha hasara cha 98%. Si seva wala mteja anayepokea ujumbe kwamba datagramu hizi zimepotea. Kama tulivyosema, UDP haina uwezo wa kudhibiti mtiririko - haitegemei. Kama tulivyoonyesha, ni rahisi kwa mtumaji wa UDP kufurika bafa ya mpokeaji.

    Ikiwa tunatazama matokeo ya netstat, tunaona kwamba jumla ya idadi ya datagrams zilizopokelewa na nodi ya seva (sio programu ya seva) ni 2000 (73,208 - 71,208). Kikaunta iliyodondoshwa kwa sababu ya kaunta kamili ya bafa za soketi inaonyesha ni datagram ngapi zilipokelewa na UDP na kupuuzwa kwa sababu bafa ya tundu la kupokea ilikuwa imejaa. Thamani hii ni 1970 (3941 - 1971), ambayo inapoongezwa kwa matokeo ya datagrams za maombi zilizopokelewa (30) husababisha datagrams 2000 zilizopokelewa na nodi. Kwa bahati mbaya, hesabu ya datagramu ya netstat iliyotupwa kwa sababu ya bafa kamili ni pana ya mfumo. Hakuna njia ya kuamua ni programu zipi (km ni bandari gani za UDP) zimeathiriwa.

    Idadi ya datagramu zilizopokelewa na seva katika mfano huu sio ya kuamua. Inategemea mambo mengi, kama vile mzigo wa mtandao, nodi ya mteja na upakiaji wa nodi za seva.

    Ikiwa tunaendesha mteja sawa na seva sawa, lakini wakati huu mteja yuko kwenye mfumo wa polepole wa Jua na seva iko kwenye mfumo wa kasi wa RS/6000, hakuna datagramu zinazopotea.

    aix % udpser06

    ^? baada ya mteja kumaliza kufanya kazi, ingiza ishara yetu ya kukatiza

    kupokea datagram 2000