ការតភ្ជាប់រន្ធ។ ទ្រឹស្តីបណ្តាញ និងកម្រិតទាប។ ឧទាហរណ៍៖ Thread-safe DLL សម្រាប់ការផ្ញើសារតាមរន្ធ

បច្ចុប្បន្នភាពចុងក្រោយ: 31.10.2015

នៅស្នូល ការងារអ៊ីនធឺណិតរន្ធគឺផ្អែកលើពិធីការ TCP និង UDP ។ នៅក្នុង .NET រន្ធត្រូវបានតំណាងដោយថ្នាក់ System.NET.Sockets.Socket ដែលផ្តល់នូវចំណុចប្រទាក់កម្រិតទាបសម្រាប់ការទទួល និងផ្ញើសារតាមបណ្តាញ។

តោះមើលលក្ខណៈសម្បត្តិសំខាន់ៗនៃថ្នាក់នេះ៖

    AddressFamily៖ ត្រឡប់អាសយដ្ឋានទាំងអស់ដែលប្រើដោយរន្ធ។ ទ្រព្យសម្បត្តិនេះ។តំណាងឱ្យតម្លៃមួយក្នុងចំណោមតម្លៃដែលបានកំណត់នៅក្នុងការរាប់បញ្ចូលអាសយដ្ឋានគ្រួសារនៃឈ្មោះដូចគ្នា។ ការរាប់បញ្ចូលមាន 18 តម្លៃខុសៗគ្នា ដែលប្រើជាទូទៅបំផុតគឺ៖

    • បណ្តាញទំនាក់ទំនង៖ អាសយដ្ឋាន IPv4

      InterNetworkV6៖ អាសយដ្ឋាន IPv6

      Ipx៖ អាសយដ្ឋាន IPX ឬ SPX

      NetBios៖ អាសយដ្ឋាន NetBios

    មាន៖ ត្រឡប់បរិមាណទិន្នន័យដែលមានសម្រាប់ការអាន

    បានភ្ជាប់៖ ត្រឡប់ពិត ប្រសិនបើរន្ធត្រូវបានភ្ជាប់ទៅម៉ាស៊ីនពីចម្ងាយ

    LocalEndPoint៖ ត្រឡប់ ចំណុចក្នុងស្រុកដែលរន្ធត្រូវបានបើកដំណើរការ និងដែលវាទទួលទិន្នន័យ

    ProtocolType៖ ត្រឡប់​តម្លៃ​រាប់​បញ្ចូល ProtocolType មួយ​ដែល​តំណាង​ឱ្យ​ពិធីការ​ដែល​ប្រើ​ដោយ​រន្ធ។ មានតម្លៃដូចខាងក្រោម៖

    • IPSecAuthenticationHeader (ក្បាល IPv6 AH)

      IPSecEncapsulatingSecurityPayload (បឋមកថា IPv6 ESP)

      IPv6DestinationOptions (បឋមកថាជម្រើសទិសដៅ IPv6)

      IPv6FragmentHeader (ផ្នែកក្បាល IPv6 Fragment)

      IPv6HopByHopOptions (ចំណងជើង IPv6 Hop ដោយ Hop Options)

      IPv6NoNextHeader (IPv6 គ្មានបឋមកថាបន្ទាប់)

      IPv6RoutingHeader

      មិនស្គាល់ (មិនស្គាល់ពិធីការ)

      មិនបានបញ្ជាក់ (ពិធីការមិនបានបញ្ជាក់)

    តម្លៃនីមួយៗតំណាងឱ្យពិធីការដែលត្រូវគ្នា ប៉ុន្តែអ្វីដែលប្រើជាទូទៅបំផុតគឺ Tcp និង Udp ។

    RemoteEndPoint៖ ត្រឡប់អាសយដ្ឋានរបស់ម៉ាស៊ីនពីចម្ងាយដែលរន្ធត្រូវបានភ្ជាប់

    ប្រភេទរន្ធ៖ ត្រឡប់ប្រភេទរន្ធ។ តំណាងឱ្យតម្លៃមួយពីការរាប់បញ្ចូល SocketType៖

    • Dgram: រន្ធនឹងទទួល និងផ្ញើ datagrams ដោយ ពិធីការ Udp. ប្រភេទនេះ។រន្ធដំណើរការដោយភ្ជាប់ជាមួយប្រភេទពិធីការ - Udp និងតម្លៃ AddressFamily.InterNetwork

      ឆៅ៖ រន្ធមានសិទ្ធិចូលប្រើពិធីការមូលដ្ឋាន ស្រទាប់ដឹកជញ្ជូនហើយអាចប្រើពិធីការដូចជា ICMP និង IGMP ដើម្បីបញ្ជូនសារ

      Rdm: រន្ធអាចទាក់ទងជាមួយ ម៉ាស៊ីនពីចម្ងាយដោយគ្មានការដំឡើង ការតភ្ជាប់អចិន្រ្តៃយ៍. ប្រសិនបើសារដែលបានផ្ញើដោយរន្ធមិនអាចបញ្ជូនបានទេ រន្ធនឹងទទួលបានការជូនដំណឹងអំពីបញ្ហានេះ

      Seqpacket៖ ផ្តល់នូវការផ្ទេរទិន្នន័យពីរផ្លូវដែលអាចទុកចិត្តបានជាមួយនឹងការតភ្ជាប់ជាប់លាប់

      ស្ទ្រីម៖ ផ្តល់នូវការផ្ទេរទិន្នន័យពីរផ្លូវដែលអាចទុកចិត្តបានជាមួយនឹងការតភ្ជាប់អចិន្ត្រៃយ៍។ ការទំនាក់ទំនងប្រើពិធីការ TCP ដូច្នេះប្រភេទរន្ធនេះត្រូវបានប្រើដោយភ្ជាប់ជាមួយប្រភេទពិធីការ Tcp និងតម្លៃ AddressFamily.InterNetwork

      មិនស្គាល់៖ អាសយដ្ឋាន NetBios

អ្នក​អាច​ប្រើ​អ្នក​បង្កើត​មួយ​របស់​វា​ដើម្បី​បង្កើត​វត្ថុ​រន្ធ។ ឧទាហរណ៍ រន្ធដែលប្រើពិធីការ Tcp៖

រន្ធរន្ធ = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

ឬរន្ធដោយប្រើពិធីការ Udp៖

រន្ធរន្ធ = រន្ធថ្មី(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

ដូច្នេះនៅពេលបង្កើតរន្ធយើងអាចបញ្ជាក់ បន្សំផ្សេងគ្នាពិធីការ ប្រភេទរន្ធ តម្លៃពីការរាប់លេខអាសយដ្ឋានគ្រួសារ។ ទោះយ៉ាងណាក៏ដោយ ក្នុងពេលជាមួយគ្នានេះ មិនមែនការផ្សំទាំងអស់សុទ្ធតែត្រឹមត្រូវនោះទេ។ ដូច្នេះ ដើម្បីដំណើរការតាមរយៈពិធីការ Tcp យើងត្រូវបញ្ជាក់ប៉ារ៉ាម៉ែត្រដូចខាងក្រោម៖ AddressFamily.InterNetwork, SocketType.Stream និង ProtocolType.Tcp។ សម្រាប់ Udp សំណុំនៃប៉ារ៉ាម៉ែត្រនឹងខុសគ្នា៖ AddressFamily.InterNetwork, SocketType.Dgram និង ProtocolType.Udp។ សម្រាប់ពិធីការផ្សេងទៀត សំណុំនៃតម្លៃនឹងខុសគ្នា។ ដូច្នេះ ការប្រើរន្ធអាចត្រូវការចំណេះដឹងខ្លះអំពីរបៀបដែលពិធីការនីមួយៗដំណើរការ។ ទោះបីជាទាក់ទងនឹង Tcp និង Udp អ្វីគ្រប់យ៉ាងគឺសាមញ្ញណាស់។

គោលការណ៍ទូទៅនៃប្រតិបត្តិការរន្ធ

នៅពេលធ្វើការជាមួយរន្ធ ដោយមិនគិតពីពិធីការដែលបានជ្រើសរើស យើងនឹងពឹងផ្អែកលើវិធីសាស្រ្តនៃថ្នាក់ Socket៖

    យល់ព្រម (): បង្កើត វត្ថុថ្មី។រន្ធដើម្បីគ្រប់គ្រងការភ្ជាប់ចូល

    Bind(): ចងវត្ថុ Socket ទៅនឹងចំណុចបញ្ចប់មូលដ្ឋាន

    Close(): បិទរន្ធ

    Connect(): បង្កើតការតភ្ជាប់ទៅម៉ាស៊ីនពីចម្ងាយ

    Listen(): ចាប់ផ្តើមស្តាប់ការស្នើសុំចូល

    Poll(): កំណត់ស្ថានភាពនៃរន្ធ

    ទទួល(): ទទួលទិន្នន័យ

    Send(): ផ្ញើទិន្នន័យ

    Shutdown(): រារាំងការផ្ញើ និងទទួលទិន្នន័យនៅលើរន្ធ

អាស្រ័យលើពិធីការដែលបានប្រើ (TCP, UDP ។ល។) គោលការណ៍ទូទៅធ្វើការជាមួយរន្ធនឹងប្រែប្រួលបន្តិច។

នៅពេលប្រើពិធីការដែលទាមទារការបង្កើតការតភ្ជាប់ ដូចជា TCP ម៉ាស៊ីនមេត្រូវតែហៅវិធីសាស្ត្រចង ដើម្បីកំណត់ចំណុចដើម្បីស្តាប់ការភ្ជាប់ចូល ហើយបន្ទាប់មកចាប់ផ្តើមស្តាប់សម្រាប់ការតភ្ជាប់ដោយប្រើវិធីសាស្ត្រស្តាប់។ បន្ទាប់មក ដោយប្រើវិធីសាស្ត្រយល់ព្រម អ្នកអាចទទួលបានសំណើការតភ្ជាប់ចូលក្នុងទម្រង់ជាវត្ថុ Socket ដែលត្រូវបានប្រើដើម្បីធ្វើអន្តរកម្មជាមួយថ្នាំងពីចម្ងាយ។ នៅលើវត្ថុ Socket ដែលបានទទួល វិធីសាស្ត្រផ្ញើ និងទទួលត្រូវបានហៅរៀងៗខ្លួន ដើម្បីផ្ញើ និងទទួលទិន្នន័យ។ ប្រសិនបើចាំបាច់ត្រូវភ្ជាប់ទៅម៉ាស៊ីនមេ វិធីសាស្ត្រតភ្ជាប់ត្រូវបានហៅ។ វិធីសាស្ត្រផ្ញើ ឬទទួលក៏ត្រូវបានប្រើដើម្បីផ្លាស់ប្តូរទិន្នន័យជាមួយម៉ាស៊ីនមេផងដែរ។

ប្រសិនបើអ្នកកំពុងប្រើពិធីការគ្មានការតភ្ជាប់ដូចជា UDP នោះអ្នកមិនចាំបាច់ហៅវិធីសាស្ត្រស្តាប់ទេ បន្ទាប់ពីហៅវិធីសាស្ត្រចង។ ហើយក្នុងករណីនេះ វិធីសាស្ត្រ ReceiveFrom ត្រូវបានប្រើដើម្បីទទួលទិន្នន័យ ហើយវិធីសាស្ត្រ SendTo ត្រូវបានប្រើដើម្បីបញ្ជូនទិន្នន័យ។

រន្ធ

រន្ធគឺជាការបញ្ចប់មួយនៃបណ្តាញទំនាក់ទំនងពីរផ្លូវរវាងកម្មវិធីពីរដែលកំពុងដំណើរការនៅលើបណ្តាញ។ ដោយភ្ជាប់រន្ធពីរជាមួយគ្នា អ្នកអាចផ្ទេរទិន្នន័យរវាង ដំណើរការផ្សេងគ្នា(ក្នុងស្រុក ឬពីចម្ងាយ)។ ការអនុវត្តរន្ធផ្តល់នូវការរុំព័ទ្ធនៃបណ្តាញ និងពិធីការស្រទាប់ដឹកជញ្ជូន។

រន្ធត្រូវបានបង្កើតឡើងដំបូងសម្រាប់ UNIX នៅសាកលវិទ្យាល័យកាលីហ្វ័រញ៉ា Berkeley ។ នៅក្នុងយូនីក វិធីសាស្ត្រទំនាក់ទំនង I/O ធ្វើតាមក្បួនដោះស្រាយបើក/អាន/សរសេរ/បិទ។ មុននឹងប្រើប្រាស់ធនធាន ត្រូវតែបើកដោយមានការអនុញ្ញាតសមរម្យ និងការកំណត់ផ្សេងទៀត។ នៅពេលដែលធនធានត្រូវបានបើក ទិន្នន័យអាចត្រូវបានអានពី ឬសរសេរទៅ។ បន្ទាប់ពីប្រើប្រាស់ធនធាន អ្នកប្រើប្រាស់ត្រូវតែហៅវិធីសាស្ត្រ Close() ដើម្បីផ្តល់សញ្ញាដល់ប្រព័ន្ធប្រតិបត្តិការថាវាត្រូវបានធ្វើរួចជាមួយនឹងធនធាន។

ពេលណាទៅបន្ទប់វះកាត់ ប្រព័ន្ធយូនីកមូលនិធិត្រូវបានបន្ថែម ដំណើរការទំនាក់ទំនង(ទំនាក់ទំនងអន្តរដំណើរការ IPC)និងការផ្លាស់ប្តូរបណ្តាញ លំនាំបញ្ចូល-ទិន្នផលដែលធ្លាប់ស្គាល់ត្រូវបានខ្ចី។ ធនធានទាំងអស់ដែលត្រូវបានលាតត្រដាងសម្រាប់ការទំនាក់ទំនងនៅក្នុងយូនីក និងវីនដូ ត្រូវបានកំណត់អត្តសញ្ញាណដោយចំណុចទាញ។ អ្នកពិពណ៌នាទាំងនេះឬ ចំណុចទាញអាចចង្អុលទៅឯកសារ អង្គចងចាំ ឬបណ្តាញទំនាក់ទំនងផ្សេងទៀត ប៉ុន្តែតាមពិតចង្អុលទៅ រចនាសម្ព័ន្ធផ្ទៃក្នុងទិន្នន័យដែលប្រើដោយប្រព័ន្ធប្រតិបត្តិការ។ រន្ធដែលជាធនធានដូចគ្នាក៏ត្រូវបានតំណាងដោយអ្នកពិពណ៌នាផងដែរ។ ដូច្នេះសម្រាប់រន្ធ អាយុកាលរបស់ចំណុចទាញអាចបែងចែកជាបីដំណាក់កាល៖ បើក (បង្កើត) រន្ធ ទទួលពី ឬផ្ញើទៅរន្ធ ហើយចុងក្រោយបិទរន្ធ។

ចំណុចប្រទាក់ IPC សម្រាប់ទំនាក់ទំនងរវាងដំណើរការផ្សេងៗគ្នាត្រូវបានបង្កើតឡើងនៅលើកំពូលនៃវិធីសាស្ត្រ I/O ។ ពួកគេធ្វើឱ្យវាកាន់តែងាយស្រួលសម្រាប់រន្ធដើម្បីផ្ញើ និងទទួលទិន្នន័យ។ គោលដៅនីមួយៗត្រូវបានបញ្ជាក់ដោយអាសយដ្ឋានរន្ធ ដូច្នេះអាសយដ្ឋាននេះអាចត្រូវបានបញ្ជាក់នៅក្នុងម៉ាស៊ីនភ្ញៀវដើម្បីបង្កើតការតភ្ជាប់ទៅកាន់គោលដៅ។

ប្រភេទរន្ធ

មានរន្ធពីរប្រភេទសំខាន់ៗ - រន្ធស្ទ្រីម និងរន្ធទិន្នន័យទិន្នន័យ។

រន្ធស្ទ្រីម

រន្ធស្ទ្រីមគឺជារន្ធដែលមាន ការតភ្ជាប់ដែលបានបង្កើតឡើងដែលរួមមានការស្ទ្រីមនៃបៃដែលអាចជាទ្វេទិស មានន័យថាកម្មវិធីអាចផ្ញើ និងទទួលទិន្នន័យតាមរយៈចំណុចបញ្ចប់នេះ។

រន្ធស្ទ្រីមធានាការកែកំហុស គ្រប់គ្រងការដឹកជញ្ជូន និងរក្សាភាពស៊ីសង្វាក់គ្នានៃទិន្នន័យ។ វាអាចត្រូវបានពឹងផ្អែកលើការចែកចាយទិន្នន័យស្ទួនតាមលំដាប់លំដោយ។ រន្ធស្ទ្រីមក៏សមរម្យសម្រាប់ការបញ្ជូន បរិមាណធំទិន្នន័យ ចាប់តាំងពីការចំណាយលើសដែលទាក់ទងនឹងការបង្កើត ការតភ្ជាប់ដាច់ដោយឡែកសម្រាប់សារនីមួយៗដែលបានផ្ញើ ប្រហែលជាមិនអាចទទួលយកបានទេ។ បរិមាណតូចទិន្នន័យ។ រន្ធស្ទ្រីមសម្រេចបានកម្រិតគុណភាពនេះដោយប្រើពិធីការ ពិធីសារត្រួតពិនិត្យការបញ្ជូន (TCP). TCP ធានាថាទិន្នន័យទៅដល់ផ្នែកម្ខាងទៀតក្នុងលំដាប់ត្រឹមត្រូវ និងគ្មានកំហុស។

សម្រាប់ប្រភេទរន្ធនេះ ផ្លូវត្រូវបានបង្កើតឡើង មុនពេលដែលសារត្រូវបានផ្ញើ។ នេះធានាថាភាគីទាំងពីរដែលពាក់ព័ន្ធនឹងអន្តរកម្មទទួលយក និងឆ្លើយតប។ ប្រសិនបើកម្មវិធីផ្ញើសារពីរទៅអ្នកទទួល វាត្រូវបានធានាថាសារនឹងត្រូវបានទទួលក្នុងលំដាប់ដូចគ្នា។

ទោះយ៉ាងណាក៏ដោយ សារបុគ្គលអាចត្រូវបានបំបែកទៅជាកញ្ចប់ព័ត៌មាន ហើយមិនមានវិធីដើម្បីកំណត់ព្រំដែននៃកំណត់ត្រានោះទេ។ នៅពេលប្រើ TCP ពិធីការនេះយកចិត្តទុកដាក់ក្នុងការបំបែកទិន្នន័យដែលបានបញ្ជូនចូលទៅក្នុងកញ្ចប់ព័ត៌មានដែលមានទំហំសមស្រប ដោយបញ្ជូនពួកវាទៅកាន់បណ្តាញ ហើយផ្គុំពួកវាឡើងវិញនៅផ្នែកម្ខាងទៀត។ កម្មវិធីដឹងតែអ្វីដែលវាត្រូវបានផ្ញើទៅស្រទាប់ TCP ប៉ុណ្ណោះ។ ចំនួនជាក់លាក់ bytes និងម្ខាងទៀតទទួលបានបៃទាំងនេះ។ នៅក្នុងវេន TCP មានប្រសិទ្ធភាពបំបែកទិន្នន័យនេះទៅជាកញ្ចប់ព័ត៌មាន ទំហំសមរម្យទទួលកញ្ចប់ព័ត៌មានទាំងនេះនៅផ្នែកម្ខាងទៀត ទាញយកទិន្នន័យពីពួកវា ហើយបញ្ចូលពួកវាជាមួយគ្នា។

ស្ទ្រីមផ្អែកលើការតភ្ជាប់ច្បាស់លាស់៖ រន្ធ A ស្នើសុំការតភ្ជាប់ទៅរន្ធ B ហើយរន្ធ B ទទួលយក ឬបដិសេធសំណើការតភ្ជាប់។

ប្រសិនបើទិន្នន័យត្រូវតែត្រូវបានធានាថាត្រូវបានបញ្ជូនទៅផ្នែកម្ខាងទៀត ឬទំហំនៃទិន្នន័យមានទំហំធំនោះ រន្ធស្ទ្រីមគឺល្អសម្រាប់រន្ធ datagram ។ ដូច្នេះ ប្រសិនបើទំនាក់ទំនងដែលអាចទុកចិត្តបានរវាងកម្មវិធីទាំងពីរមានសារៈសំខាន់បំផុត សូមជ្រើសរើសរន្ធស្ទ្រីម។

ម៉ាស៊ីនមេ អ៊ីមែលបង្ហាញឧទាហរណ៍នៃកម្មវិធីដែលត្រូវតែបញ្ជូនមាតិកាតាមលំដាប់លំដោយត្រឹមត្រូវ ដោយមិនមានការចម្លង ឬលុបចោល។ រន្ធស្ទ្រីមពឹងផ្អែកលើ TCP ដើម្បីធានាថាសារត្រូវបានបញ្ជូនទៅកាន់គោលដៅរបស់ពួកគេ។

រន្ធ Datagram

រន្ធ Datagram ជួនកាលត្រូវបានគេហៅថារន្ធ connectless ពោលគឺមិនមានការតភ្ជាប់ច្បាស់លាស់ណាមួយត្រូវបានបង្កើតឡើងរវាងពួកវាទេ - សារត្រូវបានផ្ញើទៅកាន់រន្ធដែលបានបញ្ជាក់ ហើយតាមនោះ អាចត្រូវបានទទួលពីរន្ធដែលបានបញ្ជាក់។

បើប្រៀបធៀបទៅនឹងរន្ធ datagram រន្ធស្ទ្រីមពិតជាផ្តល់ច្រើនជាងនេះ។ វិធីសាស្រ្តដែលអាចទុកចិត្តបាន។ប៉ុន្តែសម្រាប់កម្មវិធីមួយចំនួន ការចំណាយលើការភ្ជាប់ជាមួយការបង្កើតការតភ្ជាប់ច្បាស់លាស់គឺមិនអាចទទួលយកបានទេ (ឧទាហរណ៍ ម៉ាស៊ីនមេពេលវេលានៃថ្ងៃដែលផ្តល់ការធ្វើសមកាលកម្មពេលវេលាដល់អតិថិជនរបស់វា)។ យ៉ាងណាមិញ ការបង្កើតការតភ្ជាប់ដែលអាចទុកចិត្តបានទៅម៉ាស៊ីនមេត្រូវការពេលវេលា ដែលគ្រាន់តែណែនាំការពន្យារពេលក្នុងសេវាកម្ម ហើយកិច្ចការរបស់កម្មវិធីម៉ាស៊ីនមេត្រូវបរាជ័យ។ ដើម្បីកាត់បន្ថយការចំណាយលើស អ្នកគួរតែប្រើរន្ធ datagram ។

ការប្រើប្រាស់រន្ធ datagram តម្រូវឱ្យផ្ទេរទិន្នន័យពីម៉ាស៊ីនភ្ញៀវទៅម៉ាស៊ីនមេ User Datagram Protocol (UDP). នៅក្នុងពិធីការនេះ ការរឹតបន្តឹងមួយចំនួនត្រូវបានដាក់លើទំហំនៃសារ និងមិនដូចរន្ធស្ទ្រីម ដែលអាចផ្ញើសារទៅម៉ាស៊ីនមេគោលដៅបាន រន្ធទិន្នន័យទិន្នន័យមិនផ្តល់ភាពជឿជាក់ទេ។ ប្រសិនបើទិន្នន័យត្រូវបានបាត់បង់នៅកន្លែងណាមួយនៅលើបណ្តាញ នោះម៉ាស៊ីនមេនឹងមិនរាយការណ៍កំហុសទេ។

បន្ថែមពីលើប្រភេទទាំងពីរដែលបានពិភាក្សា វាក៏មានទម្រង់ទូទៅនៃរន្ធដែលហៅថា រន្ធឆៅ ឬឆៅ។

រន្ធឆៅ

គោលបំណងសំខាន់នៃការប្រើប្រាស់រន្ធឆៅគឺដើម្បីឆ្លងកាត់យន្តការដែលកុំព្យូទ័រគ្រប់គ្រង TCP/IP ។ នេះត្រូវបានសម្រេចដោយការផ្តល់នូវការអនុវត្តពិសេសនៃជង់ TCP/IP ដែលបដិសេធយន្តការដែលផ្តល់ដោយជង់ TCP/IP នៅក្នុងខឺណែល - កញ្ចប់ព័ត៌មានត្រូវបានបញ្ជូនដោយផ្ទាល់ទៅកម្មវិធី ហើយដូច្នេះត្រូវបានដំណើរការយ៉ាងមានប្រសិទ្ធភាពជាងពេលឆ្លងកាត់របស់អតិថិជន។ ជង់ពិធីការចម្បង។

តាមនិយមន័យ រន្ធឆៅគឺជារន្ធដែលទទួលកញ្ចប់ព័ត៌មាន ឆ្លងកាត់ស្រទាប់ TCP និង UDP នៅក្នុងជង់ TCP/IP ហើយបញ្ជូនពួកវាដោយផ្ទាល់ទៅកម្មវិធី។

នៅពេលប្រើរន្ធបែបនេះ កញ្ចប់ព័ត៌មានមិនឆ្លងកាត់តម្រង TCP/IP ពោលគឺឧ។ មិន​ត្រូវ​បាន​ដំណើរការ​តាម​វិធី​ណា​មួយ​ឡើយ ហើយ​បង្ហាញ​ជា​ទម្រង់​ដើម​របស់​វា។ ក្នុងករណីនេះ វាជាទំនួលខុសត្រូវរបស់កម្មវិធីទទួល ដើម្បីដំណើរការទិន្នន័យទាំងអស់ឱ្យបានត្រឹមត្រូវ និងអនុវត្តសកម្មភាពដូចជាការដកបឋមកថា និងវាលញែក - ដូចជាការរួមបញ្ចូលជង់ TCP/IP តូចមួយនៅក្នុងកម្មវិធី។

ទោះជាយ៉ាងណាក៏ដោយ វាមិនញឹកញាប់ទេដែលអ្នកប្រហែលជាត្រូវការកម្មវិធីដែលទាក់ទងនឹងរន្ធឆៅ។ ប្រសិនបើអ្នកមិនសរសេរប្រព័ន្ធ កម្មវិធីឬកម្មវិធីស្រដៀងនឹងឧបករណ៍វិភាគកញ្ចប់ព័ត៌មាន អ្នកនឹងមិនចាំបាច់ចូលទៅក្នុងព័ត៌មានលម្អិតបែបនេះទេ។ រន្ធឆៅត្រូវបានប្រើជាចម្បងក្នុងការអភិវឌ្ឍន៍កម្មវិធីពិសេសកម្រិតទាប។ ឧទាហរណ៍ ឧបករណ៍ប្រើប្រាស់ TCP/IP ផ្សេងៗដូចជាផ្លូវដាន ភីង ឬ arp ប្រើរន្ធឆៅ។

ការធ្វើការជាមួយរន្ធឆៅទាមទារចំណេះដឹងរឹងមាំ ពិធីការមូលដ្ឋាន TCP/UDP/IP ។

ច្រក

ច្រកត្រូវបានកំណត់ដើម្បីអនុញ្ញាតឱ្យមានបញ្ហានៃការទំនាក់ទំនងក្នុងពេលដំណាលគ្នាជាមួយកម្មវិធីជាច្រើន។ សំខាន់វាពង្រីកគំនិតនៃអាសយដ្ឋាន IP ។ កុំព្យូទ័រដែលកំពុងដំណើរការកម្មវិធីច្រើនក្នុងពេលតែមួយ ដោយទទួលបានកញ្ចប់ព័ត៌មានពីបណ្តាញ អាចកំណត់អត្តសញ្ញាណដំណើរការគោលដៅដោយប្រើ ចំនួនតែមួយគត់ច្រកដែលបានបញ្ជាក់នៅពេលបង្កើតការតភ្ជាប់។

រន្ធមួយមានអាសយដ្ឋាន IP របស់ម៉ាស៊ីន និងលេខច្រកដែលបានប្រើ កម្មវិធី TCP. ដោយសារអាសយដ្ឋាន IP មានតែមួយគត់នៅលើអ៊ីនធឺណិត ហើយលេខច្រកគឺមានតែមួយគត់នៅលើម៉ាស៊ីននីមួយៗ លេខរន្ធក៏មានតែមួយគត់នៅលើអ៊ីនធឺណិតទាំងមូល។ លក្ខណៈនេះអនុញ្ញាតឱ្យដំណើរការទំនាក់ទំនងលើបណ្តាញជាមួយនឹងដំណើរការមួយផ្សេងទៀតដោយផ្អែកលើលេខរន្ធ។

លេខច្រកត្រូវបានបម្រុងទុកសម្រាប់សេវាកម្មជាក់លាក់ - ទាំងនេះគឺជាលេខច្រកល្បី ដូចជាច្រក 21 ដែលប្រើក្នុង FTP ។ កម្មវិធី​របស់​អ្នក​អាច​ប្រើ​លេខ​ច្រក​ណា​មួយ​ដែល​មិន​ទាន់​បាន​បម្រុង​ទុក និង​មិន​ទាន់​ប្រើ។ ទីភ្នាក់ងារ Internet Assigned Numbers Authority (IANA)រក្សាបញ្ជីនៃលេខច្រកដែលគេស្គាល់ជាទូទៅ។

ជាធម្មតាកម្មវិធី client-server ដោយប្រើ sockets មានពីរ កម្មវិធីផ្សេងគ្នា- ម៉ាស៊ីនភ្ញៀវចាប់ផ្តើមការតភ្ជាប់ជាមួយគោលដៅ (ម៉ាស៊ីនមេ) និងម៉ាស៊ីនមេដែលកំពុងរង់ចាំការតភ្ជាប់ពីអតិថិជន។

ឧទាហរណ៍ នៅខាងអតិថិជន កម្មវិធីត្រូវតែដឹងពីអាសយដ្ឋានគោលដៅ និងលេខច្រក។ តាមរយៈការផ្ញើសំណើការតភ្ជាប់ អតិថិជនព្យាយាមបង្កើតការតភ្ជាប់ជាមួយម៉ាស៊ីនមេ៖

ប្រសិនបើព្រឹត្តិការណ៍អភិវឌ្ឍដោយជោគជ័យ ផ្តល់ថាម៉ាស៊ីនមេត្រូវបានចាប់ផ្តើម មុនពេលអតិថិជនព្យាយាមភ្ជាប់ទៅវា នោះម៉ាស៊ីនមេយល់ព្រមនឹងការតភ្ជាប់។ ដោយបានផ្តល់ការយល់ព្រម កម្មវិធីម៉ាស៊ីនមេបង្កើតរន្ធថ្មីដើម្បីធ្វើអន្តរកម្មជាពិសេសជាមួយអតិថិជនដែលបានបង្កើតការតភ្ជាប់៖

ឥឡូវនេះ ម៉ាស៊ីនភ្ញៀវ និងម៉ាស៊ីនមេអាចធ្វើអន្តរកម្មជាមួយគ្នា ដោយអានសារនីមួយៗពីរន្ធផ្ទាល់ខ្លួនរបស់ពួកគេ ហើយតាមនោះ ការសរសេរសារ។

ធ្វើការជាមួយរន្ធនៅក្នុង .NET

ការគាំទ្ររន្ធនៅក្នុង .NET ត្រូវបានផ្តល់ដោយថ្នាក់នៅក្នុង namespace System.Net.Sockets- ចូរចាប់ផ្តើមជាមួយនឹងការពិពណ៌នាសង្ខេបរបស់ពួកគេ។

ថ្នាក់សម្រាប់ធ្វើការជាមួយរន្ធ
ថ្នាក់ ការពិពណ៌នា
MulticastOption ថ្នាក់ MulticastOption កំណត់តម្លៃអាសយដ្ឋាន IP សម្រាប់ការចូលរួម ឬចាកចេញពីក្រុម IP ។
បណ្តាញស្ទ្រីម ថ្នាក់ NetworkStream អនុវត្ត ថ្នាក់មូលដ្ឋានស្ទ្រីមដែលទិន្នន័យត្រូវបានផ្ញើ និងដែលវាត្រូវបានទទួល។ នេះគឺជាអរូបីកម្រិតខ្ពស់ដែលតំណាងឱ្យការភ្ជាប់ទៅបណ្តាញទំនាក់ទំនង TCP/IP ។
TcpClient ថ្នាក់ TcpClient បង្កើតនៅលើ Socket class ដើម្បីផ្តល់សេវាកម្ម TCP បន្ថែមទៀត កម្រិតខ្ពស់. TcpClient ផ្តល់នូវវិធីសាស្រ្តជាច្រើនសម្រាប់ការផ្ញើ និងទទួលទិន្នន័យតាមបណ្តាញ។
TcpListener class នេះក៏បង្កើតនៅលើ Socket class កម្រិតទាបផងដែរ។ គោលបំណងចម្បងរបស់វាគឺកម្មវិធីម៉ាស៊ីនមេ។ វាស្តាប់ការស្នើសុំការតភ្ជាប់ចូលពីអតិថិជន និងជូនដំណឹងអំពីកម្មវិធីនៃការតភ្ជាប់ណាមួយ។
UdpClient UDP គឺជាពិធីការគ្មានការតភ្ជាប់ ដូច្នេះមុខងារផ្សេងគ្នាគឺត្រូវបានទាមទារដើម្បីអនុវត្តសេវាកម្ម UDP នៅក្នុង .NET ។
SocketException ការលើកលែងនេះត្រូវបានបោះចោលនៅពេលដែលមានកំហុសកើតឡើងនៅលើរន្ធ។
រន្ធ ថ្នាក់ចុងក្រោយនៅក្នុង System.Net.Sockets namespace គឺជាថ្នាក់ Socket ខ្លួនឯង។ វាផ្តល់នូវមុខងារជាមូលដ្ឋាននៃកម្មវិធីរន្ធ។

ថ្នាក់រន្ធ

ថ្នាក់ Socket លេង តួនាទីសំខាន់ក្នុង​ការ​សរសេរ​កម្មវិធី​បណ្តាញ ធានា​នូវ​ដំណើរការ​ទាំង​ម៉ាស៊ីនភ្ញៀវ និង​ម៉ាស៊ីនមេ។ ជាចម្បង ការហៅទៅកាន់វិធីសាស្រ្តនៃថ្នាក់នេះអនុវត្ត ការត្រួតពិនិត្យចាំបាច់វិធីសាស្រ្តដែលទាក់ទងនឹងសុវត្ថិភាព រួមទាំងការត្រួតពិនិត្យការអនុញ្ញាតសុវត្ថិភាព បន្ទាប់ពីនោះពួកគេត្រូវបានបញ្ជូនបន្តទៅសមភាគីនៃវិធីសាស្រ្តទាំងនេះនៅក្នុង Windows Sockets API ។

មុន​នឹង​ងាក​ទៅ​មើល​ឧទាហរណ៍​នៃ​ការ​ប្រើ Socket class សូម​មើល​លក្ខណៈ​សម្បត្តិ និង​វិធីសាស្ត្រ​សំខាន់ៗ​មួយ​ចំនួន​នៃ class នេះ៖

លក្ខណសម្បត្តិ និងវិធីសាស្រ្តនៃថ្នាក់ Socket
ទ្រព្យសម្បត្តិឬវិធីសាស្រ្ត ការពិពណ៌នា
អាសយដ្ឋានគ្រួសារ ផ្តល់ឱ្យគ្រួសារអាសយដ្ឋាន socket - តម្លៃពី Socket.AddressFamily enumeration ។
មាន ត្រឡប់ចំនួនទិន្នន័យដែលមានសម្រាប់ការអាន។
ការទប់ស្កាត់ ទទួលឬកំណត់តម្លៃដែលបង្ហាញថារន្ធស្ថិតនៅក្នុងរបៀបទប់ស្កាត់។
បានភ្ជាប់ ត្រឡប់តម្លៃដែលបង្ហាញថាតើរន្ធត្រូវបានភ្ជាប់ទៅម៉ាស៊ីនពីចម្ងាយ។
LocalEndPoint ផ្តល់ចំណុចបញ្ចប់ក្នុងស្រុក។
ប្រភេទពិធីការ ផ្តល់ប្រភេទពិធីការនៃរន្ធ។
RemoteEndPoint ផ្តល់ចំណុចបញ្ចប់រន្ធពីចម្ងាយ។
ប្រភេទរន្ធ ផ្តល់ប្រភេទរន្ធ។
ទទួលយក() បង្កើតរន្ធថ្មីដើម្បីដោះស្រាយសំណើការតភ្ជាប់ចូល។
ចង() ភ្ជាប់រន្ធមួយទៅចំណុចបញ្ចប់ក្នុងតំបន់ ដើម្បីស្តាប់សំណើការតភ្ជាប់ចូល។
បិទ() បង្ខំរន្ធបិទ។
ភ្ជាប់() បង្កើតការតភ្ជាប់ជាមួយម៉ាស៊ីនពីចម្ងាយ។
GetSocketOption() ត្រឡប់តម្លៃ SocketOption ។
IOControl() កំណត់របៀបប្រតិបត្តិការកម្រិតទាបសម្រាប់រន្ធ។ វិធីសាស្រ្តនេះផ្តល់នូវការចូលប្រើកម្រិតទាបទៅកាន់ថ្នាក់ Socket មូលដ្ឋាន។
ស្តាប់() ដាក់រន្ធនៅក្នុងរបៀបស្តាប់ (រង់ចាំ) ។ វិធីសាស្រ្តនេះគឺសម្រាប់តែកម្មវិធីម៉ាស៊ីនមេប៉ុណ្ណោះ។
ទទួល() ទទួលទិន្នន័យពីរន្ធដែលបានតភ្ជាប់។
ការស្ទង់មតិ() កំណត់ស្ថានភាពនៃរន្ធ។
ជ្រើសរើស() ពិនិត្យស្ថានភាពនៃរន្ធមួយ ឬច្រើន។
ផ្ញើ() ផ្ញើទិន្នន័យទៅរន្ធដែលបានភ្ជាប់។
SetSocketOption() កំណត់ជម្រើសរន្ធ។
បិទ () បិទដំណើរការបញ្ជូន និងទទួលនៅលើរន្ធ។

VSEVOLOD STAKHOV

ការសរសេរកម្មវិធីរន្ធ

បណ្តាញភាគច្រើន កម្មវិធីម៉ាស៊ីនមេរៀបចំដោយប្រើរន្ធ។ ជាការសំខាន់ រន្ធគឺស្រដៀងទៅនឹងឯកសារពិពណ៌នាជាមួយមួយ។ ភាពខុសគ្នាសំខាន់- រន្ធត្រូវបានប្រើសម្រាប់ការទំនាក់ទំនងរវាងកម្មវិធីទាំងនៅលើបណ្តាញឬនៅលើ ម៉ាស៊ីនក្នុងស្រុក. ដូច្នេះអ្នកសរសេរកម្មវិធីមិនមានបញ្ហាជាមួយនឹងការបញ្ជូនទិន្នន័យទេ រន្ធធ្វើវាសម្រាប់គាត់។ អ្នកគ្រាន់តែត្រូវប្រាកដថាប៉ារ៉ាម៉ែត្ររន្ធនៃកម្មវិធីទាំងពីរត្រូវគ្នា។

ដូច្នេះរន្ធបណ្តាញគឺជារចនាសម្ព័ន្ធផ្គូផ្គងដែលធ្វើសមកាលកម្មយ៉ាងតឹងរ៉ឹងជាមួយគ្នា។ ដើម្បីបង្កើតរន្ធនៅលើប្រព័ន្ធប្រតិបត្តិការណាមួយដែលគាំទ្រពួកវា សូមប្រើមុខងាររន្ធ (ជាសំណាងល្អ រន្ធត្រូវបានធ្វើឱ្យមានលក្ខណៈស្តង់ដារគ្រប់គ្រាន់ដែលពួកវាអាចត្រូវបានប្រើដើម្បីផ្ទេរទិន្នន័យរវាងកម្មវិធីដែលកំពុងដំណើរការ។ វេទិកាផ្សេងគ្នា) ទម្រង់មុខងារគឺ៖

int socket (int domain, int type, int protocol);

ប៉ារ៉ាម៉ែត្រដែនបញ្ជាក់ប្រភេទនៃពិធីការដឹកជញ្ជូន i.e. ពិធីការចែកចាយកញ្ចប់បណ្តាញ។ បច្ចុប្បន្នពិធីការខាងក្រោមត្រូវបានគាំទ្រ (ប៉ុន្តែសូមចំណាំថាសម្រាប់ ប្រភេទផ្សេងគ្នាប្រភេទពិធីការនៃរចនាសម្ព័ន្ធអាសយដ្ឋាននឹងខុសគ្នា)៖

  • PF_UNIX ឬ PF_LOCALការទំនាក់ទំនងក្នុងស្រុកសម្រាប់ UNIX OS (និងស្រដៀងគ្នា)។
  • PF_INET - IPv4, IP- ពិធីការអ៊ីនធឺណិត ដែលជារឿងធម្មតាបំផុតឥឡូវនេះ (អាសយដ្ឋាន 32 ប៊ីត) ។
  • PF_INET6- IPv6 ដែលជាជំនាន់បន្ទាប់នៃពិធីការ IP (IPng) - អាសយដ្ឋាន 128 ប៊ីត។
  • PF_IPX - IPX- ពិធីការ Novell ។

ពិធីការផ្សេងទៀតត្រូវបានគាំទ្រ ប៉ុន្តែ 4 នេះគឺពេញនិយមបំផុត។

ប៉ារ៉ាម៉ែត្រប្រភេទមានន័យថាប្រភេទរន្ធ i.e. របៀបដែលទិន្នន័យនឹងត្រូវបានផ្ទេរ៖ ថេរ SOCK_STREAM ត្រូវបានប្រើជាធម្មតា ការប្រើប្រាស់របស់វាមានន័យ ការផ្ទេរសុវត្ថិភាពលំហូរទិន្នន័យទ្វេទិសជាមួយនឹងការគ្រប់គ្រងកំហុស។ ជាមួយនឹងវិធីសាស្រ្តនៃការផ្ទេរទិន្នន័យនេះ អ្នកសរសេរកម្មវិធីមិនចាំបាច់ព្រួយបារម្ភអំពីការដោះស្រាយកំហុសបណ្តាញទេ ទោះបីជាវាមិនការពារប្រឆាំងនឹងកំហុសឡូជីខល ដែលមានសារៈសំខាន់សម្រាប់ម៉ាស៊ីនមេបណ្តាញក៏ដោយ។

ប៉ារ៉ាម៉ែត្រពិធីការបញ្ជាក់ ប្រភេទជាក់លាក់ពិធីការសម្រាប់ដែនដែលបានផ្តល់ឱ្យ ឧទាហរណ៍ IPPROTO_TCP ឬ IPPROTO_UDP (ប៉ារ៉ាម៉ែត្រប្រភេទត្រូវតែនៅក្នុង ក្នុងករណីនេះជា SOCK_DGRAM)។

មុខងាររន្ធគ្រាន់តែបង្កើតចំណុចបញ្ចប់មួយ ហើយត្រឡប់ចំណុចទាញរន្ធ។ រហូតទាល់តែរន្ធត្រូវបានភ្ជាប់ទៅអាសយដ្ឋានពីចម្ងាយដោយប្រើមុខងារតភ្ជាប់ ទិន្នន័យមិនអាចបញ្ជូនតាមរយៈវាបានទេ! ប្រសិនបើកញ្ចប់ព័ត៌មានត្រូវបានបាត់បង់នៅលើបណ្តាញ ឧ. នៅពេលដែលការទំនាក់ទំនងបរាជ័យកើតឡើង បំពង់ខូច - សញ្ញា SIGPIPE ត្រូវបានផ្ញើទៅកម្មវិធីដែលបង្កើតរន្ធ ដូច្នេះវាត្រូវបានណែនាំឱ្យចាត់តាំងអ្នកដោះស្រាយ សញ្ញានេះ។សញ្ញាមុខងារ។ បន្ទាប់ពីរន្ធមួយត្រូវបានភ្ជាប់ទៅមួយទៀតដោយប្រើមុខងារតភ្ជាប់ ទិន្នន័យអាចត្រូវបានបញ្ជូនពីលើវាដោយប្រើមុខងារអាន-សរសេរស្តង់ដារ ឬមុខងារបញ្ជូនពិសេស។ បន្ទាប់ពីបញ្ចប់ការងាររន្ធត្រូវតែបិទដោយប្រើមុខងារបិទ។ ដើម្បីបង្កើត កម្មវិធីអតិថិជនវាគ្រប់គ្រាន់ដើម្បីភ្ជាប់រន្ធមូលដ្ឋានជាមួយនឹងមុខងារតភ្ជាប់ពីចម្ងាយ (ម៉ាស៊ីនមេ) ។ ទម្រង់នៃមុខងារនេះគឺ៖

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

ប្រសិនបើមានកំហុស មុខងារត្រឡប់ -1 ស្ថានភាពកំហុសអាចទទួលបានដោយប្រើ ប្រព័ន្ធប្រតិបត្តិការ. នៅ ការងារជោគជ័យត្រលប់មកវិញ 0. រន្ធមួយ ពេលដែលភ្ជាប់រួច ភាគច្រើនមិនអាចភ្ជាប់ម្តងទៀតបានទេ ដូចជាកើតឡើង ឧទាហរណ៍នៅក្នុងពិធីការ IP ។ ប៉ារ៉ាម៉ែត្រ sock_fd បញ្ជាក់អ្នកពិពណ៌នារន្ធ រចនាសម្ព័ន្ធ serv_addr ផ្តល់អាសយដ្ឋានចំណុចបញ្ចប់ពីចម្ងាយ addr_len ផ្ទុកប្រវែង serv_addr (ប្រភេទ socketlen_t មានប្រភពដើមជាប្រវត្តិសាស្ត្រ វាជាធម្មតាដូចគ្នានឹង វាយ int) ភាគច្រើន ប៉ារ៉ាម៉ែត្រសំខាន់នៅក្នុងមុខងារនេះ - អាសយដ្ឋាននៃរន្ធពីចម្ងាយ។ តាមធម្មជាតិ វាមិនដូចគ្នាសម្រាប់ពិធីការផ្សេងៗទេ ដូច្នេះខ្ញុំនឹងរៀបរាប់នៅទីនេះនូវរចនាសម្ព័ន្ធអាសយដ្ឋានសម្រាប់តែពិធីការ IP (v4) ប៉ុណ្ណោះ។ សម្រាប់ការនេះ រចនាសម្ព័ន្ធឯកទេស sockaddr_in ត្រូវបានប្រើ (វាត្រូវតែត្រូវបានដេញដោយផ្ទាល់ទៅប្រភេទ sockaddr នៅពេលដែល ហៅភ្ជាប់) វាលនៃរចនាសម្ព័ន្ធនេះមើលទៅដូចនេះ:

រចនាសម្ព័ន្ធ sockaddr_in (

Sa_family_t sin_family; – កំណត់គ្រួសារអាសយដ្ឋាន ត្រូវតែជា AF_INET ជានិច្ច

U_int16_t sin_port; - ច្រករន្ធនៅក្នុងលំដាប់បណ្តាញបៃ

រចនាសម្ព័ន្ធ in_addr sin_addr; - រចនាសម្ព័ន្ធដែលមានអាសយដ្ឋាន IP

រចនាសម្ព័ន្ធពិពណ៌នាអាសយដ្ឋាន IP៖

រចនាសម្ព័ន្ធ in_addr(

U_int32_t s_addr; - រន្ធអាសយដ្ឋាន IP តាមលំដាប់លំដោយបណ្តាញ

ចំណាំលំដាប់បៃពិសេសនៅក្នុងវាលចំនួនគត់ទាំងអស់។ ដើម្បីបំប្លែងលេខច្រកទៅជាលំដាប់បណ្តាញបៃ អ្នកអាចប្រើ htons macro ( ខ្លីដែលមិនបានចុះហត្ថលេខាច្រក) ។ វាមានសារៈសំខាន់ខ្លាំងណាស់ក្នុងការប្រើប្រភេទជាក់លាក់នៃចំនួនគត់នេះ - ចំនួនគត់ខ្លីដែលមិនបានចុះហត្ថលេខា។

អាសយដ្ឋាន IPv4 ត្រូវបានបែងចែកទៅជាតែមួយ ការផ្សាយ (ការផ្សាយ) និងក្រុម (ពហុខាស) ។ អាសយដ្ឋាននីមួយៗចង្អុលទៅចំណុចប្រទាក់ម៉ាស៊ីនមួយ អាសយដ្ឋានផ្សាយចង្អុលទៅម៉ាស៊ីនទាំងអស់នៅលើបណ្តាញ ហើយអាសយដ្ឋានពហុខាសចង្អុលទៅម៉ាស៊ីនទាំងអស់នៅក្នុងក្រុមពហុខាស។ រចនាសម្ព័ន្ធ in_addr អាចត្រូវបានកំណត់ទៅអាសយដ្ឋានណាមួយនៃអាសយដ្ឋានទាំងនេះ។ ប៉ុន្តែសម្រាប់អតិថិជន socket នៅក្នុងករណីភាគច្រើន អាសយដ្ឋានតែមួយត្រូវបានចាត់តាំង។ ករណីលើកលែងគឺនៅពេលដែលវាចាំបាច់ដើម្បីស្កេនទាំងមូល បណ្តាញក្នុងស្រុកក្នុងការស្វែងរកម៉ាស៊ីនមេ បន្ទាប់មកអ្នកអាចប្រើអាសយដ្ឋានផ្សាយ។ បន្ទាប់មក ទំនងជាម៉ាស៊ីនមេត្រូវតែរាយការណ៍អាសយដ្ឋាន IP ពិតប្រាកដរបស់វា ហើយរន្ធសម្រាប់ការផ្ទេរទិន្នន័យបន្ថែមត្រូវតែភ្ជាប់ទៅវា។ មិនមានការបញ្ជូនទិន្នន័យតាមរយៈអាសយដ្ឋានផ្សាយទេ។ គំនិតល្អ។ព្រោះវាមិនដឹងថាម៉ាស៊ីនមេណាមួយកំពុងដំណើរការសំណើ។ ដូច្នេះ បច្ចុប្បន្ន រន្ធដែលផ្តោតលើការតភ្ជាប់អាចប្រើតែអាសយដ្ឋានតែមួយប៉ុណ្ណោះ។ សម្រាប់ម៉ាស៊ីនមេរន្ធស្តាប់អាសយដ្ឋាន ស្ថានភាពគឺខុសគ្នា៖ នៅទីនេះវាត្រូវបានអនុញ្ញាតឱ្យប្រើអាសយដ្ឋានផ្សាយដើម្បីឆ្លើយតបភ្លាមៗចំពោះសំណើរបស់អតិថិជនសម្រាប់ទីតាំងរបស់ម៉ាស៊ីនមេ។ ប៉ុន្តែរឿងដំបូង។ ដូចដែលអ្នកបានកត់សម្គាល់នៅក្នុងរចនាសម្ព័ន្ធ sockaddr_in វាលអាសយដ្ឋាន IP ត្រូវបានតំណាងជាចំនួនគត់វែងដែលមិនបានចុះហត្ថលេខា ហើយយើងត្រូវបានប្រើដើម្បីអាសយដ្ឋានទាំងក្នុងទម្រង់ x.x.x.x (172.16.163.89) ឬក្នុងទម្រង់តួអក្សរ (myhost.com)។ ដើម្បីបំប្លែងទីមួយ ប្រើមុខងារ inet_addr (const char *ip_addr) ហើយសម្រាប់ទីពីរ ប្រើមុខងារ gethostbyname (const char *host)។ តោះ​ទៅ​មើល​រូប​ទាំង​ពីរ​នេះ​៖

u_int32_t inet_addr (const char * ip_addr)

- ត្រឡប់ចំនួនគត់ភ្លាមៗដែលសមរម្យសម្រាប់ប្រើក្នុងរចនាសម្ព័ន្ធ sockaddr_in នៅអាសយដ្ឋាន IP ដែលបានបញ្ជូនទៅវាក្នុងទម្រង់ x.x.x.x ។ ប្រសិនបើមានកំហុសកើតឡើង INADDR_NONE ត្រូវបានប្រគល់មកវិញ។

struct HOSTENT* gethostbyname(const char *host_name)

- ត្រឡប់រចនាសម្ព័ន្ធព័ត៌មានអំពីម៉ាស៊ីនដោយផ្អែកលើឈ្មោះរបស់វា។ ប្រសិនបើមិនជោគជ័យ ត្រឡប់ NULL ។ ការស្វែងរកឈ្មោះកើតឡើងដំបូងនៅក្នុង ឯកសារម៉ាស៊ីនហើយបន្ទាប់មកទៅ DNS ។ រចនាសម្ព័ន្ធ HOSTENT ផ្តល់ព័ត៌មានអំពីម៉ាស៊ីនដែលត្រូវការ។ ក្នុងចំណោមវាលទាំងអស់របស់វា ចំនុចសំខាន់បំផុតគឺវាល char **h_addr_list ដែលតំណាងឱ្យបញ្ជីអាសយដ្ឋាន IP សម្រាប់ម៉ាស៊ីនដែលបានផ្តល់ឱ្យ។ ជាធម្មតា h_addr_list ត្រូវបានប្រើ ដែលតំណាងឱ្យអាសយដ្ឋាន IP ដំបូងរបស់ម៉ាស៊ីន ប៉ុន្តែអ្នកក៏អាចប្រើកន្សោម h_addr សម្រាប់ការនេះផងដែរ។ បន្ទាប់ពីដំណើរការមុខងារ gethostbyname បញ្ជី h_addr_list នៃរចនាសម្ព័ន្ធ HOSTENT មានអាសយដ្ឋាន IP និមិត្តសញ្ញាសាមញ្ញ ដូច្នេះអ្នកត្រូវតែប្រើមុខងារ inet_addr បន្ថែមដើម្បីបំប្លែងទៅជាទម្រង់ sockaddr_in ។

ដូច្នេះ យើង​បាន​ភ្ជាប់​រន្ធ​ម៉ាស៊ីន​ភ្ញៀវ​ទៅ​រន្ធ​ម៉ាស៊ីន​បម្រើ​ដោយ​ប្រើ​មុខងារ​តភ្ជាប់។ បន្ទាប់មកអ្នកអាចប្រើមុខងារផ្ទេរទិន្នន័យ។ សម្រាប់ការនេះអ្នកអាចប្រើទាំង លក្ខណៈស្តង់ដារ I/O កម្រិតទាបសម្រាប់ឯកសារ ដោយសាររន្ធគឺសំខាន់ អ្នកពិពណ៌នាឯកសារ. ជាអកុសលមុខងារនៃការងារកម្រិតទាបជាមួយឯកសារអាចប្រែប្រួលសម្រាប់ប្រព័ន្ធប្រតិបត្តិការផ្សេងៗគ្នា ដូច្នេះអ្នកត្រូវពិនិត្យមើលសៀវភៅដៃសម្រាប់ប្រព័ន្ធប្រតិបត្តិការរបស់អ្នក។ សូមចំណាំថាទំនាក់ទំនងបណ្តាញអាចបញ្ចប់ដោយសញ្ញា SIGPIPE ហើយមុខងារអាន/សរសេរនឹងត្រឡប់កំហុសមួយ។ អ្នកគួរចងចាំជានិច្ចដើម្បីពិនិត្យមើលកំហុស លើសពីនេះអ្នកមិនត្រូវភ្លេចថាការផ្ទេរទិន្នន័យតាមបណ្តាញអាចយឺតណាស់ ហើយមុខងារបញ្ចូល/ទិន្នផលគឺធ្វើសមកាលកម្ម ហើយនេះអាចបណ្តាលឱ្យមានការពន្យារពេលយ៉ាងសំខាន់នៅក្នុងកម្មវិធី។

ដើម្បីផ្ទេរទិន្នន័យរវាងរន្ធមាន មុខងារពិសេសជាទូទៅសម្រាប់ប្រព័ន្ធប្រតិបត្តិការទាំងអស់ គឺជាមុខងាររបស់ recv និង send family ។ ទម្រង់របស់ពួកគេគឺស្រដៀងគ្នាខ្លាំងណាស់៖

int send(int sockfd, void *data, size_t len, int flags);

- បញ្ជូនទិន្នន័យបណ្តោះអាសន្ន។

int recv(int sockfd, void *data, size_t len, int flags);

- ទទួលយកទិន្នន័យបណ្តោះអាសន្ន។

អាគុយម៉ង់ទីមួយគឺជាឧបករណ៍ពិពណ៌នារន្ធ ទីពីរគឺជាទ្រនិចសម្រាប់ទិន្នន័យដែលត្រូវផ្ទេរ ទីបីគឺជាប្រវែងសតិបណ្ដោះអាសន្ន និងទីបួនគឺជាទង់។ ប្រសិនបើជោគជ័យ ចំនួនបៃដែលបានផ្ទេរត្រូវបានបញ្ជូនមកវិញ ប្រសិនបើមិនជោគជ័យ លេខកូដកំហុសអវិជ្ជមាននឹងត្រលប់មកវិញ។ ទង់អនុញ្ញាតឱ្យអ្នកផ្លាស់ប្តូរប៉ារ៉ាម៉ែត្របញ្ជូន (ឧទាហរណ៍បើករបៀបប្រតិបត្តិការអសមកាល) ប៉ុន្តែសម្រាប់ភារកិច្ចភាគច្រើនវាគ្រប់គ្រាន់ដើម្បីទុកវាលទង់សូន្យសម្រាប់ របៀបធម្មតា។ការផ្ទេរ។ នៅពេលផ្ញើ ឬទទួលទិន្នន័យ មុខងាររារាំងការប្រតិបត្តិកម្មវិធី មុនពេលដែលសតិបណ្ដោះអាសន្នទាំងមូលត្រូវបានផ្ញើ។ ហើយនៅពេលប្រើពិធីការ tcp/ip ការឆ្លើយតបត្រូវតែចេញមកពីរន្ធពីចម្ងាយ ដែលបង្ហាញពីការផ្ញើ ឬទទួលទិន្នន័យដោយជោគជ័យ បើមិនដូច្នោះទេ កញ្ចប់ព័ត៌មានត្រូវបានផ្ញើម្តងទៀត។ នៅពេលបញ្ជូនទិន្នន័យ សូមពិចារណាបណ្តាញ MTU ( ទំហំអតិបរមាស៊ុមបញ្ជូនក្នុងពេលតែមួយ) ។ សម្រាប់ បណ្តាញផ្សេងគ្នាវាអាចខុសគ្នាឧទាហរណ៍សម្រាប់ បណ្តាញអ៊ីសឺរណិតវាស្មើនឹង 1500 ។

ដូច្នេះ ដើម្បីភាពពេញលេញ ខ្ញុំនឹងផ្តល់ឧទាហរណ៍ដ៏សាមញ្ញបំផុតនៃកម្មវិធី C ដែលអនុវត្ត socket client៖

# រួមបញ្ចូល /* បណ្ណាល័យស្តង់ដាររន្ធសម្រាប់លីនុច */

# រួមបញ្ចូល /* សម្រាប់ Windows OS ប្រើ #include */

# រួមបញ្ចូល

int main())(

int sockfd = -1;

/* អ្នកពិពណ៌នារន្ធ */

Char buf;

Char s = "អតិថិជនរួចរាល់";

HOSTENT *h = NULL;

Sockaddr_in addr;

ច្រកខ្លីដែលមិនបានចុះហត្ថលេខា = 80;

Addr.sin_family = AF_INET;

/* បង្កើតរន្ធ*/

ប្រសិនបើ (sockfd == -1)

/* ថាតើរន្ធត្រូវបានបង្កើតទេ*/

ត្រឡប់ -1;

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

// ទទួលបានអាសយដ្ឋានម៉ាស៊ីន */

ប្រសិនបើ (h == NULL)

/* តើមានអាសយដ្ឋានបែបនេះទេ? */

ត្រឡប់ -1;

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

/* បម្លែងអាសយដ្ឋាន IP ទៅជាលេខ */

ប្រសិនបើ (ភ្ជាប់(sockfd, (sockaddr*) & addr, sizeof(addr)))

/* កំពុងព្យាយាមភ្ជាប់ទៅរន្ធពីចម្ងាយ */

ត្រឡប់ -1;

/* ការតភ្ជាប់បានជោគជ័យ - បន្ត */

ប្រសិនបើ (ផ្ញើ(sockfd, s, sizeof(s), 0)< 0)

ត្រឡប់ -1;

ប្រសិនបើ(recv(sockfd, buf, sizeof(buf), 0))< 0)

ត្រឡប់ -1;

បិទ (sockfd);

/* បិទរន្ធ*/

/* សម្រាប់ Windows មុខងារ closesocket(s) ត្រូវបានប្រើប្រាស់ */

ត្រឡប់ 0;

អ្នកឃើញទេ ការប្រើរន្ធមិនពិបាកនោះទេ។ IN កម្មវិធីម៉ាស៊ីនមេគោលការណ៍ផ្សេងគ្នាទាំងស្រុងនៃការធ្វើការជាមួយរន្ធត្រូវបានប្រើ។ ដំបូងរន្ធមួយត្រូវបានបង្កើតឡើងបន្ទាប់មកវាត្រូវបានចាត់តាំង អាសយដ្ឋានក្នុងស្រុកដោយប្រើមុខងារចង អ្នកអាចកំណត់អាសយដ្ឋានផ្សាយទៅរន្ធ។ បន្ទាប់មកមុខងារស្តាប់ចាប់ផ្តើមស្តាប់អាសយដ្ឋាន សំណើការតភ្ជាប់ត្រូវបានដាក់ក្នុងជួរមួយ។ នោះគឺមុខងារស្តាប់ចាប់ផ្តើមរន្ធដើម្បីទទួលសារ។ បន្ទាប់ពីនេះ អ្នកត្រូវប្រើមុខងារទទួលយក ដែលត្រឡប់រន្ធថ្មីដែលភ្ជាប់ជាមួយម៉ាស៊ីនភ្ញៀវរួចហើយ។ វាជារឿងធម្មតាសម្រាប់ម៉ាស៊ីនមេក្នុងការទទួលយកការតភ្ជាប់ជាច្រើននៅចន្លោះពេលខ្លី។ ដូច្នេះ អ្នកត្រូវពិនិត្យមើលជួរនៃការតភ្ជាប់ចូលឥតឈប់ឈរ ដោយប្រើមុខងារទទួលយក។ ដើម្បីរៀបចំឥរិយាបទនេះ ពួកវាច្រើនតែងាកទៅរកសមត្ថភាពនៃប្រព័ន្ធប្រតិបត្តិការ។ សម្រាប់ប្រព័ន្ធប្រតិបត្តិការ Windows កំណែពហុខ្សែនៃប្រតិបត្តិការម៉ាស៊ីនមេត្រូវបានគេប្រើញឹកញាប់ជាង បន្ទាប់ពីទទួលយកការតភ្ជាប់ ខ្សែស្រឡាយថ្មីត្រូវបានបង្កើតនៅក្នុងកម្មវិធី ដែលដំណើរការរន្ធ។ នៅក្នុងប្រព័ន្ធ *nix ការបង្កើតដំណើរការកូនដោយមុខងារ fork ត្រូវបានគេប្រើញឹកញាប់ជាង។ ក្នុងពេលជាមួយគ្នានេះ ការចំណាយលើការចំណាយត្រូវបានកាត់បន្ថយដោយសារតែការពិតដែលថាច្បាប់ចម្លងនៃដំណើរការពិតជាកើតឡើងនៅក្នុង ប្រព័ន្ធឯកសារប្រូក ក្នុងករណីនេះ អថេរទាំងអស់នៃដំណើរការកុមារគឺដូចគ្នាទៅនឹងមេ។ ហើយដំណើរការកុមារអាចដោះស្រាយភ្លាមៗនូវការភ្ជាប់ចូល។ ដំណើរការមាតាបិតាបន្តស្តាប់។ សូមចំណាំថាច្រកលេខ 1 ដល់ 1024 មានសិទ្ធិ ហើយការស្តាប់ពួកវាគឺមិនតែងតែអាចធ្វើទៅបានទេ។ ចំណុចមួយទៀត៖ អ្នកមិនអាចមានរន្ធពីរផ្សេងគ្នាស្តាប់ច្រកដូចគ្នានៅអាសយដ្ឋានដូចគ្នាទេ! ជាដំបូង សូមក្រឡេកមើលទម្រង់នៃមុខងារខាងលើសម្រាប់បង្កើត server socket៖

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

- កំណត់អាសយដ្ឋានមូលដ្ឋានទៅរន្ធ ដើម្បីអនុញ្ញាតឱ្យវាទទួលយកការតភ្ជាប់ចូល។ សម្រាប់អាសយដ្ឋាន អ្នកអាចប្រើ INADDR_ANY ថេរ ដែលអនុញ្ញាតឱ្យអ្នកទទួលយកការតភ្ជាប់ចូលពីអាសយដ្ឋានទាំងអស់នៅក្នុងបណ្តាញរងដែលបានផ្តល់ឱ្យ។ ទម្រង់មុខងារគឺស្រដៀងនឹងការភ្ជាប់។ ក្នុងករណីមានកំហុស ត្រឡប់តម្លៃអវិជ្ជមាន។

int listen (int sockfd, int backlog);

- មុខងារបង្កើតជួរនៃរន្ធចូល (ចំនួននៃការតភ្ជាប់ត្រូវបានកំណត់ដោយប៉ារ៉ាម៉ែត្រ backlog វាមិនគួរលើសពីលេខ SOMAXCONN ដែលអាស្រ័យលើ OS) ។ បន្ទាប់ពីបង្កើតជួរ អ្នកអាចរង់ចាំការតភ្ជាប់ដោយប្រើមុខងារទទួលយក។ ជាធម្មតារន្ធត្រូវបានរារាំង ដូច្នេះការប្រតិបត្តិកម្មវិធីត្រូវបានផ្អាករហូតដល់ការភ្ជាប់ត្រូវបានទទួលយក។ ក្នុងករណីមានកំហុស -1 ត្រូវបានប្រគល់មកវិញ។

int ទទួលយក (int sockfd, struct *sockaddr, socklen_t addr_len)

- មុខងាររង់ចាំ ការតភ្ជាប់ចូល(ឬទាញយកវាពីជួរតភ្ជាប់) ហើយត្រឡប់រន្ធថ្មីដែលភ្ជាប់រួចហើយជាមួយម៉ាស៊ីនភ្ញៀវពីចម្ងាយ។ ក្នុងករណីនេះ រន្ធដើម sockfd នៅតែមិនផ្លាស់ប្តូរ។ រចនាសម្ព័ន្ធ sockaddr ត្រូវបានបំពេញដោយតម្លៃពីរន្ធពីចម្ងាយ។ ក្នុងករណីមានកំហុស -1 ត្រូវបានប្រគល់មកវិញ។

ដូច្នេះនេះគឺជាឧទាហរណ៍នៃម៉ាស៊ីនមេរន្ធសាមញ្ញដែលប្រើមុខងារ fork ដើម្បីបង្កើតដំណើរការកូនដែលគ្រប់គ្រងការតភ្ជាប់៖

int main())(

Pid_t pid;

/* លេខសម្គាល់ដំណើរការកុមារ */

int sockfd = -1;

/* កាន់រន្ធដើម្បីស្តាប់ */

Int s = -1;

/* ទទួលអ្នកពណ៌នារន្ធ */

Char buf;

/* ចង្អុលទៅសតិបណ្ដោះអាសន្នដើម្បីទទួល */

Char str = "ម៉ាស៊ីនមេរួចរាល់";

/* ខ្សែអក្សរដើម្បីផ្ញើទៅម៉ាស៊ីនមេ */

HOSTENT *h = NULL;

/* រចនាសម្ព័ន្ធសម្រាប់ការទទួលបានអាសយដ្ឋាន IP */

Sockaddr_in addr;

/* រចនាសម្ព័ន្ធពិធីការ Tcp/ip */

Sockaddr_in raddr;

ច្រកខ្លីដែលមិនបានចុះហត្ថលេខា = 80;

/* បំពេញវាលនៃរចនាសម្ព័ន្ធ៖ */

Addr.sin_family = AF_INET;

Addr.sin_port = htons(port);

sockfd = រន្ធ(PF_INET, SOCK_STREAM, IPPROTO_TCP);

/* បង្កើតរន្ធ*/

ប្រសិនបើ (sockfd == -1)

/* ថាតើរន្ធត្រូវបានបង្កើតទេ*/

ត្រឡប់ -1;

Addr.sin_addr.s_addr = INADDR_ANY;

/* ស្តាប់នៅគ្រប់អាស័យដ្ឋាន*/

ប្រសិនបើ (ចង(sockfd, (sockaddr*) & addr, sizeof(addr)))

/* កំណត់អាសយដ្ឋានមូលដ្ឋានទៅរន្ធ */

ត្រឡប់ -1;

ប្រសិនបើ(ស្តាប់(sockfd, 1))

/*ចាប់ផ្តើមស្តាប់*/

ត្រឡប់ -1;

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

/* ទទួលយកការតភ្ជាប់ */

Pid = fork();

// បង្កើតដំណើរការកុមារ */

ប្រសិនបើ (pid == 0)(

// នេះជាដំណើរការកុមារ*/

ប្រសិនបើ(recv(s, buf, sizeof(buf), 0))< 0)

/* ផ្ញើខ្សែអក្សរ s ទៅរន្ធពីចម្ងាយ */

ត្រឡប់ -1;

ប្រសិនបើ(send(s, str, sizeof(str), 0))< 0)

/* ទទួលការឆ្លើយតបពីម៉ាស៊ីនមេពីចម្ងាយ */

ត្រឡប់ -1;

Printf("ខ្សែអក្សរដែលបានទទួលគឺ៖ %s", buf);

/* បោះពុម្ពសតិបណ្ដោះអាសន្នទៅជាលទ្ធផលស្តង់ដារ */

បិទ (s);

/* បិទរន្ធ*/

ត្រឡប់ 0;

// ចាកចេញពីដំណើរការកុមារ */

បិទ (sockfd);

/* បិទរន្ធស្តាប់*/

ត្រឡប់ 0;

នៅពេលបង្កើតខ្សែស្រឡាយដើម្បីដំណើរការរន្ធមួយ សូមមើលសៀវភៅដៃ OS ដូចជាសម្រាប់ ប្រព័ន្ធផ្សេងគ្នាការហៅទៅកាន់មុខងារបង្កើតខ្សែស្រឡាយអាចប្រែប្រួលយ៉ាងខ្លាំង។ ប៉ុន្តែគោលការណ៍ដំណើរការសម្រាប់ខ្សែស្រឡាយនៅតែដដែល។ មុខងារដំណើរការគ្រាន់តែត្រូវឆ្លងកាត់ទ្រនិចរន្ធជាអាគុយម៉ង់ (ជាធម្មតាប្រភេទទិន្នន័យណាមួយក្នុងទម្រង់ជាមោឃៈ * អាចត្រូវបានបញ្ជូនទៅមុខងារស្ទ្រីម ដែលតម្រូវឱ្យប្រើប្រភេទខាស)។

ចំណាំសំខាន់សម្រាប់ប្រព័ន្ធវីនដូ។ ខ្ញុំបានកត់សម្គាល់ឃើញថាប្រព័ន្ធរន្ធមិនដំណើរការដោយមិនប្រើមុខងារ WSAStartup ដើម្បីចាប់ផ្តើមបណ្ណាល័យរន្ធនោះទេ។ កម្មវិធីរន្ធ Windows គួរតែចាប់ផ្តើមដូចនេះ៖

WSADATA wsaData;

WSAStartup(0x0101, &wsaData);

ហើយពេលចេញពីកម្មវិធី សូមសរសេរដូចខាងក្រោម៖

WSACleanup();

ដោយសារប្រតិបត្តិការរន្ធភាគច្រើនត្រូវបានរារាំង ការអនុវត្តភារកិច្ចត្រូវតែត្រូវបានរំខានជាញឹកញាប់ដោយរង់ចាំការធ្វើសមកាលកម្ម។ ដូច្នេះប្រព័ន្ធ *nix-like ជារឿយៗជៀសវាងការទប់ស្កាត់កុងសូលដោយបង្កើតប្រភេទកម្មវិធីពិសេសមួយ - ដេមិន។ ដេមិនមិនមែនជាកម្មសិទ្ធិរបស់កុងសូលនិម្មិតទេ ហើយកើតឡើងនៅពេលដែលដំណើរការកូនហៅថាសម ហើយដំណើរការមេបញ្ចប់មុនពេលកូនទី 2 (ហើយវាតែងតែកើតឡើងតាមវិធីនេះ)។ បន្ទាប់ពីនេះដំណើរការកូនទី 2 ក្លាយជាដំណើរការសំខាន់ហើយមិនរារាំងកុងសូលទេ។ នេះជាឧទាហរណ៍នៃឥរិយាបថកម្មវិធីនេះ៖

pid = fork();

/* បង្កើតដំណើរការកូនដំបូង*/

ប្រសិនបើ (pid<0){

/* កំហុសក្នុងការហៅ fork */

Printf("កំហុសឆ្គង :)");

ចេញ (-1);

) ផ្សេងទៀតប្រសិនបើ (pid !=0)(

/* នេះជាឪពុកម្តាយដំបូង! */

Printf("នេះជាបិតា១");

) ផ្សេងទៀត (

Pid = fork();

/* ការងាររបស់ឪពុកម្តាយទី 1 បញ្ចប់ */

/* ហើយយើងហៅដំណើរការកូនមួយទៀត */

ប្រសិនបើ (pid<0){

Printf("កំហុសឆ្គង :)");

ចេញ (-1);

) ផ្សេងទៀតប្រសិនបើ (pid !=0)(

/* នេះជាឪពុកម្តាយទីពីរ*/

Printf("នេះគឺជាឪពុក 2");

) ផ្សេងទៀត (

/* ហើយនេះគឺជាដំណើរការកូនទី 2 ដូចគ្នា*/

/* ប្តូរទៅរបៀបដេមិន "ស្តង់ដារ" */

Setsid();

/* ដំណើរការដេមិននៅក្នុងរបៀបអ្នកប្រើជាន់ខ្ពស់ */

Umask(0); /* របាំងឯកសារស្តង់ដារ */

Chdir ("/"); /* ទៅកាន់ថតឯកសារដើម */

Daemoncode(); /* តាមពិតលេខកូដដេមិនខ្លួនឯង*/

/* នៅពេលអ្នកបំបែកដេមិន ដេមិនកុមារនឹងលេចឡើង */

នោះហើយជាវា។ ខ្ញុំគិតថានេះគឺគ្រប់គ្រាន់ដើម្បីបង្កើតម៉ាស៊ីនមេរន្ធសាមញ្ញ។

ចំណុចប្រទាក់ហៅប្រព័ន្ធបណ្តាញ ( រន្ធ (), ចង(), recvfrom(), ផ្ញើទៅ ()។ល។) នៅក្នុងប្រព័ន្ធប្រតិបត្តិការ UNIX អាចត្រូវបានប្រើសម្រាប់ជង់ពិធីការផ្សេងទៀត (និងសម្រាប់ពិធីការដែលស្ថិតនៅខាងក្រោម ស្រទាប់ដឹកជញ្ជូន).

នៅពេលបង្កើតរន្ធអ្នកត្រូវតែបញ្ជាក់ប្រភេទរបស់វាឱ្យបានច្បាស់លាស់។ ការបញ្ជាក់នេះត្រូវបានធ្វើឡើងដោយប្រើប៉ារ៉ាម៉ែត្រហៅបី រន្ធ (). ប៉ារ៉ាម៉ែត្រទីមួយបញ្ជាក់ថាតើគ្រួសារពិធីការណាមួយដែលរន្ធត្រូវបានបង្កើតជាកម្មសិទ្ធិ ហើយប៉ារ៉ាម៉ែត្រទីពីរ និងទីបីកំណត់ពិធីការជាក់លាក់នៅក្នុងគ្រួសារនោះ។

ប៉ារ៉ាម៉ែត្រទីពីរត្រូវបានប្រើដើម្បីបញ្ជាក់ប្រភេទនៃចំណុចប្រទាក់សម្រាប់ធ្វើការជាមួយរន្ធ - តើវាជារន្ធស្ទ្រីម រន្ធសម្រាប់ធ្វើការជាមួយទិន្នន័យក្រាម ឬមួយផ្សេងទៀត។ ប៉ារ៉ាម៉ែត្រទីបីបញ្ជាក់ពិធីការសម្រាប់ប្រភេទចំណុចប្រទាក់ដែលបានផ្តល់ឱ្យ។ IN ជង់ពិធីការ TCP/IPមានពិធីការតែមួយគត់សម្រាប់រន្ធស្ទ្រីម - TCP និងពិធីការតែមួយគត់សម្រាប់រន្ធទិន្នន័យ - UDP ដូច្នេះសម្រាប់ពិធីការដឹកជញ្ជូន TCP/IP ប៉ារ៉ាម៉ែត្រទីបីមិនត្រូវបានអើពើ។

នៅក្នុងជង់ពិធីការផ្សេងទៀត វាអាចមានពិធីការជាច្រើនដែលមានចំណុចប្រទាក់ដូចគ្នា ឧទាហរណ៍ ទិន្នន័យក្រាម ដែលខុសគ្នាក្នុងកម្រិតនៃភាពជឿជាក់។

សម្រាប់ពិធីការដឹកជញ្ជូន TCP/IP យើងនឹងបញ្ជាក់ជានិច្ចនូវថេរកំណត់ AF_INET (គ្រួសារអាសយដ្ឋាន - អ៊ីនធឺណិត) ឬពាក្យមានន័យដូច PF_INET (គ្រួសារពិធីការ - អ៊ីនធឺណិត) ជាប៉ារ៉ាម៉ែត្រដំបូង។

ប៉ារ៉ាម៉ែត្រទីពីរនឹងយកតម្លៃដែលបានកំណត់ជាមុន SOCK_STREAM សម្រាប់រន្ធស្ទ្រីម និង SOCK_DGRAM សម្រាប់រន្ធទិន្នន័យ។

ដោយសារប៉ារ៉ាម៉ែត្រទីបីមិនត្រូវបានយកមកពិចារណាក្នុងករណីរបស់យើង យើងនឹងជំនួសតម្លៃ 0 ទៅក្នុងវា។

តំណភ្ជាប់ទៅកាន់ព័ត៌មានអំពីរន្ធដែលបានបង្កើតត្រូវបានដាក់នៅក្នុង តារាងឯកសារដំណើរការបើកស្រដៀងទៅនឹងរបៀបដែលវាត្រូវបានធ្វើសម្រាប់ pips និង FIFOs (សូមមើលសិក្ខាសាលាទី 5) ។ ការហៅប្រព័ន្ធត្រឡប់ទៅអ្នកប្រើប្រាស់វិញនូវឧបករណ៍ពណ៌នាឯកសារដែលត្រូវគ្នានឹងធាតុតារាងដែលមានប្រជាជន ដែលយើងនឹងហៅជាឧបករណ៍ពិពណ៌នារន្ធ។ វិធីសាស្រ្តនៃការរក្សាទុកព័ត៌មានអំពីរន្ធនេះអនុញ្ញាតឱ្យ ដំណើរការកូនដំបូង ទទួលមរតកវាពីដំណើរការមេ និងទីពីរ ដើម្បីប្រើសម្រាប់រន្ធមួយចំនួននៃការហៅទូរសព្ទប្រព័ន្ធដែលធ្លាប់ស្គាល់យើងរួចមកហើយពីការធ្វើការជាមួយ pips និង FIFOs: close( ) អាន() សរសេរ()។

ការហៅប្រព័ន្ធដើម្បីបង្កើតរន្ធ

គំរូការហៅតាមប្រព័ន្ធ

# រួមបញ្ចូល # រួមបញ្ចូល int socket (int domain, int type, int protocol);

ការពិពណ៌នាអំពីការហៅតាមប្រព័ន្ធ

ការហៅតាមប្រព័ន្ធ រន្ធបម្រើដើម្បីបង្កើតថ្នាំងទំនាក់ទំនងនិម្មិតនៅក្នុងប្រព័ន្ធប្រតិបត្តិការ។ ការពណ៌នានេះមិនមែនជាការពិពណ៌នាពេញលេញនៃការហៅតាមប្រព័ន្ធនោះទេ ប៉ុន្តែត្រូវបានបម្រុងទុកសម្រាប់តែការប្រើប្រាស់នៅក្នុងវគ្គសិក្សារបស់យើងប៉ុណ្ណោះ។ សម្រាប់ព័ត៌មានពេញលេញ សូមមើលសៀវភៅណែនាំ UNIX ។

ប៉ារ៉ាម៉ែត្រដែនកំណត់ក្រុមគ្រួសារពិធីការដែលព័ត៌មាននឹងត្រូវបានផ្ទេរ។ យើងនឹងពិចារណាតែពីរគ្រួសារទាំងនេះប៉ុណ្ណោះក្នុងចំណោមគ្រួសារដែលមានស្រាប់មួយចំនួន។ មានតម្លៃប៉ារ៉ាម៉ែត្រដែលបានកំណត់ជាមុនសម្រាប់ពួកគេ៖

  • PF_INET – សម្រាប់ គ្រួសារពិធីការ TCP/IP ;
  • PF_UNIX – សម្រាប់ក្រុមគ្រួសារនៃពិធីការយូនីកខាងក្នុង ដែលគេស្គាល់ថាជាដែនយូនីក។

ប៉ារ៉ាម៉ែត្រប្រភេទកំណត់អត្ថន័យនៃការផ្លាស់ប្តូរព័ត៌មាន៖ ថាតើការទំនាក់ទំនងនឹងត្រូវបានអនុវត្តតាមរយៈសារ (datagrams) ដោយបង្កើត ការតភ្ជាប់និម្មិតឬតាមរបៀបផ្សេងទៀត។ យើងនឹងប្រើវិធីពីរយ៉ាងដើម្បីផ្លាស់ប្តូរព័ត៌មានជាមួយនឹងតម្លៃដែលបានកំណត់ជាមុនសម្រាប់ប៉ារ៉ាម៉ែត្រប្រភេទ៖

  • SOCK_STREAM - សម្រាប់ការទំនាក់ទំនងដោយប្រើគ្រឹះស្ថាន ការតភ្ជាប់និម្មិត ;
  • SOCK_DGRAM - សម្រាប់ការផ្លាស់ប្តូរព័ត៌មានតាមរយៈសារ។

ប៉ារ៉ាម៉ែត្រពិធីការបញ្ជាក់ពិធីការជាក់លាក់សម្រាប់គ្រួសារពិធីការ និងវិធីសាស្ត្រទំនាក់ទំនងដែលបានជ្រើសរើស។ វាសំខាន់តែនៅពេលដែលមានពិធីការបែបនេះជាច្រើន។ ក្នុងករណីរបស់យើង គ្រួសារពិធីការ និងប្រភេទនៃការផ្លាស់ប្តូរព័ត៌មានកំណត់ពិធីការតែមួយគត់។ ដូច្នេះ យើងនឹងសន្មត់ថាប៉ារ៉ាម៉ែត្រនេះស្មើនឹង 0 ។

តម្លៃត្រឡប់

ប្រសិនបើជោគជ័យ ការហៅប្រព័ន្ធនឹងបង្ហាញឯកសារពិពណ៌នា (តម្លៃធំជាង ឬស្មើ 0) ដែលនឹងត្រូវបានប្រើជាឯកសារយោងទៅកាន់ថ្នាំងទំនាក់ទំនងដែលបានបង្កើតនៅក្នុងការហៅតាមបណ្តាញបន្ថែមទៀតទាំងអស់។ ប្រសិនបើមានកំហុសណាមួយកើតឡើង តម្លៃអវិជ្ជមានត្រូវបានត្រឡប់។

អាសយដ្ឋានរន្ធ។ ការកំណត់អាសយដ្ឋានរន្ធ។ bind() ការហៅប្រព័ន្ធ

នៅពេលដែលរន្ធត្រូវបានបង្កើត អ្នកត្រូវកំណត់អាសយដ្ឋានរបស់វា។ ការហៅតាមប្រព័ន្ធត្រូវបានប្រើសម្រាប់ការនេះ។ ចង(). ប៉ារ៉ាម៉ែត្រទីមួយនៃការហៅត្រូវតែមានឧបករណ៍ពិពណ៌នារន្ធដែលអាសយដ្ឋានកំពុងត្រូវបានកំណត់រចនាសម្ព័ន្ធ។ ប៉ារ៉ាម៉ែត្រទីពីរ និងទីបីបញ្ជាក់អាសយដ្ឋាននេះ។

ប៉ារ៉ាម៉ែត្រទីពីរត្រូវតែជាទ្រនិចទៅរចនាសម្ព័ន្ធ sockaddr ដែលមានផ្នែកដាច់ស្រយាល និងក្នុងតំបន់នៃអាសយដ្ឋានពេញលេញ។

ទ្រនិចនៃប្រភេទ struct sockaddr * ត្រូវបានរកឃើញនៅក្នុងការហៅប្រព័ន្ធបណ្តាញជាច្រើន; ពួកវាត្រូវបានប្រើដើម្បីបញ្ជូនព័ត៌មានអំពីអាសយដ្ឋាន socket មួយណា ឬគួរចងភ្ជាប់ជាមួយ។ ចូរយើងពិនិត្យមើលឱ្យកាន់តែច្បាស់អំពីប្រភេទទិន្នន័យនេះ។ រចនាសម្ព័ន្ធ struct sockaddr ត្រូវបានពិពណ៌នានៅក្នុងឯកសារ ដូចតទៅ៖

struct sockaddr (ខ្លី sa_family; char sa_data; );

សមាសភាពនៃរចនាសម្ព័ន្ធនេះគឺដោយសារតែការពិតដែលថាការហៅទូរស័ព្ទប្រព័ន្ធបណ្តាញអាចត្រូវបានប្រើសម្រាប់គ្រួសារផ្សេងគ្នានៃពិធីការដែលកំណត់ចន្លោះអាសយដ្ឋានខុសគ្នាសម្រាប់អាសយដ្ឋានរន្ធពីចម្ងាយនិងមូលដ្ឋាន។ ជារួម ប្រភេទទិន្នន័យនេះគ្រាន់តែជាគំរូទូទៅសម្រាប់បញ្ជូនរចនាសម្ព័ន្ធទិន្នន័យជាក់លាក់ចំពោះគ្រួសារពិធីការនីមួយៗទៅការហៅតាមប្រព័ន្ធប៉ុណ្ណោះ។ ធាតុទូទៅនៃរចនាសម្ព័ន្ធទាំងនេះនៅសល់តែវាលគ្រួសារ sa_family ខ្លីប៉ុណ្ណោះ (ដែលនៅក្នុងរចនាសម្ព័ន្ធផ្សេងគ្នាអាចមានឈ្មោះផ្សេងគ្នា អ្វីដែលសំខាន់នោះគឺថាពួកវាសុទ្ធតែជាប្រភេទដូចគ្នា និងជាធាតុដំបូងនៃរចនាសម្ព័ន្ធរបស់ពួកគេ) ដើម្បីពិពណ៌នាអំពី គ្រួសារពិធីការ។ ការហៅជាប្រព័ន្ធវិភាគមាតិកានៃវាលនេះដើម្បីកំណត់ឱ្យបានត្រឹមត្រូវនូវសមាសភាពនៃព័ត៌មានចូល។

ដើម្បីធ្វើការជាមួយ ក្រុមគ្រួសារនៃពិធីការ TCP/IPយើងនឹងប្រើអាសយដ្ឋានរន្ធនៃប្រភេទខាងក្រោម ដែលបានពិពណ៌នានៅក្នុងឯកសារ :

struct sockaddr _in( short sin_family; /* គ្រួសារពិធីការដែលបានជ្រើសរើសគឺតែងតែ AF_INET */ ច្រក sin_port ខ្លីដែលមិនបានចុះហត្ថលេខា; /* លេខច្រក 16 ប៊ីតក្នុងលំដាប់បៃបណ្តាញ */ struct in_addr sin_addr; /* អាសយដ្ឋានចំណុចប្រទាក់បណ្តាញ */ char sin_zero; /* វាលនេះមិនត្រូវបានប្រើទេ ប៉ុន្តែត្រូវតែបំពេញដោយសូន្យ */ );

ធាតុដំបូងនៃរចនាសម្ព័ន្ធ - sin_family បញ្ជាក់ គ្រួសារពិធីការ. យើងនឹងចូលទៅក្នុងវានូវ AF_INET ថេរដែលបានកំណត់ជាមុន ដែលស្គាល់យើងរួចហើយ (សូមមើលផ្នែកមុន)។

ផ្នែកដាច់ស្រយាលនៃអាសយដ្ឋានពេញលេញ - អាសយដ្ឋាន IP - មាននៅក្នុងរចនាសម្ព័ន្ធនៃប្រភេទ struct in_addr ដែលយើងបានជួបនៅក្នុងផ្នែក "មុខងារបកប្រែអាសយដ្ឋាន IP" inet_ntoa(), inet_aton() " .

ដើម្បីចង្អុលបង្ហាញលេខច្រក ធាតុរចនាសម្ព័ន្ធ sin_port ត្រូវបានប្រើ ដែលលេខច្រកគួរតែត្រូវបានរក្សាទុក នៅក្នុងលំដាប់បណ្តាញបៃ. មានជម្រើសពីរសម្រាប់បញ្ជាក់លេខច្រក៖ ច្រកថេរតាមដែលអ្នកចង់បាន និងច្រកដែលត្រូវបានកំណត់ដោយចៃដន្យ ប្រព័ន្ធប្រតិបត្តិការ. ជម្រើសទីមួយតម្រូវឱ្យបញ្ជាក់លេខវិជ្ជមាន ដែលត្រូវបានគេស្គាល់ជាមុនថាជាលេខច្រក ហើយសម្រាប់ពិធីការ UDP ជាធម្មតាត្រូវបានប្រើនៅពេលដំឡើងអាសយដ្ឋានរន្ធ និងនៅពេលបញ្ជូនព័ត៌មានដោយប្រើការហៅតាមប្រព័ន្ធ។ ផ្ញើទៅ ()(សូមមើលផ្នែកបន្ទាប់)។ ជម្រើសទីពីរតម្រូវឱ្យបញ្ជាក់ 0 ជាលេខច្រកក្នុងករណីនេះ ប្រព័ន្ធប្រតិបត្តិការខ្លួនវាភ្ជាប់រន្ធទៅនឹងលេខច្រកឥតគិតថ្លៃ។ វិធីសាស្រ្តនេះជាធម្មតាត្រូវបានប្រើនៅពេលដំឡើងរន្ធសម្រាប់កម្មវិធីអតិថិជន នៅពេលដែលអ្នកសរសេរកម្មវិធីមិនចាំបាច់ដឹងពីលេខច្រកពិតប្រាកដជាមុន។

តើ​លេខ​ច្រក​អ្វី​ដែល​អ្នក​ប្រើ​អាច​ប្រើ​ក្នុង​ការ​កំណត់​រចនាសម្ព័ន្ធ​ថេរ? លេខច្រក 1 ដល់ 1023 អាចត្រូវបានកំណត់ទៅរន្ធដោយដំណើរការដែលដំណើរការដោយសិទ្ធិអ្នកគ្រប់គ្រងប្រព័ន្ធប៉ុណ្ណោះ។ ជាធម្មតា លេខទាំងនេះត្រូវបានកំណត់ទៅសេវាបណ្តាញប្រព័ន្ធ ដោយមិនគិតពីប្រភេទនៃប្រព័ន្ធប្រតិបត្តិការដែលបានប្រើ ដូច្នេះកម្មវិធីអតិថិជនអ្នកប្រើប្រាស់អាចស្នើសុំសេវាកម្មពីអាសយដ្ឋានមូលដ្ឋានដូចគ្នា។ វាក៏មានកម្មវិធីបណ្តាញជាច្រើនដែលត្រូវបានប្រើប្រាស់យ៉ាងទូលំទូលាយដែលដំណើរការដំណើរការដោយមានការអនុញ្ញាតពីអ្នកប្រើប្រាស់ធម្មតា (ឧទាហរណ៍ X-Windows)។ សម្រាប់កម្មវិធីបែបនេះដោយសាជីវកម្មអ៊ីនធឺណិតសម្រាប់កំណត់ឈ្មោះ និងលេខ (

តើអ្នកចង់បង្កើតកម្មវិធីបណ្តាញនៅក្នុង Java - ប្រដាប់ក្មេងលេង បន្ទប់ជជែក ឬទាំងពីរ... អ្នកបានរកឃើញអត្ថបទត្រឹមត្រូវ - នៅទីនេះអ្នកអាចស្គាល់ពិភពលោកដ៏គួរឱ្យរំភើបនៃរន្ធនៅក្នុង Java ។ បន្ទាប់ពីអានអត្ថបទនេះអ្នកនឹងឃើញពន្លឺនៅចុងបញ្ចប់នៃផ្លូវរូងក្រោមដី - គោលបំណងនៃរន្ធនិងរបៀបបង្កើតកម្មវិធីសាមញ្ញដោយប្រើរន្ធនៅក្នុងភាសាសរសេរកម្មវិធី Java នឹងកាន់តែច្បាស់។

តើរន្ធគឺជាអ្វី?

សព្វថ្ងៃនេះ ការប្រើប្រាស់កម្មវិធីផ្ញើសារបន្ទាន់បានក្លាយជាឧបករណ៍ដែលមិនអាចខ្វះបានសម្រាប់អ្នកប្រើប្រាស់អ៊ីនធឺណិតទាំងអស់។ មានពិធីការ និងអតិថិជនផ្សេងៗគ្នាជាច្រើន (MSN, ICQ, Skype ។ល។) ដែលគ្រប់គ្នាបានឮ ហើយដែលយើងទាំងអស់គ្នាប្រើជារៀងរាល់ថ្ងៃ។ ប៉ុន្តែមិនមែនគ្រប់គ្នាសុទ្ធតែដឹងពីអ្វីដែលជាមូលដ្ឋាននៃមនុស្សយន្តរបស់ពួកគេនោះទេ - នោះហើយជាអ្វីដែលអត្ថបទនេះត្រូវបានសរសេរសម្រាប់។ ចូរនិយាយថាអ្នកបានដំឡើងកម្មវិធីផ្ញើសារបន្ទាន់មួយនៅលើកុំព្យូទ័ររបស់អ្នក។ បន្ទាប់ពីបើកដំណើរការវា ហើយបញ្ចូលឈ្មោះអ្នកប្រើប្រាស់ និងពាក្យសម្ងាត់របស់អ្នក កម្មវិធីព្យាយាមភ្ជាប់ទៅម៉ាស៊ីនមេ។ តើពាក្យ "ភ្ជាប់" មានន័យដូចម្តេច?

កុំព្យូទ័រនីមួយៗនៅលើបណ្តាញមានអាសយដ្ឋាន IP ។ អាសយដ្ឋាននេះគឺស្រដៀងនឹងអាសយដ្ឋានផ្ទះរបស់អ្នក - វាកំណត់អត្តសញ្ញាណកុំព្យូទ័ររបស់អ្នកដោយឡែក និងអនុញ្ញាតឱ្យអ្នកដទៃទំនាក់ទំនងជាមួយកុំព្យូទ័ររបស់អ្នក។ យើងនឹងមិនចូលទៅក្នុងពត៌មានលំអិតនៃអាសយដ្ឋាន IP ទេ ដោយសារអត្ថបទនេះមិនមែននិយាយអំពីពួកវាទេ ខ្ញុំគ្រាន់តែចង់ចំណាំថាអាសយដ្ឋាន IP គឺជាសំណុំនៃលេខដែលបំបែកដោយចំនុច (ឧទាហរណ៍ 64.104.137.158)។ ទោះបីជាមានវិធីមួយផ្សេងទៀតដើម្បីកំណត់អត្តសញ្ញាណកុំព្យូទ័រនៅលើបណ្តាញ - ឈ្មោះដែនដែលងាយស្រួល និងកំណត់អត្តសញ្ញាណកុំព្យូទ័រយ៉ាងច្បាស់ជាងសំណុំលេខធម្មតា (ឧទាហរណ៍ www.site)។ មានកុំព្យូទ័រពិសេសនៅលើអ៊ីនធឺណិតដែលបំប្លែងឈ្មោះដែនទៅជាអាសយដ្ឋាន IP និងច្រាសមកវិញ។

កម្មវិធីជាច្រើនអាចត្រូវបានប្រតិបត្តិស្របគ្នានៅលើកុំព្យូទ័រមួយ។ ចូរនិយាយថាអ្នកមានកម្មវិធីចំនួន 10 ដែលកំពុងដំណើរការនៅលើកុំព្យូទ័ររបស់អ្នក ហើយពួកគេទាំងអស់កំពុងរង់ចាំកុំព្យូទ័រផ្សេងទៀតដើម្បីទំនាក់ទំនងជាមួយពួកគេ។ អ្នកអាចស្រមៃមើលវាដូចនេះ៖ មានអ្នក ១០ នាក់នៅក្នុងការិយាល័យធំមួយដែលមានទូរស័ព្ទ ១ គ្រឿង ទាំងអស់កំពុងរង់ចាំការហៅទូរសព្ទពីអតិថិជនរបស់ពួកគេ។ តើអ្នកនឹងដោះស្រាយរឿងនេះដោយរបៀបណា? ជាការពិតណាស់ អ្នកអាចតែងតាំងបុគ្គលិកដែលមានទំនួលខុសត្រូវ ហើយគាត់នឹងនាំយកទូរស័ព្ទទៅអ្នកដែលត្រូវគ្នាដែលត្រូវបានហៅ ប៉ុន្តែបន្ទាប់មកអតិថិជនផ្សេងទៀតនឹងមិនអាចទៅដល់មនុស្សផ្សេងទៀតបានទេ។ លើសពីនេះ វាពិបាក និងឆ្គងណាស់ក្នុងការមាននរណាម្នាក់ទទួលខុសត្រូវក្នុងការបញ្ជូនការហៅទូរសព្ទទៅកាន់មនុស្សត្រឹមត្រូវ។ អ្នកប្រហែលជាទាយកន្លែងដែលខ្ញុំនឹងទៅជាមួយនេះ - ប្រសិនបើកម្មវិធីទាំងអស់នេះដំណើរការលើកុំព្យូទ័រតែមួយដោយមោទនភាពសុំឱ្យអតិថិជនរបស់ពួកគេទាក់ទងពួកគេតាមអាសយដ្ឋាន IP ជាក់លាក់ នោះអតិថិជនរបស់ពួកគេនឹងមិនសប្បាយចិត្តទេ។ គំនិតគឺ ... ដើម្បីឱ្យមានអាសយដ្ឋាន IP ដាច់ដោយឡែកសម្រាប់កម្មវិធីនីមួយៗមែនទេ? មិនពិត! ខ្លឹមសារនៃសំណួរគឺមិនត្រឹមត្រូវទេ - វាដូចគ្នានឹងការសួរអំពីការិយាល័យដាច់ដោយឡែកសម្រាប់អ្នកម្នាក់ៗដែរ។ អញ្ចឹង... ប្រហែលជាលេខទូរស័ព្ទដាច់ដោយឡែកនឹងគ្រប់គ្រាន់ទេ? បាទ! នៅក្នុង​ពាក្យ​ចចាមអារ៉ាម​បណ្តាញ "លេខទូរស័ព្ទ​បុគ្គល" ត្រូវបានគេហៅថា​ច្រក។ ច្រកគឺគ្រាន់តែជាលេខ ហើយកម្មវិធីនីមួយៗដែលដំណើរការលើកុំព្យូទ័រជាក់លាក់មួយអាចជ្រើសរើសលេខច្រកតែមួយគត់ដើម្បីកំណត់អត្តសញ្ញាណខ្លួនឯងទៅកាន់ពិភពខាងក្រៅ។ ចងចាំ - អ្នកមិនអាចរកឃើញច្រកទាំងនេះក្នុងចំណោមផ្នែករឹងកុំព្យូទ័រ (កុំព្យាយាមរកមើលពួកវា) ។ លេខទាំងនេះគឺឡូជីខល។ ឥឡូវនេះអ្វីគ្រប់យ៉ាងគឺច្បាស់: មានអាសយដ្ឋាន IP ដែលកុំព្យូទ័រផ្សេងទៀតអាចស្គាល់កុំព្យូទ័រជាក់លាក់មួយនៅលើបណ្តាញ និងលេខច្រកដែលកំណត់កម្មវិធីជាក់លាក់ដែលកំពុងដំណើរការនៅលើកុំព្យូទ័រ។ វាក៏ច្បាស់ដែរថាកម្មវិធីពីរនៅលើកុំព្យូទ័រផ្សេងគ្នាអាចប្រើច្រកដូចគ្នា (ផ្ទះពីរនៅតាមផ្លូវផ្សេងគ្នាក៏អាចមានលេខដូចគ្នាដែរឬអត់?)។ ជិត​ដល់​ហើយ​ គ្រាន់​តែ​បន្លាច​អ្នក​បន្តិច​ តោះ​មក​មើល​រូបមន្ត៖

អាសយដ្ឋាន IP = កំណត់អត្តសញ្ញាណកុំព្យូទ័រនៅលើបណ្តាញតែមួយ។
លេខច្រក = កំណត់អត្តសញ្ញាណកម្មវិធីដែលដំណើរការលើកុំព្យូទ័រដែលត្រូវគ្នា។

ប្រសិនបើយើងបូកបញ្ចូលគ្នានូវសមីការខាងលើ យើងទទួលបាន៖

អាសយដ្ឋាន IP + លេខច្រក = _____

នៅក្នុងពាក្យផ្សេងទៀត:

កំណត់អត្តសញ្ញាណកម្មវិធីពិសេសនៅលើបណ្តាញ។

ដើម្បីសង្ខេប រន្ធគឺជាការរួមបញ្ចូលគ្នានៃអាសយដ្ឋាន IP និងច្រកមួយ។ អាសយដ្ឋានរន្ធអនុញ្ញាតឱ្យកុំព្យូទ័រផ្សេងទៀតនៅលើបណ្តាញស្វែងរកកម្មវិធីជាក់លាក់មួយដែលកំពុងដំណើរការនៅលើកុំព្យូទ័រជាក់លាក់មួយ។ អ្នកអាចបង្ហាញអាសយដ្ឋានរន្ធដូចនេះ 64.104.137.58:80 ដែល 64.104.137.58 ជាអាសយដ្ឋាន IP និង 80 ជាច្រក។

របៀបសរសេរកម្មវិធីដោយប្រើរន្ធ?

គ្រប់គ្រាន់​ហើយ​អំពី​ទ្រឹស្ដី ចូរ​យើង​ឈាន​ដល់​សកម្មភាព។ ចូរយើងបង្កើតកូដដ៏សាមញ្ញ និងមើលឃើញនៅក្នុង Java ដែលនឹងបង្ហាញពីលទ្ធភាពនៃការប្រើប្រាស់រន្ធ។ តោះព្យាយាមអនុវត្តបញ្ជីសកម្មភាពខាងក្រោម៖

1) កម្មវិធី Java មួយនឹងព្យាយាមទំនាក់ទំនងជាមួយកម្មវិធី Java មួយផ្សេងទៀត (ដែលរង់ចាំយ៉ាងអន្ទះសារសម្រាប់នរណាម្នាក់ទាក់ទងវា) ។ តោះហៅកម្មវិធីទីមួយថា Client ហើយទីពីរគឺ Server។

2) បន្ទាប់ពីភ្ជាប់ដោយជោគជ័យទៅម៉ាស៊ីនមេ អតិថិជនរង់ចាំការបញ្ចូលទិន្នន័យពីអ្នក ហើយផ្ញើអត្ថបទទៅម៉ាស៊ីនមេ។

3) កម្មវិធីម៉ាស៊ីនមេបញ្ជូនអត្ថបទនោះទៅម៉ាស៊ីនភ្ញៀវវិញ (ដើម្បីបង្ហាញថាវាអាចធ្វើបានសូម្បីតែសកម្មភាពដ៏មានប្រយោជន៍បែបនេះ)។

4) ម៉ាស៊ីនភ្ញៀវបង្ហាញអត្ថបទដែលទទួលបានពីម៉ាស៊ីនមេ ដើម្បីបង្ហាញអ្នកពីគំនិតរបស់ម៉ាស៊ីនមេអំពីអ្នក។ ត្រៀម​ខ្លួន​សម្រាប់​ការ​ចាប់​ផ្តើ​ម​អភិវឌ្ឍ​? ចូរចាប់ផ្តើម។ ខ្ញុំគ្រាន់តែចំណាំថាខ្ញុំនឹងមិនបង្រៀនអ្នកពីកម្មវិធី Java ពីដំបូងឡើយ ប៉ុន្តែនឹងពន្យល់តែកូដដែលទាក់ទងនឹងរន្ធប៉ុណ្ណោះ។ បង្កើតកម្មវិធី Java ថ្មីចំនួន 2 ហើយដាក់ឈ្មោះវាថា Server.java និង Client.java ។ ខ្ញុំ​បាន​ផ្តល់​លេខ​កូដ​ខាង​ក្រោម​នេះ កុំ​ភ័យ​ខ្លាច ខ្ញុំ​នឹង​ពន្យល់​គ្រប់​យ៉ាង។


នាំចូល java.net.*;
នាំចូល java.io.*;
ម៉ាស៊ីនមេថ្នាក់សាធារណៈ (
ច្រក int = 6666; // ច្រកចៃដន្យ (អាចជាលេខណាមួយពី 1025 ដល់ 65535)
ព្យាយាម (
ServerSocket ss = new ServerSocket(port); // បង្កើតរន្ធ server ហើយចងវាទៅច្រកខាងលើ
System.out.println("កំពុងរង់ចាំអតិថិជន...");

រន្ធរន្ធ = ss.accept(); // បង្ខំ​ម៉ាស៊ីនមេ​ឱ្យ​រង់ចាំ​ការ​តភ្ជាប់ ហើយ​បង្ហាញ​សារ​នៅពេល​នរណា​ម្នាក់​ទាក់ទង​នឹង​ម៉ាស៊ីនមេ
System.out.println("ទទួលបានអតិថិជន :) ... ទីបំផុត មាននរណាម្នាក់បានឃើញខ្ញុំតាមរយៈគម្របទាំងអស់!");
System.out.println();

// យើងយក input និង output streams របស់ socket ឥឡូវនេះយើងអាចទទួល និងបញ្ជូនទិន្នន័យទៅ client ។


ខ្សែអក្សរ = null;
ខណៈពេលដែល (ពិត) (
បន្ទាត់ = in.readUTF(); // រង់ចាំរហូតដល់អតិថិជនផ្ញើខ្សែអក្សរ។
System.out.println("ម៉ាស៊ីនភ្ញៀវល្ងង់ទើបតែផ្ញើមកខ្ញុំនូវបន្ទាត់នេះ៖ " + បន្ទាត់);
System.out.println("ខ្ញុំកំពុងផ្ញើវាមកវិញ...");
out.writeUTF(បន្ទាត់); // ផ្ញើខ្សែអក្សរដូចគ្នានៃអត្ថបទត្រឡប់ទៅអតិថិជនវិញ។
System.out.println("កំពុងរង់ចាំបន្ទាត់បន្ទាប់...");
System.out.println();
}
) catch(Exception x)( x.printStackTrace(); )
}
}

នាំចូល java.net.*;
នាំចូល java.io.*;

អតិថិជនថ្នាក់សាធារណៈ (
public static void main(String ar) (
int serverPort = 6666; // នៅទីនេះអ្នកត្រូវតែបញ្ជាក់ច្រកដែលម៉ាស៊ីនមេត្រូវបានចង។
អាសយដ្ឋានខ្សែអក្សរ = "127.0.0.1"; // នេះគឺជាអាសយដ្ឋាន IP របស់កុំព្យូទ័រដែលកម្មវិធី server របស់យើងកំពុងដំណើរការ។
// នេះគឺជាអាសយដ្ឋានរបស់កុំព្យូទ័រដូចគ្នា ដែលម៉ាស៊ីនភ្ញៀវនឹងត្រូវបានប្រតិបត្តិ។

ព្យាយាម (
InetAddress ipAddress = InetAddress.getByName(អាសយដ្ឋាន); // បង្កើតវត្ថុដែលបង្ហាញអាសយដ្ឋាន IP ដែលបានពិពណ៌នាខាងលើ។
System.out.println("អ្នក​ណា​មួយ​បាន​ឮ​អំពី​រន្ធ​ដែល​មាន​អាសយដ្ឋាន IP " + អាសយដ្ឋាន + " និង​ច្រក " + serverPort + "?");
រន្ធរន្ធ = រន្ធថ្មី(ipAddress, serverPort); // បង្កើតរន្ធដោយប្រើអាសយដ្ឋាន IP និងច្រករបស់ម៉ាស៊ីនមេ។
System.out.println("បាទ! ខ្ញុំទើបតែកាន់កម្មវិធី។");

// យើងយកចរន្តបញ្ចូល និងទិន្នផលនៃរន្ធ ឥឡូវនេះយើងអាចទទួល និងផ្ញើទិន្នន័យដោយម៉ាស៊ីនភ្ញៀវ។
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();

// បំប្លែងស្ទ្រីមទៅជាប្រភេទមួយផ្សេងទៀតដើម្បីធ្វើឱ្យវាកាន់តែងាយស្រួលក្នុងការដំណើរការសារ។
DataInputStream ក្នុង = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);

// បង្កើតស្ទ្រីមសម្រាប់ការអានពីក្តារចុច។
ក្តារចុច BufferedReader = ថ្មី BufferedReader(InputStreamReader ថ្មី(System.in));
ខ្សែអក្សរ = null;
System.out.println("វាយបញ្ចូលអ្វីមួយ ហើយចុចបញ្ចូល។ នឹងផ្ញើវាទៅម៉ាស៊ីនមេ ហើយប្រាប់អ្នកពីអ្វីដែលវាគិត។");
System.out.println();

ខណៈពេលដែល (ពិត) (
បន្ទាត់ = keyboard.readLine(); // រង់ចាំឱ្យអ្នកប្រើប្រាស់បញ្ចូលអ្វីមួយហើយចុចប៊ូតុងបញ្ចូល។
System.out.println("ការបញ្ជូនបន្ទាត់នេះទៅម៉ាស៊ីនមេ...");
out.writeUTF(បន្ទាត់); // ផ្ញើខ្សែអក្សរអត្ថបទដែលបានបញ្ចូលទៅម៉ាស៊ីនមេ។
out.flush(); // បង្ខំខ្សែស្រឡាយដើម្បីបញ្ចប់ការបញ្ជូនទិន្នន័យ។
បន្ទាត់ = in.readUTF(); // រង់ចាំរហូតដល់ម៉ាស៊ីនមេផ្ញើខ្សែអក្សរ។
System.out.println("ម៉ាស៊ីនមេមានភាពគួរសម។ វាបានផ្ញើមកខ្ញុំ៖ " + បន្ទាត់);
System.out.println("ហាក់បីដូចជាម៉ាស៊ីនមេពេញចិត្តនឹងពួកយើង។ ចូលទៅខាងមុខ ហើយបញ្ចូលបន្ទាត់បន្ថែមទៀត។");
System.out.println();
}
) ចាប់ (ករណីលើកលែង x) (
x.printStackTrace();
}
}
}

ឥឡូវយើងចងក្រងកូដ៖

Javac Server.java Client.java

បើកបង្អួចពាក្យបញ្ជាពីរ (DOS) ។ នៅក្នុងបង្អួចមួយយើងបញ្ចូល៖

ម៉ាស៊ីនមេ Java

និងមួយទៀត៖

អតិថិជន Java

ប្រាកដក្នុងលំដាប់នោះ។

ឥឡូវនេះបញ្ចូលបន្ទាត់នៃអត្ថបទនៅក្នុងបង្អួចដែលម៉ាស៊ីនភ្ញៀវកំពុងដំណើរការហើយចុចប៊ូតុងបញ្ចូល។ មើលបង្អួចពីរហើយមើលថាមានអ្វីកើតឡើង។ ជាចុងក្រោយ ចុច Ctrl-C ដើម្បីបញ្ឈប់កម្មវិធី។

ការពន្យល់នៃកូដរន្ធ

ឥឡូវ​នេះ​សូម​ស្វែងយល់​ឱ្យ​ស៊ី​ជម្រៅ​បន្តិច​អំពី​កូដ។ អ្នកទទួលបានគំនិតមួយចំនួនរួចហើយដោយការអានមតិយោបល់ ប៉ុន្តែសូមវិភាគបន្ទាត់សំខាន់ៗមួយចំនួននៃកូដ។

ពិចារណាផ្នែកខាងក្រោមនៃកូដម៉ាស៊ីនមេ៖

ServerSocket ss = new ServerSocket(port);
រន្ធរន្ធ = ss.accept();

ថ្នាក់ ServerSocket មានភាពខុសគ្នាបន្តិចបន្តួចពីថ្នាក់ Socket ។ ថ្នាក់ Socket គឺជារន្ធមួយ។ ភាពខុសគ្នាសំខាន់រវាង ServerSocket គឺថាវាអាចបង្ខំកម្មវិធីឱ្យរង់ចាំការតភ្ជាប់ពីអតិថិជន។ នៅពេលអ្នកបង្កើតវា អ្នកត្រូវបញ្ជាក់ច្រកដែលវានឹងដំណើរការជាមួយ ហើយហៅវិធីសាស្ត្រ accept() របស់វា។ វិធីសាស្រ្តនេះបណ្តាលឱ្យកម្មវិធីរង់ចាំការតភ្ជាប់នៅលើច្រកដែលបានបញ្ជាក់។ ការប្រតិបត្តិកម្មវិធីព្យួរនៅចំណុចនេះរហូតដល់អតិថិជនភ្ជាប់។ បន្ទាប់ពីការតភ្ជាប់ដោយជោគជ័យដោយម៉ាស៊ីនភ្ញៀវ វត្ថុ Socket ធម្មតាត្រូវបានបង្កើត ដែលអ្នកអាចប្រើដើម្បីអនុវត្តប្រតិបត្តិការដែលមានស្រាប់ទាំងអស់នៅលើរន្ធ។ ចំណាំផងដែរថាវត្ថុ Socket នេះតំណាងឱ្យចុងម្ខាងទៀតនៃការតភ្ជាប់។ ប្រសិនបើអ្នកចង់ផ្ញើទិន្នន័យទៅម៉ាស៊ីនភ្ញៀវ អ្នកមិនអាចប្រើរន្ធផ្ទាល់ខ្លួនរបស់អ្នកដើម្បីធ្វើវាបានទេ។

បន្ទាប់យើងនឹងពិនិត្យមើលថ្នាក់ Socket ។ អ្នកអាចបង្កើតវត្ថុ Socket ដោយបញ្ជាក់អាសយដ្ឋាន IP និងច្រក។ អ្នកអាចប្រើថ្នាក់ InetAddress ដើម្បីបង្ហាញអាសយដ្ឋាន IP (នេះជាវិធីសាស្ត្រដែលពេញចិត្ត)។ ដើម្បីបង្កើតវត្ថុ InetAddress សូមប្រើវិធីសាស្ត្រខាងក្រោម៖

InetAddress ipAddress = InetAddress.getByName(អាសយដ្ឋាន);

ចំណាំថានៅក្នុងកម្មវិធីរបស់យើងយើងបានប្រើអាសយដ្ឋាន 127.0.0.1 ។ អាសយដ្ឋានពិសេសនេះត្រូវបានគេហៅថាអាសយដ្ឋានរង្វិលជុំ - វាគ្រាន់តែគូសផែនទីទៅកាន់កុំព្យូទ័រមូលដ្ឋាន។ ប្រសិនបើអ្នកមានបំណងដំណើរការម៉ាស៊ីនភ្ញៀវ និងម៉ាស៊ីនមេនៅលើកុំព្យូទ័រផ្សេងគ្នា នោះអ្នកត្រូវប្រើអាសយដ្ឋាន IP របស់ម៉ាស៊ីនមេដែលត្រូវគ្នា។

បន្ទាប់ពីយើងបង្កើត InetAddress រួចហើយ យើងអាចបង្កើត Socket បាន៖

រន្ធរន្ធ = រន្ធថ្មី(ipAddress, serverPort);

បន្ទាប់​ពី​បង្កើត​វត្ថុ Socket អ្នក​អាច​យក​ស្ទ្រីម​បញ្ចូល​និង​លទ្ធផល​របស់​រន្ធ។ ស្ទ្រីមបញ្ចូលនឹងអនុញ្ញាតឱ្យអ្នកអានពីរន្ធហើយស្ទ្រីមលទ្ធផលនឹងអនុញ្ញាតឱ្យអ្នកសរសេរទៅរន្ធ។

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

បន្ទាត់ខាងក្រោមគ្រាន់តែបំប្លែងស្ទ្រីមទៅជាប្រភេទស្ទ្រីមផ្សេងទៀត។ បន្ទាប់ពីនេះ វានឹងកាន់តែងាយស្រួលសម្រាប់យើងក្នុងការធ្វើការជាមួយ String objects។ លេខកូដនេះមិនធ្វើអ្វីជាមួយបណ្តាញទេ។

DataInputStream ក្នុង = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);

អ្វីៗផ្សេងទៀតគឺសាមញ្ញណាស់ - ឧបាយកលសាមញ្ញជាមួយវត្ថុខ្សែស្រឡាយ (គ្មានរន្ធ) ។ អ្នកអាចប្រើស្ទ្រីមដែលអ្នកចូលចិត្ត ហៅវិធីសាស្ត្រដែលអ្នកចូលចិត្ត ហើយត្រូវប្រាកដថាទិន្នន័យត្រូវបានបញ្ជូនទៅចុងម្ខាងទៀត។ ប្រសិនបើអ្នកមិនមានចំណេះដឹងច្រើនអំពីការប្រើប្រាស់ខ្សែស្រឡាយទេ ខ្ញុំសូមណែនាំឱ្យអ្នកស្វែងរកអត្ថបទអំពីពួកវា ហើយអានវា។