.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

انٽرنيٽ هڪ ڊگهو وقت اڳ تبديل ٿي چڪو آهي. انٽرنيٽ جي مکيه پروٽوڪول مان هڪ - UDP ايپليڪيشنن پاران استعمال ڪيو ويندو آهي نه صرف ڊيٽاگرام ۽ براڊڪاسٽ پهچائڻ، پر نيٽ ورڪ نوڊس جي وچ ۾ "پيئر کان پير" ڪنيڪشن مهيا ڪرڻ لاء. ان جي سادي ڊيزائن جي ڪري، هن پروٽوڪول ۾ ڪيترائي اڳ ۾ ئي غير منصوبا استعمال ڪيا ويا آهن، جڏهن ته، پروٽوڪول جي گهٽتائي، جهڙوڪ ضمانت جي ترسيل جي کوٽ، ڪٿي به غائب نه ٿيا آهن. اهو آرٽيڪل يو ڊي پي تي ضمانت واري ترسيل پروٽوڪول جي نفاذ کي بيان ڪري ٿو.
مضمون:جائز آهي
پروٽوڪول جي گهرج
قابل اعتماد UDP هيڊر
پروٽوڪول جا جنرل اصول
ٽائم آئوٽ ۽ پروٽوڪول ٽائمر
قابل اعتماد UDP ٽرانسميشن اسٽيٽ ڊراگرام
ڪوڊ ۾ وڌيڪ. ٽرانسميشن ڪنٽرول يونٽ
ڪوڊ ۾ وڌيڪ. رياستون

ڪوڊ ۾ وڌيڪ. ڪنيڪشن ٺاهڻ ۽ قائم ڪرڻ
ڪوڊ ۾ وڌيڪ. وقت ختم ٿيڻ تي ڪنيڪشن بند ڪرڻ
ڪوڊ ۾ وڌيڪ. ڊيٽا جي منتقلي جي بحالي
قابل اعتماد UDP API
ٿڪل
مفيد لنڪس ۽ آرٽيڪل

جائز آهي

انٽرنيٽ جو اصل فن تعمير هڪ هڪجهڙائي واري ايڊريس اسپيس فرض ڪيو جنهن ۾ هر نوڊ وٽ هڪ عالمي ۽ منفرد IP پتو هوندو هو ۽ سڌو سنئون ٻين نوڊس سان رابطو ڪري سگهي ٿو. هاڻي انٽرنيٽ، حقيقت ۾، هڪ مختلف فن تعمير آهي - عالمي IP پتي جو هڪ علائقو ۽ NAT ڊوائيسز جي پويان لڪيل نجي پتي سان ڪيترائي علائقا.هن فن تعمير ۾، صرف عالمي ايڊريس اسپيس ۾ ڊوائيسز آساني سان نيٽ ورڪ تي ڪنهن سان رابطو ڪري سگهن ٿيون ڇو ته انهن وٽ هڪ منفرد، عالمي سطح تي روٽيبل IP پتو آهي. هڪ خانگي نيٽ ورڪ تي هڪ نوڊ ساڳئي نيٽ ورڪ تي ٻين نوڊس سان ڳنڍي سگھي ٿو، ۽ گلوبل ايڊريس اسپيس ۾ ٻين معروف نوڊس سان پڻ ڳنڍي سگھي ٿو. اهو رابطو گهڻو ڪري حاصل ڪيو ويو آهي نيٽ ورڪ ايڊريس ترجمي واري ميڪانيزم جي ڪري. NAT ڊوائيسز، جهڙوڪ وائي فائي روٽر، خاص ترجمي واري ٽيبل داخل ڪن ٿا ٻاهرين ڪنيڪشن لاءِ ۽ تبديل ڪن ٿا IP پتي ۽ پورٽ نمبرن کي پيڪن ۾. هي اجازت ڏئي ٿو ٻاهر نڪرندڙ ڪنيڪشنن کي نجي نيٽ ورڪ کان ميزبانن کي گلوبل ايڊريس اسپيس ۾. پر ساڳئي وقت، NAT ڊوائيسز عام طور تي سڀني ايندڙ ٽرئفڪ کي بلاڪ ڪندا آهن جيستائين ايندڙ ڪنيڪشن لاء الڳ ضابطا مقرر نه ڪيا وڃن.

انٽرنيٽ جو هي فن تعمير ڪلائنٽ-سرور ڪميونيڪيشن لاءِ ڪافي صحيح آهي، جتي ڪلائنٽ پرائيويٽ نيٽ ورڪن ۾ ٿي سگهن ٿا، ۽ سرورز کي عالمي پتو آهي. پر اهو ٻن نوڊس جي وچ ۾ سڌي رابطي لاء مشڪلات پيدا ڪري ٿو مختلف نجي نيٽ ورڪ. ٻن نوڊس جي وچ ۾ سڌو ڪنيڪشن پيئر-ٽو-پيئر ايپليڪيشنن لاءِ ضروري آهي جهڙوڪ وائس ٽرانسميشن (Skype)، ڪمپيوٽر تائين ريموٽ رسائي حاصل ڪرڻ (TeamViewer)، يا آن لائن گیمنگ.

مختلف پرائيويٽ نيٽ ورڪن تي ڊوائيسز جي وچ ۾ پيئر-ٽو-پيئر ڪنيڪشن قائم ڪرڻ لاء سڀ کان وڌيڪ مؤثر طريقن مان هڪ کي سوراخ پنچنگ سڏيو ويندو آهي. هي ٽيڪنڪ عام طور تي استعمال ڪيو ويندو آهي ايپليڪيشنن سان گڏ يو ڊي پي پروٽوڪول جي بنياد تي.

پر جيڪڏهن توهان جي ايپليڪيشن کي ڊيٽا جي ضمانت واري ترسيل جي ضرورت آهي، مثال طور، توهان ڪمپيوٽرن جي وچ ۾ فائلون منتقل ڪري رهيا آهيو، ته پوءِ UDP استعمال ڪرڻ ۾ ڪيتريون ئي مشڪلاتون پيش اينديون ڇاڪاڻ ته UDP هڪ گارنٽيڊ ڊليوري پروٽوڪول نه آهي ۽ نه ئي ترتيب ۾ پيڪيٽ پهچائڻ، TCP جي برعڪس. پروٽوڪول

انهي صورت ۾، ضمانت واري پيڪيٽ جي ترسيل کي يقيني بڻائڻ لاء، ان کي لاڳو ڪرڻ جي ضرورت آهي ايپليڪيشن پرت پروٽوڪول جيڪو ضروري ڪارڪردگي مهيا ڪري ٿو ۽ UDP تي ڪم ڪري ٿو.

مان فوري طور تي نوٽ ڪرڻ چاهيان ٿو ته مختلف خانگي نيٽ ورڪن ۾ نوڊس جي وچ ۾ TCP ڪنيڪشن قائم ڪرڻ لاءِ ٽي سي پي هول پنچنگ ٽيڪنڪ موجود آهي، پر ڪيترن ئي NAT ڊوائيسز پاران ان لاءِ سپورٽ نه هجڻ جي ڪري، اهو عام طور تي ڳنڍڻ جو مکيه طريقو نه سمجهيو ويندو آهي. اهڙا نوڊس.

هن مضمون جي باقي لاء، مان صرف ضمانت جي ترسيل پروٽوڪول جي عمل تي ڌيان ڏيندس. UDP سوراخ ڇڪڻ واري ٽيڪنڪ جي عمل کي هيٺين مضمونن ۾ بيان ڪيو ويندو.

پروٽوڪول جي گهرج

  1. قابل اعتماد پيڪٽ جي ترسيل هڪ مثبت موٽ واري ميڪانيزم ذريعي لاڳو ڪئي وئي (جنهن کي مثبت اقرار سڏيو ويندو آهي)
  2. وڏي ڊيٽا جي موثر منتقلي جي ضرورت، يعني. پروٽوڪول کي غير ضروري پيڪٽ رليز ڪرڻ کان پاسو ڪرڻ گهرجي
  3. اهو ممڪن هجڻ گهرجي ته پهچائڻ جي تصديق واري ميڪانيزم کي منسوخ ڪرڻ (هڪ "خالص" UDP پروٽوڪول طور ڪم ڪرڻ جي صلاحيت)
  4. ڪمانڊ موڊ کي لاڳو ڪرڻ جي صلاحيت، هر پيغام جي تصديق سان
  5. پروٽوڪول مٿان ڊيٽا جي منتقلي جو بنيادي يونٽ هڪ پيغام هجڻ گهرجي

اهي گهرجون گهڻو ڪري قابل اعتماد ڊيٽا پروٽوڪول جي گهرجن سان ٺهڪندڙ آهن جن ۾ بيان ڪيل آهي آر ايف سي 908 и آر ايف سي 1151, ۽ مون انهن معيارن تي ڀروسو ڪيو جڏهن هن پروٽوڪول کي ترقي ڪندي.

انهن ضرورتن کي سمجهڻ لاءِ، اچو ته ڏسون ڊيٽا جي منتقلي جي وقت کي ٻن نيٽ ورڪ نوڊس جي وچ ۾ استعمال ڪندي TCP ۽ UDP پروٽوڪول. اچو ته ٻنهي صورتن ۾ اسان وٽ هڪ پيٽ گم ٿي ويندو.
TCP تي غير انٽرايڪٽو ڊيٽا جي منتقلي:.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

جيئن توهان ڊاگرام مان ڏسي سگهو ٿا، پيڪٽ جي گم ٿيڻ جي صورت ۾، TCP گم ٿيل پيڪٽ کي ڳوليندو ۽ گم ٿيل حصي جو نمبر پڇي موڪليندڙ کي رپورٽ ڪندو.
UDP پروٽوڪول ذريعي ڊيٽا جي منتقلي:.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

UDP ڪنهن به نقصان جي ڳولا جا قدم نه کڻندو آهي. UDP پروٽوڪول ۾ ٽرانسميشن جي غلطين جو ڪنٽرول مڪمل طور تي ايپليڪيشن جي ذميواري آهي.

TCP پروٽوڪول ۾ غلطي جي نشاندهي حاصل ڪئي وئي آهي هڪ ڪنيڪشن قائم ڪرڻ سان هڪ آخري نوڊ سان، انهي ڪنيڪشن جي حالت کي محفوظ ڪندي، هر پيڪٽ هيڊر ۾ موڪليل بائيٽ جو تعداد، ۽ هڪ اعتراف نمبر استعمال ڪندي رسيدن کي اطلاع ڪندي.

اضافي طور تي، ڪارڪردگي کي بهتر بڻائڻ لاءِ (يعني هڪ کان وڌيڪ ڀاڱو موڪلڻ کان سواءِ قبوليت حاصل ڪرڻ)، TCP پروٽوڪول نام نهاد ٽرانسميشن ونڊو استعمال ڪري ٿو - ڊيٽا جي بائيٽ جو تعداد جيڪو سيڪشن جي موڪليندڙ کي حاصل ڪرڻ جي اميد رکي ٿو.

TCP پروٽوڪول بابت وڌيڪ معلومات لاءِ، ڏسو آر ايف سي 793، UDP کان آر ايف سي 768جتي، حقيقت ۾، انهن جي وضاحت ڪئي وئي آهي.

مٿين مان، اهو واضح ٿئي ٿو ته UDP تي هڪ قابل اعتماد پيغام پهچائڻ واري پروٽوڪول ٺاهڻ لاء (هتي حوالو ڏنو ويو آهي. قابل اعتماد UDP)، ان کي لاڳو ڪرڻ جي ضرورت آهي ڊيٽا جي منتقلي ميڪانيزم کي TCP وانگر. يعني:

  • محفوظ ڪنيڪشن اسٽيٽ
  • حصو نمبر استعمال ڪريو
  • خاص تصديق پيڪيجز استعمال ڪريو
  • پروٽوڪول جي ذريعي وڌائڻ لاء هڪ آسان ونڊوز ميڪانيزم استعمال ڪريو

اضافي طور تي، توهان کي ضرورت آهي:

  • ھڪڙي پيغام جي شروعات کي سگنل ڏيو، ڪنيڪشن لاء وسيلن کي مختص ڪرڻ لاء
  • پيغام جي پڇاڙيءَ کي سگنل ڏيو، موصول ٿيل پيغام کي اپ اسٽريم ايپليڪيشن ڏانهن منتقل ڪرڻ ۽ پروٽوڪول وسيلن کي ڇڏڻ لاءِ
  • ڪنيڪشن-مخصوص پروٽوڪول کي "خالص" UDP طور ڪم ڪرڻ لاءِ پهچائڻ جي تصديق واري ميڪانيزم کي غير فعال ڪرڻ جي اجازت ڏيو

قابل اعتماد UDP هيڊر

ياد رهي ته هڪ UDP ڊيٽاگرام هڪ IP ڊيٽاگرام ۾ شامل ڪيو ويو آهي. قابل اعتماد يو ڊي پي پيڪٽ مناسب طور تي يو ڊي پي ڊيٽاگرام ۾ "لفاف ٿيل" آهي.
قابل اعتماد UDP هيڊر encapsulation:.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

قابل اعتماد UDP هيڊر جي جوڙجڪ بلڪل سادو آهي:

.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

  • پرچم - پيڪيج ڪنٽرول پرچم
  • MessageType - پيغام جو قسم اپ اسٽريم ايپليڪيشنن پاران استعمال ڪيو ويو مخصوص پيغامن جي رڪنيت حاصل ڪرڻ لاء
  • ٽرانسميشن آئي ڊي - ٽرانسميشن جو تعداد، وصول ڪندڙ جي ايڊريس ۽ پورٽ سان گڏ، منفرد طور تي ڪنيڪشن کي سڃاڻي ٿو
  • PacketNumber- پيڪٽ نمبر
  • اختيارن - اضافي پروٽوڪول جا اختيار. پهرين پيڪيٽ جي صورت ۾، اهو پيغام جي سائيز کي ظاهر ڪرڻ لاء استعمال ڪيو ويندو آهي

پرچم هن ريت آهن:

  • FirstPacket - پيغام جو پهريون پيڪيٽ
  • NoAsk - پيغام کي فعال ٿيڻ لاءِ اعترافي ميڪانيزم جي ضرورت ناهي
  • LastPacket - پيغام جو آخري پيڪيٽ
  • RequestForPacket - تصديقي پيڪيٽ يا گم ٿيل پيڪٽ لاءِ درخواست

پروٽوڪول جا جنرل اصول

جيئن ته قابل اعتماد UDP ٻن نوڊس جي وچ ۾ ضمانت واري پيغام جي منتقلي تي مرکوز آهي، ان کي لازمي طور تي ٻئي طرف سان ڪنيڪشن قائم ڪرڻ جي قابل هوندو. ڪنيڪشن قائم ڪرڻ لاءِ، موڪليندڙ فرسٽ پيڪٽ جي پرچم سان هڪ پيڪٽ موڪلي ٿو، جنهن جو جواب اهو ٿيندو ته ڪنيڪشن قائم آهي. سڀ جوابي پيڪيٽس، يا، ٻين لفظن ۾، اقرار جا پيڪيٽ، هميشه PacketNumber فيلڊ جي قيمت کي ڪاميابيءَ سان حاصل ڪيل پيڪٽن جي سڀ کان وڏي PacketNumber قدر کان وڌيڪ مقرر ڪريو. موڪليل پهرين پيڪٽ لاءِ آپشن فيلڊ پيغام جي سائيز آهي.

ڪنيڪشن کي ختم ڪرڻ لاءِ ساڳيو ميکانيزم استعمال ٿيندو آهي. LastPacket پرچم پيغام جي آخري پيڪٽ تي مقرر ڪيو ويو آهي. جوابي پيڪٽ ۾، آخري پيڪٽ جو تعداد + 1 اشارو ڪيو ويو آهي، جيڪو وصول ڪندڙ پاسي لاء پيغام جي ڪامياب پهچائڻ جو مطلب آهي.
ڪنيڪشن قائم ڪرڻ ۽ ختم ڪرڻ جو خاڪو:.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

جڏهن ڪنيڪشن قائم ٿئي ٿي، ڊيٽا جي منتقلي شروع ٿئي ٿي. ڊيٽا پيڪرن جي بلاڪ ۾ منتقل ڪئي وئي آهي. هر بلاڪ، آخري هڪ کان سواء، پيڪيٽس جو هڪ مقرر تعداد تي مشتمل آهي. اهو حاصل ڪرڻ / منتقلي ونڊو سائيز جي برابر آهي. ڊيٽا جي آخري بلاڪ ۾ ٿي سگھي ٿو گھٽ پيڪٽس. هر بلاڪ موڪلڻ کان پوء، موڪلڻ واري پاسي ترسيل جي تصديق يا گم ٿيل پيڪٽس کي ٻيهر پهچائڻ جي درخواست جو انتظار ڪري ٿو، جواب حاصل ڪرڻ لاء وصول ڪرڻ / منتقلي ونڊو کليل ڇڏيندي. بلاڪ ترسيل جي تصديق حاصل ڪرڻ کان پوء، وصول / منتقلي ونڊو شفٽ ۽ ڊيٽا جو ايندڙ بلاڪ موڪليو ويو آهي.

وصول ڪندڙ طرف پيڪٽ وصول ڪري ٿو. هر پيڪٽ کي چيڪ ڪيو ويو آهي ته ڇا اهو ٽرانسميشن ونڊو اندر اچي ٿو. پيڪيٽ ۽ نقل جيڪي ونڊو ۾ نه ٿا اچن، فلٽر ٿيل آهن. ڇاڪاڻ ته جيڪڏهن ونڊو جي سائيز مقرر ڪئي وئي آهي ۽ وصول ڪندڙ ۽ موڪليندڙ لاءِ هڪجهڙائي آهي، ته پوءِ پيڪٽس جي بلاڪ جي صورت ۾ بغير ڪنهن نقصان جي پهچائڻ جي صورت ۾، ونڊو کي ڊيٽا جي ايندڙ بلاڪ جا پيڪيٽ وصول ڪرڻ لاءِ منتقل ڪيو ويندو آهي ۽ ترسيل جي تصديق هوندي آهي. موڪليو ويو. جيڪڏهن ونڊو ڪم ٽائمر پاران مقرر ڪيل مدي اندر نه ڀريو وڃي ته پوءِ هڪ چيڪ شروع ڪيو ويندو جنهن تي پيڪيٽ نه پهچايا ويا آهن ۽ ٻيهر پهچائڻ لاءِ درخواستون موڪليون وينديون.
ٻيهر ٽرانسميشن ڊراگرام:.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

ٽائم آئوٽ ۽ پروٽوڪول ٽائمر

اتي ڪيترائي سبب آھن جو ڪنيڪشن قائم نه ٿي سگھي. مثال طور، جيڪڏهن وصول ڪندڙ پارٽي آف لائن آهي. انهي حالت ۾، جڏهن ڪنيڪشن قائم ڪرڻ جي ڪوشش ڪئي ويندي، ڪنيڪشن وقت ختم ٿيڻ سان بند ٿي ويندي. قابل اعتماد UDP عمل درآمد وقت مقرر ڪرڻ لاء ٻه ٽائمر استعمال ڪري ٿو. پهريون، ڪم ڪندڙ ٽائمر، ريموٽ ميزبان جي جواب جو انتظار ڪرڻ لاء استعمال ڪيو ويندو آهي. جيڪڏهن اهو موڪليندڙ پاسي تي فائر ٿئي ٿو، پوء آخري موڪليل پيڪٽ ٻيهر موڪلي وئي آهي. جيڪڏهن ٽائمر وصول ڪندڙ تي ختم ٿئي ٿي، پوء گم ٿيل پيڪٽس لاء چيڪ ڪيو ويو آهي ۽ ٻيهر پهچائڻ لاء درخواستون موڪليا ويا آهن.

ٻئي ٽائمر نوڊس جي وچ ۾ رابطي جي کوٽ جي صورت ۾ ڪنيڪشن کي بند ڪرڻ جي ضرورت آهي. موڪليندڙ پاسي لاء، اهو ڪم ڪندڙ ٽائمر ختم ٿيڻ کان پوء فوري طور تي شروع ٿئي ٿو، ۽ ريموٽ نوڊ کان جواب جو انتظار ڪري ٿو. جيڪڏهن مخصوص مدت جي اندر ڪو جواب نه آهي، ڪنيڪشن ختم ٿي ويندي آهي ۽ وسيلن کي آزاد ڪيو ويندو آهي. وصول ڪرڻ واري پاسي لاء، ڪنيڪشن بند ٽائمر شروع ڪيو ويندو آهي ڪم ٽائمر ٻه ڀيرا ختم ٿيڻ کان پوء. اهو ضروري آهي ته تصديق واري پيڪٽ جي نقصان جي خلاف بيمه. جڏهن ٽائمر ختم ٿئي ٿي، ڪنيڪشن پڻ ختم ٿي وئي آهي ۽ وسيلن کي آزاد ڪيو ويو آهي.

قابل اعتماد UDP ٽرانسميشن اسٽيٽ ڊراگرام

پروٽوڪول جا اصول هڪ محدود رياستي مشين ۾ لاڳو ڪيا ويا آهن، جن مان هر رياست پيڪٽ پروسيسنگ جي هڪ خاص منطق لاءِ ذميوار آهي.
قابل اعتماد UDP اسٽيٽ ڊراگرام:

.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

بند - حقيقت ۾ هڪ رياست ناهي، اهو خودڪار لاء هڪ شروعاتي ۽ آخري نقطو آهي. رياست لاء بند هڪ ٽرانسميشن ڪنٽرول بلاڪ حاصل ڪيو ويو آهي، جيڪو، هڪ غير مطابقت رکندڙ UDP سرور کي لاڳو ڪرڻ، پيڪن کي مناسب ڪنيڪشن ڏانهن موڪلي ٿو ۽ رياستي پروسيسنگ شروع ڪري ٿو.

FirstPacketSending - شروعاتي حالت جنهن ۾ ٻاهر نڪرڻ وارو ڪنيڪشن هوندو آهي جڏهن پيغام موڪليو ويندو آهي.

هن حالت ۾، عام پيغامن لاء پهريون پيٽ موڪليو ويو آهي. بغير تصديق جي پيغامن لاء، هي واحد رياست آهي جتي سڄو پيغام موڪليو ويو آهي.

موڪلڻ واري سائيڪل - پيغام پيڪٽ جي منتقلي لاء زميني حالت.

رياست کان ان کي منتقلي FirstPacketSending پيغام جي پهرين پيڪٽ کان پوء موڪليو ويو آهي. اهو هن حالت ۾ آهي ته سڀني اعترافن ۽ ٻيهر منتقلي لاءِ درخواستون اچن ٿيون. ان مان نڪرڻ ٻن صورتن ۾ ممڪن آهي - پيغام جي ڪامياب پهچائڻ جي صورت ۾ يا وقت ختم ٿيڻ جي صورت ۾.

پهريون پيڪيٽ وصول ڪيو - پيغام جي وصول ڪندڙ لاء ابتدائي حالت.

اهو ٽرانسميشن جي شروعات جي درستگي کي چيڪ ڪري ٿو، ضروري جوڙجڪ ٺاهي ٿو، ۽ پهرين پيڪٽ جي وصولي جي تصديق موڪلي ٿو.

هڪ پيغام لاءِ جيڪو هڪ واحد پيڪيٽ تي مشتمل آهي ۽ ترسيل جي ثبوت استعمال ڪرڻ کان سواءِ موڪليو ويو، اها واحد رياست آهي. اهڙي پيغام کي پروسيس ڪرڻ کان پوء، ڪنيڪشن بند ٿي وئي آهي.

هڪجهڙائي - پيغام پيڪٽ حاصل ڪرڻ لاء بنيادي حالت.

اهو پيڪٽس کي عارضي اسٽوريج ڏانهن لکندو آهي، پيڪٽ جي نقصان جي جانچ ڪري ٿو، پيڪيٽس جي هڪ بلاڪ جي ترسيل ۽ مڪمل پيغام لاءِ اعتراف موڪلي ٿو، ۽ گم ٿيل پيڪٽن جي ٻيهر پهچائڻ لاءِ درخواستون موڪلي ٿو. مڪمل پيغام جي ڪامياب وصولي جي صورت ۾، ڪنيڪشن رياست ۾ وڃي ٿو مڪمل ٿيوٻي صورت ۾، وقت ختم ٿي ويندو.

مڪمل ٿيو - مڪمل پيغام جي ڪامياب رسيد جي صورت ۾ ڪنيڪشن کي بند ڪرڻ.

هي رياست پيغام جي اسيمبليءَ لاءِ ضروري آهي ۽ ان صورت ۾ جڏهن پيغام جي ترسيل جي تصديق موڪليندڙ جي رستي ۾ گم ٿي وئي هئي. هي رياست هڪ وقت ختم ٿي وئي آهي، پر ڪنيڪشن کي ڪاميابي سان بند ڪيو ويو آهي.

ڪوڊ ۾ وڌيڪ. ٽرانسميشن ڪنٽرول يونٽ

قابل اعتماد UDP جي اهم عنصرن مان هڪ آهي ٽرانسميشن ڪنٽرول بلاڪ. هن بلاڪ جو ڪم موجوده ڪنيڪشن ۽ معاون عناصر کي ذخيرو ڪرڻ، لاڳاپيل ڪنيڪشن ۾ ايندڙ پيڪيٽس کي ورهائڻ، ڪنيڪشن ڏانهن پيڪيٽس موڪلڻ لاءِ انٽرفيس مهيا ڪرڻ، ۽ پروٽوڪول API کي لاڳو ڪرڻ آهي. ٽرانسميشن ڪنٽرول بلاڪ 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 رياست لاءِ هڪ انٽرفيس مهيا ڪري ٿو:

.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

پروٽوڪول جو سڄو منطق مٿي پيش ڪيل طبقن سان لاڳو ٿئي ٿو، گڏو گڏ هڪ معاون طبقي سان جيڪو جامد طريقا مهيا ڪري ٿو، مثال طور، ڪنيڪشن رڪارڊ مان ReliableUdp هيڊر ٺاهڻ.

اڳيون، اسان تفصيل سان غور ڪنداسين انٽرفيس طريقن جي عمل درآمد تي جيڪو پروٽوڪول جي بنيادي الگورتھم کي طئي ڪري ٿو.

DisposeByTimeout جو طريقو

DisposeByTimeout طريقو وقت ختم ٿيڻ کان پوءِ ڪنيڪشن جا وسيلا جاري ڪرڻ ۽ ڪامياب/ناڪام پيغام پهچائڻ جي سگنلنگ لاءِ ذميوار آهي.
ReliableUdpState.DisposeByTimeout:

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

اهو صرف رياست ۾ ختم ڪيو ويو آهي مڪمل ٿيو.
مڪمل ٿيل.DisposeByTimeout:

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

پروسيس پيڪيٽس جو طريقو

پروسيس پيڪٽ جو طريقو هڪ پيڪيج يا پيڪيجز جي اضافي پروسيسنگ لاء ذميوار آهي. سڌو سنئون يا هڪ پيڪٽ انتظار ٽائمر ذريعي سڏيو.

قابل هڪجهڙائي طريقو ختم ڪيو ويو آهي ۽ گم ٿيل پيڪٽس جي جانچ ڪرڻ ۽ رياست ڏانهن منتقل ڪرڻ جو ذميوار آهي مڪمل ٿيو، آخري پيڪٽ حاصل ڪرڻ ۽ ڪامياب چيڪ پاس ڪرڻ جي صورت ۾
گڏ ڪرڻ. پروسيس پيڪيٽس:

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);
  }
}

قابل موڪلڻ واري سائيڪل اهو طريقو صرف ٽائمر تي سڏيو ويندو آهي، ۽ آخري پيغام کي ٻيهر موڪلڻ جو ذميوار آهي، انهي سان گڏ ڪنيڪشن کي بند ڪرڻ واري ٽائمر کي فعال ڪرڻ.
SendingCycle.ProcessPackets:

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);
  }
}

قابل موڪلڻ واري سائيڪل هي طريقو ترسيل قبوليت ۽ ٻيهر منتقلي جي درخواستن کي قبول ڪرڻ لاءِ ختم ڪيو ويو آهي.
SendingCycle.ReceivePacket:

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);
  }
}

موڪل جو طريقو

قابل FirstPacketSending اهو طريقو ڊيٽا جو پهريون پيڪيٽ موڪلي ٿو، يا، جيڪڏهن پيغام پهچائڻ جي تصديق جي ضرورت ناهي، سڄو پيغام.
FirstPacketSending.SendPacket:

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);
}

قابل موڪلڻ واري سائيڪل هن طريقي ۾، پيڪيٽس جو هڪ بلاڪ موڪليو ويو آهي.
SendingCycle.SendPacket:

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 );
  }
}

ڪوڊ ۾ وڌيڪ. ڪنيڪشن ٺاهڻ ۽ قائم ڪرڻ

هاڻي ته اسان ڏٺو آهي بنيادي رياستون ۽ رياستن کي سنڀالڻ لاءِ استعمال ڪيل طريقا، اچو ته ڪجهه مثالن کي ٽوڙيون ته پروٽوڪول ڪيئن ڪم ڪري ٿو وڌيڪ تفصيل سان.
عام حالتن ۾ ڊيٽا ٽرانسميشن ڊراگرام:.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

تفصيل سان تخليق تي غور ڪريو ڪنيڪشن رڪارڊ ڳنڍڻ ۽ پهريون پيڪٽ موڪلڻ لاءِ. منتقلي هميشه ايپليڪيشن طرفان شروع ڪئي وئي آهي جيڪا سڏي ٿو پيغام موڪليو API. اڳيون، ٽرانسميشن ڪنٽرول بلاڪ جو 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]);
}

پهريون پيڪٽ موڪلڻ (FirstPacketSending State):

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 طريقو استعمال ڪندي، موڪليل پيڪٽ وصول ڪري ٿو، هڪ نئون ٺاهي ٿو ڪنيڪشن رڪارڊ ۽ هي پيڪٽ پاس ڪري ٿو، اڳي پارس ٿيل هيڊر سان، پروسيسنگ لاءِ رياست جي ReceivePacket طريقي ڏانهن پهريون پيڪيٽ وصول ڪيو
حاصل ڪرڻ واري پاسي تي ڪنيڪشن ٺاهڻ:

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);
}

پهريون پيڪٽ حاصل ڪرڻ ۽ هڪ اعتراف موڪلڻ (FirstPacketReceived State):

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 جو هڪ اهم حصو آهي. هڪ مثال تي غور ڪريو جنهن ۾ هڪ وچولي نوڊ ناڪام ٿي ويو ۽ ٻنهي طرفن ۾ ڊيٽا پهچائڻ ناممڪن ٿي ويو.
وقت ختم ٿيڻ سان ڪنيڪشن بند ڪرڻ لاءِ ڊراگرام:.Net لاءِ قابل اعتماد Udp پروٽوڪول جو نفاذ

جيئن آريگرام مان ڏسي سگھجي ٿو، موڪليندڙ جو ڪم ٽائمر پيڪيٽ جي بلاڪ موڪلڻ کان پوءِ فوري طور تي شروع ٿئي ٿو. اهو رياست جي SendPacket طريقي ۾ ٿئي ٿو موڪلڻ واري سائيڪل.
ڪم ٽائمر کي فعال ڪرڻ (SendingCycle State):

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 سيڪنڊن تي مقرر ڪيو ويو آهي.

ايندڙ ڪنيڪشن لاءِ، ٽائمر شروع ٿئي ٿو آخري اچڻ واري ڊيٽا پيڪٽ حاصل ڪرڻ کان پوءِ، اهو ٿئي ٿو رياست جي ReceivePacket طريقي سان هڪجهڙائي
ڪم ٽائمر کي فعال ڪرڻ (جماعت واري حالت):

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);
  // ...
}

ڪم ڪندڙ ٽائمر جي انتظار ۾ ايندڙ ڪنيڪشن تي وڌيڪ پيڪيٽ نه آيا. ٽائمر بند ٿي ويو ۽ پروسيس پيڪٽس جو طريقو سڏيو ويو، جتي گم ٿيل پيڪٽ مليا ويا ۽ ٻيهر پهچائڻ جي درخواستون پهريون ڀيرو موڪليو ويو.
ٻيهر پهچائڻ جي درخواستون موڪلڻ (جماعت واري حالت):

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 متغير مقرر ڪيو ويو آهي سچ. هي متغير ڪم ڪندڙ ٽائمر کي ٻيهر شروع ڪرڻ جو ذميوار آهي.

موڪليندڙ جي پاسي تي، ڪم ڪندڙ ٽائمر پڻ ٽاريو ويندو آهي ۽ آخري موڪليل پيڪٽ ٻيهر موڪليو ويندو آهي.
ڪنيڪشن بند ٽائمر کي فعال ڪرڻ (SendingCycle State):

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

ان کان پوء، ڪنيڪشن بند ٽائمر نڪرڻ واري ڪنيڪشن ۾ شروع ٿئي ٿو.
ReliableUdpState.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 ​​سيڪنڊ آهي.

ٿوري دير کان پوء، وصول ڪندڙ جي پاسي تي ڪم ڪندڙ ٽائمر ٻيهر فائر ڪيو، درخواستون ٻيهر موڪليا ويا، جنهن کان پوء ڪنيڪشن بند ٽائمر ايندڙ ڪنيڪشن لاء شروع ٿئي ٿو.

جڏهن بند ٽائمرز کي باهه، ٻنهي ڪنيڪشن رڪارڊ جا سڀئي وسيلا ڇڏيا ويا آهن. موڪليندڙ رپورٽ ڪري ٿو ترسيل ناڪامي کي اپ اسٽريم ايپليڪيشن (ڏسو Reliable 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);
  }
}

ڪوڊ ۾ وڌيڪ. ڊيٽا جي منتقلي جي بحالي

پيٽ جي نقصان جي صورت ۾ ڊيٽا ٽرانسميشن وصولي ڊراگرام:.Net لاءِ قابل اعتماد 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);
      }
    }
    // ...
  }
}

موڪليندڙ ٻيهر پهچائڻ جي درخواست قبول ڪندو ۽ گم ٿيل پيڪيٽ موڪليندو. اهو نوٽ ڪرڻ جي قابل آهي ته هن وقت موڪليندڙ اڳ ۾ ئي ڪنيڪشن بند ڪرڻ وارو ٽائمر شروع ڪري چڪو آهي ۽، جڏهن هڪ درخواست ملي ٿي، اهو ري سيٽ ڪيو ويو آهي.
گم ٿيل پيڪٽس ٻيهر موڪلڻ (SendingCycle State):

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

ڊيٽا جي منتقلي پروٽوڪول سان لهه وچڙ ڪرڻ لاء، اتي هڪ کليل Reliable 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)

ٿڪل

هن مضمون ۾ گهڻو ڪجهه بيان نه ڪيو ويو آهي. ٿريڊ ملائڻ واري ميڪانيزم، استثنا ۽ غلطي کي سنڀالڻ، غير مطابقت واري پيغام موڪلڻ جا طريقا. پر پروٽوڪول جو بنيادي، منطق جو بيان پروسيسنگ پيڪٽس لاءِ، ڪنيڪشن قائم ڪرڻ، ۽ ٽائيم آئوٽ کي سنڀالڻ، توھان لاءِ واضح ھئڻ گھرجي.

قابل اعتماد ترسيل پروٽوڪول جو ڏيکاريل نسخو مضبوط ۽ لچڪدار آهي اڳي بيان ڪيل گهرجن کي پورو ڪرڻ لاءِ. پر مان شامل ڪرڻ چاهيان ٿو ته بيان ڪيل عمل کي بهتر بڻائي سگهجي ٿو. مثال طور، throughput کي وڌائڻ ۽ متحرڪ طور تي ٽائمر جي مدي کي تبديل ڪرڻ لاء، ميڪانيزم جهڙوڪ سلائڊنگ ونڊو ۽ RTT کي پروٽوڪول ۾ شامل ڪري سگھجي ٿو، اهو پڻ ڪارائتو ٿيندو ته MTU کي ڪنيڪشن نوڊس جي وچ ۾ طئي ڪرڻ لاء هڪ ميکانيزم لاڳو ڪرڻ (پر صرف ان صورت ۾ جڏهن وڏا پيغام موڪليا وڃن) .

توهان جي توجه جي مهرباني، مان توهان جي تبصرن ۽ تبصرن جو منتظر آهيان.

پي ايس انهن لاءِ جيڪي تفصيل ۾ دلچسپي رکن ٿا يا صرف پروٽوڪول کي جانچڻ چاهين ٿا، GitHube تي پروجيڪٽ جي لنڪ:
قابل اعتماد UDP پروجيڪٽ

مفيد لنڪس ۽ آرٽيڪل

  1. TCP پروٽوڪول جي وضاحت: انگريزي ۾ и روسي ۾
  2. UDP پروٽوڪول جي وضاحت: انگريزي ۾ и روسي ۾
  3. RUDP پروٽوڪول جي بحث: مسودو-ietf-sigtran-reliable-udp-00
  4. قابل اعتماد ڊيٽا پروٽوڪول: آر ايف سي 908 и آر ايف سي 1151
  5. UDP تي ترسيل جي تصديق جو هڪ سادي عمل: .NET ۽ UDP سان توهان جي نيٽ ورڪنگ جو مڪمل ڪنٽرول وٺو
  6. آرٽيڪل بيان ڪري ٿو NAT ٽرورسل ميڪانيزم: نيٽ ورڪ ايڊريس مترجم جي وچ ۾ پير-کان-پيئر ڪميونيڪيشن
  7. هم وقت سازي پروگرامنگ ماڊل جو نفاذ: CLR Asynchronous پروگرامنگ ماڊل کي لاڳو ڪرڻ и IAsyncResult ڊيزائن جي نموني کي ڪيئن لاڳو ڪجي
  8. ٽاسڪ جي بنياد تي هم وقت سازي جي نمونن (APM ۾ TAP):
    TPL ۽ روايتي .NET اسينچرونس پروگرامنگ
    ٻين Asynchronous نمونن ۽ قسمن سان مداخلت

تازه ڪاري: توهان جي مهرباني mayorovp и sidristij انٽرفيس ۾ ڪم شامل ڪرڻ جي خيال لاءِ. پراڻي آپريٽنگ سسٽم سان لائبريري جي مطابقت جي ڀڃڪڙي نه ڪئي وئي آهي، ڇاڪاڻ ته 4th فريم ورڪ ٻنهي XP ۽ 2003 سرور کي سپورٽ ڪري ٿو.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو