Uunganisho wa tundu. Nadharia ya mtandao na viwango vya chini. Mfano: DLL salama ya nyuzi kwa utumaji soketi

Sasisho la mwisho: 31.10.2015

Katika msingi mtandao soketi zinatokana na itifaki za TCP na UDP. Katika NET, soketi zinawakilishwa na darasa la System.NET.Sockets.Socket, ambalo hutoa kiolesura cha kiwango cha chini cha kupokea na kutuma ujumbe kwenye mtandao.

Wacha tuangalie sifa kuu za darasa hili:

    AnwaniFamily: Hurejesha anwani zote zinazotumiwa na soketi. Mali hii inawakilisha moja ya maadili yaliyofafanuliwa katika hesabu ya AnwaniFamily ya jina moja. Hesabu ina maadili 18 tofauti, ambayo hutumiwa sana ni:

    • Mtandao: Anwani ya IPv4

      InterNetworkV6: Anwani ya IPv6

      IPx: IPX au anwani ya SPX

      NetBios: Anwani ya NetBios

    Inapatikana: Hurejesha kiasi cha data kinachopatikana kwa usomaji

    Imeunganishwa: hurejesha kweli ikiwa soketi imeunganishwa kwa seva pangishi ya mbali

    LocalEndPoint: inarudi hatua ya ndani, ambayo tundu imezinduliwa na ambayo inapokea data

    Aina ya Itifaki: Hurejesha mojawapo ya thamani za hesabu za ProtocolType zinazowakilisha itifaki inayotumiwa na soketi. Kuna maadili yafuatayo yanayowezekana:

    • IPSecAuthenticationHeader (Kichwa cha IPv6 AH)

      IPSecEncapsulatingSecurityPayload (IPv6 ESP kichwa)

      IPv6DestinationOptions (kichwa cha Chaguo Lengwa la IPv6)

      IPv6FragmentHeader (Kichwa cha Kipande cha IPv6)

      IPv6HopByHopOptions (IPv6 Hop by Hop Options kichwa)

      IPv6NoNextHeader (IPv6 Hakuna kichwa kinachofuata)

      IPv6RoutingHeader

      Haijulikani (itifaki isiyojulikana)

      Haijabainishwa (itifaki isiyobainishwa)

    Kila thamani inawakilisha itifaki inayolingana, lakini inayotumika zaidi ni Tcp na Udp.

    RemoteEndPoint: inarudisha anwani ya seva pangishi ya mbali ambayo tundu limeunganishwa

    SocketType: Hurejesha aina ya tundu. Inawakilisha moja ya maadili kutoka kwa hesabu ya SocketType:

    • Dgram: Soketi itapokea na kutuma datagrams kwa Itifaki ya UDP. Aina hii soketi hufanya kazi kwa kushirikiana na aina ya itifaki - Udp na Thamani ya AnwaniFamily.InterNetwork

      Mbichi: tundu linaweza kufikia itifaki ya msingi safu ya usafiri na inaweza kutumia itifaki kama vile ICMP na IGMP kutuma ujumbe

      Rdm: tundu linaweza kuwasiliana na majeshi ya mbali bila ufungaji muunganisho wa kudumu. Ikiwa ujumbe uliotumwa na tundu hauwezi kutolewa, tundu itapokea taarifa kuhusu hili

      Seqpacket: Hutoa uhamishaji wa data wa njia mbili unaotegemewa na muunganisho unaoendelea

      Tiririsha: hutoa uhamishaji wa data wa njia mbili unaotegemewa na muunganisho wa kudumu. Mawasiliano hutumia itifaki ya TCP, kwa hivyo aina hii ya soketi inatumika pamoja na aina ya itifaki ya Tcp na thamani ya AddressFamily.InterNetwork.

      Haijulikani: Anwani ya NetBios

Unaweza kutumia mmoja wa wajenzi wake kuunda kitu cha tundu. Kwa mfano, tundu kwa kutumia itifaki ya Tcp:

Soketi ya soketi = Soketi mpya(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

Au tundu kwa kutumia itifaki ya Udp:

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

Kwa hivyo, wakati wa kuunda tundu tunaweza kutaja michanganyiko tofauti itifaki, aina za soketi, maadili kutoka kwa hesabu ya AnwaniFamily. Hata hivyo, wakati huo huo, sio mchanganyiko wote ni sahihi. Kwa hiyo, kufanya kazi kupitia itifaki ya Tcp, lazima tueleze vigezo vifuatavyo: AddressFamily.InterNetwork, SocketType.Stream na ProtocolType.Tcp. Kwa Udp, seti ya vigezo itakuwa tofauti: AddressFamily.InterNetwork, SocketType.Dgram na ProtocolType.Udp. Kwa itifaki zingine seti ya maadili itakuwa tofauti. Kwa hivyo, kutumia soketi kunaweza kuhitaji ujuzi fulani wa jinsi itifaki za mtu binafsi zinavyofanya kazi. Ingawa kuhusu Tcp na Udp kila kitu ni rahisi.

Kanuni ya jumla ya uendeshaji wa tundu

Wakati wa kufanya kazi na soketi, bila kujali itifaki zilizochaguliwa, tutategemea njia za darasa la Soketi:

    Kukubali() : inaunda kitu kipya Soketi ya kushughulikia muunganisho unaoingia

    Bind() : Hufunga kitu cha Soketi kwa mwisho wa ndani

    Close() : hufunga tundu

    Connect(): huanzisha muunganisho kwa seva pangishi ya mbali

    Sikiliza() : Huanza kusikiliza maombi yanayoingia

    Kura (): huamua hali ya tundu

    Receive() : Hupokea data

    Send() : Hutuma data

    Shutdown(): huzuia tundu kupokea na kutuma data

Kulingana na itifaki inayotumika (TCP, UDP, nk) kanuni ya jumla Kufanya kazi na soketi kutatofautiana kidogo.

Unapotumia itifaki inayohitaji uanzishaji wa muunganisho, kama vile TCP, seva lazima ipige njia ya Bind ili kuweka mahali pa kusikiliza miunganisho inayoingia na kisha kuanza kusikiliza miunganisho kwa kutumia mbinu ya Sikiliza. Ifuatayo, kwa kutumia njia ya Kukubali, unaweza kupokea maombi ya uunganisho unaoingia kwa namna ya kitu cha Soketi, ambacho hutumiwa kuingiliana na node ya mbali. Kwenye kitu kilichopokelewa cha Soketi, njia za Tuma na Pokea zinaitwa, kwa mtiririko huo, kutuma na kupokea data. Ikiwa ni muhimu kuunganisha kwenye seva, njia ya Kuunganisha inaitwa. Njia za Tuma au Pokea pia hutumiwa kubadilishana data na seva.

Ikiwa unatumia itifaki isiyo na muunganisho, kama vile UDP, basi huna haja ya kupiga njia ya Sikiliza baada ya kupiga njia ya Kuunganisha. Na katika kesi hii, njia ya ReceiveFrom hutumiwa kupokea data, na njia ya SendTo hutumiwa kutuma data.

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.

Wakati wa kwenda kwenye chumba cha upasuaji Mfumo wa UNIX fedha zimeongezwa mawasiliano ya mchakato(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 kweli inaelekeza muundo wa ndani data inayotumiwa 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 mkondo ni soketi yenye muunganisho ulioanzishwa, inayojumuisha 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 kusambaza kiasi kikubwa data, tangu uendeshaji unaohusishwa na kuanzisha uunganisho tofauti kwa kila ujumbe unaotumwa, huenda usikubalike juzuu ndogo 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 nini kwa safu ya TCP nambari fulani ka na upande mwingine hupokea ka hizi. Kwa upande mwingine, TCP huvunja data hii kwa pakiti kwa ufanisi ukubwa unaofaa, hupokea pakiti hizi kwa upande mwingine, hutoa data kutoka kwao 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 Barua pepe inatoa 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. Ikiwa hauandiki mfumo programu au programu inayofanana na analyzer ya pakiti, hutahitaji kuingia katika maelezo hayo. 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 itifaki za msingi 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 inayotumika Maombi 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.

Kawaida maombi ya seva ya mteja kwa kutumia soketi huwa na mbili maombi tofauti- mteja anayeanzisha muunganisho na lengo (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 linatekeleza darasa la msingi mkondo ambao data hutumwa na ambayo inapokelewa. Hiki ni kifupisho cha hali ya juu ambacho kinawakilisha muunganisho kwenye chaneli ya mawasiliano ya TCP/IP.
TcpClient Darasa la TcpClient linajengwa kwenye darasa la Soketi ili kutoa huduma ya TCP kwa zaidi ngazi ya juu. 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. Hasa, wito kwa mbinu za darasa hili hufanya hundi muhimu mbinu zinazohusiana na usalama, ikiwa ni pamoja na kuangalia ruhusa za usalama, baada ya hapo zinatumwa kwa wenzao wa njia hizi katika API ya Soketi za Windows.

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

Mali 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.

VSEVOLOD STAKHOV

Soketi Programming

Idadi kubwa ya mtandao programu za seva kupangwa kwa kutumia soketi. Kimsingi, soketi ni sawa na maelezo ya faili na moja sana tofauti muhimu- soketi hutumiwa kwa mawasiliano kati ya programu ama kwenye mtandao au kwenye mashine ya ndani. Kwa hivyo, programu haina shida na uwasilishaji wa data; soketi humfanyia. Unahitaji tu kuhakikisha kuwa vigezo vya tundu vya programu mbili vinafanana.

Kwa hivyo, soketi za mtandao ni miundo iliyounganishwa ambayo imesawazishwa madhubuti na kila mmoja. Ili kuunda soketi kwenye mfumo wowote wa uendeshaji unaowaunga mkono, tumia kazi ya tundu (kwa bahati nzuri, soketi zimesawazishwa vya kutosha kwamba zinaweza kutumika kuhamisha data kati ya programu zinazoendelea. majukwaa tofauti) Umbizo la kazi ni:

tundu la int (kikoa cha int, aina ya int, itifaki ya int);

Kigezo cha kikoa kinataja aina ya itifaki ya usafiri, i.e. itifaki ya utoaji wa pakiti za mtandao. Itifaki zifuatazo zinatumika kwa sasa (lakini tafadhali kumbuka kuwa kwa aina tofauti aina ya itifaki ya muundo wa anwani itakuwa tofauti):

  • PF_UNIX au PF_LOCALmawasiliano ya ndani kwa UNIX OS (na sawa).
  • PF_INET - IPv4, IP-Itifaki ya mtandao, inayojulikana zaidi sasa (anwani 32-bit).
  • PF_INET6- IPv6, kizazi kijacho cha itifaki ya IP (IPng) - anwani ya 128-bit.
  • PF_IPX - IPX- Itifaki za Novell.

Itifaki zingine zinaungwa mkono, lakini hizi 4 ndizo maarufu zaidi.

Aina ya parameter ina maana ya aina ya tundu, i.e. jinsi data itahamishwa: SOCK_STREAM mara kwa mara hutumiwa, matumizi yake inamaanisha uhamisho salama mtiririko wa data wa pande mbili na udhibiti wa makosa. Kwa njia hii ya uhamishaji data, mpangaji programu hana haja ya kuwa na wasiwasi juu ya kushughulikia makosa ya mtandao, ingawa hii hailindi dhidi ya makosa ya kimantiki, ambayo ni muhimu kwa seva ya mtandao.

Kigezo cha itifaki kinabainisha aina maalum itifaki ya kikoa fulani, kwa mfano IPPROTO_TCP au IPPROTO_UDP (kigezo cha aina lazima kiwe ndani kwa kesi hii kuwa SOCK_DGRAM).

Kazi ya tundu inaunda tu mwisho na inarudi kushughulikia tundu; Mpaka tundu limeunganishwa na anwani ya mbali kwa kutumia kazi ya kuunganisha, data haiwezi kutumwa kwa njia hiyo! Ikiwa pakiti zimepotea kwenye mtandao, k.m. Ikiwa kuna kutofaulu kwa mawasiliano, basi programu iliyounda tundu inatumwa kwa Bomba Iliyovunjika - ishara ya SIGPIPE, kwa hivyo inashauriwa kumpa kidhibiti. ishara hii ishara ya kazi. Baada ya tundu kuunganishwa na mwingine na kazi ya kuunganisha, data inaweza kutumwa juu yake ama kwa kutumia kazi za kawaida za kusoma - kuandika au recv maalum - kutuma kazi. Baada ya kumaliza kazi, tundu lazima limefungwa kwa kutumia kazi ya karibu. Kwa kuunda maombi ya mteja Inatosha kuunganisha tundu la ndani na kazi ya kuunganisha kijijini (seva). Muundo wa kipengele hiki ni:

int connect(int sock_fd, const struct *sockaddr serv_addr, socketlen_t addr_len);

Ikiwa kuna hitilafu, chaguo la kukokotoa linarudi -1; hali ya hitilafu inaweza kupatikana kwa kutumia mfumo wa uendeshaji. Katika kazi yenye mafanikio inarudi 0. Tundu, ikiwa imeunganishwa, mara nyingi haiwezi kuunganishwa tena, kama inavyotokea, kwa mfano, katika itifaki ya IP. Kigezo cha sock_fd kinabainisha kielezi cha tundu, muundo wa serv_addr unapeana anwani ya mwisho ya mbali, addr_len ina urefu wa serv_addr (aina ya socketlen_t ina asili ya kihistoria, kawaida ni sawa na chapa int) Wengi parameter muhimu katika kazi hii - anwani ya tundu la mbali. Kwa kawaida, sio sawa kwa itifaki tofauti, kwa hiyo nitaelezea hapa muundo wa anwani tu kwa itifaki ya IP (v4). Kwa hili, muundo maalum wa sockaddr_in hutumiwa (lazima utupwe moja kwa moja kwa aina ya sockaddr wakati piga simu kuunganisha) Sehemu za muundo huu zinaonekana kama hii:

tengeneza sockaddr_in(

Familia_ya_siyo_familia; - inafafanua familia ya anwani, lazima iwe AF_INET kila wakati

U_int16_t sin_port; - bandari ya tundu kwa mpangilio wa mtandao

Muundo katika_addr sin_addr; - muundo ulio na anwani ya IP

Muundo unaoelezea anwani ya IP:

muundo katika_addr(

U_int32_t s_addr; - weka anwani ya IP kwa mpangilio wa mtandao

Kumbuka mpangilio maalum wa baiti katika sehemu zote kamili. Ili kubadilisha nambari ya bandari kuwa mpangilio wa mtandao, unaweza kutumia htons macro ( fupi isiyotiwa saini bandari). Ni muhimu sana kutumia aina hii ya nambari kamili - nambari fupi isiyo na saini.

Anwani za IPv4 zimegawanywa katika moja, matangazo (matangazo) na kikundi (multicast). Kila anwani moja inaelekeza kwenye kiolesura kimoja cha seva pangishi, anwani za utangazaji huelekeza kwa wapangishaji wote kwenye mtandao, na anwani za utangazaji anuwai huelekeza kwa wapangishi wote katika kikundi cha utangazaji anuwai. Muundo wa in_addr unaweza kupewa anwani yoyote kati ya hizi. Lakini kwa wateja wa tundu, katika idadi kubwa ya kesi anwani moja hupewa. Isipokuwa ni wakati inahitajika kuchambua nzima mtandao wa ndani katika kutafuta seva, basi unaweza kutumia anwani ya matangazo. Kisha, uwezekano mkubwa, seva lazima iripoti anwani yake halisi ya IP na tundu la uhamisho zaidi wa data lazima liunganishwe nayo. Hakuna usambazaji wa data kupitia anwani za matangazo wazo nzuri, kwa kuwa haijulikani ni seva gani inashughulikia ombi. Kwa hiyo, soketi zinazoelekezwa kwa sasa zinaweza kutumia anwani moja tu. Kwa seva za tundu za kusikiliza anwani, hali ni tofauti: hapa inaruhusiwa kutumia anwani za utangazaji ili kujibu mara moja ombi la mteja kwa eneo la seva. Lakini mambo ya kwanza kwanza. Kama ulivyoona, katika muundo wa sockaddr_in sehemu ya anwani ya IP inawakilishwa kama nambari kamili isiyo na saini, na tunatumiwa anwani katika umbizo la x.x.x.x (172.16.163.89) au katika umbizo la herufi (myhost.com). Ili kubadilisha ya kwanza, tumia kitendakazi cha inet_addr (const char *ip_addr), na kwa pili, tumia kitendakazi cha gethostbyname (const char *host). Wacha tuangalie zote mbili:

u_int32_t inet_addr(const char *ip_addr)

– hurejesha nambari kamili ya moja kwa moja inayofaa kutumika katika muundo wa sockaddr_in kwenye anwani ya IP iliyopitishwa kwake katika umbizo la x.x.x.x. Hitilafu ikitokea, INADDR_NONE itarejeshwa.

tengeneza HOSTENT* gethostbyname(const char *host_name)

- inarudisha muundo wa habari kuhusu mwenyeji kulingana na jina lake. Isipofaulu, hurejesha NULL. Utafutaji wa jina hutokea kwanza ndani faili ya majeshi na kisha kwa DNS. Muundo wa HOSTENT hutoa maelezo kuhusu mwenyeji anayehitajika. Kati ya sehemu zake zote, muhimu zaidi ni sehemu ya char **h_addr_list, ambayo inawakilisha orodha ya anwani za IP kwa seva pangishi fulani. Kawaida h_addr_list hutumiwa, ikiwakilisha anwani ya kwanza ya IP ya seva pangishi, unaweza pia kutumia usemi wa h_addr kwa hili. Baada ya kutekeleza kitendakazi cha gethostbyname, orodha h_addr_list ya muundo wa HOSTENT ina anwani rahisi za ishara za IP, kwa hivyo lazima utumie kitendakazi cha inet_addr kubadilisha hadi umbizo la sockaddr_in.

Kwa hiyo, tumeunganisha tundu la mteja kwenye tundu la seva kwa kutumia kazi ya kuunganisha. Kisha unaweza kutumia vitendaji vya kuhamisha data. Kwa hili unaweza kutumia ama vipengele vya kawaida I/O ya kiwango cha chini kwa faili, kwani tundu kimsingi kielezi cha faili. Kwa bahati mbaya, kazi za kazi za kiwango cha chini na faili zinaweza kutofautiana kwa mifumo tofauti ya uendeshaji, kwa hiyo unahitaji kuangalia mwongozo wa mfumo wako wa uendeshaji. Tafadhali kumbuka kuwa mawasiliano ya mtandao yanaweza kuisha kwa ishara ya SIGPIPE na vitendakazi vya kusoma/kuandika vitaleta hitilafu. Unapaswa kukumbuka daima kuangalia makosa, kwa kuongeza, usipaswi kusahau kwamba uhamisho wa data kwenye mtandao unaweza kuwa polepole sana, na kazi za pembejeo / pato ni sawa, na hii inaweza kusababisha ucheleweshaji mkubwa katika programu.

Ili kuhamisha data kati ya soketi kuna kazi maalum, kawaida kwa mifumo yote ya uendeshaji, ni kazi za recv na send family. Muundo wao ni sawa sana:

int send(int sockfd, batili *data, size_t len, int bendera);

- hutuma bafa ya data.

int recv(int sockfd, batili *data, size_t len, bendera za int);

- inakubali bafa ya data.

Hoja ya kwanza ni maelezo ya tundu, ya pili ni kielekezi kwa data inayopaswa kuhamishwa, ya tatu ni urefu wa bafa, na ya nne ni bendera. Ikifaulu, nambari ya baiti zilizohamishwa hurejeshwa; ikiwa haikufaulu, msimbo wa hitilafu hasi hurejeshwa. Bendera hukuruhusu kubadilisha vigezo vya upitishaji (kwa mfano, wezesha hali ya operesheni isiyolingana), lakini kwa kazi nyingi inatosha kuacha sehemu ya bendera sifuri kwa hali ya kawaida uhamisho. Wakati wa kutuma au kupokea data, vitendakazi huzuia utekelezaji wa programu kabla ya bafa nzima kutumwa. Na wakati wa kutumia itifaki ya tcp/ip, jibu lazima litoke kwenye tundu la mbali linaloonyesha kutuma au kupokea data kwa mafanikio, vinginevyo pakiti inatumwa tena. Wakati wa kutuma data, fikiria mtandao wa MTU ( ukubwa wa juu fremu iliyopitishwa kwa wakati mmoja). Kwa mitandao mbalimbali inaweza kuwa tofauti, kwa mfano, kwa Mitandao ya Ethernet ni sawa na 1500.

Kwa hivyo, kwa ajili ya ukamilifu, nitatoa mfano rahisi zaidi wa programu ya C inayotekelezea mteja wa tundu:

#pamoja na /* Maktaba za Kawaida soketi za Linux */

#pamoja na /* Kwa Windows OS tumia #include */

#pamoja na

int kuu())(

Int sockfd = -1;

/* Maelezo ya tundu */

buf ya Char;

Char s = "Mteja tayari";

HOSTENT *h = NULL;

Sockaddr_in addr;

Bandari fupi isiyo na saini = 80;

Addr.sin_family = AF_INET;

/* Tengeneza tundu */

Ikiwa(sockfd == -1)

/* Ikiwa soketi imeundwa */

Kurudi -1;

H = gethostbyname("www.myhost.com");

/* Pata anwani ya mwenyeji */

Ikiwa(h == NULL)

/* Je, kuna anwani kama hiyo? */

Kurudi -1;

Addr.sin_addr.s_addr = inet_addr(h->h_addr_list);

/* Badilisha anwani ya IP kuwa nambari */

If(connect(sockfd, (sockaddr*) &addr, sizeof(addr)))

/* Kujaribu kuunganisha kwenye tundu la mbali */

Kurudi -1;

/* Muunganisho ulifanikiwa - endelea */

Ikiwa(tuma(sockfd, s, sizeof), 0)< 0)

Kurudi -1;

Ikiwa(recv(sockfd, buf, sizeof(buf), 0)< 0)

Kurudi -1;

Funga(sockfd);

/* Funga tundu */

/* Kwa Windows, kitendakazi cha closesocket kinatumika */

Rudia 0;

Unaona, kutumia soketi sio ngumu sana. KATIKA programu za seva kanuni tofauti kabisa za kufanya kazi na soketi hutumiwa. Kwanza, tundu linaundwa, kisha linapewa anwani ya eneo kwa kutumia kitendakazi cha kumfunga, unaweza kugawa anwani ya utangazaji kwenye tundu. Kisha kazi ya kusikiliza huanza kusikiliza anwani, maombi ya uunganisho yanawekwa kwenye foleni. Hiyo ni, kazi ya kusikiliza inaanzisha tundu la kupokea ujumbe. Baada ya hayo, unahitaji kutumia kazi ya kukubali, ambayo inarudi tundu mpya tayari kuhusishwa na mteja. Ni kawaida kwa seva kukubali miunganisho mingi kwa muda mfupi. Kwa hiyo, unahitaji kuangalia mara kwa mara foleni ya miunganisho inayoingia kwa kutumia kazi ya kukubali. Ili kupanga tabia hii, mara nyingi huamua uwezo wa mfumo wa uendeshaji. Kwa Windows OS, toleo la nyuzi nyingi za operesheni ya seva hutumiwa mara nyingi zaidi; baada ya kukubali unganisho, nyuzi mpya huundwa kwenye programu, ambayo huchakata tundu. Katika mifumo ya *nix, uundaji wa mchakato wa mtoto kwa kitendakazi cha uma hutumiwa mara nyingi zaidi. Wakati huo huo, gharama za juu hupunguzwa kwa sababu ya ukweli kwamba nakala ya mchakato hutokea mfumo wa faili proc. Katika kesi hii, vigezo vyote vya mchakato wa mtoto ni sawa na mzazi. Na mchakato wa mtoto unaweza kushughulikia mara moja uunganisho unaoingia. Mchakato wa mzazi unaendelea kusikiliza. Tafadhali kumbuka kuwa bandari zilizo na nambari 1 hadi 1024 zina bahati na kuzisikiliza sio rahisi kila wakati. Hoja moja zaidi: huwezi kuwa na soketi mbili tofauti zinazosikiliza bandari moja kwenye anwani moja! Kwanza, hebu tuangalie fomati za kazi zilizo hapo juu za kuunda tundu la seva:

int bind(int sockfd, const struct *sockaddr, socklen_t addr_len);

- inapeana anwani ya eneo kwenye tundu ili kuiruhusu kukubali miunganisho inayoingia. Kwa anwani, unaweza kutumia INADDR_ANY mara kwa mara, ambayo inakuwezesha kukubali miunganisho inayoingia kutoka kwa anwani zote katika subnet fulani. Umbizo la chaguo la kukokotoa ni sawa na kuunganisha. Ikitokea hitilafu, hurejesha thamani hasi.

int kusikiliza (int sockfd, int backlog);

- kazi inaunda foleni ya soketi zinazoingia (idadi ya viunganisho imedhamiriwa na parameter ya backlog, haipaswi kuzidi namba SOMAXCONN, ambayo inategemea OS). Baada ya kuunda foleni, unaweza kusubiri muunganisho kwa kutumia kitendakazi cha kukubali. Soketi kawaida huzuia, kwa hivyo utekelezaji wa programu umesimamishwa hadi uunganisho utakubaliwa. Katika kesi ya makosa, -1 inarudishwa.

kukubali kwa ndani (int sockfd, muundo *sockaddr, socklen_t addr_len)

- kazi inasubiri muunganisho unaoingia(au kuirejesha kutoka kwa foleni ya uunganisho) na kurudisha soketi mpya ambayo tayari inahusishwa na mteja wa mbali. Katika kesi hii, soketi ya asili ya soketi bado haijabadilika. Muundo wa sockaddr umejaa maadili kutoka kwa soketi ya mbali. Katika kesi ya makosa, -1 inarudishwa.

Kwa hivyo hapa kuna mfano wa seva rahisi ya soketi ambayo hutumia kazi ya uma kuunda mchakato wa mtoto ambao unashughulikia muunganisho:

int kuu())(

Pid_t pid;

/* Kitambulisho cha mchakato wa mtoto */

Int sockfd = -1;

/* Shikilia kwa tundu ili kusikiliza kwenye */

Int s = -1;

/* Pokea maelezo ya tundu */

buf ya Char;

/* Elekeza kwenye bafa ili kupokea */

Char str = "Seva tayari";

/* Kamba ya kutuma kwa seva */

HOSTENT *h = NULL;

/* Muundo wa kupata anwani ya IP */

Sockaddr_in addr;

/* Muundo wa itifaki ya Tcp/ip */

Sockaddr_in raddr;

Bandari fupi isiyo na saini = 80;

/* Jaza sehemu za muundo: */

Addr.sin_family = AF_INET;

Addr.sin_port = htons(bandari);

sockfd = soketi(PF_INET, SOCK_STREAM, IPPROTO_TCP);

/* Tengeneza tundu */

Ikiwa(sockfd == -1)

/* Ikiwa soketi imeundwa */

Kurudi -1;

Addr.sin_addr.s_addr = INADDR_ANY;

/* Sikiliza katika anwani zote */

Ikiwa(bind(sockfd, (sockaddr*) &addr, sizeof(addr)))

/* Agiza anwani ya karibu kwenye tundu */

Kurudi -1;

Kama(sikiliza(sockfd, 1))

/* Anza kusikiliza */

Kurudi -1;

S = kubali(sockfd, (sockaddr *) &raddr, sizeof(raddr));

/* Kubali muunganisho */

Pid = uma ();

/* kuzaa mchakato wa mtoto */

Ikiwa(pid == 0)(

/* Huu ni mchakato wa mtoto */

Ikiwa(recv, buf, sizeof(buf), 0)< 0)

/* Tuma kamba s kwenye tundu la mbali */

Kurudi -1;

Ikiwa(tuma, str, saizi ya(str), 0)< 0)

/* Pokea jibu kutoka kwa seva ya mbali */

Kurudi -1;

Printf("Kamba iliyopokelewa ilikuwa: %s", buf);

/* Chapisha bafa kwa pato la kawaida */

Funga;

/* Funga tundu */

Rudia 0;

/* Toka katika mchakato wa mtoto */

Funga(sockfd);

/* Funga soketi ya kusikiliza */

Rudia 0;

Wakati wa kuunda thread ili kusindika tundu, angalia mwongozo wa OS, kama mifumo tofauti Wito kwa kazi ya kuunda nyuzi inaweza kutofautiana kwa kiasi kikubwa. Lakini kanuni za usindikaji kwa thread zinabaki sawa. Kitendakazi cha kuchakata kinahitaji tu kupitisha kielekezi cha tundu kama hoja (kawaida aina yoyote ya data katika umbizo batili * inaweza kupitishwa kwa kitendakazi cha mtiririko, ambacho kinahitaji matumizi ya aina ya kutupwa).

Kumbuka muhimu kwa mifumo ya Windows. Niligundua kuwa mfumo wa tundu haufanyi kazi bila kutumia kazi ya WSAStartup kuanzisha maktaba ya tundu. Programu ya soketi ya Windows inapaswa kuanza kama hii:

WSADATA wsaData;

WSAStartup(0x0101, &wsaData);

Na unapotoka kwenye programu, andika yafuatayo:

WSACleanup ();

Kwa kuwa shughuli nyingi za tundu zinazuia, utekelezaji wa kazi lazima uingizwe mara kwa mara kwa kusubiri maingiliano. Kwa hiyo, mifumo ya *nix-kama mara nyingi huepuka kuzuia console kwa kuunda aina maalum ya programu - daemon. Daemoni si mali ya kiweko pepe na hutokea wakati mchakato wa mtoto unapoita uma, na mchakato wa mzazi huisha kabla ya mtoto wa 2 (na hii hutokea kila mara kwa njia hii). Baada ya hayo, mchakato wa mtoto wa 2 unakuwa mchakato kuu na hauzuii console. Hapa kuna mfano wa tabia ya programu hii:

pid = uma ();

/* Unda mchakato wa mtoto wa kwanza */

ikiwa (pid<0){

/* Hitilafu katika kupiga uma */

Printf("Kosa la Kuiga:) ");

Toka(-1);

)mwingine ikiwa (pid !=0)(

/* Huyu ndiye mzazi wa kwanza! */

Printf("Huyu ni Baba 1");

)mwingine(

Pid = uma ();

/* Kazi ya mzazi wa kwanza inaisha */

/* Na tunaita mchakato mwingine wa mtoto */

Ikiwa (pid<0){

Printf("Kosa la kughushi:) ");

Toka(-1);

)mwingine ikiwa (pid !=0)(

/* Huyu ni mzazi wa pili */

Printf("Huyu ni baba 2");

)mwingine(

/* Na huu ni mchakato uleule wa mtoto wa 2 */

/* Badilisha hadi hali ya "kiwango" ya daemon */

Setid();

/* Endesha daemon katika hali ya mtumiaji mkuu */

Umask(0); /* Mask ya faili ya kawaida */

Chdir("/"); /* Nenda kwenye saraka ya mizizi */

Daemoncode(); /* Kwa kweli msimbo wa daemon yenyewe */

/* Unapopiga daemon, daemon ya mtoto inaonekana */

Ni hayo tu. Nadhani hii inatosha kuunda seva rahisi ya tundu.

kiolesura cha simu cha mfumo wa mtandao ( soketi(), funga (), recvfrom(), tuma kwa() n.k.) katika mfumo wa uendeshaji wa UNIX inaweza kutumika kwa mabunda mengine ya itifaki (na kwa itifaki zilizo hapa chini safu ya usafiri).

Wakati wa kuunda tundu, lazima ueleze aina yake kwa usahihi. Uainishaji huu unafanywa kwa kutumia vigezo vitatu vya kupiga simu soketi(). Kigezo cha kwanza kinabainisha ni familia gani ya itifaki ambayo soketi iliyoundwa ni ya familia, na vigezo vya pili na vya tatu vinafafanua itifaki maalum ndani ya familia hiyo.

Kigezo cha pili kinatumika kutaja aina ya kiolesura cha kufanya kazi na tundu - itakuwa tundu la mkondo, tundu la kufanya kazi na datagrams, au nyingine. Kigezo cha tatu kinabainisha itifaki ya aina ya kiolesura ulichopewa. KATIKA Rafu ya itifaki ya TCP/IP Kuna itifaki moja tu ya soketi za mtiririko - TCP na itifaki moja tu ya soketi za datagram - UDP, kwa hivyo kwa itifaki za usafirishaji za TCP/IP kigezo cha tatu kinapuuzwa.

Katika safu zingine za itifaki, kunaweza kuwa na itifaki kadhaa zilizo na aina moja ya kiolesura, kwa mfano, zile za datagram, ambazo hutofautiana katika kiwango cha kuegemea.

Kwa itifaki za usafiri za TCP/IP, tutabainisha kila mara AF_INET iliyofafanuliwa awali (Familia ya Anwani - Mtandao) au kisawe chake PF_INET (Familia ya Itifaki - Mtandao) kama kigezo cha kwanza.

Kigezo cha pili kitachukua thamani zilizobainishwa awali \ SOCK_STREAM za soketi za mtiririko na SOCK_DGRAM kwa soketi za datagram.

Kwa kuwa parameta ya tatu haijazingatiwa kwa upande wetu, tutabadilisha thamani 0 ndani yake.

Kiungo cha habari kuhusu tundu iliyoundwa imewekwa Jedwali la faili za mchakato wazi sawa na jinsi ilivyofanywa kwa pips na FIFOs (tazama warsha 5). Simu ya mfumo inamrudishia mtumiaji kielezi cha faili kinacholingana na kipengele cha jedwali kilichojaa watu wengi, ambacho tutakiita kuanzia sasa kielezi cha tundu. Njia hii ya kuhifadhi habari kuhusu tundu inaruhusu, kwanza, michakato ya mtoto kurithi kutoka kwa michakato ya mzazi, na, pili, kutumia kwa soketi baadhi ya simu za mfumo ambazo tayari tunazijua kutokana na kufanya kazi na pips na FIFOs: close( ) , soma() , andika() .

Simu ya mfumo ili kuunda tundu

Mfano wa simu ya mfumo

#pamoja na #pamoja na tundu la int (kikoa cha int, aina ya int, itifaki ya int);

Maelezo ya simu ya mfumo

Simu ya mfumo tundu hutumikia kuunda nodi ya mawasiliano ya kawaida katika mfumo wa uendeshaji. Maelezo haya si maelezo kamili ya simu ya mfumo, lakini yanalenga tu kutumika katika kozi yetu. Kwa habari kamili, angalia Mwongozo wa UNIX.

Kigezo cha kikoa kinafafanua familia ya itifaki ambayo habari itahamishwa. Tutazingatia familia mbili tu kati ya hizi kati ya kadhaa zilizopo. Kuna maadili ya parameta yaliyoainishwa kwao:

  • PF_INET - kwa Familia ya itifaki ya TCP/IP ;
  • PF_UNIX - kwa familia ya itifaki za ndani za UNIX, zinazojulikana kama kikoa cha UNIX.

Kigezo cha aina huamua semantiki za ubadilishanaji wa habari: ikiwa mawasiliano yatafanywa kupitia ujumbe (datagrams), kwa kuanzisha muunganisho wa mtandaoni au kwa njia nyingine. Tutatumia njia mbili tu za kubadilishana habari na maadili yaliyofafanuliwa kwa paramu ya aina:

  • SOCK_STREAM - kwa mawasiliano kwa kutumia uanzishwaji muunganisho wa mtandaoni ;
  • SOCK_DGRAM - kwa kubadilishana habari kupitia ujumbe.

Kigezo cha itifaki kinabainisha itifaki maalum ya itifaki iliyochaguliwa ya familia na njia ya mawasiliano. Ni muhimu tu ikiwa kuna itifaki kadhaa kama hizo. Kwa upande wetu, familia ya itifaki na aina ya kubadilishana habari huamua kipekee itifaki. Kwa hivyo, tutafikiria parameta hii ni sawa na 0.

Thamani ya kurudi

Ikifaulu, simu ya mfumo hurejesha kielezi cha faili (thamani kubwa kuliko au sawa na 0), ambacho kitatumika kama marejeleo ya nodi ya mawasiliano iliyoundwa katika simu zote zaidi za mtandao. Ikiwa kosa lolote litatokea, thamani hasi inarejeshwa.

Anwani za tundu. Kuweka anwani ya tundu. bind() simu ya mfumo

Mara tu tundu linapoundwa, unahitaji kusanidi anwani yake. Simu ya mfumo hutumiwa kwa hili funga (). Kigezo cha kwanza cha simu lazima kiwe na maelezo ya tundu ambayo anwani yake inasanidiwa. Vigezo vya pili na vya tatu vinataja anwani hii.

Kigezo cha pili lazima kiwe kielekezi kwa muundo wa sockaddr ulio na sehemu za mbali na za ndani za anwani kamili.

Viashiria vya aina ya struct sockaddr * vinapatikana katika simu nyingi za mfumo wa mtandao; hutumika kuwasilisha habari kuhusu ni anwani gani tundu ni au inapaswa kushikamana nayo. Hebu tuangalie kwa karibu aina hii ya data. Muundo wa muundo sockaddr umeelezewa kwenye faili kwa njia ifuatayo:

struct sockaddr (short sa_family; char sa_data; );

Utungaji huu wa muundo ni kutokana na ukweli kwamba simu za mfumo wa mtandao zinaweza kutumika kwa familia tofauti za itifaki, ambazo hufafanua nafasi za anwani tofauti kwa anwani za tundu za mbali na za ndani. Kimsingi, aina hii ya data ni kiolezo cha jumla cha kupitisha miundo ya data mahususi kwa kila familia ya itifaki kwa simu za mfumo. Kipengele pekee cha kawaida cha miundo hii ni nyanja fupi ya sa_family (ambayo, kwa kawaida, inaweza kuwa na majina tofauti katika miundo tofauti; jambo muhimu tu ni kwamba wote ni wa aina moja na ni vipengele vya kwanza vya miundo yao) kuelezea familia ya itifaki. Simu ya mfumo inachambua yaliyomo kwenye uwanja huu ili kuamua kwa usahihi muundo wa habari zinazoingia.

Kufanya kazi na familia ya itifaki za TCP/IP tutatumia anwani ya tundu ya aina ifuatayo, iliyoelezwa kwenye faili :

struct sockaddr _in( short sin_family; /* Familia ya itifaki iliyochaguliwa kila wakati ni AF_INET */ bandari fupi isiyotiwa saini; /* Nambari ya bandari 16-bit katika mpangilio wa baiti ya mtandao */ struct in_addr sin_addr; /* Anwani ya kiolesura cha mtandao */ char sin_zero; /* Sehemu hii haitumiki, lakini lazima ijazwe na sufuri */ );

Kipengele cha kwanza cha muundo - sin_family inabainisha familia ya itifaki. Tutaingia ndani yake AF_INET iliyofafanuliwa tayari, ambayo tayari tunaijua (tazama sehemu iliyotangulia).

Sehemu ya mbali ya anwani kamili - anwani ya IP - iko katika muundo wa aina ya muundo in_addr, ambayo tulikutana nayo katika sehemu ya "Kazi za Tafsiri za Anwani ya IP" inet_ntoa(), inet_aton() " .

Ili kuonyesha nambari ya mlango, kipengele cha muundo wa sin_port kinatumika, ambamo nambari ya mlango inapaswa kuhifadhiwa kwa mpangilio wa mtandao. Kuna chaguzi mbili za kubainisha nambari ya bandari: lango lisilobadilika kama anavyotaka mtumiaji na lango ambalo limepewa nasibu. mfumo wa uendeshaji. Chaguo la kwanza linahitaji kubainisha nambari chanya, inayojulikana hapo awali kama nambari ya bandari na kwa itifaki ya UDP kwa kawaida hutumiwa wakati wa kuweka anwani za soketi na wakati wa kutuma habari kwa kutumia simu ya mfumo. tuma kwa()(tazama sehemu inayofuata). Chaguo la pili linahitaji kubainisha 0 kama nambari ya mlango. Katika hali hii mfumo wa uendeshaji yenyewe hufunga tundu kwa nambari ya bandari ya bure. Njia hii hutumiwa kwa kawaida wakati wa kuanzisha soketi za programu za mteja, wakati mtayarishaji hawana haja ya kujua nambari halisi ya bandari mapema.

Je, mtumiaji anaweza kutumia nambari gani ya bandari katika usanidi usiobadilika? Nambari za bandari 1 hadi 1023 zinaweza tu kupewa soketi kwa michakato inayoendeshwa na haki za msimamizi wa mfumo. Kwa kawaida, nambari hizi hupewa huduma za mtandao wa mfumo, bila kujali aina ya mfumo wa uendeshaji unaotumiwa, ili programu za mteja wa mtumiaji zinaweza daima kuomba huduma kutoka kwa anwani sawa za mitaa. Pia kuna idadi ya programu za mtandao zinazotumiwa sana zinazoendesha michakato na ruhusa za kawaida za mtumiaji (kwa mfano, X-Windows). Kwa programu kama hizi za Shirika la Mtandao za kupeana majina na nambari (

Je, unataka kuendeleza programu ya mtandao katika Java - toy, chumba cha mazungumzo, au zote mbili... Umepata makala sahihi - hapa unaweza kufahamiana na ulimwengu wa kusisimua wa soketi katika Java. Baada ya kusoma makala hii, utaona mwanga mwishoni mwa handaki - madhumuni ya soketi na jinsi ya kuendeleza programu rahisi kwa kutumia soketi katika lugha ya programu ya Java itakuwa wazi.

Soketi ni nini?

Leo, utumiaji wa wateja wa ujumbe wa papo hapo umekuwa zana ya lazima kwa watumiaji wote wa Mtandao. Kuna itifaki na wateja wengi tofauti (MSN, ICQ, Skype, n.k.) ambazo kila mtu amezisikia na ambazo sote tunazitumia kila siku. Lakini sio kila mtu anajua ni nini msingi wa roboti zao - ndivyo nakala hii iliandikwa. Hebu tuseme umesakinisha mojawapo ya wateja wa utumaji ujumbe wa papo hapo kwenye kompyuta yako. Baada ya kuizindua na kuingiza jina lako la mtumiaji na nenosiri, programu inajaribu kuunganisha kwenye seva. Neno "kuunganisha" linamaanisha nini hasa?

Kila kompyuta kwenye mtandao ina anwani ya IP. Anwani hii ni sawa na anwani yako ya nyumbani - inatambulisha kompyuta yako kwa njia ya kipekee na inaruhusu wengine kuwasiliana na kompyuta yako. Hatutaingia katika maelezo ya anwani za IP, kwa kuwa makala hii haiwahusu, nataka tu kutambua kwamba anwani ya IP ni seti ya nambari zilizotengwa na dots (kwa mfano, 64.104.137.158). Ingawa kuna njia nyingine ya kutambua kompyuta kwenye mtandao - jina la kikoa, ambalo ni rahisi zaidi na linabainisha wazi zaidi kompyuta kuliko seti rahisi ya nambari (kwa mfano, www.site). Kuna kompyuta maalum kwenye mtandao zinazobadilisha jina la kikoa kuwa anwani ya IP na kinyume chake.

Programu kadhaa zinaweza kutekelezwa kwa sambamba kwenye kompyuta moja. Wacha tuseme una programu 10 zinazoendesha kwenye kompyuta yako, na zote zinangojea kompyuta zingine kuwasiliana nazo. Unaweza kufikiria kama hii: kuna 10 kati yenu katika ofisi kubwa na simu 1, na kila mtu anasubiri simu kutoka kwa wateja wao wenyewe. Je, utalitatuaje hili? Unaweza, bila shaka, kuteua mfanyakazi anayejibika, na ataleta simu kwa mtu anayehusika anayeitwa, lakini basi wateja wengine hawataweza kufikia watu wengine. Zaidi ya hayo, ni vigumu sana na ni vigumu kuwa na mtu anayehusika na kuelekeza simu kwa watu wanaofaa. Huenda umekisia ninakoenda na hii - ikiwa programu hizi zote zinazoendesha kwenye kompyuta moja zinawauliza wateja wao kwa kiburi kuwasiliana nao kwa anwani maalum ya IP, basi wateja wao hawatafurahi. Wazo ni ... kuwa na anwani tofauti ya IP kwa kila programu, sivyo? SI UKWELI! Kiini cha swali si sahihi - ni sawa na kuuliza kuhusu ofisi tofauti kwa kila mmoja wenu. Kweli, basi ... labda nambari za simu tofauti zitatosha? NDIYO! Katika jargon ya mtandao, "nambari za simu za kibinafsi" huitwa bandari. Lango ni nambari tu, na kila programu inayoendeshwa kwenye kompyuta fulani inaweza kuchagua nambari ya kipekee ya mlango ili kujitambulisha kwa ulimwengu wa nje. KUMBUKA - huwezi kupata bandari hizi kati ya vifaa vya kompyuta (usijaribu hata kuzitafuta). Nambari hizi ni za kimantiki. Sasa kila kitu ni wazi: kuna anwani ya IP ambayo kompyuta nyingine zinaweza kutambua kompyuta maalum kwenye mtandao, na nambari ya bandari ambayo inabainisha programu fulani inayoendesha kwenye kompyuta. Pia inakuwa wazi kwamba programu mbili kwenye kompyuta tofauti zinaweza kutumia bandari moja (nyumba mbili kwenye barabara tofauti zinaweza pia kuwa na idadi sawa, au la?). Kweli, karibu tumefika, ili kukutisha kidogo, wacha tupate fomula:

Anwani ya IP = kipekee hutambulisha kompyuta kwenye mtandao.
Nambari ya bandari = inabainisha kipekee programu inayoendesha kwenye kompyuta inayolingana.

Ikiwa tutaongeza equations hapo juu, tunapata:

Anwani ya IP + nambari ya mlango = _____

Kwa maneno mengine:

Kipekee hubainisha programu kwenye mtandao. Ikiwa ulifikiria hii mwenyewe, basi juhudi zangu hazikuwa bure. Ikiwa sivyo, basi soma jambo zima tena tangu mwanzo au tumia Google kupata makala bora zaidi. _____ ni... SOKO!

Kwa muhtasari, tundu ni mchanganyiko wa anwani ya IP na bandari. Anwani ya tundu huruhusu kompyuta nyingine kwenye mtandao kupata programu maalum inayoendeshwa kwenye kompyuta mahususi. Unaweza kuonyesha anwani ya tundu kama hii 64.104.137.58:80, ambapo 64.104.137.58 ni anwani ya IP na 80 ni bandari.

Jinsi ya kupanga kwa kutumia soketi?

Inatosha kuhusu nadharia, wacha tuchukue hatua. Wacha tukuze msimbo rahisi sana na wa kuona katika Java ambao utaonyesha uwezekano wa kutumia soketi. Wacha tujaribu kutekeleza orodha ifuatayo ya vitendo:

1) Programu moja ya Java itajaribu kuwasiliana na programu nyingine ya Java (ambayo inasubiri sana mtu awasiliane nayo). Wacha tuite programu ya kwanza Mteja, na ya pili Seva.

2) Baada ya kuunganisha kwa ufanisi kwenye seva, mteja anasubiri uingizaji wa data kutoka kwako na kutuma maandishi kwa seva.

3) Programu ya seva hutuma maandishi hayo kwa mteja (ili kuonyesha kuwa inaweza kufanya hata kitendo muhimu kama hicho).

4) Mteja anaonyesha maandishi yaliyopokelewa kutoka kwa seva ili kukuonyesha maoni ya seva kukuhusu. Je, uko tayari kuanza kuendeleza? Hebu tuanze. Acha nikumbuke kuwa sitakufundisha programu ya Java kutoka mwanzo, lakini nitaelezea tu nambari inayohusiana na soketi. Unda programu 2 mpya za Java na uzipe jina Server.java na Client.java. Nimetoa nambari iliyo hapa chini, usifadhaike, nitaelezea kila kitu.


agiza java.net.*;
agiza java.io.*;
Seva ya darasa la umma (
bandari ya ndani = 6666; // bandari ya nasibu (inaweza kuwa nambari yoyote kutoka 1025 hadi 65535)
jaribu (
ServerSocket ss = new ServerSocket(bandari); // unda tundu la seva na uifunge kwa bandari iliyo hapo juu
System.out.println("Inasubiri mteja...");

Soketi ya tundu = ss.kubali (); // kulazimisha seva kusubiri miunganisho na kuonyesha ujumbe wakati mtu anawasiliana na seva
System.out.println("Nimepata mteja:) ... Hatimaye, mtu aliniona kupitia jalada lote!");
System.out.println();

// Tunachukua mito ya pembejeo na pato ya tundu, sasa tunaweza kupokea na kutuma data kwa mteja.


Mstari wa kamba = null;
wakati (kweli) (
mstari = in.readUTF(); // subiri mteja atume safu ya maandishi.
System.out.println("Mteja bubu amenitumia mstari huu: " + mstari);
System.out.println("Ninairudisha...");
out.writeUTF(line); // tuma mfuatano sawa wa maandishi kwa mteja.
System.out.println("Inasubiri mstari unaofuata...");
System.out.println();
}
) catch(Ila x) ( x.printStackTrace(); )
}
}

Ingiza java.net.*;
agiza java.io.*;

Mteja wa darasa la umma (
utupu tuli wa umma (String ar) (
int serverPort = 6666; // hapa lazima ueleze bandari ambayo seva imefungwa.
Anwani ya kamba = "127.0.0.1"; // hii ni anwani ya IP ya kompyuta ambapo programu yetu ya seva inafanya kazi.
// Hapa kuna anwani ya kompyuta sawa ambapo mteja atatekelezwa.

Jaribu (
InetAddress ipAddress = InetAddress.getByName(anwani); // unda kitu kinachoonyesha anwani ya IP iliyoelezwa hapo juu.
System.out.println("Yeyote kati yenu alisikia kuhusu soketi iliyo na anwani ya IP " + anwani +" na mlango " + serverPort + "?");
Soketi ya soketi = Soketi mpya(ipAddress, serverPort); // tengeneza tundu kwa kutumia anwani ya IP ya seva na bandari.
System.out.println("Ndiyo! Nilipata tu kushikilia programu.");

// Tunachukua mito ya pembejeo na pato ya tundu, sasa tunaweza kupokea na kutuma data na mteja.
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();

// Badilisha mitiririko kuwa aina nyingine ili kurahisisha kuchakata ujumbe wa maandishi.
DataInputStream in = DataInputStream(dhambi mpya);
DataOutputStream out = DataOutputStream(sout mpya);

// Unda mtiririko wa kusoma kutoka kwa kibodi.
Kibodi ya BufferedReader = BufferedReader mpya(mpya ya InputStreamReader(System.in));
Mstari wa kamba = null;
System.out.println("Chapa kitu na ubonyeze ingiza. Nitaituma kwa seva na kuwaambia inachofikiria.");
System.out.println();

Wakati (kweli) (
mstari = keyboard.readLine(); // subiri mtumiaji aingize kitu na bonyeza kitufe cha Ingiza.
System.out.println("Inatuma laini hii kwa seva...");
out.writeUTF(line); // tuma kamba ya maandishi iliyoingia kwa seva.
out.flush(); // lazimisha thread kumaliza kusambaza data.
mstari = in.readUTF(); // subiri hadi seva itume safu ya maandishi.
System.out.println("Seva ilikuwa ya adabu sana. Ilinitumia hivi: " + mstari);
System.out.println("Inaonekana kama seva imefurahishwa nasi. Endelea na uweke mistari zaidi.");
System.out.println();
}
) kamata (Isipokuwa x) (
x.printStackTrace();
}
}
}

Sasa hebu tukusanye kanuni:

Javac Server.java Client.java

Wacha tufungue madirisha mawili ya amri (DOS). Katika dirisha moja tunaingia:

Seva ya Java

na katika nyingine:

Mteja wa Java

Hakika kwa utaratibu huo.

Sasa ingiza mstari wa maandishi kwenye dirisha ambalo mteja anaendesha na bonyeza kitufe cha Ingiza. Tazama madirisha mawili na uone kinachotokea. Hatimaye, bonyeza Ctrl-C ili kusimamisha programu.

Ufafanuzi wa msimbo wa soketi

Hebu sasa tuzame kwa kina kidogo kwenye kanuni. Tayari unapata mawazo kwa kusoma maoni, lakini hebu tuchambue mistari michache muhimu ya kanuni.

Fikiria kipande kifuatacho cha nambari ya seva:

ServerSocket ss = new ServerSocket(bandari);
Soketi ya tundu = ss.kubali ();

Darasa la ServerSocket ni tofauti kidogo na darasa la Soketi. Darasa la Soketi ni tundu. Tofauti kuu kati ya ServerSocket ni kwamba inaweza kulazimisha programu kusubiri miunganisho kutoka kwa wateja. Unapoiunda, unahitaji kutaja bandari ambayo itafanya kazi nayo na uite njia yake ya kukubali (). Njia hii husababisha programu kusubiri miunganisho kwenye bandari maalum. Utekelezaji wa programu hutegemea wakati huu hadi mteja aunganishe. Baada ya kuunganishwa kwa mafanikio na mteja, kitu cha kawaida cha Soketi kinaundwa, ambacho unaweza kutumia kufanya shughuli zote zilizopo kwenye tundu. Kumbuka pia kuwa kitu hiki cha Soketi kinawakilisha mwisho mwingine wa muunganisho. Ikiwa unataka kutuma data kwa mteja, huwezi kutumia soketi yako mwenyewe kufanya hivi.

Ifuatayo tutaangalia darasa la Soketi. Unaweza kuunda kitu cha Soketi kwa kubainisha anwani ya IP na bandari. Unaweza kutumia darasa la InetAddress ili kuonyesha anwani ya IP (hii ndiyo njia inayopendekezwa). Ili kuunda kitu cha InetAddress, tumia njia ifuatayo:

InetAddress ipAddress = InetAddress.getByName(anwani);

Kumbuka kuwa katika programu yetu tulitumia anwani 127.0.0.1. Anwani hii maalum inaitwa anwani ya loopback - inaweka ramani kwa kompyuta ya ndani. Ikiwa una nia ya kuendesha mteja na seva kwenye kompyuta tofauti, basi unahitaji kutumia anwani ya IP ya seva inayofanana.

Baada ya kuunda InetAddress, tunaweza kuunda Soketi:

Soketi ya soketi = Soketi mpya(ipAddress, serverPort);

Baada ya kuunda kitu cha Soketi, unaweza kuchukua mitiririko ya pembejeo na matokeo ya tundu. Mkondo wa pembejeo utakuwezesha kusoma kutoka kwa tundu, na mkondo wa pato utakuwezesha kuandika kwenye tundu.

InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();

Mistari ifuatayo inabadilisha mitiririko kuwa aina zingine za mitiririko. Baada ya hayo, itakuwa rahisi kwetu kufanya kazi na vitu vya Kamba. Nambari hii haifanyi chochote na mtandao.

DataInputStream in = DataInputStream(dhambi mpya);
DataOutputStream out = DataOutputStream(sout mpya);

Kila kitu kingine ni rahisi sana - udanganyifu rahisi na vitu vya thread (hakuna soketi). Unaweza kutumia mitiririko yako uipendayo, piga simu njia unazopenda, na uhakikishe kuwa data inapitishwa hadi upande mwingine. Ikiwa huna ujuzi sana kuhusu kutumia nyuzi, napendekeza kupata makala kuhusu wao na kuisoma.