አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

ኢንተርኔት ከረጅም ጊዜ በፊት ተለውጧል. ከኢንተርኔት ዋና ዋና ፕሮቶኮሎች አንዱ - UDP በመተግበሪያዎች ጥቅም ላይ የሚውለው ዳታግራም እና ስርጭቶችን ለማድረስ ብቻ ሳይሆን በኔትወርክ ኖዶች መካከል "የአቻ-ለ-አቻ" ግንኙነቶችን ለማቅረብ ነው. በቀላል ንድፍ ምክንያት ይህ ፕሮቶኮል ብዙ ቀደም ሲል ያልታቀዱ አጠቃቀሞች አሉት ፣ ሆኖም ፣ የፕሮቶኮሉ ጉድለቶች ፣ እንደ ዋስትና አቅርቦት እጥረት ፣ የትም አልጠፉም። ይህ ጽሑፍ በ UDP ላይ የተረጋገጠውን የመላኪያ ፕሮቶኮል አተገባበርን ይገልጻል።
ይዘቶችግቤት
የፕሮቶኮል መስፈርቶች
አስተማማኝ የ UDP ራስጌ
የፕሮቶኮሉ አጠቃላይ መርሆዎች
የጊዜ ማብቂያዎች እና የፕሮቶኮል ጊዜ ቆጣሪዎች
አስተማማኝ የ UDP ስርጭት ሁኔታ ንድፍ
ወደ ኮድ ጠለቅ ያለ። የማስተላለፊያ መቆጣጠሪያ ክፍል
ወደ ኮድ ጠለቅ ያለ። ግዛቶች

ወደ ኮድ ጠለቅ ያለ። ግንኙነቶችን መፍጠር እና ማቋቋም
ወደ ኮድ ጠለቅ ያለ። በጊዜ ማብቂያ ላይ ግንኙነቱን መዝጋት
ወደ ኮድ ጠለቅ ያለ። የውሂብ ማስተላለፍን ወደነበረበት መመለስ
አስተማማኝ UDP API
መደምደሚያ
ጠቃሚ አገናኞች እና መጣጥፎች

ግቤት

የመጀመሪያው የበይነመረብ አርክቴክቸር እያንዳንዱ መስቀለኛ መንገድ ዓለም አቀፋዊ እና ልዩ የሆነ የአይፒ አድራሻ ያለው እና ከሌሎች አንጓዎች ጋር በቀጥታ የሚገናኝበት ተመሳሳይ የአድራሻ ቦታ ወስዷል። አሁን በይነመረቡ፣ በእውነቱ፣ የተለየ አርክቴክቸር አለው - አንድ የአለምአቀፍ አይፒ አድራሻዎች እና ብዙ አካባቢዎች ከ NAT መሳሪያዎች በስተጀርባ የተደበቀ የግል አድራሻዎች።በዚህ አርክቴክቸር ውስጥ፣ በአለምአቀፍ የአድራሻ ቦታ ውስጥ ያሉ መሳሪያዎች ብቻ በአውታረ መረቡ ላይ ካለ ማንኛውም ሰው ጋር በቀላሉ መገናኘት የሚችሉት ልዩ፣ አለምአቀፍ ተዘዋዋሪ አይፒ አድራሻ ስላላቸው ነው። በግል አውታረመረብ ላይ ያለ መስቀለኛ መንገድ በተመሳሳይ አውታረ መረብ ላይ ካሉ ሌሎች አንጓዎች ጋር ሊገናኝ ይችላል፣ እና በአለምአቀፍ የአድራሻ ቦታ ውስጥ ካሉ ሌሎች ታዋቂ አንጓዎች ጋር መገናኘት ይችላል። ይህ መስተጋብር በአብዛኛው የተገኘው በአውታረ መረብ አድራሻ የትርጉም ዘዴ ምክንያት ነው። እንደ ዋይ ፋይ ራውተሮች ያሉ የ NAT መሳሪያዎች ለወጪ ግንኙነቶች ልዩ የትርጉም ሠንጠረዥ ግቤቶችን ይፈጥራሉ እና በጥቅሎች ውስጥ ያሉ የአይፒ አድራሻዎችን እና የወደብ ቁጥሮችን ያሻሽላሉ። ይህ ከግል አውታረመረብ ወደ አለምአቀፍ የአድራሻ ቦታ አስተናጋጅ ወጪ ግንኙነቶችን ይፈቅዳል። ግን በተመሳሳይ ጊዜ የNAT መሳሪያዎች ለገቢ ግንኙነቶች የተለየ ህጎች ካልተዘጋጁ በስተቀር ሁሉንም ገቢ ትራፊክ ያግዳሉ።

ይህ የበይነመረብ አርክቴክቸር ለደንበኛ-አገልጋይ ግንኙነት በቂ ነው፣ደንበኞች በግል አውታረ መረቦች ውስጥ ሊሆኑ የሚችሉበት፣ እና አገልጋዮች አለምአቀፍ አድራሻ አላቸው። ነገር ግን በሁለት አንጓዎች መካከል ቀጥተኛ ግንኙነት ላይ ችግሮች ይፈጥራል የተለያዩ የግል አውታረ መረቦች. በሁለት አንጓዎች መካከል ያለው ቀጥተኛ ግንኙነት ለአቻ ለአቻ አፕሊኬሽኖች እንደ የድምጽ ማስተላለፊያ (ስካይፕ)፣ የኮምፒውተር (TeamViewer) የርቀት መዳረሻን ወይም የመስመር ላይ ጨዋታዎችን ማግኘት አስፈላጊ ነው።

በተለያዩ የግል ኔትወርኮች ላይ ባሉ መሳሪያዎች መካከል የአቻ ለአቻ ግንኙነት ለመመስረት በጣም ውጤታማ ከሆኑ ዘዴዎች አንዱ ቀዳዳ ጡጫ ይባላል። ይህ ዘዴ በአብዛኛው በ UDP ፕሮቶኮል ላይ በመመርኮዝ ከመተግበሪያዎች ጋር ጥቅም ላይ ይውላል.

ነገር ግን ማመልከቻዎ ዋስትና ያለው የመረጃ አቅርቦት የሚያስፈልገው ከሆነ ለምሳሌ ፋይሎችን በኮምፒዩተሮች መካከል ያስተላልፋሉ ፣ ከዚያ UDP ን መጠቀም ብዙ ችግሮች ያጋጥሟቸዋል ምክንያቱም UDP ዋስትና ያለው የመላኪያ ፕሮቶኮል ስላልሆነ እና ፓኬት ማድረስ ከTCP በተለየ መልኩ በቅደም ተከተል አይሰጥም። ፕሮቶኮል.

በዚህ አጋጣሚ የተረጋገጠ የፓኬት አቅርቦትን ለማረጋገጥ አስፈላጊውን ተግባር የሚያቀርብ እና በ UDP ላይ የሚሰራ የመተግበሪያ ንብርብር ፕሮቶኮልን መተግበር ያስፈልጋል።

በተለያዩ የግል አውታረ መረቦች ውስጥ ባሉ አንጓዎች መካከል የ TCP ግንኙነቶችን ለመመስረት የ TCP ቀዳዳ የጡጫ ቴክኒክ እንዳለ ወዲያውኑ ልብ ማለት እፈልጋለሁ ፣ ግን በብዙ የ NAT መሳሪያዎች ድጋፍ ባለመገኘቱ ፣ እሱ ብዙውን ጊዜ ለመገናኘት እንደ ዋና መንገድ አይቆጠርም። እንደዚህ ያሉ አንጓዎች.

ለቀሪው የዚህ ጽሑፍ, የተረጋገጠውን የመላኪያ ፕሮቶኮል ትግበራ ላይ ብቻ አተኩራለሁ. የ UDP ቀዳዳ ጡጫ ዘዴን ተግባራዊ ማድረግ በሚቀጥሉት ጽሁፎች ውስጥ ይገለጻል.

የፕሮቶኮል መስፈርቶች

  1. በአዎንታዊ የግብረመልስ ዘዴ (አዎንታዊ እውቅና ተብሎ የሚጠራው) የሚተገበረ አስተማማኝ የፓኬት አቅርቦት
  2. ትልቅ ውሂብን በብቃት የማስተላለፍ አስፈላጊነት፣ ማለትም፣ ፕሮቶኮሉ አላስፈላጊ የፓኬት ማስተላለፍን ማስወገድ አለበት።
  3. የመላኪያ ማረጋገጫ ዘዴን መሰረዝ መቻል አለበት (እንደ “ንፁህ” UDP ፕሮቶኮል የመሥራት ችሎታ)
  4. በእያንዳንዱ መልእክት ማረጋገጫ የትእዛዝ ሁነታን የመተግበር ችሎታ
  5. በፕሮቶኮሉ ላይ ያለው የመረጃ ልውውጥ መሰረታዊ አሃድ መልእክት መሆን አለበት።

እነዚህ መስፈርቶች በአብዛኛው ከተገለጹት አስተማማኝ የውሂብ ፕሮቶኮል መስፈርቶች ጋር ይገጣጠማሉ አርኤፍ 908 и አርኤፍ 1151እና ይህን ፕሮቶኮል በምዘጋጅበት ጊዜ በእነዚያ መመዘኛዎች ላይ ተመርኩ።

እነዚህን መስፈርቶች ለመረዳት የTCP እና UDP ፕሮቶኮሎችን በመጠቀም በሁለት የአውታረ መረብ ኖዶች መካከል የሚደረጉ የመረጃ ልውውጥ ጊዜን እንመልከት። በሁለቱም ሁኔታዎች አንድ ፓኬት እንጠፋለን.
መስተጋብራዊ ያልሆነ ውሂብ በTCP ላይ ማስተላለፍ፡-አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

ከሥዕሉ ላይ እንደሚታየው፣ ፓኬት ቢጠፋ TCP የጠፋውን ፓኬት ፈልጎ ለላኪው ያሳውቀዋል የጠፋውን ክፍል ቁጥር በመጠየቅ።
የውሂብ ማስተላለፍ በ UDP ፕሮቶኮል፡-አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

UDP ምንም የኪሳራ ማወቂያ እርምጃዎችን አይወስድም። በ UDP ፕሮቶኮል ውስጥ የማስተላለፊያ ስህተቶችን መቆጣጠር ሙሉ በሙሉ የመተግበሪያው ሃላፊነት ነው.

በTCP ፕሮቶኮል ውስጥ ስህተት ፈልጎ ማግኘት የሚገኘው ከመጨረሻ መስቀለኛ መንገድ ጋር ግንኙነት በመመሥረት፣ የግንኙነቱን ሁኔታ በማከማቸት፣ በእያንዳንዱ ፓኬት ራስጌ ውስጥ የተላከውን ባይት ብዛት በማመልከት እና የእውቅና ማረጋገጫ ቁጥር በመጠቀም ደረሰኞችን በማሳወቅ ነው።

በተጨማሪም አፈጻጸሙን ለማሻሻል (ማለትም እውቅና ሳያገኝ ከአንድ በላይ ክፍል ለመላክ) የTCP ፕሮቶኮል የማስተላለፊያ መስኮት ተብሎ የሚጠራውን ይጠቀማል - የክፍል ላኪው ለመቀበል የሚጠብቀው የባይት የውሂብ ብዛት።

ስለ TCP ፕሮቶኮል የበለጠ መረጃ ለማግኘት፣ ይመልከቱ አርኤፍ 793ከ UDP እስከ አርኤፍ 768በእውነቱ, እነሱ የተገለጹበት.

ከላይ ከተዘረዘሩት ውስጥ, በ UDP ላይ አስተማማኝ የመልዕክት ማቅረቢያ ፕሮቶኮል ለመፍጠር (ከዚህ በኋላ ይባላል) ግልጽ ነው. አስተማማኝ UDP), ከ TCP ጋር ተመሳሳይ የሆኑ የውሂብ ማስተላለፊያ ዘዴዎችን ተግባራዊ ማድረግ ያስፈልጋል. ይኸውም፡-

  • የግንኙነት ሁኔታን ያስቀምጡ
  • ክፍል ቁጥር መስጠትን ተጠቀም
  • ልዩ የማረጋገጫ ፓኬጆችን ይጠቀሙ
  • የፕሮቶኮል ፍሰትን ለመጨመር ቀለል ያለ የመስኮት ዘዴን ይጠቀሙ

በተጨማሪም, ያስፈልግዎታል:

  • ለግንኙነቱ ምንጮችን ለመመደብ የመልእክት መጀመሪያ ምልክት ያድርጉ
  • የመልእክቱን መጨረሻ ምልክት ያድርጉ ፣ የተቀበለውን መልእክት ወደ ላይኛው መተግበሪያ ለማስተላለፍ እና የፕሮቶኮል ሀብቶችን ይልቀቁ
  • የግንኙነት-ተኮር ፕሮቶኮል የመላኪያ ማረጋገጫ ዘዴን እንደ “ንፁህ” UDP እንዲሰራ እንዲያሰናክል ፍቀድ

አስተማማኝ የ UDP ራስጌ

የ UDP ዳታግራም በአይፒ ዳታግራም ውስጥ መያዙን ያስታውሱ። አስተማማኝ የ UDP ፓኬት በትክክል ወደ UDP ዳታግራም "ተጠቅሏል።
አስተማማኝ የ UDP ራስጌ ማሸግ፡አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

የአስተማማኝ UDP ራስጌ መዋቅር በጣም ቀላል ነው፡-

አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

  • ባንዲራዎች - የጥቅል ቁጥጥር ባንዲራዎች
  • MessageType - ለተወሰኑ መልዕክቶች ለመመዝገብ በላይኞቹ መተግበሪያዎች ጥቅም ላይ የሚውል የመልእክት ዓይነት
  • TransmissionId - የማስተላለፊያው ቁጥር, ከተቀባዩ አድራሻ እና ወደብ ጋር, ግንኙነቱን በተለየ ሁኔታ ይለያል.
  • ፓኬት ቁጥር - የፓኬት ቁጥር
  • አማራጮች - ተጨማሪ የፕሮቶኮል አማራጮች. በመጀመሪያው ፓኬት ውስጥ, የመልእክቱን መጠን ለማመልከት ጥቅም ላይ ይውላል

ባንዲራዎች የሚከተሉት ናቸው።

  • FirstPacket - የመልእክቱ የመጀመሪያ ፓኬት
  • NoAsk - መልእክቱ እንዲነቃ የዕውቅና ዘዴን አይፈልግም።
  • የመጨረሻ ፓኬት - የመልእክቱ የመጨረሻ ጥቅል
  • RequestForPacket - የማረጋገጫ ፓኬት ወይም የጠፋ ፓኬት ጥያቄ

የፕሮቶኮሉ አጠቃላይ መርሆዎች

አስተማማኝ UDP በሁለት አንጓዎች መካከል ባለው የተረጋገጠ የመልእክት ስርጭት ላይ ያተኮረ ስለሆነ ከሌላኛው ወገን ጋር ግንኙነት መፍጠር መቻል አለበት። ግንኙነት ለመመስረት ላኪው ከFirstPacket ባንዲራ ጋር ፓኬት ይልካል፣ መልሱ ግንኙነቱ ተመስርቷል ማለት ነው። ሁሉም የምላሽ እሽጎች፣ ወይም፣ በሌላ አነጋገር፣ የእውቅና እሽጎች፣ ሁልጊዜ የፓኬት ቁጥር መስክ ዋጋ በተሳካ ሁኔታ ከተቀበሉት ፓኬቶች ትልቁ የፓኬት ቁጥር እሴት በላይ ያዘጋጃሉ። ለመጀመሪያው ፓኬት የተላከው የአማራጭ መስክ የመልእክቱ መጠን ነው።

ግንኙነትን ለማቋረጥ ተመሳሳይ ዘዴ ጥቅም ላይ ይውላል. የመጨረሻው ፓኬት ባንዲራ በመልእክቱ የመጨረሻ ፓኬት ላይ ተቀምጧል። በምላሽ ፓኬት ውስጥ, የመጨረሻው ፓኬት + 1 ቁጥር ይገለጻል, ይህም ለተቀባዩ ወገን የመልእክቱን በተሳካ ሁኔታ ማድረስ ማለት ነው.
የግንኙነት ማቋቋሚያ እና ማቋረጫ ንድፍ;አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

ግንኙነቱ ሲፈጠር የውሂብ ማስተላለፍ ይጀምራል. መረጃ የሚተላለፈው በጥቅሎች ብሎኮች ነው። እያንዳንዱ እገዳ, ከመጨረሻው በስተቀር, ቋሚ የፓኬቶች ብዛት ይዟል. የመስኮት መቀበያ/ማስተላለፊያ መጠን ጋር እኩል ነው። የመጨረሻው የውሂብ እገዳ ያነሱ እሽጎች ሊኖሩት ይችላል። እያንዳንዱን ብሎክ ከላከ በኋላ፣ ላኪው ወገን የመላኪያ ማረጋገጫ ወይም የጠፉ እሽጎችን እንደገና ለማድረስ ጥያቄን ይጠብቃል፣ ምላሾችን ለመቀበል የመቀበያ/ማስተላለፊያ መስኮቱ ክፍት ይሆናል። የማገጃ መላክ ማረጋገጫ ከተቀበለ በኋላ የመቀበያ / ማስተላለፊያ መስኮቱ ይቀየራል እና የሚቀጥለው የውሂብ እገዳ ይላካል።

የተቀበለው ወገን እሽጎችን ይቀበላል. እያንዳንዱ ፓኬት በማስተላለፊያ መስኮቱ ውስጥ ወድቆ እንደሆነ ለማየት ይጣራሉ። በመስኮቱ ውስጥ የማይወድቁ እሽጎች እና ብዜቶች ተጣርተዋል. ምክንያቱም የመስኮቱ መጠን ቋሚ ከሆነ እና ለተቀባዩ እና ለላኪው ተመሳሳይ ከሆነ ፣ ከዚያ የታሸጉ እሽጎች ያለ ኪሳራ የሚቀርቡ ከሆነ ፣ መስኮቱ የሚቀጥለው የውሂብ ብሎክ ፓኬቶችን ለመቀበል እና የመላኪያ ማረጋገጫ ይሆናል። ተልኳል። መስኮቱ በስራ ሰዓት ቆጣሪው በተቀመጠው ጊዜ ውስጥ ካልሞላ ታዲያ የትኛዎቹ እሽጎች እንዳልተገኙ ቼክ ይጀመራል እና እንደገና የመላኪያ ጥያቄዎች ይላካሉ።
የመልሶ ማስተላለፊያ ንድፍ፡አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

የጊዜ ማብቂያዎች እና የፕሮቶኮል ጊዜ ቆጣሪዎች

ግንኙነት መመስረት የማይችልባቸው በርካታ ምክንያቶች አሉ። ለምሳሌ፣ ተቀባዩ ፓርቲ ከመስመር ውጭ ከሆነ። በዚህ አጋጣሚ ግንኙነት ለመመስረት በሚሞከርበት ጊዜ ግንኙነቱ በጊዜ ማብቂያ ይዘጋል. አስተማማኝ የUDP አተገባበር የጊዜ ማብቂያዎችን ለማዘጋጀት ሁለት ጊዜ ቆጣሪዎችን ይጠቀማል። የመጀመሪያው, የስራ ሰዓት ቆጣሪ, ከርቀት አስተናጋጁ ምላሽ ለመጠበቅ ይጠቅማል. በላኪው በኩል ከተቃጠለ, የመጨረሻው የተላከው ፓኬት እንደገና ይላካል. የሰዓት ቆጣሪው በተቀባዩ ላይ ካለቀ፣ የጠፉ እሽጎች ቼክ ተከናውኗል እና እንደገና የማስረከብ ጥያቄዎች ይላካሉ።

በአንጓዎች መካከል የግንኙነት እጥረት በሚኖርበት ጊዜ ግንኙነቱን ለመዝጋት ሁለተኛው ጊዜ ቆጣሪ ያስፈልጋል. ለላኪው, የስራ ሰዓት ቆጣሪው ካለቀ በኋላ ወዲያውኑ ይጀምራል, እና ከርቀት መስቀለኛ መንገድ ምላሽ ይጠብቃል. በተጠቀሰው ጊዜ ውስጥ ምንም ምላሽ ከሌለ ግንኙነቱ ይቋረጣል እና ሀብቶች ይለቀቃሉ. ለተቀባዩ ጎን, የግንኙነቱ ቅርብ ጊዜ ቆጣሪ የሚጀምረው የስራ ጊዜ ቆጣሪው ሁለት ጊዜ ካለቀ በኋላ ነው. ይህ የማረጋገጫ ፓኬት መጥፋት ላይ ዋስትና ለመስጠት አስፈላጊ ነው. የሰዓት ቆጣሪው ሲያልቅ ግንኙነቱ ይቋረጣል እና ግብዓቶች ይለቀቃሉ።

አስተማማኝ የ UDP ስርጭት ሁኔታ ንድፍ

የፕሮቶኮሉ መርሆዎች በመጨረሻው የስቴት ማሽን ውስጥ ይተገበራሉ, እያንዳንዱ ግዛት ለተወሰነ የፓኬት ማቀነባበሪያ ሎጂክ ተጠያቂ ነው.
አስተማማኝ የ UDP ግዛት ንድፍ

አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

ዝግ - በእውነቱ ግዛት አይደለም፣ ለአውቶሜትሩ መነሻ እና መጨረሻ ነጥብ ነው። ለግዛት ዝግ የማስተላለፊያ መቆጣጠሪያ ብሎክ ተቀብሏል፣ እሱም ያልተመሳሰለ UDP አገልጋይን በመተግበር ፓኬጆችን ወደ ተገቢ ግንኙነቶች ያስተላልፋል እና የግዛት ሂደት ይጀምራል።

የመጀመሪያ ፓኬት መላክ - መልእክቱ በሚላክበት ጊዜ የወጪ ግንኙነቱ የመጀመሪያ ሁኔታ።

በዚህ ሁኔታ, ለመደበኛ መልዕክቶች የመጀመሪያው ፓኬት ይላካል. የመላክ ማረጋገጫ ለሌላቸው መልእክቶች፣ መልዕክቱ የተላከበት ብቸኛው ሁኔታ ይህ ነው።

የመላክ ዑደት - የመልእክት ፓኬቶችን ለማስተላለፍ የመሬት ሁኔታ።

ከግዛቱ ወደ እሱ የሚደረግ ሽግግር የመጀመሪያ ፓኬት መላክ የመልእክቱ የመጀመሪያ ፓኬት ከተላከ በኋላ ይከናወናል ። ሁሉም ምስጋናዎች እና የድጋሚ ማስተላለፍ ጥያቄዎች የሚመጡት በዚህ ሁኔታ ውስጥ ነው። ከእሱ መውጣት በሁለት አጋጣሚዎች ይቻላል - መልእክቱን በተሳካ ሁኔታ ማድረስ ወይም በጊዜ ማብቂያ.

የመጀመሪያ ፓኬት ደረሰ - የመልእክቱ ተቀባይ የመጀመሪያ ሁኔታ።

የማስተላለፊያውን መጀመሪያ ትክክለኛነት ይፈትሻል, አስፈላጊዎቹን መዋቅሮች ይፈጥራል እና የመጀመሪያውን ፓኬት መቀበልን ይልካል.

ነጠላ ፓኬት ላቀፈ እና የመላኪያ ማረጋገጫ ሳይጠቀም ለተላከ መልእክት ይህ ብቸኛው ሁኔታ ነው። እንደዚህ አይነት መልእክት ከተሰራ በኋላ ግንኙነቱ ተዘግቷል.

መሰብሰብ - የመልእክት ፓኬቶችን ለመቀበል መሰረታዊ ሁኔታ።

እሽጎችን ወደ ጊዜያዊ ማከማቻ ይጽፋል፣ የፓኬት መጥፋት መኖሩን ያረጋግጣል፣ ለጥቅሎች ብሎክ እና ሙሉውን መልእክት ለማድረስ ምስጋናዎችን ይልካል እና የጠፉ እሽጎች እንደገና እንዲላኩ ጥያቄዎችን ይልካል። ሙሉውን መልእክት በተሳካ ሁኔታ ከተቀበለ ግንኙነቱ ወደ ስቴቱ ይገባል ተጠናቅቋልአለበለዚያ, ጊዜው ያበቃል.

ተጠናቅቋል - ሙሉውን መልእክት በተሳካ ሁኔታ ከተቀበለ ግንኙነቱን መዝጋት።

ይህ ሁኔታ የመልእክቱ ማቅረቢያ ማረጋገጫ በላኪው መንገድ ላይ ሲጠፋ ለመልእክቱ ስብሰባ እና ለጉዳዩ አስፈላጊ ነው ። ይህ ሁኔታ በጊዜ ማብቂያ ይወጣል፣ ግንኙነቱ በተሳካ ሁኔታ እንደተዘጋ ይቆጠራል።

ወደ ኮድ ጠለቅ ያለ። የማስተላለፊያ መቆጣጠሪያ ክፍል

የአስተማማኝ ዩዲፒ ቁልፍ ከሆኑ ነገሮች አንዱ የማስተላለፊያ መቆጣጠሪያ ማገጃ ነው። የዚህ እገዳ ተግባር ወቅታዊ ግንኙነቶችን እና ረዳት አካላትን ማከማቸት ፣ የሚመጡ እሽጎችን ወደ ተዛማጅ ግንኙነቶች ማሰራጨት ፣ ፓኬቶችን ወደ ግንኙነት ለመላክ በይነገጽ ማቅረብ እና የፕሮቶኮል ኤፒአይን መተግበር ነው። የማስተላለፊያ መቆጣጠሪያ ማገጃው ከ UDP ንብርብር ፓኬጆችን ተቀብሎ ወደ ስቴት ማሽን ያስተላልፋል። እሽጎችን ለመቀበል ያልተመሳሰለ UDP አገልጋይን ተግባራዊ ያደርጋል።
አንዳንድ የ ReliableUdpConnectionControlBlock ክፍል አባላት፡-

internal class ReliableUdpConnectionControlBlock : IDisposable
{
  // массив байт для указанного ключа. Используется для сборки входящих сообщений    
  public ConcurrentDictionary<Tuple<EndPoint, Int32>, byte[]> IncomingStreams { get; private set;}
  // массив байт для указанного ключа. Используется для отправки исходящих сообщений.
  public ConcurrentDictionary<Tuple<EndPoint, Int32>, byte[]> OutcomingStreams { get; private set; }
  // connection record для указанного ключа.
  private readonly ConcurrentDictionary<Tuple<EndPoint, Int32>, ReliableUdpConnectionRecord> m_listOfHandlers;
  // список подписчиков на сообщения.
  private readonly List<ReliableUdpSubscribeObject> m_subscribers;    
  // локальный сокет    
  private Socket m_socketIn;
  // порт для входящих сообщений
  private int m_port;
  // локальный IP адрес
  private IPAddress m_ipAddress;    
  // локальная конечная точка    
  public IPEndPoint LocalEndpoint { get; private set; }    
  // коллекция предварительно инициализированных
  // состояний конечного автомата
  public StatesCollection States { get; private set; }
  // генератор случайных чисел. Используется для создания TransmissionId
  private readonly RNGCryptoServiceProvider m_randomCrypto;    	
  //...
}

ያልተመሳሰለ UDP አገልጋይ መተግበር፡-

private void Receive()
{
  EndPoint connectedClient = new IPEndPoint(IPAddress.Any, 0);
  // создаем новый буфер, для каждого socket.BeginReceiveFrom 
  byte[] buffer = new byte[DefaultMaxPacketSize + ReliableUdpHeader.Length];
  // передаем буфер в качестве параметра для асинхронного метода
  this.m_socketIn.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref connectedClient, EndReceive, buffer);
}   

private void EndReceive(IAsyncResult ar)
{
  EndPoint connectedClient = new IPEndPoint(IPAddress.Any, 0);
  int bytesRead = this.m_socketIn.EndReceiveFrom(ar, ref connectedClient);
  //пакет получен, готовы принимать следующий        
  Receive();
  // т.к. простейший способ решить вопрос с буфером - получить ссылку на него 
  // из IAsyncResult.AsyncState        
  byte[] bytes = ((byte[]) ar.AsyncState).Slice(0, bytesRead);
  // получаем заголовок пакета        
  ReliableUdpHeader header;
  if (!ReliableUdpStateTools.ReadReliableUdpHeader(bytes, out header))
  {          
    // пришел некорректный пакет - отбрасываем его
    return;
  }
  // конструируем ключ для определения connection record’а для пакета
  Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(connectedClient, header.TransmissionId);
  // получаем существующую connection record или создаем новую
  ReliableUdpConnectionRecord record = m_listOfHandlers.GetOrAdd(key, new ReliableUdpConnectionRecord(key, this, header.ReliableUdpMessageType));
  // запускаем пакет в обработку в конечный автомат
  record.State.ReceivePacket(record, header, bytes);
}

ለእያንዳንዱ የመልዕክት ማስተላለፊያ, ስለ ግንኙነቱ መረጃ የያዘ መዋቅር ይፈጠራል. እንዲህ ዓይነቱ መዋቅር ይባላል የግንኙነት መዝገብ.
አንዳንድ የ ReliableUdpConnectionRecord ክፍል አባላት፡-

internal class ReliableUdpConnectionRecord : IDisposable
{    
  // массив байт с сообщением    
  public byte[] IncomingStream { get; set; }
  // ссылка на состояние конечного автомата    
  public ReliableUdpState State { get; set; }    
  // пара, однозначно определяющая connection record
  // в блоке управления передачей     
  public Tuple<EndPoint, Int32> Key { get; private set;}
  // нижняя граница приемного окна    
  public int WindowLowerBound;
  // размер окна передачи
  public readonly int WindowSize;     
  // номер пакета для отправки
  public int SndNext;
  // количество пакетов для отправки
  public int NumberOfPackets;
  // номер передачи (именно он и есть вторая часть Tuple)
  // для каждого сообщения свой	
  public readonly Int32 TransmissionId;
  // удаленный IP endpoint – собственно получатель сообщения
  public readonly IPEndPoint RemoteClient;
  // размер пакета, во избежание фрагментации на IP уровне
  // не должен превышать MTU – (IP.Header + UDP.Header + RelaibleUDP.Header)
  public readonly int BufferSize;
  // блок управления передачей
  public readonly ReliableUdpConnectionControlBlock Tcb;
  // инкапсулирует результаты асинхронной операции для BeginSendMessage/EndSendMessage
  public readonly AsyncResultSendMessage AsyncResult;
  // не отправлять пакеты подтверждения
  public bool IsNoAnswerNeeded;
  // последний корректно полученный пакет (всегда устанавливается в наибольший номер)
  public int RcvCurrent;
  // массив с номерами потерянных пакетов
  public int[] LostPackets { get; private set; }
  // пришел ли последний пакет. Используется как bool.
  public int IsLastPacketReceived = 0;
  //...
}

ወደ ኮድ ጠለቅ ያለ። ግዛቶች

ግዛቶች ዋናው የፓኬቶች ሂደት የሚካሄድበትን የታመነ UDP ፕሮቶኮል የግዛት ማሽንን ይተገብራሉ። የአብስትራክት ክፍል ReliableUdpState ለስቴቱ በይነገጽ ያቀርባል፡-

አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

የፕሮቶኮሉ አጠቃላይ አመክንዮ ከላይ በተገለጹት ክፍሎች የተተገበረ ሲሆን ከረዳት ክፍል ጋር የማይለዋወጥ ዘዴዎችን ለምሳሌ ከግንኙነት መዝገብ የ ReliableUdp አርዕስት መገንባት።

በመቀጠል, የፕሮቶኮሉን መሰረታዊ ስልተ ቀመሮችን የሚወስኑትን የበይነገጽ ዘዴዎች አተገባበርን በዝርዝር እንመለከታለን.

በByTimeout የማስወገድ ዘዴ

የDisposeByTimeout ዘዴ ከተወሰነ ጊዜ በኋላ የግንኙነት ግብዓቶችን ለመልቀቅ እና የተሳካ/ያልተሳካ የመልእክት አቅርቦትን የማሳወቅ ሃላፊነት አለበት።
አስተማማኝ የUdpState.በጊዜአውት ያስወግዱ፡

protected virtual void DisposeByTimeout(object record)
{
  ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;      
  if (record.AsyncResult != null)
  {
    connectionRecord.AsyncResult.SetAsCompleted(false);
  }
  connectionRecord.Dispose();
}

በግዛቱ ውስጥ ብቻ የተሻረ ነው። ተጠናቅቋል.
ተጠናቅቋል።በጊዜአውት አስወግድ፡

protected override void DisposeByTimeout(object record)
{
  ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;
  // сообщаем об успешном получении сообщения
  SetAsCompleted(connectionRecord);        
}

የሂደት ፓኬቶች ዘዴ

የProcessPackets ዘዴ ለአንድ ጥቅል ወይም ፓኬጆች ተጨማሪ ሂደት ኃላፊነት አለበት። በቀጥታ ወይም በፓኬት መጠባበቂያ ጊዜ ቆጣሪ በኩል ተጠርቷል.

የሚችል መሰብሰብ ዘዴው የተሻረ ነው እና የጠፉ እሽጎችን የማጣራት እና ወደ ስቴት ለመሸጋገር ሃላፊነት አለበት ተጠናቅቋል, የመጨረሻውን ፓኬት ከተቀበለ እና የተሳካ ቼክ ካለፈ
ማሰባሰብ.የሂደት ፓኬቶች፡

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.IsDone != 0)
    return;
  if (!ReliableUdpStateTools.CheckForNoPacketLoss(connectionRecord, connectionRecord.IsLastPacketReceived != 0))
  {
    // есть потерянные пакеты, отсылаем запросы на них
    foreach (int seqNum in connectionRecord.LostPackets)
    {
      if (seqNum != 0)
      {
        ReliableUdpStateTools.SendAskForLostPacket(connectionRecord, seqNum);
      }
    }
    // устанавливаем таймер во второй раз, для повторной попытки передачи
    if (!connectionRecord.TimerSecondTry)
    {
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
      connectionRecord.TimerSecondTry = true;
      return;
    }
    // если после двух попыток срабатываний WaitForPacketTimer 
    // не удалось получить пакеты - запускаем таймер завершения соединения
    StartCloseWaitTimer(connectionRecord);
  }
  else if (connectionRecord.IsLastPacketReceived != 0)
  // успешная проверка 
  {
    // высылаем подтверждение о получении блока данных
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    connectionRecord.State = connectionRecord.Tcb.States.Completed;
    connectionRecord.State.ProcessPackets(connectionRecord);
    // вместо моментальной реализации ресурсов
    // запускаем таймер, на случай, если
    // если последний ack не дойдет до отправителя и он запросит его снова.
    // по срабатыванию таймера - реализуем ресурсы
    // в состоянии Completed метод таймера переопределен
    StartCloseWaitTimer(connectionRecord);
  }
  // это случай, когда ack на блок пакетов был потерян
  else
  {
    if (!connectionRecord.TimerSecondTry)
    {
      ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
      connectionRecord.TimerSecondTry = true;
      return;
    }
    // запускаем таймер завершения соединения
    StartCloseWaitTimer(connectionRecord);
  }
}

የሚችል የመላክ ዑደት ይህ ዘዴ የሚጠራው በሰዓት ቆጣሪ ላይ ብቻ ነው, እና የመጨረሻውን መልእክት እንደገና የመላክ እና የግንኙነቱን የቅርብ ጊዜ ቆጣሪ ማንቃት ነው.
የመላክ ዑደት።የሂደት ፓኬቶች፡-

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.IsDone != 0)
    return;        
  // отправляем повторно последний пакет 
  // ( в случае восстановления соединения узел-приемник заново отправит запросы, которые до него не дошли)        
  ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, connectionRecord.SndNext - 1));
  // включаем таймер CloseWait – для ожидания восстановления соединения или его завершения
  StartCloseWaitTimer(connectionRecord);
}

የሚችል ተጠናቅቋል ዘዴው የሩጫ ሰዓት ቆጣሪውን ያቆማል እና መልእክቱን ለተመዝጋቢዎች ይልካል.
ተጠናቅቋል።የሂደት ፓኬቶች፡

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.WaitForPacketsTimer != null)
    connectionRecord.WaitForPacketsTimer.Dispose();
  // собираем сообщение и передаем его подписчикам
  ReliableUdpStateTools.CreateMessageFromMemoryStream(connectionRecord);
}

የመቀበያ ፓኬት ዘዴ

የሚችል የመጀመሪያ ፓኬት ደረሰ የስልቱ ዋና ተግባር የመጀመሪያው የመልእክት ፓኬት በይነገጹ ላይ መድረሱን እና እንዲሁም አንድ ፓኬት የያዘ መልእክት መሰብሰብ ነው።
የመጀመሪያ ፓኬት ተቀብሏል.ተቀባዩ ፓኬት፡-

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket))
    // отбрасываем пакет
    return;
  // комбинация двух флагов - FirstPacket и LastPacket - говорит что у нас единственное сообщение
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket) &
      header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
  {
    ReliableUdpStateTools.CreateMessageFromSinglePacket(connectionRecord, header, payload.Slice(ReliableUdpHeader.Length, payload.Length));
    if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
    {
      // отправляем пакет подтверждение          
      ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    }
    SetAsCompleted(connectionRecord);
    return;
  }
  // by design все packet numbers начинаются с 0;
  if (header.PacketNumber != 0)          
    return;
  ReliableUdpStateTools.InitIncomingBytesStorage(connectionRecord, header);
  ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
  // считаем кол-во пакетов, которые должны прийти
  connectionRecord.NumberOfPackets = (int)Math.Ceiling((double) ((double) connectionRecord.IncomingStream.Length/(double) connectionRecord.BufferSize));
  // записываем номер последнего полученного пакета (0)
  connectionRecord.RcvCurrent = header.PacketNumber;
  // после сдвинули окно приема на 1
  connectionRecord.WindowLowerBound++;
  // переключаем состояние
  connectionRecord.State = connectionRecord.Tcb.States.Assembling;
  // если не требуется механизм подтверждение
  // запускаем таймер который высвободит все структуры         
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
  {
    connectionRecord.CloseWaitTimer = new Timer(DisposeByTimeout, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
  }
  else
  {
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
  }
}

የሚችል የመላክ ዑደት ይህ ዘዴ የመላኪያ ምስጋናዎችን እና የድጋሚ ማስተላለፍ ጥያቄዎችን ለመቀበል የተሻረ ነው።
የመላክ ዑደት.ተቀባዩ ፓኬት፡

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (connectionRecord.IsDone != 0)
    return;
  if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.RequestForPacket))
    return;
  // расчет конечной границы окна
  // берется граница окна + 1, для получения подтверждений доставки
  int windowHighestBound = Math.Min((connectionRecord.WindowLowerBound + connectionRecord.WindowSize), (connectionRecord.NumberOfPackets));
  // проверка на попадание в окно        
  if (header.PacketNumber < connectionRecord.WindowLowerBound || header.PacketNumber > windowHighestBound)
    return;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // проверить на последний пакет:
  if (header.PacketNumber == connectionRecord.NumberOfPackets)
  {
    // передача завершена
    Interlocked.Increment(ref connectionRecord.IsDone);
    SetAsCompleted(connectionRecord);
    return;
  }
  // это ответ на первый пакет c подтверждением         
  if ((header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket) && header.PacketNumber == 1))
  {
    // без сдвига окна
    SendPacket(connectionRecord);
  }
  // пришло подтверждение о получении блока данных
  else if (header.PacketNumber == windowHighestBound)
  {
    // сдвигаем окно прием/передачи
    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
    // обнуляем массив контроля передачи
    connectionRecord.WindowControlArray.Nullify();
    // отправляем блок пакетов
    SendPacket(connectionRecord);
  }
  // это запрос на повторную передачу – отправляем требуемый пакет          
  else
    ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, header.PacketNumber));
}

የሚችል መሰብሰብ በ ReceivePacket ዘዴ ውስጥ ከሚመጡ እሽጎች መልእክት የማሰባሰብ ዋና ሥራ ይከናወናል.
ማሰባሰብ.መቀበያ ፓኬት፡-

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (connectionRecord.IsDone != 0)
    return;
  // обработка пакетов с отключенным механизмом подтверждения доставки
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
  {
    // сбрасываем таймер
    connectionRecord.CloseWaitTimer.Change(connectionRecord.LongTimerPeriod, -1);
    // записываем данные
    ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
    // если получили пакет с последним флагом - делаем завершаем          
    if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
    {
      connectionRecord.State = connectionRecord.Tcb.States.Completed;
      connectionRecord.State.ProcessPackets(connectionRecord);
    }
    return;
  }        
  // расчет конечной границы окна
  int windowHighestBound = Math.Min((connectionRecord.WindowLowerBound + connectionRecord.WindowSize - 1), (connectionRecord.NumberOfPackets - 1));
  // отбрасываем не попадающие в окно пакеты
  if (header.PacketNumber < connectionRecord.WindowLowerBound || header.PacketNumber > (windowHighestBound))
    return;
  // отбрасываем дубликаты
  if (connectionRecord.WindowControlArray.Contains(header.PacketNumber))
    return;
  // записываем данные 
  ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
  // увеличиваем счетчик пакетов        
  connectionRecord.PacketCounter++;
  // записываем в массив управления окном текущий номер пакета        
  connectionRecord.WindowControlArray[header.PacketNumber - connectionRecord.WindowLowerBound] = header.PacketNumber;
  // устанавливаем наибольший пришедший пакет        
  if (header.PacketNumber > connectionRecord.RcvCurrent)
    connectionRecord.RcvCurrent = header.PacketNumber;
  // перезапускам таймеры        
  connectionRecord.TimerSecondTry = false;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // если пришел последний пакет
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
  {
    Interlocked.Increment(ref connectionRecord.IsLastPacketReceived);
  }
  // если нам пришли все пакеты окна, то сбрасываем счетчик
  // и высылаем пакет подтверждение
  else if (connectionRecord.PacketCounter == connectionRecord.WindowSize)
  {
    // сбрасываем счетчик.      
    connectionRecord.PacketCounter = 0;
    // сдвинули окно передачи
    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
    // обнуление массива управления передачей
    connectionRecord.WindowControlArray.Nullify();
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
  // если последний пакет уже имеется        
  if (Thread.VolatileRead(ref connectionRecord.IsLastPacketReceived) != 0)
  {
    // проверяем пакеты          
    ProcessPackets(connectionRecord);
  }
}

የሚችል ተጠናቅቋል የስልቱ ብቸኛው ተግባር የመልእክቱን የተሳካ ማድረስ በድጋሚ እውቅና መላክ ነው።
ተጠናቅቋል ተቀባዩ ፓኬት፡-

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // повторная отправка последнего пакета в связи с тем,
  // что последний ack не дошел до отправителя
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
  {
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
}

የፓኬት ዘዴን ላክ

የሚችል የመጀመሪያ ፓኬት መላክ ይህ ዘዴ የመጀመሪያውን የውሂብ ፓኬት ይልካል, ወይም, መልእክቱ የመላኪያ ማረጋገጫ የማይፈልግ ከሆነ, ሙሉውን መልእክት.
የመጀመሪያ ፓኬት መላክ.የላኪ ፓኬት፡

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
  connectionRecord.PacketCounter = 0;
  connectionRecord.SndNext = 0;
  connectionRecord.WindowLowerBound = 0;       
  // если подтверждения не требуется - отправляем все пакеты
  // и высвобождаем ресурсы
  if (connectionRecord.IsNoAnswerNeeded)
  {
    // Здесь происходит отправка As Is
    do
    {
      ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, ReliableUdpStateTools. CreateReliableUdpHeader(connectionRecord)));
      connectionRecord.SndNext++;
    } while (connectionRecord.SndNext < connectionRecord.NumberOfPackets);
    SetAsCompleted(connectionRecord);
    return;
  }
  // создаем заголовок пакета и отправляем его 
  ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
  ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
  // увеличиваем счетчик
  connectionRecord.SndNext++;
  // сдвигаем окно
  connectionRecord.WindowLowerBound++;
  connectionRecord.State = connectionRecord.Tcb.States.SendingCycle;
  // Запускаем таймер
  connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}

የሚችል የመላክ ዑደት በዚህ ዘዴ, የፓኬቶች እገዳ ይላካል.
የመላክ ዑደት.የላኪ ፓኬት፡

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{      
  // отправляем блок пакетов      
  for (connectionRecord.PacketCounter = 0;
        connectionRecord.PacketCounter < connectionRecord.WindowSize &&
        connectionRecord.SndNext < connectionRecord.NumberOfPackets;
        connectionRecord.PacketCounter++)
  {
    ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
    ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
    connectionRecord.SndNext++;
  }
  // на случай большого окна передачи, перезапускаем таймер после отправки
  connectionRecord.WaitForPacketsTimer.Change( connectionRecord.ShortTimerPeriod, -1 );
  if ( connectionRecord.CloseWaitTimer != null )
  {
    connectionRecord.CloseWaitTimer.Change( -1, -1 );
  }
}

ወደ ኮድ ጠለቅ ያለ። ግንኙነቶችን መፍጠር እና ማቋቋም

መሰረታዊ ግዛቶችን እና ግዛቶችን ለማስተናገድ ጥቅም ላይ የሚውሉትን ዘዴዎች ከተመለከትን ፣ ፕሮቶኮሉ እንዴት እንደሚሰራ የሚያሳዩ ጥቂት ምሳሌዎችን በጥቂቱ እናንሳ።
በመደበኛ ሁኔታዎች የውሂብ ማስተላለፊያ ንድፍ:አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

አፈጣጠሩን በዝርዝር አስቡበት የግንኙነት መዝገብ የመጀመሪያውን ፓኬት ለማገናኘት እና ለመላክ. ዝውውሩ የሚጀመረው የመልእክት መላኪያ ኤፒአይ በሚጠራው መተግበሪያ ነው። በመቀጠል የስርጭት መቆጣጠሪያ ማገጃ የ StartTransmission ዘዴ ተጠርቷል, ይህም ለአዲሱ መልእክት መረጃን ማስተላለፍ ይጀምራል.
የወጪ ግንኙነት መፍጠር፡-

private void StartTransmission(ReliableUdpMessage reliableUdpMessage, EndPoint endPoint, AsyncResultSendMessage asyncResult)
{
  if (m_isListenerStarted == 0)
  {
    if (this.LocalEndpoint == null)
    {
      throw new ArgumentNullException( "", "You must use constructor with parameters or start listener before sending message" );
    }
    // запускаем обработку входящих пакетов
    StartListener(LocalEndpoint);
  }
  // создаем ключ для словаря, на основе EndPoint и ReliableUdpHeader.TransmissionId        
  byte[] transmissionId = new byte[4];
  // создаем случайный номер transmissionId        
  m_randomCrypto.GetBytes(transmissionId);
  Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(endPoint, BitConverter.ToInt32(transmissionId, 0));
  // создаем новую запись для соединения и проверяем, 
  // существует ли уже такой номер в наших словарях
  if (!m_listOfHandlers.TryAdd(key, new ReliableUdpConnectionRecord(key, this, reliableUdpMessage, asyncResult)))
  {
    // если существует – то повторно генерируем случайный номер 
    m_randomCrypto.GetBytes(transmissionId);
    key = new Tuple<EndPoint, Int32>(endPoint, BitConverter.ToInt32(transmissionId, 0));
    if (!m_listOfHandlers.TryAdd(key, new ReliableUdpConnectionRecord(key, this, reliableUdpMessage, asyncResult)))
      // если снова не удалось – генерируем исключение
      throw new ArgumentException("Pair TransmissionId & EndPoint is already exists in the dictionary");
  }
  // запустили состояние в обработку         
  m_listOfHandlers[key].State.SendPacket(m_listOfHandlers[key]);
}

የመጀመሪያውን ፓኬት በመላክ ላይ (የመጀመሪያ ፓኬት መላኪያ ሁኔታ)

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
  connectionRecord.PacketCounter = 0;
  connectionRecord.SndNext = 0;
  connectionRecord.WindowLowerBound = 0;       
  // ... 
  // создаем заголовок пакета и отправляем его 
  ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
  ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
  // увеличиваем счетчик
  connectionRecord.SndNext++;
  // сдвигаем окно
  connectionRecord.WindowLowerBound++;
  // переходим в состояние SendingCycle
  connectionRecord.State = connectionRecord.Tcb.States.SendingCycle;
  // Запускаем таймер
  connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}

የመጀመሪያውን ፓኬት ከላከ በኋላ ላኪው ወደ ስቴቱ ይገባል የመላክ ዑደት - የጥቅል አቅርቦት ማረጋገጫን ይጠብቁ።
የመቀበያ ጎን, የ EndReceive ዘዴን በመጠቀም, የተላከውን ፓኬት ይቀበላል, አዲስ ይፈጥራል የግንኙነት መዝገብ እና ይህንን ፓኬት አስቀድሞ ከተተነተነ ራስጌ ጋር ወደ ስቴቱ የመቀበያ ፓኬት ዘዴ ያስተላልፋል። የመጀመሪያ ፓኬት ደረሰ
በተቀባዩ በኩል ግንኙነት መፍጠር;

private void EndReceive(IAsyncResult ar)
{
  // ...
  // пакет получен
  // парсим заголовок пакета        
  ReliableUdpHeader header;
  if (!ReliableUdpStateTools.ReadReliableUdpHeader(bytes, out header))
  {          
    // пришел некорректный пакет - отбрасываем его
    return;
  }
  // конструируем ключ для определения connection record’а для пакета
  Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(connectedClient, header.TransmissionId);
  // получаем существующую connection record или создаем новую
  ReliableUdpConnectionRecord record = m_listOfHandlers.GetOrAdd(key, new ReliableUdpConnectionRecord(key, this, header. ReliableUdpMessageType));
  // запускаем пакет в обработку в конечный автомат
  record.State.ReceivePacket(record, header, bytes);
}

የመጀመሪያውን ፓኬት በመቀበል እና እውቅና መላክ (የመጀመሪያ ፓኬት የተቀበለው ሁኔታ)

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket))
    // отбрасываем пакет
    return;
  // ...
  // by design все packet numbers начинаются с 0;
  if (header.PacketNumber != 0)          
    return;
  // инициализируем массив для хранения частей сообщения
  ReliableUdpStateTools.InitIncomingBytesStorage(connectionRecord, header);
  // записываем данные пакет в массив
  ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
  // считаем кол-во пакетов, которые должны прийти
  connectionRecord.NumberOfPackets = (int)Math.Ceiling((double) ((double) connectionRecord.IncomingStream.Length/(double) connectionRecord.BufferSize));
  // записываем номер последнего полученного пакета (0)
  connectionRecord.RcvCurrent = header.PacketNumber;
  // после сдвинули окно приема на 1
  connectionRecord.WindowLowerBound++;
  // переключаем состояние
  connectionRecord.State = connectionRecord.Tcb.States.Assembling;  
  if (/*если не требуется механизм подтверждение*/)
  // ...
  else
  {
    // отправляем подтверждение
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
  }
}

ወደ ኮድ ጠለቅ ያለ። በጊዜ ማብቂያ ላይ ግንኙነቱን መዝጋት

የጊዜ ማብቂያ አያያዝ የአስተማማኝ UDP አስፈላጊ አካል ነው። አንድ መካከለኛ መስቀለኛ መንገድ ያልተሳካበት እና በሁለቱም አቅጣጫዎች የውሂብ መላክ የማይቻልበትን አንድ ምሳሌ ተመልከት።
በጊዜ ማብቂያ ግንኙነትን ለመዝጋት ዲያግራም፡-አስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

ከሥዕሉ ላይ እንደሚታየው የላኪው የሥራ ሰዓት ቆጣሪ እሽጎችን ከላከ በኋላ ወዲያውኑ ይጀምራል። ይህ የሚሆነው በስቴቱ SendPacket ዘዴ ነው። የመላክ ዑደት.
የስራ ሰዓት ቆጣሪን ማንቃት (የመላክ ሁኔታ)

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{      
  // отправляем блок пакетов   
  // ...   
  // перезапускаем таймер после отправки
  connectionRecord.WaitForPacketsTimer.Change( connectionRecord.ShortTimerPeriod, -1 );
  if ( connectionRecord.CloseWaitTimer != null )
    connectionRecord.CloseWaitTimer.Change( -1, -1 );
}

ግንኙነቱ በሚፈጠርበት ጊዜ የሰዓት ቆጣሪ ጊዜዎች ይዘጋጃሉ። ነባሪው ShortTimerPeriod 5 ሰከንድ ነው። በምሳሌው ውስጥ, ወደ 1,5 ሰከንድ ተቀናብሯል.

ለገቢ ግንኙነት ጊዜ ቆጣሪው የሚጀምረው የመጨረሻውን ገቢ የውሂብ ፓኬት ከተቀበለ በኋላ ነው ፣ ይህ የሚሆነው በስቴቱ የመቀበያ ፓኬት ዘዴ ነው ። መሰብሰብ
የሥራ ሰዓት ቆጣሪን ማንቃት (ሁኔታን መሰብሰብ)

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // ... 
  // перезапускаем таймеры        
  connectionRecord.TimerSecondTry = false;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ...
}

የስራ ሰዓት ቆጣሪውን በመጠባበቅ ላይ ምንም ተጨማሪ ፓኬቶች በመጪው ግንኙነት ላይ አልደረሱም. የሰዓት ቆጣሪው ጠፍቶ የ ProcessPackets ዘዴን ጠራ፣ የጠፉ እሽጎች የተገኙበት እና የመልሶ ማቅረቢያ ጥያቄዎች ለመጀመሪያ ጊዜ ተልከዋል።
የመልሶ ማቅረቢያ ጥያቄዎችን በመላክ ላይ (ሁኔታን መሰብሰብ)

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  // ...        
  if (/*проверка на потерянные пакеты */)
  {
    // отправляем запросы на повторную доставку
    // устанавливаем таймер во второй раз, для повторной попытки передачи
    if (!connectionRecord.TimerSecondTry)
    {
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
    connectionRecord.TimerSecondTry = true;
    return;
    }
  // если после двух попыток срабатываний WaitForPacketTimer 
  // не удалось получить пакеты - запускаем таймер завершения соединения
  StartCloseWaitTimer(connectionRecord);
  }
  else if (/*пришел последний пакет и успешная проверка */)
  {
    // ...
    StartCloseWaitTimer(connectionRecord);
  }
  // если ack на блок пакетов был потерян
  else
  { 
    if (!connectionRecord.TimerSecondTry)
    {
      // повторно отсылаем ack
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
      connectionRecord.TimerSecondTry = true;
      return;
    }
    // запускаем таймер завершения соединения
    StartCloseWaitTimer(connectionRecord);
  }
}

የ TimerSecondTry ተለዋዋጭ ተቀናብሯል እውነተኛ. ይህ ተለዋዋጭ የስራ ሰዓት ቆጣሪውን እንደገና ለማስጀመር ሃላፊነት አለበት.

በላኪው በኩል፣ የስራ ሰዓት ቆጣሪው እንዲሁ ተቀስቅሷል እና የመጨረሻው የተላከው ፓኬት እንደገና ይላካል።
የግንኙነት ጊዜ ቆጣሪን ማንቃት (የመላክ ሁኔታ)

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  // ...        
  // отправляем повторно последний пакет 
  // ...        
  // включаем таймер CloseWait – для ожидания восстановления соединения или его завершения
  StartCloseWaitTimer(connectionRecord);
}

ከዚያ በኋላ የግንኙነቱ ቅርብ ጊዜ ቆጣሪ በወጪ ግንኙነት ውስጥ ይጀምራል።
አስተማማኝ የUdpState.StartCloseWaitTimer:

protected void StartCloseWaitTimer(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(connectionRecord.LongTimerPeriod, -1);
  else
    connectionRecord.CloseWaitTimer = new Timer(DisposeByTimeout, connectionRecord, connectionRecord.LongTimerPeriod, -1);
}

የግንኙነቱ ቅርብ የሰዓት ቆጣሪ ጊዜ ማብቂያ ጊዜ በነባሪ 30 ሰከንድ ነው።

ከአጭር ጊዜ በኋላ, በተቀባዩ ጎን ላይ ያለው የስራ ሰዓት ቆጣሪ እንደገና ይቃጠላል, ጥያቄዎች እንደገና ይላካሉ, ከዚያ በኋላ የግንኙነቱ ጊዜ ቆጣሪ ለመጪው ግንኙነት ይጀምራል.

የሰዓት ቆጣሪዎቹ ሲቃጠሉ የሁለቱም የግንኙነት መዝገቦች ሁሉም ሀብቶች ይለቀቃሉ። ላኪው የማድረስ አለመሳካቱን ለላይኛው መተግበሪያ ሪፖርት ያደርጋል (አስተማማኝ UDP API ይመልከቱ).
የግንኙነት መዝገብ ምንጮችን መልቀቅ፡-

public void Dispose()
{
  try
  {
    System.Threading.Monitor.Enter(this.LockerReceive);
  }
  finally
  {
    Interlocked.Increment(ref this.IsDone);
    if (WaitForPacketsTimer != null)
    {
      WaitForPacketsTimer.Dispose();
    }
    if (CloseWaitTimer != null)
    {
      CloseWaitTimer.Dispose();
    }
    byte[] stream;
    Tcb.IncomingStreams.TryRemove(Key, out stream);
    stream = null;
    Tcb.OutcomingStreams.TryRemove(Key, out stream);
    stream = null;
    System.Threading.Monitor.Exit(this.LockerReceive);
  }
}

ወደ ኮድ ጠለቅ ያለ። የውሂብ ማስተላለፍን ወደነበረበት መመለስ

የጥቅል መጥፋት በሚኖርበት ጊዜ የውሂብ ማስተላለፊያ መልሶ ማግኛ ንድፍአስተማማኝ የ Udp ፕሮቶኮል ለ .ኔት ትግበራ

በጊዜ ማብቂያ ላይ ግንኙነቱን ለመዝጋት ቀደም ሲል እንደተነጋገርነው, የስራ ሰዓት ቆጣሪው ሲያልቅ, ተቀባዩ የጠፉ እሽጎችን ይፈትሻል. ፓኬት ቢጠፋ፣ ተቀባዩ ላይ ያልደረሱ የጥቅሎች ብዛት ዝርዝር ይዘጋጃል። እነዚህ ቁጥሮች በLostPackets ድርድር ውስጥ ገብተዋል የአንድ የተወሰነ ግንኙነት እና የመልሶ ማግኛ ጥያቄዎች ይላካሉ።
ጥቅሎችን ለማስመለስ ጥያቄዎችን በመላክ ላይ (የመሰብሰብ ሁኔታ)፦

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  //...
  if (!ReliableUdpStateTools.CheckForNoPacketLoss(connectionRecord, connectionRecord.IsLastPacketReceived != 0))
  {
    // есть потерянные пакеты, отсылаем запросы на них
    foreach (int seqNum in connectionRecord.LostPackets)
    {
      if (seqNum != 0)
      {
        ReliableUdpStateTools.SendAskForLostPacket(connectionRecord, seqNum);
      }
    }
    // ...
  }
}

ላኪው የማድረስ ጥያቄውን ተቀብሎ የጎደሉትን እሽጎች ይልካል። በዚህ ጊዜ ላኪው የግንኙነቱን የቅርብ ጊዜ ቆጣሪ መጀመሩን እና ጥያቄው ሲደርሰው እንደገና መጀመሩን ልብ ሊባል ይገባል።
የጠፉ እሽጎችን እንደገና በመላክ ላይ (የመላክ ሁኔታ)

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // ...
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  // сброс таймера закрытия соединения 
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ...
  // это запрос на повторную передачу – отправляем требуемый пакет          
  else
    ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, header.PacketNumber));
}

የሪሴንት ፓኬት (ፓኬት ቁጥር 3 በስዕሉ ላይ) በመጪው ግንኙነት ይቀበላል። የመቀበያ መስኮቱ ሙሉ መሆኑን እና መደበኛ የመረጃ ስርጭት ወደነበረበት መመለሱን ለማረጋገጥ ፍተሻ ይደረጋል።
በተቀባዩ መስኮት ውስጥ ስኬቶችን በመፈተሽ ላይ (የመሰብሰቢያ ሁኔታ)

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // ...
  // увеличиваем счетчик пакетов        
  connectionRecord.PacketCounter++;
  // записываем в массив управления окном текущий номер пакета        
  connectionRecord.WindowControlArray[header.PacketNumber - connectionRecord.WindowLowerBound] = header.PacketNumber;
  // устанавливаем наибольший пришедший пакет        
  if (header.PacketNumber > connectionRecord.RcvCurrent)
    connectionRecord.RcvCurrent = header.PacketNumber;
  // перезапускам таймеры        
  connectionRecord.TimerSecondTry = false;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ...
  // если нам пришли все пакеты окна, то сбрасываем счетчик
  // и высылаем пакет подтверждение
  else if (connectionRecord.PacketCounter == connectionRecord.WindowSize)
  {
    // сбрасываем счетчик.      
    connectionRecord.PacketCounter = 0;
    // сдвинули окно передачи
    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
    // обнуление массива управления передачей
    connectionRecord.WindowControlArray.Nullify();
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
  // ...
}

አስተማማኝ UDP API

ከውሂብ ማስተላለፍ ፕሮቶኮል ጋር ለመግባባት ክፍት የሆነ አስተማማኝ የ Udp ክፍል አለ ፣ እሱም በማስተላለፊያ ቁጥጥር እገዳ ላይ መጠቅለያ ነው። የክፍሉ በጣም አስፈላጊዎቹ አባላት እነኚሁና:

public sealed class ReliableUdp : IDisposable
{
  // получает локальную конечную точку
  public IPEndPoint LocalEndpoint    
  // создает экземпляр ReliableUdp и запускает
  // прослушивание входящих пакетов на указанном IP адресе
  // и порту. Значение 0 для порта означает использование
  // динамически выделенного порта
  public ReliableUdp(IPAddress localAddress, int port = 0) 
  // подписка на получение входящих сообщений
  public ReliableUdpSubscribeObject SubscribeOnMessages(ReliableUdpMessageCallback callback, ReliableUdpMessageTypes messageType = ReliableUdpMessageTypes.Any, IPEndPoint ipEndPoint = null)    
  // отписка от получения сообщений
  public void Unsubscribe(ReliableUdpSubscribeObject subscribeObject)
  // асинхронно отправить сообщение 
  // Примечание: совместимость с XP и Server 2003 не теряется, т.к. используется .NET Framework 4.0
  public Task<bool> SendMessageAsync(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, CancellationToken cToken)
  // начать асинхронную отправку сообщения
  public IAsyncResult BeginSendMessage(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, AsyncCallback asyncCallback, Object state)
  // получить результат асинхронной отправки
  public bool EndSendMessage(IAsyncResult asyncResult)  
  // очистить ресурсы
  public void Dispose()    
}

መልዕክቶች በደንበኝነት ይቀበላሉ. የመልሶ ጥሪ ዘዴ የውክልና ፊርማ፡-

public delegate void ReliableUdpMessageCallback( ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteClient );

መልእክት

public class ReliableUdpMessage
{
  // тип сообщения, простое перечисление
  public ReliableUdpMessageTypes Type { get; private set; }
  // данные сообщения
  public byte[] Body { get; private set; }
  // если установлено в true – механизм подтверждения доставки будет отключен
  // для передачи конкретного сообщения
  public bool NoAsk { get; private set; }
}

ለአንድ የተወሰነ የመልእክት አይነት እና/ወይም ላኪ ለመመዝገብ፣ ሁለት አማራጭ መለኪያዎች ጥቅም ላይ ይውላሉ፡ ReliableUdpMessageTypes messageType እና IPEndPoint ipEndPoint።

የመልእክት ዓይነቶች፡-

public enum ReliableUdpMessageTypes : short
{ 
  // Любое
  Any = 0,
  // Запрос к STUN server 
  StunRequest = 1,
  // Ответ от STUN server
  StunResponse = 2,
  // Передача файла
  FileTransfer =3,
  // ...
}

መልእክቱ በተመሳሰል መልኩ ነው የተላከው፤ ለዚህም ፕሮቶኮሉ ያልተመሳሰለ የፕሮግራም አወጣጥ ሞዴልን ተግባራዊ ያደርጋል፡

public IAsyncResult BeginSendMessage(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, AsyncCallback asyncCallback, Object state)

መልእክት የመላክ ውጤቱ እውነት ይሆናል - መልእክቱ በተሳካ ሁኔታ ተቀባዩ ላይ ከደረሰ እና ሐሰት - ግንኙነቱ በጊዜ ማብቂያ ከተዘጋ፡-

public bool EndSendMessage(IAsyncResult asyncResult)

መደምደሚያ

በዚህ ጽሑፍ ውስጥ ብዙ አልተገለጸም. የክር ማዛመጃ ዘዴዎች፣ ልዩ እና የስህተት አያያዝ፣ ያልተመሳሰሉ የመልእክት መላኪያ ዘዴዎችን መተግበር። ነገር ግን የፕሮቶኮሉ ዋና አካል፣ ፓኬቶችን ለማስኬድ አመክንዮ መግለጫ፣ ግንኙነት መመስረት እና የጊዜ ማብቂያዎችን አያያዝ ለእርስዎ ግልጽ መሆን አለበት።

የታመነው የአቅርቦት ፕሮቶኮል ስሪት ቀደም ሲል የተገለጹትን መስፈርቶች ለማሟላት ጠንካራ እና ተለዋዋጭ ነው። ነገር ግን የተገለጸው አተገባበር ሊሻሻል እንደሚችል መጨመር እፈልጋለሁ. ለምሳሌ ፣የልቀት መጠን ለመጨመር እና የሰዓት ቆጣሪ ጊዜዎችን በተለዋዋጭ ለመለወጥ ፣እንደ ተንሸራታች መስኮት እና RTT ያሉ ስልቶች ወደ ፕሮቶኮሉ ሊጨመሩ ይችላሉ ፣በግንኙነት አንጓዎች መካከል MTUን የሚወስኑበት ዘዴን መተግበሩ ጠቃሚ ይሆናል (ነገር ግን ትላልቅ መልዕክቶች ከተላኩ ብቻ) .

ስለ ትኩረትዎ እናመሰግናለን, አስተያየቶችዎን እና አስተያየቶችዎን በጉጉት እጠብቃለሁ.

PS ለዝርዝሮቹ ፍላጎት ላላቸው ወይም ፕሮቶኮሉን መሞከር ለሚፈልጉ፣ በ GitHube ላይ ያለው የፕሮጀክቱ አገናኝ፡-
አስተማማኝ የ UDP ፕሮጀክት

ጠቃሚ አገናኞች እና መጣጥፎች

  1. የTCP ፕሮቶኮል ዝርዝር መግለጫ፡- በእንግሊዝኛ и በሩሲያኛ
  2. የ UDP ፕሮቶኮል ዝርዝር መግለጫ፡- በእንግሊዝኛ и በሩሲያኛ
  3. የRUDP ፕሮቶኮል ውይይት፡- ረቂቅ-ietf-sigtran-የሚታመን-udp-00
  4. አስተማማኝ የውሂብ ፕሮቶኮል፡- አርኤፍ 908 и አርኤፍ 1151
  5. በ UDP ላይ ቀላል የማድረስ ማረጋገጫ ትግበራ፡- በ NET እና UDP አውታረ መረብዎን አጠቃላይ ይቆጣጠሩ
  6. NAT የማቋረጫ ዘዴዎችን የሚገልጽ ጽሑፍ፡- የአቻ ለአቻ ግንኙነት በመላው የአውታረ መረብ አድራሻ ተርጓሚዎች
  7. ያልተመሳሰለው የፕሮግራም አወጣጥ ሞዴል ትግበራ፡- የ CLR ያልተመሳሰለ ፕሮግራሚንግ ሞዴልን በመተግበር ላይ и የ IAsyncResult ንድፍ ንድፍ እንዴት እንደሚተገበር
  8. ያልተመሳሰለውን የፕሮግራም አወጣጥ ሞዴል ወደ ተግባር-ተኮር ያልተመሳሰል ስርዓተ-ጥለት (ኤፒኤም በTAP) ማስተላለፍ፡
    TPL እና ባህላዊ NET Asynchronous Programming
    ከሌሎች ያልተመሳሰሉ ቅጦች እና ዓይነቶች ጋር መስተጋብር

አዘምን፡ አመሰግናለሁ mayorovp и sidristij በይነገጹ ላይ አንድ ተግባር ለመጨመር ሀሳብ። የላይብረሪውን ከአሮጌ ስርዓተ ክወናዎች ጋር ያለው ተኳሃኝነት አልተጣሰም, ምክንያቱም 4 ኛ ማዕቀፍ ሁለቱንም XP እና 2003 አገልጋይን ይደግፋል።

ምንጭ: hab.com

አስተያየት ያክሉ