البحث في الموقع
المحتوى عن 'tcp'.
-
يقدم هذا القسم المثال السائد والمُستخدَم اليوم للتحكم في الازدحام من طرفٍ إلى طرف، والذي يطبّقه بروتوكول TCP. تتمثل الإستراتيجية الأساسية لبروتوكول TCP في إرسال رزمٍ إلى الشبكة دون حجز، ومن ثم الاستجابة للأحداث الملاحَظة، كما يَفترض بروتوكول TCP وجود رتل FIFO فقط في موجّهات الشبكة، ولكنه يعمل أيضًا مع رتلٍ عادل. أدخل فان جاكوبسون Van Jacobson التحكم في الازدحام باستخدام بروتوكول TCP إلى الإنترنت في أواخر الثمانينات، وذلك بعد ثماني سنوات تقريبًا من تشغيل مكدس بروتوكولات TCP / IP، وقبل ذلك الوقت مباشرةً كان يعاني الإنترنت من انهيار الازدحام congestion collapse، حيث يرسل المضيفون رزمهم إلى الإنترنت بالسرعة التي تسمح بها النافذة المُعلن عنها، ويحدث الازدحام في بعض الموجّهات، مما يتسبب في إسقاط الرزم، وتنتهي مهلة المضيفين ويعيدون إرسال الرزم الخاصة بهم، مما يؤدي إلى مزيدٍ من الازدحام. تتمثل فكرة التحكم في الازدحام باستخدام بروتوكول TCP، في أن يحدد كل مصدرٍ مقدار السعة المتاحة في الشبكة، بحيث يعرف عدد الرزم التي يمكنه نقلها بأمان. وبمجرد أن يكون لدى مصدرٍ معين هذه الرزم العديدة قيد النقل، فإنه يستخدم وصول إشعارٍ ACK في إشارةٍ إلى أن إحدى رزمه قد غادرت الشبكة، وبالتالي فمن الآمن إدخال رزمةٍ جديدة في الشبكة دون زيادةٍ على مستوى الازدحام. يُقال أن بروتوكول TCP يضبط وقته ذاتيًا self-clocking، وذلك باستخدام الإشعارات لتسريع إرسال الرزم. وبطبيعة الحال فعملية تحديد السعة المتاحة ليست بالمهمة السهلة، ومما يزيد الطين بلةً أن حيز النطاق التراسلي المتاح يتغير بمرور الوقت نظرًا لأن الاتصالات الأخرى تأتي وتذهب، مما يعني أن أي مصدرٍ معينٍ يجب أن يكون قادرًا على ضبط عدد الرزم المنقولة، وسيشرح هذا القسم الخوارزميات التي يستخدمها بروتوكول TCP لمعالجة هذه المشاكل وغيرها. نلاحظ أنه وعلى الرغم من أننا نشرح آليات التحكم في الازدحام في بروتوكول TCP واحدةً تلو الأخرى، وهذا يُعطي انطباعًا بأننا نتحدث عن ثلاث آليات مستقلة، لكنها تشكّل معًا التحكم في الازدحام باستخدام بروتوكول TCP. سنبدأ هنا بنوعٍ من التحكم في الازدحام باستخدام بروتوكول TCP المُشار إليه غالبًا باسم TCP القياسي standard TCP، ولكننا سنرى أن هناك فعليًا عدد قليل من أنواع التحكم في الازدحام باستخدام بروتوكول TCP قيد الاستخدام اليوم، ومع ذلك يستمر الباحثون في استكشاف أساليبٍ جديدة لمعالجة هذه المشكلة التي سنناقشها أدناه. الزيادة المضافة / النقص المضاعف يحتفظ بروتوكول TCP بمتغير حالةٍ جديدٍ لكل اتصال، يُسمى نافذة الازدحام CongestionWindow، والذي يستخدمه المصدر للحدِّ من مقدار البيانات المسموح به أثناء النقل في وقتٍ معين. تُعَد نافذة الازدحام CongestionWindow نسخةً للتحكم في الازدحام للنافذة المُعلن عنها للتحكم في التدفق، ويُعدَّل بروتوكول TCP بحيث يكون الحد الأقصى المسموح به لعدد بايتات البيانات غير المعترف بها هو الحد الأدنى من نافذة الازدحام والنافذة المُعلن عنها، وبالتالي تُعدَّل النافذة الفعالة لبروتوكول TCP على النحو التالي باستخدام المتغيرات المحددة سابقًا: MaxWindow = MIN(CongestionWindow, AdvertisedWindow) EffectiveWindow = MaxWindow - (LastByteSent - LastByteAcked) وهذا يعني أن يحل الحد الأقصى MaxWindow محل النافذة المُعلن عنها AdvertisedWindow في حساب النافذة الفعالة EffectiveWindow، وبالتالي لا يُسمَح لمصدر بروتوكول TCP بالإرسال بصورةٍ أسرع مما يستوعبه المكوّن الأبطأ مثل الشبكة أو المضيف الوجهة. تكمن المشكلة في كيفية تعلّم بروتوكول TCP قيمةً مناسبةً لنافذة الازدحام CongestionWindow، حيث لا يوجد شيء يرسل هذه القيمة المناسبة إلى جانب الإرسال من بروتوكول TCP بخلاف النافذة المعلَن عنها AdvertisedWindow، والتي يرسلها الجانب المتلقي من الاتصال، لكن تكمن الإجابة هنا في أن يضبط مصدر TCP نافذة الازدحام CongestionWindow بناءً على مستوى الازدحام الذي يتخيّل وجوده في الشبكة، ويتضمن ذلك تقليل نافذة الازدحام عندما يرتفع مستوى الازدحام وزيادة نافذة الازدحام عندما ينخفض مستوى الازدحام، وتسمى هذه الآلية مجتمعةً بالزيادة المضافة / النقص المضاعف additive increase/multiplicative decrease أو اختصارًا AIMD، وسيُوضّح السبب وراء هذا الاسم أدناه. إذًا، كيف يحدد المصدر أن الشبكة مزدحمة وأنه يجب أن يقلّل من نافذة الازدحام؟ تستند الإجابة إلى ملاحظة أن السبب الرئيسي لعدم تسليم الرزم ونتائج المهلة الزمنية timeout؛ هو أن الرزمة قد أُسقِطت بسبب الازدحام، إذ من النادر أن تُسقَط رزمةٌ بسبب خطأ أثناء الإرسال، ولذلك يفسّر بروتوكول TCP تشغيل المهلات على أنه علامة على الازدحام، فيقلّل من معدل الإرسال، بحيث يضبط المصدر نافذة الازدحام CongestionWindow إلى نصف قيمتها السابقة في كل مرةٍ تعمل فيها المهلة. ويتوافق هذا التقسيم إلى النصف في نافذة الازدحام CongestionWindow لكل مهلةٍ مع جزء "النقص المضاعف multiplicative decrease" من آلية AIMD. على الرغم من تعريف نافذة الازدحام CongestionWindow في صورة بايتات، إلا أنه من الأسهل فهم الانخفاض المضاعف باستخدام الرزم الكاملة. افترض أن نافذة الازدحام مضبوطة حاليًا على 16 رزمة على سبيل المثال، فإذا اكتشِفت خسارة، فستُضبَط هذه النافذة على 8، حيث يجري اكتشاف خسارة عند انتهاء المهلة -ولكن بروتوكول TCP لديه آليةٌ أخرى لاكتشاف الرزم المُهمَلة-. تتسبب الخسائر الإضافية في تقليل نافذة الازدحام CongestionWindow إلى 4، ثم إلى 2، وأخيرًا إلى رزمةٍ واحدة. ولا يُسمح لنافذة الازدحام CongestionWindow بالانخفاض عن حجم رزمةٍ واحدة، أو باستخدام مصطلحات بروتوكول TCP، بالانخفاض عن الحد الأقصى لحجم جزء maximum segment size أو اختصارًا MSS. من الواضح أن استراتيجية التحكم في الازدحام التي تعمل على تقليل حجم النافذة متحفظة للغاية، حيث سنحتاج أيضًا إلى أن نكون قادرين على زيادة نافذة الازدحام للاستفادة من السعة المتوفرة حديثًا في الشبكة، وهذا هو جزء "الزيادة المضافة additive increase" من آلية AIMD، والذي يعمل على النحو التالي: يضيف المصدر ما يعادل رزمةً واحدةً إلى نافذة الازدحام CongestionWindow في كل مرةٍ يُرسل فيها المصدر رزمًا بمقدار هذه النافذة بنجاح، أي يحدث إقرار بإرسال كل رزمة مُرسَلةٍ خلال آخر وقت ذهابٍ وإياب round-trip time، أو اختصارًا RTT (هذه الزيادة الخطية موضحة في الشكل السابق). لاحظ أنه من الناحية العملية، لا ينتظر بروتوكول TCP إشعارات بمقدار رزمةٍ كاملة لإضافة ما يعادل رزمة واحدة إلى نافذة الازدحام، ولكن بدلًا من ذلك تزيد نافذة الازدحام CongestionWindow بمقدارٍ ضئيل لكل إشعارٍ ACK يصل، حيث تُزاد نافذة الازدحام على النحو التالي: Increment = MSS x (MSS/CongestionWindow) CongestionWindow += Increment أي بدلًا من زيادة نافذة الازدحام CongestionWindow بمقدار كل بايتات الحد الأقصى لحجم جزءMSS في كل فترة RTT، فإننا نزيده بجزءٍ بسيط من الحد الأقصى MSS في كل مرةٍ يُستلَم إشعار ACK فيها. وبافتراض أن كل إشعار ACK يقر باستلام بايتات الحد الأقصى MSS، فإن هذا الجزء المٌضاف هو MSS/CongestionWindow. يستمر هذا النمط من الزيادة والنقصان المستمرين في نافذة الازدحام طوال فترة الاتصال. وإذا رُسمت القيمة الحالية لنافذة الازدحام CongestionWindow على أنها دالةً بالنسبة للوقت، فسنحصل على نمط سن المنشار الموضح في الشكل السابق. إنّ المفهوم المهم الواجب فهمه حول آلية AIMD؛ هو أن المصدر مستعد لتقليل نافذة الازدحام بمعدلٍ أسرع بكثير من زيادة نافذة الازدحام الخاصة، وهذا على النقيض من استراتيجية الزيادة المضافة / النقص الإضافي، حيث تُزاد النافذة بمقدار رزمةٍ واحدةٍ عند وصول إشعار ACK، وتنخفض بمقدار 1 عند مرور المهلة، وقد ثبُت أن آلية AIMD شرطٌ ضروري لاستقرار آلية التحكم في الازدحام. التفسير البديهي لتخفيض بروتوكول TCP النافذة بقوة وزيادتها بصورةٍ متحفّظة هو تفاقم عواقب وجود نافذةٍ كبيرة جدًا، حيث سيُعاد إرسال الرزم التي أُسقِطت عندما تكون النافذة كبيرةً جدًا، مما يزيد الازدحام سوءًا، ومن المهم الخروج من هذه الحالة بسرعة. في الأخير، سيحتاج بروتوكول TCP إلى أدق آليةٍ ممكن منحها لتحديد المهلة، نظرًا لأن حدوث المهلة هو مؤشرٌ على الازدحام الذي يؤدي إلى انخفاضٍ مضاعف. لقد غطينا فعليًا آلية مهلة بروتوكول TCP سابقًا، لذلك لن نكررها هنا، والشيئان الرئيسيان اللذان يجب تذكرهما بشأن هذه الآلية، هما ضبط المهلات الزمنية على أنها دالةً لكلٍ من متوسط فترات RTT والانحراف المعياري في ذلك المتوسط، واختبار بروتوكول TCP وقتَ الذهاب والإياب فقط مرةً واحدة لكل فترة RTT بدلًا من مرةٍ واحدة لكل رزمة، باستخدام ساعةٍ ذات حبيبات خشنة (500 ميلي ثانية)، نظرًا لتكلفة قياس كل إرسال بساعة دقيقة. آلية البداية البطيئة آلية الزيادة المضافة التي وُصفت للتو هي الطريقة الصحيحة للاستخدام عندما يعمل المصدر بالقرب من السعة المتاحة للشبكة، ولكن الأمر سيستغرق وقتًا طويلًا لتكثيف الاتصال عندما يبدأ من نقطة الصفر، لذلك يوفر بروتوكول TCP آليةً ثانيةً تسمى البداية البطيئة Slow Start، والتي تُستخدَم لزيادة نافذة الازدحام بسرعة من نقطة البداية الباردة cold start، حيث تعمل البداية البطيئة على زيادة نافذة الازدحام أسيًا، وليس خطيًا. يبدأ المصدر بضبط نافذة الازدحام CongestionWindow إلى رزمةٍ واحدة، ويضيف بروتوكول TCP إلى نافذة الازدحام قيمة 1 عند وصول إشعار ACK لهذه الرزمة ثم يرسل رزمتين، وعند تلقي الإشعارين المقابلين يزيد بروتوكول TCP قيمة نافذة الازدحام CongestionWindow بمقدار 2 أي 1 لكل إشعار، ثم يرسل بعد ذلك 4 رزم. والنتيجة النهائية هي أن بروتوكول TCP يضاعف بفعالية عدد الرزم التي ينقلها في كل فترة RTT. يوضّح الشكل التالي النمو في عدد رزم النقل ضمن آلية البداية البطيئة: سبب تسمية أية آليةٍ أسية بأنها "بطيئة" هو أمرٌ محير في البداية، ولكن يمكن تفسيره إذا وُضِع في السياق التاريخي المناسب، إذ سنحتاج إلى موازنة البداية البطيئة بالسلوك الأصلي لبروتوكول TCP وليس بالآلية الخطية. ضع في الحسبان ما يحدث عند إنشاء اتصال وبدء المصدر في إرسال الرزم -أي عندما لا يحتوي المصدر حاليًا على رزمٍ قيد النقل-، فإذا أرسل المصدر العديد من الرزم التي تسمح بها النافذة المعلَن عنها وهو بالضبط ما فعله بروتوكول TCP قبل تطوير البداية البطيئة؛ فعندئذٍ حتى إذا كان هناك قدرٌ كبير نسبيًا من حيز النطاق التراسلي المتاح في الشبكة، فقد لا تتمكن الموجهات من استهلاك رشقة burst الرزم هذه، وكل ذلك يتوقف على مقدار مساحة التخزين المؤقت المتوفرة في الموجّهات، لذلك صُمِّمت البداية البطيئة لإبعاد الرزم بحيث لا تحدث هذه الرشقة. إذًا، تكون البداية البطيئة "أبطأ" بكثير من إرسال بيانات بقيمة النافذة المُعلن عنها بالكامل دفعةً واحدةً على الرغم من أن نموها الأسي أسرع من النمو الخطي. هناك في الواقع حالتان مختلفتان تعمل فيهما آلية البداية البطيئة، أولهما في بداية الاتصال، حيث لا يعرف المصدر في ذلك الوقت عدد الرزم التي سيكون قادرًا على نقلها في وقتٍ معين، وهنا ضع في الحسبان أن بروتوكول TCP اليوم يعمل على كل شيء بدءًا من الروابط بسرعة 1 ميجابت في الثانية وحتى الروابط بسرعة 40 جيجابت في الثانية، لذلك لا توجد طريقة للمصدر لمعرفة سعة الشبكة. تستمر البداية البطيئة في هذه الحالة في مضاعفة نافذة الازدحام CongestionWindow كل فترة RTT حتى حدوث خسارة، وفي ذلك الوقت يؤدي حدوث المهلة إلى انخفاضٍ مضاعف حتى تقسيم نافذة الازدحام على 2. وتُستخدَم في الحالة الثانية البداية البطيئة بصورةٍ أدق قليلًا، حيث يحدث ذلك عند انقطاع الاتصال أثناء انتظار انتهاء المهلة. لنتذكر كيفية عمل خوارزمية النافذة المنزلقة sliding window في بروتوكول TCP وهي على النحو التالي: عند فقدان رزمة ما، فسيكون المصدر قد وصل في النهاية إلى نقطةٍ أرسل عندها أكبر قدرٍ من البيانات التي تسمح به النافذة المعلَن عنها، وبالتالي يتوقف أثناء انتظار الإشعار ACK الذي لن يصل. ستنتهي المهلة في النهاية، ولكن لن تكون هناك رزمٌ قيد النقل بحلول هذا الوقت، مما يعني أن المصدر لن يتلقى أي إشعاراتٍ "لتسجيل وقت" إرسال الرزم الجديدة، وسيحصل بدلًا من ذلك على إشعارٍ ACK واحدٍ تراكمي يُعيد فتح النافذة المعلن عنها بالكامل. سيستخدم المصدر بعد ذلك البداية البطيئة لإعادة تشغيل تدفق البيانات بدلًا من تفريغ بيانات النافذة بالكامل على الشبكة دفعةً واحدةً، كما هو موضح أعلاه. يستخدم المصدرُ البدايةَ البطيئة مرةً أخرى، إلا أنه يعرف الآن معلوماتٍ أكثر مما كان يعرف في بداية الاتصال، حيث يحتوي المصدر على القيمة الحالية والمفيدة من نافذة الازدحام CongestionWindow، وهذه هي القيمة التي كانت موجودةً قبل آخر خسارةٍ للرزمة، مقسومةً على 2 نتيجةً للخسارة، حيث يمكننا تشبيه ذلك بنافذة الازدحام المستهدفة target congestion window. تُستخدَم البداية البطيئة لزيادة معدل الإرسال بسرعةٍ إلى هذه القيمة، ثم تُستخدَم الزيادة الإضافية بعد هذه النقطة، وهنا لاحظ أنه لدينا مشكلةً صغيرةً يجب الاهتمام بها في ضبط التسجيل، حيث نريد أن نتذكر نافذة الازدحام المستهدفة الناتجة عن الانخفاض المضاعف، وكذلك نافذة الازدحام الفعلية التي تستخدمها البداية البطيئة. لمعالجة هذه المشكلة، يقدم بروتوكول TCP متغيرًا مؤقتًا لتخزين النافذة المستهدفة، يسمى عتبة الازدحام CongestionThreshold، والتي تُضبَط مساويةً لقيمة نافذة الازدحام CongestionWindow الناتجة عن الانخفاض المضاعَف، ويُعاد بعد ذلك ضبط نافذة الازدحام CongestionWindow إلى رزمةٍ واحدة، ثم تُزاد برزمةٍ واحدة لكل إشعار ACK مُستقبَل حتى يصل إلى قيمة عتبة الازدحام CongestionThreshold، وعندها تُزاد بقيمة رزمةٍ واحدة لكل فترة RTT. أي سيزيد بروتوكول TCP من نافذة الازدحام كما هو محدَّد في الشيفرة التالية: { u_int cw = state->CongestionWindow; u_int incr = state->maxseg; if (cw > state->CongestionThreshold) incr = incr * incr / cw; state->CongestionWindow = MIN(cw + incr, TCP_MAXWIN); } حيث يمثّل المتغير state حالة اتصال TCP معيّن، ويحدّد الحد الأعلى لمدى حجم نافذة الازدحام المسموح به للنمو. يتتبّع الشكل الآتي كيفية زيادة نافذة الازدحام CongestionWindow الخاصة ببروتوكول TCP ونقصانها بمرور الوقت ويقدّم توضيحًا للتفاعل بين البداية البطيئة والزيادة المضافة / النقص المضاعف. لقد أُخِذ هذا التتبع من اتصال TCP فِعلي، حيث يُظهِر الشكل قيمة نافذة الازدحام الحالية (الخط الملون) مع مرور الوقت، وتمثِّل الرموزُ النقطية المُصمتة أعلى الرسم البياني المهلات الزمنية؛ وتمثل العلامات المقطَّعة أعلى الرسم البياني الوقت الذي ترسَل فيه كل رزمة؛ بينما تمثّل الخطوط العمودية الوقت الذي أُرسَلت فيه الرزمة المعاد إرسالها في النهاية لأول مرة. هناك العديد من الأشياء الواجب ملاحظتها حول هذا التتبع، أولها هي الزيادة السريعة في نافذة الازدحام في بداية الاتصال، وهي تتوافق مع مرحلة البداية البطيئة الأولية، حيث تستمر مرحلة البداية البطيئة حتى يُفقد العديد من الرزم في حوالي 0.4 ثانية من الاتصال، وفي ذلك الوقت تُسوَّى نافذة الازدحام CongestionWindow عند حوالي 34 كيلوبايت، وسنناقش سبب فقد الكثير من الرزم أثناء البداية البطيئة أدناه. يعود السبب وراء تسوية نافذة الازدحام في عدم وصول إشعارات، وذلك نظرًا لحقيقة فقدان العديد من الرزم وعدم إرسال رزمٍ جديدة خلال هذا الوقت، وهذا مُشارٌ إليه من خلال عدم وجود علاماتٍ مُقطَّعة في الجزء العلوي من الرسم البياني. تحدث المهلة في النهاية في حوالي ثانيتين، وتُقسَم في ذلك الوقت نافذة الازدحام على 2 أي تُخفَّض من 34 كيلوبايت تقريبًا إلى حوالي 17 كيلوبايت، وتُضبَط عتبة الازدحام CongestionThreshold على هذه القيمة، وتؤدي البداية البطيئة بعد ذلك إلى إعادة ضبط نافذة الازدحام CongestionWindow إلى رزمةٍ واحدة وبدء الزيادة من هناك. لا توجد تفاصيلٌ كافية في التتبّع لمعرفة ما يحدث بالضبط عند فقدان رزمتين بعد ثانيتين فقط، لذلك ننتقل إلى الزيادة الخطية في نافذة الازدحام التي تحدث بين ثانيتين وأربع ثوانٍ، وهذا يتوافق مع الزيادة المضافة. تُسوَّى نافذة الازدحام CongestionWindow في حوالي 4 ثوانٍ مرةً أخرى بسبب فقدان الرزمة. ويحدث الآن في حوالي 5.5 ثانية ما يلي: تنتهي المهلة الزمنية، مما يؤدي إلى تقسيم نافذة الازدحام على 2، وتخفيضها من حوالي 22 كيلوبايت إلى 11 كيلوبايت، وتُضبَط عتبة الازدحام CongestionThreshold على هذا المقدار. يُعاد ضبط نافذة الازدحام CongestionWindow إلى رزمةٍ واحدة، حيث يدخل المرسل بدايةً بطيئة. تؤدي البداية البطيئة إلى نمو نافذة الازدحام CongestionWindow أسيًا حتى يصل إلى حد الازدحام. تنمو نافذة الازدحام CongestionWindow بعد ذلك خطيًا. يتكرر نفس النمط في حوالي 8 ثوانٍ عند حدوث مهلةٍ أخرى. نعود الآن إلى السؤال عن سبب فقد الكثير من الرزم خلال فترة البداية البطيئة الأولية، حيث يحاول بروتوكول TCP معرفة مقدار حيز النطاق التراسلي المتاح على الشبكة، وهذه مهمةٌ صعبة، فإذا لم يكن المصدر نشطًا في هذه المرحلة، أي إذا زاد فقط من نافذة الازدحام خطيًا على سبيل المثال، فسيستغرق وقتًا طويلًا حتى يكتشف مقدار حيز النطاق التراسلي المتاح، ويمكن أن يكون لهذا تأثير كبير على الإنتاجية المحققة لهذا الاتصال؛ بينما إذا كان المصدر نشطًا في هذه المرحلة، حيث يكون بروتوكول TCP ضمن مرحلة النمو الأسي؛ فإن المصدر يخاطر بأن تسقط الشبكةُ رزمًا بمقدار نصف النافذة. ضع في الحسبان الموقف الذي يكون فيه المصدر قادرًا على إرسال 16 رزمةً بنجاح عبر الشبكة لمعرفة ما يمكن أن يحدث أثناء النمو الأسي، وهذا ما يتسبب في مضاعفة نافذة الازدحام إلى 32. وبفرض أن الشبكة لديها ما يكفي من القدرة على دعم 16 رزمة من هذا المصدر، فستكون النتيجة المحتملة عندئذٍ هي إسقاط الشبكة 16 رزمة من 32 رزمة مرسَلة بموجب نافذة الازدحام الجديدة؛ وهذه هي النتيجة الأسوأ في الواقع، حيث ستُخزَّن بعض الرزم مؤقتًا في بعض الموجّهات. وستزداد حدّة هذه المشكلة مع زيادة ناتج جداء التأخير × حيز النطاق التراسلي للشبكات، حيث يعني جداء التأخير × حيز النطاق التراسلي ذو القيمة 500 كيلوبايت على سبيل المثال أن كل اتصالٍ لديه القدرة على فقدان ما يصل إلى 500 كيلوبايت من البيانات في بداية كل اتصال، وهذا على فرض أن كلًا من المصدر والوجهة ينفذان توسّع "النوافذ الكبيرة". لقد أوجِدت بدائل للبداية البطيئة، حيث يحاول المصدر تقدير حيز النطاق التراسلي المتاح بوسائل أكثر تطورًا، ويُطلق على أحد الأمثلة اسم البداية السريعة quick-start، حيث تتمحور الفكرة الأساسية حول امكانية مرسل بروتوكول TCP لطلب معدل إرسال أولي أكبر مما تسمح به البداية البطيئة، وذلك عن طريق وضع المعدل المطلوب في رزمة التزامن SYN الخاصة به بمثابة خيارٍ من خيارات بروتوكول IP. يمكن للموجهات على طول المسار فحص الخيار وتقييم مستوى الازدحام الحالي على الرابط الصادر لهذا التدفق وتحديد ما إذا كان هذا المعدل مقبولًا أم لا، أو إذا كان المعدل الأخفض مقبولًا، أم يجب استخدام البداية البطيئة القياسية. ستحتوي رزمة SYN بحلول الوقت الذي تصل فيه إلى جهاز الاستقبال إما على معدلٍ مقبول لجميع الموجهات على المسار، أو على إشارةٍ إلى أن موجّهًا أو أكثر من الموجّهات الموجودة على المسار لا يمكنه دعم طلب البداية السريعة. يستخدم مرسل TCP في الحالة الأولى هذا المعدل لبدء الإرسال؛ ويعود في الحالة الثانية إلى البداية البطيئة القياسية، وإذا سُمح لبروتوكول TCP بالبدء في الإرسال بمعدلٍ أعلى؛ فيمكن أن تصل الجلسة بسرعةٍ أكبر إلى نقطة ملء الأنبوب، بدلًا من أخذ العديد من أوقات الذهاب والإياب round-trip times لفعل بذلك. من الواضح أن أحد التحديات التي تواجه هذا النوع من التحسينات في بروتوكول TCP هو أنه يتطلب قدرًا أكبر من تعاون الموجّهات، أكثر مما يتطلبه بروتوكول TCP القياسي، فإذا كان موجهٌ واحد في المسار لا يدعم البداية السريعة، فسيعود النظام إلى البداية البطيئة القياسية، وبالتالي قد يمر وقتٌ طويل قبل أن تتمكن هذه الأنواع من التحسينات من الوصول إلى الإنترنت، ومن المُرجح أن تُستخدَم في بيئات الشبكات المُتحكَّم بها controlled network، مثل شبكات البحث research networks في الوقت الحالي. إعادة الإرسال السريع والاستعادة السريعة لقد كانت الآليات الموصوفة حتى الآن جزءًا من الاقتراح الأصلي لإضافة التحكم في الازدحام إلى بروتوكول TCP، ولكن سرعان ما اُكتشِف أن التطبيق الصلب coarse-grained لمُهلات بروتوكول TCP أدّى إلى فتراتٍ طويلة، توقف خلالها الاتصال أثناء انتظار انتهاء صلاحية المؤقت، ولذلك أُضيفت آليةٌ جديدة تسمى إعادة الإرسال السريع fast retransmit إلى بروتوكول TCP، وتُعَد إعادة الإرسال السريع عمليةً تجريبيةً تؤدي أحيانًا إلى إعادة إرسال الرزمة التي أُسقِطت في وقتٍ أقرب من آلية المهلة العادية، لكنها لا تحل محل المهلات العادية؛ فهي تحسّنها فقط. تُعَد فكرة إعادة الإرسال السريع واضحةً ومباشرة، حيث يستجيب المستقبل بإشعارٍ في كل مرةٍ تصل رزمة بيانات إلى جانب الاستقبال، حتى لو أُقِر فعليًا بهذا الرقم التسلسلي، وبالتالي إذا وصلت الرزمة مخالفةً للترتيب (أي عندما يتعذر على بروتوكول TCP التعرُّف على البيانات المُحتواة بالرزمة لأن البيانات السابقة لم تصل بعد)، فسيعيد بروتوكول TCP إرسال نفس الإشعار الذي أرسله في المرة الأخيرة، ويُطلق على هذا الإرسال الثاني لنفس الإشعار اسم إشعارٍ مكرَّر، فإذا رأى الجانب المُرسل إشعارًا مكررًا، فإنه سيعلم أن الجانب الآخر يجب أن يكون قد تلقى رزمةً مخالفةً للترتيب، مما يشير إلى احتمال فقد رزمة سابقة. وبما أنه من الممكن أيضًا أن تكون الرزمة السابقة قد تأخرت فقط بدلًا من فقدها، فإن المرسل ينتظر حتى يرى عددًا من الإشعارات المكررة ثم يعيد إرسال الرزمة المفقودة، حيث ينتظر بروتوكول TCP عمليًا حتى يرى ثلاثة إشعاراتٍ مكررة قبل إعادة إرسال الرزمة. يوضح الشكل السابق كيف يؤدي وجود إشعاراتٍ مكرّرة إلى إعادة إرسالٍ سريع، حيث تستقبل الوِجهة الرزم 1 و2 في هذا المثال، لكن تضيع الرزمة 3 في الشبكة، وبالتالي ستُرسل الوجهة إشعارًا مكررًا للرزمة 2 عند وصول الرزمة 4، ومرةً أخرى عند وصول الرزمة 5، وهكذا. سنبسّط هذا المثال من خلال التفكير فيما يتعلق بالرزم 1 و2 و3 وما إلى ذلك، بدلًا من القلق بشأن الأرقام التسلسلية لكل بايت، فإذا رأى المرسل الإشعار المكرّر الثالث للرزمة 2 والتي أُرسِلت بسبب حصول المستقبل على الرزمة 6، فسيعيد المرسل إرسال الرزمة 3، ويمكن ملاحظة أنه عند وصول النسخة المُعاد إرسالها من الرزمة 3 إلى الوجهة، فسيرسل المستقبل بعد ذلك إشعارًا تراكميًا بكل الرزم حتى الرزمة 6 مع إشعارٍ بالرزمة 6 أيضًا إلى المصدر. يوضح الشكل السابق سلوك إصدارٍ من بروتوكول TCP مع آلية إعادة الإرسال السريع. من الممتع موازنة هذا السلوك مع السلوك المُناقش سابقًا والذي لم يُطبّق إعادة الإرسال السريع، حيث يجرى هنا التخلص من الفترات الطويلة التي تظل خلالها نافذة الازدحام ثابتة دون إرسال أية رزم. يمثّل الخط الملون نافذة الازدحام CongestionWindow، أما النقطة المصمتة فتمثّل المهلةَ الزمنية؛ في حين تمثّل العلاماتُ المُقطَّعة الوقتَ الذي تُرسَل فيه كل رزمة والخطوط العمودية الوقتَ الذي أُرسَلت فيه الرزمة المُعاد إرسالها في النهاية لأول مرة. هذه التقنية قادرةٌ على القضاء على حوالي نصف المُهلات ذات التطبيق الصلب على اتصال TCP نموذجي، مما يؤدي إلى تحسُّنٍ بنسبة 20% تقريبًا في الإنتاجية مقابل ما كان يمكن تحقيقه بخلاف ذلك. لاحظ أن استراتيجية إعادة الإرسال السريع لا تلغي جميع المُهلات ذات التطبيق الصلب، لأنه لن تكون هناك رزمٌ كافيةٌ قيد النقل لإيصال ما يكفي من الإشعارات المكرّرة بالنسبة لحجم النافذة الصغيرة، وذلك بالنظر إلى ما يكفي من الرزم المفقودة -كما يحدث أثناء مرحلة البداية البطيئة الأولية على سبيل المثال-، حيث تُوقِف خوارزمية النافذة المنزلقة في النهاية المرسل حتى تحدث المهلة الزمنية. ويمكن عمليًا اكتشاف آلية إعادة الإرسال السريع لبروتوكول TCP ما يصل إلى ثلاث رزمٍ أُسقِطت في كل نافذة. هناك تحسينٌ أخيرٌ يمكن إجراؤه، وذلك من خلال استخدام الإشعارات التي لا تزال في الأنبوب لتسجيل وقت إرسال الرزم، وهو عندما تشير آلية إعادة الإرسال السريع إلى الازدحام بدلًا من إسقاط نافذة الازدحام طوال الطريق إلى رزمةٍ واحدةٍ وتشغيل البداية البطيئة. تزيل هذه الآلية المُسماة الاستعادة السريعة fast recovery وبفعالية مرحلة البداية البطيئة التي تحدث بين اكتشاف إعادة الإرسال السريع للرزمة المفقودة وبداية الزيادة المضافة، حيث تتجنب الاستعادة السريعة فترة البداية البطيئة بين 3.8 و4 ثوانٍ في الشكل السابق، وتخفّض بدلًا من ذلك نافذة الازدحام إلى النصف أي من 22 كيلوبايت إلى 11 كيلوبايت وتُستأنَف الزيادة المضافة، وبالتالي تُستخدَم البداية البطيئة فقط في بداية الاتصال، وكلما حدثت مهلةٌ ذات تطبيقٍ صلب، وتتبّع نافذةُ الازدحام نمط الزيادة المضافة / النقص المضاعف في جميع الأوقات الأخرى. خوارزمية TCP CUBIC تُعَد خوارزمية CUBIC أحد أشكال خوارزمية TCP القياسية التي وُصفت للتو، وهي خوارزمية التحكم في الازدحام الافتراضية الموزَّعة في نظام لينكس، ويكون الهدف الأساسي لخوارزمية CUBIC هو دعم الشبكات ذات جداء التأخير × حيز النطاق التراسلي الكبير، والتي تُسمى أحيانًا long-fat networks. تعاني هذه الشبكات من خوارزمية TCP الأصلية التي تتطلب الكثير من الأوقات ذهابًا وإيابًا للوصول إلى السعة المتاحة للمسار من طرفٍ إلى طرف، في حين تفعل خوارزمية CUBIC ذلك لكونها مبادِرةً أكثر في زيادة حجم النافذة، ولكن البراعة هي أن تكون أقوى وأكثر مبادرةً دون أن تؤثر سلبًا على التدفقات الأخرى. تتمثل إحدى الجوانب المهمة في نهج خوارزمية CUBIC في تعديل نافذة الازدحام على فتراتٍ منتظمة، بناءً على مقدار الوقت المنقضي منذ حدوث الازدحام الأخير، مثل وصول إشعار ACK مكرّر، وليس فقط عند وصول إشعار ACK أي الإشعار الأخير تابعًا لزمن RTT. يسمح ذلك لخوارزمية CUBIC بالتصرف بصورةٍ عادلةٍ عند التنافس مع تدفقات RTT القصيرة، والتي لديها إشعارات واصلةٌ بصورةٍ متكررة. الجانب الثاني المهم لخوارزمية CUBIC هو استخدامها دالةً تكعيبيةً cubic function لضبط نافذة الازدحام. يسهُل فهم الفكرة الأساسية من خلال النظر إلى الشكل العام للدالة التكعيبية، والتي تتكون من ثلاث مراحل هي إبطاء النمو slowing growth، وتسوية الارتفاع flatten plateau، وزيادة النمو increasing growth. يُظهر الشكل السابق مثالًا عامًا مُزودًا بجزءٍ إضافي من المعلومات ألا وهو الحد الأقصى المُستهدف لحجم نافذة الازدحام والذي يُحقَّق قبل حدوث الازدحام الأخير، ويُشار إليه باسم Wmax. تكمن الفكرة في أن تبدأ بسرعة مع إبطاء معدل النمو كلما اقتربت من الحد الأقصىWmax، وكن حذرًا، وليكن النمو قريبًا من الصفر عند الاقتراب من الحد الأقصى Wmax، ثم زِد معدل النمو كلما ابتعدت عن الحد الأقصى Wmax؛ أما المرحلة الأخيرة فهي البحث عن حدٍ أقصىWmax جديد قابلٍ للتحقيق. تحسب خوارزمية CUBIC نافذة الازدحام على أنها دالةً بالنسبة للزمن t منذ حدوث الازدحام الأخير كما يلي: حيث: حيث أن C هو ثابت توسُّع scaling constant، وβ هو عامل النقص المضاعف. تضبط خوارزمية CUBIC العامل β بالقيمة 0.7 بدلًا من 0.5 الذي يستخدمه بروتوكول TCP القياسي. وبالنظر إلى الشكل السابق، توصف خوارزمية CUBIC غالبًا على أنها انتقالٌ من دالةٍ مُقعرة concave إلى محدّبة convex، في حين أن دالة بروتوكول TCP القياسية الإضافية محدبةٌ فقط. ترجمة -وبتصرّف- للقسم TCP Congestion Control من فصل Congestion Control من كتاب Computer Networks: A Systems Approach اقرأ أيضًا المقال السابق: أنظمة الأرتال المستخدمة في التحكم بازدحام الشبكات الحاسوبية مشكلة تخصيص الموارد للتحكم في الازدحام في الشبكات الحاسوبية
-
- الشبكات الحاسوبية
- الازدحام
-
(و 1 أكثر)
موسوم في:
-
بروتوكول النقل الأعقد هو البروتوكول الذي يوفر خدمة تدفق بايتات موثوقة 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 تتصرف بصفةٍ مثالية، حيث عُرفت عقد الشبكة بإدخال أخطاءٍ في الرسائل أثناء نقلها من مخزن الإدخال المؤقت إلى مخزن الإخراج المؤقت. ومن المعروف أيضًا أن عقد الشبكة تعيد ترتيب الرسائل عن طريق الخطأ. لا يزال من الضروري توفير فحوصات طرفٍ إلى طرف لضمان خدمة موثوقة / مرتبة نتيجة لأسباب الضعف البسيطة هذه، على الرغم من تطبيق المستويات الأدنى من النظام أيضًا لهذه الوظيفة. صيغة الجزء segment format بروتوكول TCP هو بروتوكول موجَّهٌ بالبايت، مما يعني أن المرسل يكتب البايت في اتصال TCP ويقرأ المتلقي البايت من خلال اتصال TCP. على الرغم من أن "تدفق البايتات" يصف الخدمة التي يقدمها بروتوكول TCP لعمليات التطبيق، فإن بروتوكول TCP نفسه لا يرسل البايتات الفردية عبر الإنترنت. وبدلًا من ذلك، يخزن بروتوكول TCP على المضيف المصدر ما يكفي من البايتات من عملية الإرسال لملء رزمةٍ بحجم معقول ثم يرسل هذه الرزمة إلى نظيره على المضيف الوجهة. يفرغ بروتوكول TCP على المضيف الوجهة بعد ذلك محتويات الرزمة في مخزن الاستلام المؤقت، وتقرأ عملية الاستلام من هذا المخزن المؤقت في أوقات فراغها. يوضح الشكل التالي هذا الموقف، حيث يُظهر تدفق البيانات في اتجاه واحد فقط بهدف التبسيط. تذكر أن اتصال TCP واحدًا يدعم عمومًا تدفقات البايتات في كلا الاتجاهين. تسمَّى الرزم المتبادلة بين نظراء بروتوكول TCP في الشكل السابق باسم الأجزاء segments، لأن كل واحد يحمل جزء من تدفق البايتات. يحتوي كل جزء TCP على العنوان الموضح في الشكل التالي. وستوضّح معظم هذه الحقول ضمن هذا القسم. يحدد حقلا 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 في الاتجاه المعاكس، كما هو موضح في الشكل التالي: يُستخدم حقل الرايات 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. تتضمن طريقة المصافحة الثلاثية تبادل ثلاث رسائل بين العميل والخادم، كما هو موضح في الجدول الزمني الوارد في الشكل التالي. الفكرة هي وجود طرفين يريدان الاتفاق على مجموعة من المعاملات، والتي هي أرقام البداية التسلسلية التي يخطط الجانبان لاستخدامها في تدفقات البايتات الخاصة بهما في حالة فتح اتصال 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. من السهل فهم مخطط انتقال حالة TCP، حيث يشير كل صندوقٍ إلى حالة يمكن لأحد طرفي اتصال TCP أن يجد نفسه فيها. تبدأ جميع الاتصالات في الحالة CLOSED، ومع تقدم الاتصال، ينتقل الاتصال من حالة إلى أخرى وفقًا للأقواس. يُسمَّى كل قوس بوسم tag لنموذج حدث / إجراء event/action. وبالتالي إذا كان الاتصال في حالة LISTEN مع وصول جزء SYN (أي جزء مع ضبط راية SYN على سبيل المثال)، ينتقل الاتصال إلى الحالة SYN_RCVD ويتخذ إجراء الرد بجزء ACK + SYN. لاحظ أن نوعين من الأحداث يؤديان إلى انتقال الحالة: وصول جزء من النظير (الحدث على القوس من LISTEN إلى SYNRCVD على سبيل المثال) استدعاء عملية التطبيق المحلي عمليةً على بروتوكول 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 على جانب الاستقبال بمخزن استقبالٍ مؤقت، حيث يحتفظ هذا المخزن المؤقت بالبيانات التي تصل مخالفةً للترتيب، وكذلك البيانات ذات الترتيب الصحيح (مثل عدم وجود بايتاتٍ مفقودة في وقت سابق من التدفق) ولكن عملية التطبيق لم تتح لها الفرصة لقراءتها بعد. نتجاهل في البداية حقيقة أن كلًا من المخازن المؤقتة والأرقام التسلسلية ذات حجم محدود وبالتالي ستلتف في النهاية لجعل المناقشة التالية أسهل، ولا نفرق أيضًا بين المؤشر إلى المخزن المؤقت حيث يُخزَّن بايتٌ معين من البيانات وبين الرقم التسلسلي لذلك البايت. بالنظر أولًا إلى جانب الإرسال، يحتفظ مخزن الإرسال المؤقت بثلاث مؤشرات، لكل منها معنى واضح: 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 المختلفة. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } حيز النطاق التراسلي 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. اقرأ أيضًا بروتوكولات طرف إلى طرف End-to-End Protocols في الشبكات الحاسوبيةالمقال السابق: تأسيس الشبكات الحاسوبية والتعرف على تطبيقاتها البرمجيات المستخدمة في بناء الشبكات الحاسوبية التوجيه Routing بين الأجهزة المتنقلة في الشبكات الحاسوبية دليل بصري لكيفية استخدام أنفاق SSH
-
- tcp
- شبكات حاسوبية
-
(و 2 أكثر)
موسوم في:
-
يدعم TCP تجريد تدفق البايت، أي أن برامج التطبيقات تكتب البايت في التدفق، والأمر متروك لبروتوكول TCP لاتخاذ القرار بأن لديه بايتات كافية لإرسال جزء. لكن ما هي العوامل التي تحكم هذا القرار؟ سنتابع في هذا المقال ما تحدثنا عنه في المقال السابق حول بروتوكولات تدفق البايتات الموثوقة بالاعتماد على مثال TCP، وسنكمل الحديث هنا عن هذه البروتوكولات آخذين جانب آلية الإرسال والبدائل. إذا تجاهلنا إمكانية التحكم في التدفق، أي بفرض أن النافذة مفتوحة على مصراعيها كما هو الحال عند بدء الاتصال لأول مرة، عندئذ يكون لدى بروتوكول TCP ثلاث آليات لبدء إرسال جزء. أولًا، يحتفظ بروتوكول TCP بمتغير، يسمى عادةً حجم الجزء الأقصى maximum segment size أو اختصارًا MSS، ويرسل جزءًا بمجرد أن يجمع بايتاتٍ بحجم MSS من عملية الإرسال. يُضبَط MSS على حجم أكبر جزء يمكن أن يرسله TCP دون التسبب في تجزئة عنوان IP المحلي. أي ضُبِط MSS على أقصى وحدة إرسال maximum transmission unit أو اختصارًا MTU للشبكة المتصلة مباشرة، مطروحًا منها حجم ترويستي TCP و IP. الشيء الثاني الذي ينبّه بروتوكول TCP لإرسال جزء هو أن عملية الإرسال طلبت منه صراحةً القيام بذلك. يدعم بروتوكول TCP العملية push، وتستدعي عملية الإرسال هذه العملية لتفريغ flush المخزن المؤقت للبايتات غير المرسلة بفعالية. المنبّه trigger الأخير لإرسال جزء هو إنطلاق المؤقت timer، حيث يحتوي الجزء الناتج على العديد من البايتات المخزَّنة حاليًا للإرسال. وعلى أية حال لن يكون هذا "المؤقت" كما تتوقعه بالضبط كما سنرى قريبًا. متلازمة النوافذ الساذجة Silly Window Syndrome لا يمكننا بالتأكيد تجاهل التحكم في التدفق فقط، والذي يلعب دورًا واضحًا في تقييد المرسل. فإذا كان لدى المرسل بايتات بحجم MSS من البيانات لإرسالها وكانت النافذة مفتوحة على الأقل بهذا القدر، فإن المرسل يرسل جزءًا كاملًا. افترض أن المرسل يجمّع البايتات لإرسالها، ولكن النافذة مغلقة حاليًا. لنفترض الآن وصول ACK يفتح النافذة بفعالية بما يكفي لإرسال المرسل، بحجم MSS / 2 بايت مثلًا. هل يجب على المرسل إرسال جزء نصف ممتلئ أم الانتظار حتى تفتح النافذة بحجم MSS كامل؟ لم تذكر المواصفات الأصلية شيئًا بشأن هذه النقطة، وقررت عمليات التنفيذ الأولي لبروتوكول TCP المضي قدمًا وإرسال جزء نصف كامل، ولكن ليس هناك ما يخبرنا إلى متى سيبقى بهذه الحالة قبل أن تفتح النافذة أكثر. اتضح أن استراتيجية الاستفادة الكبيرة من أية نافذةٍ متاحة تؤدي إلى حالة تُعرَف الآن باسم متلازمة النوافذ الساذجة، حيث يساعد الشكل التالي على تصور ما يحدث: إذا فكّرت في تدفق TCP على أنه حزامٌ ناقل به حاويات "ممتلئة" أو أجزاء بيانات data segments تسير في اتجاهٍ واحد وحاويات فارغة هي الإشعارات ACKs تسير في الاتجاه العكسي. فإن الأجزاء ذات الحجم MSS تتوافق مع الحاويات الكبيرة والأجزاء ذات الحجم 1 بايت تتوافق مع حاويات صغيرة جدًا. طالما أن المرسل يرسل أجزاءًا بحجم MSS ويرسل المستقبل إشعارات ACKs على الأقل بحجم MSS من البيانات في كل مرة، وبالتالي سيعمل كل شيء جيدًا (كما في القسم أ من الشكل الآتي). لكن ماذا لو اضطر المستقبل إلى تقليل النافذة بحيث لا يتمكن المرسل في وقتٍ ما من إرسال MSS كامل من البيانات؟ إذا ملأ المرسل حاويةً فارغة حجمها أصغر من MSS بمجرد وصولها، فسيرسل المستقبل إشعارًا بهذا العدد الأصغر من البايتات، وبالتالي تظل الحاوية الصغيرة المدخلة في النظام إلى أجلٍ غير مسمى فيه، أي أنها تُملَأ وتُفرَغ على الفور عند كل طرف ولا تُدمَج مطلقًا مع الحاويات المجاورة لإنشاء حاويات أكبر، كما في القسم (ب) من الشكل التالي. اُكتشِف هذا السيناريو عندما وجدت التطبيقات الأولى لبروتوكول TCP نفسها تملأ الشبكة بأجزاء صغيرة. تُعتبر متلازمة النوافذ الساذجة مشكلةً فقط عندما يرسل المرسل جزءًا صغيرًا أو يفتح جهاز الاستقبال النافذة بمقدار صغير. إذا لم يحدث أي من هذين الأمرين، فلن تُدخَل الحاوية الصغيرة مطلقًا في التدفق. من غير الممكن تحريم إرسال مقاطع صغيرة، فقد يقوم التطبيق بعملية push بعد إرسال بايت واحد على سبيل المثال، ولكن من الممكن منع جهاز الاستقبال من إدخال حاوية صغيرة (أي نافذة صغيرة مفتوحة)، حيث يجب أن ينتظر جهاز الاستقبال حيزًا يساوي حجم MSS قبل أن يعلن عن نافذة مفتوحة، وذلك بعد الإعلان عن نافذةٍ صفرية. نظرًا لإمكانية استبعاد إمكانية إدخال حاويةٍ صغيرة في التدفق، إلا أننا نحتاج أيضًا إلى آلياتٍ لدمجها. يمكن للمستقبل القيام بذلك عن طريق تأخير ACK، أي إرسال ACK واحد مدمج بدلًا من إرسال عدة رسائلٍ أصغر، ولكن هذا حل جزئي فقط لأن جهاز الاستقبال ليس لديه طريقة لمعرفة المدة التي يمكن فيها تأخير انتظار وصول جزء آخر أو انتظار التطبيق لقراءة المزيد من البيانات (وبالتالي فتح النافذة). يقع الحل النهائي على عاتق المرسل، وهو ما يعيدنا إلى مشكلتنا الأصلية: متى يقرر مرسل TCP إرسال جزءsegment؟ خوارزمية Nagle بالعودة إلى مرسل TCP، إذا كانت هناك بياناتٌ لإرسالها ولكن النافذة مفتوحة بحجمٍ أقل من حجم MSS، فقد نرغب في الانتظار بعض الوقت قبل إرسال البيانات المتاحة، ولكن السؤال هو كم طول هذه المدة؟ إذا انتظرنا وقتًا طويلًا، فإننا نُضِر بذلك التطبيقات التفاعلية مثل تطبيق Telnet. وإذا لم ننتظر طويلًا بما فيه الكفاية، فإننا نجازف بإرسال مجموعةٍ من الرزم الصغيرة والوقوع في متلازمة النوافذ الساذجة. الجواب هو إدخال مؤقت timer والإرسال عند انتهاء مدته. يمكننا استخدام مؤقت قائم على النبضات، مثل مؤقت ينطلق كل 100 ميلي ثانية. قدّم Nagle حلًا رائعًا للتوقيت الذاتي. الفكرة هي أنه طالما لدى بروتوكول TCP أي بيانات قيد الإرسال in flight، فإن المرسل سيتلقى في النهاية ACK. يمكن التعامل مع ACK كإطلاق مؤقت، ينبِّه بإرسال المزيد من البيانات. توفر خوارزمية Nagle قاعدة بسيطة وموحدة لاتخاذ قرار بشأن توقيت بدء الإرسال. When the application produces data to send if both the available data and the window >= MSS send a full segment else if there is unACKed data in flight buffer the new data until an ACK arrives else send all the new data now من المقبول دائمًا إرسال جزء كامل إذا سمحت النافذة بذلك، كما يحق لك إرسال كمية صغيرة من البيانات على الفور إذا لم يكن هناك أي أجزاء قيد النقل. ولكن إذا كان هناك أي شيء قيد الإرسال، فيجب على المرسل انتظار ACK قبل إرسال الجزء التالي. وبالتالي سيرسل تطبيقٌ تفاعلي مثل Telnet الذي يكتب باستمرار بايتًا واحدًا في المرة الواحدة البياناتِ بمعدل جزء واحد لكل RTT. ستحتوي بعض الأجزاء على بايت واحد، بينما يحتوي البعض الآخر على عدد بايتات بقدر ما كان المستخدم قادرًا على الكتابة في وقت واحد ذهابًا وإيابًا. تسمح واجهة المقبس للتطبيق بإيقاف تشغيل خوارزمية Nagel عن طريق تعيين خيار TCP_NODELAY نظرًا لأن بعض التطبيقات لا يمكنها منح مثل هذا التأخير لكل عملية كتابة تقوم بها لاتصالٍ من نوع TCP، حيث يعني ضبط هذا الخيار إرسال البيانات في أسرع وقتٍ ممكن. إعادة الإرسال التكيفي Adaptive Retransmission بما أن بروتوكول TCP يضمن التسليم الموثوق للبيانات، فإنه يعيد إرسال كل جزء إذا لم يُستلَم إشعار ACK خلال فترةٍ زمنية معينة. يضبط بروتوكول TCP هذه المهلة الزمنية كدالة لوقت RTT الذي يتوقعه بين طرفي الاتصال. إن اختيار قيمة المهلة الزمنية المناسبة ليس بهذه السهولة لسوء الحظ، نظرًا لمجال قيم RTT الممكنة بين أي زوجٍ من المضيفين في الإنترنت، بالإضافة إلى الاختلاف في RTT بين نفس المضيفين بمرور الوقت. لمعالجة هذه المشكلة، يستخدم بروتوكول TCP آلية إعادة الإرسال التكيفية. سنقوم بوصف هذه الآلية الآن وتطورها مع مرور الوقت حيث اكتسب مجتمع الإنترنت المزيد من الخبرة باستخدام TCP. الخوارزمية الأصلية نبدأ بخوارزمية بسيطة لحساب قيمة المهلة الزمنية timeout بين زوجٍ من المضيفين. هذه هي الخوارزمية التي وُصفت في الأصل في مواصفات بروتوكول TCP، ولكن يمكن استخدامها بواسطة أي بروتوكول طرفٍ إلى طرف end-to-end protocol. تكمن الفكرة في الاحتفاظ بمتوسط تشغيل RTT ثم حساب المهلة الزمنية كدالة لوقت RTT. يسجل TCP الوقت في كل مرة يرسل فيها جزء بيانات، ويقرأ بروتوكول TCP الوقت مرةً أخرى عند وصول ACK لهذا الجزء، ثم يأخذ الفرق بين هاتين المرتين على أنه SampleRTT. ثم يحسب TCP قيمة EstimatedRTT كمتوسط مرجح بين التقدير estimate السابق وهذه العينة sampleالجديدة، حيث: EstimatedRTT = alpha x EstimatedRTT + (1 - alpha) x SampleRTT يُحدَّد المعامل alpha لتنعيم EstimatedRTT. تتتبّع قيمةُ alpha الصغيرة التغييراتِ في RTT ولكن ربما تتأثر بشدة بالتقلبات المؤقتة. ومن ناحيةٍ أخرى، تكون قيمة alpha الكبيرة أكثر استقرارًا ولكن ربما لا تكون سريعة بما يكفي للتكيف مع التغييرات الحقيقية. أوصت مواصفات TCP الأصلية بإعداد قيمة alpha بين 0.8 و 0.9. يستخدم بروتوكول TCP المعامل EstimatedRTT لحساب المهلة الزمنية timeout بطريقة متحفظة إلى حدٍ ما: TimeOut = 2 x EstimatedRTT خوارزمية كارن / بارتريدج Karn/Partridge اُكتشِف عيبٌ واضح في الخوارزمية السابقة البسيطة بعد عدة سنوات من الاستخدام على الإنترنت. كانت المشكلة أن الإشعار ACK لا يُقِر حقًا بالإرسال، بل باستلام البيانات في الحقيقة، أي عندما يُعاد إرسال جزء ثم وصول ACK إلى المرسل، فمن المستحيل تحديد ما إذا كان ينبغي إرفاق هذا الإشعار بالإرسال الأول أو الثاني للجزء بغرض قياس sample RTT. من الضروري معرفة الإرسال الذي سيُربَط به لحساب العينة SampleRTT بدقة. إذا افترضت أن الإشعار ACK للإرسال الأصلي ولكنه كان في الحقيقة للثاني كما هو موضح في الشكل التالي، فإن SampleRTT كبيرةٌ جدًا كما في القسم (أ) من الشكل التالي، وإذا افترضت أن الإشعار ACK للإرسال الثاني ولكنه كان في الواقع للإرسال الأول، فإن عينة SampleRTT صغيرةٌ جدًا كما في القسم (ب) من الشكل التالي: الحل الذي جرى اقتراحه في عام 1987 بسيط جدًا: يتوقف بروتوكول TCP عن أخذ عيناتٍ من RTT عندما يعيد إرسال جزء ما، فهو يقيس SampleRTT فقط للأجزاء التي أُرسلت مرةً واحدة فقط. يُعرف هذا الحل باسم خوارزمية كارن / بارتريدج تيّمنًا بمخترعَيها. يتضمن الإصلاح المقترح أيضًا تغييرًا صغيرًا ثانيًا في آلية مهلة TCP الزمنية. يضبط بروتوكول TCP المهلة التالية لتكون ضعف آخر مهلة في كل مرة يعيد فيها الإرسال، بدلًا من إسنادها إلى آخرEstimatedRTT. اقترح كارن و بارتريدج أن يستخدم بروتوكولُ TCP تراجعًا أسيًا exponential backoff، على غرار ما يفعله إيثرنت. الدافع لاستخدام التراجع الأسي بسيط: الازدحام هو السبب الأكثر احتمالًا لفقدان الأجزاء، مما يعني أن مصدر TCP يجب ألا يتفاعل بقوة مع انقضاء المهلة الزمنية، فكلما انقضت مهلة الاتصال الزمنية، يجب أن يصبح المصدر أكثر حذرًا. سنرى هذه الفكرة مرة أخرى، مجسَّدةً في آلية أعقد لاحقًا. خوارزمية جاكوبسون / كارلس Jacobson/Karels قُدّمت خوارزمية كارن / بارتريدج في وقت كان فيه الإنترنت يعاني من مستويات عالية من ازدحام الشبكة، فصُمِّم نهج هذه الخوارزمية لإصلاح بعض أسباب هذا الازدحام، ولكن على الرغم من تقديمها تحسينًا، إلا أنه لم يتم القضاء على الازدحام. اقترح باحثان آخران (جاكوبسون وكارلس) تغييرًا جذريًا في بروتوكول TCP لمحاربة الازدحام في العام التالي (1988). سنركز على هذا الاقتراح المتعلق بتحديد انتهاء المهلة وإعادة إرسال جزء ما. يجب أن يكون ارتباط آلية المهلة الزمنية بالازدحام واضحًا، فإذا انقضت المهلة في وقت مبكرٍ جدًا، فقد تعيد إرسال جزء بدون داعٍ، والذي يضيف فقط إلى الحِمل على الشبكة. السبب الآخر للحاجة إلى قيمة مهلة دقيقة هو أن المهلة تُؤخَذ للإشارة إلى الازدحام، مما يؤدي إلى تشغيل آلية للتحكم في الازدحام. أخيرًا، لاحظ أنه لا يوجد شيء يتعلق بحساب مهلة جاكوبسون وكارلس الخاص ببروتوكول TCP. يمكن استخدامه من قبل أي بروتوكول من طرفٍ إلى طرف. تكمن المشكلة الرئيسية في حساب الخوارزمية الأصلية في أنها لا تأخذ في الاعتبار تباين عينات RTT. إذا كان الاختلاف بين العينات صغيرًا، فيمكن الوثوق في EstimatedRTT بصورةٍ أفضل ولا يوجد سبب لضرب هذا التقدير في 2 لحساب المهلة الزمنية. يشير التباين الكبير في العينات من ناحية أخرى إلى أن قيمة المهلة لا ينبغي أن تكون مرتبطة بإحكام شديد بقيمة EstimatedRTT. بينما في النهج الجديد، يقيس المرسل SampleRTT جديدًا كما كان يتم سابقًا، ثم تُطوى هذه العينة الجديدة في حساب المهلة على النحو التالي: Difference = SampleRTT - EstimatedRTT EstimatedRTT = EstimatedRTT + ( delta x Difference) Deviation = Deviation + delta (|Difference| - Deviation) حيث تقع قيمة delta بين 0 و1. أي أننا نحسب كلًا من متوسط وقت RTT والتغير في هذا المتوسط، ثم يحسب TCP قيمة المهلة كدالة لكل من EstimatedRTT وDeviation على النحو التالي: TimeOut = mu x EstimatedRTT + phi x Deviation يُعيَّن mu على القيمة 1 وphi على القيمة 4 بناءً على الخبرة. وهكذا تكون TimeOut قريبةً من EstimatedRTT عندما يكون التباين صغيرًا، حيث يؤدي التباين الكبير إلى سيطرة مصطلح الانحراف Deviation على الحساب. التطبيق Implementation هناك نقطتان جديرتان بالملاحظة فيما يتعلق بتطبيق المهلات الزمنية في بروتوكول TCP. الأولى هي إمكانية تطبيق حساب EstimatedRTT وDeviation دون استخدام حساب الأعداد العشرية. فبدلًا من ذلك، تُوسَّع العملية الحسابية بالكامل بمقدار 2n، مع اختيار delta لتكون 1/2n. يتيح لنا ذلك إجراء العمليات الحسابية الصحيحة، وتطبيق الضرب والقسمة باستخدام الإزاحات shifts، وبالتالي تحقيق أداءٍ أعلى. يُعطى الحساب الناتج عن طريق جزء الشيفرة التالية، حيث n = 3 (أي delta = 1/8). لاحظ تخزين EstimatedRTT وDeviation في نماذجهما الموسّعَين، بينما قيمة SampleRTT في بداية الشيفرة و TimeOut في النهاية هي قيمٌ حقيقية غير مُوسَّعة. إذا وجدت صعوبة في تتبع الشيفرة، فقد ترغب في محاولة إدخال بعض الأرقام الحقيقية فيها والتحقق من أنها تعطي نفس النتائج مثل المعادلات أعلاه: { SampleRTT -= (EstimatedRTT >> 3); EstimatedRTT += SampleRTT; if (SampleRTT < 0) SampleRTT = -SampleRTT; SampleRTT -= (Deviation >> 3); Deviation += SampleRTT; TimeOut = (EstimatedRTT >> 3) + (Deviation >> 1); } النقطة الثانية هي أن خوارزمية جاكوبسون / كارلس جيدة فقط مثل الساعة المستخدمة لقراءة الوقت الحالي. كانت دقة الساعة كبيرة في تطبيقات يونيكس النموذجية في ذلك الوقت حيث وصلت إلى 500 ميلي ثانية، وذلك أكبر بكثير من متوسط RTT عبر دولة في مكانٍ ما والذي يكون بين 100 و200 ميلي ثانية. لجعل الأمور أسوأ، فحص تطبيق يونيكس لبروتوكول TCP فيما إذا كان يجب أن يحدث انتهاء للمهلة في كل مرة تُحدَّد فيها الساعة 500 ميلي ثانية ولن يأخذ سوى عينةٍ من وقت الذهاب والإياب مرة واحدة لكل RTT. و قد يعني الجمع بين هذين العاملين أن المهلة ستحدث بعد ثانية واحدة من إرسال الجزء. تشتمل توسّعات TCP على آلية تجعل حساب RTT هذا أدق قليلًا. تستند جميع خوارزميات إعادة الإرسال التي ناقشناها إلى مهلات الإشعارات، والتي تشير إلى احتمال فقد جزءٍ ما. لاحظ أن المهلة لا تخبر المرسل فيما إذا اُستلِمت بنجاحٍ أي أجزاءٍ أرسلها بعد فقدان جزء، وذلك لأن إشعارات TCP تراكمية cumulative، أي أنها تحدد فقط الجزء الأخير المُستلم دون أي فجوات سابقة. ينمو استقبال الأجزاء التي تظهر بعد زيادة الفجوة بصورةٍ متكررة كما تؤدي الشبكات الأسرع إلى نوافذ أكبر. إذا أخبرت ACK المرسلَ أيضًا عن الأجزاء اللاحقة، إن وجدت، فقد يكون المرسل أذكى بشأن الأجزاء التي يعيد إرسالها، إضافةً لاستخلاص استنتاجات أفضل حول حالة الازدحام، وإجراء تقديرات RTT أفضل. حدود السجلات Record Boundaries ليس بالضرورة أن يكون عدد البايتات التي يكتبها المرسل نفس عدد البايتات التي قرأها المستقبل نظرًا لأن بروتوكول TCP هو بروتوكول تدفق بايتات، فقد يكتب التطبيق 8 بايتات، ثم 2 بايت، ثم 20 بايت إلى اتصال TCP، بينما يقرأ التطبيق على جانب الاستقبال 5 بايتات في المرة الواحدة داخل حلقة تتكرر 6 مرات. لا يقحم بروتوكول TCP حدود السجلات بين البايتين الثامن والتاسع، ولا بين البايتين العاشر والحادي عشر. هذا على عكس بروتوكول الرسائل الموّجهة، مثل بروتوكول UDP، حيث تكون الرسالة المرسَلة بنفس طول الرسالة المُستلَمة. يمتلك بروتوكول TCP، على الرغم من كونه بروتوكول تدفق بايتات، ميزتين مختلفتين يمكن للمرسل استخدامهما لإدراج حدود السجلات في تدفق البايتات هذا، وبالتالي إعلام المستقبِل بكيفية تقسيم تدفق البايتات إلى سجلات. (تُعَد القدرة على تحديد حدود السجلات أمرًا مفيدًا في العديد من تطبيقات قواعد البيانات على سبيل المثال) وضُمِّنت هاتان الميزتان في الأصل في بروتوكول TCP لأسباب مختلفة تمامًا، ثم جرى استخدامهما لهذا الغرض بمرور الوقت، وهما: الآلية الأولى هي ميزة البيانات العاجلة urgent data feature، التي طُبِّقت بواسطة الراية URG وحقل UrgPtr في ترويسة TCP. صُمِّمت آلية البيانات العاجلة في الأصل للسماح للتطبيق المرسِل بإرسال بيانات خارج النطاق إلى نظيره. نعني بعبارة خارج النطاق out-of-band البياناتِ المنفصلة عن تدفق البيانات الطبيعي (أمر مقاطعة عملية جارية بالفعل على سبيل المثال). حُدِّدت هذه البيانات خارج النطاق في الجزء segment باستخدام حقل UrgPtr وكان من المقرر تسليمها إلى عملية الاستلام بمجرد وصولها، حتى لو عنى ذلك تسليمها قبل بيانات ذات رقمٍ تسلسلي سابق. لكن، لم تُستخدَم هذه الميزة بمرور الوقت، لذلك بدلًا من الإشارة إليها ببيانات "عاجلة" ، فقد اُستخدمت للدلالة على بيانات "خاصة"، مثل علامة السجل record marker. طُوِّر هذا الاستخدام لأنه، كما هو الحال مع عملية push، يجب على TCP على الجانب المستلم إبلاغ التطبيق بوصول بيانات عاجلة، أي أن البيانات العاجلة في حد ذاتها ليست مهمة. إنها تشير إلى حقيقة أن عملية الإرسال يمكنها إرسال إشارة فعالة إلى جهاز الاستقبال بأن هناك أمرٌ مهم. الآلية الثانية لإدخال علامات نهاية السجلات في بايت هي العملية push. صُمِّمت هذه الآلية في الأصل للسماح لعملية الإرسال بإعلام بروتوكول TCP بأنه يجب عليه إرسال أو تفريغ flush أي بايتات جمَّعها لنظيره. يمكن استخدام العملية push لتطبيق حدود السجلات لأن المواصفات تنص على أن بروتوكول TCP يجب أن يرسل أي بيانات مخزَّنة مؤقتًا عند المصدر عندما يقول التطبيق push، ويُعلِم بروتوكول TCP، اختياريًا، التطبيق في الوجهة عند وجود جزء وارد يحتوي على مجموعة الراية PUSH. إذا كان جانب الاستقبال يدعم هذا الخيار (لا تدعم واجهة المقبس هذا الخيار)، فيمكن عندئذٍ استخدام العملية push لتقسيم تدفق TCP إلى سجلات. برنامج التطبيق حرٌ دائمًا بحشر حدود السجلات دون أي مساعدة من بروتوكول TCP، حيث يمكنه إرسال حقل يشير إلى طول السجل الذي يجب أن يتبعه، أو يمكنه حشر علامات حدود السجل الخاصة به في تدفق البيانات على سبيل المثال. إضافات بروتوكول TCP لقد ذكرنا أن هناك إضافات Extensions لبروتوكول TCP تساعد في التخفيف من بعض المشاكل التي واجهها حيث أصبحت الشبكة الأساسية أسرع. صُمِّمت هذه الإضافات ليكون لها تأثيرٌ ضئيل على بروتوكول TCP قدر الإمكان، حيث تُدرَك كخياراتٍ يمكن إضافتها إلى ترويسة TCP. (سبب احتواء ترويسة TCP على حقل HdrLen هو أن الترويسة يمكن أن تكون بطول متغير، يحتوي الجزء المتغير من ترويسة TCP على الخيارات المُضافة). أهمية إضافة هذه الإضافات كخيارات بدلًا من تغيير جوهر ترويسة TCP هو أن المضيفين لا يزالون قادرين على التواصل باستخدام TCP حتى لو لم يقوموا بتطبيق الخيارات، ولكن يمكن للمضيفين الذين يقومون بتطبيق الإضافات الاختيارية الاستفادة منها. يتفق الجانبان على استخدام الخيارات أثناء مرحلة إنشاء اتصال TCP. تساعد الإضافة الأولى على تحسين آلية ضبط مهلة TCP الزمنية. يمكن لبروتوكول TCP قراءة ساعة النظام الفعلية عندما يكون على وشك إرسال جزء بدلًا من قياس RTT باستخدام حدث قاسٍ coarse-grained، ووضع هذا الوقت (فكر به على أنه علامة زمنية timestamp مؤلفة من 32 بتًا) في ترويسة الجزء، ثم يُرجِع echoes المستقبل هذه العلامة الزمنية مرةً أخرى إلى المرسل في إشعاره، ويطرح المرسل هذه العلامة الزمنية من الوقت الحالي لقياس وقت RTT. يوفر خيار العلامة الزمنية مكانًا مناسبًا لبروتوكول TCP لتخزين سجل وقت إرسال جزء، أي يخزن الوقت في الجزء نفسه. لاحظ أن نقاط النهاية في الاتصال لا تحتاج إلى ساعات متزامنة، حيث تُكتَب العلامة الزمنية وتُقرَأ في نهاية الاتصال نفسها. تعالج الإضافة الثانية مشكلة التفاف wrapping around حقل SequenceNum المكون من 32 بت لبروتوكول TCP في وقت قريب جدًا على شبكة عالية السرعة. يستخدم بروتوكول TCP العلامة الزمنية المؤلفة من 32 بتًا الموصوفة للتو لتوسيع حيز الأرقام التسلسلية بفعالية بدلاً من تحديد حقل رقم تسلسلي جديد مؤلف من 64 بتًا. أي يقرر بروتوكول TCP قبول أو رفض جزء بناءً على معرّف بطول 64 بت يحتوي على حقل SequenceNum بترتيب 32 بت المنخفض والعلامة الزمنية بترتيب 32 بت العالي. بما أن العلامة الزمنية تتزايد دائمًا، فإنها تعمل على التمييز بين تجسبدَين مختلفين لنفس الرقم التسلسلي. لاحظ استخدام العلامة الزمنية في هذا الإعداد فقط للحماية من الالتفاف، حيث لا يُتعامَل معها كجزء من الرقم التسلسلي لغرض طلب البيانات أو الإشعار بوصولها. تسمح الإضافة الثالثة لبروتوكول TCP بالإعلان عن نافذةٍ أكبر، مما يسمح له بملء الأنابيب ذات جداء (التأخير × حيز النطاق التراسلي) الأكبر والتي تتيحها الشبكات عالية السرعة. تتضمن هذه الإضافة خيارًا يحدد عامل توسيع scaling factor للنافذة المعلن عنها. أي يسمح هذا الخيار لطرفي TCP بالاتفاق على أن حقل AdvertisedWindow يحسب أجزاءًا أكبر (عدد وحدات البيانات ذات 16 بايت الممكن عدم الإقرار بها من قبل المرسل على سبيل المثال) بدلًا من تفسير الرقم الذي يظهر في حقل AdvertisedWindow على أنه يشير إلى عدد البايتات المسموح للمرسل بعدم الإقرار بها. يحدد خيار توسيع النافذة عدد البتات التي يجب على كل جانبٍ إزاحة حقل AdvertisedWindow بها لليسار قبل استخدام محتوياته لحساب نافذة فعالة. تسمح الإضافة الرابعة لبروتوكول TCP بتوفير إشعاره التراكمي cumulative acknowledgment مع الإشعارات الانتقائية selective acknowledgments لأية أجزاءٍ إضافية جرى استلامها ولكنها ليست متجاورة مع جميع الأجزاء المُستلمة مسبقًا، وهذا هو خيار الإشعار الانتقائي أو SACK. يستمر جهاز الاستقبال بالإقرار أو الإشعار عن الأجزاء بشكلٍ طبيعي عند استخدام خيار SACK، أي لا يتغير معنى حقل Acknowledge، ولكنه يستخدم أيضًا حقولًا اختيارية في الترويسة لإرسال إشعارات وصول أي كتلٍ إضافية من البيانات المستلمة. يتيح ذلك للمرسل إعادة إرسال الأجزاء المفقودة فقط وفقًا للإشعار الانتقائي. هناك استراتيجيتان مقبولتان فقط للمرسل بدون SACK. تستجيب الاستراتيجية المتشائمة pessimistic لانتهاء المهلة بإعادة إرسال الجزء المنتهية مهلته، وكذلك أي أجزاء سترسَل لاحقًا أيضًا، وتفترض الإستراتيجية المتشائمة الأسوأ والذي هو فقد كل تلك الأجزاء. عيب الاستراتيجية المتشائمة هو أنها قد تعيد إرسال الأجزاء المُستلمة بنجاح في المرة الأولى دون داعٍ. الإستراتيجية الأخرى هي الإستراتيجية المتفائلة optimistic، والتي تستجيب لانتهاء المهلة بإعادة إرسال الجزء المنتهية مهلته فقط. يفترض النهج المتفائل السيناريو الأكثر تفاؤلًا والذي هو فقد جزء segment واحد فقط. عيب الإستراتيجية المتفائلة أنها بطيئة للغاية دون داعٍ، عندما تضيع سلسلة من الأجزاء المتتالية، كما يحدث عندما يكون هناك ازدحام. كما أنها بطيئة نظرًا لعدم القدرة على اكتشاف خسارة كل جزءٍ حتى يتلقى المرسل ACK لإعادة إرسال الجزء السابق، لذلك فهي تستهلك وقت RTT واحدًا لكل جزءٍ حتى يعيد إرسال جميع الأجزاء في السلسلة المفقودة. تتوفر استراتيجية أفضل للمرسل مع خيار SACK وهي: أعد إرسال الأجزاء التي تملأ الفجوات بين الأجزاء التي جرى الإقرار بها انتقائيًا. بالمناسبة، لا تمثّل هذه الإضافات القصة الكاملة. حيث سنرى بعض الإضافات الأخرى عندما ننظر في كيفية تعامل بروتوكول TCP مع الازدحام. تتعقب هيئة تخصيص أرقام الإنترنت Internet Assigned Numbers Authority أو اختصارًا IANA جميع الخيارات المحددة لبروتوكول TCP (إضافةً للعديد من بروتوكولات الإنترنت الأخرى). الأداء Performance تذكر أن في بداية السلسلة قد قدّم المقياسين الكميّين اللذين يجري من خلالِهما تقييم أداء الشبكة وهما: زمن الاستجابة latency والإنتاجية throughput. لا تتأثر هذه المقاييس فقط بالعتاد الأساسي، مثل تأخير الانتشار propagation delay وحيز نطاق الرابط التراسلي link bandwidth، كما هو مذكور في تلك المناقشة، ولكن تتأثر أيضًا بتكاليف البرمجيات الزائدة. يمكننا مناقشة كيفية قياس أداء البروتوكول القائم على البرمجيات بشكل هادف الآن بعد أن أصبح متاحًا لنا رسمًا بيانيًا كاملًا له متضمنًا بروتوكولات نقل بديلة. تكمن أهمية هذه القياسات في أنها تمثل الأداء الذي تراه برامج التطبيق. نبدأ، كما ينبغي لأي تقرير لنتائج التجارب، بوصف طريقتنا التجريبية. وهذا يشمل الجهاز المستخدم في التجارب، حيث تحتوي كل محطة عمل على زوج من معالجات Xeon لوحدة المعالجة المركزية بتردد 2.4 جيجاهرتز والتي تعمل بنظام لينوكس في هذه الحالة. يجري استخدام زوج من محوّلات إيثرنت، المسمَّى NIC بطاقة واجهة الشبكة network interface card، على كل جهاز لتمكين سرعات أعلى من 1 جيجابت في الثانية. يمتد الإيثرنت على غرفة جهاز واحدة لذا لا يمثل الانتشار مشكلة، مما يجعل هذا مقياسًا لتكاليف المعالجات / البرمجيات الزائدة. يحاول برنامجُ الاختبار الذي يعمل أعلى واجهة المقبس ببساطة نقلَ البيانات بأسرع ما يمكن من جهازٍ إلى آخر، ويوضح الشكل السابق هذا الإعداد. قد تلاحظ أن هذا الإعداد التجريبي لا يمثل ميزة خاصة من حيث العتاد أو سرعة الروابط. لا يتمثل الهدف من هذا القسم في إظهار مدى سرعة تشغيل بروتوكول معين، ولكن لتوضيح المنهجية العامة لقياس أداء البروتوكول والإبلاغ عنه. يجري اختبار الإنتاجية لمجموعة متنوعة من أحجام الرسائل باستخدام أداة قياس معيارية تسمى TTCP. يوضح الشكل التالي نتائج اختبار الإنتاجية. الشيء الرئيسي الواجب ملاحظته في هذا الرسم البياني هو أن معدل النقل يتحسن مع زيادة حجم الرسائل. وهذا أمرٌ منطقي، حيث تتضمن كل رسالة قدرًا معينًا من الحِمل الزائد، لذا فإن الرسالة الأكبر تعني أن هذا الحِمل يُستهلَك على عددٍ أكبر من البايتات. يُسطَّح منحني سرعة النقل الأعلى من 1 كيلوبايت، وعند هذه النقطة يصبح الحِمل لكل رسالة غير مهم عند مقارنته بالعدد الكبير من البايتات التي يتعين على مكدّس البروتوكول معالجتها. تجدر الإشارة إلى أن الحد الأقصى للإنتاجية أقل من 2 جيجابت في الثانية، وهي سرعة الرابط المتاحة في هذا الإعداد. ستكون هناك حاجة لمزيد من الاختبار وتحليل النتائج لمعرفة مكان الاختناق أو معرفة إذا كان هناك أكثر من عنق زجاجة أو اختناق bottleneck. قد يعطي النظر إلى حِمل وحدة المعالجة المركزية مؤشرًا على ما إذا كانت وحدة المعالجة المركزية هي مكان الاختناق أم أن اللوم يقع على حيز النطاق التراسلي للذاكرة أو أداء محوّل adaptor الشبكة أو بعض المشكلات الأخرى. نلاحظ أيضًا أن الشبكة في هذا الاختبار "مثالية" بصورةٍ أساسية. لا يوجد أي تأخير أو خسارة تقريبًا، وبالتالي فإن العوامل الوحيدة التي تؤثر على الأداء هي تطبيق بروتوكول TCP إضافةً إلى عتاد وبرمجيات محطة العمل. ولكن نتعامل في معظم الأوقات مع شبكاتٍ بعيدة عن الكمال، ولا سيما روابطنا المقيدة بحيّز النطاق التراسلي وروابط الميل الأخير والروابط اللاسلكية المعرّضة للضياع. نحتاج إلى فهم كيفية تعامل بروتوكول TCP مع الازدحام قبل أن نقّدر تمامًا كيف تؤثر هذه الروابط على أداء TCP. هدّدت سرعة روابط الشبكة المتزايدة بشكل مطرد بالتقدم على ما يمكن تسليمه إلى التطبيقات في أوقات مختلفة من تاريخ الشبكات. بدأ جهد بحثي كبير في الولايات المتحدة في عام 1989 لبناء "شبكات جيجابت gigabit networks" على سبيل المثال، حيث لم يكن الهدف فقط بناء روابط ومبدلات يمكن تشغيلها بسرعة 1 جيجابت في الثانية أو أعلى، ولكن أيضًا لإيصال هذه الإنتاجية على طول الطريق إلى عملية تطبيقٍ واحدة. كانت هناك بعض المشكلات الحقيقية (كان لابد من تصميم محولات شبكة، وبنيات محطات عمل، وأنظمة تشغيل مع مراعاة إنتاجية النقل من شبكة إلى تطبيق على سبيل المثال) وكذلك بعض المشكلات المُدرَكة التي تبين أنها ليست خطيرة للغاية. وكان على رأس قائمة مثل هذه المشاكل القلقُ من أن بروتوكولات النقل الحالية، وخاصةً بروتوكول TCP، قد لا تكون على مستوى التحدي المتمثل في عمليات الجيجابت. كما اتضح، كان أداء بروتوكول TCP جيدًا في مواكبة الطلبات المتزايدة للشبكات والتطبيقات عالية السرعة. أحد أهم العوامل هو إدخال توسيع النافذة للتعامل مع منتجات تأخير حيز النطاق التراسلي الأكبر، ولكن غالبًا ما يكون هناك فرقٌ كبير بين الأداء النظري لبروتوكول TCP وما يجري تحقيقه عمليًا. يمكن أن تؤدي المشكلات البسيطة نسبيًا مثل نسخ البيانات مرات أكثر من اللازم أثناء انتقالها من محول الشبكة إلى التطبيق إلى انخفاض الأداء، كما يمكن أن تؤدي ذاكرة التخزين المؤقت غير الكافية إلى انخفاض الأداء عندما يكون منتج تأخير حيز النطاق التراسلي كبيرًا. وديناميكيات TCP معقدة بدرجة كافية، بحيث يمكن للتفاعلات الدقيقة بين سلوك الشبكة وسلوك التطبيق وبروتوكول TCP نفسه تغيير الأداء بصورةٍ كبيرة. من الجدير بالذكر أن بروتوكول TCP يستمر في الأداء الجيد مع زيادة سرعات الشبكة، ويندفع الباحثون لإيجاد حلول عند حدوث تعارض مع بعض القيود (المرتبطة عادةً بالازدحام أو زيادة منتجات تأخير حيز النطاق التراسلي أو كليهما). خيارات التصميم البديلة SCTP وQUIC على الرغم من أن بروتوكول TCP قد أثبت أنه بروتوكول قوي يلبي احتياجات مجموعة واسعة من التطبيقات، إلا أن مساحة تصميم بروتوكولات النقل كبيرة جدًا. ليس بروتوكول TCP بأي حالٍ النقطة الصالحة الوحيدة في مساحة التصميم هذه. نختم مناقشتنا لبروتوكول TCP من خلال النظر في خيارات التصميم البديلة. بينما نقدم شرحًا حول سبب اتخاذ مصممي TCP الخيارات التي قاموا بها، فإننا نلاحظ وجود بروتوكولات أخرى اتخذت خيارات أخرى، وقد يظهر المزيد من هذه البروتوكولات في المستقبل. هناك صنفان على الأقل من بروتوكولات النقل: البروتوكولات الموجَّهة بالتدفق stream-oriented protocols مثل بروتوكول TCP وبروتوكولات الطلب / الرد request/reply protocols مثل بروتوكول RPC. قسمنا مساحة التصميم ضمنيًا إلى نصفين ووضعنا بروتوكول TCP مباشرةً في نصف عالم البروتوكولات الموجَّهة بالتدفق. يمكننا أيضًا تقسيم البروتوكولات الموجهة بالتدفق إلى مجموعتين، موثوقة reliable وغير موثوقة unreliable، مع احتواء الأولى على بروتوكول TCP والأخيرة أكثر ملاءمة لتطبيقات الفيديو التفاعلية التي تفضل إسقاط أو إهمال إطار بدلًا من تحمّل التأخير المرتبط بإعادة الإرسال. يُعَد بناء تصنيف لبروتوكول النقل أمرًا مثيرًا للاهتمام ويمكن مواصلته بتفاصيل أكثر، ولكن العالم ليس أبيض وأسود كما قد نحب. افترض ملاءمة بروتوكول TCP كبروتوكول نقل لتطبيقات الطلب / الرد على سبيل المثال. بروتوكول TCP هو بروتوكول ثنائي الاتجاه، لذلك سيكون من السهل فتح اتصال TCP بين العميل والخادم، وإرسال رسالة الطلب في اتجاه واحد، وإرسال رسالة الرد في الاتجاه الآخر، ولكن هناك نوعان من التعقيدات. الأول هو أن بروتوكول TCP هو بروتوكول موجَّهٌ بالبايت وليس بروتوكول موجَّه بالرسائل، وأن تطبيقات الطلب / الرد تتعامل دائمًا مع الرسائل. (سنكتشف مسألة البايتات مقابل الرسائل بتفصيل أكبر بعد قليل). التعقيد الثاني هو أنه في تلك المواقف التي تتلاءم فيها كل من رسالة الطلب ورسالة الرد في رزمة شبكة واحدة، يحتاج بروتوكول الطلب / الرد المصمم جيدًا رزمتان فقط لتطبيق التبادل، بينما يحتاج بروتوكول TCP إلى تسع رزم على الأقل: ثلاث لتأسيس الاتصال، واثنان لتبادل الرسائل، وأربع لإنهاء الاتصال. إذا كانت رسائل الطلب أو الرد كبيرة بما يكفي لأن تتطلب رزم شبكةٍ متعددة (قد يستغرق الأمر 100 رزمة لإرسال إستجابة بحجم 100000 بايت على سبيل المثال)، ستكون التكاليف الزائدة لإعداد الاتصال وإلغائه غير منطقية. ليس الأمر دائمًا أن بروتوكولًا معينًا لا يمكنه دعم وظيفةٍ معينة، ففي بعض الأحيان يكون هناك تصميم أكثر كفاءة من تصميم آخر في ظل ظروف معينة. ثانيًا، قد تتساءل عن سبب اختيار TCP لتقديم خدمة تدفق بايتات موثوقة بدلًا من خدمة تدفق رسائل موثوقة، حيث تُعتبر الرسائل الخيار الطبيعي لتطبيق قاعدة البيانات الذي يريد تبادل السجلات. هناك إجابتان على هذا السؤال: الأول هو أن البروتوكول الموجَّه بالرسائل يجب أن ينشئ حدًا أعلى لأحجام الرسائل، فالرسالة الطويلة التي بلا حدود هي تدفق بايتات. ستكون هناك تطبيقات تريد إرسال رسائل أكبر بالنسبة إلى أي حجم رسالة يحدده البروتوكول، مما يجعل بروتوكول النقل عديم الفائدة ويجبر التطبيق على تنفيذ خدماته الشبيهة بالنقل. السبب الثاني هو أنه على الرغم من أن البروتوكولات الموجهة بالرسائل هي بالتأكيد أكثر ملاءمة للتطبيقات التي ترغب في إرسال السجلات إلى بعضها البعض، إلا أنه يمكنك بسهولة إدخال حدود السجل في تدفق البايتات لتطبيق هذه الوظيفة. القرار الثالث الذي اُتخِذ في تصميم TCP هو أنه يسلّم البايتات بناءً على التطبيق. هذا يعني أنه قد يحتفظ بالبايتات التي استلمها مخالفةً للترتيب من الشبكة، في انتظار بعض البايتات المفقودة لملء ثغرة. هذا مفيد للغاية للعديد من التطبيقات ولكن تبين أنه غير مفيد تمامًا إذا كان التطبيق قادرًا على معالجة البيانات المخالفة للترتيب. فلا تحتاج صفحة الويب مثلًا التي تحتوي على كائنات متعددة مضمَّنة إلى تسليم جميع الكائنات بالترتيب قبل البدء في عرض الصفحة. هناك صنف من التطبيقات يفضِّل التعامل مع البيانات المخالفة للترتيب في طبقة التطبيق، مقابل الحصول على البيانات في وقت أقرب عند إسقاط الرزم أو سوء ترتيبها داخل الشبكة. أدت الرغبة في دعم مثل هذه التطبيقات إلى إنشاء بروتوكولي نقل معياريين من IETF. كان أولها بروتوكول SCTP، بروتوكول نقل التحكم في التدفق Stream Control Transmission Protocol. يوفر بروتوكول SCTP خدمة توصيل مُرتَّبة جزئيًا، بدلًا من خدمة TCP المُرتَّبة بدقة. (يتخذ بروتوكول SCTP أيضًا بعض قرارات التصميم الأخرى التي تختلف عن بروتوكول TCP، بما في ذلك اتجاه الرسالة ودعم عناوين IP المتعددة لجلسة واحدة). وحّدت منظمة IETF في الآونة الأخيرة بروتوكولًا محسَّنًا لحركة مرور الويب، يُعرف باسم QUIC. رابعًا، اختار بروتوكول TCP تطبيق مراحل إعداد / تفكيك صريحة، لكن هذا ليس مطلوبًا، حيث سيكون من الممكن إرسال جميع معاملات الاتصال الضرورية مع رسالة البيانات الأولى في حالة إعداد الاتصال. اختار TCP اتباع نهجٍ أكثر تحفظًا يمنح المتلقي الفرصة لرفض الاتصال قبل وصول أي بيانات. يمكننا إغلاق الاتصال الذي كان غير نشط لفترة طويلة من الزمن بهدوء في حالة التفكيك، ولكن هذا من شأنه أن يعقّد تطبيقات مثل تسجيل الدخول عن بُعد الذي يريد الحفاظ على الاتصال نشطًا لأسابيع في كل مرة، حيث ستُجبَر هذه التطبيقات على إرسال رسائل "keep alive" خارج النطاق للحفاظ على حالة الاتصال عند الطرف الآخر من الاختفاء. أخيرًا، بروتوكول TCP هو بروتوكول قائم على النافذة window-based، لكن هذا ليس الاحتمال الوحيد. البديل هو التصميم القائم على المعدَّل rate-based design، حيث يخبر المستلمُ المرسلَ بالمعدّل (معبرًا عنه إما بالبايتات أو بالرزم في الثانية) الذي يكون على استعداد لقبول البيانات الواردة إليه، فقد يخبر المتلقي المرسل على سبيل المثال أنه يستطيع استيعاب 100 رزمة في الثانية. هناك ازدواجية مثيرة للاهتمام بين النوافذ والمعدَّل، حيث أن عدد الرزم (البايتات) في النافذة، مقسومًا على RTT، هو المعدل بالضبط. يشير حجم النافذة المكوَّن من 10 رزم و 100 ميلي ثانية RTT على سبيل المثال إلى أنه يُسمح للمرسل بالإرسال بمعدل 100 رزمة في الثانية. يرفع جهاز الاستقبال أو يخفض المعدل الذي يمكن للمرسل الإرسال به بفعالية من خلال زيادة أو تقليل حجم النافذة المعلن عنها. تُرَد هذه المعلومات مرةً أخرى إلى المرسل في حقل AdvertisedWindow من إشعار ACK كل جزء في بروتوكول TCP. تتمثل إحدى المشكلات الرئيسية في البروتوكول المستند إلى المعدل في عدد المرات التي يُرحَّل فيها المعدل المطلوب (والذي قد يتغير بمرور الوقت) إلى المصدر: هل هو لكل رزمة أم مرة واحدة لكل RTT أم عندما يتغير المعدل فقط؟ على الرغم من أننا قد ناقشنا للتو النافذة مقابل المعدل في سياق التحكم في التدفق، إلا أنها قضية متنازع عليها بشدة في سياق التحكم في الازدحام، والتي ستُناقش لاحقًا. بروتوكول QUIC أُنشِئ بروتوكول اتصالات إنترنت بروتوكول UDP السريعة Quick UDP Internet Connections أواختصارًا QUIC في Google في عام 2012، ولا يزال يخضع للتوحيد القياسي standardization في منظمة IETF في وقت كتابة هذا الكتاب، ولقد شهد بالفعل قدرًا معتدلًا من النشر (في بعض متصفحات الويب وعدد كبير من مواقع الويب الشائعة). حقيقة أنه كان ناجحًا إلى هذه الدرجة هي في حد ذاتها جزءٌ مثير للاهتمام من قصة QUIC، وكانت قابلية النشر التزامًا رئيسيًا لمصممي البروتوكول. يأتي الدافع وراء بروتوكول QUIC مباشرةً من النقاط التي أشرنا إليها أعلاه حول بروتوكول TCP: لقد تبين أن بعض قرارات التصميم غير مثالية لمجموعة من التطبيقات التي تعمل عبر بروتوكول TCP، كحركة مرور بروتوكول HTTP (الويب). أصبحت هذه المشكلات أوضح بمرور الوقت، نظرًا لعوامل مثل ظهور الشبكات اللاسلكية ذات زمن الاستجابة العالي، وتوافر شبكات متعددة لجهاز واحد (شبكة Wi-Fi والشبكة الخلوية على سبيل المثال)، والاستخدام المتزايد للتشفير واستيثاق الاتصالات على الويب. تستحق بعض قرارات تصميم بروتوكول QUIC الرئيسية المناقشة في حين أن وصفه الكامل خارج نطاقنا. إذا كان وقت استجابة الشبكة مرتفعًا (من رتبة مئات الميلي ثانية) فيمكن أن تزيد بسرعة بعض فترات RTT إزعاجًا واضحًا للمستخدم النهائي. يستغرق عادةً إنشاء جلسة HTTP عبر بروتوكول TCP مع تأمين طبقة النقل ثلاث رحلاتٍ ذهابًا وإيابًا (واحدة لتأسيس جلسة TCP واثنتان لإعداد معاملات التشفير) قبل إرسال رسالة HTTP الأولى. أدرك مصممو QUIC أنه يمكن تقليل هذا التأخير (وهو النتيجة المباشرة لنهج متعدد الطبقات لتصميم البروتوكول) بصورةٍ كبيرة إذا دُمِج إعداد الاتصال ومصافحات الأمان المطلوبة وحُسِّن لأدنى حد من وقت الذهاب والإياب. لاحظ أيضًا كيف قد يؤثر وجود واجهات متعددة للشبكة على التصميم. إذا فقد هاتفك المحمول اتصال Wi-Fi وتحتاج إلى التبديل إلى اتصال خلوي، سيتطلب ذلك عادةً مهلة TCP على اتصالٍ واحد وسلسلة جديدة من المصافحات على الاتصال الآخر. كان جعل الاتصال شيئًا يمكنه الاستمرار عبر اتصالات طبقة الشبكة المختلفة هدفًا تصميميًا آخر لبروتوكول QUIC. أخيرًا، يُعد نموذج تدفق البايتات الموثوق لبروتوكول TCP تطابقًا ضعيفًا مع طلب صفحة الويب، عند الحاجة إلى جلب العديد من الكائنات ويمكن البدء بعرض الصفحة قبل وصولها جميعًا. أحد الحلول لذلك هو فتح اتصالات TCP متعددة على التوازي، ولكن هذا الأسلوب (الذي اُستخدِم في الأيام الأولى للويب) له مجموعة من العيوب الخاصة به، لا سيما فيما يتعلق بالتحكم في الازدحام. ومن المثير للاهتمام أنه جرى اتخاذ العديد من قرارات التصميم التي شكّلت تحدياتٍ لنشر بروتوكول نقل جديد بحلول الوقت الذي ظهر فيه QUIC. والجدير بالذكر أن العديد من "الصناديق المتوسطة middleboxes" مثل الجدران النارية firewalls وNAT لديها فهم كافٍ لبروتوكولات النقل المنتشرة على نطاق واسع (TCP وUDP) بحيث لا يمكن الاعتماد عليها لتمرير بروتوكول نقل جديد. ونتيجة لذلك يتواجد بروتوكول QUIC في الواقع فوق بروتوكول UDP، أي أنه بروتوكول نقلٍ يعمل فوق بروتوكول نقل. يطبّق بروتوكول QUIC إنشاء اتصالٍ سريع مع التشفير والاستيثاق authentication في أول RTT، ويفضّل توفير معرّف اتصال على استمراره عبر التغييرات في الشبكة الأساسية. وهو يدعم تعدد إرسال عدة تدفقات على اتصال نقل واحد، لتجنب توقف رأس الخط الذي قد ينشأ عند إسقاط رزمةٍ واحدة بينما يستمر وصول البيانات المفيدة الأخرى. ويحافظ على خصائص تجنب الازدحام لبروتوكول TCP. بروتوكول QUIC هو التطور الأكثر إثارة للاهتمام في عالم بروتوكولات النقل. العديد من قيود بروتوكول TCP معروفةٌ منذ عقود، ولكن يمثّل بروتوكول QUIC واحدًا من أنحج الجهود حتى الآن للتركيز على نقطة مختلفة في مساحة التصميم. ويقدم دراسة حالة رائعة في النتائج غير المتوقعة للتصميمات متعددة الطبقات وفي تطور الإنترنت، نظرًا لأنه مستوحى من تجربة بروتوكول HTTP والويب، والتي نشأت بعد فترة طويلة من تأسيس بروتوكول TCP بشكل جيد في الإنترنت. بروتوكول TCP متعدد المسارات Multipath TCP ليس من الضروري دائمًا تحديد بروتوكول جديد إذا وجدت أن البروتوكول الحالي لا يخدم حالة استخدام معينة بشكل كافٍ. من الممكن في بعض الأحيان إجراء تغييرات جوهرية في كيفية تطبيق بروتوكول موجود، ولكن تظل وفية للمواصفات الأصلية. يعد بروتوكول Multipath TCP مثالًا على مثل هذه الحالة. تتمثل فكرة Multipath TCP في توجيه الرزم خلال مسارات متعددة عبر الإنترنت، باستخدام عنوانَي IP مختلفين لإحدى نقاط النهاية على سبيل المثال. يمكن أن يكون هذا مفيدًا بشكل خاص عند تسليم البيانات إلى جهازٍ محمول متصل بكل من شبكة Wi-Fi والشبكة الخلوية (وبالتالي يملك عنوانين IP فريدين). يمكن أن تواجه فقدانًا كبيرًا في الرزمة نظرًا لكون كلتا الشبكتين لاسلكيتين، لذا فإن القدرة على استخدامهما لحمل الرزم يمكن أن تحسّن تجربة المستخدم بصورة كبيرة. الحل هو أن يعيد الجانب المستلم من TCP بناء تدفق البايتات الأصلي بالترتيب قبل تمرير البيانات إلى التطبيق، والذي يظل غير مدرك أنه يجلس على بروتوكول Multipath TCP. (وهذا على عكس التطبيقات التي تفتح عمدًا اتصالين أو أكثر من اتصالات TCP للحصول على أداء أفضل). يبدو بروتوكول Multipath TCP بسيطًا، ولكنه من الصعب للغاية الحصول عليه بصورةٍ صحيحة لأنه يكسر العديد من الافتراضات حول كيفية تطبيق التحكم في تدفق TCP، وإعادة تجميع الجزء segment بالترتيب، والتحكم في الازدحام. نتركه كتمرينٍ لك لاستكشاف التفاصيل الدقيقة، حيث يُعد القيام بذلك طريقةً رائعة للتأكد من أن فهمك الأساسي لبروتوكول TCP سليم. ترجمة -وبتصرّف- للقسم Reliable Byte Stream من فصل ProtocolsEnd-to-End من كتاب Computer Networks: A Systems Approach. اقرأ أيضًا بروتوكولات طرف إلى طرف End-to-End Protocols في الشبكات الحاسوبيةالمقال السابق: تأسيس الشبكات الحاسوبية والتعرف على تطبيقاتها البرمجيات المستخدمة في بناء الشبكات الحاسوبية التوجيه Routing بين الأجهزة المتنقلة في الشبكات الحاسوبية دليل بصري لكيفية استخدام أنفاق SSH
-
- آلية الإرسال والبدائل
- تدفق بيانات
-
(و 3 أكثر)
موسوم في:
-
سنعمل في هذا المقال على تطوير خادم TCP متزامن يقوم بإنشاء أرقام عشوائية باستخدام حوالي 65 سطرًا من كود Go، إذ سأشرح كيفية تطوير خادم TCP متزامن، بلغة البرمجة Go، والتي تقوم بإرجاع أرقام عشوائية. إن لم تقرأ المقال السابق حول إنشاء كلمات مرور عشوائية وآمنة في Go، فننصحك بالرجوع إليه وقراءته أولًا. تعمل خوادم TCP و UDP بخدمة عملاء الشبكة في كل مكان عبر شبكات TCP / IP. لكل اتصال وارد من عميل TCP، سيقوم خادم TCP ببدء تشغيل goroutine جديد لمعالجة هذا الطلب. تستطيع إيجاد هذا المشروع concTCP.go على GitHub. التعامل مع اتصالات TCP يمكنك العثور على منطق البرنامج في دالة ()handleConnection بلغة Go، والذي يتم تنفيذه على النحو التالي: func handleConnection(c net.Conn) { fmt.Printf("Serving %s\n", c.RemoteAddr().String()) for { netData, err := bufio.NewReader(c).ReadString('\n') if err != nil { fmt.Println(err) return } temp := strings.TrimSpace(string(netData)) if temp == "STOP" { break } result := strconv.Itoa(random()) + "\n" c.Write([]byte(string(result))) } c.Close() } إذا أرسل عميل TCP سلسلة التعليمات "STOP"، فسيتم إنهاء برنامج Go أي goroutine الذي يخدم عميل TCP محدد؛ وإلا، سيرسل خادم TCP رقمًا عشوائيًا إلى عميل TCP. تضمن الحلقة for أن عميل TCP سيتم خدمته طالما يُتَطلب ذلك. تقرأ الحلقة for الموجودة في كود Go البيانات من عميل TCP سطرًا بسطر باستخدام ('bufio.NewReader(c).ReadString('\n وتُعيد إرسال البيانات باستخدام (((c.Write([]byte(string(result. التزامن تنفيذ دالة ()main، يُعطي أمرًا لخادم TCP لبدء تشغيل برنامج goroutine جديد في كل مرة يتعين عليه خدمة عميل TCP: func main() { arguments := os.Args if len(arguments) == 1 { fmt.Println("Please provide a port number!") return } PORT := ":" + arguments[1] l, err := net.Listen("tcp4", PORT) if err != nil { fmt.Println(err) return } defer l.Close() rand.Seed(time.Now().Unix()) for { c, err := l.Accept() if err != nil { fmt.Println(err) return } go handleConnection(c) } } أولاً، تتأكد ()main من أن البرنامج يحتوي على وسيطة سطر أوامر واحدة على الأقل. لاحظ أن الكود الموجود لا يتحقق مما إذا كانت وسيطة سطر الأوامر المحددة هي رقم مَنفذ TCP صالح أم لا. ومع ذلك، إذا لم تكن القيمة المحددة رقم منفذ TCP صالحًا، فسوف يفشل استدعاء ()net.Listen مع ظهور رسالة خطأ مشابهة لما يلي: $ go run concTCP.go 12a listen tcp4: lookup tcp4/12a: nodename nor servname provided, or not known $ go run concTCP.go -10 listen tcp4: address -10: invalid port يتم استخدام استدعاء ()net.Listen لإخبار برنامج Go بقبول اتصالات الشبكة وبالتالي كخادم. قيمة الإرجاع ()net.Listen هي من النوع net.Conn، والتي تنفذ واجهات io.Reader و io.Writer. تقوم الدالة ()main أيضًا باستدعاء الدالة ()rand.seed لتهيئة مُنشئ الأرقام العشوائية. أخيرًا، تُتيح حلقة for للبرنامج الحفاظ على قبول عملاء TCP الجدد باستخدام ()accept والتي سيتم معالجتها بواسطة نسخ الدالة ()handleConnection، والتي يتم تنفيذها على شكل goroutines. أول معامل للدالة ()net.Listen يُحدد المعامل الأول من الدالة ()net.Listen نوع الشبكة التي سيتم استخدامها، بينما يُحدد المعامل الثاني عنوان الخادم بالإضافة إلى رقم المَنفذ الذي سيستمع إليه الخادم. القيم الصالحة للمُعامل الأول هي: tcp, tcp4 (IPv4-only), tcp6 (IPv6-only), udp, udp4 (IPv4- only), udp6 (IPv6-only), ip, ip4 (IPv4-only), ip6 (IPv6-only), Unix (Unix sockets), Unixgram, Unixpacket فعالية خادم TCP المتزامن يتطلب concTCP.go وسيطة سطر أوامر واحدة، وهي رقم المَنفذ الذي سيستمع إليه. سيكون الناتج الذي ستحصل عليه من concTCP.go عند خدمة عملاء TCP مشابهًا لما يلي: $ go run concTCP.go 8001 Serving 127.0.0.1:62554 Serving 127.0.0.1:62556 يمكن لناتج (1)netStat التحقق من أن concTCP.go يخدم العديد من عملاء TCP أثناء الاستماع لمزيد من الاتصالات: $ netstat -anp TCP | grep 8001 tcp4 0 0 127.0.0.1.8001 127.0.0.1.62556 ESTABLISHED tcp4 0 0 127.0.0.1.62556 127.0.0.1.8001 ESTABLISHED tcp4 0 0 127.0.0.1.8001 127.0.0.1.62554 ESTABLISHED tcp4 0 0 127.0.0.1.62554 127.0.0.1.8001 ESTABLISHED tcp4 0 0 *.8001 *.* LISTEN يعلمنا السطر الأخير من ناتج الأمر السابق أن هناك عملية تستمع إلى المَنفذ 8001، مما يعني أنه لا يزال بإمكانك الاتصال بمنفذ TCP رقم 8001. يتحقق أول سطرين من وجود اتصال شبكة TCP ثابت يستخدم أرقام المنافذ 8001 و 62556. وبالمثل، يتحقق السطران الثالث والرابع من وجود اتصال TCP آخر يستخدم أرقام المنافذ 8001 و 62554. تُظهر هذه الصورة ناتج concTCP.go عند خدمة العديد من عملاء TCP: بشكل مشابه، تُظهر الصورة التالية الناتج من عميلين من TCP يتم تنفيذهما باستخدام (1)nc: يُمكنك ايجاد معلومات أكثر عن (1)nc، والتي تُدعى أيضًا (1)netcat على ويكيبيديا. الملخص لقد تعلمت للتو كيفية تطوير خادم TCP متزامن يقوم بإنشاء أرقام عشوائية باستخدام حوالي 65 سطرًا من كود Go، وهو أمر مثير للإعجاب جدًا! إذا كنت تريد أن يقوم خادم TCP بمهمة مختلفة، فقط قم بتغيير تنفيذ الدالة ()handleConnection. ترجمة وبتصرّف للمقال Build a concurrent TCP server in Go، لصاحبه Mihalis Tsoukalos.
-
إن بروتوكول التحكم في نقل البيانات (Transmission Control Protocol) وبروتوكول الإنترنت (Internet Protocol) المسمى اختصارًا TCP/IP هو معيار يضم مجموعة بروتوكولاتٍ مطورةً في نهاية السبعينات من القرن الماضي من وكالة مشاريع أبحاث الدفاع المتقدمة (Defense Advanced Research Projects Agency [DARPA])، كطرق للتواصل بين مختلف أنواع الحواسيب وشبكات الحواسيب؛ إن بروتوكول TCP/IP هو العصب المحرك للإنترنت، وهذا ما يجعله أشهر مجموعة بروتوكولات شبكيّة على وجه الأرض. TCP/IP المكونان الرئيسيان من مكونات TCP/IP يتعاملان مع مختلف نواحي شبكة الحاسوب؛ بروتوكول الإنترنت -جزء «IP» من TCP/IP- هو بروتوكول عديم الاتصال (connectionless) يتعامل مع طريقة توجيه (routing) الرزم الشبكية مستخدمًا ما يسمى «IP Datagram» كوحدة رئيسية للمعلومات الشبكية؛ تتكون IP Datagram من ترويسة، يتبعها رسالة. إن بروتوكول التحكم في نقل البيانات هو «TCP» من TCP/IP، ويُمكِّن مضيفي الشبكة من إنشاء اتصالاتٍ يستطيعون استخدامها لتبادل مجاري البيانات (data streams)؛ ويَضمَن أيضًا بروتوكول TCP أن البيانات التي أُرسِلَت بواسطة تلك الاتصالات ستُسَلَّم وتصل إلى مضيف الشبكة المُستقبِل كما أُرسِلَت تمامًا وبنفس الترتيب من المُرسِل. دورة علوم الحاسوب دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب اشترك الآن ضبط TCP/IP يتكون ضبط TCP/IP من عدِّة عناصر التي يمكن أن تُغيَّر بتعديل ملفات الإعدادات الملائمة، أو باستخدام حلول مثل خادوم «بروتوكول ضبط المضيف الديناميكي» (Dynamic Host Configuration Protocol [DHCP])، الذي يمكن أن يُضبَط لتوفير إعدادات TCP/IP صالحة لعملاء الشبكة تلقائيًا، يجب أن تُضبط قيم تلك الإعدادات ضبطًا صحيحًا لكي تساعد في عمل الشبكة عملًا سليمًا في نظام أوبنتو عندك. عناصر الضبط الخاصة ببروتوكول TCP/IP ومعانيها هي: عنوان IP: هو سلسة نصية فريدة يُعبَّر عنها بأربع مجموعات من أرقام تتراوح بين الصفر (0)، ومئتان وخمسٌ وخمسون (255)، مفصولةٌ بنقط، وكل أربعة أرقام تمثل ثمانية (8) بتات من العنوان الذي يكون طوله الكامل اثنان وثلاثون (32) بتًا، تُسمى هذه الصيغة باسم «dotted quad notation». قناع الشبكة: قناع الشبكة الفرعية (أو باختصار: قناع الشبكة [netmask])، هو قناع ثنائي يفصل قسم عنوان IP المهم للشبكة، عن قسم العنوان المهم للشبكة الفرعية (Subnetwork)؛ على سبيل المثال، في شبكة ذات الفئة C (Class C network)، قناع الشبكة الافتراضي هو 255.255.255.0، الذي يحجز أول ثلاثة بايتات من عنوان IP للشبكة، ويسمح لآخر بايت من عنوان IP أن يبقى متاحًا لتحديد المضيفين على الشبكة الفرعية. عنوان الشبكة: يمثل عنوان الشبكة (Network Address) البايتات اللازمة لتمثيل الجزء الخاص من الشبكة من عنوان IP، على سبيل المثال، المضيف صاحب العنوان 12.128.1.2 في شبكة ذات الفئة A يستطيع استخدام 12.0.0.0 كعنوان الشبكة، حيث يمثل الرقم 12 البايت الأول من عنوان IP (جزء الشبكة)، وبقية الأصفار في البايتات الثلاثة المتبقية تمثل قيم مضيفين محتملين في الشبكة؛ وفي مضيف شبكة يستخدم عنوان IP الخاص 192.168.1.100 الذي يستخدم بدوره عنوان الشبكة 192.168.1.0 الذي يحدد أول ثلاثة بايتات من شبكة ذات الفئة C والتي هي 192.168.1، وصفرًا الذي يُمثِّل جميع القيم المحتملة للمضيفين على الشبكة. عنوان البث: عنوان البث (Broadcast Address) هو عنوان IP يسمح لبيانات الشبكة بأن تُرسَل إلى كل المضيفين معًا في شبكة محلية بدلًا من إرسالها لمضيف محدد. العنوان القياسي العام للبث لشبكات IP هو 255.255.255.255، لكن لا يمكن استخدام هذا العنوان لبث الرسائل لكل مضيف على شبكة الإنترنت، لأن الموجهات (routers) تحجبها؛ ومن الملائم أن يُضبَط عنوان البث لمطابقة شبكة فرعية محددة، على سبيل المثال، في شبكة خاصة ذات الفئة C، أي 192.168.1.0، يكون عنوان البث 192.168.1.255؛ تُولَّد رسائل البث عادةً من بروتوكولات شبكيّة مثل بروتوكول استبيان العناوين (Address Resolution Protocol [ARP])، وبروتوكول معلومات التوجيه (Routing Information Protocol [RIP]). عنوان البوابة: إن عنوان البوابة (Gateway Address) هو عنوان IP الذي يمكن الوصول عبره إلى شبكة معينة أو إلى مضيف معين على شبكة؛ فإذا أراد أحد مضيفي الشبكة التواصل مع مضيفٍ آخر، ولكن المضيف الآخر ليس على نفس الشبكة، فيجب عندئذٍ استخدام البوابة؛ في حالات عديدة، يكون عنوان البوابة في شبكةٍ ما هو الموجه (router) على تلك الشبكة، الذي بدوره يُمرِّر البيانات إلى بقية الشبكات أو المضيفين كمضيفي الإنترنت على سبيل المثال. يجب أن تكون قيمة عنوان البوابة صحيحةً، وإلا فلن يستطيع نظامك الوصول إلى أي مضيف خارج حدود شبكته نفسها. عنوان خادوم الأسماء: عناوين خادوم الأسماء (Nameserver Addresses) تمثل عناوين IP لخواديم خدمة أسماء المضيفين DNS، التي تستطيع استبيان (resolve) أسماء مضيفي الشبكة وتحويلها إلى عناوين IP؛ هنالك ثلاث طبقات من عناوين خادوم الأسماء، التي يمكن أن تُحدَّد بترتيب استخدامها: خادوم الأسماء الرئيسي (Primary)، وخادوم الأسماء الثانوي (Secondary)، وخادوم الأسماء الثلاثي (Tertiary)، ولكي يستطيع نظامك استبيان أسماء أسماء مضيفي الشبكة وتحويلها إلى عناوين IP الموافقة لهم، فيجب عليك تحديد عناوين خادوم الأسماء الذي تثق به لاستخدامه في ضبط TCP/IP لنظامك؛ في حالاتٍ عديدة، تُوفَّر هذه العناوين من موزع خدمة شبكتك، لكن هنالك خواديم أسماء عديدة متوفرة مجانًا للعموم، كخواديم Level3 (Verizon) بعناوين IP تتراوح بين 4.2.2.1 إلى 4.2.2.6. تنبيه: إن عنوان IP، وقناع الشبكة، وعنوان الشبكة، وعنوان البث، وعنوان البوابة تُحدَّد عادةً بالإمكان الملائمة لها في ملف /etc/network/interfaces، عناوين خادوم الأسماء تُحدَّد عادة في قسم nameserver في ملف /etc/resolve.conf، للمزيد من المعلومات، راجع صفحة الدليل لكلٍ من interfaces و resolv.conf على التوالي وبالترتيب، وذلك بكتابة الأوامر الآتية في محث الطرفية: للوصول إلى صفحة دليل interfaces، اكتب الأمر الآتي: man interfaces وللوصول إلى صفحة دليل resolv.conf: man resolv.conf توجيه IP يمثِّل توجيه IP (IP Routing) الوسائل اللازمة لتحديد واكتشاف الطرق في شبكات TCP/IP بالإضافة إلى تحديد بيانات الشبكة التي ستُرسَل، يَستخدِم التوجيه ما يسمى «جداول التوجيه» (routing tables) لإدارة تمرير رزم بيانات الشبكة من مصدرها إلى وجهتها؛ وذلك عادة بواسطة عقد شبكيّة وسيطة تسمى «موجهات» (routers)؛ وهنالك نوعان رئيسيان من توجيه IP: التوجيه الثابت (static routing)، والتوجيه الديناميكي (dynamic routing). يشتمل التوجيه الثابت على إضافة توجيهات IP يدويًّا إلى جدول توجيهات النظام، ويتم ذلك عادةً بتعديل جدول التوجيهات باستخدام الأمر route؛ يتمتع التوجيه الثابت بعدِّة مزايا تميزه عن التوجيه الديناميكي، كسهولة استخدامه في الشبكات الصغيرة، وقابلية التوقع (يُحسَب جدول التوجيهات مسبقًا دائمًا، وهذا ما يؤدي إلى استخدام نفس المسار في كل مرة)، ويؤدي إلى حِملٍ قليل على الموجهات الأخرى ووصلات الشبكة نتيجةً لعدم استخدام بروتوكولات التوجيه الديناميكي؛ لكن يواجه التوجيه الثابت بعض الصعوبات أيضًا؛ فعلى سبيل المثال، التوجيهُ الثابتُ محدودٌ للشبكات الصغيرة، ولا يمكن أن يتوسَّع توسعًا سهلًا، ويصعب عليه التأقلم مع نقصان أو فشل معدات الشبكة في الطريق المسلوك نتيجةً للطبيعة الثابتة لذاك الطريق. يُعتَمَد على التوجيه الديناميكي في الشبكات الكبيرة ذات احتمالات عديدة للطرق الشبكية المسلوكة من المصدر إلى الوجهة، وتُستخدَم بروتوكولات توجيه خاصة، كبروتوكول معلومات الموجه (Router Information Protocol [RIP])، الذي يتولَّى أمر التعديلات التلقائية في جداول التوجيه، مما يجعل من التوجيه الديناميكي أمرًا ممكنًا؛ وللتوجيه الديناميكي مزايا عدّة عن التوجيه الثابت، كإمكانية التوسع بسهولة، والتأقلم مع نقصان أو فشل معدات الشبكة خلال الطريق المسلوك في الشبكة، بالإضافة إلى الحاجة لإعداداتٍ قليلةٍ نسبيًا لجداول التوجيه، ﻷن الموجهات تعلم عن وجود وتوفر بعضها بعضًا؛ وهذه الطريقة تمنع حدوث مشاكل في التوجيه نتيجةً لخطأ بشري في جداول التوجيه. لكن التوجيه الديناميكي ليس كاملًا، ويأتي مع عيوب، كالتعقيد، والحِمل الزائد على الشبكة بسبب التواصل بين الموجهات، التي لا تفيد المستخدمين المباشرين فوريًا، وتستهلك التراسل الشبكي. بروتوكولَي TCP و UDP إن بروتوكول TCP هو بروتوكول مبني على الاتصال (connection-based)، ويوفر آليةً لتصحيح الأخطاء، وضمانةً لتسليم البيانات عبر ما يُعرَف بالمصطلح «التحكم في الجريان» (flow control)، يُحدِّد التحكم في الجريان متى يجب إيقاف نقل البيانات، وإعادة إرسال الرزم التي أُرسِلَت سابقًا والتي واجهة مشاكل كالتصادمات (collisions)؛ إذ أنَّ التأكيد على الوصول الدقيق والكامل للبيانات عبر بروتوكول TCP هو أمر جوهري في عملية تبادل البيانات المهمة كالتحويلات في قواعد البيانات. أما بروتوكول UDP (User Datagram Protocol) على الجهة الأخرى، هو بروتوكول عديم الاتصال (connectionless)، الذي نادرًا ما يتعامل مع عمليات نقل البيانات المهمة لأنه يفتقر إلى التحكم في جريان البيانات أو أيّة طريقة أخرى للتأكد من توصيل البيانات عمليًا؛ لكن بروتوكول UDP يُستخدَم استخدامًا شائعًا في التطبيقات كتدفق (streaming) الصوت والصورة، حيث أنه أسرع بكثير من TCP ﻷنه لا يحتوي على آليةٍ لتصحيح الأخطاء والتحكم في الجريان، وفي الأماكن التي لا يهم فيها فقدان بعض الرزم الشبكية كثيرًا. بروتوكول ICMP إن بروتوكول ICMP (Internet Control Messaging Protocol) هو إضافة إلى بروتوكول الإنترنت (IP) الذي يُعرَّف في RFC (Request For Comments) ذي الرقم #792 ويدعم التحكم في احتواء الرزم الشبكية والأخطاء ورسائل المعلومات، يُستخدَم بروتوكول ICMP بتطبيقات شبكيّة كأداة ping، التي تستطيع تحديد إذا ما كان جهازٌ ما متاحًا على الشبكة، أمثلة عن رسالة الخطأ المُعادَة من ICMP -التي تكون مفيدةً لمضيفي الشبكة وللأجهزة كالموجهات- تتضمن رسالتَي «Destination Unreachable» و «Time Exceeded». العفاريت العفاريت (Daemons) هي تطبيقات نظام خاصة التي تعمل عادةً عملًا دائمًا في الخلفية، وتنتظر طلبياتٍ للوظائف التي توفرها من التطبيقات الأخرى، يتمحور عمل العديد من العفاريت حول الشبكة، وبالتالي فإن عددًا كبيرًا من العفاريت التي تعمل في الخلفية في نظام أوبنتو تُوفِّر وظائف تتعلق بالشبكة؛ بعض الأمثلة عن عفاريت الشبكة تتضمن «عفريت بروتوكول نقل النص الفائق» (HyperText Transport Protocol Daemon [httpd])، الذي يوفر وظيفة خادوم الويب؛ و «عفريت الصدفة الآمنة» (Secure SHell Daemon [sshd])، الذي يوفر طريقةً للدخول الآمن عن بُعد وإمكانيات نقل الملفات؛ و «عفريت بروتوكول الوصول إلى رسائل الإنترنت» (Internet Message Access Protocol Daemon [imapd]) الذي يوفر خدمات البريد الإلكتروني... مصادر تتوفر صفحات دليلٍ لبروتوكولي TCP و IP التي تحتوي على معلومات قيمّة. راجع أيضًا المصدر الآتي من IBM: «TCP/IP Tutorial and Technical Overview». مصدرٌ أخرى هو كتاب «TCP/IP Network Administration» من O'Reilly. ترجمة -وبتصرف- للمقال Ubuntu Server Guide: Networking TCP/IP.
-
عرضنا في الجزء الأول من هذا الدّليل بعض المفاهيم الأساسيّة في مجال الشّبكات. نستكمل الحديث في هذا المقال بالتطرّق إلى ماهيّة الواجهات في الشّبكة والبروتوكولات المستخدَمة لربط الشّبكات. الواجهاتالواجهات هي نقاط الاتّصال بالنّسبة لحاسوبك. تُربَط كلّ واجهة بجهاز طرفيّ ملموس أو افتراضيّ. توجد عادةً واجهة شبكة قابلة للإعداد لكلّ بطاقة Ethernet أو بطاقة شبكة لا سلكيّة على الخادوم. تُعرَّف واجهة شبكة افتراضيّة تُسمّى loopback (الاسترجاع) أو localhost (المستضيف المحلّي) لكلّ بطاقة شبكة. تُستخدَم هذه الواجهة لتوصيل العمليّات أو التّطبيقات العاملة على نفس الجهاز في ما بينها. تظهر هذه الواجهة في العديد من الأدوات باسم lo. يُعدّ مدراء الشّبكات في الغالب واجهة لخدمة البيانات القادمة من شبكة الإنترنت وأخرى للشّبكة المحليّة أو الخاصّة. على سبيل المثال، يضبُط مزّودو الخدمات السّحابيّة Cloud services الخواديم الخاصّة الافتراضيّة Virtual private server, VPS للعمل بواجهتيْ شبكة (إضافة إلى الواجهة المحليّة lo): الأولى باسم eth0 مضبوطة لمعالجة البيانات القادمة من الإنترنت، والثّانيّة eth1 للاتّصال بالشّبكة الخاصّة بمزوّد الخدمة. البروتوكولاتيعمل ربط الشّبكات عن طريق تركيب مجموعة من البروتوكولات فوق بعضها. بهذه الطّريقة يُمكن إرسال قطعة بيانات باستخدام بروتوكولات مختلفة يغلّف كلٌّ منها الآخر. سنعرض لبعض البروتوكولات شائعة الاستخدام مع محاولة شرح الفروق في ما بينها إضافةً إلى السّيّاق والمستوى الّذي تتدخّل فيه. نبدأ بالبروتوكولات الّتي تعمل في الطّبقات الدّنيا من الشّبكة ونصعد إلى البروتوكولات الأكثر تجريدًا (الطّبقات العليا). 1- التّحكّم في الوصول إلى الوسائط Media Access Control, MACيُستخدَم لتمييز الأجهزة الطّرفيّة. يُفترَض أن يكون لدى كلّ جهاز طرفيّ عنوان وحيد يُمنَح له عند تصنيعه؛ يُسمَّى عنوان MAC، ويُمكّن من تعريفه ضمن الشّبكة. تسمح عنونة العتاد عن طريق عناوين MAC بالإشارة إلى الجهاز الطّرفيّ بقيمة وحيدة لا تتغيّر حتّى ولو استخدمت البرامج اسمًا آخر لتعريف الجهاز أثناء عملها. يعمل بروتوكول التّحكّم في الوصول إلى الوسائط ضمن طبقة الوصلة، وربّما يكون البروتوكول الوحيد من هذا المستوى الّذي ستجد الفرصة للتّعامل معه دوريًّا. 2- بروتوكول الإنترنت Internet protocol, IPوهو أحد البروتوكولات الأساسيّة الّتي تعمل عليها شبكة الإنترنت. يعمل بروتوكول الإنترنت مع عناوين IP، وهي فريدة في كلّ شبكة، ممّا يسمح للأجهزة بالتّواصل في ما بينها عبر الشّبكة. يُنفَّذ ابروتكول الإنترنت على مستوى طبقة التّوصيل ضمن نموذج TCP/IP. يجب عند ربط الشّبكات في ما بينها، توجيه البيانات عند عبورها حدود الشّبكة. يفترض ابروتكول الإنترنت أنّ الشّبكة غير موثوقة؛ ووجود مسارات متعدّدة يُمكن التّغيير ديناميكيًّا بينها للوصول إلى الوجهة. يُنفَّذ ابرتوكول IP عمليًّا بصيّغ عديدة أشهرها اليوم هو الإصدار الرّابع من البروتوكول IPv4، إلاّ أنّ الإصدار السّادس IPv6 يزداد شعبيةً يومًا بعد يوم نظرًا للشّح المتزايد في عناوين الإصدار الرابع المتوفّرة، والتّحسينات المُضافة إلى إمكانيّات البروتوكول. 3- بروتوكول رسائل التّحكّم في الإنترنت Internet control message protocol, ICMPيُستخدَم لإرسال رسائل بين الأجهزة الطّرفيّة للإشعار بحالتها من حيث التّوفّر ووجود أخطاء وطبيعتها. تُستخدَم حزم ICMP في أدوات تشخيص الشّبكة مثل traceroute وping. تُرسَل حزم ICMP عادةً عند ما تواجه حزمة من نوعيّة أخرى مشكلة أثناء النّقل، أيّ أنّ حزم ICMP هي في الواقع آليّة للتّعليق على الاتّصالات عبر الشّبكة. 4- بروتوكول التّحكّم في الإرسال Transmission control protocol, TCPيُؤسّس بروتوكول TCP لاتّصالات موثوقة ويعمل في طبقة النّقل من نموذج TCP/IP. يغلّف بروتوكول TCP البياناتِ ضمن حزم ثمّ يرسلها إلى المستقبِل على الطّرف الآخر من الاتّصال عبر الوسائل المتوفّرة في الطّبقات الأدنى. يتأكّد ابروتوكول TCP في الطّرف المستقبل من عدم وجود أخطاء أثناء النّقل وقد يُعيد طلب بعض الحزم ثمّ يُجمّع البيانات في رسالة واحدة لإرسالها إلى طبقة التّطبيق. يُنشئ بروتوكول TCP، قبل البدء بنقل البيانات، اتّصالًا عبر آليّة تُعرَف بالمصافحة الثّلاثية Three-way handshake. تمكّن هذه الآلية طرفيْ الاتّصال من الإقرار باستلام الطّلبات والاتّفاق على طريقة لضمان موثوقيّة البيانات. بعد اكتمال نقل البيانات يُنهى الاتّصال عبر آليّة مشابهة تُدعَى المصافحة الرّباعيّة. تعتمد الكثير من استخدامات الإنترنت على بروتوكول TCP. نذكر منها الويب WWW، نقل الملفّات عبر FTP، والبريد الإلكتروني. يُمكن القول دون كثير من المجازفة أنّ الإنترنت الّتي نعرفها اليوم لم تكن لتوجد لولا ابروتوكول TCP. 5- بروتوكول مخطَّط بيانات المستخدِم User datagram protocol, UDPيعمل مثل TCP في طبقة النّقل. الفرق الأساسيّ بين الاثنين أنّ UDP ،على العكس من TCP، لا يضمن موثوقيّة النّقل؛ فلا يتأكّد من استلام الطّرف الآخر في الاتّصال للبيانات. قد يبدو من الوهلة الأولى ألّا فائدة من بروتوكول UDP، فهو لا يوفّر آليّة لضمان الموثوقيّة؛ إلّا أنّه مهمّ جدًّا لتأديّة بعض الوظائف. بروتوكول UDP أسرع بكثير من TCP، فهو لا يحتاج للانتظار للتّأكّد من استلام حزمة البيانات، وإعادة إرسالها في حال عدم الاستلام. كما أنّه لا يؤسّس لاتّصال مع وِجهة البيانات بل يكتفي بإلقائها إليه ولا يهتمّ هل يقبلها أم لا. تُفيد سهولة المعاملة الّتي يعرّفها UDP في التّواصل غير المعقَّد مثل طلب موارد على الشّبكة. لا يحتفظ ابروتوكول بمعلومات عن حالة الاتّصال ممّا يجعل منه خيّارًا مناسبًا لإرسال البيانات من جهاز واحد إلى عملاء عديدين في الوقت الحقيقي Real time clients. تجعل هذه الميزات من UDP الخيّار الأمثل لبرامج VoIP (الصّوت عبر ابروتوكول الإنترنت، Voice over IP)، الألعاب، والتّطبيقات الأخرى الّتي لا تحتمل الانتظار. 6- بروتوكول نقل النّصوص التّشعبيّة Hypertext transfer protocol, HTTPيعرَّف هذا البروتوكول على مستوى طبقة التّطبيق، ويكوّن الأساس للتّواصل عبر الويب. يعرّف HTTP دوالّ مختلفة لإخبار النّظام البعيد مالّذي يطلُبه المستخدِم. نذكر منها على سبيل المثال POST، GET و DELETE الّتي تتعامل كلّها مع البيانات المطلوبة ولكنّ بطُرق مختلفة. 7- بروتوكول نقل الملفّات File transfer protocolيعمل على مستوى طبقة التّطبيق، ويوفّر طريقة لنقل ملفّات كاملة من مستضيف إلى آخر. يجب الانتباه إلى أنّ بروتوكول FTP غير آمن ويجب ألّا يُستخدَم في أي شبكة معروضة للعموم إلّا إذا كان على خادوم لا يقبل سوى تنزيل الملفّات. 8- نظام أسماء النّطاقات Domain name system, DNSيُنفَّذ على مستوى طبقة التّطبيق من أجل تعريف آليّة توفّر تسميّات يسهُل تذكّرها للموارد على شبكة الإنترنت. تعطي هذه الآليّة إمكانيّة ربط اسم نطاق بعنوان IP وتسمح بتصفّح موقع عبر إدخال اسمه في المتصفّح. للمزيد راجع مقال مقدّمة إلى مُصطَلحات وعناصر ومفاهيم نظام أسماء النطاقات 9- بروتوكول الصّدفة الآمنة Secure Shell, SSHيعمل بروتوكول SSH على مستوى طبقة التّطبيق ويُستخدَم للتّواصل مع خادوم بعيد بطريقة آمنة تُعمّي Encrypt البيانات. تعتمد تقنيّات عديدة على SSH نظرًا لتوفّره على التّعميّة من طرف إلى طرف End-to-end وشيوع استخدامه. توجد الكثير من البروتوكولات الأخرى المهمّة الّتي لم تُذكَر في هذا الدّرس؛ إلّا أنّ المذكور منها هنا يُعطي نظرة عامّة حول أهم التّقنيّات الّتي تجعل من الإنترنت واقعًا وتسمح للأجهزة بالتّواصل في ما بينها. خاتمةيجب أن تُدرك بانتهاء هذا الدّليل بعض المفهيم الأساسيّة لعمل الشّبكات ممّا يمنحك القدرة على فهم كيف تتواصل مختلف عناصر الشّبكات في ما بينها؛ الأمر الّذي يُساعدك على فهم مقالات أخرى عن الموضوع أو مستندات التّوثيق الموجودة في النّظام. ترجمة بتصرّف لمقال An Introduction to Networking Terminology, Interfaces, and Protocols.
-
- أساسيات في networking
- udp
- (و 5 أكثر)
-
يُعدّ إعداد وربط الشّبكات من الأمور المهمّة لكلّ من يريد إدارة الخواديم. ليس إعداد الشّبكات فقط أساسيًّا لتوفير خدمات على الويب ولكنّه يمنح أيضًا إدراكًا يُساعد في تشخيص المشاكل. يقدّم هذا الدّليل، المكوَّن من جزأيْن، نظرة عامّة على المصطلحات الأكثر شيوعًا في مجال ربط الشّبكات Networking؛ إذ سيتطرّق إلى المفاهيم القاعديّة، والبروتوكولات الأكثر انتشارًا؛ إضافةً إلى مسؤوليّات الطّبقات Layers الموجودة في الشّبكة وخصائصها. رغم أنّ هذا الدّليل مستقلّ عن نظام التّشغيل المُستخدَم، إلّا أنّه سيكون مفيدًا جدًّا عند إضافة خدمات وميزات تستخدم الشّبكة على خادومك. مصطلحات الشّبكاتيجب، قبل الدّخول في عمق الموضوع، تعريفُ بعض المصطلحات الشّائعة الّتي ستقرأها في هذا الدّليل أو أيّ دليل آخر أو توثيق يتعلّق بربط الشّبكات. اتّصال Connection: يُحيل الاتّصال، ضمن مجال الشّبكات، إلى أجزاء مترابطة من المعلومات تُنقَل عبر الشّبكة. يُستنتج من ذلك أنّ الاتّصال عمومًا يُنشَأ قبل الشّروع في نقل البيانات (باتّباع إجراءات مُعرَّفة في ابروتوكول)، ثمّ يُفكَّك - أي الاتّصال - بعد الانتهاء من نقل البيانات. حزمة Packet: وهي الوحدة الصّغرى المنقولة عبر الشّبكة. تغلّف الحزمُ قطعَ البيانات لنقلها من طرف إلى آخر أثناء التّواصل عبر الشّبكة. لدى الحزمة ترويسة Header تحوي معلومات عن الحزمة؛ منها: المصدَر والوِجهة، الختم الزّمنيّ Timestamp، القفزات Hops (أجزاء المسار بين المصدَر والوِجهة)،… إلخ. بينما يحوي الجزء الأكبر من الحزمة البيانات الفعلية المنقولة، ويُسمَّى أحيانًا بالمتن Body أو الحمولة Payload. واجهة شبكة Network interface: يُمكن أن تُحيل واجهة شبكة إلى أيّ نوع من الرّبط بين البرمجيّات Software والعتاد Hardware. على سبيل المثال، إذا كانت لدى الخادوم بطاقتا شبكة، فيُمكن التّحكّم في كلّ واحدة منهما وإعدادها بشكل مستقلّ عن طريق إعداد الواجهة المرتبطة بها.يُمكن أن تكون واجهة الشّبكة مرتبطة بجهاز طرفيّ Device ملموس، أو أن تكون تمثيلًا لواجهة افتراضيّة. الجهاز الطّرفي loopback (يُستخدم للتّخاطب بين البرامج الموجودة على نفس الجهاز) مثال على الواجهات الافتراضيّة. شبكة منطقة محليّة Local area network,LAN: يُطلَق عليها أحيانًا الشّبكة المحليّة. تُشير إلى شبكة - أو جزء من شبكة - لا يُتاح لعموم المستخدمين عبر الإنترنت الوصول إليها. الشّبكة الموجودة في المنزل أو المكتب مثال على الشّبكات المحليّة. شبكة واسعة Wide area network, WAN: وتعني شبكة أكثر اتّساعًا بكثير من شبكة محليّة. يُستخدَم مصطلح الشّبكة الواسعة أحيانًا للدّلالة على شبكة الإنترنت ككلّ، رغم أنّه يُشير في الأصل إلى الشّبكات الواسعة والمتفرّقة عمومًا. إذا وُصِفت واجهة بأنّها متّصلة بشبكة واسعة (WAN) فالمقصود - عادةً - هو أنّها متّصلة بالإنترنت. ابروتوكول Protocol: البروتوكول هو مجموعة من القواعد والمعايير Standards الّتي تعرّف لغةً يُمكن للأجهزة الطّرفيّة استخدامُها للتّخاطب. تُستخدَم ابروتوكولات عديدة في ربط الشّبكات، وتُنفَّذ عادةً على هيئة طبقات مختلفة.أمثلة على ابروتوكولات المستويات الدّنيا: IP، UDP ، TCP وICMP. الأمثلة التّاليّة هي لتطبيقات مبنيّة على طبقات من البروتكولات الأدنى مستوى: HTTP (للوصول إلى صفحات الويب)، TLS/SSL، SSH وFTP. منفذ Port: المنفذ هو عنوان ضمن الجهاز يُمكن ربطه ببرنامج محدّد. المنفذ ليس واجهة ملموسة أو موقِعًا، بل هو طريقة تجعل من الجهاز (الخادوم) قادرًا على التّواصل باستخدام أكثر من تطبيق. جدار ناريّ Firewall: الجدار النّاريّ هو برنامج يُقرّر السّماح لحركة البيانات - القادمة إلى الخادوم أو الخارجة منه - بالمرور أو يمنعها من ذلك. يعمل الجدار النّاري اعتمادًا على قواعد تحدّد نوعيّة البيانات المقبولة والمنافذ المسموح للبيانات بالمرور عبرها. تحظر الجدران النّارية عادةً منافذ الخادوم غير المستخدمة من طرف أيّ تطبيق. ترجمة عناوين الشّبكة Network address translation, NAT: وهي طريقة لإرسال الطّلبات القادمة إلى خادوم توجيه Routing إلى الأجهزة الطّرفيّة المُناسبة أو إلى الخواديم داخل الشّبكة المحليّة الّتي لديها معلومات عن وِجهة الطّلبات. تُستخدم ترجمة عناوين الشّبكة في الشّبكات المحليّة لتوجيه طلبات قادمة على نفس عنوان IP إلى الخواديم الخلفيّة المناسبة. الشّبكات الخاصّة الافتراضيّة Virtual private network, VPN: الشّبكات الخاصّة الافتراضيّة هي طريقة لتوصيل شبكات محليّة مختلفة عبر الإنترنت، مع الحفاظ على الخصوصيّة. تُستخدم هذه الطّريقة لتوصيل أنظمة متباعدة كما لو كانت في نفس الشّبكة المحليّة، لأسباب أمنيّة غالبًا. يجب أن تكون لديك الآن نبذة عن المفاهيم الأساسيّة في مجال ربط الشّبكات. توجد مصطلحات أخرى عديدة، يُمكن أن تُصادفك، لم تُذكَر في اللّائحة أعلاه. سنشرح مصطلحات أخرى في هذا الدّليل فورَ احتيّاجنا إليها. طبقات الشّبكةتُقدّم الشّبكات غالبًا وفق بنيتها الأفقيّة، بين المستضيفات Hosts؛ إلّا أنّ تنفيذ الشّبكة يتمّ وفقا لطبقات على مستوى حاسوب أو حواسيب عدّة. يعني عملُ الشّبكات على طبقات وجودَ تقنيّات متعدّدة تُبنى كلّ واحدة منها فوق الأخرى من أجل أن يعمل التّواصل بطريقة سلِسة. تُجرِّد Abstract كلُّ طبقة البياناتِ الخامّ القادمة من الطّبقة الأدنى، تجرّدها أكثر وتجعل من التّعامل معها أسهل بالنّسبة للتّطبيقات والمستخدمين. يُساعد تنظيم الشّبكة على طبقات في تسهيل استخدام الطّبقات الدّنيا بطرُق جديدة دون بذل الجهد في تطوير ابروتوكولات وتطبيقات تتعامل مع صيّغ البيانات الموجودة في هذه الطّبقات. تختلف طريقة وصف تخطيط طبقات الشّبكة كثيرًا حسب النموذج Model المستخدَم. لا يتغيّر المسار الّذي تأخذه البيانات في الشّبكة رغم اختلاف النّماذج. تبدأ البيانات رحلَتها، عند إرسالها من الجهاز، من قمّة كومة Stack الطّبقات متّجهة إلى الطّبقات الدّنيا. يحدُث نقل البيانات بين الأجهزة فعليًّا في المستوى الأدنى. تُعيد البيانات بعد النّقل رحلتها عبر طبقات الجهاز المستقبِل ولكن في الاتّجاه المعاكس: من الطبقة الدّنيا إلى القمّة. تُضيف كلّ طبقة غلافًا على حزمة البيانات عندما تصل إليها من الطّبقة الأعلى منها، وهو ما يُساعد الطّبقات المواليّة لها في معرفة ما يتوجّب عليها فعلُه بالبيانات. عند الاستقبال تنزع الطّبقة على الجهاز المستقبِل غلاف الطّبقة المكافئة لها على الجهاز المُرسِل. 1- نموذج OSIنموذج OSI (اختصار ل Open Systems Interconnect: شبكة وصل الأنظمة المفتوحة) هو أحد الطُّرُق الأولى لوصف الطّبقات المختلفة في الشّبكة. يُعرّف نموذج OSI سبعَ طبقات هي: التّطبيق Application: وهي الطّبقة الّتي يتفاعل معها المستخدمون وتطبيقات المستخدمين. يكثُر استخدام مصطلحات مثل توفّر الموارد Availability of resources، شركاء للتّخاطب معهم، مزامنة البيانات Data synchronization لوصف الاتّصال على هذا المستوى. التّقديم Presentation: طبقة التّقديم هي المسؤولة عن تعيين الموارد وتعريف السّيّاق Context. تُستخدم لترجمة بيانات المستويات الأدنى إلى صيغة يُمكن للتّطبيقات التّعامل معها. الجلسة Session: وهي مُداوِل Handler الاتّصال: تُنشئ، تُحافظ على، وتنهي الاتّصال بين المُتخاطبَيْن بطريقة مستمرّة. النّقل Transport: مسؤوليّتها إحالة اتّصال موثوق للطّبقات الموجودة فوقها (التّطبيق، التّقديم، والجلسة). تعني موثوقيّةُ الاتّصال في هذا الإطار القدرةَ على التّحقّق من وصول كلّ جزء من البيانات سليمًا إلى الطّرف الآخر من الاتّصال. يُمكن لهذه الطّبقة إعادة إرسال البيانات المفقودة أو المشوَّهة كما أنّ بإمكانها إبلاغ الأجهزة البعيدة بتسلّم البيانات القادمة منها. الشّبكة Network: تُستخدَم هذه الطّبقة لتوجيه البيانات بين مختلف العُقَد Nodes الموجودة في الشّبكة. تسخدم طبقة الشّبكة عنواين لمعرفة الجهاز الّذي ستُرسَل إليه البيانات. يُمكن لهذه الطّبقة أيضًا تقسيمُ الرّسائل ذات الحجم الكبير إلى قطع أصغر تُجمَّع على الطّرف الآخر من الاتّصال - بعد استلامه لها - لإنشاء الرّسالة الأصليّة. وصلة البيانات Data link: تُنفَّذ هذه الطّبقة بحيث تُنشئ وتُحافظ على وصلات موثوقة بين مختلف العُقد والأجهزة الموجودة في الشّبكة باستخدام اتّصالات ملموسة. الاتّصال الملموس Physical: وهي الطّبقة المسؤولة عن معالجة الأجهزة الطّرفية الفعليّة المُستخدَمة للاتّصال. تستدعِي هذه الطّبقةُ البرنامجَ الّذي يُدير الاتّصالات الملموسة والعتاد (مثل Ethernet). توجد إذن العديد من الطّبقات الّتي يُمكن الحديث عنها انطلاقًا من قربها من العتاد والوظيفة الّتي تقدّمها. 2- نموذج TCP/IPيشيع استخدام تعبير حزمة ابروتوكلات الإنترنت Internet protocol suite للحديث عن هذا النّموذج الأسهل والأكثر تبنيًّا. يُعرِّف نموذجُ TCP/IP أربع طبقات، يتداخل بعضٌ منها مع طبقات نموذج OSI: التّطبيق: وهي الطّبقة المسؤولة - في هذا النّموذج - عن إنشاء وإرسال بيانات المستخدِم بين التّطبيقات. يُمكن أن توجد التّطبيقات على أنظمة متباعدة، ويجب أن تظهر وكأنّها تعمل محلّيًّا لدى المستخدِم.يوصف الاتّصال بأنّه يحدُث بين النّظراء Peers. النّقل: وهي الطّبقة المسؤولة عن الاتّصال بين العمليّات Processes. يستخدِم هذا المستوى من الشّبكة المنافذَ لعنونة مختلف الخدمات. يُمكن لطبقة النّقل إنشاء اتّصالات موثوقة أو غير موثوقة حسب نوعيّة البروتوكول المستخدَم. التّوصيل Internet: مسؤوليّتها نقل البيانات من عقدة على الشّبكة إلى أخرى. تعرف هذه الطّبقة طرفيْ الاتّصال ولكنّها لا تهتمّ بالاتّصال الفعليّ المُستخدَم للانتقال من طرف إلى آخر. تُعرَّف عناوين IP على هذا المستوى بوصفها طريقة للوصول إلى الأنظمة البعيدة. الوصلة Link: تُنفّذ طبقة الوصلة مخطَّط الشّبكة المحليّة الّذي يسمح لطبقة التّوصيل بتقديم واجهة بعناوين. تنشئ هذه الطّبقة الاتّصالات بين العقد المتجاورة بهدف إرسال البيانات بينها نموذج TCP/IP أكثر تجريدًا وسلاسة من سابقه؛ ممّا جعله أكثر سهولةً للتّنفيذ وبالتّالي الطريقة الأكثر انتشارًا لتقسيم الطّبقات في الشّبكات.