اذهب إلى المحتوى

برتوكولات تدفق البايتات الموثوقة في الشبكات الحاسوبية: بروتوكول TCP مثالا


Ola Abbas

بروتوكول النقل الأعقد هو البروتوكول الذي يوفر خدمة تدفق بايتات موثوقة Reliable Byte Stream وموجهة نحو الاتصال، على عكس بروتوكول فك تعدد الإرسال demultiplexing البسيط كبروتوكول UDP. أثبتت هذه الخدمة أنها مفيدة لمجموعةٍ واسعة من التطبيقات لأنها تحرر التطبيق من القلق بشأن البيانات المفقودة أو المُعاد ترتيبها. ربما يكون بروتوكول التحكم في الإرسال Transmission Control Protocol عبر الإنترنت هو البروتوكول الأكثر استخدامًا من هذا النوع، كما أنه مضبوطٌ بعناية. لهذين السببين يدرس هذا القسم بروتوكول TCP بالتفصيل، على الرغم من أننا نحدد ونناقش خيارات التصميم البديلة في نهاية القسم.

يضمن بروتوكول TCP التسليمَ الموثوق به والمرتّب لتدفقٍ من البايتات. إنه بروتوكول ثنائي الاتجاه full-duplex، مما يعني أن كل اتصال TCP يدعم زوجًا من تدفقات البايتات، حيث يتدفق كلٌّ منهما في اتجاه. يتضمن أيضًا آليةً للتحكم في التدفق لكل من تدفقات البايتات هذه التي تسمح للمستقبل بتحديد مقدار البيانات التي يمكن للمرسل إرسالها في وقتٍ معين. أخيرًا، يدعم بروتوكول TCP آلية فك تعدد الإرسال، مثل بروتوكول UDP، والتي تسمح لبرامج تطبيقات متعددة على أي مضيف معين بإجراء محادثة مع نظرائها في نفس الوقت.

يطبّق بروتوكول TCP أيضًا، بالإضافة إلى الميزات المذكورة أعلاه، آلية التحكم في الازدحام عالية الضبط. تتمثل فكرة هذه الآلية في التحكم في مدى سرعة إرسال بروتوكول TCP للبيانات، ليس من أجل منع المرسل من الإفراط في تشغيل جهاز الاستقبال، ولكن من أجل منع المرسل من زيادة التحميل على الشبكة.

يخلط العديد من الأشخاص بين التحكم في الازدحام congestion control والتحكم في التدفق flow control، لذلك سنعيد صياغة الفرق. يتضمن التحكم في التدفق منع المرسلين من تجاوز سعة أجهزة الاستقبال، بينما يتضمّن التحكم في الازدحام منع حقن الكثير من البيانات في الشبكة، مما يتسبب في زيادة تحميل المبدّلات switches أو الروابط links. وبالتالي فإن التحكم في التدفق هو مشكلة شاملة، بينما يهتم التحكم في الازدحام بكيفية تفاعل المضيفين والشبكات.

قضايا طرف إلى طرف End-to-End Issues

يوجد في صميم بروتوكول TCP خوارزمية النافذة المنزلقة sliding window. على الرغم من كونها نفس الخوارزمية الأساسية المُستخدمة غالبًا على مستوى الروابط، نظرًا لأن بروتوكول TCP يعمل عبر طبقة الإنترنت بدلًا من الرابط الفيزيائي نقطة لنقطة، إلا أنّ هناك العديد من الاختلافات المهمة. يحدد هذا القسم الفرعي هذه الاختلافات ويشرح كيف تعقّد بروتوكول TCP، ثم تصف الأقسام الفرعية التالية كيف يعالج بروتوكول TCP هذه التعقيدات وغيرها.

أولًا، بينما تعمل خوارزمية النافذة المنزلقة على مستوى الروابط المقدمة عبر رابطٍ فيزيائي واحد يربط دائمًا نفس جهازي الحاسوب، فيدعم بروتوكول TCP الاتصالات المنطقية بين العمليات التي تعمل على أي جهازَي حاسوب على شبكة الإنترنت. هذا يعني أن بروتوكول TCP يحتاج إلى مرحلة تأسيس اتصال صريحة يتفق خلالها طرفا الاتصال على تبادل البيانات مع بعضهما بعضًا. يماثل هذا الاختلاف الاضطرار إلى الاتصال dial up بالطرف الآخر، بدلًا من امتلاك خط هاتف مخصَّص dedicated phone line. ويحتوي بروتوكول TCP أيضًا على مرحلة تفكيك اتصال صريحة. أحد الأشياء التي تحدث أثناء إنشاء الاتصال هو قيام الطرفين بإنشاء حالة مشتركة ما لتمكين خوارزمية النافذة المنزلقة من البدء. يجب فصل الاتصال حتى يعرف كل مضيف أنه لا بأس من تحرير هذه الحالة.

ثانيًا، في حين أنه يوجد لدى رابط فيزيائي واحد يربط دائمًا نفس جهازي الحاسوب وقت رحلة ذهاب وإياب round-trip time أو اختصارًا RTT ثابت، فمن المحتمل أن يكون لدى اتصالات TCP أوقات ذهابٍ وإيابٍ مختلفة. قد يساوي وقت RTT من أجل اتصال TCP بين مضيفٍ في سان فرانسيسكو ومضيفٍ في بوسطن على سبيل المثال، مفصول بينهما بعدة آلاف من الكيلومترات، 100 ميلي ثانية، بينما قد يساوي وقت RTT من أجل اتصال TCP بين مضيفين في نفس الغرفة، على بعد أمتار قليلة فقط، 1 ميلي ثانية فقط. يجب أن يكون بروتوكول TCP نفسه قادرًا على دعم كلا الاتصالين. و لجعل الأمور أسوأ، فقد يبلغ وقت RTT لِاتصال TCP بين المضيفين في سان فرانسيسكو وبوسطن 100 ميلي ثانية في الساعة 3 صباحًا، ولكنّ وقت RTT يبلغ 500 ميلي ثانية في الساعة 3 مساءً. يمكن أن تكون الاختلافات في وقت RTT ممكنةً أثناء اتصال TCP الذي لا يدوم سوى بضع دقائق. ما يعنيه هذا بالنسبة لخوارزمية النافذة المنزلقة هو أن آلية المهلة الزمنية timeout التي تؤدي إلى إعادة الإرسال يجب أن تكون قابلة للتكيُّف. (بالتأكيد، يجب أن تكون المهلة الزمنية لرابط من نقطةٍ إلى نقطة معاملًا قابلًا للإعداد، ولكن ليس من الضروري تكييف هذا المؤقت مع زوجٍ معين من العقد).

ثالثًا، إمكانية إعادة ترتيب الرزم أثناء عبورها للإنترنت، إنما هذا غير ممكن على رابط من نقطة إلى نقطة حيث يجب أن تكون الرزمة الأولى الموضوعة في أحد طرفي الرابط هي أول ما يظهر في الطرف الآخر. لا تسبب الرزم المخالفة قليلًا للترتيب مشاكلًا لأن خوارزمية النافذة المنزلقة يمكنها إعادة ترتيب الرزم بصورةٍ صحيحة باستخدام الرقم التسلسلي. تكمن المشكلة الحقيقية في المدى الذي يمكن أن تصل إليه رزمٌ مخالفة للترتيب، أو، كما يُقال بطريقة أخرى، مدى تأخر وصول الرزمة إلى الوجهة. يمكن أن تتأخر الرزمة في الإنترنت في أسوأ الحالات حتى انتهاء صلاحية حقل IP الذي هو العُمر time to live أو (TTL)، وفي ذلك الوقت تُهمَل الرزمة (وبالتالي لا يوجد خطر من وصولها متأخرة). يفترض بروتوكول TCP أن كل رزمة لها عمرٌ أقصى مع العلم أن بروتوكول IP يرمي الرزم بعيدًا بعد انتهاء صلاحية حقل TTL. يُعد العمر الدقيق، المعروف باسم الحد الأقصى لعمر الجزء maximum segment lifetime أو اختصارًا MSL، خيارًا هندسيًا، والإعداد الحالي الموصى به هو 120 ثانية. ضع في بالك أن بروتوكول IP لا يفرض مباشرة هذه القيمة البالغة 120 ثانية، أي أنه ببساطة تقدير تقليدي يقوم به بروتوكول TCP لطول مدة بقاء الرزمة على الإنترنت. يجب أن يكون بروتوكول TCP جاهزًا حتى تظهر الرزم القديمة جدًا فجأة في جهاز الاستقبال، مما قد يؤدي إلى إرباك خوارزمية النافذة المنزلقة.

رابعًا، تُصمَّم أجهزة الحواسيب المتصلة برابط من نقطة إلى نقطة لدعم الروابط. فإذا حُسِب جداء التأخير × حيز النطاق التراسلي للرابط ليكون 8 كيلوبايت على سبيل المثال، مما يعني أن حجم النافذة حُدِّد للسماح بما يصل إلى 8 كيلوبايت من البيانات بعدم الإقرار unacknowledged في وقت معين، وعندها فمن المحتمل أن يكون لأجهزة الحاسوب في أيٍّ من طرفي الرابط القدرة على تخزين ما يصل إلى 8 كيلوبايت من البيانات. سيكون تصميم النظام بخلاف ذلك سخيفًا. يمكن توصيل أي نوع من أجهزة الحاسوب تقريبًا بالإنترنت، مما يجعل كمية الموارد المخصصة لأي اتصال TCP متغيرًا بدرجة كبيرة، لا سيما بالنظر إلى أن أي مضيف يمكنه دعم مئات اتصالات TCP في نفس الوقت. وهذا يعني أن بروتوكول TCP يجب أن يتضمن آلية يستخدمها كل جانب "لمعرفة" الموارد (مقدار مساحة المخزن المؤقت على سبيل المثال) التي يستطيع الجانب الآخر تطبيقها على الاتصال. وهذه هي مشكلة التحكم في التدفق.

خامسًا، نظرًا لأن جانب الإرسال للرابط المتصل مباشرةً لا يمكنه الإرسال بصورةٍ أسرع مما يسمح به حيز نطاق الرابط التراسلي، ولأن مضيفًا واحدًا فقط يضخ البيانات في الرابط، فلا يمكن جعل الرابط مزدحمًا عن غير قصد. يكون الحِمل على الرابط مرئيًا على شكل رتل من الرزم عند المرسل، وفي المقابل، ليس لدى جانب الإرسال من اتصال TCP فكرة عن الروابط التي سيجري اجتيازها للوصول إلى الوجهة. قد يكون جهاز الإرسال متصلًا مباشرةً بشبكة إيثرنت سريعة نسبيًا على سبيل المثال، وقادرة على إرسال البيانات بمعدل 10 جيجابت في الثانية، ولكن يجب اجتياز رابطٍ بسرعة 1.5 ميجابت في الثانية في مكان ما في منتصف الشبكة. لجعل الأمور أسوأ، قد تحاول البيانات التي تنشئها العديد من المصادر المختلفة اجتياز هذا الرابط البطيء نفسه، وهذا يؤدي إلى مشكلة ازدحام الشبكة.

نختم هذه المناقشة لقضايا طرفٍ إلى طرف من خلال مقارنة نهج TCP لتوفير خدمة توصيلٍ موثوقة / مرتبة مع النهج الذي تستخدمه الشبكات القائمة على الدارات الافتراضية مثل شبكة X.25 المهمة تاريخيًا. يُفترض أن شبكة IP الأساسية غير موثوقة في بروتوكول TCP وتسلّم الرسائل مخالفةً للترتيب، أي يستخدم بروتوكول TCP خوارزمية النافذة المنزلقة على أساس طرفٍ إلى طرف لتوفير تسليمٍ موثوق / مرتب. وفي المقابل، تستخدم شبكات X.25 بروتوكول النافذة المنزلقة داخل الشبكة، على أساس النقل قفزة بقفزة hop-by-hop. الافتراض الكامن وراء هذا النهج هو أنه إذا ُسلِّمت الرسائل بصورة موثوقة ومرتّبة بين كل زوج من العقد على طول المسار بين مضيف المصدر والمضيف الوجهة، فإن الخدمة من طرفٍ إلى طرف تضمن أيضًا تسليمًا موثوقًا / مرتبًا.

تكمن مشكلة هذا النهج الأخير في أن سلسلةً من الضمانات السريعة المتتالية من نقل قفزة بقفزة لا تضيف بالضرورة ضمانًا شاملًا. أولًا، إذا أضيف رابطٌ غير متجانس (رابط إيثرنت مثلًا) إلى أحد طرفي المسار، فلا يوجد ضمان بأن هذه الخطوة ستحافظ على نفس الخدمة مثل الخطوات الأخرى. ثانيًا، إذا ضمِن بروتوكول النافذة المنزلقة تسليم الرسائل بصورة صحيحة من العقدة A إلى العقدة B، ومن ثم من العقدة B إلى العقدة C، فإنه لا يضمن أن العقدة B تتصرف بصفةٍ مثالية، حيث عُرفت عقد الشبكة بإدخال أخطاءٍ في الرسائل أثناء نقلها من مخزن الإدخال المؤقت إلى مخزن الإخراج المؤقت. ومن المعروف أيضًا أن عقد الشبكة تعيد ترتيب الرسائل عن طريق الخطأ. لا يزال من الضروري توفير فحوصات طرفٍ إلى طرف لضمان خدمة موثوقة / مرتبة نتيجة لأسباب الضعف البسيطة هذه، على الرغم من تطبيق المستويات الأدنى من النظام أيضًا لهذه الوظيفة.

اقتباس

توضح هذه المناقشة أحد أهم المبادئ في تصميم النظام وهو مبدأ طرف إلى طرف end-to-end argument. ينص هذا المبدأ على أنه لا ينبغي تأمين وظيفة (توفير تسليمٍ موثوق / مرتب في مثالنا) في المستويات الأدنى من النظام ما لم يجري تطبيقها بصورةٍ كاملة وصحيحة على هذا المستوى. لذلك تجادل هذه القاعدة لصالح نهج TCP / IP،وهي ليست مطلقة، فهي تسمح للوظائف بأن تُوفَّر بصورةٍ غير كاملة عند مستوى منخفض كتحسينٍ للأداء. هذا هو السبب في أن هذه القاعدة متوافقة تمامًا مع مبدأ end-to-end argument لإجراء اكتشاف الخطأ (CRC على سبيل المثال) على أساس خطوةٍ بخطوة، أي يُفضّل اكتشاف وإعادة إرسال رزمةٍ تالفة واحدة عبر قفزة أو خطوةٍ واحدة بدلًا من الاضطرار إلى إعادة إرسال ملفٍ كامل من طرفٍ إلى طرف.

صيغة الجزء segment format

بروتوكول TCP هو بروتوكول موجَّهٌ بالبايت، مما يعني أن المرسل يكتب البايت في اتصال TCP ويقرأ المتلقي البايت من خلال اتصال TCP. على الرغم من أن "تدفق البايتات" يصف الخدمة التي يقدمها بروتوكول TCP لعمليات التطبيق، فإن بروتوكول TCP نفسه لا يرسل البايتات الفردية عبر الإنترنت. وبدلًا من ذلك، يخزن بروتوكول TCP على المضيف المصدر ما يكفي من البايتات من عملية الإرسال لملء رزمةٍ بحجم معقول ثم يرسل هذه الرزمة إلى نظيره على المضيف الوجهة. يفرغ بروتوكول TCP على المضيف الوجهة بعد ذلك محتويات الرزمة في مخزن الاستلام المؤقت، وتقرأ عملية الاستلام من هذا المخزن المؤقت في أوقات فراغها. يوضح الشكل التالي هذا الموقف، حيث يُظهر تدفق البيانات في اتجاه واحد فقط بهدف التبسيط. تذكر أن اتصال TCP واحدًا يدعم عمومًا تدفقات البايتات في كلا الاتجاهين.

HowTCPManagesAByteStream.png

تسمَّى الرزم المتبادلة بين نظراء بروتوكول TCP في الشكل السابق باسم الأجزاء segments، لأن كل واحد يحمل جزء من تدفق البايتات. يحتوي كل جزء TCP على العنوان الموضح في الشكل التالي. وستوضّح معظم هذه الحقول ضمن هذا القسم.

TCPHeaderFormat.png

يحدد حقلا SrcPort وDstPort منفذي ports المصدر والوجهة، على التوالي، تمامًا كما في بروتوكول UDP. يتحد هذان الحقلان، بالإضافة إلى عناوين IP المصدر والوجهة، لتعريف كل اتصال TCP بشكل فريد. وهذا يعني أن مفتاح فك تعدد الإرسال demux الخاص ببروتوكول TCP مُعطى بواسطة صف رباعي العناصر 4-tuple (حيث tuple هو (صف وتُجمَع إلى صفوف) هي بنية بيانات تُمثِّل سلسلةً مرتبة من العناصر غير القابلة للتبديل، وبالتالي لا يمكن تعديل القيم الموجودة فيها) وهنا هذا الصف مؤلَّف من 4 عناصر.

(SrcPort, SrcIPAddr, DstPort, DstIPAddr)

لاحظ أن اتصالات TCP تأتي وتذهب، وبالتالي من الممكن إنشاء اتصال بين زوجٍ معين من المنافذ، واستخدامه لإرسال البيانات واستلامها، وإغلاقه، ثم تضمين نفس زوج المنافذ في اتصال ثانٍ في وقت لاحق. نشير أحيانًا إلى هذه الحالة على أنهما تجسيدان incarnations مختلفان لنفس الاتصال.

تُضمَّن جميع حقول Acknowledgement و SequenceNum و AdvertisedWindow في خوارزمية نافذة بروتوكول TCP المنزلقة. بما أن بروتوكول TCP هو بروتوكول موجهٌ بالبايت، فإن لكل بايت من البيانات رقم تسلسلي. يحتوي حقل SequenceNum على رقمٍ تسلسلي للبايت الأول من البيانات المنقولة في هذا الجزء، ويحمل حقلا Acknowledgement و AdvertisedWindow معلومات حول تدفق البيانات في الاتجاه الآخر. لتبسيط مناقشتنا، نتجاهل حقيقة أن البيانات يمكن أن تتدفق في كلا الاتجاهين، ونركز على البيانات التي لها رقم تسلسلي SequenceNum معين يتدفق في اتجاه واحد، وتتدفق قيم الحقلين Acknowledgement و AdvertisedWindow في الاتجاه المعاكس، كما هو موضح في الشكل التالي:

SimplifiedIllustrationOfTheTCPProcess.png

يُستخدم حقل الرايات Flags المكوّن من 6 بتات لنقل معلومات التحكم بين نظراء بروتوكول TCP. تتضمن الرايات المحتملة رايات SYN و FIN و RESET و PUSH و URG و ACK. تُستخدَم رايتا SYN و FIN عند إنشاء اتصال TCP وإنهائه على التوالي. تُضبَط الراية ACK في أي وقت يكون حقل Acknowledgement صالحًا، مما يعني أنه يجب على المستلم الانتباه إليه. تشير الراية URG إلى أن هذا الجزء يحتوي على بياناتٍ عاجلة، فعند تعيين هذه الراية، يشير حقل UrgPtr إلى مكان بدء البيانات غير العاجلة الموجودة في هذا الجزء. يجري احتواء البيانات العاجلة في الجزء الأمامي من جسم الجزء segment body، بعدد بايتاتٍ يصل إلى قيمة الراية UrgPtr في الجزء. تشير الراية PUSH إلى أن المرسل قد استدعى عملية PUSH، مما يشير إلى الجانب المستلم من TCP بوجوب إعلام عملية الاستلام بهذه الحقيقة. أخيرًا، تشير الراية RESET إلى أن جهاز الاستقبال قد أصبح مرتبكًا، لأنه تلقى جزءًا لم يتوقع تلقيه على سبيل المثال، وبالتالي يريد إلغاء الاتصال.

أخيرًا، يُستخدَم حقل المجموع الاختباري Checksum تمامًا بنفس الطريقة المستخدمة في بروتوكول UDP، أي يُحسَب عبر ترويسة TCP وبيانات TCP والترويسة الزائفة pseudoheader، والتي تتكون من عنوان المصدر وعنوان الوجهة وحقول الطول من ترويسة IP. المجموع الاختباري مطلوب لبروتوكول TCP في كلٍ من IPv4 و IPv6. بما أن ترويسة TCP متغيرة الطول (يمكن إرفاق الخيارات بعد الحقول الإلزامية)، فيُضمَّن حقل HdrLen الذي يعطي طول الترويسة بكلمات ذات حجم 32 بتًا. يُعرف هذا الحقل أيضًا باسم حقل الإزاحة Offset، لأنه يقيس الإزاحة من بداية الرزمة إلى بداية البيانات.

تأسيس الاتصال وإنهاؤه

يبدأ اتصال TCP عندما يقوم عميلٌ "مستدعٍ caller" بفتحٍ فعّال active open لخادم "مُستدعَى callee". وبفرض أن الخادم قد أجرى في وقتٍ سابق فتحًا سلبيًا غير فعّال passive open، فيشارك الجانبان في تبادل الرسائل لإنشاء الاتصال. (تذكر أن الطرف الذي يرغب في بدء اتصال يجري فتحًا فعالًا، بينما الطرف الذي يرغب في قبول الاتصال يجري فتحًا سلبيًا. ويسمح بروتوكول TCP بإعداد الاتصال ليكون متماثلًا symmetric، حيث يحاول كلا الجانبين فتح الاتصال في نفس الوقت، ولكن الحالة الشائعة هي أن يجري أحد الجانبين فتحًا فعّالًا والآخر يجري فتحًا سلبيًا. يبدأ الطرفان في إرسال البيانات بعد انتهاء مرحلة إنشاء الاتصال فقط. وبالمثل، فبمجرد انتهاء المشارك من إرسال البيانات، فإنه يغلق اتجاهًا واحدًا للاتصال، مما يتسبب في بدء بروتوكول TCP بجولة من رسائل إنهاء الاتصال. لاحظ أنه في حين أن إعداد الاتصال هو نشاط غير متماثل asymmetric (أحد الجانبين يجري فتحًا سلبيًا والجانب الآخر يجري فتحًا فعّالًا)، فإن تفكيك teardown الاتصال يكون متماثلًا symmetric (يجب على كل جانب إغلاق الاتصال بشكل مستقل). لذلك من الممكن أن يكون أحد الطرفين قد أنهى إغلاقًا، مما يعني أنه لم يعد بإمكانه إرسال البيانات، ولكن يجب إبقاء النصف الآخر من الاتصال ثنائي الاتجاه مفتوحًا ومواصلة إرسال البيانات بالنسبة للجانب الآخر.

طريقة المصافحة الثلاثية Three-Way Handshake

تسمى الخوارزمية التي يستخدمها بروتوكول TCP لإنشاء اتصال وإنهائه بمصافحة ثلاثية. نصف أولًا الخوارزمية الأساسية ثم نوضّح كيف يستخدمها بروتوكول TCP. تتضمن طريقة المصافحة الثلاثية تبادل ثلاث رسائل بين العميل والخادم، كما هو موضح في الجدول الزمني الوارد في الشكل التالي.

TimelineForThree-wayHandshakeAlgorithm.png

الفكرة هي وجود طرفين يريدان الاتفاق على مجموعة من المعاملات، والتي هي أرقام البداية التسلسلية التي يخطط الجانبان لاستخدامها في تدفقات البايتات الخاصة بهما في حالة فتح اتصال TCP. قد تكون هذه المعاملات أي حقائق يريد كل جانب أن يعرفها الجانب الآخر. أولًا، يرسل العميل (المشارك الفعّال) جزءًا إلى الخادم (المشارك السلبي) يوضح الرقم التسلسلي الأولي الذي يخطط لاستخدامه (Flags=SYN,SequenceNum= x). يستجيب الخادم بعد ذلك بجزء واحد يقوم بوظيفة مزدوجة وهي الإقرار برقم العميل التسلسلي Flags = ACK وAck = x + 1، وتحديد رقم البداية التسلسلي الخاص به Flags = SYN وSequenceNum = y. وبالتالي ضُبطت بتات SYN وACK في حقل Flags في هذه الرسالة الثانية. أخيرًا، يستجيب العميل بجزء ثالث يعترف برقم الخادم التسلسلي Flags = ACK وAck = y + 1. السبب الذي يجعل كل جانب يعترف برقمٍ تسلسلي أكبر بمقدار واحد عن الرقم المرسَل هو أن حقل الإشعار Acknowledgement يحدد بالفعل "الرقم التسلسلي التالي المتوقع"، وبالتالي يُعترف ضمنيًا بجميع الأرقام التسلسلية السابقة. جرى جدولة مؤقتٍ timer لكل جزء من الجزأين الأولين على الرغم من عدم ظهوره في هذا المخطط الزمني. وعند عدم تلقي الاستجابة المتوقعة، فسيُعاد إرسال الجزء.

قد تسأل نفسك لماذا يجب على العميل والخادم تبادل أرقام البداية التسلسلية مع بعضهما بعضًا في وقت إعداد الاتصال. سيكون من الأسهل إذا بدأ كل جانب ببساطة برقمٍ تسلسلي "معروف"، مثل 0. تتطلب مواصفات TCP أن يختار كل جانب من جوانب الاتصال رقم بداية تسلسليًا أوليًا عشوائيًا، والسبب في ذلك هو الحماية من وجود تجسيدين لنفس الاتصال يعيدان استخدام نفس الأرقام التسلسلية في وقتٍ قريب جدًا، أي في الوقت الذي لا يزال فيه فرصةٌ بأن يتداخل جزءٌ من تجسيد اتصالٍ سابق مع تجسيد اتصالٍ لاحق.

مخطط انتقال الحالة State-Transition Diagram

بروتوكول TCP معقدٌ بدرجةٍ كافية بحيث تتضمن مواصفاته مخطط انتقال الحالة. توجد نسخةٌ من هذا المخطط في الشكل الآتي. يوضح هذا المخطط فقط الحالات المشاركة في فتح اتصال (كل شيء فوق الحالة ESTABLISHED) وفي إغلاق الاتصال (كل شيء أدنى الحالة ESTABLISHED). يكون كل شيء يحدث أثناء فتح الاتصال، أي تشغيل خوارزمية النافذة المنزلقة، مخفيًا في الحالة ESTABLISHED.

TCPState-transitionDiagram.png

من السهل فهم مخطط انتقال حالة TCP، حيث يشير كل صندوقٍ إلى حالة يمكن لأحد طرفي اتصال TCP أن يجد نفسه فيها. تبدأ جميع الاتصالات في الحالة CLOSED، ومع تقدم الاتصال، ينتقل الاتصال من حالة إلى أخرى وفقًا للأقواس. يُسمَّى كل قوس بوسم tag لنموذج حدث / إجراء event/action. وبالتالي إذا كان الاتصال في حالة LISTEN مع وصول جزء SYN (أي جزء مع ضبط راية SYN على سبيل المثال)، ينتقل الاتصال إلى الحالة SYN_RCVD ويتخذ إجراء الرد بجزء ACK + SYN.

لاحظ أن نوعين من الأحداث يؤديان إلى انتقال الحالة:

  1. وصول جزء من النظير (الحدث على القوس من LISTEN إلى SYNRCVD على سبيل المثال)
  2. استدعاء عملية التطبيق المحلي عمليةً على بروتوكول TCP (حدث الفتح الفعال على القوس من الحالة CLOSED إلى SYNSENT على سبيل المثال).

بعبارة أخرى، يحدّد مخطط انتقال الحالة الخاص ببروتوكول TCP بفعالية دلالات semantics كلٍ من واجهة نظير لنظير peer-to-peer interface وَواجهة خدمته. تُوفَّر صيغة syntax لهاتين الواجهتين من خلال صيغة الجزء ومن خلال بعض واجهات برمجة التطبيقات على التوالي، مثل واجهة برمجة تطبيقات المقبس socket API.

دعنا الآن نتتبع التحولات النموذجية المأخوذة من خلال المخطط في الشكل السابق. ضع في اعتبارك أنه في كل طرفٍ من طرفي الاتصال، يجري بروتوكول TCP انتقالات مختلفة من حالة إلى أخرى. يستدعي الخادم أولًا عملية فتحٍ سلبية على بروتوكول TCP عند فتح اتصال، مما يؤدي إلى انتقال TCP إلى حالة LISTEN. يجري العميل فتحًا فعالًا في وقت لاحق، مما يؤدي إلى إرسال نهاية الاتصال جزء SYN إلى الخادم والانتقال إلى حالة SYNSENT. ينتقل الخادم إلى حالة SYNRCVD عندما يصل جزء SYN إليه ويستجيب بجزء SYN + ACK. يؤدي وصول هذا الجزء إلى انتقال العميل إلى الحالة ESTABLISHED وإرسال ACK مرة أخرى إلى الخادم. وينتقل الخادم أخيرًا إلى الحالة ESTABLISHED عند وصول ACK. وبالتالي كأننا قد قمنا للتو بتتبع طريقة المصافحة الثلاثية.

هناك ثلاثة أشياء يجب ملاحظتها حول النصف المخصص لإنشاء الاتصال في مخطط انتقال الحالة. أولًا، في حالة فقد ACK الخاص بالعميل إلى الخادم، وهو ما يتوافق مع المرحلة الثالثة من طريقة المصافحة الثلاثية، فإن الاتصال لا يزال يعمل بصورةٍ صحيحة. وذلك لأن جانب العميل موجود بالفعل في حالة ESTABLISHED، لذلك يمكن أن تبدأ عملية التطبيق المحلي في إرسال البيانات إلى الطرف الآخر. سيكون لكل جزء من أجزاء البيانات هذه مجموعة رايات ACK، والقيمة الصحيحة في حقل Acknowledgement، لذلك سينتقل الخادم إلى الحالة ESTABLISHED عند وصول جزء البيانات الأول. هذه في الواقع نقطةٌ مهمة حول بروتوكول TCP، حيث يبلّغ كل جزء عن الرقم التسلسلي الذي يتوقع المرسل رؤيته بعد ذلك، حتى إذا كان هذا يكرّر نفس الرقم التسلسلي الموجود في جزءٍ واحد أو أكثر من الأجزاء السابقة.

الشيء الثاني الواجب ملاحظته حول مخطط انتقال الحالة هو أن هناك انتقالًا مضحكًا خارج حالة LISTEN عندما تستدعي العملية المحلية عملية إرسال على بروتوكول TCP. بمعنى أنه من الممكن للمشارك السلبي تحديد طرفي الاتصال (أي نفسه والمشارك البعيد الذي يرغب في الاتصال به)، ومن ثم تغيير رأيه بشأن انتظار الجانب الآخر وإنشاء اتصال فعال بدلًا من ذلك. على حد علمنا، هذه ميزة من ميزات بروتوكول TCP التي لا تستفيد منها أية عملية تطبيق.

آخر شيء يجب ملاحظته بشأن المخطط هو الأقواس غير الظاهرة. تجدول معظم الحالات التي تتضمن إرسال جزءٍ إلى الجانب الآخر أيضًا مهلةً زمنية timeout تؤدي في النهاية إلى إعادة إرسال الجزء عند عدم حدوث الاستجابة المتوقعة. لا تُوصف عمليات إعادة الإرسال هذه في مخطط انتقال الحالة. في حال عدم وصول الاستجابة المتوقعة بعد عدة محاولات، يستسلم بروتوكول TCP ويعود إلى الحالة CLOSED.

الشيء المهم حول عملية إنهاء الاتصال الواجب أخذه بعين الاعتبار هو أن عملية التطبيق على جانبي الاتصال يجب أن تغلق نصف الاتصال الخاص بها بشكل مستقل. إذا أغلق جانبٌ واحد فقط الاتصال، فهذا يعني أنه ليس لديه المزيد من البيانات للإرسال، ولكنه لا يزال متاحًا لتلقي البيانات من الجانب الآخر. يؤدي هذا إلى تعقيد مخطط انتقال الحالة لأنه يجب أن يأخذ في الاعتبار احتمال أن يستدعي الجانبان معامل الإغلاق في نفس الوقت، بالإضافة إلى احتمال أن يستدعي أحد الجانبين الإغلاق ثم، في وقت لاحق، يستدعي الجانب الآخر الإغلاق. وبالتالي يوجد في أي جانبٍ ثلاثُ مجموعات من الانتقالات التي تحصل على اتصال من الحالة ESTABLISHED إلى الحالة CLOSED:

  • يجري إغلاق هذا الجانب أولًا:
 ESTABLISHED  FIN_WAIT_1  FIN_WAIT_2  TIME_WAIT  CLOSED
  • يغلق الجانب الآخر أولًا:
 ESTABLISHED  CLOSE_WAIT  LAST_ACK  CLOSED
  • يغلق كلا الجانبين في نفس الوقت:
 ESTABLISHED  FIN_WAIT_1  CLOSING  TIME_WAIT  CLOSED

يوجد في الواقع تسلسل رابع، وإن كان نادرًا، للانتقالات التي تؤدي إلى الحالة CLOSED، حيث يتبع القوس من الحالة FINWAIT1 إلى الحالة TIME_WAIT.

الشيء الرئيسي الواجب معرفته حول تفكيك الاتصال هو أن الاتصال في حالة TIME_WAIT لا يمكنه الانتقال إلى حالة CLOSED حتى ينتظر ضِعف الحد الأقصى من الوقت الذي قد يبقى فيه مخطط بيانات IP على الإنترنت (أي 120 ثانية). والسبب في ذلك هو أنه بينما يرسل الجانب المحلي من الاتصال ACK كاستجابةٍ للجزء FIN الخاص بالجانب الآخر، فإنه لا يعرف أن ACK قد سُلِّم بنجاح. لذلك قد يعيد الجانب الآخر إرسال الجزء FIN الخاص به، وقد يتأخر الجزء FIN الثاني في الشبكة. إذا سُمِح للاتصال بالانتقال مباشرةً إلى الحالة CLOSED، فقد يأتي زوجٌ آخر من عمليات التطبيق ويفتح نفس الاتصال (مثل استخدم نفس زوج أرقام المنافذ)، وقد يبدأ الجزء FIN المتأخر من تجسيد الاتصال السابق على الفور في إنهاء التجسيد اللاحق لذلك الاتصال.

إعادة النظر في خوارزمية النافذة المنزلقة Sliding Window Revisited

نحن الآن جاهزون لمناقشة بروتوكول TCP لخوارزمية النافذة المنزلقة، والتي تخدم عدة أغراض: (1) تضمن التسليم الموثوق للبيانات، (2) تضمن تسليم البيانات بالترتيب، (3) تفرض التحكم في التدفق بين المرسل والمُستقبِل. استخدام بروتوكول TCP لخوارزمية النافذة المنزلقة هو نفسه على مستوى الرابط بالنسبة لأول وظيفتين من هذه الوظائف الثلاث، بينما يختلف بروتوكول TCP عن خوارزمية مستوى الرابط في أنه يحتوي على وظيفة التحكم في التدفق أيضًا. يعلن جهاز الاستقبال عن حجم النافذة للمرسل بدلًا من وجود نافذةٍ منزلقة ذات حجم ثابت، ويحدث ذلك باستخدام حقل AdvertisedWindow في ترويسة TCP، ويمتلك المرسل بعد ذلك على ما لا يزيد عن قيمة بايتات الحقل AdvertisedWindow من البيانات غير المعترف بها في أي وقت. يحدد جهاز الاستقبال قيمة مناسبة للحقل AdvertisedWindow بناءً على مقدار ذاكرة الاتصال المخصصة لغرض تخزين البيانات مؤقتًا. الفكرة هي منع المرسل من الإفراط في تشغيل مخزن المستقبل المؤقت (سنناقش هذا بإسهاب أدناه).

التسليم الموثوق والمرتب

افترض الموقف الموضح في الشكل التالي لمعرفة كيفية تفاعل جانبي الإرسال والاستقبال من بروتوكول TCP مع بعضهما بعضًا لتنفيذ تسليمٍ موثوقٍ ومرتّب. يحتفظ TCP على جانب الإرسال بمخزن إرسال مؤقت، ويُستخدم هذا المخزن المؤقت لتخزين البيانات التي أُرسلت ولكن لم يجري الاقرار بها بعد، وكذلك البيانات التي كتبها التطبيق المرسل ولكن لم تُرسل. يحتفظ TCP على جانب الاستقبال بمخزن استقبالٍ مؤقت، حيث يحتفظ هذا المخزن المؤقت بالبيانات التي تصل مخالفةً للترتيب، وكذلك البيانات ذات الترتيب الصحيح (مثل عدم وجود بايتاتٍ مفقودة في وقت سابق من التدفق) ولكن عملية التطبيق لم تتح لها الفرصة لقراءتها بعد.

RelationshipBetweenTCPSendBufferAndReceiveBuffer.png

نتجاهل في البداية حقيقة أن كلًا من المخازن المؤقتة والأرقام التسلسلية ذات حجم محدود وبالتالي ستلتف في النهاية لجعل المناقشة التالية أسهل، ولا نفرق أيضًا بين المؤشر إلى المخزن المؤقت حيث يُخزَّن بايتٌ معين من البيانات وبين الرقم التسلسلي لذلك البايت.

بالنظر أولًا إلى جانب الإرسال، يحتفظ مخزن الإرسال المؤقت بثلاث مؤشرات، لكل منها معنى واضح: LastByteAcked وLastByteSent وLastByteWritten. أي:

LastByteAcked <= LastByteSent

بما أن المستقبل لا يمكنه أن يقِر أو يرسل إشعارًا بوصول بايتٍ لم يُرسَل بعد، ولأن بروتوكول TCP لا يمكنه إرسال بايتٍ لم تكتبه عملية التطبيق بعد، فلاحظ أيضًا أنه ليس ضروريًا حفظ أي من البايتات الموجودة على يسار LastByteAcked في المخزن المؤقت لأنه جرى التعرف عليها بالفعل، ولا يلزم تخزين أي من البايتات الموجودة على يمين LastByteWritten لأنها لم تُنشَأ بعد.

LastByteSent <= LastByteWritten

يجري الاحتفاظ بمجموعة مماثلة من المؤشرات (الأرقام التسلسلية) على جانب الاستقبال: LastByteRead وNextByteExpected وLastByteRcvd، ولكن التفاوتات أقل بسبب مشكلة التسليم المخالف للترتيب. تكون العلاقة الأولى

LastByteRead <NextByteExpected

صحيحة لأنه لا يمكن للتطبيق قراءة البايت حتى يُستلَم ويجب استقبال جميع البايتات السابقة أيضًا. يشير NextByteExpected إلى البايت مباشرةً بعد أحدث بايت لتلبية هذا المعيار. وثانيًا عندها إذا وصلت البيانات بالترتيب، فإن NextByteExpected يشير إلى البايت بعد LastByteRcvd، بينما إذا وصلت البيانات مخالفةً للترتيب، فإن NextByteExpected يشير إلى بداية الفجوة gap الأولى في البيانات، كما في الشكل السابق. لاحظ أنه لا تحتاج البايتات الموجودة على يسار LastByteRead أن تُخزَّن مؤقتًا لأن عملية التطبيق المحلي قد قرأتها بالفعل، ولا تحتاج البايتات الموجودة على يمين LastByteRcvd إلى تخزينها مؤقتًا لأنها لم تصل بعد.

NextByteExpected <= LastByteRcvd + 1

التحكم في التدفق Flow Control

معظم المناقشة أعلاه مشابهة لتلك الموجودة في خوارزمية النافذة المنزلقة القياسية. الاختلاف الحقيقي الوحيد هو أننا هذه المرة أوضحنا حقيقة أن عمليات تطبيق المرسل والمستقبل تملأ وتفرّغ المخزن المؤقت المحلي، على التوالي. (أخفت المناقشة السابقة حقيقة أن البيانات الواردة من عقدة المنبع تملأ مخزن الإرسال المؤقت وأن البيانات التي تُرسَل إلى عقدة المصب تفرّغ مخزن الاستقبال المؤقت).

لابد من الفهم الجيد لذلك قبل المتابعة، إذ تأتي الآن النقطة التي تختلف فيها الخوارزميتان بصورةٍ أكبر. نعيد في ما يلي تقديم حقيقة أن كلا المخزنين المؤقتين لهما حجمٌ محدد، يُشار إليهما MaxSendBuffer وMaxRcvBuffer، على الرغم من أننا لا نقلق بشأن تفاصيل كيفية تطبيقها. أي نحن مهتمون فقط بعدد البايتات التي تُخزَّن مؤقتًا وليس في المكان الذي تُخزَّن فيه هذه البايتات بالفعل.

تذكر أنه في بروتوكول النافذة المنزلقة، يحدّد حجمُ النافذة مقدارَ البيانات التي يمكن إرسالها دون انتظار إشعارٍ من المستقبل. وبالتالي يخنق جهاز الاستقبال المرسل عن طريق الإعلان عن نافذة لا تزيد عن كمية البيانات التي يمكنه تخزينها مؤقتًا. لاحظ أن بروتوكول TCP على جانب الاستقبال يجب أن يحافظ على ما يلي:

LastByteRcvd - LastByteRead <= MaxRcvBuffer

وذلك لتجنب تجاوز المخزن المؤقت الخاص به، لذلك يعلن عن نافذة بحجم

AdvertisedWindow = MaxRcvBuffer - ((NextByteExpected - 1) - LastByteRead)

والذي يمثل مقدار المساحة الخالية المتبقية في المخزن المؤقت الخاص به. يُقِر المستلم بالبيانات بمجرد وصولها طالما وصلت جميع البايتات السابقة أيضًا. وينتقل LastByteRcvd إلى اليمين (أي يزداد)، مما يعني أن النافذة المعلن عنها قد تتقلص، حيث يعتمد ما إذا تقلّصت أم لا على مدى سرعة عملية التطبيق المحلي في استهلاك البيانات. إذا كانت العملية المحلية تقرأ البيانات بنفس السرعة التي تصل بها، مما يؤدي إلى زيادة LastByteRead بنفس معدل LastByteRcvd، فإن النافذة المُعلن عنها تظل مفتوحة، أي AdvertisedWindow = MaxRcvBuffer، ولكن إذا تأخرت عملية الاستلام، ربما لأنها تؤدي عمليةً مكلفة للغاية على كل بايت من البيانات التي تقرأها، فإن النافذة المُعلن عنها تصبح أصغر مع كل جزء يصل حتى تصل في النهاية إلى القيمة 0.

يجب أن يلتزم بروتوكول TCP على جانب الإرسال بالنافذة المعلن عنها من جهاز الاستقبال. هذا يعني أنه في أي وقت، يجب أن يضمن أن:

LastByteSent - LastByteAcked <= AdvertisedWindow

أي يحسب المرسل نافذة فعالة تحد من مقدار البيانات الممكن إرسالها:

EffectiveWindow = AdvertisedWindow - (LastByteSent - LastByteAcked)

يجب أن يكون EffectiveWindow أكبر من 0 قبل أن يتمكن المصدر من إرسال المزيد من البيانات. لذلك من الممكن أن يصل جزءٌ ما للإقرار بـ x بايت، مما يسمح للمرسل بزيادة LastByteAcked بمقدار x، ولكن نظرًا لأن عملية الاستلام لم تكن تقرأ أي بيانات، فإن النافذة المُعلن عنها أصبحت الآن أصغر بمقدار x بايت من الوقت السابق، وبالتالي سيتمكّن المرسل من تحرير مساحة المخزن المؤقت، مع عدم إرسال أي بيانات أخرى.

يجب أن يتأكد جانب الإرسال أيضًا طوال هذا الوقت من أن عملية التطبيق المحلي لا تتجاوز مخزن الإرسال المؤقت، أي:

LastByteWritten - LastByteAcked <= MaxSendBuffer

إذا حاولت عملية الإرسال كتابة y بايت إلى TCP، ولكن:

(LastByteWritten - LastByteAcked) + y> MaxSendBuffer

عندها سيوقف بروتوكول TCP عملية الإرسال ولا يسمح لها بتوليد المزيد من البيانات.

أصبح من الممكن الآن فهم كيف تؤدي عملية الاستلام البطيئة إلى إيقاف عملية الإرسال السريعة في النهاية. أولًا، يمتلئ مخزن الاستقبال المؤقت، مما يعني تقلص النافذة المعلن عنها إلى 0. وتعني النافذة المعلن عنها بالقيمة 0 أن جانب الإرسال لا يمكنه نقل أي بيانات، بالرغم من الإقرار بالبيانات التي أرسلها سابقًا بنجاح. أخيرًا، يدل عدم القدرة على نقل أي بيانات على إمتلاء مخزن الإرسال المؤقت، مما يؤدي في النهاية إلى إيقاف بروتوكول TCP لعملية الإرسال. يكون بروتوكول TCP قادرًا على فتح نافذته احتياطيًا بمجرد أن تبدأ عملية الاستلام في قراءة البيانات مرةً أخرى، مما يسمح لبروتوكول TCP في طرف الإرسال بنقل البيانات من المخزن المؤقت الخاص به. ، تُزاد قيمة LastByteAcked عندما يجري الإقرار بهذه البيانات في النهاية، وتصبح مساحة المخزن المؤقت التي تحتوي على هذه البيانات المعترف بها حرة، ويُلغى إيقاف عملية الإرسال ويُسمَح لها بالمتابعة.

هناك تفصيلٌ متبقٍ يجب حله، وهو كيف يعرف الجانب المرسل أن النافذة المُعلن عنها لم تعد 0؟ يرسل بروتوكول TCP دائمًا جزء segment استجابةً لجزء البيانات المستلمة، وتحتوي هذه الاستجابة على أحدث القيم للحقلين Acknowledge و AdvertisedWindow، حتى في حال عدم تغيُّر هذه القيم منذ آخر مرة أُرسلت فيها، وهذه هي المشكلة. لا يُسمَح للمرسل بإرسال أي بيانات أخرى بمجرد أن يعلن جانب الاستلام عن نافذة بحجم 0، مما يعني أنه ليس لديه طريقة لاكتشاف أن النافذة المُعلن عنها لم تعد 0 في وقت ما في المستقبل. لا يرسل بروتوكول TCP على جانب الاستقبال أجزاءًا بلا بيانات nondata تلقائيًا، إنما يرسلها فقط استجابةً لجزء بياناتٍ واصلة.

يتعامل بروتوكول TCP مع هذا الوضع على النحو التالي: يستمر جانب الإرسال في إرسال جزء بحجم بايتٍ واحد من البيانات بين الحين والآخر عندما يعلن الجانب الآخر عن نافذة بحجم 0. يعلم جانب الإرسال أن هذه البيانات لن تُقبل على الأرجح، لكنه يحاول على أية حال، نظرًا لتنبيه trigger كل جزء من هذه الأجزاء المكونة من 1 بايت استجابةً تحتوي على النافذة المعلن عنها حاليًا. في النهاية، ينبّه triggers أحد هذه المسابر المكونة من 1 بايت استجابةً تبلّغ عن نافذةٍ غير صفرية معلن عنها.

لاحظ أن هذه الرسائل ذات 1 بايت تسمى مسابر النافذة الصفرية Zero Window Probes وعمليًا يجري إرسالها كل 5 إلى 60 ثانية. أما بالنسبة للبايت المفرد من البيانات الذي سيُرسل في المسبار: فهو البايت التالي للبيانات الفعلية الموجودة خارج النافذة مباشرةً (يجب أن تكون بيانات حقيقية إذا قبِلها المستقبل).

لاحظ أن السبب الذي يجعل الجانب المرسل يرسل جزء المسبار هذا دوريًا هو أن بروتوكول TCP مصمم لجعل جانب الاستقبال بسيطًا قدر الإمكان، فهو ببساطة يستجيب لأجزاء من المرسل، ولا يبدأ أي إجراءٍ بمفرده. هذا مثال على قاعدة تصميم بروتوكولٍ معترف بها (على الرغم من عدم تطبيقها عالميًا)، والتي نطلق عليها قاعدة المرسل الذكي / المستقبل الغبي smart sender/ dumb receiver بسبب عدم وجود اسمٍ أفضل.

الحماية من الالتفاف Protecting Against Wraparound

يأخذ هذا القسم والقسم التالي في الاعتبار حجم حقلي SequenceNum وAdvertisedWindow وتأثيرات أحجامهما على أداء وصحة بروتوكول TCP. يبلغ طول الحقل SequenceNum الخاص ببروتوكول TCP 32 بتًا، بينما يبلغ طول الحقل AdvertisedWindow 16 بتًا. مما يعني أن بروتوكول TCP قد استوفى بسهولة متطلبات خوارزمية النافذة المنزلقة بحيث تكون مساحة الرقم التسلسلي ضعف حجم النافذة: 232 >> 2 × 216، ومع ذلك فإن هذا المطلب ليس بالشيء المهم لهذين الحقلين، وبإمكانك افتراض كل حقلٍ على حدة.

تكمن أهمية مساحة الرقم التسلسلي 32 بت في أن الرقم التسلسلي المُستخدَم في اتصالٍ معين قد يلتف، أي يمكن إرسال بايتٍ برقمٍ تسلسلي S في وقت واحد، ثم قد يرسَل بايتٌ ثانٍ بنفس الرقم التسلسلي S في وقت لاحق. نفترض أن الرزم لا يمكنها البقاء على الإنترنت لفترة أطول من MSL الموصى بها، وبالتالي نحتاج حاليًا إلى التأكد من أن الرقم التسلسلي لا يلتف خلال فترة زمنية مدتها 120 ثانية. يعتمد حدوث ذلك أم لا على مدى سرعة نقل البيانات عبر الإنترنت، أي مدى السرعة التي يمكن بها استهلاك مساحة الرقم التسلسلي 32 بت. (تفترض هذه المناقشة أننا نحاول استهلاك مساحة الرقم التسلسلي بأسرع ما يمكن، ولكن بالطبع سنكون كذلك إذا كنا نقوم بعملنا المتمثل في الحفاظ على الأنبوب ممتلئًا) يوضح الجدول التالي المدة التي يستغرقها الرقم التسلسلي للالتفاف حول الشبكات ذات أحياز النطاق التراسلي bandwidths المختلفة.

حيز النطاق التراسلي Bandwidth الوقت اللازم للالتفاف Time until Wraparound
T1 مقداره 1.5 ميجابت في الثانية 6.4 ساعات
T3 مقداره 45 ميجابت في الثانية 13 دقيقة
Fast Ethernet مقداره 100 ميجابت في الثانية 6 دقائق
OC-3 مقداره 155 ميجابت في الثانية 4 دقائق
OC-48 مقداره 2.5 جيجابت في الثانية 14 ثانية
OC-192 مقداره 10 جيجابت في الثانية 3 ثوان
10GigE مقداره 10 جيجابت في الثانية 3 ثوان

كما ترى مساحة الرقم التسلسلي 32 بت كافيةٌ عند حيز نطاقٍ تراسلي متواضع، ولكن بالنظر إلى أن روابط OC-192 أصبحت شائعة الآن في الشبكات الرئيسية backbone للإنترنت، وأن معظم الخوادم تأتي الآن بواجهات 10Gig Ethernet (أو 10 جيجابت في الثانية)، فنكون قد تجاوزنا الآن هذه النقطة وسيكون 32 بتًا صغيرًا جدًا. عملت مؤسسة IETF على توسيع بروتوكول TCP الذي يوسّع بفعاليةٍ مساحة الرقم التسلسلي للحماية من التفاف الرقم التسلسلي.

الحفاظ على الأنبوب ممتلئا Keeping the Pipe Full

تكمن أهمية حقل AdvertisedWindow ذي 16 بتًا في أنه يجب أن يكون كبيرًا بما يكفي للسماح للمرسل بالحفاظ على الأنبوب ممتلئًا. من الواضح أن جهاز الاستقبال حر في عدم فتح النافذة بالحجم الذي يسمح به حقل AdvertisedWindow، فنحن مهتمون بالحالة التي يكون فيها لدى المستقبل مساحة تخزين كافية للتعامل مع أكبر قدرٍ ممكن من البيانات المسموح بها AdvertisedWindow.

لا يُحدَّد حجم حقل AdvertisedWindow في هذه الحالة بحيز النطاق الشبكة التراسلي فقط ولكن بجداء التأخير × حيز النطاق التراسلي بدلًا من ذلك، والذي يجب فتحه بصورةٍ كافية للسماح بإرسال الجداء الكامل للتأخير × حيز النطاق التراسلي للبيانات المُراد إرسالها. بافتراض أن RTT تبلغ 100 ميلي ثانية (رقم نموذجي للاتصال عبر البلاد في الولايات المتحدة)، يعطي الجدول التالي جداء التأخير × حيز النطاق التراسلي للعديد من تقنيات الشبكة:

حيز النطاق التراسلي Bandwidth جداء التأخير × حيز النطاق التراسلي Delay × Bandwidth Product
T1 مقداره 1.5 ميجابت في الثانية 18 كيلوبايت
T3 مقداره 45 ميجابت في الثانية 549 كيلوبايت
Fast Ethernet مقداره 100 ميجابت في الثانية 1.2 ميجا بايت
OC-3 مقداره 155 ميجابت في الثانية 1.8 ميجا بايت
OC-48 مقداره 2.5 جيجابت في الثانية 29.6 ميجا بايت
OC-192 مقداره 10 جيجابت في الثانية 118.4 ميجا بايت
10GigE مقداره 10 جيجابت في الثانية 118.4 ميجا بايت

كما ترى فإن حقل AdvertisedWindow الخاص ببروتوكول TCP في حالةٍ أسوأ من حقل SequenceNum الخاص به، فهو ليس كبيرًا بما يكفي للتعامل حتى مع اتصال T3 عبر الولايات المتحدة القارية، نظرًا لأن الحقل 16 بت يسمح لنا بالإعلان عن نافذة حجمها 64 كيلو بايت فقط. يوفر توسيع TCP نفسه المذكور أعلاه آليةً لزيادة حجم النافذة المعلن عنها بفعالية.

بهذا نكون قد تعرفنا على برتوكولات تدفق البايتات الموثوقة في الشبكات الحاسوبية آخذين بروتوكول TCP مثالًا في ذلك، وسنتابع بالمقال الموالي شرحها بالتخصيص في آليات الإرسال والبدائل.

ترجمة -وبتصرّف- للقسم Reliable Byte Stream من فصل ProtocolsEnd-to-End من كتاب Computer Networks: A Systems Approach.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...