-
المساهمات
189 -
تاريخ الانضمام
-
تاريخ آخر زيارة
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Ola Abbas
-
مشكلة التوسع إلى المليارات Scaling to Billions لقد رأينا الآن كيفية بناء شبكةٍ متشابكة internetwork تتكون من عدة شبكاتٍ ذات أنواعٍ مختلفة. أي أننا تعاملنا مع مشكلة عدم التجانس heterogeneity. المشكلة الحرجة الثانية في التشبيك internetworking، ويمكن القول أنها المشكلة الأساسية لجميع الشبكات، هي التوسّع scale. يجدر النظر في نمو الإنترنت لفهم مشكلة توسّع شبكة، حيث تضاعف حجم الإنترنت تقريبًا كلَّ عام خلال 30 عامًا. يدفعنا هذا النوع من النمو إلى مواجهة عدة تحديات. ومن أهم هذه التحديات كيفية بناء نظام توجيه يمكنه التعامل مع مئات الألوف من الشبكات ومليارات العقد النهائية. تعتمد معظم الطرق لمعالجة قابلية التوسّع في التوجيه على استخدام الهرمية hierarchy كما سنرى في هذا الفصل. يمكن تقديم الهرمية في شكل مناطق areas داخل نطاق domain، حيث نستخدم أيضًا الهرمية لتوسيع نظام التوجيه بين النطاقات interdomain. بروتوكول التوجيه بين النطاقات الذي مكّن الإنترنت من التوسع إلى حجمه الحالي هو بروتوكول BGP. سنلقي نظرة على كيفية عمل بروتوكول BGP، وعلى التحديات التي يواجهها مع استمرار نمو الإنترنت. ترتبط مشكلة العنونة ارتباطًا وثيقًا بقابلية التوسع، إذ أصبح من الواضح أن مخطط العنونة 32 بت للإصدار 4 (IP version 4) من بروتوكول IP لن يستمر بعد عقدين من الزمن، وقد أدى ذلك إلى تعريف إصدارٍ جديد من بروتوكول IP، وهو الإصدار 6 (IP version 6)، حيث اُستخدم الإصدار 5 في تجربة سابقة. يوسّع IPv6 حيز العناوين بشكل أساسي ولكنه يضيف أيضًا عددًا من الميزات الجديدة، والتي عُدِّل بعضها تحديثًا للإصدار IPv4. طالما أن الإنترنت يستمر في النمو من حيث الحجم، فإنه يحتاج أيضًا إلى تطوير وظائفه. تغطّي الأقسام الأخيرة من هذا الفصل بعض التحسينات الهامة لإمكانات الإنترنت. التحسين الأول هو البث المتعدد multicast والذي هو تحسين لِنموذج الخدمة الأساسية. سنوضح كيفية دمج البث المتعدد، وهو القدرة على توصيل نفس الرزم إلى مجموعة من المستقبلات بكفاءة، ضمن الإنترنت، وسنشرح العديد من بروتوكولات التوجيه التي طُوِّرت لدعم البث المتعدد. التحسين الثاني هو تبديل التسمية متعددة البروتوكولات Multiprotocol Label Switching أو اختصارًا MPLS الذي يعدّل آلية تمرير شبكات IP. وقد أتاح هذا التعديل إجراء بعض التغييرات في طريقة تنفيذ توجيه IP وفي الخدمات التي تقدمها شبكات IP. أخيرًا، سننظر في تأثيرات التنقّل mobility على التوجيه ووصف بعض التحسينات على بروتوكول IP لدعم المضيفين والموجّهات المتنقلة. لا تزال قضايا قابلية التوسع مهمةً لكلٍّ من هذه التحسينات. الإنترنت العالمي Global Internet رأينا كيفية توصيل مجموعةٍ غير متجانسة من الشبكات لإنشاء شبكة متشابكة وكيفية استخدام الهرمية البسيطة لعنوان IP لجعل التوجيه في الإنترنت قابلًا للتوسّع إلى حدٍ ما. نقول إنه قابل للتوسع "إلى حدٍ ما"، لأنه على الرغم من أن كل موجهٍ لا يحتاج إلى معرفة جميع المضيفين المتصلين بالإنترنت، إلا أنه في النموذج الموصوف حتى الآن يحتاج إلى معرفة جميع الشبكات المتصلة بالإنترنت. يحتوي الإنترنت اليوم مئات الألوف من الشبكات المتصلة به أو أكثر من ذلك. ولكن لا تتوسّع بروتوكولات التوجيه مثل تلك التي ناقشناها سابقًا إلى هذه الأرقام. يبحث هذا القسم في مجموعة متنوعة من التقنيات التي تعمل على تحسين قابلية التوسُّع بصورة كبيرة والتي مكّنت الإنترنت من النمو بقدر ما هو عليه الآن. نحتاج إلى صورةٍ عامة في أذهاننا لما يبدو عليه الإنترنت العالمي قبل الوصول إلى هذه التقنيات. إنه ليس مجرد توصيلٍ عشوائي من شبكات الإيثرنت، ولكنه يتخذ شكلًا يعكس حقيقة أنه يربط بين العديد من المنظمات المختلفة. يعطي الشكل السابق وصفًا بسيطًا لحالة الإنترنت في عام 1990، وقد نما هيكل topology شبكة الإنترنت بصورةٍ أعقد مما يوحي إليه هذا الشكل منذ ذلك الوقت. سنقدم صورةً أدق للإنترنت الحالي في قسمٍ لاحق. تتمثل إحدى سمات هذا الهيكل البارزة في أنه يتكون من مواقع المستخدم النهائي end-user sites، كَجامعة ستانفورد Stanford University على سبيل المثال، التي تتصل بشبكات مزود الخدمة (كانت شبكة BARRNET عبارةً عن شبكة مزود خدمة المواقع في منطقة خليج سان فرانسيسكو على سبيل المثال). خدّم العديد من مزوّدي الخدمة منطقةً جغرافية محدودة في عام 1990، وبالتالي عُرفوا باسم الشبكات الإقليمية regional networks. ارتبطت الشبكات الإقليمية، بدورها، بشبكة رئيسية وطنية nationwide backbone، حيث موّلت مؤسسة العلوم الوطنية National Science Foundation أو اختصارًا NSF هذه الشبكة في عام 1990، وبالتالي كانت تُسمى NSFNET backbone. أفسحت شبكة NSFNET الطريق لشبكة Internet2، التي لا تزال تدير الشبكة الرئيسية backbone هذه نيابة عن مؤسسات البحث Research والتعليم Education في الولايات المتحدة (توجد شبكات R & E مماثلة لها في بلدان أخرى)، ولكن بالطبع يحصل معظم الناس على اتصالهم بالإنترنت من مزودي الخدمات التجاريين. تُبنى شبكات المزود الأكبر اليوم (يطلق عليها المستوى 1 وبالأجنبية tier-1) عادةً من عشرات الموجّهات المتطورة الموجودة في مناطق المدينة الرئيسية (يشار إليها بالعامية باسم مدن NFL) المتصلة بواسطة روابط من نقطة لنقطة (غالبًا بسعة 100 جيجابت في الثانية). لا يكون كل موقع مستخدمٍ نهائي عادةً شبكةً واحدة، ولكنه يتكون بدلًا من ذلك من شبكات فيزيائية متعددة متصلة بواسطة مبدّلات switches وموجّهات routers. لاحظ أنه من المحتمل أن يكون كل مزودٍ ومستخدمٍ نهائي كيانًا مستقلًا إداريًا. وهذا له بعض العواقب الهامة على التوجيه. فمن المحتمل جدًا أن يكون لدى مزودي الخدمات المختلفين أفكارًا مختلفة حول أفضل بروتوكول توجيه لاستخدامه داخل شبكاتهم وحول كيفية إسناد المقاييس للروابط الموجودة في الشبكة على سبيل المثال. وبسبب هذا الاستقلال، تكون شبكة كل مزود عادةً عبارة عن نظامٍ مستقل autonomous system أو اختصارًا AS. سنعرّف هذا المصطلح بصورةٍ أدق لاحقًا، ولكن في الوقت الحالي من المناسب التفكير في النظام المستقل AS كشبكةٍ تُدار بصورةٍ مستقلة عن الأنظمة المستقلة الأخرى. يمكن استخدام حقيقة أن الإنترنت لديه بنية واضحة لصالحنا أثناء معالجة مشكلة قابلية التوسع. ولكن نحن بحاجة إلى التعامل مع مسألتين مرتبطتين بمشكلة التوسّع scaling. المسألة الأولى هي قابلية توسّع التوجيه. حيث نحتاج إلى إيجاد طرقٍ لتقليل عدد أرقام الشبكة التي تُنقَل في بروتوكولات التوجيه وتُخزَّن في جداول التوجيه الخاصة بالموجّهات. أمّا المسألة الثانية فهي استخدامية العناوين، أي التأكد من عدم استهلاك حيز عناوين IP بسرعة كبيرة. نرى استخدام مبدأ الهرمية hierarchy مرارًا وتكرارًا في هذا الكتاب لتحسين قابلية التوسُّع. وقد رأينا في الفصل السابق كيف يمكن لبنية عناوين IP الهرمية تحسين قابلية التوسع في التوجيه، وخاصةً مع المرونة التي يوفرها التوجيه بين النطاقات عديم التصنيف Classless Interdomain Routing أو اختصارًا CIDR والشبكات الفرعية. وسنرى لاحقًا استخدامات أخرى لِلهرمية، وشريكها التجميع aggregation، لتوفير أكبر قابليةٍ للتوسُّع، أولًا في نطاقٍ domain واحد ثم بين النطاقات. ثم سنناقش الإصدار 6 من بروتوكول IP، والذي كان اختراعه نتيجة مخاوف قابلية التوسع إلى حدٍ كبير. مناطق التوجيه Routing Areas كمثالٍ أول على استخدام الهرمية لتوسيع نظام التوجيه، سنَفحص كيفية استخدام بروتوكولات توجيه حالة الرابط link-state (مثل بروتوكولي OSPF و IS-IS) لتقسيم نطاق التوجيه إلى نطاقات فرعية تسمى مناطق areas. (تختلف المصطلحات إلى حدٍ ما بين البروتوكولات، ولكن سنستخدم مصطلحات بروتوكول OSPF هنا). فيمكن للنطاقات النمو بصورةٍ أكبر من خلال إضافة هذا المستوى الإضافي من الهرمية دون إنهاك بروتوكولات التوجيه أو اللجوء إلى بروتوكولات التوجيه بين النطاقات interdomain routing protocols الأعقد التي سنوضّحها لاحقًا. المنطقة area عبارة عن مجموعة من الموجّهات المضبوطة إداريًا لتبادل معلومات حالة الرابط مع بعضها بعضًا. هناك منطقة خاصة واحدة هي المنطقة الرئيسية backbone area، والمعروفة أيضًا بالمنطقة 0. يوضح الشكل الآتي مثالًا عن نطاق توجيهٍ مُقسمٍ إلى مناطق. الموجّهات R1 و R2 و R3 هي أعضاء في المنطقة الرئيسية وأعضاءٌ أيضًا في منطقة واحدة ليست منطقة رئيسية على الأقل، حيث الموجه R1 هو في الواقع عضو في كلٍّ من المنطقة 1 والمنطقة 2. يُعرَف الموجّه العضو في كلٍ من المنطقة الرئيسية ومنطقة ليست بمنطقة رئيسية nonbackbone area بموجّه منطقةٍ حدودي area border router أو اختصارًا ABR. لاحظ أن هذه الموجّهات تختلف عن الموجّهات الموجودة على حافة نظام AS، والتي يُشار إليها باسم موجهات حدود AS للتوضيح. يتم التوجيه داخل منطقةٍ واحدة بالضبط كما هو مّوضح في الفصل السابق. ترسِل جميع الموجّهات في المنطقة إعلانات حالة الرابط لبعضها بعضًا، وبالتالي فهي تطوّر خارطةً كاملة ومستقرة للمنطقة. ولكنّ لا تترك إعلانات حالة الرابط الخاصة بالموجّهات التي ليست موجّهات منطقةٍ حدودية المنطقةَ التي نشأت فيها. هذا له تأثير في جعل عمليات حساب المسار route calculation والإغراق flooding أكثر قابلية للتوسع بصورة كبيرة. فلن يرى الموجّه R4 مثلًا الموجود في المنطقة 3 أبدًا إعلان حالة رابطٍ من الموجه R8 الموجود في المنطقة 1. ولذلك لن يعرف شيئًا عن الهيكل topology التفصيلي لِلمناطق المغايرة لِمنطقته. إذًا كيف يحدّد الموجّه في منطقةٍ ما عقدة توجيه القفزة التالية next hop الصحيحة للرزمة الموجّهةِ إلى شبكةٍ في منطقة أخرى؟ تصبح الإجابة عن هذا السؤال واضحةً إذا تخيلنا أن مسار الرزمة التي يجب أن تنتقل من منطقةٍ ليست منطقة رئيسية إلى منطقة أخرى مقسَّمٌ إلى ثلاثة أجزاء. أولًا، تنتقل الرزمة من الشبكة المصدر إلى المنطقة الرئيسية، ثم تعبر المنطقة الرئيسية، وتنتقل منها إلى الشبكة الوِجهة. تلخّص موجّهات المنطقة الحدودية، لإنجاز هذا العمل، معلوماتِ التوجيه التي تعلّمتها من منطقةٍ ما وتُتيحَها ضمن إعلاناتها إلى مناطق أخرى. يتلقى الموجّه R1 على سبيل المثال إعلانات حالة الرابط من جميع الموجّهات في المنطقة 1 وبالتالي يمكنه تحديد تكلفة الوصول إلى أي شبكة في المنطقة 1. يعلن الموجّه R1 عن تكاليف الوصول إلى الشبكات في المنطقة 1 عندما يرسل إعلانات حالة الرابط إلى المنطقة 0، كما لو كانت جميع هذه الشبكات متصلةً مباشرة بالموجه R1. يتيح ذلك لجميع الموجّهات في المنطقة 0 معرفة تكلفة الوصول إلى جميع الشبكات في المنطقة 1. ثم تلخّص موجهات المنطقة الحدودية هذه المعلومات وتعلن عنها في المناطق الغير الرئيسية، وبالتالي تتعلم جميع الموجّهات كيفية الوصول إلى جميع الشبكات في النطاق domain. لاحظ أنه في حالة المنطقة 2، يوجد موجهان ABR، وبالتالي يتعين على الموجّهات في المنطقة 2 أن تختار أي موجهٍ ستستخدم للوصول إلى المنطقة الرئيسية. هذا سهل بما فيه الكفاية، نظرًا لأن كلًا من الموجهين R1 و R2 سَيُعلِنان عن تكاليف الوصول إلى شبكاتٍ مختلفة، لذلك سيتضح أيهما هو الخيار الأفضل لأن موجهات المنطقة 2 تشغّل خوارزمية المسار الأقصر shortest-path algorithm. فمن الواضح جدًا أن الموجّه R1 سيكون خيارًا أفضل من الموجّه R2 للوِجهات في المنطقة 1. يُجري مسؤول administrator الشبكة مقايضة بين قابلية التوسُّع والتوجيه الأمثل عند تقسيم نطاقٍ إلى مناطق. يُجبِر استخدامُ المناطق جميعَ الرزم التي تنتقل من منطقة إلى أخرى على المرور عبر المنطقة الرئيسية حتى لو كان المسار الأقصر متاحًا. فلن تتدفق الرزم بين الموجهين R4 و R5 على سبيل المثال حتى لو كانا متصلين مباشرةً لأنهما موجودان في منطقتين مختلفتين وغير رئيسيتين. اتضح أن الحاجة إلى قابلية التوسع غالبًا تكون أهم من الحاجة إلى استخدام المسار الأقصر على الإطلاق. أخيرًا، نلاحظ أن هناك خدعة يمكن من خلالها لمسؤولي الشبكة أن يقرروا بصورةٍ أكثر مرونة أي موجهاتٍ تذهب في المنطقة 0. حيث تستخدم هذه الخدعة فكرة الرابط الافتراضي virtual link بين الموجّهات. يمكن الحصول على هذا الرابط الافتراضي عن طريق ضبط موجهٍ غير متصلٍ مباشرةً بالمنطقة 0 لتبادل معلومات توجيه المنطقة الرئيسية مع هذا الموجّه. حيث يمكن ضبط رابطٍ افتراضي من الموجّه R8 إلى الموجّه R1 على سبيل المثال، مما يجعل الموجّه R8 جزءًا من المنطقة الرئيسية، وسيشارك الموجه R8 الآن في إغراق الموجهات الأخرى في المنطقة 0 بإعلان حالة الرابط. تحدَّد تكلفة الرابط الافتراضي من الموجّه R8 إلى الموجّه R1 من خلال تبادل معلومات التوجيه التي تحدث في المنطقة 1، ويمكن أن تساعد هذه التقنية في تحسين التوجيه الأمثلي. التوجيه بين النطاقات Interdomain Routing باستخدام بروتوكول BGP تحدّثنا عن فكرة أن الإنترنت منظمٌ ضمن أنظمةٍ مستقلة في بداية هذا الفصل، ويكون كل نظامٍ منها تحت سيطرة كيانٍ إداري منفصل. قد تكون الشبكة الداخلية المعقّدة لشركةٍ ما عبارةً عن نظام مستقل AS واحد، كما هو الحال بالنسبة للشبكة الوطنية لأي مزود خدمة إنترنت ISP. يوضح الشكل التالي شبكة بسيطة ذات نظامَين مستقلين autonomous systems: هدف هذه الأنظمة المستقلة هو توفير طريقة إضافية لتجميع معلومات التوجيه بصورةٍ هرمية في شبكة إنترنت كبيرة، وبالتالي تحسين قابلية التوسُّع. نقسِّم الآن مشكلة التوجيه إلى جزأين: التوجيه داخل نظام مستقل واحد والتوجيه بين الأنظمة المستقلة. نشير إلى جزأي مشكلة التوجيه بالتوجيه بين النطاقات interdomain routing والتوجيه داخل النطاق intradomain routing، حيث يُطلق اسمٌ آخر على الأنظمة المستقلة في الإنترنت هو نطاقات التوجيه routing domains. بالإضافة إلى تحسين قابلية التوسع، يفصل نموذجُ النظام المستقل AS التوجيهَ داخل النطاق الذي يحدث في أحد الأنظمة المستقلة عن ذلك الذي يحدث في نظامٍ مستقل آخر. وبالتالي يمكن لكل نظامٍ مستقل تشغيلَ أي بروتوكولات توجيه يختارها داخل النطاق. ويمكنه استخدام بروتوكولات مساراتٍ ثابتة static routes أو بروتوكولات متعددة، إذا رغب في ذلك. وعندئذٍ تكون مشكلة التوجيه بين النطاقات هي مشكلة مشاركة أنظمةٍ مستقلة مختلفة لمعلومات إمكانية الوصول لبعضها بعضًا، وهذه المعلومات هي توصيف مجموعة عناوين IP التي يمكن الوصول إليها عبر نظامٍ مستقل معين. تحديات التوجيه بين النطاقات Interdomain Routing ربما يكون التحدي الأهم للتوجيه بين النطاقات اليوم، هو حاجة كل نظامٍ مستقل لتحديد سياسات policies التوجيه الخاصة به. قد يبدو مثالٌ بسيط عن سياسة التوجيه المطبَّقة في نظامٍ مستقل معين كما يلي: "أُفضّلُ إرسال حركة مرور البيانات عبر النظام المستقل X بدلًا من النظام المستقل Y كلما أمكن ذلك، لكنني سأستخدم النظام المستقل Y إذا كان المسار الوحيد، ولا أريد مطلقًا نقل حركة مرور البيانات من النظام المستقل X إلى النظام المستقل Y أو العكس". ستكون مثل هذه السياسة نموذجية عندما تدفع المال لكل من النظامين المستقلين X و Y لتوصيل نظامك المستقل ببقية الإنترنت، والنظام المستقل X هو مزوّد الاتصال المفضل لديك، ويكون النظام المستقل Y هو البديل. لن تتوقع مساعدة النظامين المستقلين X و Y لنقل حركة المرور بينهما عبر شبكتك، وهذا ما يسمى بحركة المرور العابرة transit traffic. نظرًا لأنك ترى كلًا منهما كمزوّدَين (ومن المفترض أنك دفعت المال مقابل أداء هذا الدور). كلما زادت الأنظمة المستقلة التي تتصل بها، زادت السياسات المعقّدة التي قد تتبعها، خاصة عندما تفكر في مزوّدي الشبكة الرئيسية، الذين قد يتواصلون مع العشرات من مزوّدي الخدمة الآخرين ومئات العملاء ولديهم ترتيبات اقتصادية مختلفة (تؤثر على سياسات التوجيه) مع كل مزوّد. يتمثل أحد أهداف التصميم الرئيسية للتوجيه بين النطاقات في أن السياسات مثل تلك المُبينة في المثال أعلاه، والسياسات الأعقد، يجب أن يدعمها نظام التوجيه بين النطاقات. ولِجعل المشكلة أكثر صعوبةً تحتاج إلى أن تكون قادرًا على تنفيذ مثل هذه السياسة دون أي مساعدة من أنظمة مستقلة أخرى، وأن تكون قادرًا على مواجهة الضبط الخاطئ misconfiguration المحتمل أو السلوك الضار الذي تسلكه أنظمة مستقلة أخرى. علاوةً على ذلك، تكون هناك غالبًا رغبةٌ في إبقاء السياسات خاصة، لأن الكيانات التي تدير الأنظمة المستقلة، والتي معظمها هم مزودو خدمة الإنترنت ISP، غالبًا ما تكون في منافسة مع بعضها بعضًا ولا تريد إعلان ترتيباتها الاقتصادية على الملأ. كان هناك بروتوكولين رئيسيين للتوجيه بين النطاقات في تاريخ الإنترنت. الأول كان بروتوكول البوابة الخارجية Exterior Gateway Protocol أو اختصارًا EGP، الذي احتوى على عدد من القيود، ربما كان أشدها تقييدًا على هيكل topology شبكة الإنترنت بصورة كبيرة. صُمِّم بروتوكول EGP عندما كان للإنترنت هيكلٌ يشبه الشجرة كما هو موضح في الشكل الآتي، ولم يُسمح للهيكل أن يصبح أعم. لاحظ أنه في هذه البنية البسيطة الذي تشبه الشجرة، يوجد شبكة رئيسية وحيدة، والأنظمة المستقلة متصلة فقط كآباء وأبناء وليس كنظراء peers. لقد كان بديل بروتوكول EGP هو بروتوكول البوابة الحدودية Border Gateway Protocol أو اختصارًا BGP، والذي تكرر من خلال أربعة إصدارات BGP-4. يُنظر إلى بروتوكول BGP غالبًا على أنه واحد من أكثر أجزاء الإنترنت تعقيدًا، لذلك سنغطي بعض أهم نقاطه هنا. لا يقدم بروتوكول BGP، على عكس بروتوكول EGP، أي افتراضات تقريبًا حول كيفية اتصال الأنظمة المستقلة، فهو يشكّل رسمًا بيانيًا عشوائيًا. من الواضح أن هذا النموذج عام بما يكفي لاستيعاب الشبكات المتشابكة غير المبنيّة على أساس الشجرة non-tree-structured internetworks، مثل الصورة المبسَّطة لإنترنت متعدّد المزودين كما هو موضح في الشكل الآتي. (اتّضح أنه لا يزال هناك نوع آخر لبنية الإنترنت، كما سنرى لاحقًا، لكنها لا تشبه بساطة بنية الشجرة، ولا يضع بروتوكول BGP أي افتراضات حول هذه البنية). يتكون الإنترنت اليوم، على عكس الإنترنت المبني على أساس الشجرة الموضحة في بداية هذا الفصل أو حتى الصورة البسيطة إلى حدٍ ما في الشكل السابق، من مجموعة غنية من الشبكات المترابطة، تديرها في الغالب شركات خاصة، أو مزودو خدمة الإنترنت ISP بدلًا من الحكومات. يقدم العديد من مزودي خدمة الإنترنت هذه الخدمة إلى "المستهلكين consumers"، أي الأفراد الذين لديهم حواسيب في منازلهم، بينما يقدم مزودو خدمةٍ آخرون شيئًا يشبه خدمة الشبكة الرئيسية القديمة، ويربطون بين مزودي الخدمة الآخرين وأحيانًا بين الشركات الكبيرة. ويُرتِّب العديد من مزودي الخدمة للترابط مع بعضهم بعضًا في نقطة تناظر peering point واحدة. يمكننا البدء بتحديد بعض المصطلحات للحصول على فكرةٍ أفضل عن كيفية إدارة التوجيه بين هذا الترابط المُعقد للأنظمة المستقلة. نحدّد حركة المرور المحلية local traffic على أنها حركة المرور التي تنشأ عند العقد داخل النظام المستقل أو تنتهي عندها، وحركة المرور العابرة transit traffic على أنها حركة مرور تمر عبر نظامٍ مستقل. يمكن تصنيف الأنظمة المستقلة إلى ثلاثة أنواع: نظام مستقل جذري Stub AS: وهو نظام AS يحتوي على اتصال واحد فقط مع نظام AS آخر، فلن يحمل مثل هذا النظام المستقل سوى حركة المرور المحلية. الشركة الصغيرة في الشكل السابق هي مثال على نظام AS جذري. نظام مستقل متعدد طرق الاتصال Multihomed AS: هو نظام AS له اتصالات بأكثر من نظام AS آخر ولكنه يرفض نقل حركة المرور العابرة، مثل الشركة الكبيرة في الجزء العلوي من الشكل السابق. نظام مستقل عابر Transit AS :هو نظام AS له اتصالات بأكثر من نظام AS آخر وهو مصمم لنقل حركة المرور العابرة والمحلية، مثل مزودي الشبكة الرئيسية في الشكل السابق. إن أهداف التوجيه بين النطاقات أعقد من إيجاد المسارات المثلى للتوجيه استنادًا إلى تقليل نوعٍ من مقياس الرابط link metric والتي تم تسليط الضوء عليها في فصل سابق. أولًا، من الضروري إيجاد مسار إلى الوجهة المقصودة خالٍ من الحلقات. ثانيًا، يجب أن تكون المسارات متوافقة مع سياسات الأنظمة المستقلة المختلفة على طول المسار، وكما رأينا بالفعل، قد تكون هذه السياسات معقدة على نحوٍ كيفي. يركّز التوجيه بين النطاقات interdomain على إيجاد مسار خالٍ من الحلقات non-looping ومتوافق مع السياسة وهي مشكلة أعقد للتحسين، بينما يُركِّز التوجيه داخل النطاق intradomain على مشكلة محددة جيدًا لتحسين تكلفة المسار القياسية. هناك عوامل إضافية تجعل التوجيه بين النطاقات interdomain routing صعبًا. العامل الأول هو ببساطة مسألة التوسّع. يجب أن يكون موجّه الشبكة الرئيسية قادرًا على تمرير أي رزمةٍ متجهة إلى أي مكان على الإنترنت. وهذا يعني وجود جدول توجيه يوفر تطابقًا لأي عنوان IP صالح. ساعد توجيه CIDR في التحكم في عدد البادئات المميزة التي تُنقَل في توجيه الإنترنت الرئيسي، فهناك حتمًا الكثير من معلومات التوجيه التي يجب تمريرها والتي وصل عددها إلى ما يقارب 700,000 بادئة في منتصف عام 2018. ينشأ تحدٍ آخر في التوجيه بين النطاقات من الطبيعة المستقلة للنطاقات. لاحظ أن كل نطاقٍ يمكنه تشغيل بروتوكولات التوجيه الداخلية الخاصة به واستخدام أي مخططٍ يختاره لإسناد المقاييس للمسارات. وهذا يعني أنه من المستحيل حساب تكاليف المسار الموجَّه لمسارٍ يعبر أنظمة مستقلة متعددة. قد تعني التكلفة 1000 عبر مزودٍ واحد مسارًا رائعًا، ولكن قد يعني ذلك مسارًا سيئًا وغير مقبول لمزودٍ آخر. ولذلك يعلن التوجيه بين النطاقات عن إمكانية الوصول reachability فقط. مفهوم قابلية الوصول هو في الأساس بيانٌ يقول "يمكنك الوصول إلى هذه الشبكة من خلال هذا النظام المستقل AS". هذا يعني أن التوجيه بين النطاقات لاختيار المسار الأمثل أمر مستحيل أساسًا. تثير الطبيعة المستقلة بين النطاقات قضية الثقة. قد لا يرغب المزود A في تصديق إعلانات معينة من المزود B خوفًا من أن يعلن المزود B عن معلومات توجيه خاطئة. على سبيل المثال، يمكن أن يكون الوثوق بالمزود B عندما يعلن عن مسارٍ رائعٍ إلى أي مكان على الإنترنت خيارًا كارثيًا إذا تبين أن المزود B قد ارتكب خطأً في ضبط الموجّهات الخاصة به أو أنه لا يمتلك سعةً كافية لحمل حركة مرور البيانات. ترتبط مسألة الثقة أيضًا بالحاجة إلى دعم السياسات المعقدة. فمثلًا قد تكون على استعداد للثقة بمزودٍ معين فقط عندما يعلن عن إمكانية الوصول إلى بادئات معينة، وبالتالي سيكون لديك سياسة تقول "استخدم النظام المستقل X للوصول إلى البادئات p و q فقط، إذا وفقط إذا أعلن النظام المستقل X عن إمكانية الوصول إلى تلك البادئات ". أساسيات بروتوكول BGP يحتوي كل نظام AS على موجهٍ حدودي border router واحد أو أكثر تدخل وتغادر الرزمُ من خلاله النظام المستقل. حيث أن الموجّهات R2 و R4 في مثالنا البسيط في الشكل الآتي هي موجّهات حدودية. (عُرفت الموجّهات على مر السنين أحيانًا باسم البوابات gateways، ومن هنا جاءت أسماء البروتوكولَين BGP و EGP). الموجّه الحدودي هو ببساطة موجّه IP مكلَّفٌ بمهمة تمرير الرزم بين الأنظمة المستقلة. يجب أن يكون لكل نظام AS مشاركٍ في بروتوكول BGP أيضًا متحدّثٌ speaker خاصٌ ببروتوكول BGP واحد على الأقل، وهو موجّه "يتحدّث speaks" ببروتوكول BGP إلى متحدّثي بروتوكول BGP آخرين في أنظمة مستقلة أخرى. من الشائع أن تجد أن الموجّهات الحدودية هي أيضًا متحدثات بروتوكول BGP، لكنه ليس واجبًا. لا ينتمي بروتوكول BGP إلى أي من الصنفين الرئيسيتين لبروتوكولات التوجيه، وهما متّجه المسافة distance-vector وحالة الرابط link-state. يعلن بروتوكول BGP، على عكس هذه البروتوكولات، عن مسارات كاملة كقائمة معدودة من الأنظمة المستقلة للوصول إلى شبكة معينة، حيث يُسمى أحيانًا بروتوكول متّجه المسار path-vector لهذا السبب. يُعد الإعلان عن المسارات الكاملة ضروريًا لتمكين أنواع قرارات السياسة، الموضحة سابقًا، من أن تُتّخَذ وفقًا لرغبات نظام AS معين. كما أنه يُمكِّن من اكتشاف حلقات التوجيه بسهولة. افترض مثال الشبكة البسيط الموضح في الشكل السابق لمعرفة كيفية عمل ذلك، وافترض أن مزودي الخدمة هم شبكات عابرة transit networks، بينما شبكات العملاء هي شبكات جذريّة stubs. يمكن لمتحدثِ بروتوكول BGP لنظام AS للمزود A (في الشكل هو AS 2) أن يعلن عن معلومات قابلية الوصول لكلٍ من أرقام الشبكة المُسندة للعملاء P و Q. وبالتالي سيقول "أن الشبكات 128.96 و 192.4.153 و 192.4.32 و 192.4.3 يمكن الوصول إليها مباشرةً من النظام المستقل AS 2". وعند تلّقي هذا الإعلان، يمكن للشبكة الرئيسية الإعلان عن أنه "يمكن الوصول إلى الشبكات 128.96 و 192.4.153 و 192.4.32 و 192.4.3 على طول المسار (AS 1 , AS 2)". وبالمثل، يمكنها الإعلان عن أنه "يمكن الوصول إلى الشبكات 192.12.69 و 192.4.54 و 192.4.23 على طول المسار (AS 1 , AS 3)". تتمثل إحدى الوظائف المهمة لبروتوكول BGP في منع إنشاء مسارات الحلقات. افترض وجود الشبكة الموضحة في الشكل السابق. وهي تختلف عن الشبكة الموضَّحة في الشكل الذي قبله فقط في إضافة رابطٍ إضافي بين النظامين المستقلين AS 2 و AS 3، ولكن التأثير الآن هو أن الرسم البياني للأنظمة المستقلة يحتوي على حلقةٍ فيه. لنفترض أن النظام المستقل AS 1 تعلّم أنه يمكنه الوصول إلى الشبكة 128.96 من خلال النظام المستقل AS 2، لذلك يعلن عن هذه الحقيقة للنظام المستقل AS 3، والذي بدوره يعلن عنها مرة أخرى إلى النظام المستقل AS 2. يمكن للنظام المستقل AS 2 الآن تحديد أن النظام المستقل AS 3 هو المسار المفضل للرزم الموجهة للشبكة 128.96 في حالة عدم وجود أية آلية لمنع الحلقة. إذا بدأ النظام المستقل AS 2 في إرسال رزمٍ، موجهةٍ إلى الشبكة 128.96، إلى النظام المستقل AS 3 ، فإن النظام المستقل AS 3 سيُرسلها إلى النظام المستقل AS 1، وبالتالي سيعيد النظام المستقل AS 1 تلك الرزم إلى النظام المستقل AS 2، وستدور في حلقةٍ إلى الأبد. يُمنع حدوث ذلك عن طريق حمل مسار النظام المستقل الكامل في رسائل التوجيه. بالتالي سيحوي الإعلان عن المسار في هذه الحالة إلى الشبكة 128.96 الذي استلمه النظام المستقل AS 2 من النظام المستقل AS 3 على مسار النظام المستقل (AS 3 , AS 1 , AS 2 , AS 4). يرى النظام المستقل AS 2 نفسه في هذا المسار، وبالتالي يستنتج أن هذا ليس مسارًا مفيدًا لاستخدامه. من الواضح أن أرقام AS المحمولة في بروتوكول BGP يجب أن تكون فريدة لكي تعمل تقنية منع الحلقة هذه. فيمكن للنظام المستقل AS 2 التعرف على نفسه فقط في مسار AS في المثال أعلاه إذا لم يعرّف نظام مستقلٌ آخر نفسه بنفس الطريقة. يبلغ طول أرقام AS الآن 32 بتًا، وتُسندها سلطة مركزية لضمان هذا التفرُّد uniqueness. سيعلن نظامٌ مستقل عن المسارات التي يراها جيدةً بما يكفي لنفسه فقط. إذا كان متحّدث بروتوكول BGP قادرًا على الاختيار من بين عدة مسارات مختلفة إلى وجهةٍ ما، سيختار أفضلها وفقًا لسياساته المحلية الخاصة، ثم سيكون هذا هو المسار الذي يعلن عنه. إن متحدّث بروتوكول BGP غير ملزمٍ بالإعلان عن أي مسار إلى أية وجهة، حتى لو كان لديه مسار. هذه هي الطريقة التي يمكن بها لِلنظام المستقل تنفيذ سياسة عدم توفير عبور not providing transit من خلال رفض الإعلان عن مسارات البادئات غير الواردة في هذا النظام المستقل، حتى لو كان يعرف كيفية الوصول إليها. يجب أن يكون متحدثو بروتوكول BGP قادرين على إلغاء المسارات التي أُعلِن عنها مسبقًا عند فشل الروابط وتغيير السياسات. ويحدث ذلك باستخدام شكلٍ من أشكال الإعلان السلبي يُعرف باسم المسار المسحوب withdrawn route. تُنقل معلومات قابلية الوصول الإيجابية والسلبية في رسالة تحديث BGP، ويعرض الشكل التالي صيغة هذه الرسالة. (لاحظ أن الحقول في هذا الشكل هي من مضاعفات 16 بت، على عكس صيغ الرزم الأخرى في هذا الفصل): يُعرَّف بروتوكول BGP، على عكس بروتوكولات التوجيه الموصوفة في الفصل السابق، للتشغيل فوق بروتوكول TCP، وهو بروتوكول النقل الموثوق. يجب عدم إرسال معلومات مُرسلة من متحدِّثٍ إلى آخر مرةً أخرى، نظرًا لأن متحدثي بروتوكول BGP يمكنهم الاعتماد على بروتوكول TCP ليكونوا موثوقين. وبالتالي طالما لم يتغير شيء، يمكن لمتحدّث بروتوكول BGP ببساطة إرسال رسالة تنشيط اتصال keepalive عرَضية تقول "ما زلت هنا ولم يتغير شيء". إذا تعطل هذا الموجّه أو انفصل عن نظيره، سيقف عن إرسال رسائل تنشيط الاتصال، وستَفترِض الموجّهات الأخرى التي تعلمت المسارات منه أن هذه المسارات لم تعد صالحة. علاقات Relationships النظام المستقل وسياساته المشتركة تبين أن هناك عددًا قليلًا من السياسات المشتركة التي تعكس العلاقات المشتركة بين الأنظمة المستقلة. يوضح الشكل التالي العلاقات الأكثر شيوعًا: العلاقات الثلاث المشتركة والسياسات التي تتماشى معها هي: المزوِّد - العميل Provider-Customer: يعمل المزودون على توصيل عملائهم ببقية الإنترنت. قد يكون العميل شركة، أو قد يكون مزود خدمة إنترنت أصغر (الذي قد يكون له عملاء خاصين به). لذا فإن السياسة الشائعة هي الإعلان عن جميع المسارات التي تعرفها لعميلك، والإعلان عن المسارات التي تتعلمها من عميلك إلى الجميع. العميل - المزوّد Customer-Provider: يريد العميل في الاتجاه الآخر توجيه حركة المرور إليه (وعملائه، إذا كان لديه) بواسطة مزوده، ويريد أن يكون قادرًا على ارسال حركة المرور إلى بقية الإنترنت من خلال مزوّده. لذا فإن السياسة الشائعة في هذه الحالة هي الإعلان عن البادئات والمسارات الخاصة بك التي تعلّمتها من عملائك إلى مزود الخدمة الخاص بك، والإعلان عن المسارات التي تعلمتها من مزود الخدمة إلى عملائك، ولكن لا تعلن عن المسارات التي تعلّمتها من مزودٍ إلى مزودٍ آخر. والسبب في الجزء الأخير هو التأكد من أن العميل لا يجد نفسه عاملًا في مجال نقل حركة المرور من مزود إلى آخر، وهذا ليس في مصلحته إذا كان يدفع لمزودي الخدمة لنقل حركة المرور نيابة عنه. النظير peer: الخيار الثالث هو التناظر المتماثل symmetrical peering بين الأنظمة المستقلة. يكون مزودي الخدمة الذين يعدّون أنفسهم متساوين ونظائر، بحيث يمكنهم الوصول إلى عملاء بعضهم بعضًا دون الحاجة للدفع لمزوّد آخر. تتمثل السياسة المعتادة هنا في الإعلان عن المسارات التي تعلمتها من عملائك إلى نظيرك peer، والإعلان عن المسارات التي تعلمتها من نظيرك إلى عملائك، ولكن لا تعلن عن المسارات من نظيرك إلى أي مزود أو العكس. شيء واحد يجب ملاحظته حول هذا الأسلوب وهو إعادته بعض الهيكلة إلى شبكة الإنترنت التي تظهر أنّها غير مُنظّمة unstructured. لدينا الشبكات الجذرية stub networks في الجزء السفلي من التسلسل الهرمي، وتُمثّل هذه الشبكات عملاءٌ لمزودٍ واحد أو أكثر، ونرى مع تقدمنا في التسلسل الهرمي مزوّدي الخدمة الذين لديهم مزودين آخرين كعملاءٍ لهم. لدينا في الجزء العلوي مزودون لديهم عملاء ونظائر ولكنهم ليسوا عملاء لأي شيء، ويُعرف هؤلاء المزوّدون بمزودي الطبقة الأولى Tier-1. دمج التوجيه بين النطاقات مع التوجيه داخل النطاق توضّح المناقشة السابقة كيفية تعلّم متحدث بروتوكول BGP معلومات التوجيه بين النطاقات، ولكن لا يزال السؤال مطروحًا حول كيفية حصول جميع الموجّهات الأخرى في النطاق على هذه المعلومات. وهناك عدة طرق يمكن من خلالها معالجة هذه المشكلة. لنبدأ بموقف بسيط جدًا، وهو أيضًا شائع جدًا. من الواضح أن الموجّه الحدودي والذي يتصل فقط بالأنظمة المستقلة الأخرى عند نقطة واحدة، هو الخيار الوحيد لجميع المسارات خارج نظام AS في حالة نظام مستقل جذري stub. يمكن لهذا الموجّه حقن مسارٍ افتراضي default route في بروتوكول التوجيه داخل النطاق، وهذا بيانٌ مفاده أن أية شبكة لم يعلن عنها صراحةً في بروتوكول النطاق الداخلي يمكن الوصول إليها من خلال الموجّه الحدودي. تذكّر، من تمرير بروتوكول IP، أنّ المدخلة الافتراضية default entry في جدول التمرير تأتي بعد كل المدخلات الأكثر تحديدًا، وهي تقابل أي شيءٍ فشلَ في مطابقة مدخلةٍ محددة. تتمثل الخطوة التالية في التعقيد في جعل الموجّهات الحدودية تضخ مساراتٍ معينة تعّلمتها من خارج نظام AS. افترض، على سبيل المثال، الموجّه الحدودي لنظام AS الذي يتصل بعميل AS. يمكن لهذا الموجّه معرفة أن بادئة الشبكة 192.4.54 / 24 موجودة داخل عميل AS، إما من خلال بروتوكول BGP أو بسبب ضبط المعلومات في الموجه الحدودي، ويمكنه حقن مسارٍ لهذه البادئة في بروتوكول التوجيه الذي يعمل داخل مزود AS. سيكون هذا إعلانًا من النوع: "لدي رابطٌ بالبادئة 192.4.54 / 24 بتكلفة X". قد يتسبب ذلك في معرفة الموجّهات الأخرى في مزود AS أن هذا الموجّه الحدودي هو المكان المناسب لإرسال الرزم المخصَّصة لتلك البادئة. يأتي المستوى الأخير من التعقيد في الشبكات الرئيسية، التي تتعلم الكثير من معلومات التوجيه من بروتوكول BGP بحيث يصبح حقنها في بروتوكول داخل النطاق مكلفًا للغاية. إذا أراد الموجه الحدودي، على سبيل المثال، حقن 10000 بادئة تعلّمها من نظام AS آخر، فسيتعيّن عليه إرسال رزم حالة رابط كبيرة جدًا إلى الموجهات الأخرى في نظام AS، وستصبح حسابات المسار الأقصر معقدةً للغاية. لذلك تستخدم الموجّهات في الشبكة الرئيسية متغيرًا من بروتوكول BGP يسمى BGP الداخلي interior BGP أو اختصارًا iBGP لإعادة توزيع المعلومات التي تعلّمتها باستخدام متحدّثي بروتوكول BGP على حواف نظام AS إلى جميع الموجهات الأخرى في نظام AS بفعالية. (يعمل البديل الآخر لبروتوكول BGP بين الأنظمة المستقلة ويُسمى BGP الخارجي exterior BGP أو اختصارًا eBGP. يمكّن بروتوكول iBGP أي موجهٍ في نظام AS من التعرف على أفضل موجهٍ حدودي لاستخدامه عند إرسال رزمةٍ إلى أي عنوان، ويتتبع كل موجه في نظام AS في الوقت نفسه كيفية الوصول إلى كل موجهٍ حدودي باستخدام بروتوكول تقليدي داخل النطاق بدون معلوماتٍ محقونة. يكون كل موجهٍ في نظام AS قادرًا على تحديد العقدة التوجيهية التالية المناسبة لجميع البادئات من خلال الجمع بين هاتين المجموعتين من المعلومات. افترض شبكة المثال البسيط التي تمثل نظامًا مستقلًا واحدًا في الشكل السابق. تتحدَث الموجّهات الحدودية الثلاثة، A و D و E، بروتوكول eBGP مع أنظمة مستقلة أخرى وتتعلّم كيفية الوصول إلى البادئات المختلفة. تتواصل الموجّهات الحدودية الثلاثة هذه مع الموجهات الأخرى ومع الموجّهات الداخلية B و C من خلال إنشاء شبكة من جلسات iBGP بين جميع الموجّهات في النظام المستقل. دعنا نركز الآن على كيفية بناء الموجّه B لرؤيته الكاملة لكيفية تمرير الرزم إلى أية بادئة. انظر إلى الجزء العلوي الأيسر من الشكل الآتي، والذي يعرض المعلومات التي يتعلّمها الموجّه B من جلسات iBGP الخاصة به. يتعلم أنه من الأفضل الوصول إلى بعض البادئات عبر الموجّه A، والبعض الآخر عبر الموجّه D، والبعض الآخر عبر الموجّه E. وفي الوقت نفسه، تعمل جميع الموجّهات في النظام المستقل أيضًا على تشغيل بعض بروتوكولات التوجيه داخل النطاق مثل بروتوكول معلومات التوجيه Routing Information Protocol أو اختصارًا RIP أو بروتوكول OSPF. (المصطلح العام لبروتوكولات داخل النطاق هو بروتوكول بوابة داخلية interior gateway protocol أو اختصارًا IGP). يتعلم الموجّه B كيفية الوصول إلى العقد الأخرى داخل النطاق من هذا البروتوكول المنفصل تمامًا، كما هو موضح في أعلى الجدول الأيمن من الشكل الآتي. يحتاج الموجه B إلى إرسال رزمٍ إلى الموجّه C للوصول إلى الموجّه E على سبيل المثال. أخيرًا في الجدول السفلي، يجمع الموجه B الصورة بأكملها معًا، ويجمّع المعلومات حول البادئات الخارجية التي تعلمها من iBGP مع المعلومات حول المسارات الداخلية إلى الموجهات الحدودية المتعلَّمة من بروتوكول IGP. وبالتالي إذا أمكن الوصول إلى بادئة مثل 18.0 / 16 عبر الموجه الحدودي E، وكان أفضل مسار داخلي إلى الموجه E هو عبر الموجه C، فسيترتّب عن ذلك إعادة توجيه أية رزمة مخصَّصة للبادئة 18.0 / 16 إلى الموجه C، ويمكن بهذه الطريقة لأي موجهٍ في النظام المستقل إنشاء جدول توجيه كامل لأية بادئةٍ يمكن الوصول إليها عبر بعض موجهات الحدود في النظام المستقل. ترجمة -وبتصرّف- للقسم Global Internet من فصل Advanced Internetworking من كتاب Computer Networks: A Systems Approach. اقرأ أيضًا المقال السابق: تطبيق مبدلات وموجهات الشبكات الحاسوبية برمجيا وعتاديا التشبيك Internetworking بين أنواع مختلفة من الشبكات الحاسوبية شبكة الإنترنت باستخدام بروتوكول IP
-
هناك العديد من الطرق لتغيير حجم عنصر في برنامج الفوتوشوب، ولكن ليس عليك أن تكون محترفًا للحصول على هذا التغيير الذي تريده. سنلقي نظرةً في هذا المقال على طرق بسيطة للغاية لتكبير وتحويل وتغيير حجم عنصر، وذلك باستخدام عملية التحويل Transform. توجد ثلاث طبقات في المثال الذي سنستخدمه، حيث أن الطبقة السفلية هي عبارة عن طبقة بيضاء في الخلفية نريد تغيير حجمها لملء لوحة الرسم، أما الطبقة الوسطى فتحتوي رسمًا يمثّل الشمس التي نريد وضعها في مركز لوحة الرسم ومطابقتها مع حجم الطبقة البيضاء، بينما الطبقة الثالثة هي زهرة نريد وضعها في مركز دائرة الشمس. سنستخدم خيارات مختلفة لتغيير الحجم لمعرفة كيفية عمل كل من هذه الخيارات. تغيير حجم عنصر باستخدام عملية التكبير Scale سنحدّد أولًا الطبقة ذات المربع الأبيض من الزاوية السفلية اليمنى من الشاشة، فالطبقة المحدَّدة لها خلفية رمادية فاتحة. حدّد طبقة المربع الأبيض ثم انقر على قائمة Edit ثم اختر Transform، ثم Scale. سيظهر مربع يحيط به مقابض جانبية حول المربع الأبيض. يمكنك تكبير حجم المربع الأبيض بسرعة من خلال النقر فوق أي مقبض وسحبه، وبالتالي سيتغير حجم المربع تغيرًا متناسبًا، أي أن الطول والعرض سيتغيران بنفس نسبة الطول والعرض الأصليين. يمكنك أن ترى أن المربع لا يناسب لوحة الرسم تمامًا، لذلك نحتاج إلى تخصيص الحجم ليتناسب مع لوحة الرسم، ويمكن فعل ذلك من خلال الانتقال إلى شريط الخيارات Options Bar في الجزء العلوي من الشاشة، ثم إلغاء النقر على زر الحفاظ على نسبة الطول إلى العرض Maintain Aspect Ratio (أيقونة الارتباط)، والذي يحدد تناسبية العنصر. وبالتالي يمكنك إمساك مقبض أحد الجوانب وسحبه دون تغيير الجوانب الأخرى. أصبح الآن المربع الأبيض يملأ لوحة الرسم بأكملها، وبالتالي انتهينا من تغيير حجم تلك الطبقة. تغيير حجم عنصر باستخدام التحويل الحر Free Transform سنستخدم طريقة التحويل مثل طريقة أخرى لتغيير حجم عنصر في برنامج الفوتوشوب، حيث تعمل هذه الطريقة تمامًا مثل طريقة التكبير، وسنحدد الطبقة التي تحتوي الشمس من الزاوية السفلية اليمنى في هذا المثال. اذهب إلى قائمة Edit ثم اختر التحويل الحر Free Transform. يحيط بالشمس الآن مربعٌ يحيط به مقابض يمكنك استخدامها لتغيير الحجم كما فعلنا سابقًا مع المربع الأبيض. نريد إبقاء أبعاد الشمس متناسبةً عند تكبيرها، لذلك سنضغط على زر الحفاظ على نسبة العرض إلى الطول من أيقونة الارتباط من شريط الخيارات مرةً أخرى، ثم نستخدم المقابض لتغيير حجم الشمس بحيث تملأ المربع الأبيض. هناك خيار آخر لتحديد الحجم، حيث يمكنك استخدام المقابض الموجودة على المربع المحيط بالشكل كما هو موضح أعلاه، أو يمكنك ضبط النسب المئوية للطول H والعرض W يدويًا من شريط الخيارات، سواءً اخترت الخيار Scale أو الخيار Free Transform. سنختار الآن الطبقة التي تحتوي الزهرة، لهذا تأكّد من تحديد أيقونة Maintain Aspect Ratio وزِد نسبة الطول إلى 325%، وبالتالي سيُعدَّل العرض تلقائيًا إلى نفس نسبة الطول المئوية لأن الارتباط مفعَّل. تغيير حجم عنصر باستخدام خيارات التحويل الفرعية يحتوي الأمر Transform على خيارات متعددة أخرى مثل التدوير rotate والانحراف skew والتشويه distort، وكذا المنظور perspective والالتواء warp، والتي تُعَد طرقًا أخرى لتغيير حجم عنصر في الفوتوشوب بهدف إنشاء تأثيرات مختلفة. لقد استخدمنا في المثال التالي خيار المنظور perspective لجعل الشمس والزهرة تظهران وكأنهما تنسحبان في الفضاء، وذلك عن طريق ضبط مقابض المربع المحيط بالشكل حتى تحصل على التأثير الذي تريده، كما استخدمنا أيضًا التحويل الحر على الزهرة لتقليل حجمها. نقدّم فيما يلي وصفًا سريعًا لما سيفعله كل خيار فرعي: التدوير Rotate: يدوِّر هذا الخيار الصورة حول نقطة مرجعية ثابتة، فإذا حرّكت المؤشر خارج الحدود المحيطة بالعنصر، فإن هذا المؤشر سيصبح سهمًا منحنيًا ذا وجهين، بعدها سيمكنك سحب المؤشر لتدوير الصورة. اضغط على المفتاح Shift من لوحة المفاتيح لنقل الدوران بزيادة قدرها 15 درجة. الانحراف Skew: يؤدي هذا الخيار إلى إمالة العنصر رأسيًا وأفقيًا من خلال سحب المقبض الجانبي لإمالة المربع المحيط بالعنصر. التشويه Distort: يسمح هذا الخيار بتمديد العنصر الخاص بك في جميع الاتجاهات، حيث يمكنك استخدام مقابض الزاوية لتشويه الشكل. المنظور Perspective: يطبّق هذا الخيار منظورًا من نقطة واحدة على العنصر المختار، لهذا أمسِك بمقبض زاوية واسحبه لتطبيق المنظور الذي تريده. الالتواء Warp: يسمح هذا الخيار بمعالجة تفصيلية لشكل العنصر، حيث يظهر رسم بياني "شبكي" فوق الصورة عند تفعيل هذا الخيار. اسحب نقاط التحكم أو الخط أو المنطقة داخل الشبكة لتغيير شكل الشبكة، وسيتبع ذلك تغيّر شكل العنصر. اختصارات لوحة المفاتيح بما أن استخدام لوحة المفاتيح قد يكون أكثر فاعلية، فإليك بعض اختصارات لوحة المفاتيح التي يمكنك استخدامها لتغيير الحجم: استخدم الاختصار Ctrl + T مع نظام التشغيل Windows، أو الاختصار Command + T مع نظام التشغيل Mac لتفعيل التحويل الحر، حيث سيؤدي ذلك إلى تشكّل مربع يحيط بالطبقة أو العنصر المحدَّد. اضغط مع الاستمرار على مفتاح Alt لنظام التشغيل Windows، أو مفتاح Option لنظام التشغيل Mac أثناء سحب المقبض لإعادة تشكيل العنصر من مركزه. اضغط مع الاستمرار على مفتاح Shift عند سحب مقبض المربع المحيط بالعنصر باستخدام الطريقة Free Transform، والذي سيقيّد نسبة الطول إلى العرض مثل بديلٍ للنقر فوق أيقونة Maintain Aspect Ratio. سيؤدي الضغط مع الاستمرار على Shift + Alt في نظام Windows أو Shift + Option في نظام التشغيل Mac مع النقر على المقبض وسحبه؛ إلى تغيير حجم العنصر تغييرًا متناسبًا من مركز العنصر إذا نقرت على مقبض زاوية، أو سيعدِّل الجوانب المتقابلة بالتساوي إذا استخدمت مقبضًا جانبيًا. انقر على زر الفأرة الأيمن في نظام التشغيل Windows، أو اضغط على المفتاح Control مع زر الفأرة الأيسر في نظام التشغيل Mac، وذلك عندما يكون المربع المحيط بالعنصر مرئيًا، لعرض القائمة الفرعية لخيارات التحويل التي تحتوي على التدوير والانحراف والتشويه وما إلى ذلك. فإن حدَّدت أيًا من هذه الخيارات الفرعية، فيمكنك الضغط مع الاستمرار على المفتاح Alt في نظام Windows، أو المفتاح Option في نظام التشغيل Mac مع النقر والسحب لتطبيق هذه الخيارات. يمكنك التبديل مؤقتًا إلى الأوضاع Skew أو Distort أو Perspective مباشرةً من لوحة المفاتيح دون الحاجة إلى تحديدها من أي قائمة عند تفعيل التحويل الحر كما يلي: بالنسبة إلى وضع Skew أو Distort: ما عليك سوى الضغط باستمرار على مفتاح Ctrl في نظام Windows، أو مفتاح Command في نظام Mac، وذلك أثناء سحب مقبض جانبي أو مقبض زاوية. بالنسبة إلى وضع Perspective: اضغط باستمرار على Shift + Ctrl + Alt في نظام Windows، أو على المفاتيح Shift + Command + Option في نظام Mac، واسحب مقبض الزاوية. يعيدك رفع يديك عن المفاتيح السابقة إلى وضع التحويل الحر الأساسي. يؤدي الضغط على المفتاح Enter من لوحة المفاتيح إلى الخروج من عملية التحويل الحر. الخلاصة طريقتا التحويل Transform والتحويل الحر Free Transform، هما أبسط الطرق التي تُستخدَم لتغيير حجم العناصر في برنامج الفوتوشوب، حيث سيصبح استخدامها سهلًا بمجرد استخدامها مرتين، كما يمكنك أيضًا استخدام تحويلات متعددة للحصول على التأثير المناسب لك. ترجمة -وبتصرّف- للمقال How to Scale, Transform, and Resize an Object in Photoshop لصاحبته Amber Fogel. اقرأ أيضًا كيفية تخفيض حجم ملفات الصور من النوع JPEG وأنواع الصور الأخرى كيفية إنشاء أنماط Patterns رسومية تفصيلية باستخدام برنامج فوتوشوب كيفية قص الشعر من الخلفيات المعقدة في الفوتوشوب
-
يُعَد برنامج سكريبوس Scribus من أفضل البدائل المجانية لبرنامج النشر الشهير أدوبي إن ديزاين Adobe InDesign، وقد أصبح يدعم اللغة العربية إضافةً لتوفيره واجهات عربية كاملة منذ الإصدار 1.5.3 وما بعده، لذلك تستطيع تنزيله لمختلف الأنظمة بما فيها الويندوز. لا بد أنك قرأت مرارًا وتكرارًا أن برنامج سكريبوس هو "برنامج تخطيط layout"، حيث لم يُصمَّم هذا البرنامج بصورة أساسية مع ميزات معالج الكلمات مثل برامج OpenOffice.org أو Word أو WordPerfect. تخيّل عوضًا عن ذلك شخصًا يعمل في مجال التصميم ويريد عمل تخطيط لإعلان، أو شخصًا يريد عمل نشرة إخبارية جذابة وغنية بالمعلومات، أو جريدة، أو كتيّبًا، أو حتى كتابًا يحتاج فيه التصميم والتخطيط إلى تحكّم دقيق. تُعَد القرارات المتعلقة بما يُطبَع والمكان الذي يُطبَع هذا المحتوى عليه قرارات منفصلة تمامًا في الطباعة الاحترافية، حيث يهتم الشخص المعني بالتخطيط أولًا وقبل كل شيء بتخطيط هذا المحتوى، ثم بنوع الورق أو الأمور الأخرى التي يُطبَع عليها المحتوى، وعدد الألوان المطلوبة، ونوع معدات الطباعة المستخدمة، وما إلى ذلك؛ بينما يهتم برنامج سكريبوس بصورة أساسية بجزء التخطيط، ولكن ستكون في هذه العملية قادرًا على إنتاج شيء يمكن نقله إلى شركة طباعة احترافية وتلبية احتياجاتها. يمكن تشغيل برنامج سكريبوس بالنسبة إلى المستخدم العادي على أي حاسوب مهما كان نوعه، وطباعة النتائج على طابعة منزلية، سواءً بالألوان أو بالأبيض والأسود. لا يحتاج خرج برنامج سكريبوس أبدًا إلى الوصول إلى مرحلة الطباعة، إذ سيُنشئ سكريبوس ملفات PDF التي يمكن استخدامها لعرض تقديمي معروض على الشاشة، أو سينشئ نماذج PDF، حيث تُعَد ملفات PDF وسيلةً مرغوبة للإنترنت بصورة متزايدة. يوضّح الشكل التالي صورةً ذات مخطط يصعب تحقيقه في برامج معالجة النصوص: ميزات برنامج سكريبوس فيما يلي بعض من ميزات سكريبوس الأساسية: تتمثل الخطوة الأولى في استخدام برنامج سكريبوس باختيار المستند المناسب. قد يبدو ذلك أمرًا غير متوقَّع، ولكن المستند A4 أو USLetter أو أيًا كان، ما هو إلا مساحة يمكن العمل فيها، بحيث يظهر باللون الأبيض أو اللون الذي تختاره، ولكنه في الواقع ليس له لون، ولا يمكن إسناد لون له. توجد كائنات موضوعة في مساحة العمل هذه، ويطلَق على معظمها اسم إطارات frames، فإن كانت هذه الإطارات إطاراتٍ نصية، فقد تحتوي على نص، وبالتالي تُدعى كائنات مضمَّنة in-line objects. تحتوي إطارات الصور على صور فقط، وهناك أيضًا إطارات للأشكال والمضلعات والخطوط، بحيث يمكن تحويل نوع إطارات إلى نوع آخر، ولكنها وقتها ستفقد ميزاتها السابقة بمجرد أن تتحوّل، إذ يفقد إطارُ الصورة المحوَّل إلى إطار نص الصورةَ التي قد يحتوي عليها. إذا نظرت إلى هذا الغلاف النموذجي الآتي فقد تعتقد أن هذا مستحيل، حيث قلنا سابقًا أن مساحة عمل المستند ليس لها لون، لكن يوضّح هذا المثال أن الإطار يمكن أن يكون كبيرًا بحجم مساحة المستند، لذلك فهو إطار بحجم الصفحة ولونه رمادي. يُظهر الشكل التالي تخطيطًا في برنامج Scribus يحتوي إطارات وأدلة guides وشبكات grids وهوامش margins مرئية: يمكن تحريك هذه الإطارات بحريّة على الصفحة ويمكن تحريكها خارج الصفحة ومن صفحة إلى أخرى، وتغيير حجمها، و وكذا معالجة محتوياتها، وبالتالي فإن هدف سكريبوس الأساسي هو معالجة تخطيط مستندك بمستوى عالٍ من الإتقان من ناحية الموضع والدقة Resolution وإدارة الألوان، بحيث يمكن إنجاز هذا العمل على مستوى احترافي. الميزة الأخرى المهمة لعمل التخطيط هي القدرة على العمل ضمن طبقات، وبالتالي لدينا في الشكل السابق إطار رمادي بحجم الصفحة، مع وضع جميع الإطارات الأخرى فوقه. يمكننا تحريك الكائنات إلى أعلى وأسفل الطبقات إذا دعت الحاجة لذلك، مما يؤدي إلى جعل الكائنات مرئيةً تمامًا أو مرئيةً جزئيًا أو مخفيةً تمامًا. لا تظهر بعض الأشياء التي تظهر على الشاشة أبدًا في العمل النهائي، مثل مؤشرات الهوامش والأدلة وخطوط الشبكة، والتي تُستخدَم ببساطة للمساعدة في محاذاة الكائنات على الصفحة ومحاذاة بعضها البعض. ليست بعض الأشياء الأخرى التي قد يتوقع المرء طباعتها دائمًا مطلوبة، فقد تكون الكائنات مخفية أو مرئية ولكنها لا تُطبَع ولا تظهر في المنتج النهائي (ملف PDF)، وهذه الميزة مفيدة للغاية. التمهيد للاستخدام تحتوي الملفات مع كل إصدار على عدد من معاملات عملك والتي لم تكن جزءًا من الإصدارات السابقة. التأثير الأكبر على المستخدم هو أن إصدارات Scribus الحالية يمكنها تحميل الملفات المُنشَأة باستخدام إصدارات أقدم، ولكنها ستحفظها بالتنسيق الأحدث فقط. لا يمكن للإصدارات الأقدم تحميل ملفات أحدث لسوء الحظ، وسيؤدي ذلك إلى حدوث خطأ. لذلك إذا كنت بحاجة إلى مشاركة ملفات Scribus مع شخص آخر، فاستخدم نفس الإصدار الذي يستخدمه. المشكلة التي تنشأ عند تبديل التنسيقات يحدث تغيير في عرض النص داخل إطارات النص مع استمرار تطوير برنامج سكريبوس، بحيث قد تُعرض الأحرف بالنسبة لخط معين بالقرب من حد الإطار العلوي، وقد تكون هناك اختلافات في المساحة المطلوبة أسفل الحرف، بالإضافة إلى بعض الاختلافات في تباعد الأسطر. لذلك توقع بعض التغيير والتبديل في إطارات النص عند تحميل ملفات قديمة في إصدارات أحدث من برنامج سكريبوس، ولاحظ أيضًا أنه يُرجَّح أن تحدث هذه الاختلافات إن استخدمت إصدارات لم تُعرَّف على أنها مستقرة. هذا سبب آخر لاستخدام نفس إصدار سكريبوس أثناء العمل في مشروع فردي، وبالتالي ستظل قادرًا على إنجاز عملك عند عدم تحديث الإصدار أثناء العمل على شيء مهم، ولك يجب أن تضيف إصلاحات إضافية إليه. الأعمدة Columns تُعَد الأعمدة مصدرًا شائعًا للارتباك، وأحيانًا الرعب بالنسبة للأشخاص الذين يتعاملون مع برنامج سكريبوس للمرة الأولى. حيث يرغب المستخدِمون الجدد في كثير من الأحيان، في إسناد "خاصية الأعمدة" إلى صفحة المستند، ولكن الصفحة هي مجرد مساحة العمل الخاصة بك، حيث تحدّد حدود مشروعك. طرق إنشاء بيئة الأعمدة والعمل فيها يمكن أن تحتوي إطارات النص على أعمدة. حيث ستجد بمجرد أن يكون لديك إطار نص، أنه يمكن ضبط هذا الإطار في أداة الخصائص Properties Tool ضمن تبويب الشكل Shape، الذي يمكن الوصول إليه من خلال الذهاب إلى نافذة خصائص ثم اختيار الشكل، حيث يمكنك ضبط عدد الأعمدة والفراغ بين الأعمدة، لكن قد يصبح استخدام عدد كبير جدًا من الأعمدة مع حجم الإطار الخاص بك أمرًا غير جميل للغاية. إذا سئمت من ضبط هذه الأعمدة بصورة متكررة، فيمكنك جعل الأعمدة ميزة افتراضية لإطارات النص الخاصة بك، من خلال الانتقال إلى قائمة الإعدادات Settings ثم اختيار التفضيلات Preferences، ثم الأدوات Tools في الإصدارات 1.2.x، وانتقل إلى قائمة ملف File ثم اختر تفضيلات Preferences، ثم أدوات Tools في الإصدارات 1.3.x. إذا كان لديك مستند مفتوح أثناء إعداد التفضيلات، فستُطبَّق الإعدادات الجديدة على المستندات المستقبلية وليس على المستندات الحالية. يمكنك في الإصدارات 1.3.x تعديل هذه الميزة الخاصة بالمستند الحالي من قائمة ملف File ثم إعداد المستند Document Setup. يمكنك أيضًا استخدام ميزة أدلة الأعمدة في الصفحة التي قد تكون مصدر ارتباك للبعض، ولكنها مجرد أدلة، حيث يمكنك إنشاء إطارات نص مرتبة في أعمدة على الصفحة بمجرد أن تكون لديك أدلة (أو حتى بدونها)، ثم ربطها من إطار إلى آخر ضمن تدفق النص. يتيح لك ذلك استخدام أعمدة متفاوتة العرض، أو مرتَّبة ترتيبًا غير عادي، أو ذات نمط ارتباط غير نموذجي. الاستفادة القصوى من برنامج سكريبوس يُعَد برنامج Scribus معقدًا، وكثيرًا ما نحصل على تعليقات من الأشخاص الذين واجهوا صعوبات في تنفيذ بعض العمليات يدويًا، والتي يمكن تحقيقها باستخدام أدوات مُدمَجة. سنحاول مساعدتك في التعرف على هذه الأدوات عند بدء مشروعاتك. المستند ومساحة العمل يسهّل تعديلان اثنان من استخدام برنامج Scribus، حيث أن التعديل الأول هو وحدات العرض، أينما عليك استخدام وحدات صغيرة مثل المليمترات "mm" أو النقاط "pt"، وذلك للحصول على أفضل دقة لموضع واستخدام الصناديق المختلفة. يمكن ضبط أو إعادة ضبط هذه الوحدات بسرعة باستخدام الأداة الموجودة في الزاوية اليسرى السفلية من النافذة الرئيسية، والتي تعرض وحدات العرض الحالية، كما يمكنك ضبط الوحدات للمستندات المستقبلية من قائمة ملف File ثم اختر تفضيلات Preferences، ثم إعداد المستند Document. أما التعديل الثاني، فيجب أن تدرك فيه أن موضع مستندك على خلفية مساحة العمل قابلٌ للتعديل، وهنا انتقل إلى قائمة ملف File ثم اختر إعداد المستند Document Setup ثم عرض Display، أو انتقل إلى قائمة ملف File ثم اختر تفضيلات Preferences ثم عرض Display، لضبط مكان وجود المستند ضمن مساحة العمل هذه. الشبكات Grids والأدلة Guides يتضمن تصميم مخطط المستند إنشاء توزيع جميل للعناصر، وهذا بدوره يتطلب وضعًا ومحاذاةً دقيقةً للكائنات المختلفة على الصفحة، حيث سيساعدك استخدام الشبكات والأدلة في تحقيق أقصى استفادة من المساحة المتاحة لديك، والمساعدة في تحديد الموضع بدقة. السلوك الافتراضي هو إخفاء الشبكات والأدلة، ولكن يمكنك عرضها باستخدام قائمة "عرض View" ثم خيار إظهار الشبكة Show Grid، ومن خلال قائمة "عرض" ثم الخيار إظهار الأدلة Show Guides. يمكنك ضبط الشبكة من خلال الانتقال إلى قائمة ملف File ثم إعداد المستند Document Setup، ثم الأدلة Guides، حيث يمكنك أيضًا تحديد إظهار أو إخفاء الشبكة والأدلة. إذا أردت تغيير الإعدادات لجميع المستندات المستقبلية، فانتقل إلى قائمة "ملف"، ثم اختر تفضيلات Preferences، ثم "الأدلة Guides". إذا فعّلتَ الإعدادات الافتراضية من قائمة "العرض" ثم الأدلة Guides، فسترى أنه لا توجد أدلة لتراها، ولهذا يجب عليك إنشاء هذه الأدلة من خلال قائمة صفحة Page ثم إدارة الأدلة Manage Guides، حيث يمكنك إنشاء العديد من الأدلة الأفقية والرأسية التي تريدها. لاحظ أيضًا من قائمة صفحة Page الخيارَ "اتبع الشبكة Snap to Grid"، والخيار "اتبع الأدلة Snap to Guides"، التي ستساعدك في ربط كائن "مغناطيسيًا" بالشبكة أو الأدلة. الطبقات Layers لن تستفيد مستندات متعددة شيئًا من استخدام الطبقات بسبب بساطتها، ولكن يجب أن نتذكر أن هذه الإمكانية موجودةذ، حيث سيسمح لك استخدام الطبقات في تخطيطٍ معقّد يحتوي أنواعًا متعددةً من العناصر المختلفة بالتركيز على طبقة واحدة من الكائنات دون القلق بشأن التداخل مع تلك الكائنات الموجودة في طبقة أخرى. يمكن أيضًا جعل الطبقة بأكملها غير مرئية، وبالتالي يمكن استبعادها من الطباعة، وهي ميزة مفيدة جدًا عند استخدامها لوضع مجموعة من التعليقات التوضيحية التي لن تصبح جزءًا من الخرج النهائي. الصفحات الرئيسية Master Pages قد تُنشئ مستندًا به مجموعة عناصر مثل العناوين أو الحدود أو أرقام الصفحات، والتي ستكون ثابتةً في جميع الصفحات، أو قد تُعِدّ صفحات رئيسية لرسالة إخبارية أسبوعية أو شهرية. تبقى الصفحات الرئيسية مثل ميزة خلفية ثابتة بمجرد إنشائها وتحريرها، وتوضع فوقها العناصر القابلة للتعديل، حيث قد يحتوي المستند على أكثر من نوع واحد من الصفحات الرئيسية، ولكن يمكن لكل صفحة أن تستخدم نوعًا واحدًا فقط. ترجمة -وبتصرّف- للمقال Working with Scribus: How to begin لصاحبه Gregory Pittman.
-
لا يملك الكثير من المبرمجين الذين يصنعون أروع البرامج وأكثرها فائدةً اليوم -مثل العديد من الأشياء التي نراها على الإنترنت أو نستخدمها يوميًا- خلفيةً نظريةً في علوم الحاسوب، لكنهم لا يزالون مبرمجين رائعين ومبدعين ونقدِّر ما يبنونه، حيث تملك علوم الحاسوب النظرية استخداماتها وتطبيقاتها، ويمكن أن تكون عمليةً تمامًا. يستهدف هذا المقال المبرمجين الذين يعرفون عملهم جيدًا ولكنهم لا يملكون خلفيةً نظريةً في علوم الحاسوب، وذلك من خلال واحدة من أكثر أدوات علوم الحاسوب واقعيةً، وهي: صيغة O الكبير Big O notation، وتحليل تعقيد الخوارزمية algorithm complexity. تُعَدّ هذه الأداة واحدةً من الأدوات المفيدة عمليًا للأشخاص العاملين في المجال الأكاديمي لعلوم الحاسوب، وفي إنشاء برامج على مستوى الإنتاج في الصناعة، لذلك نأمل أن تتمكن من تطبيقها في الشيفرة الخاصة بك لتحسينها بعد قراءة هذا المقال، كما يُفتَرض أن تكون قادرًا على فهم جميع المصطلحات الشائعة التي يستخدمها المختصون في علوم الحاسوب، مثل مصطلحات: التعقيد "Big O"، و"السلوك المقارب asymptotic behavior"، و"تحليل الحالة الأسوأ worst-case analysis" بعد قراءة هذا المقال. يستهدف هذا المقال أيضًا طلاب المدارس الإعدادية والثانوية في أي مكان في العالم، والذين يتنافسون دوليًا في الأولمبياد الدولي للمعلوماتية، أو مسابقة الخوارزميات الطلابية، أو مسابقات أخرى مماثلة. لا يحتوي هذا المقال على أي متطلبات رياضية مسبقَة، كما سيمنحك الخلفية التي ستحتاجها لمواصلة دراسة الخوارزميات مع فهمٍ أقوى للنظرية الكامنة وراءها، وننصح الأشخاص الذين يشاركون في هذه المسابقات الطلابية بشدة بقراءة هذا المقال التمهيدي بأكمله ومحاولة فهمه تمامًا، لأنه سيكون ضروريًا أثناء دراسة الخوارزميات وتعلُّم المزيد من التقنيات المتقدِّمة. سيكون هذا المقال مفيدًا للمبرمجين الصناعيين الذين ليس لديهم خبرة كبيرة في علوم الحاسوب النظرية، ونظرًا لتخصيص هذا المقال للطلاب، فقد يبدو في بعض الأحيان مثل كتاب مدرسي، حيث قد ترى بعض الموضوعات شديدة الوضوح لأنك رأيتها خلال سنوات دراستك على سبيل المثال، لذلك يمكنك تخطيها إذا شعرت أنك تفهمها. تصبح الأقسام الأخرى أقل عمقًا ونظريًا، حيث يحتاج الطلاب المشاركون في هذه المسابقات إلى معرفة المزيد عن الخوارزميات النظرية أكثر من ممارس المهنة العادي، ولا تزال معرفة هذه الأشياء أمرًا جيدًا بما أنها ليست صعبةً كثيرًا، لذا يستحق ذلك الأمر إعطاءه بعضًا من وقتك. لا تحتاج إلى خلفية رياضية لأن النص الأصلي لهذا المقال قد استهدف طلاب المدارس الثانوية، لذلك سيكون أي شخصٍ لديه بعض الخبرة في البرمجة -أي إن عرف ما هي العَودية recursion على سبيل المثال- قادرًا على المتابعة دون أي مشكلة. ستجد خلال هذا المقال العديد من الروابط التي تنقلك للاطلاع على مواد مهمة خارج نطاق موضوع المقال، إذ يُحتمل درايتك بمعظم هذه المفاهيم إذا كنت مبرمجًا صناعيًا؛ أما إذا كنت طالبًا مشاركًا في المسابقات، فسيعطيك اتباع هذه الروابط أفكارًا حول مجالات أخرى من علوم الحاسوب أو هندسة البرمجيات التي ربما لم تستكشفها بعد، والتي يمكنك الاطلاع عليها لتوسيع اهتماماتك. يصعب على الكثير من المبرمجين والطلاب فهم تحليل تعقيد الخوارزمية وصيغة Big O، أو يخافون منه، أو يتجنبونه تمامًا ويعدّونه عديم الفائدة، لكنه ليس صعبًا أو نظريًا كما قد يبدو للوهلة الأولى. يُعَدّ تعقيد الخوارزمية طريقةً لقياس سرعة تشغيل برنامج ما أو خوارزمية ما، لذلك يُعَد أمرًا عمليًا. الدافع Motivation يوجد أدوات لقياس مدى سرعة تشغيل البرنامج، فهناك برامج تسمى المشخِّصات profilers، حيث تقيس وقت التشغيل بالميلي ثانية ويمكنها مساعدتنا في تحسين الشيفرة الخاصة بنا عن طريق تحديد الاختناقات bottlenecks، وعلى الرغم من فائدة هذه الأداة إلا أنها ليست ذات صلة فعلية بتعقيد الخوارزمية، فتعقيد الخوارزمية مصمَّمٌ لمقارنة خوارزميتين ضمن المستوى المثالي، أي تجاهل التفاصيل منخفضة المستوى، مثل: لغة برمجة التطبيق، أو العتاد الذي تعمل عليه الخوارزمية، أو مجموعة تعليمات وحدة المعالجة المركزية CPU. عندما نريد مقارنة الخوارزميات من حيث ماهيتها -أي الأفكار التي تُعرّفنا كيفية حساب شيءٍ ما-، فلن يساعدنا العد بالميلي ثانية في ذلك، إذ يُحتمَل أن تعمل الخوارزمية السيئة والمكتوبة بلغة برمجة منخفضة المستوى مثل لغة التجميع Assembly، بصورة أسرع بكثير من خوارزمية جيدة مكتوبة بلغة برمجة عالية المستوى مثل بايثون، أو روبي، لذلك يجب تحديد معنى "الخوارزمية الأفضل". بما أن الخوارزميات هي برامج تجري عمليات حسابية فقط، ولا تجري أشياءً أخرى تقوم بها الحواسيب، مثل: مهام الشبكات، أو دخل المستخدم، وخرجه؛ فسيسمح لنا ذلك بتحليل التعقيد بقياس مدى سرعة البرنامج عند إجراء العمليات الحسابية. تتضمن أمثلة العمليات الحسابية البحتة العمليات العشرية العددية numerical floating-point operations، مثل: الجمع والضرب، أو البحث داخل قاعدة بيانات متناسبة مع الذاكرة العشوائية RAM عن قيمة معينة، أو تحديد المسار الذي ستمر به شخصية ذكاء اصطناعي في لعبة فيديو، بحيث يتعين عليها فقط السير مسافةً قصيرةً داخل عالمها الافتراضي (كما في الشكل الآتي)، أو تشغيل تطابق نمط تعبير نمطي regular expressions مع سلسلة، فالعمليات الحسابية موجودة في كل مكان في البرامج الحاسوبية. تستخدم شخصيات الذكاء الاصطناعي في ألعاب الفيديو الخوارزميات لتجنب العقبات عند تنقّلها في العالم الافتراضي يُعَدّ تحليل التعقيد أداةً لشرح كيفية تصرّف الخوارزمية مع زيادة حجم الدخل. وهنا نتساءل، إذا زدنا الدخل، فكيف ستتصرّف الخوارزمية؟ أي إذا كانت الخوارزمية الخاصة بنا تستغرق ثانيةً واحدةً للتشغيل بالنسبة إلى دخلٍ بحجم 1000، فكيف ستتصرف الخوارزمية إذا ضاعفنا حجم الدخل؟ هل ستعمل بالسرعة نفسها، أم بنصف السرعة، أم أبطأ بأربع مرات؟ يُعَدّ هذا مهمًا في البرمجة العملية لأنه سيسمح لنا بالتنبؤ بسلوك الخوارزمية عندما تصبح بيانات الدخل أكبر؛ فمثلًا، إذا أنشأنا خوارزميةً لتطبيق ويب يعمل جيدًا مع 1000 مستخدِم، وقِسنا وقت تشغيله باستخدام تحليل تعقيد الخوارزمية، فيمكننا توقُّع ما سيحدث بمجرد حصولنا على 2000 مستخدِم بدلًا من ذلك. يمنحنا تحليل التعقيد في مسابقات الخوارزميات رؤيةً عن المدة التي سيستغرقها تشغيل الشيفرة لأكبر حالات الاختبار التي تُستخدَم لاختبار صحة البرنامج، لذلك إذا قِسنا سلوك برنامجنا مع دخل صغير، فسنعرف سلوكه مع الدخل الأكبر. لنبدأ بمثال بسيط هو إيجاد العنصر الأكبر في مصفوفة. عد التعليمات سنستخدم لغات برمجة مختلفة لأمثلة هذا المقال، لكن لا تيأس إن لم تعرف لغة برمجة معينة، وبما أنك تعرف البرمجة، فيجب أن تكون قادرًا على قراءة الأمثلة دون أي مشكلة حتى إن لم تكن على دراية بلغة البرمجة المختارة، لأنها ستكون بسيطةً ولن نستخدم أية ميزات خاصة بلغة معينة. إذا كنت طالبًا منافسًا في مسابقات الخوارزميات، فيُرجَّح استخدمك لغة C++، لذلك لن تواجه مشكلة، وبالتالي نوصي في هذه الحالة التدرّب باستخدام لغة C++. يمكن البحث عن العنصر الأكبر في مصفوفة باستخدام شيفرة لغة جافا سكريبت التالية، بافتراض أن مصفوفة الدخل هي A، وحجمها n: var M = A[ 0 ]; for ( var i = 0; i < n; ++i ) { if ( A[ i ] >= M ) { M = A[ i ]; } } أول شيء سنفعله هو حساب عدد التعليمات الأساسية التي ينفذها هذا الجزء من الشيفرة، حيث سنفعل هذا مرةً واحدةً فقط، ولن يكون ضروريًا لاحقًا، لذلك تحمَّل لبضع لحظات. نقسّم الشيفرة إلى تعليماتٍ بسيطة عندما نحللها، فهذه التعليمات البسيطة هي ذات التعليمات، أو قريبة منها، والتي يمكن لوحدة المعالجة المركزية من تنفيذها مباشرةً، كما سنفترض أن معالجنا يمكنه تنفيذ العمليات التالية على أساس تعليمة واحدة لكل منها: إسناد قيمة لمتغير. البحث عن قيمة عنصر معين في مصفوفة. مقارنة قيمتين. زيادة قيمة. العمليات الحسابية الأساسية، مثل: الجمع، والضرب. سنفترض أن التفرع -أي الاختيار بين جزئي if وelse بعد تقييم شرط if- سيحدث على الفور ولن يحسب هذه التعليمات. السطر الأول من الشيفرة السابقة هو: var M = A[ 0 ]; يتطلب هذا السطر تعليمتين: إحداهما للبحث عن العنصر A[ 0 ]، والأخرى لإسناد قيمته إلى M، حيث سنفترض أن قيمة n تساوي 1 على الأقل دائمًا، كما تتطلّب الخوارزمية هاتين التعليمتين دائمًا، بغض النظر عن قيمة n، ويجب أيضًا تشغيل شيفرة تهيئة حلقة for دائمًا، ويعطينا هذا تعليمتين أخريين، هما: الإسناد assignment، والمقارنة comparison: i = 0; i < n; ستشغَّل هاتان التعليمتان قبل أول تكرار من حلقة for، كما نحتاج إلى تعليمتين إضافيتين للتشغيل بعد كل تكرار لحلقة for، وهما: زيادة المتغير i، ومقارنة للتحقق من أننا ما زلنا ضمن الحلقة، أي كما يلي: ++i; i < n; إذا تجاهلنا جسم الحلقة، فسيكون عدد التعليمات التي تحتاجها هذه الخوارزمية هو 4 + 2n، أي 4 تعليمات في بداية حلقة for، وتعليمتين في نهاية كل تكرار من n تكرار. يمكننا الآن تحديد دالة رياضية f( n )، حيث تعطينا عدد التعليمات التي تحتاجها الخوارزمية عند إعطاء n، أي لدينا f( n ) = 4 + 2n عندما يكون جسم حلقة for فارغًا. تحليل الحالة الأسوأ Worst-case analysis لدينا بالنظر إلى جسم حلقة for عملية بحث في مصفوفة، وعملية مقارنة تحدث دائمًا، كما يلي: if ( A[ i ] >= M ) { … أي يوجد تعليمتان، ولكن اعتمادًا على قيم المصفوفة، فقد يعمل جسم تعليمة if وقد لا يعمل. فإذا تحقق A[ i ] >= M، فسنشغّل هاتين التعليمتين الإضافيتين -أي البحث في مصفوفة والإسناد-، كما يلي: M = A[ i ] لكن لا يمكننا الآن تحديد الدالة f( n ) بسهولة، وذلك لعدم اعتماد عدد التعليمات على n فقط، وإنما على الدخل أيضًا، فإذا كان الدخل A = [ 1, 2, 3, 4 ] مثلًا، فستحتاج الخوارزمية إلى تعليمات أكثر مما إذا كان الدخل A = [ 4, 3, 2, 1 ]. نفكر عند تحليل الخوارزميات في أسوأ سيناريو غالبًا، فما هو أسوأ شيء يمكن حدوثه لخوارزميتنا؟ ومتى تحتاج الخوارزمية إلى معظم التعليمات لإكمالها؟ في هذه الحالة، يحدث ذلك عندما يكون لدينا مصفوفة بترتيب تصاعدي مثل A = [ 1, 2, 3, 4 ]، حيث يجب استبدال المتغير M في كل مرة، وبالتالي، سينتج عن ذلك تنفيذ معظم التعليمات، ويُطلَق على هذه الحالة اسم تحليل الحالة الأسوأ Worst-case analysis؛ وهذا ليس أكثر من مجرد التفكير في الحالة التي تحدث عندما نكون الأقل حظًا. لدينا في أسوأ الحالات 4 تعليمات للتشغيل داخل جسم حلقة for، لذلك لدينا f( n ) = 4 + 2n + 4n = 6n + 4، حيث تعطينا الدالة f عدد التعليمات التي قد تكون مطلوبةً في الحالة الأسوأ بالاعتماد على حجم المشكلة n. السلوك المقارب Asymptotic behavior تمنحنا الدالة السابقة فكرةً جيدةً عن مدى سرعة الخوارزمية، ولكن كما وعدناك، فلن تحتاج إلى القيام بالمهمة الشاقة المتمثلة في عد التعليمات في البرنامج. يعتمد عدد تعليمات وحدة المعالجة المركزية الفعلية اللازمة لكل عبارة لغة برمجة، على مُصرِّف compiler لغة البرمجة، وكذا على مجموعة تعليمات وحدة المعالجة المركزية المتاحة، سواءً كان معالج AMD أو Intel Pentium على حاسوبك، أو كان معالج MIPS على Playstation 2 الخاصة بك، وسنتجاهل ذلك أيضًا كما ذكرنا سابقًا. سنشغّل الآن الدالة "f" الخاصة بنا من خلال "مرشِّح filter" ليساعدنا في التخلص من التفاصيل الصغيرة التي يفضّل المتخصصون في علوم الحاسوب تجاهلها. يوجد قسمان في الدالة f التي تساوي 6n + 4، وهما: 6n، و4، كما لا نهتم في تحليل التعقيد إلا بما يحدث لدالة عد التعليمات عندما يكبر دخل البرنامج (n)، ويتماشى هذا مع الأفكار السابقة لسلوك "السيناريو الأسوأ" الذي ينص على الاهتمام بكيفية تصرّف الخوارزمية عند معالجتها بصورة سيئة، أي عندما تفعل هذه الخوارزمية شيئًا صعبًا، وهذا مفيد حقًا عند مقارنة الخوارزميات. إذا تغلبت خوارزمية على خوارزمية أخرى عند استخدام دخل كبير، فيُرجَّح أن الخوارزمية الأسرع ستبقى أسرع عند إعطاء دخلٍ أسهل وأصغر. سنحذف الأقسام التي تنمو ببطء ونبقي فقط الأقسام التي تنمو بسرعة عندما تصبح n أكبر، ومن الواضح أن 4 ستبقى 4 لأن n تنمو بصورة أكبر؛ أما 6n فتنمو بصورةٍ أكبر وأكبر، لذلك تميل إلى كونها أهم بالنسبة للمشكلات الأكبر، وبالتالي، أول شيء سنفعله هو حذف 4 والاحتفاظ بالدالة على صورة f( n ) = 6n. يُعَدّ ما سبق منطقيًا، وذلك لأنّ الرقم 4 هو "ثابت التهيئة initialization constant" ببساطة، وقد تتطلب لغات البرمجة المختلفة وقتًا مختلفًا لعملية الإعداد، فمثلًا، تحتاج لغة جافا إلى بعض الوقت لتهيئة آلتها الافتراضية virtual machine، وبما أننا نتجاهل الاختلافات في لغات البرمجة، فمن المنطقي تجاهل هذه القيمة فقط. الشيء الثاني الذي سنتجاهله هو معامل الضرب الثابت أمام n، وبالتالي ستصبح الدالة f( n ) = n، مما يجعل الأمور أكثر بساطةً. يُعَدّ إهمال معامل الضرب أمرًا منطقيًا إذا فكرنا في كيفية تصريف لغات البرمجة المختلفة، فقد تُصرَّف عبارة "البحث في المصفوفة" في إحدى لغات البرمجة إلى تعليمات مختلفة عن لغات برمجةٍ مختلفة، كما لا يتضمّن الإجراء A[ i ] التحقق من عدم تجاوز المتغير i لحجم المصفوفة المُصرَّح عنها في لغة سي C على سبيل المثال، ولكنه يتضمّن ذلك في لغة باسكال Pascal؛ إذًا فالشيفرة التالية المكتوبة بلغة باسكال: M := A[ i ] تكافئ الشيفرة التالية المكتوبة بلغة سي: if ( i >= 0 && i < n ) { M = A[ i ]; } لذلك نتوقّع أن لغات البرمجة المختلفة ستنتج عوامِلًا مختلفةً عندما نعُد تعليماتها. تستخدِم لغة باسكال مصرِّفًا غبيًا يغفَل عن التحسينات الممكنة في هذا المثال، كما تتطلب ثلاث تعليمات لكل وصول إلى مصفوفة، في حين تتطلب لغة سي تعليمةً واحدةً. يُطبَّق إهمال هذا العامل على جميع الاختلافات بين لغات البرمجة والمصرِّفات أيضًا، وبالتالي، تُحلَّل فكرة الخوارزمية فقط. يُسمَّى المرشِّح المتمثِّل بعمليتَي "إهمال جميع العوامل"، و"الإبقاء على القسم الذي يكبر أكثر" كما هو موصوف أعلاه بالسلوك المقارب asymptotic behavior، ولذلك نمثِّل السلوك المقارب للدالة f( n ) = 2n + 8 من خلال الدالة f( n ) = n. نهتم رياضيًا بنهاية الدالة f لأن n يميل إلى اللانهاية؛ ولكن إن لم تفهم ما تعنيه هذه العبارة، فلا تقلق لأنّ هذا كل ما تحتاج إلى معرفته، كما لن نستطيع إهمال الثوابت في النهاية في إطار رياضي صارم، ولكننا نفعل ذلك لأغراض علوم الحاسوب وللأسباب الموضَّحة أعلاه. سنحل بعض الأمثلة لفهم الفكرة أكثر، فمثلًا، لنجد السلوك المقارب لدوال المثال التالي بإهمال العوامِل الثابتة، والحفاظ على الأقسام التي تكبر بسرعة: تعطي الدالة f( n ) = 5n + 12 الدالة f( n ) = n باستخدام الاستنتاج نفسه بالضبط كما هو مذكور أعلاه. تعطي الدالة f (n) = 109 الدالة f( n ) = 1، حيث سنهمل معامل الضرب 109 * 1، لكن لا يزال يتعين علينا وضع 1 هنا للإشارة إلى أنّ لهذه الدالة قيمة غير صفرية. تعطي الدالة f( n ) =n2 + 3n + 112 الدالة f( n ) = n2، حيث تكبرn2 أكثر من 3n بالنسبة لقيمة n كبيرة بدرجة كافية، لذلك نحتفظ بها. تعطي الدالة f( n ) = n3 + 1999n + 1337 الدالة f( n ) = n3، فعلى الرغم من أنّ العامل الموجود أمام n كبير جدًا، لكن لا يزال بإمكاننا العثور على قيمة n كبيرة بما يكفي، بحيث يكون n3 أكبر من 1999n، وبما أننا مهتمون بسلوك قيم n الكبيرة جدًا، فسنبقي على n3 فقط، أي تصبح الدالة n3 المرسومة باللون الأزرق في الشكل التالي أكبر من الدالة 1999n المرسومة باللون الأحمر بعد القيمة n = 45، كما تبقى هي الأكبر بعد هذه النقطة إلى الأبد. تعطي الدالة f( n ) = n +√n الدالة f (n) = n، وذلك لأنّ n تنمو أسرع من √n كلما زادتn ويمكنك تجربة الأمثلة الآتية بنفسك. تمرين 1 f( n ) = n6 + 3n f( n ) = 2n + 12 f( n ) = 3n + 2n f( n ) = nn + n (اكتب نتائجك، وسترى الحل أدناه). إذا واجهتك مشكلة مع أحد العناصر المذكورة أعلاه، فجرِّب بعض قيم n الكبيرة لمعرفة القسم الأكبر، وهذا بسيط جدًا، أليس كذلك؟ التعقيد Complexity بما أنه يمكننا إهمال كل هذه الثوابت "الشكلية"، فمن السهل جدًا معرفة السلوك المقارب لدالة عدّ تعليمات البرنامج، حيث يملك البرنامج الذي لا يحتوي على حلقات، الدالة f( n ) = 1، لأن عدد التعليمات التي يحتاجها هو مجرد عددٍ ثابت -إلا في حالة استخدامه العودية كما سنرى لاحقًا-. يملك البرنامج الذي يحتوي حلقةً واحدةً تمتد من 1 إلى n، الدالة f( n ) = n، حيث سينفِّذ عددًا ثابتًا من التعليمات قبل الحلقة، وعددًا ثابتًا من التعليمات بعد الحلقة، وعددًا ثابتًا من التعليمات داخل الحلقة التي تُشغَّل جميعًا n مرة. يجب أن يكون هذا أكثر سهولةً وأقل مللًا من عدّ التعليمات الفردية، لذلك لنلقِ نظرةً على بعض الأمثلة لفهم ذلك أكثر. يتحقق البرنامج التالي المكتوب بلغة PHP من وجود قيمة معيَّنة داخل مصفوفة A لها الحجم n: <?php $exists = false; for ( $i = 0; $i < n; ++$i ) { if ( $A[ $i ] == $value ) { $exists = true; break; } } ?> تسمَّى هذه الطريقة للبحث عن قيمة داخل مصفوفة البحث الخطي linear search، وهذا اسم معقول لاحتواء هذا البرنامج على الدالة f( n ) = n، كما سنحدد بالضبط ما تعنيه كلمة "خطي" في القسم التالي. لاحظ وجود عبارة "break" هنا، والتي قد تؤدّي إلى إنهاء البرنامج في وقت قريب، وربما بعد تكرارٍ واحد؛ لكن تذكّر اهتمامنا بالسيناريو الأسوأ، وهو بالنسبة لهذا البرنامج عدم احتواء المصفوفة A على القيمة التي نبحث عنها، لذلك لا يزال لدينا الدالة f( n ) = n. تمرين 2 حلّل عدد التعليمات التي يحتاجها برنامج PHP أعلاه بالنسبة إلى n في الحالة الأسوأ للعثور على الدالة ( f( n، وذلك على غرار الطريقة التي حلّلنا بها البرنامج الأول المكتوب بلغة جافا سكريبت، ثم تحقق من أنه لدينا f( n ) = n بصورةٍ مقاربة. لنلقِ نظرةً على البرنامج المكتوب بلغة بايثون Python، والذي يجمع عنصرين من مصفوفة معًا لينتج مجموع يُخزَّن في متغير آخر: v = a[ 0 ] + a[ 1 ] لدينا هنا عددٌ ثابت من التعليمات، لذلك f (n) = 1. يتحقق البرنامج التالي المكتوب بلغة C++ من احتواء متّجه -مصفوفة مختارة أو جزء من مصفوفة- يُسمَّى A، وذو حجم n على قيمتين متماثلتين في أي مكان ضمنه: bool duplicate = false; for ( int i = 0; i < n; ++i ) { for ( int j = 0; j < n; ++j ) { if ( i != j && A[ i ] == A[ j ] ) { duplicate = true; break; } } if ( duplicate ) { break; } } بما أنه توجد هنا حلقتان متداخلتان داخل بعضهما البعض، فسيكون لدينا سلوكًا مقاربًا موصوفًا بالدالة f( n ) = n2. إذا استدعى برنامج دالةً داخل حلقة وعرفنا عدد التعليمات التي تجريها الدالة المستدعاة، فمن السهل تحديد عدد تعليمات البرنامج بأكمله. لنلقِ نظرةً على المثال التالي المكتوب بلغة ? int i; for ( i = 0; i < n; ++i ) { f( n ); } إذا علمنا أن f( n ) هي دالة تنفِّذ n تعليمة بالضبط، فيمكننا حينئذٍ معرفة أن عدد تعليمات البرنامج بأكمله هو n2 بصورةٍ مقاربة، حيث تُستدعى الدالة n مرة تمامًا. ننتقل الآن إلى الصيغة التخيُّلية التي يستخدمها علماء الحاسوب للسلوك المقارب، حيث سنقول أن برنامجنا هو Θ ( f( n )) عندما نحدِّد الدالة f بصورة مقاربة، فمثلًا، البرامج المذكورة أعلاه هي Θ (1) وΘ( n2 ) وΘ( n2 ) على التوالي، حيث تُقرَأ Θ( n ) "ثيتا بالنسبة إلى n". نقول أحيانًا أنّ f( n ) -وهي الدالة الأصلية التي تحسب عدد التعليمات بما في ذلك الثوابت- هي شيء ما Θ، حيث نقول مثلًا أنّ f( n ) = 2n هي دالة Θ( n )، كما يمكننا كتابة 2n ∈ Θ (n) أيضًا، والتي تُنطَق "2n هي ثيتا بالنسبة إلى n". لا ترتبك بشأن هذا الصيغة، فكل ما تنص عليه هو أنه إذا حسبنا عدد التعليمات التي يحتاجها البرنامج وهي 2n، فسيُوصَف السلوك المقارب للخوارزمية بـ n والذي نتج بإهمال الثوابت. فيما يلي بعض العبارات الرياضية الصحيحة باستخدام هذا الصيغة: n6 + 3n ∈ Θ( n6 ) 2n + 12 ∈ Θ( 2n ) 3n + 2n ∈ Θ( 3n ) nn + n ∈ Θ( nn ) بالمناسبة، إذا حللت التمرين 1 السابق، فهذه هي بالضبط الإجابات التي يجب أن تصل إليها. نسمّي ما نضعه ( هنا )Θ التعقيد الزمني time complexity، أو تعقيد complexity الخوارزمية، لذلك فللخوارزمية التي تحتوي على الصيغة Θ( n ) تعقيدٌ هو n. لدينا أيضًا أسماءً خاصةً للصيغ التالية: Θ( 1 )، وΘ( n )، وΘ( n2 ) وΘ( log( n ) )، وذلك لكثرة ظهورها، حيث نقول أنّ خوارزمية Θ( 1 ) هي خوارزمية ذات وقت ثابت constant-time algorithm، والخوارزمية Θ( n ) خطية linear، وΘ( n2 ) تربيعية quadratic؛ أما الخوارمية Θ( log( n ) ) فهي لوغاريتمية logarithmic. لا تقلق إن لم تعرف ما هي اللوغاريتمات حتى الآن، سنشرح ذلك لاحقًا. صيغة O الكبير Big-O notation قد تكون معرفة سلوك الخوارزمية بهذه الطريقة كما فعلنا أعلاه أمرًا صعبًا، خاصةً بالنسبة للأمثلة الأعقد، ولكن يمكننا القول بأن سلوك خوارزميتنا لن يتجاوز أبدًا حدًا معينًا، وبالتالي لن نضطر إلى تحديد السرعة التي تعمل بها الخوارزمية، وذلك حتى عند تجاهل الثوابت بالطريقة التي طبّقناها سابقًا، فكل ما علينا فعله هو إيجاد حدٍ معين، حيث سنشرح ذلك بمثال. مشكلة الفرز (sorting problem) هي إحدى المشكلات الشهيرة التي يستخدمها علماء الحاسوب لتدريس الخوارزميات، حيث تُعطَى مصفوفة A بحجم n في مشكلة الفرز، ويُطلَب منا كتابة برنامج لفرز أو ترتيب هذه المصفوفة، وتُعَدّ هذه المشكلة مشكلةً مهمةً كونها مشكلةً واقعيةً في الأنظمة الحقيقية، إذ يحتاج مستكشف الملفات إلى فرز الملفات التي يعرضها حسب الاسم حتى يتمكن المستخدِم من التنقل بينها بسهولة، أو قد تحتاج لعبة فيديو إلى فرز الكائنات ثلاثية الأبعاد المعروضة في العالم بناءً على بعدها عن عين اللاعب داخل العالم الافتراضي من أجل تحديد ما هو مرئي وما هو غير مرئي، وهو ما يسمى مشكلة الرؤية Visibility Problem، فالكائنات التي تكون أقرب للاعب هي المرئية، في حين أنّ الكائنات البعيدة قد تخفيها الكائنات الموجودة أمامها، ويوضّح الشكل الآتي هذه المشكلة، إذ لن يرى اللاعب الموجود في النقطة الصفراء المناطق المظلَّلة، كما يُعَدّ تقسيم العالم إلى أجزاء صغيرة وفرزها حسب المسافة التي تفصلها عن اللاعب إحدى طرق حل مشكلة الرؤية. يُعَدّ الفرز أيضًا مهمًا بسبب وجود العديد من الخوارزميات لحله، كما يكون بعضها أسوأ من البعض الآخر، وهي أيضًا مشكلة سهلة التحديد والشرح، لذلك لنكتب جزءًا من شيفرة تفرز مصفوفة. الطريقة التالية هي طريقة غير فعالة لفرز مصفوفة في لغة روبي Ruby، حيث تدعم لغة روبي فرز المصفوفات باستخدام دوال مبنيّة مسبقًا يجب استخدامها بدلًا من ذلك، وهي بالتأكيد أسرع مما سنراه هنا، ولكن ما سنستخدمه هنا هي شيفرة بغرض التوضيح فقط: b = [] n.times do m = a[ 0 ] mi = 0 a.each_with_index do |element, i| if element < m m = element mi = i end end a.delete_at( mi ) b << m end تسمى هذه الطريقة الفرز الانتقائي Selection sort، حيث تجد هذه الخوارزمية الحد الأدنى من المصفوفة -يُرمَز إلى المصفوفة بالمتغير a في الشيفرة السابقة، بينما يُرمَز إلى الحد الأدنى بالمتغير m، والمتغير mi هو دليله في المصفوفة-، وتضعه في نهاية مصفوفة جديدة -أي المصفوفة b في حالتنا-، ثم تزيله من المصفوفة الأصلية، وبعدها تجد الحد الأدنى بين القيم المتبقية للمصفوفة الأصلية، وتلحِقه بالمصفوفة الجديدة التي تحتوي على عنصرين الآن، ثم تزيله من المصفوفة الأصلية؛ وتستمر هذه العملية إلى حين إزالة جميع العناصر من المصفوفة الأصلية وإدخالها في المصفوفة الجديدة، مما يعني فرز المصفوفة. نلاحظ وجود حلقتين متداخلتين في الشيفرة السابقة، حيث تعمل الحلقة الخارجية n مرة، وتعمل الحلقة الداخلية مرةً واحدةً لكل عنصر من عناصر المصفوفة a. تحتوي المصفوفة a في البداية على n عنصر، ونزيل عنصر مصفوفة واحد في كل تكرار، لذلك تتكرر الحلقة الداخلية n مرة خلال التكرار الأول للحلقة الخارجية، ثم n - 1 مرة، وبعدها n - 2 مرة، وهكذا دواليك حتى التكرار الأخير للحلقة الخارجية التي تعمل خلالها مرةً واحدةً فقط. من الصعب قليلًا تقييم تعقيد هذا البرنامج، حيث يجب معرفة المجموع 1 + 2 + … +(n+(n-1، ولكن يمكننا بالتأكيد إيجاد "الحد الأعلى" لهذا المجموع، وهذا يعني أنه يمكننا تغيير برنامجنا - أي يمكنك فعل ذلك في عقلك، وليس في الشيفرة الفعلية- لجعله أسوأ مما هو عليه، ومن ثم إيجاد تعقيد هذا البرنامج الجديد، فإذا تمكّنا من العثور على تعقيد البرنامج الأسوأ الذي أنشأناه، فسنعلم أنّ برنامجنا الأصلي أسوأ أو ربما أفضل. بالتالي إذا أوجدنا تعقيدًا جيدًا لبرنامجنا المعدَّل الذي هو أسوأ من برنامجنا الأصلي، فيمكننا معرفة أنه سيكون لبرنامجنا الأصلي تعقيدًا جيدًا جدًا أيضًا، أي إما جيدًا بمستوى برنامجنا المعدَّل أو أفضل منه. لنفكّر في طريقة تعديل هذا البرنامج لتسهيل معرفة تعقيده، ولكن ضع في بالك أنه لا يمكننا سوى جعل الأمر أسوأ هكذا، إذ سيأخذ البرنامج مزيدًا من التعليمات، وبالتالي سيكون تقديرنا مفيدًا لبرنامجنا الأصلي. يمكن تغيير الحلقة الداخلية للبرنامج بجعلها تتكرر n مرة دائمًا بدلًا من تكرارها عددًا متغيرًا من المرات، كما ستكون بعض هذه التكرارات عديمة الفائدة، لكنها ستساعدنا في تحليل تعقيد الخوارزمية الناتجة؛ وإذا أجرينا هذا التغيير البسيط، فمن الواضح أن الخوارزمية الجديدة التي أنشأناها هي Θ( n2 ) وذلك لوجود حلقتين متداخلتين بحيث يتكرر كل منهما n مرة بالضبط، وبالتالي، يمكننا القول أنّ الخوارزمية الأصلية هي O( n2 ). تُنطَق O( n2 ) "أوه كبيرة لمربع n، أي big oh of n squared"، وهذا يقودنا للقول بأن برنامجنا ليس أسوأ من n2 بصورةٍ مقاربة، فقد يكون أفضل من ذلك أو مثله. إذا كان برنامجنا هو بالفعل Θ( n2 ) فلا يزال بإمكاننا القول أنه O( n2 ) أي تخيل تغيير البرنامج الأصلي بطريقة لا تغيره كثيرًا، لكنها لا تزال تجعله أسوأ قليلًا مثل إضافة تعليمات لا معنى لها في بداية البرنامج، بحيث سيؤدي فعل ذلك إلى تغيير دالة عدّ التعليمات بواسطة ثابت بسيط، والذي سنتجاهله عندما يتعلق الأمر بالسلوك المقارب، وبالتالي فالبرنامج Θ( n2 ) هو O( n2 ) أيضًا. قد لايكون البرنامج O( n2 ) هو Θ( n2 ) أيضًا، فأيّ برنامج Θ( n ) مثلًا هو O( n2 ) وO( n ) كذلك، وإذا تخيلنا أن برنامج Θ( n ) هو عبارة عن حلقة for بسيطة تتكرر n مرة، فيمكن جعلها أسوأ بتغليفها ضمن حلقة for أخرى تتكرر n مرة أيضًا، وبالتالي ينتج برنامج له دالة f( n ) = n2، كما يمكن تعميم ذلك بالقول أنّ أي برنامج Θ( a ) هو O( b ) عندما يكون b أسوأ من a. لا يحتاج التغيير الذي أجريناه على البرنامج إلى إعطائنا برنامجًا له معنى أو مكافئًا لبرنامجنا الأصلي، حيث يحتاج فقط إلى تنفيذ تعليمات أكثر من التعليمات الأصلية بالنسبة إلى قيمة n معينة، أي نستخدم هذا التغيير من أجل حساب عدد التعليمات فقط وليس لحل مشكلتنا. لذا يمكن القول بأن برنامجنا هو O( n2 ) بطريقةٍ آمنة، وذلك لأننا حلّلنا خوارزميتنا، ووجدناها ليست أسوأ من n2، ولكنها في الواقع قد تساوي n2، وبالتالي يمكننا تقدير سرعة تشغيل برنامجنا. لنستعرض بعض الأمثلة لتساعدك على التعرف على هذه الصيغة الجديدة. تمرين 3 أيٌّ مما يلي صحيح؟ خوارزمية Θ( n ) هي O( n ) خوارزمية Θ( n ) هي O( n2 ) خوارزمية Θ( n2 ) هي O( n3 ) خوارزمية Θ( n ) هي O( 1 ) خوارزمية O( 1 ) هي Θ( 1 ) خوارزمية O( n ) هي Θ( 1 ) الحل هذا صحيح لأنّ برنامجنا الأصلي كان Θ( n )، ويمكننا تحقيق O( n ) دون تغيير برنامجنا على الإطلاق. هذا صحيح لأنّ n2 أسوأ من n. هذا صحيح لأنّ n3 أسوأ من n2. هذا خطأ لأنّ 1 ليس أسوأ من n، فإذا أخذ البرنامج n تعليمةً بصورةٍ مقاربة -أي عددًا خطيًا من التعليمات-، فلا يمكننا جعله أسوأ ولا يمكن جعله يأخذ تعليمةً واحدةً بصورةٍ مقاربة -أي عددًا ثابتًا من التعليمات-. هذا صحيح لأنّ التعقيدان متماثلان. قد يكون هذا صحيحًا أو غير صحيح وذلك اعتمادًا على الخوارزمية، لكنه خاطئ في الحالة العامة، فإذا كانت الخوارزمية Θ( 1 )، فمن المؤكد أنها O( n )؛ أما إذا كانت O( n ) فقد لا تكون Θ( 1 )، فمثلًا، خوارزمية Θ( n ) هي O ( n ) وليست Θ( 1 ). تمرين 4 استخدم متتالية الجمع الحسابية arithmetic progression sum لإثبات أنّ البرنامج أعلاه ليس O( n2 ) فقط، وإنما Θ( n2 ) أيضًا، ويمكنك البحث عن معنى المتتالية الحسابية في ويكيبيديا في حالة عدم معرفتك بها. يعطي التعقيد O-complexity لخوارزمية ما حدًا أعلى لتعقيد الخوارزمية الفعلي - أي الوقت الأكبر الذي قد تستغرقه الخوارزمية-، بينما تعطي الصيغة Θ تعقيد الخوارزمية الفعلي، حيث نقول أحيانًا أن الصيغة Θ تعطينا حدًا تامًا، وإذا علمت أننا وجدنا حد تعقيدٍ غير تام، فيمكنك استخدام الحرف الصغير o للإشارة إلى ذلك، فمثلًا، إذا كان للخوارزمية التعقيد Θ( n )، فسيكون تعقيدها التام n، وبالتالي سيكون لهذه الخوارزمية O( n ) و O( n2 ) معًا. بما أن الخوارزمية هي Θ( n )، فسيكون حد O( n ) هو الحد التام؛ أما حد O( n2 ) فليس تامًا، ولذلك يمكننا كتابة أن الخوارزمية هي o( n2 ) والتي تُنطق "o الصغير بالنسبة إلى مربع n"، وذلك لتوضيح أن الحد ليس تامًا. كما يُفضَّل إيجاد حدود تامة للخوارزميات لأنها تعطينا مزيدًا من المعلومات حول سلوكها، ولكنه ليس أمرًا سهلًا دائمًا. تمرين 5 حدّد أيًا من الحدود التالية هي حدودًا تامةً وأيها لا، ثم تحقق من صحتها أو خطئها، ويجب عليك استخدام الصيغة o لتحديد الحدود غير التامة: خوارزمية Θ (n) التي لها الحد الأعلى O (n). خوارزمية Θ (n2) التي لها الحد الأعلى O (n3). خوارزمية Θ(1) التي لها الحد الأعلى O (n). خوارزمية Θ (n) التي لها الحد الأعلى O (1). خوارزمية Θ (n) التي لها الحد الأعلى O (2n). الحل الحد تام لأنّ تعقيد Θ وتعقيد O متماثلان في هذه الحالة. الحد غير تام لأنّ تعقيد O أكبر من تعقيد Θ، وقد يكون حد O( n2 ) تامًا، لذلك يمكننا كتابة أن الخوارزمية هي o( n3). الحد غير تام، لأنّ تعقيد O أكبر من تعقيد Θ، وقد يكون حد O( 1 ) تامًا، لذلك يمكننا الإشارة بأنّ الحد O( n ) ليس تامًا من خلال كتابته بالشكل o( n ). الحد خاطئ، فقد اُرتكِب خطأ في حسابه، فلا يمكن أن يكون لخوارزمية Θ( n ) حد أعلى من O( 1 )، وذلك لأنّ التعقيد n أكبر من التعقيد 1 -تذكر أنّ O تعطي حدًا أعلى. الحد تام، فقد يبدو مثل حد غير تام، لكن هذا ليس صحيحًا في الواقع، -تذكر أنّ سلوك 2n وn المقارب هو نفسه، وأنّ الصيغتَين O وΘ تهتمان بالسلوك المقارب؛ إذًا لدينا O( 2n ) = O( n )، وبالتالي، فهذا الحد تام لأن التعقيد هو نفس Θ. قد تجد نفسك تائهًا قليلًا في هذه الصيغة الجديدة، ولكن سنقدم صيغتين آخرين بسيطتين بالنسبة للصيغ Θ، وO، وo قبل انتقالنا إلى بعض الأمثلة، ويُستحسَن أن تعرف هاتين الصيغتَين الآن، حيث لن نستخدمهما كثيرًا في هذا المقال لاحقًا. عدّلنا برنامجنا في المثال أعلاه ليصبح أسوأ -أي أخذ المزيد من التعليمات، وبالتالي المزيد من الوقت- وأنشأنا الصيغة O، حيث تُعَدّ الصيغة O ذا مغزىً لأنها تخبرنا بأن برنامجنا لن يكون أبدًا أبطأ من حدٍ معين، ولهذا فهي توفر معلومات قيّمةً تمكننا من القول بأن برنامجنا جيد بما فيه الكفاية، وإذا فعلنا العكس وعدّلنا برنامجنا ليصبح أفضل، ثم أوجدنا تعقيد البرنامج الناتج، فنستخدم الصيغة Ω التي تعطينا تعقيدًا يخبرنا بأن برنامجنا لن يكون أفضل، وهذا مفيد إذا أردنا إثبات أن البرنامج يعمل ببطء أو أن الخوارزمية سيئة، وقد يكون هذا مفيدًا للقول بأن الخوارزمية بطيئة جدًا عند استخدامها في حالة معينة، فمثلًا، خوارزمية Ω( n3 ) ليست أفضل من n3. قد تكون الصيغة Θ( n3 ) سيئًة مثل Θ (n4) أو أسوأ منها، لكننا نعلم أنها سيئة إلى حد ما على الأقل. إذًا تعطينا الصيغة Ω حدًا أدنى لتعقيد خوارزمية، كما يمكننا كتابة الصيغة ω على غرار الصيغة ο عندما يكون الحد ليس تامًا، فمثلًا، خوارزمية Θ ( n3 ) هي ο( n4 ) وω( n2 ) وتُقرَأ Ω( n ) "أوميغا كبيرة بالنسبة إلى n"، بينما تُقرَأ ω( n ) "أوميغا صغيرة بالنسبة إلى n". تمرين 6 اكتب حد O تام وآخر غير تام، وحد Ω تام وآخر غير تام من اختيارك للتعقيدات التالية، ولكن بشرط وجودهما طبعًا: Θ( 1 ) Θ(√n) Θ( n ) Θ( n2 ) Θ( n3 ) الحل هذا هو تطبيق مباشر للتعاريف أعلاه: الحدود التامة هي O( 1 ) وΩ( 1 )، كما يكون حد O غير التام هو O( n ) -تذكّر أن O تعطينا حدًا أعلى-، وبما أن n أكبر من 1، فسيمثِّل حدًا غير تام يمكننا كتابته بالشكل o( n ) أيضًا، كما لا يمكننا إيجاد حد غير تام للصيغة Ω لعدم تمكننا من الحصول على أقل من 1 لهذه الدوال، إذًا يجب تعاملنا مع الحد التام فقط. يجب أن تكون للحدود التامة تعقيد Θ نفسه، لذا فهي O(√n) وΩ(√n) على التوالي؛ أما الحدود غير التامة فقد تكون O( n )، حيث تُعَدّ n أكبر من √n وبالتالي فهي حد أعلى لها. وبما أننا نعلم أن هذا حدًا أعلى غير تام، فيمكننا أيضًا كتابته بالصورة o( n )؛ أما الحد الأدنى غير التام، فيمكننا ببساطة استخدام Ω( 1 )، وبما أننا نعلم أن هذا الحد ليس تامًا، فيمكننا كتابته بالصورة ω( 1. 3 ). الحدود التامة هي O( n ) وΩ( n ). قد يكون الحدان الغير تامين هما ω( 1 ) وo( n3 ) وهي في الواقع حدودٌ سيئة للغاية، لأنها بعيدة كل البعد عن التعقيدات الأصلية، إلا أنها لا تزال صالحة باستخدام التعاريف. الحدود التامة هي O( n2 ) وΩ( n2 ) ويمكننا استخدام ω( 1 ) وo( n3 ) بالنسبة للحدود غير التامة كما في المثال السابق. الحدود التامة هي O( n3 ) وΩ( n3 ) على التوالي، وقد يكون الحدان غير التامَين هما ω(n2 √n) وω(n3 √n)، وعلى الرغم من أنّ هذه الحدود ليست تامة، إلا أنها أفضل من تلك الموجودة في جواب رقم 3 و4 من هذا التمرين أعلاه. قد تعطي الصيغتان O وΩ أيضًا حدودًا تامة، وسبب استخدامنا لهما بدلًا من الصيغة Θ هو أننا قد لا نكون قادرين على معرفة ما إذا كان الحد الذي أوجدناه تامًا أم لا، أو ربما لا نرغب في متابعة العملية باستخدام الصيغة Θ التي تحتاج تدقيقًا عميقًا. إذا لم تتذكر تمامًا جميع الرموز المختلفة واستخداماتها، فلا تقلق بشأنها كثيرًا الآن، حيث يمكنك دائمًا العودة والبحث عنها، وأهم الرموز هي O وΘ. لاحظ أيضًا أنه على الرغم من كون الصيغة Ω تعطينا سلوكًا ذو حدٍ منخفض للدالة -أي تحسّن برنامجنا وأصبح ينفّذ تعليماتٍ أقل-، إلا أننا ما زلنا نشير إليها بتحليل "الحالة الأسوأ"، لأننا نزوّد برنامجنا بأسوأ دخلٍ ممكن من n ونحلّل سلوكه في ظل هذا الافتراض. يوضح الجدول التالي الرموز التي قدمناها للتو وتوافقاتها مع الرموز الرياضية المعتادة للمقارنات التي نستخدمها مع الأعداد، كما يعود السبب في عدم استخدامنا للرموز المعتادة هنا واستخدام الأحرف الإغريقية بدلًا منها، إلى الإشارة إلى إجراء مقارنة سلوك مقارب وليس مقارنة بسيطة: 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; } عامل المقارنة المقارب Asymptotic comparison operator عامل المقارنة العددي Numeric comparison operator الخوارزمية هي ( شيء ما )o يوجد عدد < هذا الشيء الخوارزمية هي ( شيء ما )O يوجد عدد ≤ هذا الشيء الخوارزمية هي ( شيء ما )Θ يوجد عدد = هذا الشيء الخوارزمية هي ( شيء ما )Ω يوجد عدد ≥ هذا الشيء الخوارزمية هي ( شيء ما )ω يوجد عدد > هذا الشيء اللوغاريتمات Logarithms هل تعرف ما هي اللوغاريتمات؟ إن كانت إجابتك نعم، فلا تتردد في تخطي هذا القسم، فهذا القسم هو مقدمة لمن ليس على دراية باللوغاريتمات، أو لمن لم يستخدمها كثيرًا مؤخرًا، فهو موجَّهٌ للطلاب الأصغر سنًا، والذين لم يروا اللوغاريتمات في المدرسة بعد. تُعَدّ اللوغاريتمات مهمة بسبب ظهورها بكثرة عند تحليل التعقيد، ويُعَدّ اللوغاريتم عمليةً تُطبَّق على رقم ما ليصبح أصغر، حيث تشبه هذه العملية الجذر التربيعي لرقم إلى حد كبير؛ لذلك إذا كان هناك شيء واحد تريد تذكره حول اللوغاريتمات، فهو أنها تأخذ رقمًا وتجعله أصغر بكثير من الأصل. يوضِّح الشكل الآتي مقارنةً بين الدوال n، و√n، وlog( n )، إذ تنمو الدالة n -أو كما تُسمَّى الدالة الخطية linear function- المرسومة باللون الأخضر في أعلى الشكل، أسرع بكثير من دالة الجذر التربيعي المرسومة باللون الأحمر في المنتصف، والتي بدورها تنمو أسرع بكثير من الدالة log( n ) المرسومة باللون الأزرق في الجزء السفلي من هذا الرسم البياني، ويكون الفرق واضحًا تمامًا حتى بالنسبة إلى n صغيرة مثل n = 100. تُعَدّ اللوغاريتمات عمليةً عكسيةً لرفع شيءٍ ما إلى أس مثل الجذور التربيعية التي هي عملية عكسية لتربيع شيءٍ ما، وسنشرح ذلك بمثال. ضع في بالك المعادلة التالية: 2x = 1024 نريد حل هذه المعادلة لإيجاد قيمة x، لذلك لنسأل أنفسنا: ما هو الرقم الذي يجب رفع الأساس 2 إليه حتى نحصل على 1024؟ هذا الرقم هو 10. بالفعل لدينا 210 = 1024، وهو أمر سهل التحقق منه؛ كما تساعدنا اللوغاريتمات من خلال الإشارة إلى هذه المشكلة باستخدام صيغة جديدة، فالرقم 10 في هذه الحالة هو لوغاريتم 1024 ونكتبه بالصورة ( log( 1024 ونقرأه "لوغاريتم 1024". بما أننا نستخدم العدد 2 أساسًا، فتسمى هذه اللوغاريتمات لوغاريتمات الأساس 2، كما توجد لوغاريتمات لها أساسات أخرى، ولكننا سنستخدم فقط لوغاريتمات الأساس 2 في هذا المقال، وإذا كنت طالبًا منافسًا في مسابقات دولية ولا تعرف شيئًا عن اللوغاريتمات، فنوصيك بشِدة بالتدرّب على اللوغاريتمات بعد الانتهاء من هذا المقال. تُعَدّ لوغاريتمات الأساس 2 أكثر أنواع اللوغاريتمات شيوعًا في علوم الحاسوب لأنه غالبًا ما يكون لدينا كيانان مختلفان فقط هما: 0 و1، كما نميل أيضًا إلى تقسيم مشكلة كبيرة واحدة إلى نصفين، لذلك ما عليك سوى معرفة لوغاريتمات الأساس 2 لمتابعة هذا المقال. تمرين 7 حُلّ المعادلات أدناه، وأوجد اللوغاريتم في كل حالة باستخدام اللوغاريتمات ذات الأساس 2 فقط: 2x = 64 (22)x= 64 4x = 4 2x = 1 2x + 2x = 32 (2x) * (2x) = 64 الحل لا يتضمن الحل أكثر من تطبيق الأفكار المُعرَّفة أعلاه: يمكننا باستخدام طريقة التجربة والخطأ إيجاد أن x = 6، وبالتالي، log( 64 ) = 6. يمكن كتابة (22)x بالصورة 22x من خلال تطبيق خصائص الأس، إذًا لدينا 2x = 6 لأن log( 64 ) = 6 من النتيجة السابقة، وبالتالي، x = 3. يمكننا كتابة 4 بالشكل 22 باستخدام معرفتنا من المعادلة السابقة، وبهذا تصبح المعادلة (22)x= 4 وهي 22x = 4 نفسها، ونلاحظ أن log( 4 ) = 2 لأن 22 = 4، وبالتالي، لدينا أن 2x = 2، وعليه فـ x = 1؛ كما يمكن ملاحظة ذلك بسهولة من المعادلة الأصلية، حيث أن ناتج الرفع للأس 1 هو الأساس نفسه. تذكر أن ناتج الرفع للأس 0 هو 1، لذلك لدينا log( 1 ) = 0، بما أنّ 20= 1، وبالتالي، x = 0. لا يمكننا أخذ اللوغاريتم مباشرةً بسبب وجود المجموع، ولكن يمكن ملاحظة أنّ 2x+ 2x هي 2 * (2x) نفسها، حيث ضربنا هنا بالعدد 2 أي لهما الأساس نفسه، وبالتالي، ينتج 2x + 1، والآن كل ما علينا فعله هو حل المعادلة 2x + 1= 32، حيث نجد أنّ log( 32 ) = 5، وهكذا x + 1 = 5، وبالتالي، x = 4. نضرب هنا قوتين للعدد 2 معًا، ولذلك يمكننا ضمهما من خلال ملاحظة أن (2x) * (2x) هي 22x نفسها، وبالتالي كل ما علينا فعله هو حل المعادلة 22x= 64 التي حللناها بالفعل أعلاه، حيث x = 3. التعقيد العودي Recursive complexity لنلقِ نظرةً على دالة عودية recursive function، فالدالة العودية هي دالة تستدعي نفسها. هل يمكننا تحليل تعقيدها؟ توجِد الدالة الآتية والمكتوبة بلغة بايثون، حيث تُقيِّم مضروب factorial عددٍ معين، إذ يمكن إيجاد مضروب عدد صحيح موجب بضربه بجميع الأعداد الصحيحة السابقة معًا، فمثلًا، مضروب العدد 5 هو 5 * 4 * 3 * 2 * 1؛ كما نعبِّر عن ذلك بالصورة "!5" ونقرؤها "مضروب العدد خمسة five factorial"، ويفضِّل بعض الناس نُطقها بصوت عالٍ مثل "خمسة !!!". def factorial( n ): if n == 1: return 1 return n * factorial( n - 1 ) لنحلّل تعقيد هذه الدالة، فعلى الرغم من عدم احتواء هذه الدالة على أية حلقات، إلا أنّ تعقيدها ليس ثابتًا constant، حيث يجب علينا متابعة عد التعليمات مرةً أخرى لمعرفة تعقيدها، فإذا مرّرنا المتغير n إلى هذه الدالة، فستنفّذ n مرة؛ وإذا لم تكن متأكدًا من ذلك، فشغّل هذه الدالة "يدويًا" الآن من أجل n = 5 للتحقق منها. ستنفَّذ هذه الدالة مثلًا 5 مرات من أجل n = 5، بحيث ستستمر في إنقاص قيمة n بمقدار 1 في كل استدعاء، وبالتالي، يكون تعقيد هذه الدالة هو ( Θ( n. إذا لم تكن متأكدًا من هذه الحقيقة، فتذكر أنه يمكنك دائمًا العثور على التعقيد الدقيق عن طريق حساب عدد التعليمات، وإذا رغبت في ذلك، فيمكنك محاولة حساب عدد التعليمات الفعلية التي تطبّقها هذه الدالة لإيجاد الدالة f( n )، والوصول إلى نتيجة أنها خطية بالفعل، مع العلم أنّ خطية تعني Θ( n ). يحتوي الشكل التالي على رسم بياني لمساعدتك على فهم مفهوم العودية المُطبَّقة عند استدعاء الدالة factorial( 5 )، ويجب على هذا الشكل توضيح لماذا تعقيد هذه الدالة هو تعقيد خطي: العودية (معاوة الاستدعاء) التي تطبّقها الدالة factorial التعقيد اللوغاريتمي Logarithmic complexity إحدى المشكلات الشهيرة في علوم الحاسوب هي البحث عن قيمة داخل مصفوفة، ولقد حلّلنا هذه المشكلة سابقًا من خلال الحالة العامة، كما تصبح هذه المشكلة ممتعةً إذا كان لدينا مصفوفة مرتَّبة ونريد إيجاد قيمة معينة بداخلها، حيث تُسمَّى إحدى طرق القيام بذلك البحث الثنائي binary search. ننظر إلى العنصر الأوسط في المصفوفة، وإذا وجدنا العنصر هناك، فقد انتهينا؛ وإلّا فإذا كانت القيمة التي وجدناها أكبر من القيمة التي نبحث عنها، فسنعلم أن العنصر سيكون في الجزء الأيسر من المصفوفة؛ وإلّا فإننا نعلم أنه سيكون في الجزء الأيمن من المصفوفة، كما يمكننا الاستمرار في تقسيم هذه المصفوفات الصغيرة إلى نصفين حتى يتبقّى عنصر واحد فقط، وتوضّح الشيفرة الوهمية التالية هذه الفكرة: def binarySearch( A, n, value ): if n = 1: if A[ 0 ] = value: return true else: return false if value < A[ n / 2 ]: return binarySearch( A[ 0...( n / 2 - 1 ) ], n / 2 - 1, value ) else if value > A[ n / 2 ]: return binarySearch( A[ ( n / 2 + 1 )...n ], n / 2 - 1, value ) else: return true تُعَدّ هذه الشيفرة الوهمية تبسيطًا للتطبيق الفعلي، كما يُعَدّ وصفها أسهل من تطبيقها عمليًا، حيث يحتاج المبرمج إلى الاهتمام ببعض مشاكل التطبيق. يجب تطبيق الدالة floor() أو ceil() بسبب وجود أخطاء بفارق الواحد off-by-one، وقد لا ينتج عن القسمة على العدد 2 قيمةً صحيحةً، فالجزء الصحيح أو المتمم الصحيح الأسفل floor لعدد حقيقي ما x، هو أكبر عدد صحيح ليس أكبر من x، فصحيح العدد 2.6 هو 2، أي أنّ أكبر عدد صحيح ليس أكبر من 2.6. بينما السقف أو المتمم الصحيح الأعلى ceil لعدد حقيقي x، فهو أصغر عدد صحيح ولكنه ليس أصغر من x، لأن سقف العدد 2.15 هو 3، أي أنّ أصغر عدد صحيح ليس أصغر من 2.15. لكن يمكننا افتراض أن هذه الطريقة ستنجح دائمًا، وسنفترض أنّ تطبيقنا الفعلي يهتم بأخطاء الفراق الواحد off-by-one، وذلك لأننا نريد تحليل تعقيد هذه الطريقة فقط. إذا لم تطبّق البحث الثنائي مطلقًا، فقد ترغب في فعل ذلك باستخدام لغة البرمجة المفضلة لديك. يوضّح الشكل الآتي لصاحبه لوك فرانكل Luke Francl طريقة عمل البحث الثنائي باستخدام العودية، حيث يُميَّز الوسيط A لكل استدعاء باللون الأسود، وتستمر العودية حتى تصبح المصفوفة مكوّنةً من عنصر واحد فقط. إذا لم تكن متأكدًا من عمل هذه الطريقة، فشغّلها يدويًا باستخدام مثال بسيط واقنع نفسك بأنها تعمل بالفعل. لنحاول تحليل هذه الخوارزمية العودية، حيث سنفترض -من أجل التبسيط- أن المصفوفة تُقسَم دائمًا إلى نصفين تمامًا، متجاهلين الجزأين 1+ و 1- من الاستدعاء العودي. كما يجب اقتناعك بعدم تأثير إجراء تغيير بسيط على نتائج التعقيد مثل تجاهل الجزأين 1+ و1-، وهذه حقيقة يجب عادةً إثباتها إذا أردنا أن نكون حريصين من وجهة نظر رياضية، لكنها بديهية عمليًا. سنفترض للتبسيط أن حجم المصفوفة هو بالضبط قوة للعدد 2. بحيث لا يغير هذا الافتراض النتائج النهائية لتعقيدنا الذي سنصل إليه، وسيحدث السيناريو الأسوأ لهذه المشكلة عند عدم ظهور القيمة التي نبحث عنها في مصفوفتنا على الإطلاق، كما سنبدأ في هذه الحالة بمصفوفة ذات حجم n في الاستدعاء الأول للعودية، ثم سنحصل على مصفوفة بحجم n / 2 في الاستدعاء التالي. وبعدها سنحصل على مصفوفة بحجم n / 4 في الاستدعاء العودي التالي، ثم مصفوفة بحجم n / 8، وهكذا؛ حيث تقسَم المصفوفة إلى نصفين في كل استدعاء، حتى نصل إلى عنصر واحد فقط، لذلك لنكتب عدد العناصر في المصفوفة الخاصة بنا لكل استدعاء كما يلي: 0th iteration: n 1st iteration: n / 2 2nd iteration: n / 4 3rd iteration: n / 8 … ith iteration: n / 2i last iteration: 1 لاحظ احتواء المصفوفة على n / 2i عنصر في التكرار i بسبب تقسيم المصفوفة في كل تكرار إلى نصفين، مما يعني أننا نقسم عدد عناصرها على 2، أي نضرب المقام بـ 2؛ وإذا فعلنا ذلك i مرة، فسنحصل على n / 2i، إذ يستمر هذا الإجراء ونحصل على عدد أصغر من العناصر مع كل قيمة أكبر للمتغير i، حتى نصل إلى التكرار الأخير الذي يتبقى فيه عنصر واحد فقط، وإذا رغبنا في معرفة التكرار i الذي يتبقى فيه عنصرٌ واحد فقط، فعلينا حل المعادلة التالية: 1 = n / 2i سيكون هذا صحيحًا فقط عندما نصل إلى الاستدعاء النهائي للدالة ()binarySearch، وليس في الحالة العامة، لذلك فإيجاد قيمة i هنا سيساعدنا في العثور على التكرار الذي ستنتهي فيه العودية. وإذا ضربنا كلا الطرفين بـ 2i فسنحصل على: 2i= n يجب أن تبدو هذه المعادلة مألوفة إذا قرأت قسم اللوغاريتمات أعلاه، وبالتالي ينتج: i = log( n ) يخبرنا هذا أن عدد التكرارات المطلوبة لإجراء بحث ثنائي هو log( n )، حيث n هي عدد عناصر المصفوفة الأصلية، ويُعَدّ ذلك أمرًا منطقيًا. بافتراض أنّ n = 32 فسيكون لدينا مصفوفة مؤلفة من 32 عنصرًا، فكم مرةً يجب تقسيم هذه المصفوفة إلى نصفين للحصول على عنصر واحد فقط؟ سنحتاج إلى تقسيمها خمس مرات للحصول إلى عنصر واحد، أي بالترتيب التالي: 32 ← 16 ← 8 ← 4 ← 2 ← 1، والعدد 5 هو لوغاريتم 32، لذلك يكون تعقيد البحث الثنائي هو Θ( log( n ) ). تسمح لنا هذه النتيجة الأخيرة بمقارنة البحث الثنائي والبحث الخطي، وبما أن ( log( n أصغر بكثير من n، فيمكن استنتاج أن البحث الثنائي أسرع بكثير من البحث الخطي للبحث داخل مصفوفة، لذلك يُستحسَن إبقاء المصفوفات مرتبةً عند العمل على عدة عمليات بحث فيها. الفرز الأمثل Optimal sorting تهانينا! لقد بتّ الآن تعرف كلًا من تحليل تعقيد الخوارزميات، وسلوك الدوال المقارب، وصيغة big-O؛ بالإضافة إلى كيفية إيجاد تعقيد الخوارزمية ليكون O( 1 )، وO( log( n ) )، وO( n )، وO( n2 ) وما إلى ذلك بديهيًا، كما أصبحت تعرف الرموز o، وO، وω، وΩ، وΘ، وماذا يعني تحليل الحالة الأسوأ أيضًا. يُعَدّ هذا القسم الأخير من المقال أعقد قليلًا، لذا لا تتردد في أخذ راحة إذا تعبت، حيث سيتطلب منك التركيز وقضاء بعض الوقت في حل التمارين، لكنه سيوفر لك طريقةً مفيدةً للغاية في تحليل تعقيد الخوارزمية وهذا أمرٌ مهم، لذلك فهو بالتأكيد يستحق الفهم. يُدعى الفرز الذي طبقناه سابقًا بالفرز الانتقائي، حيث ذكرنا أنه ليس الفرز الأمثل؛ والخوارزمية المثلى هي الخوارزمية التي تحل المشكلة بأفضل طريقة ممكنة، مما يعني عدم وجود خوارزميات أفضل منها، وهذا يعني أن لدى جميع الخوارزميات الأخرى الموجهة لحل المشكلة تعقيدًا أسوأً أو مساويًا لتلك الخوارزمية المثلى، كما قد يكون هناك العديد من الخوارزميات المثلى لمشكلةٍ ما بحيث تشترك جميعها في التعقيد نفسه، ويمكن حل مشكلة الفرز على النحو الأمثل بطرق مختلفة، كما يمكن استخدام فكرة البحث الثنائي نفسها من أجل الفرز بسرعة، وتسمى طريقة الفرز المثلى هذه الفرز بالدمج mergesort. سنحتاج أولًا في إجراء فرز الدمج، إلى إنشاء دالة مساعدة والتي سنستخدمها بعد ذلك لإجراء الفرز الفعلي، حيث تأخذ دالة الدمج merge مصفوفتين مرتّبتَين سابقًا، ثم تدمجهما معًا في مصفوفة كبيرة مرتبة، ويمكن القيام بذلك بسهولة كما يلي: def merge( A, B ): if empty( A ): return B if empty( B ): return A if A[ 0 ] < B[ 0 ]: return concat( A[ 0 ], merge( A[ 1...A_n ], B ) ) else: return concat( B[ 0 ], merge( A, B[ 1...B_n ] ) ) تأخذ الدالة concat عنصرًا يُسمى "الرأس head" ومصفوفة تُسمى "الذيل tail"، ثم تبني وتعيد مصفوفةً جديدةً تحتوي على عنصر "الرأس" الذي يمثِّل العنصر الأول في المصفوفة الجديدة، وعلى عنصر "الذيل" الذي يمثِّل بقية العناصر الموجودة في المصفوفة، حيث تعيد الدالة concat( 3, [ 4, 5, 6 ] ) مثلًا، ما يلي: [ 3, 4, 5, 6 ]. ونستخدم المتغيرين An وBn للإشارة إلى أحجام المصفوفتين A وB على التوالي. تمرين 8 تحقق من إجراء الدالة المذكورة أعلاه لعملية الدمج، ثم أعد كتابتها بلغة البرمجة المفضلة لديك بطريقة تكرارية -أي باستخدام حلقات for- بدلًا من استخدام العودية. يكشف تحليل هذه الخوارزمية أن وقت تشغيلها Θ( n )، حيث يمثِّل n طول المصفوفة الناتجة أي n = A_n + B_n. تمرين 9 تحقق من أن وقت تشغيل الدالة merge هو Θ( n ). يمكننا بناء خوارزمية فرز أفضل باستخدام هذه الدالة، حيث نقسم المصفوفة إلى قسمين، ونرتِّب كل جزء من الجزأين عوديًا، ثم ندمج المصفوفتين المرتبتين في مصفوفة واحدة كبيرة، وذلك كما يلي: def mergeSort( A, n ): if n = 1: return A # it is already sorted middle = floor( n / 2 ) leftHalf = A[ 1...middle ] rightHalf = A[ ( middle + 1 )...n ] return merge( mergeSort( leftHalf, middle ), mergeSort( rightHalf, n - middle ) ) يُعَدّ فهم هذه الدالة أصعب مما مررنا به سابقًا، لذلك قد يأخذ منك التمرين التالي بضع دقائق. تمرين 10 تحقق من صحة الدالة mergeSort، وذلك من خلال التحقق من تمكّن الدالة mergeSort من فرز المصفوفة المعطاة بصورة صحيحة، وإذا واجهتك مشكلة في فهم سبب نجاحها في ذلك، فجرّبها باستخدام مصفوفة صغيرة على أساس مثال ثم شغّلها "يدويًا"، وتأكد عند تشغيل هذه الدالة يدويًا من حصولك على النصف الأيسر leftHalf والنصف الأيمن rightHalf. وإذا قسّمت المصفوفة في المنتصف تقريبًا، فليس من الضروري قسم المصفوفة في المنتصف تمامًا إذا احتوت على عدد فردي من العناصر وهذا الهدف من استخدام الدالة floor أعلاه. لنحلل الآن تعقيد الدالة mergeSort، حيث سنقسم المصفوفة إلى نصفين متساويين في الحجم على غرار دالة البحث الثنائي binarySearch في كل خطوة من خطوات الدالة mergeSort، ولكننا سنحافظ في هذه الحالة على كلا النصفين طوال فترة التنفيذ، ثم نطبّق الخوارزمية عوديًا في كل نصف، كما نطبّق عملية الدمج merge على النتيجة التي تستغرق وقتًا مقداره Θ( n ) بعد أن تعيد الخوارزمية العودية. لبهذا نكون قد قسمنا المصفوفة الأصلية إلى مصفوفتين بحجم n / 2 لكل منهما، ثم دمجنا هذه المصفوفات، وهي عملية لدمج n عنصرًا وبالتالي تستغرق وقتًا (Θ (n، كما يوضح الشكل التالي هذه العملية العودية: شجرة العودية لطريقة الفرز بالدمج merge sort تمثِّل كل دائرة استدعاءً للدالة mergeSort كما يشير الرقم المكتوب في الدائرة إلى حجم المصفوفة التي يجري فرزها، إذ تكون الدائرة الزرقاء العلوية الاستدعاء الأصلي للدالة mergeSort، بحيث نحصل على فرز مصفوفة بالحجم n، كما تشير الأسهم إلى الاستدعاءات المتكررة التي تجريها الدوال فيما بينها. يعمل الاستدعاء الأصلي للدالة mergeSort على استدعائها مرتين في مصفوفتين وحجم كل منهما n / 2، حيث يشار إلى ذلك بواسطة السهمين الموجودين في الأعلى، ثم يجري كل من هذين الاستدعائَين بدورهما استدعائين خاصين بهما لدمج مصفوفتين بحجم n / 4 لكل منهما، وهكذا دواليك حتى نصل إلى مصفوفات ذات حجم 1؛ ويسمَّى هذا الرسم البياني بالشجرة العودية recursion tree، لأنه يوضح كيفية حدوث العودية ويظهر مثل شجرة، لكن الجذر root في الأعلى والأوراق في الأسفل، لذلك يظهر مثل شجرة مقلوبة. لاحظ أن العدد الإجمالي للعناصر هو n في كل مستوى من الرسم البياني أعلاه، حيث يحتوي المستوى الأول على استدعاء واحد فقط للدالة mergeSort مع مصفوفة بحجم n أي العدد الإجمالي للعناصر هو n، كما يحتوي المستوى الثاني على استدعائين للدالة mergeSort وكل منهما بحجم n / 2. لكن n / 2 + n / 2 = n وهكذا يكون العدد الإجمالي للعناصر هو n في هذا المستوى، كما توجد 4 استدعاءات في المستوى الثالث، بحيث يُطبَّق كل استدعاء على مصفوفة بحجم n / 4، أي سيساوي عدد العناصر الإجمالي n / 4 + n / 4 + n / 4 + n / 4 = 4n / 4 = n، وبالتالي نحصل على n عنصر. يجب على المستدعي في كل مستوى من هذا الرسم البياني إجراء عملية دمج merge على العناصر التي يعيدها المستدعَى، إذ يجب على الدائرة المشار إليها باللون الأحمر مثلًا، ترتيب عدد n / 2 من العناصر، وذلك بتقسيم المصفوفة ذات الحجم n / 2 إلى مصفوفتين بحجم n / 4، ثم تُستدعَى الدالة mergeSort عوديًا لفرز تلك المصفوفة، ثم تُدمَجان معًا، ويُشار إلى هذه الاستدعاءات بالدوائر ذات اللون الأخضر. تحتاج عملية الدمج إلى دمج n / 2 عنصر في كل مستوى من الشجرة، ويكون العدد الإجمالي للعناصر المدموجة هو n. حيث تدمج الدالة في ذلك المستوى n / 2 عنصر، ويجب على الدالة الموجودة على يمينها -ذات اللون الأزرق- دمج n / 2 عنصرأيضًا، وبالتالي ينتج عدد العناصر الإجمالي التي يجب دمجها في هذا المستوى . تعقيد كل مستوى هو Θ( n )، كما يكون عدد المستويات في هذا الرسم البياني، والذي يُطلق عليه أيضًا عمق depth شجرة العودية مساويًا لـ log( n )، وسبب ذلك هو السبب ذاته تمامًا الذي استخدمناه عند تحليل تعقيد البحث الثنائي. لدينا log( n ) مستوى وتعقيد كل مستوى هو Θ( n )، وبالتالي، يكون تعقيد الدالة mergeSort هو Θ(n * log( n ))، وهذا أفضل بكثير من Θ( n2 ) الذي هو تعقيد خوارزمية الفرز الانتقائي -تذكر أنّ log( n ) أصغر بكثير من n، وبالتالي يكون n * log (n) أصغر بكثير من n * n = n2-، وإذا وجدت ذلك معقدًا، فلا تقلق لأن الأمر ليس سهلًا في المرة الأولى. يسمح لنا تحليل التعقيد بمقارنة الخوارزميات لمعرفة أيها أفضل كما رأيت في هذا المثال الأخير، ويمكننا الآن أن نكون على يقينٍ تام من تفوّق خوارزمية الفرز بالدمج على خوارزمية الفرز الانتقائي للمصفوفات الكبيرة، كما سيكون استخلاص هذا الاستنتاج صعبًا إذا لم تملك الخلفية النظرية لتحليل الخوارزمية. تُستخدَم خوارزميات الفرز التي لها وقت تشغيل Θ( n * log( n ) )عمليًا، إذ تستخدم نواة نظام لينكس مثلًا، خوارزمية فرز تسمى heapsort، والتي لها وقت تشغيل مماثل لخوارزمية الفرز بالدمج mergesort الذي أوجدناه للتو، والذي هو Θ( n log( n ) )، لذلك فهو الأمثل. لاحظ أننا لم نثبت أن خوارزميات الفرز هذه هي الأمثل، لأن ذلك يتطلب معرفةً رياضيةً أكبر، لكن كن مطمئنًا أنه لا يمكن لهذه الخوارزميات المثلى التحسن أكثر من ذلك من وجهة نظر التعقيد. يجب الآن بعد قراءة هذا المقال أن يكون حدسك الذي طورته لتحليل تعقيد الخوارزمية قادرًا على مساعدتك في تصميم برامج أسرع، ويجب عليك تركيز جهودك المثلى على الأشياء المهمة حقًا بدلًا من الأشياء الصغيرة التي لا تهمك، مما يتيح لك العمل بصورةٍ أكثر إنتاجية. كما يجب أن تكون اللغة الرياضية والتمثيل الذي طُوِّر في هذا المقال مثل صيغة Big-O مفيدَين أيضًا في التواصل مع مهندسي البرمجيات الآخرين عندما تنقاشهم بموضوع وقت تشغيل الخوارزميات. ترجمة -وبتصرف- للمقال A Gentle Introduction to Algorithm Complexity Analysis لصاحبه Dionysis "dionyziz" Zindros. اقرأ أيضًا المرجع الشامل إلى تعلم الخوارزميات للمبتدئين تعقيد الخوارزميات Algorithms Complexity ترميز Big-O في الخوارزميات خوارزمية ديكسترا Dijkstra’s Algorithm
-
تُعَد الصور التي تستخدمها في موقع الويب من أهم العناصر التي لا يجب أن تكون جذابةً فقط، ولكن يجب ألّا تكون كبيرة الحجم جدًا حتى لا تبطّئ وقت تحميل موقعك، فأحد الأسباب الرئيسية وراء بطء الموقع هو أن الصور المضمَّنة فيه لم يتغير حجمها لتحقيق أداء الموقع الأمثل. سنشرح في هذا المقال الطرق اليدوية لتقليل أحجام الصور في برنامج الفوتوشوب، من خلال تغيير نوع الملف وتغيير حجم الملفات وضغطها عن طريق حفط الملفات، وذلك باستخدام الطريقة "حفظ للويب" Save for Web. سنقدّم أيضًا بعض الإضافات plugins والخيارات المستندة إلى الويب. تغيير نوع الملف يشير حجم ملف الصورة إلى عدد البكسلات في الإنش، فكلما زاد عدد البكسلات في الإنش، زادت المعلومات التي يحتفظ بها الملف، وبالتالي يزيد حجمه. أنواع ملفات الصور الأكثر شيوعًا هما JPG وPNG: رسوميات الشبكة المحمولة Portable Network Graphics أو اختصارًا PNG: يُستخدَم هذا النوع من الملفات غالبًا مع الملفات الرسومية، مثل الشعارات والأيقونات والرسوم التوضيحية والنصوص، حيث لا تفقد هذه الملفات بيانات كثيرة عند معالجتها أو ضغطها أثناء تحريرها باستخدام أحد تطبيقات تحرير الصور مثل برنامج الفوتوشوب، لذلك يُشار إليها على أنها غير فاقدة للبيانات lossless، وبالتالي تميل هذه الملفات إلى أن تكون ذات حجم أكبر. المجموعة المشتركة لخبراء التصوير Joint Photographic Experts Group أو اختصارًا JPEG: من أكثر أنواع ملفات الصور التي ستجدها على الإنترنت شيوعًا. يمكن لهذا النوع من الملفات أن يحتوي على ملايين الألوان، ويمكن ضغطه كثيرًا مع الحفاظ على الجودة. يشار إلى هذا النوع من الصور على أنها فاقدة للبيانات lossy، لأن عملية الضغط تزيل بكسلات من الصورة. يمكنك استخدام أي نوع ملفات من النوعين السابقين، إذ يعتمد النوع الذي تختاره على موقعك، وعلى عدد ونوع الصور الذي تريد استخدامه. لقد كان تنسيق الصورة التالية الأصلي ملف JPG على سبيل المثال: ولكننا غيرنا نوع الملف من خلال الذهاب إلى قائمة ملف File في برنامج الفوتوشوب، ثم اختيار Save As، بعدها اختيار التنسيق PNG، وإكمال عملية حفظ الملف في النهاية، وبهذا تغيَّر حجم الملف من 646 كيلوبايت إلى 1.3 ميجابايت عند تغيير نوعه إلى ملفات PNG الأكبر كما ذكرنا سابقًا، لذلك يُفضَّل استخدام الصورة ذات النوع JPEG لضمان أوقات تحميل أسرع، لأن هذه الصورة مليئة بالألوان والتفاصيل. وإذا أردت أن تكون الصورة قادرةً على أن تكبر أكثر دون فقدان دقتها، فاستخدم الصور بتنسيق PNG. هناك تنسيقات ملفات أخرى متعددة متاحة، لكن ركزنا على النوعين JPEG وPNG لأنهما الأشهر. تغيير حجم الصورة يدويًا في برنامج الفوتوشوب يمكنك تغيير حجم الصورة يدويًا في برنامج الفوتوشوب، وذلك من خلال الذهاب إلى قائمة Image ثم اختيار حجم الصورة Image Size، إذ تبدو هذه الأداة كما في الشكل التالي: يوجد حجم الصورة Image Size الحالي والأبعاد Dimensions، حيث كلاهما مقدَّر بالبكسل أعلى هذه الأداة، كما في الشكل السابق. ستغير التعديلات التي تجريها هذا الحجم. القائمة Fit To هي قائمة منسدلة تحتوي على أحجام محددة مسبقًا وإعدادات متعلقة بالبكسل. إن اخترت الخيار الأول في قائمة Fit To لضبط الأبعاد وعدد البكسلات في الإنش ppi، فيمكنك رؤية تغير حجم الملف. جرّب هذه الإعدادات لتحديد الحجم القياسي من القائمة المنسدلة المناسب، أو لتحديد إذا كنت بحاجة إلى تغيير خيارات العرض أو الطول أو الدقة يدويًا للحصول على الحجم الذي تحتاجه. عملية حفظ الملف للويب Save for Web تختلف طريقة حفظ الملف Save for Web عن طريقة الحفظ Save As، من حيث أن خيار الويب يزيل البيانات الوصفية metadata من الملف، والبيانات الوصفية هي تفاصيل تحتوي نوع الصورة وأصلها. تًعَد طريقة حفظ الملف للويب مخصَّصةٌ للصور التي ستُعرَض على الإنترنت، لذلك يمكن أن تكون طريقةً سريعةً جدًا لتغيير حجم الصورة مع الحفاظ على جودتها. يمكن الوصول إلى الخيار Save for Web من خلال الانتقال إلى قائمة File ثم اختر Export ثم Save for Web: توجد فائدة أخرى لهذه الطريقة التي يمكنك ملاحظتها عندما تفتح نافذة Save for Web، فإن اخترت التبويب 2up، فسيمكنك مشاهدة موازنة الصورة الأصلية جنبًا إلى جنب مع الصورة التي جرى تغييرها. استخدم هنا الإعدادات المُسبَقة في الزاوية العلوية اليمنى لاختيار التنسيق JPG واضبط الجودة التي تريدها، بعدها يمكنك معرفة فيما إذا توافق ملفك الجديد مع معايير الجودة الخاصة بك أم لا عن طريق معاينة الصورة، ويمكنك التحقق من صحة التغيير في حجم الملف من خلال النظر إلى البيانات الموجودة أسفل كل صورة: يمكنك أيضًا تغيير الحجم باستخدام حقلَي العرض والطول في الزاوية السفلية اليمنى، وبما أن هذا المقال يناقش تغيير الحجم تحديدًا، فلن نشرح الخيارات الأخرى المعروضة في شاشة Save for Web. أدوات WordPress لتحسين الصور يُعَد برنامج الفوتوشوب خيارًا رائعًا إن أردت تقليل حجم ملف الصورة بنفسك، ولكن إن أردت شيئًا آليًا لمساعدتك في تغيير حجم صورك، فهناك عدد كبير من خيارات إضافات WordPress التي يمكن أن تساعدك، وفيما يلي قائمة ببعض هذه الخيارات الشائعة ووصف موجز لفوائدها: الإضافة Imagify: تحسّن جميع صورك دفعةً واحدة، وتغير حجمها بسهولة وتستعيد نسخ الصور الأصلية عند الحاجة. يًعَد سعر هذه الإضافة مقبولًا، فهي مجانية للتنزيل وتتضمن 20 ميجابايت من مساحة الملف، وتوجد خيارات أخرى هي 5 دولارات شهريًا مقابل 500 ميجابايت و10 دولارات شهريًا لمساحة غير محدودة. الإضافة ShortPixel: تتيح هذه الإضافة التعامل مع حجم ملف غير محدود، ويضيف استخدام مفتاح API واحد مع مواقع متعددة إيجابيات على هذه الإضافة، كما أنها توفر خطط دفع مرنة لمرة واحدة وشهرية. الإضافة Optimole: تقدّم هذه الإضافة بالنسبة للبيانات الموجَّهة، لوحة تحكم dashboard، حيث يمكنك مراجعة إحصائيات التحسين، وتسمح خطة هذه الإضافة المجانية بحوالي 5000 زائر شهريًا وحيز نطاق تراسلي bandwidth غير محدود. موارد الويب التي تساعد في تحسين الصور هناك الكثير من أدوات تحسين الصور المجانية على الإنترنت التي يمكنك استخدامها إن لم يكن لديك المال و/أو الوقت الكافي، ومن هذه الأدوات، نجد أداة Compressjpg: تتيح لك هذه الأداة رفع ملفات متعددة وتغيير حجمها جميعًا مرةً واحدة، كما أن لديها ميزةً تتمثّل بتحويل الصور من تنسيق iPhone HEIC إلى تنسيق JPEG، وتوجد مواقع أخرى مماثلة لهذه الأداة، مثل Tinypng وImage Compressor. اللمسات الأخيرة لا تقلّل من أهمية تحسين صورك، إذ لا تسبّب المواقع البطيئة مغادرة زوّارها فحسب، بل إنها لا تحظى أيضًا باهتمام عمليات بحث جوجل، ويمكن أن توفّر الصور الواضحة وسريعة التحميل هذا الشيء الإضافي الذي يميز موقعك عن البقية، وسيجعل الموقع المحسَّن الزائرين يعودون إليه مرةً أخرى. ترجمة -وبتصرّف- للمقال How to Reduce the Size of JPEG and Other Image Files لصاحبته Amber Fogel. اقرأ أيضًا قواعد التعامل مع الصور والرسوميات كيفية إنشاء أنماط Patterns رسومية تفصيلية باستخدام برنامج فوتوشوب تعلّم بعض الإجراءات السريعة لتعديل الصور على GIMP
-
تحدثنا حتى الآن عمّا يجب على المبدّلات والموجّهات فعله، دون وصف كيفية القيام بذلك. حيث توجد طريقة مباشرة لبناء مبدّلٍ أو موجّه، تتمثل في شرائك لمعالجٍ للأغراض العامة وتجهيزه بواجهات شبكة متعددة. بحيث يمكن لمثل هذا الجهاز الذي يعمل ببرمجياتٍ مناسبة، تلقّي رزمٍ على إحدى واجهاته، وإجراء أيٍّ من وظائف التبديل أو التمرير الموضّحة في هذا الفصل، إلى جانب إرسال رزمٍ عبر واجهاته الأخرى. ويسمى هذا بالمبدّل البرمجي software switch، وهو ليس بعيدًا جدًا عن معمارية العديد من أجهزة الشبكات التجارية المتوسطة إلى المنخفضة. وهذه هي نفس الطريقة التي طُبِّقت فيها موجّهات الإنترنت الأولى، والتي سُمِّيت بـبوابات gateways في ذلك الوقت - في الأيام الأولى للإنترنت -. حيث تستفيد التطبيقات التي تقدم أداءً فائقًا من تسريع العتاد الإضافي - ونشير إليها بالمبدّلات العتادية hardware switches -، رغم اشتمال كلا النَهجَين بوضوح على مزيج من العتاد والبرمجيات. يقدّم هذا القسم نظرةً عامةً عن كلٍّ من التصميمات التي تتمحور حول البرمجيات software والتصميمات المتمحورة حول العتاد hardware، ولكن تجدر الإشارة إلى أنّ التمييز بين المبدّلات والموجّهات ليس بهذه الأهمية. فقد اتّضح أنّ تطبيق المبدّلات والموجّهات لهما الكثير من القواسم المشتركة لدرجة أنّ مسؤول الشبكة يشتري عادةً صندوق تمرير، بعدها يضبطه ليكون مبدّل L2 أو موجّه L3 أو مزيجًا من الاثنين. سنستخدم الكلمة مبدّل switch لتمثيل كلا المصطلحين (مبدّل وموجّه) في هذا القسم نظرًا لتشابُه تصميماتِهما الداخلية كثيرًا، ولتجنّب الملل من قول "مبدّل أو موجّه" طوال الوقت، كما سنذكر الاختلافات بين الاثنين عند الاقتضاء. المبدل البرمجي Software Switch يوضّح الشكل الآتي مبدّلًا برمجيًا أُنشئ باستخدام معالجٍ للأغراض العامة مع أربع واجهات شبكة NIC. حيث يُعَدّ مسار الرزمة التي تصل مثلًا إلى الواجهة NIC 1 وتُمرَر إلى الواجهة NIC 2 مسارًا مباشرًا، إذ تنسخ الواجهة NIC 1 البايتات الخاصة بها مباشرةً من الرزمة التي تستلمها في الذاكرة الرئيسية عبر ناقل الإدخال / الإخراج (وهو PCIe في هذا المثال) باستخدام تقنية تسمى الوصول المباشر للذاكرة direct memory access أو اختصارًا DMA. تفحص وحدة المعالجة المركزية ترويسة الرزمة بمجرد أن تصبح هذه الرزمة في الذاكرة لتحديد الواجهة التي يجب إرسال الرزمة عليها، كما ترشِد الواجهة NIC 2 لإرسال الرزمة مرةً أخرى مباشرةً من الذاكرة الرئيسية باستخدام تقنية DMA. فالمهم هو تخزين الرزمة مؤقتًا في الذاكرة الرئيسية، وهذا هو جزء التخزين من عملية خزّن ومرّر store-and-forward، مع قراءة وحدة المعالجة المركزية لحقول الترويسة الضرورية فقط في مسجّلات المعالجة الداخلية الخاصة بها. هناك نوعان من الاختناقات bottlenecks المُحتملة مع هذه الطريقة، إذ يحدّ أحد هذين النوعين أو كليهما من سعة تمرير الرزمة الإجمالية للمبدّل البرمجي. والمشكلة الأولى هنا هي تقيّد الأداء بحقيقة وجوب مرور جميع الرزم داخل وخارج الذاكرة الرئيسية. حيث ستختلف المسافة المقطوعة بالأميال بناءً على المبلغ الذي ترغب في دفعه مقابل العتاد، ولكن يمكن لجهاز مقيّد بناقل ذاكرة يبلغ 1333 ميجاهرتز و 64 بت مثلًا، نقل البياناتِ بمعدّل ذروة يزيد قليلًا عن 100 جيجابت في الثانية، وذلك كافٍ لبناء مبدّل مع عدد قليل من منافذ إيثرنت بسرعة 10 جيجابت في الثانية، ولكنه ليس كافيًا لموجّهٍ متطوّر في نواة الإنترنت. يفترض هذا الحد الأعلى أنّ نقل البيانات هو المشكلة الوحيدة. وهذا جيدٌ تقريبًا بالنسبة للرزم الطويلة ولكنه ليس كذلك عندما تكون الرزم قصيرة، فهذه هي الحالة الأسوأ التي يجب على مصمّمي المبدّلات التخطيط لها. فمِن المُرَّجح هيمنة تكلفة معالجة كلّ رزمة مع الرزم ذات الحجم الأدنى، والتي تتضمن تحليل ترويستها وتحديد رابط الخرج الذي ستُنقَل عليه، وبالتالي قد ينتج اختناق. افترض قدرة المعالج مثلًا على إجراء جميع المعالجات اللازمة لتبديل 40 مليون رزمة كلّ ثانية. حيث يُسمى هذا أحيانًا معدّل الرزم في الثانية packet per second أو اختصارًا pps. فإذا كان متوسط الرزم هو 64 بايتًا، فهذا يعني ضمنيًا أن الإنتاجية Throughput تساوي: Throughput = pps x BitsPerPacket = 40 × 106 × 64 × 8 = 2048 × 107 وهي إنتاجية لسرعة تبلغ حوالي 20 جيجابت في الثانية، ولكنها أقلّ بكثير من النطاق الذي يطلبه المستخدمون من مبدّلاتهم اليوم. ضع في حساباتك تشارك جميع المستخدمين المتصلين بالمبدّل بهذه الـ 20 جيجابت في الثانية، كما يتشارك جميع المستخدمين المتصلين بِالوسيط المشترك بِحيّز النطاق التراسُلي لمقطع إيثرنت واحد (غير قابل للتبديل unswitched. وهكذا، سيكون المبدّل ذي 16 منفذًا مثلًا مع هذه الإنتاجية الكلية، قادرًا فقط على التعامل مع متوسط معدّل بيانات يبلغ حوالي 1 جيجابت في الثانية على كلّ منفذ. حيث لا تمثّل أرقام أداء هذا المثال الحد الأقصى لمعدّل الإنتاجية المطلق الذي قد تحققه البرمجيات عالية المستوى والتي تعمل على خادم متطوّر، ولكنها تشير إلى الحدود التي تواجهها في النهاية عند اتباع هذا النهج. هناك شيء أخير من المهم فهمُه عند تقييم تطبيقات التبديل. إذ لا تُعَدّ الخوارزميات غير البسيطة non-trivial algorithms التي نوقشت سابقًا في هذا الفصل، -مثل كلٍّ من خوارزمية الشجرة الممتدة التي تستخدمها جسور التعلم learning bridges، وخوارِزمية متّجه المسافة التي يستخدمها بروتوكول RIP، وخوارِزمية حالة الرابط التي يستخدمها بروتوكول OSPF-، جزءًا مباشرًا من قرار تمرير كلّ رزمة. حيث تعمل هذه الخوارزميات دوريًا في الخلفية، ولكن لا يتعيّن على المبدّلات تنفيذ شيفرة OSPF لكلّ رزمة تُمررها مثلًا. ويُعدّ الإجراء الأكثر تكلفةً والذي من المرجح تنفيذه من قِبل وحدة المعالجة المركزية لكلّ رزمة هو البحث في الجدول، مثل: البحث عن رقم VCI في جدول VC، أو عنوان IP في جدول تمرير L3، أو عنوان إيثرنت في جدول تمرير L2. يُعَدّ التمييز بين هذين النوعين من المعالجة مُهمًا بدرجة كافية لمنحه اسمًا: حيث يتوافق مستوى التحكم control plane مع المعالجة الخلفية المطلوبة "للتحكم" في الشبكة (مثل: تشغيل بروتوكول OSPF، أو RIP، أو بروتوكول BGP الذي سنوضّحه في الفصل التالي)، كما يتوافق مستوى البيانات data plane مع معالجة كلّ رزمة مطلوبة لنقل الرزم من منفذ الإدخال إلى منفذ الإخراج. ويُطلق على هذا التمييز اسم مستوى التحكم ومستوى المستخدم في شبكات الوصول الخلوية، لأسباب تاريخية، ولكن الفكرة هي نفسها، إذ يعرّف المعيار 3GPP مبدأ CUPS (مستوى التحكم / مستوى المستخدم) كمبدأ معماري. يسهُل الخلط بين هذين النوعين من المعالجة عندما يعمل كلاهما على نفس وحدة المعالجة المركزية، كما هو الحال في المبدّل البرمجي الموضَّح في الشكل السابق. ولكن يمكن تحسين الأداء بصورة كبيرة عن طريق تحسين كيفية تطبيق مستوى البيانات، وبالتالي تحديد واجهةٍ معرّفة جيدًا بين مستوى التحكم ومستويات البيانات. المبدل العتادي Hardware Switch كانت المبدّلات والموجّهات عالية الأداء عبارة عن أجهزة متخصصة طوال معظم تاريخ الإنترنت، والتي أُنشئت باستخدام الدارات المتكاملة الخاصة بالتطبيقات Application-Specific Integrated Circuits أو اختصارًا ASICs. بالرغم من إمكانية بناء موجّهات ومبدّلات منخفضة النهاية باستخدام خوادم سلعية تجارية تشغّل برامج C، ولكن كان من الضروري تواجُد دارات ASIC لتحقيق معدّلات الإنتاجية المطلوبة. تكمن مشكلة دارات ASIC في استغراق العتاد لوقت طويل في التصميم والتصنيع، مما يعني أنّ التأخير في إضافة ميزات جديدة إلى مبدّلٍ يُقاس عادةً بالسنوات، وليس بالأيام أو الأسابيع التي اعتادت صناعة البرمجيات اليوم عليها. حيث نرغب في الاستفادة من أداء دارات ASIC ومرونة البرمجيات في الحالة المثالية. جعلت التطورات الأخيرة في معالجات النطاق المحدد (والمكونات السلعية الأخرى) هذا ممكنًا لحسن الحظ. وبنفس القدر من الأهمية، فإنّ المواصفات المعمارية الكاملة للمبدّلات التي تستفيد من هذه المعالجات الجديدة متاحة الآن عبر الإنترنت، وهي العتاد المكافئ للبرمجيات مفتوحة المصدر. وهذا يعني قدرة أي شخص على إنشاء مبدّل عالي الأداء عن طريق سحب المخطط من الويب (راجع مشروع الحوسبة المفتوحة Open Compute Project أو اختصارًا OCP للحصول على أمثلة) بنفس الطريقة التي يمكن بها بناء حاسوبك. لكنك ما زلت بحاجة إلى برمجيات لتشغّلها على العتاد في كلتا الحالتين، ولكن مثلما يتوفّر نظام لينُكس للتشغيل على حاسوبك المصمَّم في المنزل، فهناك الآن مكدّسات L2 وL3 مفتوحة المصدر متاحة على جيثب GitHub للتشغيل على المبدّل المُنشَأ في المنزل. يمكنك أيضًا ببساطة شراء مبدّلٍ مُبنى مسبقًا من الشركة المصنعة للمبدّلات السلعية ثم تحميل البرنامج الخاص بك عليه. فيما يلي وصفٌ لـ المبدّلات ذات الصندوق الأبيض المفتوحة open white-box switches، والتي يُطلق عليها هذا الاسم لتمييزها عن مبدلات الصندوق الأسود المغلقة open white-box switches التي هيمنت تاريخيًا على الصناعة. الشكل السابق هو تصويرٌ مبسَّط لمبدّل الصندوق الأبيض. حيث يتمثل الاختلاف الرئيسي عن التطبيق السابق على معالج الأغراض العامة، في إضافة وحدة معالج الشبكة Network Processor Unit أو اختصارًا NPU. وهو معالج خاص بالنطاق، يحوي معمارية ومجموعة تعليمات مُحسَّنة لمعالجة ترويسات الرزم (لتطبيق مستوى البيانات على سبيل المثال). تتشابه وحدات NPU مع وحدات GPU التي تحتوي على بنية محسّنة لمعالجة الرسوميات الحاسوبية، ولكن حُسِّنت وحدة NPU لتحليل ترويسات الرزم واتخاذ قرار التمرير. بحيث بات ممكنًا لها معالجة الرزم (الإدخال، واتخاذ قرار التمرير، والإخراج) بمعدّلات مقاسة بِالتيرابت في الثانية Terabits-per-second أو اختصارًا Tbps، وبسرعة كافية لمواكبة منافذ 32x100-Gbps، أو منافذ 48x40-Gbps الموضحة بالمخطط السابق. ويكمن جمال تصميم هذا المبدّل الجديد في قدرته الآن على برمجة صندوق أبيض معيّن ليصبح مبدّل L2 أوموجّه L3 أو مزيجًا من الاثنين، وذلك فقط عن طريق البرمجة. تعمل رزمة برمجيات مستوى التحكم نفسها المستخدمة في المبدّل البرمجي على وحدة تحكُّم CPU، كما تُحمَّل برامج مستوى البيانات على وحدة NPU لتعكس قرارات التمرير التي تتخذها برمجيات مستوى التحكم إضافةً إلى ذلك. وتعتمد برمجة وحدة NPU على مصنّع الرقائق، إذ يكون خط أنابيب pipeline التمرير ثابتًا في بعض الحالات ويحمِّل معالجُ التحكم فقط جدول التمرير إلى وحدة NPU (نعني بكلمة ثابتًا أنّ وحدة NPU تعرف فقط كيفية معالجة ترويسات معيّنة، مثل الإيثرنت وIP، ولكن في حالاتٍ أخرى يكون خط أنابيب التمرير نفسه قابلًا للبرمجة. لغة P4 هي لغة برمجة جديدة يمكن استخدامها لبرمجة خطوط أنابيب التمرير المستندة إلى وحدة NPU. حيث تحاول لغة P4 إخفاء العديد من الاختلافات في مجموعات تعليمات وحدة NPU الأساسية. تستفيد وحدة NPU من ثلاث تقنيات داخليًا. أولًا، تخزّن ذاكرةٌ سريعة تعتمد على ذاكرة SRAM الرزمَ مؤقتًا أثناء معالجتها، وتُعَد ذاكرة SRAM وهي الذاكرة العشوائية الثابتة Static Random Access Memory، أسرع من ذاكرة DRAM (الذاكرة العشوائية الديناميكية) التي تستخدمها الذاكرة الرئيسية. ثانيًا، تخزّن الذاكرة المستندة إلى TCAM أنماطَ patterns البت المطلوب مطابقتها مع الرزم المُعالَجة، ويرمز CAM في TCAM إلى Content Addressable Memory أي ذاكرة مُعنونَة بمضمونها، مما يعني أنّ المفتاح الذي تريد البحث عنه في الجدول يمكن استخدامه بفعالية كعنوان في الذاكرة التي تطبّق الجدول. كما يرمز الحرف T إلى Ternary أي ثلاثي وهي طريقة رائعة للقول أنّ المفتاح الذي تريد البحث عنه قد يحتوي على أحرف بديلة wildcards فيه (مثل المفتاح 10*1 الذي يطابق كلًا من 1001 و1011). أخيرًا، تُطبَّق المعالجةُ المتضمنة تمرير كلّ رزمة عن طريق خط أنابيب التمرير. ويُطبَّق خط الأنابيب هذا بواسطة دارات ASIC، ولكن يمكن تعديل سلوك تمرير خط الأنابيب عن طريق تغيير البرنامج الذي يشغّله عندما يكون التصميم جيدًا. إذ يُعبَّر عن هذا البرنامج على مستوى عالٍ مثل مجموعة من أزواج (مطابقة، إجراء) Match, Action، وإذا تطابق حقل كذا وكذا في الترويسة، فنفّذ هذا الإجراء أو ذاك. تكمن أهمية معالجة الرزم المُطبَّقة بواسطة خط أنابيب متعدد المراحل بدلًا من معالج أحادي المرحلة في تضمُّن تمرير رزمةٍ واحدة النظر في حقول ترويسة متعددة على الأرجح. ويمكن برمجة كلّ مرحلة من خلال النظر في مجموعة مختلفة من الحقول. ويضيف خط الأنابيب متعدد المراحل وقت استجابة بسيطًا من طرف إلى طرف لكلّ رزمة (يُقاس بالنانو ثانية)، ولكنه يعني أيضًا إمكانية معالجة الرزم المتعددة في نفس الوقت. قد تُجري المرحلة 2 بحثًا ثانيًا عن الرزمة A، بينما تجري المرحلة 1 بحثًا أوليًا عن الرزمة B على سبيل المثال، وهكذا. وهذا يعني قدرة كل وحدة NPU على مواكبة سرعات الخط. - كانت سرعة أحدث التقنيات هي 12.8 تيرابت في الثانية حتى وقت كتابة هذا الكتاب -. يتضمن الشكل السابق أخيرًا مكونات سلعية أخرى تجعل كلّ هذا عمليًا. حيث أصبح من الممكن الآن شراء وحدات الإرسال والاستقبال القابلة للتوصيل pluggable transceiver التي تهتم بجميع تفاصيل الوصول إلى الوسائط، سواءً كانت جيجابت إيثرنت Gigabit Ethernet، أو 10 جيجابت إيثرنت 10 Gigabit Ethernet أو SONET، بالإضافة إلى الألياف البصرية. حيث تتوافق جميع أجهزة الإرسال والاستقبال هذه مع عوامل النموذج الموحَّدة، مثل: SFP+، والتي يمكن توصيلها بمكونات أخرى عبر ناقل قياسي مثل SFI. تتمثل الفكرة الرئيسية في دخول صناعة الشبكات الآن إلى نفس العالم السلعي الذي تمتّّعت به صناعة الحوْسبة على مدار العقدين الماضيين. وحدات معالجة الشبكة Network Processing Units يُعَدّ استخدامنا لمصطلح NPU غير قياسي بعض الشيء. فقد كان NPU تاريخيًا، هو الاسم الذي يُعطَى لرقائق معالجة الشبكة الأكثر تحديدًا، والمستخدمة لتطبيق جدران الحماية الذكية أو فحص الرزم العميق على سبيل المثال. ولم تكن للأغراض العامة مثل وحدات NPU التي نناقشها هنا، كما لم تكن عالية الأداء. ويبدو من المحتمل أنّ النهج الحالي سيجعل معالجات الشبكة المبنية لهذا الغرض قديمة، ولكنّنا نفضل التسمية NPU لأنها تتوافق مع الاتجاه لبناء معالجات قابلة للبرمجة وخاصة بالنطاق، بما في ذلك وحدات معالجة الرسوميات GPUs للرسوميات ووحدات TPU وحدات معالجة المُوَتِّر Tensor Processing Units، للذكاء الاصطناعي AI. الشبكات المعرفة بالبرمجيات Software Defined Networks يتحول الانتباه مع تزايد إضفاء الطابع السلعي على المبدّلات، إلى البرمجيات التي تتحكم بها. وهذا يضعنا مباشرةً في منتصف الاتجاه لبناء شبكات معرّفة بالبرمجيات SDN. وهي فكرة بدأت في الظهور منذ حوالي عشر سنوات، فقد كانت المراحل الأولى من شبكات SDN هي التي دفعت صناعة الشبكات إلى التحرك نحو مبدّلات الصندوق الأبيض. فكرة SDN الأساسية هي فكرة ناقشناها بالفعل وهي فصل decouple مستوى التحكم في الشبكة (أي حيث تعمل خوارزميات التوجيه، مثل: RIP، وOSPF، وBGP عن مستوى بيانات الشبكة (أي حيث تُتّخَذ قرارات تمرير الرزم)، مع انتقال مستوى التحكم في الشبكة إلى برمجيات تعمل على خوادم سلعية، وتطبيق مستوى بيانات الشبكة بواسطة مبدّلات الصندوق الأبيض. وقد كانت الفكرة الرئيسية وراء شبكات SDN هي أخذ هذا الفصل decoupling خطوةً إلى الأمام، وتحديد واجهة قياسية بين مستوى التحكم ومستوى البيانات. إذ يسمح القيام بذلك لأيّ تطبيقٍ لمستوى التحكم بالتحدُّث مع أيّ تطبيقٍ لمستوى البيانات، وهذا ما يكسر الاعتماد على أيّ حلّ تصنيع مجمَّع. تُسمى الواجهة الأصلية التدفق المفتوح OpenFlow، وقد عُرفت فكرة فصل مستويات التحكم والبيانات باسم التفريق disaggregation، أمّا لغة P4 المذكورة سابقًا فهي محاولة من الجيل الثاني لتعريف هذه الواجهة من خلال تعميم واجهة التدفق المفتوح. هناك جانب آخر مهم للتفريق، وهو إمكانية استخدام مستوى تحكُّم مركزي منطقيًا للتحكم في مستوى بيانات الشبكة الموّزعة. ونقول "مركزية منطقيًا" لأنه بينما تبقى الحالة التي جمّعَها مستوى التحكم في بنية بيانات عالمية مثل خارطة الشبكة، سيبقى تطبيق بنية البيانات هذا ممكنًا مع توزيعه على خوادم متعددة. حيث يمكنها العمل في سحابة مثلًا. وهذا يُعَدّ أمرًا مهمًا لكلٍّ من قابلية التوسع والتوافرية، فالمفتاح هو ضبط المستويين وتوسّعهما بصورة مستقلة عن بعضهما البعض. وقد انطلقت هذه الفكرة بسرعة في السحابة، حيث يشغّل مزوّدو السحابة اليوم حلولًا قائمة على شبكات SDN داخل مراكز بياناتهم وعبر الشبكات الأساسية التي تربط مراكز بياناتهم ببعضها. ومن بين إحدى نتائج هذا التصميم، نجد عدم وضوح أنّ مستوى التحكم المركزي المنطقي لا يدير فقط شبكةً من المبدّلات الفيزيائية (العتادية) التي تربط الخوادم الفيزيائية، بل يدير أيضًا شبكةً من المبدّلات الافتراضية (البرمجية) التي تربط الخوادم الافتراضية مثل الآلات الافتراضية و الحاويات containers. فإذا كُنتَ تحسب منافذ المبدّل (التي هي مقياسٌ جيد لجميع الأجهزة المتصلة بشبكتك)، فقد يتجاوز عدد المنافذ الافتراضية، عدد المنافذ الفيزيائية في الإنترنت في عام 2012. يُعَد نظام تشغيل الشبكة Network Operating System أو اختصارًا NOS أحد العوامل الرئيسية الأخرى لنجاح شبكة SDN، كما هو موضح في الشكل السابق. إذ يُسهّل نظام NOS تنفيذ وظائف التحكم في الشبكة، والمعروفة باسم تطبيقات التحكم Control Apps، مثل نظام تشغيل الخادم، مثل: Linux، وiOS، وAndroid، وWindows الذي يوفّر مجموعةً من التجريدات عالية المستوى التي تسهل تنفيذ التطبيقات (يمكنك قراءة الملفّات وكتابتها بدلًا من الوصول المباشر إلى محركات الأقراص على سبيل المثال). يجرّد نظام NOS الجيد تفاصيل مبدّلات الشبكة ويوفّر لمطوّر التطبيق تجريدًا لـخريطة الشبكة Network Map. كما يكتشف نظام NOS التغييرات في الشبكة الأساسية، مثل: المبدّلات، والمنافذ، والروابط التي تتجه لأعلى ولأسفل)، وينفّذ تطبيق التحكم السلوك الذي يريده ببساطة في هذا الرسم البياني المجرد. وهذا يعني أنّ نظام NOS يتحمّل عبء تجميع حالة الشبكة (الجزء الصعب من الخوارزميات الموّزعة مثل خوارزميات حالة الرابط وخوارزميات متّجه المسافة)، والتطبيق مجاني لتنفيذ خوارزمية أقصر مسار ببساطة وتحميل قواعد التمرير في المبدّلات الأساسية. ويُعَدّ الهدف الأساسي من خلال التركيز على هذا المنطق هو التوصُّل إلى حلٍ مُحسَّن عالميًا. حيث تؤكّد الأدلة المنشورة من مزوّدي السحابة الذين تبنّوا هذا النهج على هذه الميّزة. كان اعتماد شبكة SDN في المؤسسات وشركات الاتصالات بطيئًا على عكس مزودي السحابة. حيث يتعلق هذا جزئيًا بقدرة الأسواق المختلفة على إدارة شبكاتها، إذ تمتلك كلٌّ من شركات Google، وMicrosoft، وAmazon، المهندسين ومهارات DevOps اللازمة للاستفادة من هذه التقنية، بينما لا يزال البعض الآخر يفضّل الحلول الجاهزة والمتكاملة التي تدعم الإدارة وواجهات سطر الأوامر المألوفة لديهم. الشبكات الافتراضية على طول الطريق كانت هناك أفكارٌ حول كيفية جعل شبكات تبديل الرزم افتراضية منذ البداية، بدءًا من الدارات الافتراضية. ولكن ماذا يعني بالضبط جعل الشبكة افتراضية؟ تُعَدّ الذاكرة الافتراضية مثالًا مفيدًا. إذ تخلق الذاكرة الافتراضية تجريدًا لمجموعةٍ كبيرةٍ وخاصةٍ من الذاكرة، على الرغم من إمكانية مشاركة الذاكرة الحقيقية الأساسية بواسطة العديد من التطبيقات وأصغر بكثير من تجمُّع pool للذواكر الافتراضية. ويمكّن هذا التجريد المبرمجين من العمل تحت وهم وجود الكثير من الذاكرة التي لا يوجد أحدٌ آخر يستخدمها، بينما يعتني نظام إدارة الذاكرة في الخفاء بأشياء مثل: ربط الذاكرة الوهمية بالموارد الفيزيائية، وتجنّب التعارض بين المستخدمين . وبالمثل، تقدِّم افتراضية الخادم تجريدًا لآلة افتراضية VM، تحتوي على جميع ميزات الآلة الفيزيائية. وقد تكون هناك العديد من الآلات الافتراضية المدعومة على خادمٍ فيزيائي واحد، بينما يكون نظام التشغيل والمستخدمون على الآلة الافتراضية غير مدركين لحسن الحظ ارتباط الآلة الافتراضية بالموارد الفيزيائية. أي أنّ النقطة الأساسية هي افتراضية موارد الحوسبة التي تحافظ على التجريدات والواجهات التي كانت موجودة قبل أن تكون افتراضية. ويُعَدّ هذا مهمًّا، فهو يعني عدم حاجة مستخدمي هذه الأفكار التجريدية إلى التغيير، فهم يرون إعادة إنتاجٍ حقيقية للمورد المُحوَّل إلى الوضع الافتراضي. كما تعني الافتراضية أيضًا أنّ المستخدمين المختلفين (يُطلق عليهم أحيانًا المستأجرون) لا يمكنهم التداخل مع بعضهم بعضًا. إذًا ماذا يحدث عندما نحاول جعل الشبكة افتراضية؟ كانت الشبكات الافتراضية الخاصة الموضّحة سابقًا، إحدى النجاحات المُبكرة للشبكات الافتراضية. فقد سمحت لشركات الاتصالات بتقديم وهمٍ لعملاء الشركات بأنّ لديهم شبكةً خاصةً بهم، رغم تشاركهم في الواقع في الروابط والمبدّلات الأساسية مع العديد من المستخدمين الآخرين. ولكن تضيف الشبكات الافتراضية الخاصة الطابع الافتراضي فقط على بعض الموارد، لا سيما جداول العنوَنة والتوجيه. بينما تذهب افتراضية الشبكة إلى أبعد من ذلك اليوم، وتجعل كلّ جانب من جوانب الشبكات افتراضيًا، وهذا يعني وجوب دعم الشبكة الافتراضية لجميع المفاهيم الأساسية للشبكة الفيزيائية، فهي تشبه الآلة الافتراضية، مع دعمها لجميع موارد الخادم، ووحدة المعالجة المركزية، وأجهزة التخزين، وأجهزة الإدخال / الإخراج وغيرها. تحقيقًا لهذه الغاية، تُعَدّ شبكات VLAN -الموضَّحة سابقًا- الطريقة التي نستخدم بها شبكة L2 افتراضيًا. فقد أثبتت شبكات VLAN فائدتها الكبيرة للمؤسسات التي أرادت عزل مجموعات داخلية مختلفة (الأقسام والمختبرات مثلًا)، مما يمنح كلًا منها مظهرًا وكأنها تمتلك شبكة LAN خاصة بها. كما كان يُنظر إلى شبكات VLAN على أنّها طريقة واعدة لإضفاء الطابع الافتراضي على شبكات L2 في مراكز البيانات السحابية، مما يجعل من الممكن منح كلّ مستأجر شبكة L2 خاصةٍ به لعزل حركة مرور البيانات الخاصة به عن حركة مرور بيانات جميع المستأجرين الآخرين. ولكن كانت هناك مشكلة، حيث أن 4096 شبكةً محليةً افتراضيةً محتملةً غير كافية لحساب جميع المستأجرين الذين قد تستضيفهم السحابة، فهي تحتاج ضمن السحابة، إلى توصيل الآلات الافتراضية بدلًا من الآلات الفيزيائية التي تعمل عليها تلك الآلات الافتراضية. قُدِّم معيارٌ آخر سُمّي الشبكة المحلية الافتراضية الموسَّعة Virtual Extensible LAN أو اختصارًا VXLAN لمعالجة هذه المشكلة. حيث يغلِّف معيار VXLAN إطار إيثرنت افتراضي داخل رزمة UDP على عكس النهج الأصلي، الذي غَلَّف بفعالية إطار إيثرنت افتراضي داخل إطار إيثرنت آخر. هذا يعني أن الشبكة الافتراضية المستندة إلى VXLAN، والتي يشار إليها غالبًا باسم شبكة تراكب Overlay Network، تعمل فوق شبكة قائمة على IP، والتي تعمل بدورها على شبكة إيثرنت أساسية (أو ربما في شبكة VLAN واحدة فقط من شبكة الإيثرنت الأساسية). كما يتيح معيار VXLAN أيضًا لمستأجر واحد في السحابة، امتلاك شبكات VLAN متعدِّدة خاصة به، مما يسمح له بفصل حركة مرور بياناته الداخلية، وهذا يعني أنه من الممكن في النهاية أن يكون لديك شبكة VLAN مغلَّفة ضمن شبكة VXLAN تراكبية overlay ومغلَّفة ضمن شبكة VLAN. الشيء القوي في الافتراضية هو أنّها إذا تمت بصورة صحيحة، فيجب أن يكون من الممكن دمج موردٍ افتراضي داخل موردٍ افتراضي آخر، إذ يجب أن يتصرّف المورّد الافتراضي تمامًا مثل الموارد الفيزيائية، والقدرة على جعل مورد افتراضي افتراضيًا أيضًا هو أفضل دليل على عملك الجيد في جعل المورد الفيزيائي الأصلي افتراضيًا، فهي شبكات افتراضية على طول الطريق. تُعد ترويسة VXLAN الفعلية بسيطةً، كما هو موضح في الشكل السابق. تتضمن الترويسة معرّف شبكةٍ افتراضية ذو 24 بت Virtual Network Id أو اختصارًا VNI، بالإضافة إلى بعض الرايات flag والبِتات المحجوزة. كما يتضمن أيضًا إعدادًا معينًا لحقلي مصدر ووجهة UDP، مع حجز منفذ الوجهة 4789 رسميًا لشبكات VXLAN. ويُعَدّ اكتشاف كيفية التعرف بصورة فريدة على شبكات LAN الافتراضية (وسوم VLAN والشبكات الافتراضية (معرّفات VXLAN VID) الجزء السهل. وذلك لكون التغليف هو حجر الزاوية الأساسي لِلافتراضية، فكلّ ما تحتاج إلى إضافته هو معرّفٌ يخبرك إلى أيٍّ من المستخدمين المحتملين تنتمي هذه الرزمة المغلّفة. يتواجَه الجزء الصعب مع فكرة تداخُل الشبكات الافتراضية (مغلَّفة) داخل الشبكات الافتراضية، والتي هي نسخة version الشبكات من التعاود recursion. أمّا التحدي الآخر، فهو فهم كيفية أتمتة إنشاء الشبكات الافتراضية وإدارتها ونقلها وحذفها، إذ لا يزال هناك مجال كبير للتحسين على هذا المجال، وسيكون إتقان هذا، هو التحدي في صميم الشبكات في العقد المقبل. وبينما سيحدث بعض هذا العمل بلا شك في إعدادات الملكية، فهناك منصات افتراضية للشبكات مفتوحة المصدر (مثل مشروع تنغستن فابريك Tungsten Fabric التابع لمؤسسة لينكس Linux تقود الطريق. ترجمة -وبتصرّف- للقسم Implementation من فصل Internetworking من كتاب Computer Networks: A Systems Approach. اقرأ أيضًا المقال التالي: التشبيك المتقدم Advanced Internetworking في الشبكات الحاسوبية المقال السابق: توجيه Routing الرزم ضمن الشبكات الحاسوبية
-
افترضنا حتى الآن أنّ المبدّلات والموجّهات تملك معرفةً كافيةً بمخطط الشبكة، حتى تتمكن من اختيار المنفذ الصحيح الذي يجب إخراج كلّ رزمة عليه. حيث يكون التوجيه مسألةً هامةً فقط من أجل رزمة طلب الاتصال في حالة الدارات الافتراضية، وتتبع جميع الرزم اللاحقة نفس مسار الطلب. ويُعَدّ التوجيه مسألة هامة لكلّ رزمة في شبكات مخططات البيانات، بما في ذلك شبكات IP. حيث يجب أن يكون المبدّل أو الموجّه في كلتا الحالتين قادرًا على النظر إلى عنوان الوجهة ثم تحديد أيٍّ من منافذ الإخراج هو الخيار الأفضل لوصول الرزمة إلى ذلك العنوان. يتَّخذ المبدّل هذا القرار من خلال استشارة جدول التمرير كما رأينا سابقًا. وتتمثل مشكلة التوجيه الأساسية في كيفية حصول المبدّلات والموجّهات على المعلومات في جداول التمرير الخاصة بها. سنميّز الآن بين مصطلحي جدول التمرير وجدول التوجيه. حيث يُستخدَم جدول التمرير عند تمرير الرزمة، وبالتالي يجب أن يحتوي على معلومات كافية لإنجاز وظيفة التمرير. أي أنه لابد أن يحتوي كل صف في جدول التمرير على ربطٍ بين بادئة شبكة مع واجهة صادرة وبعض معلومات MAC، مثل عنوان إيثرنت لموجّه القفزة التالية. ومن ناحية أخرى، يُعَدّ جدول التوجيه الجدول الذي أنشأته خوارزميات التوجيه على أساس مقدِّمة لبناء جدول التمرير. حيث يحتوي على روابطٍ mappings بين بادئات الشبكة وموجّهات القفزة التالية. كما قد يحتوي أيضًا على معلومات حول كيفية تعلّم على هذه المعلومات، بحيث يتمكن الموجّه من تحديد متى يجب عليه تجاهُل بعض المعلومات. إذا كان جدول التوجيه وجدول التمرير بُنى بيانات منفصلة أم لا، فهو أمرٌ من اختيار التطبيق، ولكن هناك العديد من الأسباب للاحتفاظ بهما منفصلَين. حيث يجب هيكلة جدول التمرير لتحسين عملية البحث عن عنوان عند تمرير الرزمة، بينما يحتاج جدول التوجيه إلى التحسين بهدف حساب التغييرات في مخطط topology الشبكة. وقد يُطبَّق جدول التمرير في أجهزة متخصصة في كثير من الحالات، لكنه أمرٌ نادر بالنسبة لجدول التوجيه. 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; } Prefix/Length موجّه القفزة التالية NextHop 18/8 171.69.245.10 بينما يقدّم الجدول التالي مثالًا لصفٍ من جدول التمرير، والذي يحتوي على معلومات حول كيفية تمرير رزمة إلى عقدة القفزة التالية: أرسِلْ الرزمة عبر الواجهة رقم 0 مع عنوان MAC الذي هو 8:0:2b:e4:b:1:2. لاحظ أنّ آخر جزءٍ من المعلومات، يوفّره بروتوكول ARP: Prefix/Length الواجهة Interface عنوان MAC 18/8 if0 8:0:2b:e4:b:1:2 نحتاج إلى تذكير أنفسنا بسؤالٍ رئيسي قبل الدخول في تفاصيل التوجيه، والذي يجب طرحه في أيّ وقت نحاول فيه بناء آلية للإنترنت: (هل يتوسّع هذا الحل؟) الإجابة عن هذا السؤال باستخدام الخوارزميات والبروتوكولات الموضَّحة في هذا القسم هي (ليست كافية جدًا). فهذه الحلول مصمَّمة لشبكات ذات حجم متواضع إلى حدٍّ يصل لبضع مئات من العقد. ولكن تعمل الحلول التي ستُشرح الآن كلبنةٍ أساسيّة لبنية التوجيه الهرمي التحتية المستخدَمة في الإنترنت اليوم. حيث تُعرَف كلّ البروتوكولات الموضَّحة في هذا القسم باسم **بروتوكولات التوجيه داخل النطاق ** intradomain routing protocols، أو **بروتوكولات البوّابة الداخلية ** interior gateway protocols أو اختصارًا IGPs. نحتاج إلى تحديد نطاق التوجيه routing domain لفهم هذه المصطلحات. والتعريف الجيد هو شبكة متشابكة internetwork تخضع فيها جميع الموجّهات لنفس التحكم الإداري (مثل حرم جامعي واحد أو شبكة مزوّد خدمة إنترنت واحدة). حيث ستظهر أهمية هذا التعريف لاحقًا عندما ننظر إلى **بروتوكولات التوجيه بين النطاقات ** interdomain routing protocols. أمّا الشيء المهم الآن فهو دراستنا لمشكلة التوجيه في سياق الشبكات الصغيرة إلى متوسطة الحجم، وليس في سياق شبكةٍ بحجم الإنترنت. الشبكة كرسم بياني Network as a Graph يوضِّح الشكل الآتي رسمًا بيانيًا لشبكةً سُميت عُقَد الرسم البياني فيها من A إلى F، والتي قد تكون مضيفين hosts، أو مبدّلات، أو موجّهات، أو شبكات. سنركّز في مناقشتنا الأولية على الحالة التي تكون فيها العقد عبارة عن موجّهات. حيث تتوافق أضلاع الرسم البياني مع روابط الشبكة. وكلّ ضلعٍ له تكلفة مرتبطة به، مما يعطي بعض المؤشرات على الرغبة في الإرسال عبر هذا الرابط. لاحظ أنّ نماذج الشبكات (الرسوم البيانية) المُستخدَمة في هذا المقال لها أضلاع غير موجّهة undirected edges، أُسندت إليها تكلفة واحدة. ولكن الأضلاع الموجَّهة أدق، مما يعني عادةً أنه سيكون هناك زوجٌ من الأضلاع بين كلّ عقدة، فيتدفق كلٌّ منها باتجاهٍ مختلف، بحيث يكون لكلّ منهما تكلفة ضلع خاصة به. تتمثل مشكلة التوجيه الأساسية في العثور على المسار الأقل تكلفةً بين أيّ عقدتين، حيث تساوي تكلفة المسار مجموع تكاليف جميع الأضلاع التي يتكوّن منها المسار. ويمكنك تخيُّل أنه فيما يخص شبكة بسيطة مثل تلك الموجودة في الشكل السابق، وحساب جميع أقصر المسارات وتحميلها إلى حيّز تخزين غير متطاير على كلّ عقدة. مثل هذا النهج الثابت له العديد من أوجه النقص هي: لا يعالج فشل العقدة أو الرابط. لا يفرض إضافة عقد أو روابط جديدة. وهذا يعني أن تكاليف الضلع غير قابلة للتغيير، على الرغم من أننا قد نرغب في تغيير تكاليف الرابط بمرور الوقت (مثل إسناد تكلفة عالية لرابطٍ محمَّل كثيرًا). يتحقق التوجيه في معظم الشبكات العملية عن طريق تشغيل بروتوكولات التوجيه بين العقد بسبب الأمور الثلاثة السابقة. إذ توفِّر هذه البروتوكولات طريقةً ديناميكيةً وموزعةً لحلّ مشكلة إيجاد المسار الأقل تكلفة في ظلّ وجود حالات فشل الرابط والعقدة وتغيير تكاليف الضلع -لاحظ وجود كلمة موزعة distributed في الجملة السابقة-. من الصعب جعل الحلول المركزية قابلةً للتوسع، لذا تستخدم جميع بروتوكولات التوجيه المستخدمة على نطاق واسع خوارزمياتٍ موزّعة. تُعَدّ الطبيعة الموزّعة لِخوارزميات التوجيه أحد الأسباب الرئيسية التي تجعل هذا المجال غنيًا للبحث والتطوير، وذلك بالنظر إلى وجود الكثير من التحديات لجعل الخوارزميات الموزّعة تعمل جيدًا. إذ تزيد الخوارزميات الموزّعة من احتمالية امتلاك موجّهين في لحظة واحدة لأفكار مختلفة عن أقصر مسار مثلًا للوصول إلى وجهة معيّنة. فقد يعتقد كلّ واحد أنّ الآخر أقرب إلى الوجهة ويقرر إرسال رزم إليه. ومن الواضح أنّ هذه الرزم ستكون عالقةً في حلقة حتى يُحَل التناقض بين الموجّهَين، كما سيكون من الجيّد حلّها في أقرب وقت ممكن. وهذا مجرّد مثال واحد عن نوع المشكلة التي يجب على بروتوكولات التوجيه معالجتها. افترِض أنّ تكاليف الضلع في الشبكة معروفة. سنشرح الصنفين الرئيسيتين من بروتوكولات التوجيه، وهما مُتجه المسافة distance vector، وحالة الرابط link state. لنعود إلى مشكلة حساب تكاليف الضلع بطريقة مفيدة لاحقًا. متجه المسافة Distance-Vector باستخدام بروتوكول RIP الاسم الشائع الآخر لهذا الصنف من الخوارزمية هو بيلمان- فورد Bellman-Ford تيمُّنًا بمخترعَيها. وفيه تبني كلّ عقدة مصفوفة أحادية البُعد (متجه) تحتوي على مسافات distances أو تكاليف costs جميع العقد الأخرى، ثم توزِّع هذا المتّجه على الجيران المباشِرين. يكون الاعتبار الأولي لتوجيه متجّه المسافة: أنّ كلّ عقدة تعرف تكلفة روابط كلّ جيرانها المتصلين مباشرةً بها. وقد تتوفّر هذه التكاليف عندما يضبط مديرُ الشبكة الموجّه. وتُسنَد تكلفة لانهائية للرابط المعطّل. A B C D E F G A 0 1 1 ∞ 1 1 ∞ B 1 0 1 ∞ ∞ ∞ ∞ C 1 1 0 1 ∞ ∞ ∞ D ∞ ∞ 1 0 ∞ ∞ 1 E 1 ∞ ∞ ∞ 0 ∞ ∞ F 1 ∞ ∞ ∞ ∞ 0 1 G ∞ ∞ ∞ 1 ∞ 1 0 من الأسهل التفكير في مثال مشابه لذلك الموضَّح في الشكل السابق لمعرفة كيفية عمل خوارزمية توجيه متجّه المسافات. حيث تُضبَط تكلفة كلّ رابط على القيمة 1، بحيث يكون المسار الأقلّ تكلفةً هو ببساطة رابط مع أقلّ عدد من القفزات (بما أنّ جميع الأضلاع لها نفس التكلفة، فلن نعرض التكاليف في الرسم البياني). حيث يمكن تمثيل معرفة كلّ عقدة بالمسافات بينها وبين جميع العقد الأخرى بجدولً مُشابه للجدول السابق. لاحظ أنّ كلّ عقدة تعرف فقط المعلومات الموجودة في صفٍ واحد من الجدول (الذي يحمل اسم هذه العقدة في العمود الأيسر). والرؤية العامة global view المقدَّمة هنا غير متاحة في أيّ نقطة من الشبكة. يمكن عدّ كلّ صف في الجدول السابق مثل قائمة بالمسافات بين عقدة واحدة وجميع العقد الأخرى، والتي تمثّل المعتقدات الحالية لتلك العقدة. تُحدِّد كلّ عقدة تكلفةً مقدارها 1 لجيرانها المتصلين مباشرةً، وما لا نهاية (∞) لجميع العقد الأخرى في البداية. وبالتالي تعتقد العقدة A مبدئيًا أنه من الممكن الوصول إلى العقدة B بقفزة واحدة، في حين لا يمكن الوصول إلى العقدة D. يعكس جدول التوجيه المخزَّن في العقدة A هذه المجموعة من المعتقدات ويتضمّن اسم العقدة التالية التي قد تستخدمها العقدة A للوصول إلى أيّة عقدة ممكن الوصول إليها. إذًا سيبدو جدول توجيه العقدة A في البداية مثل الجدول التالي: العقدة الهدف Destination التكلفة Cost عقدة القفزة التالية NextHop B 1 B C 1 C D ∞ - E 1 E F 1 F G ∞ - الخطوة التالية في توجيه متّجه المسافة هي احتواء كل عقدة ترسل رسالة إلى جيرانها المتصلين مباشرةّ، على قائمة المسافات الشخصية الخاصة بها. حيث تُخبر العقدة F العقدة A بإمكانية وصولها إلى العقدة G بتكلفة 1، كما تعرف العقدة A أيضًا قدرتها على الوصول إلى F بتكلفة 1، لذلك تجمع هذه التكاليف للحصول على تكلفة الوصول إلى العقدة G عن طريق العقدة F. هذه التكلفة الإجمالية 2 أقل من التكلفة الحالية ∞، لذلك تسجّل العقدة A إمكانية وصولها إلى العقدة G بتكلفة 2 من خلال العقدة F. تتعلم العقدة A من العقدة C أنه يمكن الوصول إلى العقدة D عن طريق العقدة C بتكلفة 1، وتضيف هذا إلى تكلفة الوصول إلى C (1) وتقرر إمكانية الوصول إلى العقدة D عبر العقدة C بتكلفة 2، وهو أفضل من التكلفة القديمة ∞. كما تتعلم العقدة A من العقدة C إمكانية الوصول إلى العقدة B عن طريق العقدة C بتكلفة 1، لذلك تستنتج أنّ تكلفة الوصول إلى العقدة B عبر العقدة C هي 2. وبما أنّها أسوأ من التكلفة الحالية للوصول إلى B (1)، ستتجاهل المعلومات الجديدة. وعندها يمكن للعقدة A تحديث جدول التوجيه الخاص بها باستخدام التكاليف وعقد القفزة التالية وذلك لجميع العقد في الشبكة، والنتيجة موضَّحة في الجدول التالي: العقدة الوِجهة Destination التكلفة Cost عقدة القفزة التالية NextHop B 1 B C 1 C D 2 C E 1 E F 1 F G 2 F لا يتطلّب الأمر سوى عددٍ قليل من عمليات تبادل المعلومات بين العقد المتجاورة، قبل احتواء كلّ عقدة على جدول توجيه كامل في حالة عدم وجود أيّ تغييرات في مخطط الشبكة. وتُسمى عملية الحصول على معلومات توجيه مستقرّة لجميع العقد بالتقارب convergence. يوضح الجدول الآتي المجموعة النهائية من التكاليف من كلّ عقدة إلى جميع العقد الأخرى عند تقارب التوجيه، أي أنّه يمثّل الرؤية العامة Global View. حيث يجب التأكيد على عدم وجود عقدة واحدة في الشبكة تحتوي على جميع المعلومات الواردة في هذا الجدول، كما تعرف كلّ عقدة فقط محتويات جدول التوجيه الخاص بها. ويكمن جمال الخوارزمية الموزعة هذه، في تمكينها لجميع العقد من تحقيق رؤية مستقرّة للشبكة في غياب وجود أية سلطة مركزية. A B C D E F G A 0 1 1 2 1 1 2 B 1 0 1 2 2 2 3 C 1 1 0 1 2 2 2 D 2 2 1 0 2 3 1 E 1 2 2 3 0 2 3 F 1 2 2 2 2 0 1 G 2 3 2 1 3 1 0 هناك بعض التفاصيل الواجب ملؤها قبل اكتمال مناقشتنا لتوجيه متجّه المسافة. حيث نلاحظ أولًا وجود حالتين مختلفتين تقرِّر بموجبهما عقدةٌ معيّنة إرسال تحديثٍ في التوجيه إلى جيرانها. وإحدى هاتين الحالتين هي التحديث الدوري periodic update، حيث ترسل كلّ عقدة تلقائيًا رسالة تحديث بين الحين والآخر في هذه الحالة، حتى لو لم يتغيَّر شيء. كما يعمل ذلك على السماح للعقد الأخرى بمعرفة أنّ هذه العقدة لا تزال قيد التشغيل، إلى جانب تأكُّدها من استمرار حصولها على المعلومات التي قد تحتاج إليها إذا أصبحت مساراتها الحالية غير متاحة. يختلف تكرار هذه التحديثات الدورية من بروتوكولٍ لآخر، ويتراوح عادةً من عدّة ثوانٍ إلى عدّة دقائق. أمّا الآلية الثانية التي تسمى أحيانًا التحديث المحفَّز triggered update، تحدث عندما تلاحظ العقدة فشل رابطٍ أو تتلقى تحديثًا من إحدى العقد المجاورة لها مما يتسبب في تغيير أحد المسارات في جدول التوجيه الخاص بها. حيث ترسل العقدة تحديثًا إلى العقد المجاورة لها عندما يتغيّر جدول توجيهها، مما قد يؤدّي إلى تغيير في جداول هذه العقد ويتسبب في إرسال هذه العقد بدورها تحديثًا إلى جيرانها. افترض الآن ما يحدث عند فشل رابط أو عقدة. حيث تُرسَل العقد التي تلاحظ هذا الفشل أولًا قوائمًا جديدةً بالمسافات إلى جيرانها، وعادةً ما يستقر النظام بسرعة إلى حدٍّ ما في حالة جديدة. وهناك إجابتان مختلفتان فيما يتعلّق بمسألة كيفية اكتشاف العقدة للفشل. أحد هذه الأساليب هو اختبار العقدة للرابطَ إلى عقدة أخرى باستمرار عن طريق إرسال رزمة تحكُّم، ثم تلقّي إشعارٍ بالاستلام. أمّا الأسلوب الآخر فهو تحديد العقدة أنّ الرابط (أو العقدة الموجودة في الطرف الآخر من الرابط) معطَّل إن لم تتلقَّ تحديثًا بالتوجيه الدوري المتوقَّع لدورات التحديث القليلة الماضية. لفهم حالة اكتشاف العقدة فشل رابط، افترض ما سيحدث عندما تكتشف العقدة F فشل الرابط الذي يربطها بالعقدة G. أولًا، تحدّد العقدة F المسافة الجديدة إلى العقدة G بالقيمة ∞، وتمرر هذه المعلومات إلى العقدة A. بما أن العقدة A تعرف أن مسارها المكوَّن من قفزتين إلى العقدة G يمر عبر العقدة F، فإن العقدة A ستحدد أيضًا المسافة إلى العقدة G بالقيمة ∞. ولكن ستتعلم العقدة A مع التحديث التالي من العقدة C أن العقدة C لديها مسارٌ مكون من قفزتين إلى العقدة G. وهكذا ستعرف العقدة A أنه من الممكن الوصول إلى العقدة G في 3 قفزات عبر العقدة C، وهذا أقل من ∞، وبالتالي ستحدّث العقدة A الجدول الخاص بها تبعًا لذلك. وعند إعلانها عن هذا إلى العقدة F، فستتعلم العقدة F أنّ بإمكانها الوصول إلى العقدة G بتكلفة 4 عبر العقدة A، وهي أقل من ∞، وسيصبح النظام مستقرًا مرةً أخرى. قد تمنع ظروف مختلفة قليلًا استقرار الشبكة لسوء الحظ. افترض، على سبيل المثال، أن الرابط من العقدة A إلى العقدة E معطّلٌ. فتعلن العقدة A عن مسافة لا نهائية (∞) إلى العقدة E في الدورة التالية من التحديثات، لكن العقدتين B و C يعلنان عن مسافة 2 إلى العقدة E. قد يحدث ما يلي اعتمادًا على التوقيت الدقيق للأحداث: تستنتج العقدة B، عند سماع أن العقدة E يمكن الوصول إليها عبر قفزتين من العقدة C، أنه يمكن الوصول إلى العقدة E في 3 قفزات وتعلن عن ذلك إلى العقدة A، لتستنتج العقدة A أنه يمكنها الوصول إلى العقدة E في 4 قفزات وتعلن عن ذلك للعقدة C، وبالتالي تستنتج العقدة C أنه يمكنها الوصول إلى العقدة E في 5 قفزات، وهَلُمَّ جرًّا. تتوقف هذه الدورة فقط عندما تصل المسافات إلى رقم كبير بما يكفي لعدّه ∞. لا تعرف أي من العقد فعليًا أن العقدة E لا يمكن الوصول إليها في غضون ذلك، وأن جداول توجيه الشبكة لا تستقر. يُعرف هذا الموقف باسم مشكلة العد إلى اللانهاية count to infinity. هناك عدة حلول جزئية لهذه المشكلة. الحل الأول هو استخدام عدد صغير نسبيًا كتقريب لما لا نهاية (∞). فقد نقرر أن الحد الأقصى لعدد القفزات لعبور شبكةٍ معينة لن يكون أبدًا أكثر من 16 على سبيل المثال، ولذا يمكننا اختيار القيمة 16 كقيمة تمثل اللانهاية. هذا على الأقل يحدْ من الوقت الذي يستغرقه العد إلى اللانهاية. ويمكن أن نواجه مشكلة أيضًا إذا نمت شبكتنا إلى نقطة تبعد عن بعض العقد بأكثر من 16 قفزة. يُطلق على إحدى تقنيات تحسين وقت استقرار التوجيه اسم الانقسام الأفقي split horizon. فكرة هذه التقنية تقوم على أنه إذا أرسلت العقدة تحديث توجيه إلى العقد المجاورة لها، فإنها لا ترسل تلك المسارات إلى العقدة المجاورة التي تعلمت منها هذه المسارات. إذا احتوت العقدة B على المسار (E , 2 , A) في جدولها مثلًا، فإنها تعرف أنها تعلمت هذا المسار من العقدة A، وبالتالي كلما أرسلت العقدة B تحديث توجيه إلى العقدة A، فلا تضمّن المسار (E , 2) في هذا التحديث. يوجد شكلٌ أقوى من تقنية الانقسام الأفقي، يُسمى الانقسام الأفقي مع الانعكاس الهادم split horizon with poison reverse، حيث ترسل العقدة B بالفعل هذا المسار مرة أخرى إلى العقدة A، لكنها تضع معلومات سلبية في المسار للتأكد من أن العقدة A لن تستخدم العقدة B في النهاية للوصول إلى العقدة E. حيث ترسل العقدة B المسار (E , ∞) مثلًا إلى العقدة A. المشكلة في كلتا الطريقتين هي أنهما تعملان فقط مع حلقات التوجيه التي تتضمن عقدتين. لذلك يجب اتخاذ تدابير أكثر صرامة بالنسبة لحلقات التوجيه الأكبر. استكمالًا للمثال، لو انتظرت العقدتان B و C لفترة من الوقت بعد سماع فشل الرابط من العقدة A قبل الإعلان عن المسارات إلى العقدة E، لَكانتا قد اكتشفتَا أن أيًا منهما لم يكن لديه حقًا مسار إلى العقدة E. تؤخِّر طريقة التوجيه بمتجه المسافة لسوء الحظ من تقارب البروتوكول، فسرعة التقارب هي إحدى المزايا الرئيسية لمنافستها والتي هي طريقة التوجيه بحالة الرابط link-state routing، والتي سنتكلم عنها لاحقًا. التطبيق Implementation الشيفرة التي تطبق هذه الخوارزمية واضحةٌ جدًا. تحدد البنية Route كل مدخلة في جدول التوجيه، ويحدد الثابت MAX_TTL المدة التي تُحتفَظ بها مدخلةٌ في الجدول قبل التخلص منها. #define MAX_ROUTES 128 /* الحجم الأقصى لِجدول التوجيه */ #define MAX_TTL 120 /* الوقت (مقدرًا بالثواني) حتى انتهاء صلاحية المسار */ typedef struct { NodeAddr Destination; /* عنوان الوجهة */ NodeAddr NextHop; /* عنوان عقدة القفزة التالية */ int Cost; /* مقياس المسافة */ u_short TTL; /* (العُمر) time to live */ } Route; int numRoutes = 0; Route routingTable[MAX_ROUTES]; يعتمد الإجراء، الذي يحدّث جدول توجيه العقدة المحلية، على مسارٍ جديد يُعطَى باستخدام الدالة mergeRoute. تمسح دالة المؤقت، على الرغم من عدم ظهورها، قائمةَ المسارات في جدول توجيه العقدة دوريًا، وتقلل من حقل TTL لكل مسار، وتتجاهل أية مسارات لها زمن TTL يساوي 0. لكن لاحظ إعادة ضبط الحقل TTL بالقيمة MAX_TTL في أي وقت تُعيد فيه رسالةُ تحديثٍ قادمةٌ من عقدةٍ مجاورة تأكيدَ المسار: void mergeRoute (Route *new) { int i; for (i = 0; i < numRoutes; ++i) { if (new->Destination == routingTable[i].Destination) { if (new->Cost + 1 < routingTable[i].Cost) { /* وُجِد مسارٌ أفضل */ break; } else if (new->NextHop == routingTable[i].NextHop) { /* تغير مقياس عقدة القفزة التالية الحالية */ break; } else { /* المسار غير جيد --- تجاهله فقط */ return; } } } if (i == numRoutes) { /* هذا مسارٌ جديد تمامًا؛ فهل هناك حيزٌ لذلك؟ */ if (numRoutes < MAXROUTES) { ++numRoutes; } else { /* لا يمكن احتواء هذا المسار في الجدول لذا استسلم */ return; } } routingTable[i] = *new; /* TTL أعِد ضبط */ routingTable[i].TTL = MAX_TTL; /* حساب قفزة للوصول إلى العقدة التالية */ ++routingTable[i].Cost; } أخيرًا، تُعَد الإجرائية updateRoutingTable الإجرائية الرئيسية التي تستدعي الدالة mergeRoute لدمج كافة المسارات الموجودة في تحديث التوجيه الذي يصل من عقدة مجاورة. void updateRoutingTable (Route *newRoute, int numNewRoutes) { int i; for (i=0; i < numNewRoutes; ++i) { mergeRoute(&newRoute[i]); } } بروتوكول معلومات التوجيه Routing Information Protocol يُعد بروتوكول معلومات التوجيه RIP أحد بروتوكولات التوجيه الأكثر استخدامًا في شبكات IP. يرجع استخدامه على نطاق واسع منذ بدايات ظهور IP، إلى حقيقة أنه مُوزَّعٌ جنبًا إلى جنب مع إصدار يونيكس الشهير Berkeley Software Distribution الذي يُختصَرإلى BSD، والذي اُشتقَّت منه العديد من إصدارات يونيكس التجارية وهو أيضًا بسيط للغاية. بروتوكول RIP هو المثال الأساسي لبروتوكول التوجيه المبني على خوارزمية متجه المسافة الموصوفة سابقًا. تختلف بروتوكولات التوجيه في الشبكات المتشابكة قليلًا عن نموذج الرسم البياني المثالي. الهدف من الموجّهات في الشبكة المتشابكة هو تعلم كيفية تمرير الرزم إلى شبكات مختلفة. وبالتالي تعلن الموجّهات عن تكلفة الوصول إلى الشبكات بدلًا من الإعلان عن تكلفة الوصول إلى الموجّهات الأخرى. يعلن الموجه C للموجِّه A في الشكل التالي، على سبيل المثال، حقيقةَ أنه يمكنه الوصول إلى الشبكات 2 و 3 (التي يتصل بها مباشرةً) بتكلفة 0، والشبكات 5 و 6 بتكلفة 1، والشبكة 4 بتكلفة 2. يمكنك أن ترى دليلًا على ذلك في صيغة رزمة RIP (الإصدار 2) في الشكل الآتي. تُعالَج غالبية الرزمة بالثلاثية (العنوان، القناع، المسافة) (address, mask, distance). ولكن مبادئ خوارزمية التوجيه هي نفسها. فإذا تعلم الموجّه A، على سبيل المثال، من الموجّه B أنه يمكن الوصول إلى الشبكة X بتكلفة أقل عبر الموجّه B مقارنةً بعقدة القفزة التالية الموجودة في جدول التوجيه، فإن الموجّه A يحدّث التكلفة ومعلومات عقدة القفزة التالية لرقم الشبكة وفقًا لذلك. بروتوكول RIP هو في الواقع تطبيق مباشر إلى حد ما لتوجيه متجه المسافة. ترسل الموجهات التي تشغّل بروتوكول RIP إعلاناتها كل 30 ثانية، حيث يرسل الموجّه أيضًا رسالة تحديث عندما يتسبب تحديثٌ من موجهٍ آخر في تغيير جدول التوجيه الخاص به. إحدى النقاط الهامة هي أن بروتوكول RIP يدعم عائلات عناوين متعددة، وليس عناوين IP فقط، وهذا هو سبب وجود الجزء Family ضمن الإعلانات. قدّم الإصدار 2 من بروتوكول RIP المسمَّى RIPv2 أيضًا أقنعة الشبكة الفرعية الموضحة سابقًا، بينما عمل الإصدار 1 من بروتوكول RIP مع عناوين IP القديمة. يمكن استخدام مجموعة من المقاييس metrics أو التكاليف المختلفة للروابط في بروتوكول التوجيه. يتخذ بروتوكول RIP أبسط نهج، حيث تساوي جميع تكاليف الروابط القيمة 1، وبالتالي يحاول RIP دائمًا العثور على الحد الأدنى لقفز المسار. المسافات الصالحة هي من 1 إلى 15، وتمثل المسافة 16 اللانهاية. يحد هذا أيضًا من استخدام بروتوكول RIP بالعمل على شبكات صغيرة إلى حد ما، أي تلك الشبكات التي ليس لها مسارات أطول من 15 قفزة. حالة الرابط link state باستخدام بروتوكول OSPF التوجيه باستخدام حالة الرابط هو الصنف الرئيسي الثاني لبروتوكول التوجيه داخل النطاق. تشبه الافتراضات الابتدائية لتوجيه حالة الرابط إلى حدٍ ما تلك الافتراضات الخاصة بتوجيه متجه المسافة. يُفترض أن تكون كل عقدة قادرة على معرفة حالة الرابط الذي يصلها بجيرانها (لأعلى أو لأسفل) وتكلفة كل رابط. نريد تزويد كل عقدة بمعلومات كافية لتمكينها من العثور على المسار الأقل تكلفة إلى أية وجهة. الفكرة الأساسية وراء بروتوكولات حالة الرابط بسيطة للغاية: تعرف كل عقدة كيفية الوصول إلى جيرانها المتصلين بها مباشرة، وإذا تأكدت من نشر كل هذه المعرفة على كل عقدة، فستحصل كل عقدة على معرفة كافية بالشبكة لبناء خارطة كاملة لها. من الواضح أن هذا شرط كافٍ (على الرغم من أنه ليس شرطًا ضروريًا) للعثور على أقصر مسار إلى أية نقطة في الشبكة، وبالتالي تعتمد بروتوكولات توجيه حالة الرابط على آليتين هما: النشر الموثوق لمعلومات حالة الرابط، وحساب المسارات من مجموع معرفة حالة الرابط المتراكمة. الإغراق الموثوق Reliable Flooding الإغراق الموثوق هو عملية التأكد من حصول جميع العقد المشاركة في بروتوكول التوجيه على نسخة من معلومات حالة الرابط من جميع العقد الأخرى. الفكرة الأساسية هي أن ترسل العقدة معلومات حالة الرابط الخاصة بها على جميع روابطها المتصلة مباشرة بها، أي تتلقى كل عقدة هذه المعلومات ثم تُمررها إلى جميع روابطها. تستمر هذه العملية حتى تصل المعلومات إلى جميع العقد في الشبكة. تنشئ كل عقدةٍ حزمة تحديث، تسمى أيضًا رزمة حالة الرابط link-state packet أو اختصارًا LSP، والتي تحتوي على المعلومات التالية: معرّف العقدة التي أنشأت رزمة LSP. قائمة بالعقد المجاورة المتصلة مباشرةً بتلك العقدة، مع تكلفة الرابط لكل منها. رقم تسلسلي. عُمر time to live هذه الرزمة. أول عنصرين مطلوبين لتفعيل حساب المسار، و يُستخدَم العنصران الآخران في جعل عملية إغراق الرزمة لجميع العقد موثوقة. تتضمن هذه الوثوقية التأكد من أن لديك أحدث نسخة من المعلومات، حيث قد يكون هناك العديد من رزم LSP المتناقضة التي تعبر الشبكة من عقدة واحدة. ثبُتَ أن تحقيق الإغراق الموثوق أمرٌ صعب للغاية (تسبب إصدار قديم لتوجيه حالة الرابط المستخدَم في شبكة أربانت ARPANET في فشل هذه الشبكة في عام 1981 على سبيل المثال). يعمل الإغراق بالطريقة التالية. أولاً، يكون إرسال رزم LSP بين الموجهات المتجاورة موثوقًا باستخدام إشعارات الاستلام وإعادة الإرسال كما هو الحال في بروتوكول طبقة الربط الموثوق. ولكن هناك عدة خطوات أخرى ضرورية لإغراق جميع العقد في الشبكة برزم LSP بصورة موثوقة. افترض العقدة X التي تتلقى نسخةً من رزمة LSP التي نشأت في عقدة أخرى هي Y. لاحظ أن العقدة Y قد تكون أي موجهٍ آخر في نفس نطاق التوجيه كالعقدة X. تتحقق العقدة X فيما إذا كانت قد خزّنت بالفعل نسخة من الرزمة LSP من العقدة Y. إن لم يحدث ذلك، فإنها تخزن رزمة LSP. وإذا كان لديها نسخة بالفعل، فإنها تقارن الأرقام التسلسلية، فإذا احتوت رزمة LSP الجديدة على رقم تسلسلي أكبر، فمن المفترض أن تكون الأحدث، وتخزّن رزمة LSP الجديدة، لتحل محل الرزمة القديمة. يشير الرقم التسلسلي الأصغر (أو المتساوي) إلى رزمة LSP أقدم (أو ليست أحدث) من الرزمة المخزَّنة، لذلك ستكون متجاهَلة وليس هناك حاجة إلى أي إجراء آخر. إذا كانت رزمة LSP المستلَمة هي الأحدث، عندها ترسل العقدة X نسخةً من رزمة LSP إلى جميع جيرانها باستثناء الجار الذي استلمت رزمة LSP منه للتو. تساعد حقيقة عدم إرسال رزمة LSP مرة أخرى إلى العقدة التي اُستلِمت منها في وضع حد لإغراق LSP. بما أن العقدة X تمرّر الرزمة LSP إلى جميع جيرانها، والذين يفعلون الشيء نفسه، فإن أحدث نسخة من رزمة LSP تصل في النهاية إلى جميع العقد. يوضح الشكل السابق رزمة LSP المُغرَقة في شبكة صغيرة. تصبح كل عقدة مظللةً لأنها تخزّن رزمة LSP الجديدة. تصل رزمة LSP إلى العقدة X في القسم (أ) من الشكل السابق، والتي ترسلها إلى جيرانها وهما العقدتان A و C في القسم (ب) من الشكل السابق. لا ترسل العقدتان A و C رزمة LSP مرة أخرى إلى العقدة X، ولكن تُرسِلانها إلى العقدة B. بما أن العقدة B تتلقى نسختين متطابقتين من الرزمة LSP، فإنها ستقبل الرزمة التي تصل أولًا وتتجاهل الثانية كنسخةٍ مكررة. ثم تمرر رزمة LSP إلى العقدة D، والتي ليس لها جيران لِإغراقها، وتكتمل العملية. تولّد كل عقدةٌ رزمَ LSP ضمن حالتين كما هو الحال في بروتوكول RIP. يمكن أن يتسبب انتهاء صلاحية مؤقتٍ دوري أو تغيير في مخطط الشبكة في أن تنشئ عقدةٌ رزمة LSP جديدة. ولكن السبب الوحيد المستند إلى مخطط الشبكة لأن تنشئ العقدة رزمةَ LSP هو تعطُّل أحد الروابط المتصلة مباشرةً بها أو عبر جيرانها المباشرين. يمكن الكشف عن فشل الرابط في بعض الحالات بواسطة بروتوكول طبقة الربط. يمكن اكتشاف زوال العقدة المجاورة أو فقدان الاتصال بها باستخدام الرزم الترحيبية hello packets الدورية. وترسل كل عقدةٍ هذه الرزم إلى جيرانها المباشرين على فترات زمنية محددّة. إذا مر وقت طويل وكافٍ دون تلقي رزمة ترحيبية من أحد الجيران، فستعلن بأنّ الرابط إلى هذا الجار مُعطَّل، وستنشئ رزم LSP جديدة لتبيّن هذه الحقيقة. يتمثل أحد أهداف التصميم المهمّة لآلية إغراق بروتوكول حالة الرابط في أنه يجب إغراق أحدث المعلومات في جميع العقد بأسرع ما يمكن. بينما يجب إزالة المعلومات القديمة من الشبكة وعدم السماح بتداولها. بالإضافة إلى أنه من المستحسن تقليل إجمالي حركة مرور بيانات التوجيه التي تُرسَل عبر الشبكة، فهو مجرد حِملٍ من منظور أولئك الذين يستخدمون الشبكة لِتطبيقاتهم. إحدى الطرق السهلة لتقليل الحِمل هي تجنب توليد رزم LSP ما لم يكن ذلك ضروريًا للغاية. ويمكن القيام بذلك باستخدام مؤقتات طويلة جدًا، غالبًا في حدود الساعات، لإنشاء رزم LSP الدورية. بما أن بروتوكول الإغراق يمكن الاعتماد عليه حقًا عند تغيُّر مخطط الشبكة، فمن الآمن افتراض أن الرسائل التي تقول "لم يتغير شيء" لا تحتاج إلى إرسالها كثيرًا. تحمل رزم LSP أرقامًا تسلسلية للتأكد من استبدال المعلومات القديمة بمعلومات أحدث. حيث تزيد العقدة الرقم التسلسلي بمقدار 1 في كل مرة تُنشِئ فيها رزمة LSP جديدة. لا يُتوقع أن تلتف هذه الأرقام التسلسلية على عكس معظم الأرقام التسلسلية المستخدمة في البروتوكولات، لذا يجب أن يكون الحقل كبيرًا جدًا (64 بت مثلًا). إذا تعطّلت عقدة ثم عادت مرة أخرى، فإنها تبدأ برقم تسلسلي 0. وإذا كانت العقدة معطّلةً لفترة طويلة، فستنتهي مهلة جميع رزم LSP القديمة لتلك العقدة. وبخلاف ذلك، ستتلقى هذه العقدة في النهاية نسخةً من رزمة LSP الخاصة بها مع رقمٍ تسلسلي أعلى، والتي يمكنها بعد ذلك زيادة قيمتها واستخدامها كرقمٍ تسلسلي خاص بها. وسيَضمَن ذلك أن تحِل رزمة LSP الجديدة الخاصة بها محلَ أي من رزم LSP القديمة الموجودة قَبل تعطّل العقدة. تحمل رزم LSP أيضًا عُمرًا time to live. والذي يُستخدم لضمان إزالة معلومات حالة الرابط القديمة من الشبكة. تعمل العقدة دائمًا على تقليل قيمة TTL الخاصة برزمة LSP المستلَمة حديثًا قبل إغراقها في جيرانها. كما تعمل على إعطاء عمرٍ لرزمة LSP أثناء تخزينها في العقدة. تُعيد العقدة إغراق رزمة LSP باستخدام TTL بقيمة 0، عندما تصل قيمة TTL إلى 0، والذي تفسره جميع العقد في الشبكة كإشارة لحذف رزمة LSP. حساب المسار Route Calculation تستطيع العقدة حساب خارطة كاملة لمخطَّط الشبكة بمجرد أن تحصل على نسخة من رزمة LSP من كل عقدة أخرى، ويمكنها تحديد أفضل مسار لكل وجهة من خلال هذه الخارطة. إذًا السؤال هو بالضبط كيف تُحسب المسارات من خلال هذه المعلومات؟ يعتمد الحل على خوارزمية معروفة جيدًا في نظرية الرسم البياني، والتي هي خوارزمية Dijkstra الأقصر مسارًا. سنُعرِّف أولًا خوارزمية Dijkstra باستخدام مصطلحات نظرية الرسم البياني. تخيّل أن العقدة تأخذ جميع رزم LSP التي تلقتها وتبني تمثيلًا رسوميًا للشبكة، حيث يرمز N إلى مجموعة العقد في الرسم البياني، ويرمز l (i ، j) إلى التكلفة غير السلبية (الوزن) المرتبط بالضلع بين العقدتين i و j في المجموعة N بحيث تكون l (i ، j) = ∞ إن لم يكن هناك ضلع يربط العقدتين i و j. تُشير العقدة s في المجموعة N في الوصف الآتي إلى العقدة التي تنفّذ الخوارزمية للعثور على أقصر مسار لجميع العقد الأخرى في N. تحافظ الخوارزمية أيضًا على المتغيرين التاليين: M تشير إلى مجموعة العقد المتضمّنة في الخوارزمية حتى الآن، وتشير C(n) إلى تكلفة المسار من العقدة s إلى كل عقدة n. تُعرَّف الخوارزمية على النحو التالي بالنظر إلى هذه التعريفات: M = {s} for each n in N - {s} C(n) = l(s,n) while (N != M) M = M + {w} such that C(w) is the minimum for all w in (N-M) for each n in (N-M) C(n) = MIN(C(n), C(w)+l(w,n)) تعمل الخوارزمية على النحو التالي: نبدأ بالمجموعة M التي تحتوي على العقدة s ثم نهيّئ جدول تكاليف (أو المصفوفة C (n)) العقد الأخرى باستخدام التكاليف المعروفة للعقد المتصلة مباشرةً. ثم نبحث عن العقدة التي يمكن الوصول إليها بأقل تكلفة (w) ونضيفها إلى المجموعة M. أخيرًا، نحدّث جدول التكاليف من خلال النظر في تكلفة الوصول إلى العقد من خلال العقدة w. نختار مسارًا جديدًا للعقدة n. في السطر الأخير من الخوارزمية، التي تمر عبر العقدة w إذا كانت التكلفة الإجمالية للانتقال من المصدر إلى العقدة w ثم من العقدة w إلى العقدة n أقلّ من المسار القديم إلى العقدة n. يتكرر هذا الإجراء حتى تصبح جميع العقد ضمن المجموعة M. يحسب كل مبدّل جدول التوجيه الخاص به مباشرةً من رزم LSP التي جمعها باستخدام تحقيقٍ خوارزمية Dijkstra المُسماة خوارزمية البحث الأمامي forward search. حيث يحتفظ كل مبدلٍ بقائمتين، تُعرفان باسم Tentative تجريبية وConfirmed مؤكدة. تحتوي كل من هذه القوائم على مجموعة من مدخلاتٍ من النموذج (Destination, Cost, NextHop). تعمل الخوارزمية على النحو التالي: هيّئ القائمة المؤكدة Confirmed بمدخلةٍ لك، هذه المدخلة لها تكلفة 0. أطلق على العقدة التي أُضيفت للتو إلى القائمة Confirmed في الخطوة السابقة اسم العقدة Next وحدّد رزمة LSP الخاصة بها. احسب تكلفة Cost الوصول إلى العقدة المجاورة Neighbor لكل عقدةٍ مجاورة Neighbor للعقدة Next، بحيث تساوي مجموع التكلفة من عندك إلى العقدة Next ومن العقدة Next إلى العقدة Neighbor. إن لم تكن العقدة Neighbor حاليًا في القائمة Confirmed أو في القائمة Tentative، فأضِف (Neighbor, Cost, NextHop) إلى القائمة Tentative، حيث يكون NextHop هو الاتجاه الذي تستخدمه للوصول إلى العقدة Next. إذا كانت العقدة Neighbor حاليًا في القائمة Tentative، وكانت التكلفة Cost أقل من التكلفة المدرجَة حاليًا للعقدة Neighbor، فاستبدل المدخلة الحالية بـ (Neighbor, Cost, NextHop) حيث NextHop هو الاتجاه الذي تستخدمه للوصول إلى العقدة Next. إذا كانت القائمة Tentative فارغة، فتوقف. وإلا فاختر المدخلة من القائمة Tentative بأقل تكلفة، وانقله إلى القائمة Confirmed، ثم عُدْ إلى الخطوة 2. سيصبح فهم ذلك أسهل كثيرًا عندما ننظر إلى مثال، حيث افترض الشبكة الموضحة في الشكل السابق. لاحظ أن هذه الشبكة بها مجموعة من تكاليف الأضلاع المختلفة. يتتبع الجدول الآتي خطوات بناء جدول توجيه العقدة D. نشير إلى مخارج العقدة D باستخدام أسماء العقد التي تتصل بها، B و C. لاحظ الطريقة التي تتبعها الخوارزمية، حيث تبدأ فيها باستخدام المسارات الخاطئة (مثل مسار التكلفة المكون من 11 وحدة إلى العقدة B والذي كان أول إضافة إلى القائمة Tentative ولكنها تنتهي بالمسارات الأقل تكلفة لجميع العقد. الخطوة Step القائمة المؤكدة Confirmed القائمة التجريبية Tentative ملاحظات 1 (D,0,–) بما أن العقدة D هي العضو الجديد الوحيد في القائمة المؤكدة، فانظر إلى رزمة LSP الخاصة بها. 2 (D,0,–) (B,11,B) (C,2,C) تقول رزمة LSP الخاصة بالعقدة D أنه يمكن الوصول للعقدة B باستخدام العقدة B بتكلفة 11، وهو أفضل من أي شيء آخر في أيٍّ من القائمتين، لذا ضعها في القائمة Tentative؛ ونفس الشيء بالنسبة للعقدة C. 3 (D,0,–) (C,2,C) (B,11,B) ضع عضو القائمة Tentative الأقل تكلفة والذي هو (C) في القائمة Confirmed، ثم افحص رزمة LSP للعضو المؤكَّد حديثًا الذي هو (C). 4 (D,0,–) (C,2,C) (B,5,C) (A,12,C) تكلفة الوصول من العقدة B إلى العقدة C هي 5، لذا استبدل (B ، 11 ، B) بها، وتخبرنا رزمة LSP الخاصة بالعقدة C أنه يمكن الوصول إلى العقدة A بتكلفة 12. 5 (D,0,–) (C,2,C) (B,5,C) (A,12,C) انقل العضو الأقل تكلفة من القائمة Tentative الذي هو (B) إلى القائمة Confirmed، ثم انظر إلى رزمة LSP الخاصة به. 6 (D,0,–) (C,2,C) (B,5,C) (A,10,C) بما أنه يمكن الوصول إلى العقدة A بتكلفة 5 عن طريق العقدة B، فاستبدل مدخلة القائمة Tentative. 7 (D,0,–) (C,2,C) (B,5,C) (A,10,C) انقل العضو الأقل تكلفة من القائمة Tentative الذي هو (A) إلى القائمة Confirmed، وبذلك نكون قد انتهينا. تتميز خوارزمية توجيه حالة الرابط بالعديد من الخصائص الرائعةهي: لقد ثبت أنها تستقر بسرعة، ولا تولّد الكثير من حركة مرور البيانات، وتستجيب بسرعة لتغييرات مخطط الشبكة أو فشل العقدة، ولكن يمكن أن يكون مقدار المعلومات المخزَّنة في كل عقدة (رزمة LSP واحدة لكل عقدة أخرى في الشبكة) كبيرًا جدًا. هذه واحدة من المشكلات الأساسية للتوجيه وهي مثال عن المشكلة العامة ألا وهي قابلية التوسع. بروتوكول المسار المفتوح الأقصر أولا Open Shortest Path First Protocol يُعد بروتوكول OSPF أحد أكثر بروتوكولات توجيه حالة الرابط استخدامًا. تشير الكلمة الأولى، مفتوح Open، إلى حقيقة أنه معيار مفتوح وغير مملوك، أُنشئ تحت رعاية فريق Internet Engineering Task Force أو اختصارًا IETF. يأتي جزء "SPF" من اسمٍ بديل لتوجيه حالة الرابط. يضيف بروتوكول OSPF العديد من الميزات إلى خوارزمية حالة الرابط الأساسية بما في ذلك ما يلي: استيثاق رسائل التوجيه Authentication of routing messages: تتمثل إحدى ميّزات خوارزميات التوجيه الموّزعة في أنها تنشر المعلومات من عقدة واحدة إلى العديد من العقد الأخرى، وبالتالي يمكن أن تتأثر الشبكة بأكملها بمعلومات سيئة من عقدة واحدة. لذلك من الجيد التأكد من إمكانية الوثوق بجميع العقد المشاركة في البروتوكول، حيث يساعد استيثاق رسائل التوجيه في تحقيق ذلك. استخدمت الإصدارات القديمة من بروتوكول OSPF كلمة مرور بسيطة مؤلفة من 8 بايتات للاستيثاق. وهذا ليس شكلًا قويًا من أشكال الاستيثاق لمنع المستخدمين الضارين، ولكنه يخفّف من بعض المشكلات التي تسببها أخطاء الضبط misconfiguration أو الهجمات العرَضية (أُضيف شكلٌ مماثل من الاستيثاق إلى بروتوكول RIP في الإصدار 2)، وأُضيف استيثاق تشفير قوي لاحقًا. الهرمية الإضافية Additional hierarchy: تُعد الهرمية أحد الأدوات الأساسية المستخدمة لجعل الأنظمة أكثر قابلية للتوسُّع. يقدّم بروتوكول OSPF طبقةً أخرى من الهرمية في التوجيه من خلال السماح بتقسيم نطاقٍ domain إلى مناطق areas. هذا يعني أن الموجّه داخل النطاق لا يحتاج بالضرورة إلى معرفة كيفية الوصول إلى كل شبكة داخل هذا النطاق، فقد يكون قادرًا على الوصول من خلال معرفة كيفية الوصول إلى المنطقة الصحيحة فقط. وبالتالي هناك انخفاض في كمية المعلومات التي يجب نقلها وتخزينها في كل عقدة. موازنة الحمل Load balancing: يسمح بروتوكول OSPF بإسناد مساراتٍ متعددة إلى نفس المكان بنفس التكلفة، وسيؤدي إلى توزيع حركة مرور البيانات بالتساوي على تلك المسارات، وبالتالي الاستفادة بصورة أفضل من سعة الشبكة المتاحة. هناك عدة أنواع مختلفة من رسائل OSPF، ولكن جميعها تبدأ بالترويسة نفسها، كما هو موضح في الشكل السابق. يُضبَط الحقل Version حاليًا على القيمة 2، وقد يأخذ حقل النوع Type القيم من 1 إلى 5. يحدّد الحقل SourceAddr مُرسل الرسالة، والحقل AreaId هو معرّف مؤلفٌ من 32 بتًا للمنطقة التي تُوجد بها العقدة. الرزمة بأكملها، باستثناء بيانات الاستيثاق، محميةٌ بواسطة مجموع اختباري مؤلف من 16 بتًا باستخدام نفس الخوارزمية التي تستخدمها ترويسة IP. حقل نوع الاستيثاق Authentication type هو 0 في حال لم يُستخدَم أي استيثاق، وخلاف ذلك، قد يكون 1 مما يعني ضِمنًا استخدام كلمة مرور بسيطة، أو 2 مما يشير إلى استخدام المجموع الاختباري للاستيثاق المشفّر. ويحمل حقل الاستيثاق Authentication كلمة المرور أو المجموع الاختباري المشفَّر في الحالات الأخيرة. من بين أنواع رسائل OSPF الخمسة، النوع 1 هو الرسالة الترحيبية "hello"، التي يرسلها الموجّه إلى نظرائه لإعلامهم بأنه ما زال يعمل ومتّصِل. تُستخدم الأنواع المتبقية لطلب رسائل حالة الرابط وإرسالها والإشعار باستلامها. اللبنة الأساسية لرسائل حالة الرابط في بروتوكول OSPF هي إعلان حالة الرابط link-state advertisement أو اختصارًا LSA، فقد تحتوي رسالةٌ واحدة على العديد من إعلانات LSA. يجب أن يوفّر بروتوكول OSPF معلومات حول كيفية الوصول إلى الشبكات مثل بقية بروتوكولات التوجيه عبر شبكة متشابكة. وبالتالي يجب أن يوفر بروتوكول OSPF معلومات أكثر قليلًا من البروتوكول البسيط القائم على الرسم البياني. فقد يُنشئ الموجّه الذي يشغّل بروتوكول OSPF رزمَ حالة الرابط التي تعلن عن واحدة أو أكثر من الشبكات المتصلة مباشرة بهذا الموجه. يجب أيضًا أن يعلن الموجه المتصل بموجّهٍ آخر عن طريق رابطٍ عن تكلفة الوصول إلى هذا الموجه عبر هذا الرابط. هذان النوعان من الإعلانات ضروريان لتمكين جميع الموجّهات الموجودة في نطاقٍ ما من تحديد تكلفة الوصول إلى جميع الشبكات في هذا النطاق وتحديد موجّه القفزة التالية المناسبة لكل شبكة. يوضّح الشكل السابق صيغة رزمة إعلان حالة الرابط من النوع 1. تعلن إعلانات LSA من النوع 1 عن تكلفة الروابط بين الموجّهات. تُستخدَم إعلانات LSA من النوع 2 للإعلان عن الشبكات التي يتصل بها الموجّه المُعلِن، بينما تُستخدم الأنواع الأخرى لدعم الهرمية الإضافية وسيُشرح لاحقًا في الفصول القادمة. يجب أن تكون العديد من الحقول في إعلان LSA مألوفة من المناقشة السابقة. الحقل LS Age هو الحقل الذي يعادل حقل TTL، باستثناء أنه يكون متزايدًا وتنتهي صلاحية إعلان LSA عندما يصل العمر age إلى قيمة قصوى محددة. يخبرنا الحقل Type أن هذا هو النوع 1 من إعلانات LSA. يكون الحقل Link state ID والحقل Advertising router متطابقين في النوع 1 من إعلانات LSA. يحمل كل منهما معرّفًا مؤلفًا من 32 بت للموجّه الذي أنشأ إعلان LSA. يمكن استخدام عدد من استراتيجيات الإسناد لإسناد هذا المعرّف، فمن الضروري أن يكون فريدًا في نطاق التوجيه، وأن يستخدم موجّهٌ معينٌ نفس معرّف الموجّه باستمرار. تتمثل إحدى طرق اختيار معرّف الموجه الذي يُلبي هذه المتطلبات في اختيار أقل عنوان IP من بين جميع عناوين IP المُسنَدة لهذا الموجّه. (تذّكر أن الموجّه قد يكون له عنوان IP مختلف على كلّ واجهةٍ من واجهاته). يُستخدَم حقل LS sequence number لاكتشاف إعلانات LSA القديمة أو المكررة. الحقل LS checksum مشابه للحقول الأخرى التي رأيناها في البروتوكولات الأخرى، حيث يُستخدَم بالطبع للتحقق من عدم تلف البيانات. وهو يغطّي جميع الحقول في الرزمة باستثناء الحقل LS Age، لذلك ليس من الضروري إعادة حساب المجموع الاختباري في كل مرة يزداد فيها الحقل LS Age. الحقل Length هو طول إعلان LSA الكامل مقدرًا بالبايت. نصل الآن إلى معلومات حالة الرابط الفعلية. وقد أصبح هذا الأمر معقدًا بعض الشيء بسبب وجود معلومات نوع الخدمة type of service أو اختصارًا TOS. يُمثَّل كل رابط في LSA بواسطة الحقول Link ID، و Link Data، و metric، حيث يحدّد أول حقلين من هذه الحقول الرابط، وتتمثل الطريقة الشائعة للقيام بذلك في استخدام معرّف الموجّه الخاص بالموجه في الطرف البعيد من الرابط بعدّه كحقل Link ID ثم استخدام حقل Link Data لإزالة الغموض بين الروابط المتوازية المتعددة إن لزم الأمر. والحقل metric هو بالطبع تكلفة الرابط. ويخبرنا الحقل Type بشيء عن الرابط، على سبيل المثال إذا كان رابطًا من نقطة لنقطة. تسمح معلومات TOS لِبروتوكول OSPF باختيار مساراتٍ مختلفة لِرزم IP بناءً على القيمة الموجودة في حقل TOS الخاص بهذه الرزم. يمكن إسناد مقاييس مختلفة بناءً على قيمة TOS للبيانات بدلًا من إسناد مقياسٍ واحد لرابط. إذا كان لدينا رابط في شبكتنا وهو جيدٌ جدًا لحركة مرور البيانات الحساسة للتأخير على سبيل المثال، فيمكن إعطاء هذا الرابط مقياسًا منخفضًا لقيمة TOS التي تمثل تأخيرًا منخفضًا ومقياسًا عاليًا لكل شيء آخر. سيختار بروتوكول OSPF بعد ذلك أقصر مسار مختلفٍ لتلك الرزم التي ضُبِط حقل TOS الخاص بها على تلك القيمة. من الجدير بالذكر أنه في وقت كتابة النسخة الإنجليزية من هذا الكتاب لم تُنشَر هذه القدرة على نطاقٍ واسع بعد. المقاييس Metrics تفترض المناقشة السابقة أن تكاليف الرابط، أو المقاييس، معروفةٌ عند تنفيذ خوارزمية التوجيه. سنناقش في هذا القسم بعض طرق حساب تكاليف الرابط التي أثبتت فعاليتها عمليًا. أحد الأمثلة التي رأيناها بالفعل، والذي هو بسيطٌ للغاية، هو إسناد التكلفة 1 لجميع الروابط، وبالتالي سيكون المسار الأقل تكلفة هو المسار الذي يحتوي على أقل عدد من القفزات. لكن هذا النهج له عيوبٌ عديدة. أولًا، لا يُميّز بين الروابط على أساس وقت الاستجابة، وبالتالي فإن رابطًا فضائيًا ذو وقت استجابة قدره 250 ميلي ثانية يجده بروتوكولُ التوجيه جذابًا كرابطٍ أرضي بوقت استجابة قدره 1 ميلي ثانية. ثانيًا، لا يفرّق بين المسارات على أساس السعة، مما يجعل رابطًا بسرعة 1 ميجا بت في الثانية يبدو جيدًا كرابطٍ بسرعة 10 جيجابت في الثانية. أخيرًا، لا يميز بين الروابط بناءً على حِملها الحالي، مما يجعل من المستحيل التوجيه باستخدام الروابط المحمَّلة تحميلًا زائدًا. اتضح أن هذه المشكلة الأخيرة هي الأصعب لأنك تحاول التقاط خصائص الرابط المعقدة والديناميكية بتكلفة قياسية واحدة. كانت شبكة أربانت ARPANET مكانًا لاختبار عددٍ من الأساليب المختلفة لحساب تكلفة الرابط، وكانت أيضًا المكان الذي أظهر استقرارًا فائقًا لحالة الرابط على توجيه متجّه المسافة. حيث استخدمت الآلية الأصلية متجّه المسافة بينما استخدم الإصدار الأحدث حالة الرابط. تتعقّب المناقشة التالية تطور مقياس توجيه ARPANET. قام مقياس توجيه ARPANET الأصلي بقياس عدد الرزم التي وُضِعت في الرتل منتظرةً إرسالها على كل رابط، مما يعني أنه أُسند وزن تكلفةٍ أكبر للرابط الذي يحتوي على 10 رزم في الرتل التي تنتظر إرسالها، مقارنةً برابطٍ يحتوي على 5 رزم في رتل الإرسال. ولكن استخدام طول الرتل كمقياسٍ للتوجيه لم يعمل جيدًا، نظرًا لأن طول الرتل هو مقياسٌ مصطنعٌ للحِمل، فهو يحرك الرزم نحو أقصر رتل بدلًا من توجيهها نحو الوجهة، وذلك موقفٌ مألوفٌ جدًا لنا عندما نقفز من رتلٍ لآخر في محل البقالة. عانت آلية توجيه ARPANET الأصلية من حقيقة أنها لم تهتم بحيز نطاق الرابط التراسلي bandwidth أو وقت استجابته latency. اهتم الإصدار الثاني من خوارزمية توجيه ARPANET بكلٍ من حيز نطاق الرابط التراسلي ووقت الاستجابة واستخدم التأخير delay، بدلًا من طول الرتل، كمقياسٍ للحِمل. وتم ذلك على النحو التالي. أولًا، وُضعت علامةٌ زمنية لكل رزمة واردة بوقت وصولها إلى الموجّه ArrivalTime، وسُجِّل وقت مغادرته من الموجّه DepartTime أيضًا. ثانيًا، حَسبَت العقدةُ تأخيرَ Delay تلك الرزمة عند استلام الجانب الآخر إشعارًا ACK على مستوى الرابط كما يلي: Delay = (DepartTime - ArrivalTime) + TransmissionTime + Latency حيث عُرِّف وقت الإرسال TransmissionTime ووقت الاستجابةLatency تعريفًا ثابتًا للرابط وهما يلتقطان حيّز نطاق الرابط التراسلي ووقت استجابته على التوالي. لاحظ أنه في هذه الحالة، يمثّل ناتج DepartTime - ArrivalTime مقدار الوقت الذي تأخرت فيه الرزمة (وُضِعت في الرتل) في العقدة بسبب الحِمل. إذا لم يصل إشعار ACK، ولكن انتهت مهلة الرزمة بدلًا من ذلك، فسيُعاد ضبط وقت المغادرة DepartTime إلى وقت إعادة إرسال الحزمة. يلتقط DepartTime - ArrivalTime في هذه الحالة موثوقية الرابط، فكلما زاد تكرار إعادة إرسال الرزم، قلّت وثوقية الرابط، وكلما زادت رغبتنا في تجنُّبه. أخيرًا، اُشتقّ الوزن المُسنَد لكل رابط من متوسط التأخير الذي اختبرته الرزم المرسَلة مؤخرًا عبر هذا الرابط. واجه هذا النهج أيضًا الكثير من المشاكل على الرغم من التحسين على الآلية الأصلية. حيث عَمِل جيدًا في ظل الحِمل الخفيف، بما أن عاملي التأخير الثابتان سَيطَرَا على التكلفة. ولكن سيبدأ الرابط المزدحم في الإعلان عن تكلفة عالية جدًا في ظل الحِمل الثقيل. وقد يُسبب هذا في تحرُّك كل حركة مرور البيانات بعيدًا عن هذا الرابط، وتركه في وضع الخمول، ثم يُعلن عن تكلفة منخفضة، وبالتالي يجذب كل حركة مرور البيانات مرة أخرى إليه، وما إلى ذلك. يكمن تأثير عدم الاستقرار بأن العديد من الروابط ستقضي في الواقع وقتًا طويلًا في وضع الخمول في ظل الحمل الثقيل، وهو آخر شيء تريده. كانت هناك مشكلة أخرى وهي أن نطاق قيم الرابط كان كبيرًا جدًا، فقد يبدو الرابط المحمَّل كثيرًا بسرعة 9.6 كيلوبت في الثانية أكثر تكلفة بـ 127 مرة من الرابط المحمَّل بصورة خفيفة بسرعة 56 كيلوبت في الثانية. (ضع في بالك أننا نتحدث عن شبكة ARPANET حوالي عام 1975). وهذا يعني أن خوارزمية التوجيه ستختار مسارًا به 126 قفزة من الروابط التي تحمَّل بصورة خفيفة بسرعة 56 كيلوبت في الثانية بدلًا من مسار مؤلفٍ من 1 قفزة بسرعة 9.6 كيلو بت في الثانية. يُعَد التخلص من بعض حركة مرور البيانات من خط محمّل بصورة زائدة فكرةً جيدة، إلّا أنّ جعلهُ غير جذاب لدرجة أن يفقد كل حركة مروره أمرٌ متهوّر. ويُعَد استخدام 126 قفزة بدلًا من قفزة واحدة استخدامًا سيئًا لموارد الشبكة. عوقبت الروابط الفضائية بلا داعٍ أيضًا، بحيث بدا الرابط الفضائي الخامل بسرعة 56 كيلوبت في الثانية أكثر تكلفة بكثير من الرابط الأرضي الخامل بسرعة 9.6 كيلوبت في الثانية، على الرغم من أن الأول سيعطي أداءً أفضل للتطبيقات ذات حيز النطاق التراسلي العالي. تناول نهج ثالث هذه المشاكل. فتمثلت التغييرات الرئيسية في ضغط نطاق المقياس الديناميكي بصورة كبيرة لصالح نوع الرابط، وتقليل تباين المقياس مع مرور الوقت. يتحقق تقليل التباين هذا من خلال عدة آليات. أولًا، تحويل قياس التأخير إلى استخدامية رابط، وحساب متوسط هذا الرقم مع آخر استخداميةٍ مبلَّغٍ عنها لمنع التغييرات المفاجئة. ثانيًا، كان هناك حد صارم لِمدى تغير المقياس من دورة قياس إلى أخرى. تقل احتمالية أن تتخلى جميع العقد عن المسار مرة واحدة بصورة كبيرة من خلال تقليل التغييرات في التكلفة . تحقّقَ ضغط النطاق الديناميكي عن طريق تزوّيد الاستخدامية utilization المُقاسة، ونوع الرابط، وسرعة الرابط في عمليةٍ تظهر بيانيًا في الشكل التالي. لاحظ ما يلي: لا يُظهر الرابط المحمَّل كثيرًا أبدًا تكلفة تزيد عن ثلاثة أضعاف تكلفته عند الخمول. تكلفة الرابط الأغلى تساوي سبعة أضعاف تكلفة الرابط الأقل تكلفة. يُعَد الرابط الفضائي عالي السرعة أكثر جاذبية من الرابط الأرضي منخفض السرعة. التكلفة هي اختصاص استخدامية الرابط فقط عند الأحمال المتوسطة إلى العالية. تعني كل هذه العوامل أنه من غير المرجح أن يحدث تخلي عن الرابط بشكلٍ شامل، نظرًا لأنه يمكن أن تجعل الزيادة في التكلفة بمقدار ثلاثة أضعاف الرابطَ غير جذاب لبعض المسارات ولكنها تتركه بمثابة الخيار الأفضل للآخرين. وصلنا إلى المنحدرات slopes والإزاحات offsets ونقاط التوقف breakpoints الخاصة بالمنحنيات في الشكل السابق من خلال قدرٍ كبير من التجربة والخطأ، والضبط بعنايةٍ لتوفير أداءٍ جيد. اتضح أنه نادرًا ما تتغير المقاييس في غالبية عمليات نشر الشبكة في العالم الحقيقي، وإن وجدت تحدث فقط تحت سيطرة مسؤول الشبكة، وليس تلقائيًا. والسبب في ذلك جزئيًا هو أن الحكمة التقليدية السائدة ترى الآن أن المقاييس المتغيرة ديناميكيًا غير مستقرة للغاية، على الرغم من أن هذا ربما لا يكون صحيحًا. والأهم من ذلك، أن العديد من الشبكات اليوم تفتقر إلى التباين الكبير في سرعات الروابط وأوقات الاستجابة التي سادت في شبكات ARPANET. وبالتالي فإن المقاييس الثابتة هي القاعدة. أحد الأساليب الشائعة لتحديد المقاييس هو استخدام ثابتٍ مضروب في 1/link_bandwidth. ترجمة -وبتصرّف- للقسم Routing من فصل Internetworking من كتابComputer Networks: A Systems Approach. اقرأ أيضًا المقال التالي: تطبيق مبدلات وموجهات الشبكات الحاسوبية برمجيا وعتاديا المقال السابق: الشبكات الفرعية والعناوين والأخطاء في بروتوكول IP التوجيه Routing بين الأجهزة المتنقلة في الشبكات الحاسوبية
-
سنتحدث في هذا المقال عن كيفية إنشاء الشبكات الفرعية، وكيفية إضافة عناوين للحصول على مخطَّط بيانات لمضيف أو موجه معين على الشبكة الفيزيائية، كما سنتحدث عن كيفية تعامل الإنترنت مع الأخطاء، لنختتم بالحديث عن الشبكات الافتراضية أمام الأنفاق إنشاء الشبكات الفرعية Subnetting والعنونة عديمة التصنيف Classless Addressing كان الهدف الأساسي من عناوين IP هو تحديد جزء الشبكة بصورة فريدة، وتحديدًا شبكةً فيزيائيةً واحدةً بالضبط. ولكن اتضح أنّ هذا النهج له بعض العيوب. فتخيّل أنّ حرمًا جامعيًا كبيرًا به الكثير من الشبكات الداخلية قرّر الاتصال بالإنترنت. هنا سيحتاج موقع كلّ شبكة مهما كانت صغيرة، إلى عنوان شبكة من الصنف C. والأسوأ من ذلك هو حاجة أية شبكة بها أكثر من 255 مضيفًا إلى عنوان من الصنف B. قد لا يبدو هذا أمرًا بالغ الأهمية، ولكن في الواقع لم يكن الأمر كذلك عندما حدث تصوّر الإنترنت لأول مرّة، فهناك عدد محدود فقط من أرقام الشبكات، وعدد أقل بكثير من عناوين الصنف B مقارنة بعناوين الصنف C. حيث تميل عناوين الصنف B إلى أن تكون ذات طلب مرتفع خاصةً لأنك لا تعرف أبدًا إذا كانت شبكتك ستتوسع إلى أكثر من 255 عقدة، لذلك فمن الأسهل استخدام عناوين الفئة B من البداية بدلًا من الاضطرار إلى إعادة ترقيم كلّ مضيف عند نفاد مساحة شبكة من الصنف C. لكن المشكلة التي نلاحظها هنا هي عدم كفاءة إسناد Assigning العناوين، إذ تستخدم الشبكة ذات العقدتين عناوين شبكة من الفئة C بالكامل، وبالتالي تُهدِر 253 عنوانًا مفيدًا، كما تُهدِر أيضًا شبكةٌ من الصنف B -تضم أكثر بقليل من 255 مضيفًا- أكثرَ من 64000 عنوان. لذلك، إسناد رقم شبكة واحد لكلّ شبكة فيزيائية يستهلك حيز عناوين IP، حيث يُحتمل أنّ يكون هذا الاستهلاك أسرع بكثير مما نودّ. وسنحتاج إلى توصيل أكثر من 4 مليارات مضيف لاستخدام جميع العناوين الصالحة، كما سنحتاج فقط إلى توصيل 214 (حوالي 16000) شبكة من الصنف B قبل نفاد هذا الجزء من حيز العناوين، لذلك لابد إيجاد طريقة ما لاستخدام أرقام الشبكة بصورة أكثر كفاءة. يؤدّي إسناد Assigning العديد من أرقام الشبكة إلى عيبٍ آخر يتضّح عندما تفكِّر في التوجيه routing. تذكّر أنّ مقدار الحالة المخزَّنة في عقدةٍ مشاركة في بروتوكول التوجيه متناسبٌ مع عدد العقد الأخرى. وأنّ التوجيه في الإنترنت internet يتكون من بناء جداول التمرير التي تخبر الموجّه بكيفية الوصول إلى شبكات مختلفة. وبالتالي كلّما زاد عدد أرقام الشبكة المستخدَمة، زاد حجم جداول إعادة التوجيه forwarding tables. كما تزيد جداول التمرير الكبيرة التكاليف على الموجِّهات، ومن المحتمل بطؤها في البحث مقارنة مع الجداول الأصغر لتقنية معيّنة. لذا فهي تقلل من أداء الموجّه، ويوفر هذا دافعًا آخر لإسناد أرقام الشبكة بعناية. يوفّر إنشاء الشبكات الفرعية Subnetting الخطوة الأولى لتقليل العدد الإجمالي لأرقام الشبكة المسنَدة. تكمن الفكرة في أخذ رقم شبكة IP واحد وتخصيص عناوين IP مع رقم الشبكة هذا للعديد من الشبكات الفيزيائية، والتي يشار إليها الآن باسم الشبكات الفرعية subnets. هناك العديد من الأشياء الواجب القيام بها لإنجاح هذا العمل. إذ يجب أولًا أن تكون الشبكات الفرعية قريبةً من بعضها البعض، لأنها ستبدو جميعها مثل شبكة واحدة إذا نظرت إليها من نقطة بعيدة في الإنترنت. كما لا بد من وجود رقم شبكة واحد فقط بينها. وهذا يعني أن الموجّه سيكون قادرًا فقط على تحديد مسار واحد للوصول إلى أيٍّ من الشبكات الفرعية، لذلك فمن الأفضل أن تكون جميعها في نفس الاتجاه العام. يُعَدّ الوضع المثالي لاستخدام الشبكات الفرعية هو حرم جامعي كبير أو شركة لديها العديد من الشبكات الفيزيائية. فكلّ ما تحتاج معرفته للوصول من خارج الحرم الجامعي إلى أيّ شبكة فرعية داخله هو المكان الذي يتّصل فيه الحرم الجامعي ببقية الإنترنت. ويكون هذا المكان غالبًا في نقطة واحدة، لذا تكفي مدخلةٌ في جدول التمرير. إذ لا تزال معرفة كيفية الوصول إلى نقطة واحدة في شبكة الحرم الجامعي بدايةً جيدة، حتى لو كانت هناك نقاط متعددة تتصل بها شبكة الحرم الجامعي ببقية الإنترنت. تتضمّن الآلية التي يمكن من خلالها تشارُك رقمِ شبكة واحد بين شبكات متعدِّدة، ضبطَ جميع العقد في كلّ شبكة فرعية باستخدام قناع الشبكة الفرعية subnet mask. إذ يجب أن يكون لجميع المضيفين على نفس الشبكة رقم الشبكة نفسه باستخدام نفس تنسيق عناوين IP البسيط. ويتيح لنا قناع الشبكة الفرعية تقديم رقم شبكة فرعية، بحيث سيكون لجميع المضيفين على نفس الشبكة الفيزيائية نفس رقم الشبكة الفرعية، مما يعني أنّ المضيفين قد يكونوا على شبكات فيزيائية مختلفة لكنهم يشتركون برقم شبكة واحد. هذا المفهوم موضَّح في الشكل التالي: ضُبِط المضيف الآن باستخدام كلٍّ من عنوان IP وقناع الشبكة الفرعية المرفقة به. حيث ضُبِط المضيف H1 في الشكل الآتي مثلًا بعنوان 128.96.34.15 وقناع شبكة فرعية 255.255.255.128. تُضبَط جميع الأجهزة المضيفة على شبكةٍ فرعية معيَّنة بنفس القناع؛ أي يوجد قناع شبكة فرعية واحد لكلّ شبكة فرعية. وتحدّد العملية الثنائية AND لهذين الرقمين رقمَ الشبكة الفرعية للمضيف ولجميع الأجهزة المضيفة الأخرى على نفس الشبكة الفرعية. ويُعَدّ 128.96.34.15 AND 255.255.255.128 في هذه الحالة مساويًا ،128.96.34.0 وهذا هو رقم الشبكة الفرعية العلوية في الشكل التالي: أول شيء يفعله المضيف عند إرسال رزمة إلى عنوان IP معيّن هو إجراء العملية الثنائية AND بين قناع الشبكة الفرعية الخاصة به وعنوان IP الوجهة. فإذا كانت النتيجة مساويةً لرقم شبكة المضيف المرسَل الفرعية، فسيعرف أنّ المضيف الوجهة موجود على نفس الشبكة الفرعية، ويمكن تسليم الرزمة مباشرةً عبر الشبكة الفرعية. أما إذا كانت النتائج غير متساوية، فيجب إرسال الرزمة إلى موجّهٍ لتمريرها إلى شبكة فرعية أخرى. لو أرسل المضيف H1 إلى H2 مثلًا، سيطبّق المضيف H1 عملية AND على قناع شبكته الفرعية (255.255.255.128) مع عنوان المضيف H2 وهو (128.96.34.139) فينتج العنوان 128.96.34.128. لا تتطابق هذه النتيجة مع رقم شبكة المضيف H1 الفرعية (128.96.34.0)، لذلك يعرف المضيف H1 أنّ المضيف H2 موجود على شبكة فرعية مختلفة. فيرسل المضيف H1 الرزمة إلى الموجّه الافتراضي الخاص به R1، نظرًا لعدم قدرة المضيف H1 على تسليم الرزمة إلى المضيف H2 مباشرةً عبر الشبكة الفرعية. يتغير جدول التمرير الخاص بالموجّه أيضًا بصورة طفيفة عند استخدام الشبكات الفرعية. تذكّر أنه كان لدينا سابقًا جدول تمرير مكوَّنٌ من مدخلات من النموذج NetworkNum ، NextHop. ويجب أن يحتوي الآن على مدخلات من النموذج SubnetNumber ، SubnetMask ، NextHop لدعم الشبكات الفرعية. كما يطبّق الموجّه عملية AND على عنوان وجهة الرزمة مع قناع الشبكة الفرعية SubnetMask لكل مدخَلةٍ للعثور على المدخَلة الصحيحة في الجدول. فإذا تطابقت النتيجة مع رقم الشبكة الفرعية SubnetNumber للمدخَلة فهذه هي المدخلة الصحيحة التي يجب استخدامها، ويمرر الرزمة إلى موجّه القفزة التالي المشار إليه. كما سيكون للموجّه R1 في مثال الشبكة ضمن الشكل السابق المدخلات الموضّحة في الجدول التالي: 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; } رقم الشبكة الفرعية SubnetNumber قناع الشبكة الفرعية SubnetMask العقدة التالية NextHop 128.96.34.0 255.255.255.128 Interface 0 128.96.34.128 255.255.255.128 Interface 1 128.96.33.0 255.255.255.0 R2 نستمر في مثال مخطَط البيانات المرسَل من المضيف H1 إلى المضيف H2، حيث سيجري الموجّه R1 عملية AND على عنوان المضيف H2 الذي هو (128.96.34.139) مع قناع الشبكة الفرعية للمدخَلة الأولى (255.255.255.128)، ويوازن النتيجة (128.96.34.128) مع رقم شبكة هذه المدخلة (128.96.34.0). وبما أنهما ليسا متطابقين، فسينتقل إلى المدخَلة التالية، إلى أن تحدث المطابقة. لذا يسلّم الموجه R1 مخطط البيانات إلى المضيف H2 باستخدام الواجهة 1، وهي الواجهة المتصلة بنفس شبكة المضيف H2. يمكن الآن وصف خوارزمية إعادة توجيه مخطَّط البيانات بالطريقة التالية: D = الوجهة IP عنوان for each forwarding table entry (SubnetNumber, SubnetMask, NextHop) D1 = SubnetMask & D if D1 = SubnetNumber if NextHop is an interface (واجهة) سلّم مخطط البيانات مباشرةً إلى الوجهة else سلّم مخطط البيانات إلى العقدة التوجيهية التالية أو إلى الموجّه يُضمَّن عادةً مسار التوجيه الافتراضي default route في الجدول على الرغم من عدم ظهوره في هذا المثال، ويمكن استخدامه إذا لم يُعثَر على مطابقات صريحة. لاحظ أنّ تطبيقًا ساذجًا لهذه الخوارزمية سيكون غير فعال نهائيًا، وهو تطبيق يتضمّن عملية AND متكرِّرة على عنوان الوجهة، مع قناع شبكة فرعية وقد لا تكون هذه العملية مختلفةً في كلّ مرّة، إلى جانب البحث الخطي في الجدول. أحد النتائج المهمة للشبكات الفرعية هي رؤية أجزاء مختلفة من الإنترنت للعالم بطريقة مختلفة. فترى الموجّهاتُ الشبكةَ شبكةً واحدةً عندما تكون خارجها. كما ترى الموجّهات الموجودة خارج الحرم الجامعي مجموعة الشبكات في الشكل السابق على أنها مجرّد شبكة 128.96، وتحتفظ بمدخَلة واحدة في جداول التمرير الخاصة بها لإخبارها بكيفية الوصول إليها. ولكن يجب أن تكون الموجِّهات الموجودة داخل الحرم الجامعي قادرةً على توجيه الرزم إلى الشبكة الفرعية الصحيحة. وبالتالي لا ترى جميع أجزاء الإنترنت نفس معلومات التوجيه بالضبط، وهذا مثالٌ عن تجميع aggregation معلومات التوجيه، وهو أمر أساسي لتوسيع نطاق نظام التوجيه. يوضّح القسم التالي كيف يمكن نقل التجميع إلى مستوٍ آخر. العنونة عديمة التصنيف Classless Addressing للشبكات الفرعية نظير، يُطلق عليه أحيانًا اسم إعداد مجموعة شبكات فرعية متجاورة supernetting، ولكن غالبًا ما يُطلق عليه التوجيه عديم التصنيف بين النطاقات Classless Interdomain Routing أو اختصارًا CIDR، وتُلفَظ "cider". يأخذ نظام CIDR فكرة الشبكات الفرعية إلى نهايتها المنطقية من خلال التخلص بشكل أساسي من أصناف العناوين. لماذا لا تكفي الشبكات الفرعية subnetting وحدها؟ تسمح الشبكات الفرعية فقط بتقسيم العنوان ذي الصنف إلى شبكات فرعية متعدِّدة، بينما يسمح نظام CIDR بدمج العديد من العناوين ذات الصنف في مجموعة شبكات فرعية متجاورة supernet واحدة. كما يعالج أيضًا عدم كفاءة حيز العناوين، ويعمل بطريقة تحافظ على نظام التوجيه من التحميل الزائد overloaded. افترض حالة الشركة الافتراضية التي تحتوي شبكتها على 256 مضيفًا، لمعرفة كيفية اقتران قضايا كفاءة حيّز العناوين مع قابلية توسّع نظام التوجيه. يُعَدّ الصنف C خيارًا غير مناسب بالنسبة للعدد المطلوب تغطيته من المضيفين، لذلك فقد تميل إلى استخدام الصنف B. ولكن استخدام قطعةٍ من حيز عناوينٍ قد يستخدم 65535 عنوان لعنوَنة 256 مضيفًا له كفاءة 256 / 65,535 = 0.39% فقط. وبالرغم من إمكانية مساعدة الشبكات الفرعية على إسناد العناوين بعناية، إلا أنها لا تتغلّب على حقيقة رغبة أية مؤسَّسة لديها أكثر من 255 مضيفًا أو توقعًا بوجود هذا العدد الكبير، بعناوين من الفئة B. الطريقة الأولى التي قد تتعامل بها مع هذه المشكلة هي رفض إعطاء عنوان من الصنف B لأيّ مؤسسة تطلب ذلك ما لم يكن بإمكانها إظهار الحاجة إلى شيء قريب من 64 ألف عنوان، ومنحها بدلًا من ذلك عددًا مناسبًا من عناوين الصنف C لتغطية العدد المتوقَّع من المضيفين. إذ يمكن بصورةٍ أدق مطابقة مقدار حيّز العناوين المستهلكة مع حجم المؤسسة نظرًا لتوزيعنا لها الآن في قطعٍ chunks مؤلَّفة من 256 عنوانًا في المرّة الواحدة. ويمكن ضمان استخدامية عناوين بنسبة 50% على الأقل بالنسبة لأية مؤسسة بها 256 مضيفًا على الأقل، وعادةً أكثر من ذلك بكثير. وللأسف حتى وإن استطاعت الشركة تبرير استخدامها لعناوين من الصنف B، لن يُنظر لهذا الطلب كون عناوين الصنف B محجوزة منذ فترة طويلة. لكنّ هذا الحلّ يثير مشكلةً خطيرة ألا وهي متطلبات التخزين الزائدة في الموجّهات. إذا كان هناك موقع واحد يحتوي على سبيل المثال على 16 رقم شبكة من الصنف C مُسندةً إليه، فهذا يعني أنّ كلّ موجّه إنترنت أساسي سيحتاج إلى 16 مدخلة في جداول التوجيه الخاصة به لتوجيه الرزم إلى هذا الموقع، حتى لو كان المسار إلى كلّ واحدة من هذه الشبكات هو نفسه. وإذا أُسندت عناوينًا من الصنف B للموقع، يمكن تخزين معلومات التوجيه نفسها في مدخَلة جدول واحدة، ولكن ستكون كفاءة إسناد العناوين فقط 16 × 255 / 65.536 = 6.2%. لذلك يحاول نظام CIDR موازنة الرغبة في تقليل عدد المسارات التي يحتاج الموجّه إلى معرفتها مقابل الحاجة إلى توزيع العناوين بكفاءة. وللقيام بذلك، يساعدنا نظام CIDR في تجميع المسارات aggregate routes. حيث يُتيح لنا استخدام مدخَلةٍ في جدول التمرير تُخبرنا بكيفية الوصول إلى الكثير من الشبكات المختلفة، ويُتمّ ذلك عن طريق كسر الحدود الصارمة بين أصناف العناوين. بفرض لدينا مؤسَّسة مكوّنة من 16 رقم شبكة من الصنف C، حيث يمكن توزيع مجموعة من عناوين الصنف C المتجاورة contiguous بدلًا من توزيع 16 عنوانًا عشوائيًا. وعلى فرض تم إسناد أرقام شبكة من الصنف C من 192.4.16 إلى 192.4.31. نلاحظ أنّ أعلى 20 بت لجميع العناوين في هذا النطاق هي نفسها (11000000 00000100 0001). وبالتالي فما أُنشئ بفعالية هو رقم شبكة مكوَّن من 20 بت، وهو شيء يقع بين رقم شبكة من الصنف B ورقم من الصنف C من حيث عدد الأجهزة المضيفة التي يمكنه دعمها. بمعنى ستحصل على كفاءة عنوَنة مرتفعة من خلال توزيع العناوين في قطعٍ أصغر من شبكةٍ من الصنف B، باستخدام بادئة prefix لشبكة واحدة يمكن استخدامها في جداول التمرير. لاحظ أنه لكي يعمل هذا المخطط، ستحتاج إلى توزيع كتلٍ blocks من عناوين الصنف C التي تشترك ببادئة مشتركة، مما يعني أنّ كلّ كتلة يجب أن تحتوي على عددٍ من شبكات الصنف C التي تكون من قوة العدد اثنين. يتطلب نظام CIDR نوعًا جديدًا من الترميز لتمثيل أرقام الشبكة أو البادئات كما هي معروفة، لأنّ البادئات قد تكون بأيّ طول. والاصطلاح هو وضع / X بعد البادئة، حيث X هو طول البادئة بالبِتَات. لذلك يمكن تمثيل بادئة مؤلَّفة من 20 بتًا لجميع الشبكات من 192.4.16 إلى 192.4.31 على أنّها 192.4.16/20. أمّا إذا أردت تمثيل رقم شبكة واحد من الصنف C، يبلغ طوله 24 بتًا، فستكتبه .192.4.16/24 ستسمع الناس اليوم غالبًا يتحدثون عن بادئات "slash 24" أكثر من استخدام شبكات الصنف C، على الرغم من كون نظام CIDR هو المعيار الأساسي. ويمكن ملاحظة أنّ تمثيل عنوان الشبكة بهذه الطريقة مشابه لطريقة mask, value المُستخدمة في الشبكات الفرعية، طالما أنّ masks تتكوّن من بتات متجاورة تبدأ من البِت الأعلى أهميةً (وهو ما يحدث دائمًا في الواقع تقريبًا). لا تُعَدّ القدرة على تجميع المسارات على حافة الشبكة كما رأينا للتو سوى الخطوة الأولى. فتخيّل شبكة مزوّد خدمة الإنترنت، والتي تتمثّل وظيفتها الأساسية في توفير الاتصال بالإنترنت لعدد كبير من الشركات وشبكات الحرم الجامعي (أو العملاء)، أنها خصّصت بادئات للعملاء بطريقة تشترك فيها العديد من شبكات العملاء المختلفة المتصلة بشبكة المزود ببادئة عنوان مشتركة وأقصر، عندئذٍ يمكن الحصول على تجميع مسارات أكبر. لنأخذ المثال الوارد في الشكل السابق، مع افتراض أنّ ثمانية عملاء يخدّمهم مزوِّد الشبكة، وقد أُسنِدت بادئات شبكة 24 بت لكلٍّ منهم. حيث تبدأ كلٌّ من هذه البادئات بنفس 21 بت، كما يعلن مزوّد الشبكة عن مسار واحد لجميع العملاء الذين يمكن الوصول إليهم من خلال نفس مزوّد الشبكة عن طريق الإعلان فقط عن بادئة 21 بت التي يتشاركونها. ويمكنه القيام بذلك حتى لو لم تُسلََّم جميع البادئات ذات 24 بت، طالما أنّ المزوِّد في النهاية سيكون له الحق في تسليم تلك البادئات إلى العميل. تتمثل إحدى طرق تحقيق ذلك في إسناد جزء من حيِّز عنونة المزوِّد مسبقًا ثم السماح لمزوِِّد الشبكة بإسناد عناوين من ذلك الحيز لعملائه حسب الحاجة. ويمكن ملاحظة أنه على عكس هذا المثال البسيط، ليست هناك حاجة لأن تكون جميع بادئات العملاء بنفس الطول. إعادة النظر في تمرير IP افترضنا في كامل مناقشتنا لتمرير IP حتى الآن، قدرتنا على العثور على رقم الشبكة في الرزمة، ثم البحث عن هذا الرقم في جدول التمرير. ولكن نحتاج إلى إعادة فحص هذا الافتراض بعد تقديمنا لنظام CIDR. إذ يعني نظام CIDR أنّ البادئات قد تكون بأيّ طول من 2 إلى 32 بت. كما يمكن في بعض الأحيان علاوةً على ذلك، وجود تداخل overlap بين البادئات في جدول التمرير. أي أنّ بعض العناوين قد تتطابق مع أكثر من بادئة واحدة، فقد نجد مثلًا كلًا من البادِئَتين 171.69 (بادئة ذات 16 بت) و171.69.10 (بادئة ذات 24 بت) في جدول التمرير الخاص بموجّه واحد. حيث تتطابق في هذه الحالة الرزمة المخصصة للعنوان 171.69.10.5 على سبيل المثال، بوضوحٍ مع البادِئَتين. وتستند القاعدة في هذه الحالة على مبدأ أطول تطابُق longest match، أي أنّ الرزمة تطابِق البادئة الأطول، والتي ستكون 171.69.10 في هذا المثال. من ناحية أخرى، فالرزمة المخصَّصة للعنوان 171.69.20.5 ستطابِق البادئة 171.69 ولن تطابق البادئة 171.69.10، حيث ستكون البادئة 171.69 هي أطول تطابق في حالة عدم وجود أيّ مدخلة مطابقة أخرى في جدول التوجيه. كانت مهمة العثور على أطول تطابق بكفاءة بين عناوين IP والبادئات متغيّرة الطول في جدول التمرير مجالًا مثمرًا للبحث لسنوات عديدة، إذ تَستخدم الخوارزمية الأكثر شهرة أسلوبًا يُعرف باسم شجرة PATRICIA، والذي طُوِّر بالفعل قبل نظام CIDR. ترجمة العناوين باستخدام بروتوكول ARP تحدثنا في القسم السابق عن كيفية الحصول على مخططات بيانات IP على الشبكة الفيزيائية الصحيحة، لكن تغاضينا عن مسألة كيفية الحصول على مخطَّط بيانات لمضيفٍ أو موجّهٍ معيّن على تلك الشبكة. حيث تكمن المشكلة الرئيسية في احتواء مخططات بيانات IP على عناوين IP، ولكن لا يفهم عتاد الواجهة الفيزيائية الموجودة على المضيف أو الموجّه الذي تريد إرسال مخطط البيانات إليه سوى مخططَ عنوَنة تلك الشبكة المعيّنة. وبالتالي نحتاج إلى ترجمة عنوان IP إلى عنوان على مستوى الرابط، بحيث يكون مفهومًا على هذه الشبكة (عنوان إيثرنت المؤلَّف من 48 بتًا على سبيل المثال). ليُمكن بعد ذلك تغليف مخطّط بيانات IP داخل إطار يحتوي على عنوان مستوى الرابط هذا وإرساله إمّا إلى الوجهة النهائية أو إلى موجّه يَعِد بتمرير مخطط البيانات إلى الوجهة النهائية. تتمثل إحدى الطرق البسيطة لربط عنوان IP مع عنوان شبكة فيزيائي في تشفير عنوان المضيف الفيزيائي في جزء المضيف من عنوان IP الخاصّ به. فقد يُمنَح مضيفٌ بعنوان فيزيائي 00100001 01001001 (الذي يحتوي على القيمة العشرية 33 في البايت العلوي و81 في البايت السفلي)، على أنّ عنوان IP هو 128.96.33.81. يُستخدَم هذا الحلّ في بعض الشبكات، غير أنّه محدود لأنّ عناوين الشبكة الفيزيائية لا يمكن أن تزيد عن 16 بتًا في هذا المثال، ويبلغ طولها 8 بتات فقط على شبكة من الصنف C. ومن الواضح أنّ هذا لن يعمل مع عناوين إيثرنت ذات 48 بتًا. الحلّ الأعمّ هو احتفاظ كلّ مضيف بجدولٍ مؤلَّفٍ من أزواج عناوين، أي أنّ الجدول سيربط عناوين IP مع عناوين فيزيائية. كما قد يدير مسؤول النظام هذا الجدول مركزيًا ثمّ ينسخه إلى كلّ مضيف على الشبكة، إلا أنّ الأسلوب الأفضل هو تعلُّم كلّ مضيف محتويات الجدول ديناميكيًا باستخدام الشبكة. ويمكن تحقيق ذلك باستخدام بروتوكول تحليل العناوين Address Resolution Protocol أو اختصارًا ARP. فالهدف من بروتوكول ARP هو تمكين كلّ مضيف على الشبكة من إنشاء جدول روابط mappings بين عناوين IP وعناوين مستوى الرابط. وبما أنّ هذه الروابط mappings قد تتغير بمرور الوقت (لأن بطاقة إيثرنت في مضيف قد تنكسر وتُستبدَل ببطاقةٍ جديدة بعنوان جديد على سبيل المثال)، فتُعطَى المدخلات مهلةً دوريًا ثم تُزال. ويحدث هذا كلّ 15 دقيقة، بحيث تُعرَف مجموعة الروابط المُخزَّنة حاليًا في مضيف باسم ذاكرة ARP المخبئية cache أو جدول ARP. يستفيد بروتوكول ARP من حقيقة دعم العديد من تقنيات الشبكة على مستوى الرابط مثل تقنية إيثرنت، للبثّ الإذاعي (broadcast. فإذا أراد المضيف إرسال مخطَّط بيانات IP إلى مضيفٍ (أو موجّه) يعرف وجوده على نفس الشبكة (أي أنّ عُقَد الإرسال والاستقبال لهما نفس رقم شبكة IP، فسيتحقق أولًا من الربط mapping في الذاكرة المخبئية. وإن لم يعثر على ذلك الربط، فسيحتاج المضيف إلى استدعاء بروتوكول ARP عبر الشبكة. وذلك عن طريق بث استعلام ARP إذاعي على الشبكة. يحتوي هذا الاستعلام على عنوان IP المَعنيّ (أي عنوان IP الهدف). حيث يتلقّى كل مضيف هذا الاستعلام، ويتحقق منه لمعرفة إذا كان مطابقًا لعنوان IP الخاص به. إذا حدث تطابق، فسيرسِل المضيف رسالة استجابة تحتوي على عنوان طبقة الربط الخاصة به مرةً أخرى إلى مُنشئ الاستعلام. كما يضيف منشئ الاستعلام المعلوماتِ الواردة في هذه الاستجابة إلى جدول ARP الخاص به. تتضمّن رسالة الاستعلام أيضًا عنوان IP وعنوان طبقة الربط للمضيف المرسِل. وبالتالي يمكن لكلّ مضيف على الشبكة معرِفة مستوى رابط المرسِل وعناوين IP الخاصة به ووضع هذه المعلومات في جدول ARP الخاص به عندما يبث مضيفٌ رسالة استعلام إذاعيًا، ولكن لا يضيف كلّ مضيفٍ هذه المعلومات إلى جدول ARP الخاص به. فإذا كان لدى المضيف مدخَلة لهذا المضيف في جدوله مسبقًا، فسيحدّث refreshes هذه المدخَلة، بمعنى سيعيد ضبط طول الوقت إلى حين تجاهل هذه المدخلة. وإذا كان هذا المضيف هو الهدف من هذا الاستعلام، فسيُضيف معلومات حول المرسِل إلى جدولِه، حتى لو لم يكن لديه بالفعل مدخَلة لهذا المضيف، وهذا بسبب وجود فرصة جيدة بأن يكون المضيف المصدر على وشك إرسال رسالة على مستوى التطبيق، كما قد يتعيّن عليه في النهاية إرسال استجابة أو إشعار ACK الى المصدر. بمعنى أنه بحاجة إلى عنوان المصدر الفيزيائي للقيام بذلك. وإذا لم يكن المضيف هو الهدف ولم يكن لديه بالفعل مدخَلة للمصدر في جدول بروتوكول ARP الخاص به، فلن يضيف مدخَلةً الى المصدر لعدم وجود سبب للاعتقاد بحاجة هذا المضيف في أيّ وقت إلى عنوان مستوى الرابط الخاص بالمصدر، إذ ليست هناك حاجة إلى ازدحام جدول بروتوكول ARP بهذه المعلومات. يوضِّح الشكل السابق صيغة رزمة ARP لروابط mappings عناوين IP وعناوين إيثرنت. ويمكن استخدام بروتوكول ARP مع عدة أنواع أخرى من الروابط mappings، حيث أنّ الاختلافات الرئيسية هي في أحجام العناوين. تحتوي الرزمة بالإضافة إلى عنوان IP وعنوان طبقة الربط لكلٍّ من المرسل والهدف على ما يلي: حقل HardwareType الذي يحدِّد نوع الشبكة الفيزيائية (مثل شبكة إيثرنت). حقل ProtocolType الذي يحدِّد بروتوكول الطبقة العليا (مثل بروتوكول IP). حقل HLen (طول عنوان العتاد hardware address length) وحقل PLen (طول عنوان البروتوكول protocol address length) اللذان يحدِّدان طول عنوان طبقة الربط وعنوان بروتوكول الطبقة الأعلى على التوالي. حقل Operation الذي يحدِّد ما إذا كان هذا طلبًا أم استجابة. عنوان عتاد المصدر والهدف (إيثرنت مثلًا) وعنوان البروتوكول (IP مثلًا). لاحظ إمكانية إضافة نتائج عملية ARP كعمود إضافي في جدول التمرير كما هو موضح بالجدول السابق. وبذلك لا يكتشف الموجّه R2 أنّ العقدة التوجيهية التالية هي الموجّه R1 فقط عندما يحتاج لتمرير رزمة إلى الشبكة 2 مثلًا، ولكنه يجد أيضًا عنوان MAC لوضعه على الرزمة لإرساله إلى الموجّه R1. ضبط المضيف Host Configuration باستخدام بروتوكول DHCP تضبط الشركةُ المصنّعة عناوين إيثرنت في محوّل adaptor الشبكة، وتُدار هذه العملية بطريقة تضمن تفرُّد هذه العناوين عالميًا. ومن الواضح أنّ هذا يُعَدّ شرطًا كافيًا لضمان أنّ أيّ مجموعة من الأجهزة المضيفة المتصِّلة بشبكة إيثرنت واحدة (بما في ذلك شبكة محلية ممتدة) سيكون لها عناوين فريدة. فكلّ ما نطلبه من عناوين إيثرنت هو التفرُّد uniqueness، ومع ذلك فلا يجب أن تكون عناوين IP فريدةً على شبكة متشابكة فحسب، بل لابدّ من عكسها أيضًا لمعمارية هذه الشبكة. تحتوي عناوين IP على جزء الشبكة وجزء المضيف، ويجب أن يكون جزء الشبكة هو نفسه لجميع المضيفين على الشبكة نفسها. وبالتالي لا يمكن ضبط عنوان IP لمرّةٍ واحدة في مضيف عند تصنيعه، لأنّ ذلك يعني إعلام الشركة المصنّعة للشبكات التي سيتواجد فيها هؤلاء المضيفون. وهذا يعني عدم قدرة المضيف على الانتقال إلى شبكة أخرى بمجرّد اتصاله بشبكة معيّنة، ولذلك يجب أن تكون عناوين IP قابلةً لإعادة الضبط reconfigurable. هناك بعض المعلومات الأخرى التي يحتاجها المضيف قبل تمكّنه من بدء إرسال الرزم إلى جانب عنوان IP. وأبرزها هي عنوان الموجّه الافتراضي، وهو المكان الذي قد يرسل المضيف إليه الرزم التي لا يكون عنوان وجهتها على نفس شبكة المضيف المرسل. توفِّر معظم أنظمة تشغيل المضيف طريقةً لمسؤول النظام أو حتى لمستخدم النظام، لضبط configure معلومات IP التي يحتاجها المضيف يدويًا. ولكن هناك بعض العيوب الواضحة لمثل هذا الضبط اليدوي، وأحدها هو حاجته ببساطة للكثير من العمل لضبط جميع المضيفين في شبكة كبيرة، خاصةً عندما تفكّر في أنّ مثل هذه الأجهزة المضيفة لا يمكن الوصول إليها عبر الشبكة إلى حين ضبطها. والأهم من ذلك هو أنّ عملية الضبط معرضةٌ جدًا للخطأ، إذ من الضروري التأكد من حصول كلّ مضيف على رقم الشبكة الصحيح وعدم تلقّي أيّ مضيفَين لنفس عنوان IP. ولذلك يجب استخدام طرق الضبط الآلي automated configuration. تستخدم الطريقة الأساسية بروتوكولًا يُعرف باسم بروتوكول ضبط المضيف ديناميكيًا Dynamic Host Configuration Protocol أو اختصارًا DHCP. يعتمد بروتوكول DHCP على وجود خادم DHCP مسؤول عن توفير معلومات ضبط المضيفين. حيث يوجد خادم DHCP واحد على الأقل لكل نطاقٍ إداري administrative domain. ويمكن لخادم DHCP أن يعمل بأبسط مستوى كمستودعٍ مركزي لمعلومات ضبط المضيف. افترض مثلًا وجود مشكلة إدارة العناوين في الشبكة المتشابكة لشركة كبيرة. حيث يحمي بروتوكول DHCP مسؤولي الشبكة من الاضطرار للتجول إلى كلّ مضيفٍ في الشركة حاملين معهم قائمةً بالعناوين وخريطة الشبكة لضبط كلّ مضيفٍ يدويًا. وبدلًا من ذلك يمكن تخزين معلومات ضبط كلّ مضيف في خادم DHCP واستردادها تلقائيًا بواسطة كلّ مضيف عند تشغيله أو توصيله بالشبكة. ولكن سيبقى على مسؤول الشبكة اختيار العنوان الذي سيتلقّاه كلّ مضيف، حيث سيخزّن ذلك في الخادم فقط. وتُخزَّن معلومات ضبط كلّ مضيف في هذا النموذج ضمن جدولٍ مفهرسٍ بشكل من أشكال معرّف العميل الفريد، والذي عادةً ما يكون عنوان العتاد (عنوان الإيثرنت لمحوّل الشبكة الخاص به مثلًا). يحمي الاستخدام الأعقد لبروتوكول DHCP مسؤول الشبكة حتى من الاضطرار إلى إسناد عناوين لكلّ مضيفٍ. حيث يحتفظ خادم DHCP في هذا النموذج بتجمُّعٍ pool من العناوين المتاحة التي يوزِّعها على المضيفين عند الطلب. وهذا يقلٍّل بصورة كبيرة من مقدار الضبط الواجب على مسؤول الشبكة القيام به. فمن الضروري الآن تخصيص نطاق من عناوين IP (جميعها بنفس رقم الشبكة) لكلّ شبكة. كما يُفضَّل إلغاء الغرض الأساسي من بروتوكول DHCP الذي هو تقليل لمقدار الضبط اليدوي المطلوب ليعمل المضيف، إذا توجب ضبط كلّ مضيف بعنوان خادم DHCP. وبالتالي فالمشكلة الأولى التي يواجهها بروتوكول DHCP هي اكتشاف الخادم. يرسِل مضيفٌ مُشغَّلٌ أو متصلٌ حديثًا بالشبكة رسالةً DHCPDISCOVER إلى عنوان IP خاص (255.255.255.255)، وهو عنوان بث IP الإذاعي للاتصال بخادم DHCP. وهذا يعني استلام هذه الرسالة من قبل المضيفين والموجّهات على تلك الشبكة، ولا تعيد الموجّهات تمرير مثل هذه الرزم إلى شبكات أخرى، وهو ما يمنع البث الإذاعي إلى كامل شبكة الإنترنت. تكون إحدى هذه العقد هي خادم DHCP للشبكة في أبسط الحالات. وبالتالي سيجيب الخادم على المضيف الذي أنشأ رسالة الاكتشاف discovery message، لتَتجاهل جميع العٌقد الأخرى هذه الرسالة. لكن من غير المستحسن طلب خادم DHCP واحد على كلّ شبكة، لأنّ هذا مازال يؤدّي إلى إنشاء عدد كبير من الخوادم الواجب ضبطها بصورة صحيحة ومستقرّة. وبالتالي يستخدم بروتوكول DHCP مفهوم وكيل النقل relay agent. حيث يوجد وكيل نقلٍ واحد على الأقل في كل شبكة، ويُضبَط باستخدام معلومة واحدة فقط هي عنوان IP لخادم DHCP. وإذا تلقّى وكيل النقل رسالة DHCPDISCOVER، فسيُرسلها إلى خادم DHCP وينتظر الاستجابة، ثم يرسلها مرةً أخرى إلى العميل الطالب. يوضح الشكل التالي عملية نقل رسالة من مضيف إلى خادم DHCP بعيد: يوضِّح الشكل الآتي صيغة رسالة DHCP. حيث تُرسَل الرسالة فعليًّا باستخدام بروتوكول يسمّى بروتوكول مخطط بيانات المستخدِم User Datagram Protocol أو اختصارًا UDP، والذي يعمل عبر بروتوكول IP. سنشرح بروتوكول UDP بالتفصيل لاحقًا. ولكن الشيء الوحيد المثير للاهتمام في هذا السياق هو توفير مفتاح فكّ الإرسال المتعدد الذي يقول "هذه رزمة DHCP". إن بروتوكول DHCP مشتقٌ من بروتوكولٍ سابق يسمى BOOTP. وبالتالي فبعض حقول الرزم ليست ذات صلة وثيقة بضبط المضيف. حيث يضع العميل عنوان العتاد (عنوان الإيثرنت الخاص به على سبيل المثال) في حقل chaddr عند محاولة الحصول على معلومات الضبط. ليجيب خادم DHCP عن طريق ملء حقل yiaddr -أي عنوان IP الخاص بك your IP address-، وإرساله إلى العميل. ويمكن تضمين معلوماتٍ أخرى مثل الموجه الافتراضي الذي سيستخدمه هذا العميل في حقل الخيارات options. من الواضح عدم قدرة المضيفين على الاحتفاظ بالعناوين إلى أجلٍ غير مسمى عندما يسند بروتوكول DHCP عناوين IP ديناميكيًا للمضيفين. إذ سيؤدّي هذا في النهاية إلى نفاذ تجمّع العناوين الخاص بالخادم. لذلك لا يمكن الاعتماد على مضيفٍ لإعادة عنوانه، لأنه قد يكون معطّلًا، أو مفصولًا عن الشبكة، أو قد توقّف تشغيله. بالتالي يسمح بروتوكول DHCP بتأجير العناوين لبعض الوقت، حيث يكون الخادم حرًا في إعادة هذا العنوان إلى مجموعة العناوين الخاصة به بمجرّد انتهاء وقت التأجير. ومن الواضح أنّ المضيف الذي يحمل عنوانًا مؤجّرًا، سيَحتاج إلى تجديد الإيجار دوريًا إذا كان لا يزال متصلًا بالشبكة ويعمل بصورة صحيحة. نلاحظ أن بروتوكول DHCP قد يُدخِل أيضًا بعض التعقيد إلى إدارة الشبكة، لأنّه يجعل الربط بين المضيفين الفيزيائيين وعناوين IP أكثر ديناميكيةً. وهذا قد يجعل مهمّة مدير الشبكة أصعب إذا أصبح من الضروري تحديد موقع مضيف به خلل مثلًا. الإبلاغ عن خطأ Error Reporting باستخدام بروتوكول ICMP المشكلة التالية هي كيفية تعامل الإنترنت مع الأخطاء. يكون بروتوكول IP مستعدًا تمامًا لإهمال مخطَّطات البيانات عندما تصبح الأمور صعبة، وحين لا يعرف الموجّه كيفية تمرير مخطط البيانات أو عندما يفشل جزء واحد من مخطط البيانات في الوصول إلى الوجهة على سبيل المثال. لكنه لا يفشل بالضرورة بصمت، إذ يُضبَط بروتوكول IP دائمًا باستخدام بروتوكول مصاحب يُعرف باسم بروتوكول رسائل التحكم بالإنترنت Internet Control Message Protocol أو اختصارًا ICMP. والذي يحدّد مجموعةً من رسائل الخطأ التي تُرسَل مرةً أخرى إلى المضيف المصدر عندما يتعذّر على الموجّه أو المضيف معالجة مخطط بيانات IP بنجاح. إذ يحدّد بروتوكول ICMP رسائل الخطأ التي تشير إلى عدم إمكانية الوصول إلى المضيف الوجهة (ربما بسبب فشل الرابط)، إلى جانب فشل عملية إعادة التجميع، ووصول زمن TTL إلى الصفر، وفشل المجموع الاختباري لترويسة IP، وما إلى ذلك. يحدّد بروتوكول ICMP أيضًا مجموعةً من رسائل التحكم التي يمكن للموجه إرسالها مرةً أخرى إلى مضيف المصدر. وتُعَدّ إحدى رسائل التحكم الأكثر فائدةً هي تلك المسماة ICMP-Redirect، والتي تُخبر المضيف المصدر بوجود مسار أفضل إلى الوجهة. كما تُستخدَم رسائل ICMP-Redirect في الحالة التالية: افترض أنّ مضيفًا متصلًا بشبكة فيها موجّهان متصلان بها يُطلق عليهما R1 وR2، بحيث يستخدم المضيفُ الموجّه R1 في صورة موجّه افتراضي خاص به. فإذا تلقّى الموجّه R1 مخطَّط بيانات من المضيف، فسيعرف استنادًا إلى جدول التمرير الخاص به، أنّ الموجّه R2 سيكون خيارًا أفضل لعنوان وجهة معيّن، وسيرسل رسالة ICMP-Redirect إلى المضيف، ويطلب منه استخدام الموجّه R2 لجميع مخططات البيانات المستقبلية الموجَّهة إلى تلك الوجهة، ليقوم المضيف بإدراج مسار التوجيه الجديد إلى جدول التمرير الخاص به. كما يوفر بروتوكول ICMP أيضًا الأساس لِأداتين من أدوات تنقيح الأخطاء debugging المستخدَمة على نطاق واسع، وهما ping وtraceroute. حيث تستخدم الأداة ping رسائل ICMP echo لتحديد ما إذا كانت العقدة قابلةً للوصول وفعّالة. كما تستخدم الأداة traceroute تقنيةً غير بديهية لتحديد مجموعة الموجّهات على طول المسار إلى الوجهة. الشبكات الافتراضية Virtual Networks والأنفاق Tunnels نختم مناقشتنا لبروتوكول IP من خلال النظر في قضية ربما لم تتوقعها، لكنها مهمّة. ركّزت مناقشتنا حتى الآن على تمكين العُقد الموجودة على الشبكات المختلفة من التواصل مع بعضها البعض بطريقة غير مقيّدة، وعادةً ما يكون هذا هو الهدف في الإنترنت، حيث يريد الجميع أن يكون قادرًا على إرسال بريد إلكتروني إلى الجميع، كما يريد منشئ موقع ويب جديد الوصول إلى أوسع جمهور ممكن. ولكن هناك العديد من المواقف التي تتطلّب اتصالًا أكثر تحكُّمًا. ومن الأمثلة المهمة على هذا نذكر حالةالشبكة الخاصة الافتراضية virtual private network أو اختصارًا VPN. يُستخدَم مصطلح VPN بصورة مفرطة وتختلف تعريفاته، ولكن يمكن تعريف VPN من خلال التفكير أولًا في فكرة الشبكة الخاصة. حيث تبني الشركات التي لديها العديد من المواقع شبكاتٍ خاصة عن طريق استئجار داراتٍ من شركات الهاتف واستخدام هذه الخطوط لربط المواقع. حيث يقتصر الاتصال بين مواقع تلك الشركة فقط في مثل هذه الشبكة، وهو أمر مرغوب فيه غالبًا لأسباب أمنية. حيث تُستبدَل خطوط النقل المؤجّرة التي لا تتشاركها الشركة مع أية شركةٍ أخرى بنوعٍ من الشبكات المشتركة لإنشاء شبكة خاصة وهمية. وتُعَدّ الدَارة الافتراضية virtual circuit أو اختصارًا VC بديلًا معقولًا للغاية للخط المؤجّر leased line، نظرًا لاستمرارها بتوفير اتصال منطقيّ من نقطة لنقطة بين مواقع الشركة. فإذا كان لدى الشركة X دَارة افتراضية من الموقع A إلى الموقع B على سبيل المثال، من الواضح أنه يمكنها إرسال رزم بين الموقعين A وB. ولكن لا توجد طريقة تمكّن الشركة Y من تسليم رُزَمِها إلى الموقع B دون إنشاء دارتها الافتراضية أولًا إلى الموقع B. كما يمكن منع إنشاء مثل هذه الدارة الافتراضية إداريًا، وبالتالي منع الاتصال غير المرغوب فيه بين الشركة X والشركة Y. يوضِّح القسم (أ) من الشكل الآتي شبكتين خاصتين لشركتين منفصلتين. حيث نُقِلت كلتا الشبكتين في القسم (ب) إلى شبكة دارة افتراضية. بحيث يبقى الاتصال المحدود للشبكة الخاصة الحقيقية، ولكن أُنشِئت شبكتين خاصتين افتراضيتين نظرًا لاشتراكهما الآن بنفس وسائل الإرسال والمبدّلات. تُستخدَم شبكة دارة افتراضية في الشكل السابق (باستخدام تقنية ATM على سبيل المثال) لتوفير الاتصال المُتحكَّم به بين المواقع. كما يمكن أيضًا توفير وظيفة مماثلة باستخدام شبكة IP لتوفير الاتصال. ولكن لا يمكن ربط مواقع الشركات المختلفة بشبكة متشابكة واحدة فقط نظرًا لتوفيرنا بذلك اتصالًا بين الشركة X والشركة Y، وهو ما نرغب في تجنبه، ولحل هذه المشكلة سنحتاج إلى تقديم مفهومٍ جديد وهو نفق IP. يمكن عَدّ النفق IP رابطًا افتراضيًّا من نقطة لنقطة بين زوج من العقد المفصولة فعليًّا بعدد عشوائي من الشبكات. حيث يُنشَأ الرابط الافتراضي داخل الموجّه عند مدخل النفق من خلال تزويده بعنوان IP الخاص بالموجّه الموجود في أقصى نهاية النفق tunnel. إذا أراد الموجّه عند مدخل النفق إرسال رزمة عبر هذا الرابط الافتراضي، فسيغلّف الرزمة داخل مخطّط بيانات IP، حيث يكون عنوان الوجهة في ترويسة IP هو عنوان الموجّه الموجود في أقصى نهاية النفق، بينما عنوان المصدر هو عنوان الموجّه المغلِّف. يشبه هذا الرابط الافتراضي ارتباطًا عاديًا في جدول التمرير الخاص بالموجّه عند مدخل النفق. وبافتراض الشبكة الموجودة في الشكل السابق على سبيل المثال، فقد ضُبِط نفقٌ من الموجّه R1 إلى الموجّه R2، وأُسنِد رقم واجهة افتراضي بقيمة 0، وبالتالي قد يبدو جدول التمرير في الموجّه R1 مثل الجدول التالي: رقم الشبكة NetworkNum العقدة التوجيهية التالية NextHop 1 Interface 0 2 Virtual interface 0 Default Interface 1 يحتوي الموجّه R1 على واجهتين فيزيائيتين هما: الواجهة 0 التي تتصل بالشبكة 1، والواجهة 1 التي تتصل بشبكة متشابكة كبيرة، وبالتالي فهي الشبكة الافتراضية لجميع حركات مرور البيانات التي لا تتطابق مع شيء أكثر تحديدًا في جدول التمرير. كما يحتوي الموجّه R1 على واجهة افتراضية أيضًا، وهي واجهة النفق. بفرض استقبَل الموجّه R1 رزمةً من الشبكة 1 تحتوي على عنوان من الشبكة 2. وفقًا لجدول التمرير، يجب إرسال هذه الرزمة إلى الواجهة الافتراضية 0، بحيث يأخذ الموجّه الرزمة ويضيف ترويسة IP الموجهة إلى الموجّه R2 من أجل إرسال رزمةٍ إلى هذه الواجهة. لينتقل إلى تمرير الرزمة كما لو أنها اُستلِمت للتو، ويكون عنوان الموجّه R2 هو 18.5.0.1. بما أنّ رقم الشبكة لهذا العنوان هو 18، وليس 1 أو 2، فسيُعاد توجيه الرزمة الموجَّهة إلى الموجّه R2 عبر الواجهة الافتراضية default interface إلى الشبكة المتشابكة. تبدو الرزمة بمجرد مغادرتها الموجّه R1 لبقية العالم مثل رزمة IP عادية مخصّصة للموجّه R2، وتُمرَر وفقًا لذلك. حيث تُمرِر جميع الموجّهات الموجودة في الشبكة المتشابكة هذه الرزمة باستخدام الوسائل العادية، حتى تصل إلى الموجّه R2. ويكتشف الموجّه R2 حمل الرزمة لعنوانه الخاص عندما يستقبلها، لذلك يزيل عنوانَ IP وينظر إلى حِمل الرزمة، فيجد رزمة IP داخلية يكون عنوان وجهتها في الشبكة 2. يعالج الموجّه R2 الآن هذه الرزمة مثل أيّ رزمة IP أخرى يتلقّاها، كما يُمرِر الموجّه R2 الرزمة إلى الشبكة 2 لاتصاله المباشر بها. ويوضّح الشكل السابق التغيير في تغليف encapsulation الرزمة أثناء تحركها عبر الشبكة. حيث يعمل الموجّه R2 مثل نقطة نهاية النفق، ولكن لا يوجد ما يمنعه من أداء وظائف الموجّه العادية. فقد يستقبل بعض الرزم التي لا تُعَدّ واصلةً عن طريق نفق مثلًا، وهذه الرزمة موجهةٌ إلى الشبكات التي يعرف كيفية الوصول إليها، ويمكن تمريرها بالطريقة العادية. قد تتساءل عن سبب رغبة أيّ شخص في تحمُّل عناء إنشاء نفق وتغيير تغليف الرزمة أثناء مرورها عبر شبكة متشابكة، ومن بين أحد الأسباب هو الأمن security. إذ قد يصبح النفق بعد استكماله بالتشفير، نوعًا خاصًا جدًا من الروابط عبر شبكة عامة. أمّا السبب الآخر، فهو امتلاك الموجّهين R1 وR2 لبعض القدرات غير المتوفرة على نطاق واسع في الشبكات المتداخلة مثل توجيه البث المتعدد. إذ يمكن بناء شبكة وهمية من خلال توصيل هذه الموجّهات بنفق، بحيث تبدو جميع الموجّهات في هذه الشبكة التي لديها هذه الإمكانية متصلةً مباشرةً. بينما يُعَدّ السبب الثالث لبناء الأنفاق، هو حَمل الرزم باستخدام بروتوكولات أخرى غير بروتوكول IP خلال شبكة IP. وطالما أنّ الموجهات في أيٍّ من طرفيّ النفق تعرف كيفية التعامل مع هذه البروتوكولات الأخرى، فسينظر إليها نفق IP على أنّها رابط من نقطة لنقطة يمكن من خلاله إرسال رزمٍ مغايرة عن رزم IP. كما توفّر الأنفاق أيضًا آليةً يمكن من خلالها إجبار رزمة على تسليمها إلى مكانٍ محدَّد على الرغم من إمكانية إيحاء ترويستها الأصلية التي تُغلَّف داخل ترويسة النفق، بوجوب نقلها إلى مكان آخر. وهكذا نجد أنّ الأنفاق تقنية قوية وعامة جدًا لبناء روابط افتراضية عبر الشبكات المتشابكة، لذلك تتكرّر هذه التقنية مع حالة الاستخدام الأكثر شيوعًا والتي هي نفق IP عبر بروتوكول IP. للنفق سلبيات أيضًا، تتمثّل أولّها في زيادته من طول الرزم، ويُعتَبر هذا بدوره هدرًا كبيرًا لحيّز النطاق التراسلي للرزم القصيرة. وقد تكون الرزم الأطول عرضةً للتجزئة والتي لها مجموعة من العيوب الخاصة بها. كما قد تكون هناك أيضًا آثار على الأداء بالنسبة للموجّهات في أيٍّ من طرفي النفق، نظرًا لحاجتها إلى القيام بعمل أكثر من طلبات التمرير العادية، مثل إضافة وإزالة ترويسة النفق. كما توجد أخيرًا، تكلفة إدارية للكيان الإداري المسؤول عن إعداد الأنفاق والتأكد من معالجتها بصورة صحيحة بواسطة بروتوكولات التوجيه. ترجمة -وبتصرّف- للقسم Internet من فصل Internetworking من كتاب Computer Networks: A Systems Approach. اقرأ أيضًا المقال التالي: توجيه Routing الرزم ضمن الشبكات الحاسوبية المقال السابق: الشبكات الفرعية والعناوين والأخطاء في بروتوكول IP
-
توجد الأنماط Patterns بجميع أشكالها بدءًا من الأشكال البسيطة التكرارية إلى المصفوفات الرسومية المعقدة، وسنشاركك في هذا المقال بعض النصائح لإنشاء تأثيرات أنماط تفصيلية باستخدام رسوم مفعمة بالألوان، إذ سنستخدم أولًا تقنيةً لملء لوحة الرسم canvas برسوميات موضوعة عشوائيًا، ثم سنعرض طريقتين يدويتين لإنشاء تصاميم لأنماط مكرَّرة بسلاسة. كيفية إنشاء أنماط تعبئة رسومية عشوائية تُستخدَم هذه التقنية لإنشاء أنماط رسومية تفصيلية، إذ تُملأ لوحة الرسم كاملةً وبصورة سريعة برسوميات مثل صورة أو رسم، من أي مصدرٍ للصور، بحيث تكون هذه الرسوميات موضوعةً عشوائيًا. تكون نتيجة هذه التقنية تكرارًا غير سلس، ولكنها مفيدة لملء منطقة لها أي حجم دون تكرار في التصميم على الإطلاق، إذ تُعَد هذه التقنية مناسبةً لنمط البلاط التقليدي. يمكنك تنزيل رسومات مجانية من مكتبة Heritage Type Co الضخمة، والتي تُعَد مثاليةً لإنشاء أنماط طبيعية، وسنستخدم ملفات من مجموعة Fresh Fruits من هذه المكتبة في المثال التالي. لاحظ أن حجم هذه الرسومات كبير جدًا، وهذا أمر رائع إن أردت أن تصنع نمطًا حقيقيًا لطباعته على الأقمشة، ولكن يمكنك تصغير هذه الرسومات مسبقًا عند استخدامها رقميًا. يوجد شيءٌ آخر رائع بشأن هذه الرسومات هو أنها مقصوصة وغير مرتبطة بأي شيء آخر. اذهب إلى قائمة Edit ثم اختر Define Pattern كما في الشكل السابق لحفظ الصورة مثل عيّنة swatch داخل مكتبة الأنماط في الفوتوشوب، وكرّر هذه الخطوة مع جميع الرسومات التي تريد استخدامها لتكوين تصميم النمط الخاص بك. أنشئ مستندًا جديدًا لتصميم النمط الرئيسي، وتذكّر أن تأثير هذا النمط لا يتكرر، ولا توضَع أجزاؤه بجانب بعضها البعض بسلاسة، لذلك يجب إنشاء مستند له الحجم size / الدقة resolution النهائية من أجل الاستخدام النهائي. املأ طبقة الخلفية Background باللون الأسود باستخدام الاختصار ALT+Backspace من لوحة المفاتيح، ثم أنشئ طبقةً جديدةً واذهب إلى قائمة Edit ثم اختر Fill كما في الشكل السابق. عيِّن الخيار Pattern مثل خيار للمحتويات Contents، ثم حدّد أول نمط من بين أنماط رسوماتك المخصصة custom pattern، بعدها حدّد الخيار Script وغيّر الإعداد إلى تعبئة عشوائية Random Fill. تحتوي شاشة التعبئة العشوائية Random Fill على مجموعة متنوعة من الخيارات لتخصيص التأثير، حيث أن أهم هذه الخيارات هو مقدار الكثافة Density الذي يحدّد عدد نسخ الشكل الموجودة. اضبط قيم المقياس scaling values بالقيمتين 0.75 و1 كما في الشكل السابق بحيث يكون هناك اختلاف طفيف في الحجم بين هذه الرسومات، وفعّل خيار "تدوير النمط Rotate Pattern"، بحيث لا تتموضع جميع الرسومات بنفس الشكل. يمكنك وضع القيمة 0.2 مثل قيمةٍ للتحكم بالسطوع Brightness، لإضافة اختلاف بسيط في السطوع بين الرسومات، ولكن هذه الخطوة اختيارية. أنشئ طبقةً جديدةً ثم انتقل إلى قائمة Edit، ثم اختر Fill مرةً أخرى، وذلك لإنشاء نمطٍ آخر باستخدام رسمٍ ثانٍ. استخدم إعدادات التعبئة العشوائية Random Fill ذاتها. أعِد نفس الخطوات لكل رسم نمط تعبئة إلى أن تُغطَّى لوحة الرسم بمجموعة متنوعة من الصور الموضوعة عشوائيًا على طبقات منفصلة. يمكنك تقليل كثافة الطبقات الأخيرة عندما تبدأ لوحة الرسم بالامتلاء، من أجل تغطية أي فجوات في النمط دون أن تطغى طبقة على الطبقات الأخرى. والنتيجة هي نمط معقد بتفاصيل كثيفة، إذ وُضِعت مئات الرسومات ضمن طبقات في اتجاهات عشوائية. يحسّن تأثيرُ الظل Drop Shadow البسيط (الموضَّح في الشكل السابق) الذي يُطبَّق على الطبقة، النمطَ من خلال تحديد الطبقة التي نريد تطبيق هذا التأثير عليها، ونختار الحجم Size الأكبر لهذا التأثير ليتوافق مع الأبعاد الكبيرة لهذا النمط. انقر زر الفأرة الأيمن واختر Copy Layer Style لنسخ التأثير، ثم انقر على جميع طبقات النمط مع الضغط على مفتاح Shift من لوحة المفاتيح، ثم ألصِق التأثير من خلال النقر على زر الفأرة الأيمن واختيار Paste Layer Style من أجل تطبيق نفس تأثير الظل drop shadow على جميع الطبقات. يُحسَّن النمط تحسينًا أكبر عن طريق إضافة طبقة ضبط السطوع / التباين Brightness/Contrast adjustment بعد كل طبقة من هذا النمط. انقر على أيقونة clip mask لقص طبقة الضبط adjustment layer قصًا يتناسب مع الطبقة التي تحتها، ثم اضبط قيمة السطوع Brightness عشوائيًا لإنشاء طبقات تظليل خفيفة بين طبقات الرسوميات. والنتيجة النهائية هي نمط معقد برسومات تفصيلية. لا توجد نهاية لإبداع أشكال أنماط باستخدام هذه الطريقة اعتمادًا على الصور المستخدمة. كيفية إنشاء أنماط مكررة إذا أردت تكرار تصميم نمطك بسلاسة، فيمكنك استخدام تقنية مماثلة للتقنية السابقة، ولكن مع إضافة بعض الخطوات الإضافية. سنستخدم في المثال التالي مجموعةً مختارةً من رسومات Tropical Watercolour. أنشئ مستندًا جديدًا يحتوي على تصميم النمط الخاص بك، وسنستخدم في هذا المثال نفس حجم المستند 5000x5000px، ولكن يمكنك استخدام الحجم المناسب للنمط الذي تصممه. اسحب الأدلة guides من المساطر rulers التي يمكنك إظهارها من قائمة View ثم اختيار Rulers، وذلك من أجل تحديد حواف edges لوحة الرسم الأصلية. انتقل إلى قائمة Image ثم اختر Canvas Size، وزد حجم منطقة لوحة الرسم canvas لتوفير مساحة عمل أكبر، إذ تكفي مضاعفة حجم المستند الأصلي. تساعد هذه الأدلة في تخيّل حدود لوحة الرسم الأصلية. املأ الخلفية وأنشئ طبقةً جديدة، ثم أنشئ طبقات أخرى تحتوي على رسومات النمط الذي تريد تصميمه. نحتاج هذه المرة إلى التأكد من أن مستوى الكثافة Density منخفض بما يكفي لتجنب تداخل الرسومات الكثيرة، لهذا جرّب قيمة للكثافة أصغر من 1px مثل القيمة 0.5px، ومع ذلك لا تعطي المعاينة النتيجة النهائية، لذلك اضغط OK لرؤية النتيجة وتراجع إن لم تناسبك هذه النتيجة. يجب نسخ أي عناصر رسومية متقاطعة مع دليلٍ إلى الجانب المقابل منه، وذلك للتأكد من تكرار النمط الكامل دون تقطيع في الرسوم. استخدم أداة Lasso لرسم تحديد حول جميع الرسومات الموجودة على حافة واحدة كما في الشكل السابق. اذهب إلى قائمة Edit ثم نسخ Copy، ثم اذهب إلى قائمة Edit مرةً أخرى واختر لصق خاص Paste Special، ثم Paste in Place لإنشاء نسخة من الرسوميات على طبقة جديدة. اضغط على CTRL+T (أو CMD+T) من لوحة المفاتيح لتفعيل خاصية التحويل Transform، ثم انقر على رمز المثلث في شريط الأدوات العلوي كما في الشكل السابق، بعدها أدخل قيم حجم مستندك ضمن حقل X أو Y المناسب لإزاحة الرسوميات المتكررة إلى الجانب الآخر. اجعل الطبقة غير مرئية وفعّل طبقة النمط الرئيسية مرةً أخرى، ثم ارسم تحديدًا حول أي رسوميات متداخلة مع الحافة الأخرى. أزِح هذه العناصر بنفس الطريقة باستخدام الاختصار CTRL+T، ولكن بقيمة سالبة لتحريكها في الاتجاه الآخر. ادمج جميع الطبقات ضمن طبقة نمط واحدة من خلال الانتقال إلى قائمة Layer، ثم اختر دمج الطبقات Merge Layers، أو من خلال الاختصار CTRL+E من لوحة المفاتيح. كرّر العملية نفسها على المحور الآخر لعكس العناصر من اليسار إلى اليمين، ومن اليمين إلى اليسار كما في الشكل السابق. استخدم نفس قيمة حجم المستند في الحقل X فقط، ثم اجعل الطبقة غير مرئية، وانسخ أي رسوميات من هذا الجانب إلى الجانب الآخر أيضًا. تأكد من موازنة العناصر على الحافتين اليسرى / اليمنى والحافتين العلوية / السفلية للتأكد من أنها متطابقة على طول الأدلة قبل دمج الطبقات، ولاحظ ترتيب الطبقات الموضّح في الشكل السابق. اجعل طبقة النمط الأولى التي أنشأتها غير مرئية، وكرّر الخطوات ذاتها لإنشاء نمط متكرر مع الرسم التالي. طبّق التعبئة العشوائية random fill أولًا، ثم انسخ أي عناصر موجودة على طول الأدلة، بحيث تظهر على الجانب الآخر أيضًا من الدليل. تستغرق هذه العملية وقتًا أطول بكثير بسبب الاضطرار إلى معالجة كل طبقة، بالإضافة إلى الاضطرار إلى العمل بقيم كثافة متفرقة، لكن النمط يملأ اللوحة سريعًا. طبّق تأثيرات التظليل لتحسين التصميم. اذهب إلى قائمة Image واختر حجم اللوحة Canvas Size وأعد المستند إلى حجمه الأصلي كما في الشكل السابق. انتقل إلى قائمة العرض View، ثم اختر معاينة النمط Pattern Preview لتتحقق من تكرار النمط بسلاسة مرةً أخرى. سيقسّم برنامج الفوتوشوب النمط حتى تتمكن من رؤية كيفية تكرار الحواف بسلاسة. تولِّد هذه التقنية أنماطًا تفصيلية تمامًا مثل طريقة التعبئة العشوائية الأصلية، ولكن الأنماط في هذه التقنية تتكرر بسلاسة مع أحجام لا نهائية. كيفية إنشاء أنماط يدويا يُعَد الإعداد "معاينة النمط Pattern Preview"، أداةً مفيدة لإنشاء الأنماط يدويًا دون استخدام تعبئة عشوائية، وبالتالي يمكنك التحكم بتصميم النمط بالكامل. ابدأ بنسخ كل العناصر الموجودة في الطبقات الفردية. إذا حرّكت الرسوم باتجاه حافة لوحة الرسم مع تفعيل الخيار معاينة النمط Pattern Preview، فإن برنامج الفوتوشوب سيكرّر ما تفعله على الجانب الآخر أليًا. كرّر نسخ كل رسم ودوّره، وغيّر موضعه لإنشاء تصميم النمط الخاص بك يدويًا، ستستغرق هذه العملية وقتًا أطول دون استخدام التعبئة العشوائية، ولكن يمكنك التحكم في مكان وضع كل قطعة. ليست هناك حاجة أيضًا إلى معالجة العناصر المتكررة على كل حافة لأن وضع معاينة النمط في الفوتوشوب يفعل ذلك نيابةً عنك. انتقل إلى قائمة Edit بمجرد اكتمال النمط الخاص بك، ثم اختر "تعريف نمط Define Pattern"، لحفظ التصميم في مكتبة الأنماط في فوتوشوب، حيث يمكن أن تصل مجموعة من الأدوات إلى هذا النمط. يمكن ملء لوحة الرسم بالكامل بتصميم النمط السلس الخاص بك عند استخدامه مع الطبقة ذات الشكل Pattern Overlay أو الطبقة ذات الضبط Pattern Fill. ترجمة -وبتصرّف- للمقال How to Create Detailed Graphic Patterns in Photoshop لصاحبه Chris Spooner. اقرأ أيضًا مقدمة إلى برنامج أدوبي فوتوشوب Adobe Photoshop كيفية تصميم تأثير الجلد على النصوص في الفوتوشوب
-
يُعَد تصميم صفحة الهبوط Landing page عملًا فنيًا حقيقيًا، وعملًا تسويقيًا يؤتي ثماره، حيث أُنشِئت هذه الصفحة خصيصًا لتحويل زوّار موقعك إلى عملاء، لذلك فتصميم صفحة الهبوط يستحق اهتمامك وبحثك. قد تُكلِّفك صفحة الهبوط سيئة التصميم ملايين التحويلات conversions (أي تحويل الزوار إلى عملاء)، لذلك أُعِدَّ هذا المقال للتأكد من تجنّب هذا السيناريو، وسنستعرض الأمور التي تجعل هذه الصفحة فعَالةً مع شرح العناصر الإلزامية لتصميمها. حدد هدفك قد تصبح صفحة الهبوط ذات التصميم الجميل آلةً لتوليد عمليات تحويل الزوّار إلى عملاء، وطالما أنك تعرف كيفية استخدام إمكانات هذه الصفحة، فعليك فهم سبب حاجتك لمثل هذه الصفحة قبل بدئك بالتصميم. تعمل صفحات الهبوط مثل وحدات ويب منفصلة، وتُنشَأ لهدف محدَّد وهو استقبال حركة مرور الزوار القادمة من حملة تسويقية وتحويلهم إلى عملاء، ويمكن تشتيت انتباه الناس بسهولة، فقد يربك موقعُ الويب الذي يحتوي على خيارات وأزرار وروابط متعددة الزوار البعض، وقد ينسى بعضهم كيف وصل إلى هذه الصفحة. ركز جيدا يجب عليك الآن بناء مفهوم تصميم صفحة الهبوط بالكامل استنادًا إلى هذا الهدف الذي حددته، إذ يجب أن يكون كل عنصرٍ مضمّن في التصميم متعلقًا بهذا الهدف، ويجب التخلّص من جميع عوامل التشتيت التي قد تؤدي إلى إبعاد المستخدِمين. وهذا يعني تقييد التصميم على تلك العناصر الأساسية التي يحتاجها المستخدِم لاتخاذ قرار فقط، لذلك فكّر جيدًا فيما يجب وما لا يجب عليك تضمينه في التصميم. ابدأ التصميم يُعَد تصميم صفحة الهبوط عمليةً مدروسة، فقد تكلّفك عواملٌ خاطئة، مثل: العناصر، أو الرسالة، أو الموضع الخاطئ، تحويلاتٍ كثيرة لذلك تمهّل قليلًا. أهم شيء يجب مراعاته عند البدء من نقطة الصفر هو تنظيم عناصر التصميم، لذلك فكّر بتصميم صفحة الهبوط على أنه مسارٌ يؤدي إلى الهدف الأساسي وهو تحويل الزوّار إلى عملاء. ويمكنك تخيّل عناصر التصميم لترسم مسارًا يؤدي طبيعيًا إلى الهدف المحدّد. يوجد مسارٌ قصير وآخر طويل، ويجب أن يكون لديك كلا المسارين في الحالة الفضلى، وهما: يتكوّن المسار القصير، من ترتيب عناصر تصميم صفحة الهبوط في الجزء البارز من الصفحة above the fold، ويجب أن يوفّر هذا القسم وحده معلومات كافية للمستخدِم لتحويله إلى عميل. يوجَّه المسار الطويل إلى الأشخاص الذين يحتاجون إلى مزيد من الإقناع، ويوفّر جميع المعلومات الإضافية التي يحتاجها المستخدِم من أجل تحويله إلى عميل مثل الشهادات والدليل الاجتماعي، والضمانات، مثل: سياسة الإرجاع، وسياسة استرداد الأموال، وطريقة الشحن، والأسئلة الشائعة، وما إلى ذلك. الجزء البارز من الصفحة أو مسار التحويل القصير تسمّى المنطقة من الصفحة التي يراها المستخدِم قبل التمرير للأسفل بالجزء البارز من الصفحة above the fold، وهي المعلومات الأولى التي يراها الأشخاص عند وصولهم إلى صفحتك، ولذلك يجب إعطاء اهتمام إضافي لهذا القسم. فكّر في كل عنصر بعناية واترك فقط المعلومات الأساسية التي يحتاجها المستخدِم لتحويله إلى عميل، وستُذكَر لاحقًا الأشياء الأخرى التي تحقّق هدفك، ولكنها ليست ضروريةً ليتخذ المستخدم قراره في هذه المرحلة. يجب أن يرى المستخدِم العناصر التالية عند وصوله إلى صفحتك: تناسق مرئي مع الإعلان: افترِض أن إعلانًا لبيع أحذية قد لفت انتباهك، وبالتالي تنقر عليه وتصل إلى الصفحة لتجدها تعرض ساعات، فماذا تفعل؟ هل تغلق الصفحة؟ هذا صحيح غالبًا. يجب التأكيد بصورةٍ كافية على أهمية تناسق تصميم صفحة الهبوط مع الإعلان، لذلك ضع في حساباتك أن التناسق هو الانطباع الأول لصفحة الهبوط، ولهذا يجب أن تكون جميع العناصر من الألوان والرسالة والمرئيات وغيرها، متناسقةً مع الإعلان الذي جلب الزوار إلى هذه الصفحة. عنوان ملفت للانتباه: هو الرسالة الأولى (وليست الأخيرة) التي يراها زائر صفحة الهبوط، ولهذا ستحتاج أنت أو فريق التسويق إلى مزيد من التفكير في صياغة عنوان رئيسي قوي وملفت للانتباه، فهذه هي الرسالة الأهم التي ستحدد استمرار المستخدم في قراءة عرضك أم لا. نسخة من المعلومات: اجعل صفحة الهبوط موجزةً وغنيةً بالمعلومات. قد تحتاج بعض صفحات الهبوط فقط إلى عنوان فرعي مؤلف من جملة أو جملتين اعتمادًا على الهدف المحدّد، بينما تحتاج صفحات أخرى إلى احتواء مزيدٍ من المعلومات مثل شرح موجز للعرض وللفوائد التي تحصل عليها، ويُعَدّ استخدام القوائم النقطية لمثل هذه الحالات فعّالًا للغاية بحيث تجعل المعلومات سهلة القراءة والفهم. صورة منتج عالية الدقة: المحتوى المرئي محفّزٌ كبير للحواس، حيث يعالج الدماغ البشري المعلومات المرئية أسرع بكثير من النصوص، لذلك يجب تضمين صورة عالية الدقة تتوافق مع العرض في صفحة الهبوط الخاصة بك. استخدم صورةً عالية الدقة أو شخصية كرتونية لترافق عرضك، حتى لو كنت تقدّم خدمةً ولا تبيع منتجًا حقيقيًا، فقد أُثبِت أن الشخصيات الكرتونية في التسويق تعزز نشاطك. زرّ للحث على اتخاذ إجراء: الزر هو الوِجهة التي تؤدي إليها جميع العناصر الأخرى، إذ يجب أن يجذب العين زرّ الدعوة لاتخاذ الإجراء call-to-action، وهناك الكثير من التقنيات لفصل هذا الزر بصريًا عن العناصر الأخرى، وفيما يلي بعض من أكثر هذه التقنيات فعالية: اجعله بارزًا، واستخدم لونًا شديد التباين. كبّره، فالعناصر الكبيرة جذابة. امنحه مساحة أكبر، فالمساحة السلبية المحيطة بالزر تلفت الأنظار. انظر إلى تصميمك الآن من بعيد، فإن ما زال الزر ملحوظًا جيدًا، فهذا عمل رائع ويجب أن يكون الزر واضحًا ويصف عمله قدر الإمكان، لهذا يجب أن يعرف المستخدِم ما سيحدث بعد النقر عليه. حافز قوي: يضمن هذا الحافز أن يتخذ الزوار إجراءً في الحال دون انتظار لوقتٍ لاحق، فإن انتظر المستخدِمون قليلًا، فسيفكّر عدد كبير منهم في الخروج من الموقع. والحوافز القوية هي عناصر، مثل: العد التنازلي، والموعد النهائي للعرض، والإصدار، والمخزون المحدود، والخصم المبكر، وغير ذلك. لهذا تأكد من وضع هذه الحوافز بالقرب من الزر، فهذه الحوافز ستغير رأي العميل في حال عدل عن رأيه في النقر على الزر. نموذج إرسال (اختياري): قد لا تستمر صفحتك إلى أسفل الجزء البارز من الصفحة بناءً على الهدف منها، وبالتالي ستحتاج إلى وضع نموذج إرسال قبل الزر مباشرةً. وبما أن الناس لا يحبون نماذج الإرسال الطويلة، فعليك وضع 3 حقول على الأكثر، مثل: حقل الاسم، والبريد الإلكتروني، والرسالة. قد يكون مسار التحويل القصير كافيًا لبعض المستخدِمين ليتحولوا إلى عملاء، ولكن سيبحث بعض المستخدِمين الآخرين عن معلومات إضافية قبل اتخاذ قرار إيجابي، فمهمتك هي تزويد هؤلاء المستخدِمين بهذه المعلومات. الجزء الموجود أسفل الجزء البارز من الصفحة below the fold أو مسار التحويل الطويل نأمل أن يتحوّل جزء كبير من الزوار الواصلين إلى الصفحة نتيجة حملتك إلى عملاء باستخدام مسار التحويل القصير، ولكن يجب أن يكون لديك معلومات إضافية قوية للمستخدِمين المهتمين ولكنهم ما زالوا بحاجة إلى مزيد من الإقناع. لهذا يجب أن تجيب هذه المعلومات عن جميع الأسئلة المحتملة، وتحل جميع المشاكل، وتبدّد أي شكوك محتملة قد تكون لدى المستخدم بشأن عرضك، وتشمل هذه المعلومات ما يأتي: معلومات عمّا يجب أن يفعله المستخدم: قد يكون بعض المستخدمين مهتمين بعرضك ولكن لديهم شكوك حول كيفية ومكان استخدامه، لهذا يوضّح قسم "ماذا يجب أن تفعل؟" الأمر لهؤلاء المستخدمين، وهنا اشرح وأعطِ أمثلةً عن مكان وكيفية ملاءمة منتجك بصورة أفضل. يُعَدّ الهدف هو أن يتخيل الأشخاص أنفسهم يستخدمون هذا المنتج، وبالتالي يصبحون أكثر ميلًا للشراء، لأنهم يتخيلون كل الأشياء التي يمكنهم فعلها بمنتجك، أو يصلون إلى النتيجة المرغوبة من استخدام خدمتك. معلومات عن كيفية عمل المنتج أو الخدمة: يُعنى مستخدمون آخرون بالشفافية، فهم بحاجة لمعرفة كيفية سير العملية قبل التسجيل والاتصال. لهذا لا تخفي هذه المعلومات واشرحها خطوةً بخطوة، فهذا أفضل أسلوب يمكنك اتباعه. دليل اجتماعي: ضمّن شعارات العلامات التجارية الشهيرة المرتبطة بمنتجك أو خدمتك، والشهادات الموثوقة من عملاء حقيقيين، وردود الفعل من شبكة التواصل الاجتماعي التي تناقش منتجك، والتقييمات. حيث سيحظى أي شيء يُظهر رأيًا عامًا إيجابيًا لعرضك بتقدير كبير من زوّار صفحة الهبوط. معلومات تقنية وضمانات: زوّد المستخدمين الذين يحتاجون إلى التعمّق أكثر بمعلومات، مثل: طرق الإنتاج، والمواد المستخدَمة، وتكاليف الشحن، وفرص الحصول على شحن مجاني، وطرق الدفع وما إلى ذلك؛ وقدّم ضمانات، مثل: سياسة الإرجاع، وسياسة استرداد الأموال. ضمّن قسمًا يحتوي على الأسئلة الشائعة بما في ذلك الأسئلة الحقيقية التي يطرحها الزوّار. نموذج إرسال وزرّ دعوة لاتخاذ إجراء آخر: ضع ما شئت في القسم الموجود أسفل الجزء البارز من الصفحة، ولكن تذكّر جزءًا أساسيًا هو: كرّر زر الدعوة لاتخاذ إجراء. إن لم تضع نموذج إرسال في البداية، فثاني أفضل مكان لوضعه هو هنا (وهو إلزامي). إذ لن يعود أحدٌ للبحث عن النموذج أو الزر. ولهذا يمكنك إبقاء الزر موجودًا أثناء التمرير عبر الصفحة، وبذلك ستتاح للقارئ فرصة التحوّل إلى عميل في حالة اتخاذ قرار أثناء النزول عبر صفحتك. الخلاصة تختلف صفحات الهبوط اختلافًا كبيرًا من صفحة إلى أخرى، ولكن تظل العناصر الرئيسية نفسها، وقد غطينا جميع المعلومات الأساسية التي تحتاجها لبدء إنشاء تصميم صفحة هبوط قادرة لتحويل الزوّار إلى عملاء من نقطة الصفر، وبهذا تكون قادرًا على تصميم صفحة الهبوط تصميمًا صحيحًا. ترجمة -وبتصرّف- للمقال Create an Effective Landing Page Design from Scratch لصاحبته Iveta Pavlova.
-
هل تريد إنشاء مقاطع فيديو تقدّم فيها دروسًا تعليميةً باستخدام برنامج Adobe Character Animator ولكنك لا تعرف من أين تبدأ؟ إذًا تابع معنا هذا المقال الذي يقدّم أساسيات إنشاء دمية متحركة إنطلاقًا من شخصية ساكنة باستخدام هذا البرنامج، وستتعلّم أيضًا أساسيات العمل على هذا البرنامج ابتداءً من إعداد الشخصية التي تريد تحريكها، ثم تحويلها إلى دمية، وصولًا إلى تصدير الفيديو. ستُتاح لك الفرصة أيضًا لتنزيل الدمية التالية مجانًا، لذلك جهّز نفسك وأعِد العدّة للانطلاق! احصل على الشخصية يجب أن يكون لديك شخصية لتحريكها في حاسوبك، أو أن لديك تصوّر على الأقل في ذهنك عن هذه الشخصية بما أنك مهتم بعملية شخصية ساكنة إلى دمية متحركة باستخدام برنامج Adobe Character Animator. فإن لم يكن لديك هذه الشخصية بعد، فأول خطوةٍ هي الحصول عليها، ولكن كيف؟ تُعَدّ طرق الحصول على شخصية غير محدودة، حيث يمكنك الاختيار من بين الكثير من الشخصيات المتاحة مجانًا أو للبيع عبر الإنترنت، كما يمكنك الحصول على شخصية مصمَّمة لك حصريًا أيضًا، إذ سيحبّ فنانون كثيرون في منصة مستقل مثلًا العمل على ذلك من أجلك. ويمكنك أيضًا تصميم شخصيتك الخاصة إذا كنت رسامًا جيدًا، وبالتالي ستحتاج برنامجًا مناسبًا، مثل: Adobe Photoshop، أو Adobe Illustrator. لقد استخدمنا في هذا المقال شخصيةً مجانيةً تُدعَى Mr.Geekson، وهي مصمَّمة أصلًا باستخدام برنامج Adobe Illustrator، أليست هذه الشخصية جميلة؟ جهز نفسك بكاميرا وميكروفون ستحتاج إلى كاميرا وميكروفون لتستخدم برنامج Adobe Character Animator استخدامًا صحيحًا، لأنه يكتشف تعبيراتك، وحركات وجهك باستخدام هذه الكاميرا من أجل تحريك الدمية وفقًا لذلك. استخدام الكاميرا أمر إلزامي ولكن الميكروفون اختياري، إذ ستحتاجه لتتحدث من خلال شخصيتك بنفسك. لكن يمكنك دائمًا استخدام صوت شخص آخر إن لم تحب استخدام صوتك. ضع تسميات وترتيبا لأجزاء الجسم قد تبدو هذه الخطوة مملة، ولكنها الخطوة التي تحوّل الشخصية إلى دمية متحركة في برنامج Adobe Character Animator. إذا رسمتَ شخصيتك بنفسك، فستحتاج إلى إعداد عدة أشكال للفم، والعينين، والحاجبَين، وأجزاء الجسم، وغير ذلك. بحيث تستطيع الدمية إظهار تعبيرات مختلفة، مثل: السعادة، والحزن، والغضب، والدهشة. الخطوة التالية هي تجميع وتسمية أجزاء وجه ووجسم الشخصية، بطريقة تمكّن البرنامج من التعرّف عليها Adobe Character Animator. حيث يستخدم البرنامج هذه الأسماء الأساسية لكي يفهم تعبيرات وجهك التي يلتقطها من الكاميرا، وبالتالي يفعّل جزء وجه الشخصية المناسب. يوضّح الشكل التالي طريقة تسمية عناصر وجه وجسم الشخصية Mr. Geekson: ضمن شخصيتك في برنامج Adobe Character Animator تهانينا! باتباعك للخطوات السابقة فقد أصبحت شخصيتك تُدعَى دميةً puppet الآن، وستُدرَج كل التسميات التي أجريتها لشخصيتك ضمن برنامج Adobe Character Animator. حيث سيأخذ برنامج Adobe Character Animator بكل التغييرات التي أجريتها على ملف الشخصية الأساسي المصمَّم باستخدام الفوتوشوب أو الإليستريتور، وذلك بغض النظر عن البرنامج الذي استخدمته لإنشاء هذه الدمية في المقام الأول. إذا رتّبت عناصر شخصيتك وسمّيتها بطريقةٍ صحيحة ضمن ملف AI أو PSD، فيجب أن تكون دميتك قادرةً على متابعة حركات رأسك وجفونك، كما يجب أن تكون قادرةً على تحريك شفتيها بالتزامن مع صوتك lipsync عندما تتحدث، وإذا لم يكتشف البرنامج تعابير وجهك كما ينبغي، فيمكنك دائمًا ضبط كل هذه الإعدادات يدويًا باستخدام لوحات وإجراءات برنامج Adobe Character Animator. خصص إشارات tags وسلوكيات behaviors لأجزاء جسم الدمية استخدم الأدوات الموجودة في نافذة Puppet لتعيين إشاراتٍ tags، وسلوكيات behaviors إلى أجزاء جسم الدمية المختلفة. يوضّح الشكل الآتي الإشارات والسلوكيات التي عيّناها للدمية Mr. Geekson، حيث عملنا على وضع إشارات على كل أجزاء الجسم، ثم جعلنا الأذرع قابلةً للسحب draggable، بحيث يمكن التحكم بها باستخدام الفأرة، كما وضعنا الإشارة "dangle" إلى ربطة العنق لكي تكون متدلية وبالتالي تتأرجح بسلاسة، إلى جانب وضعنا للإشارة "fixed" على الرجلين لكي تكون ثابتة. خصص مفاتيحا للمنبهات Triggers قد يكون التحكم بحركات ذراع الدمية باستخدام لوحة المفاتيح أو التحكم بها باستخدام الفأرة ولوحة المفاتيح معًا أسهل بالنسبة لبعض الأشخاص، لذلك لديك الخيار في تخصيص المفاتيح التي يؤدي الضغط عليها تنبيه حدثٍ معين. سنوضّح هذه الخطوة باستخدام دميتنا Mr. Geekson. لقد حدّدنا أزرارًا مختلفةً من لوحة المفاتيح (K وJ وL وS وU وI) وهي مرتبطة بوضعيات مختلفة لليد، أو للأشياء التي تمسكها يد الدمية. حيث تتحكم هذه الطريقة بالذراعين بسهولة عندما تسجّل الكاميرا تعبيرات وجهك وحديثك. ابدأ تسجيل مشاهدك من نافذة Scene ابدأ التسجيل من نافذة Scene، وتأكّد من جودة إضاءة وجهك، حتلى يتمكّن البرنامج من اكتشاف تعابيرك والتعرّف عليها دون عناء، بعدها حاول التخلّص أيضًا من الضوضاء في الخلفية عند تسجيل صوتك. لاحظ شريط مستوى الصوت الذي يُظهر لك مستوى صوتك، ويُعلِمك إن كنت بحاجة إلى رفع صوتك. هل أنت جاهز لبدء تحريك دميتك؟ إذًا هيا بنا. إن لم تكن مرتاحًا بكثرة هذه المهام المتعددة، فإن هذا البرنامج يتيح لك تسجيل أجزاء منفصلة لحركات دميتك. لذلك اهتم أولًا بحركات الوجه، ثم بنظرات العيون ومزامنة حركات الشفاه وغير ذلك. يمكنك أيضًا ضبط طول كل تسجيل، وإجراء جميع أنواع التعديلات الإضافية بحيث تُدمَج الطبقات المختلفة معًا. تصدير الفيديو Exporting بهذا يكون قد حان الوقت لتصدير تسجيلك على أساس مقطع فيديو، أو تسلسل صور، وهذا بعد أن تكون جاهزًا وراضيًا عن النتيجة النهائية. إن اخترت تصدير النتيجة على أساس مقطع فيديو، فسيفتح برنامج Adobe Character Animator برنامجَ Adobe Media Encoder تلقائيًا، بحيث يمكنك تحديد وضبط إعدادات طريقة تصدير الفيديو التي تريدها؛ أما إذا اخترت تصدير النتيجة على أساس تسلسل صور، فسيمنحك البرنامج مجموعةً متنوعةً من التنسيقات التي يمكنك من خلالها اختيار التنسيق المفضل لديك. ويمكن ربط حسابات التواصل الاجتماعي الخاصة بك، ومشاركة الفيديو هناك على الفور. الخلاصة وبهذا يكون قد أصبح لديك الآن دمية متحركة بالكامل بين يديك، وأنشأت الفيديو التعليمي الأول باستخدام برنامج Adobe Character Animator، بعد أن تعلّمت في هذا المقال أساسيات إنشاء دمية متحركة انطلاقًا من شخصية ساكنة باستخدام برنامج Adobe Character Animator، وذلك بدءً بمرحلة الحصول على الشخصية المراد العمل عليها، مرورًا بالمتطلبات التي تحتاج إليها لفعل ذلك، وأهم الخطوات الواجب المرور عليها، وصولًا إلى كيفية تصدير العمل المنجز في شكل مقطع فيديو أو صورة. والآن يكون قد حان الوقت لتجرب هذا البرنامج. وإذا أردت تخطي جزء التحويل الشخصية إلى دمية، فيمكنك الحصول على الشخصية Mr. Geekson المجانية تمامًا والجاهزة للتحميل، ثم تضمينها في برنامج Adobe Character Animator. ترجمة -وبتصرّف- للمقال Creating Adobe Character Animator Puppet from Static Character: The Basics لصاحبته Iveta Pavlova.
-
رأينا في المقال السابق أنه من الممكن بناء شبكات محلية LAN كبيرة نسبيًا باستخدام الجسور bridges ومبدّلات LAN، لكن هذه الأساليب كانت محدودة في قدرتها على التوسُّع والتعامل مع عدم التجانس. سيُقدّم هذا الفصل بعض الطرق لتجاوز قيود الشبكات ذات الجسور، مما يمكّننا من بناء شبكات كبيرة وغير متجانسة بتوجيهٍ فعّال نسبيًا. سيُشار إلى هذه الشبكات باسم الشبكات المتشابكة internetworks، وسنواصل مناقشة كيفية إنشاء شبكة متشابكة عالمية حقًا في الباب التالي، لكننا سنكتشف الأساسيات حاليًا. ما هي الشبكة المتشابكة Internetwork؟ نستخدم مصطلح شبكة متشابكة، أو أحيانًا الإنترنت بحرف i صغير، للإشارة إلى مجموعة عشوائية من الشبكات المترابطة لتوفير نوعٍ من خدمة توصيل رزم من مضيف إلى مضيف host-to-host packet delivery service. فقد تنشئ مثلًا شركة لها العديد من المواقع sites شبكةً متشابكةً خاصة، من خلال ربط الشبكات المحلية في مواقعها المختلفة بروابط من نقطة لنقطة مؤجَّرة من شركة الهاتف. عندما نتحدّث عن الشبكة المتشابكة العالمية المستخدمة على نطاق واسع والتي تتّصل بها نسبة كبيرة من الشبكات الآن، فسنسمّيها الإنترنت بحرف I كبير. سنتعرف على مبادئ استخدام الشبكة المتشابكة "بحرف i صغير" تماشيًا مع نهج المبادئ الأولى لهذا الكتاب، ولكننا سنوضح هذه الأفكار بأمثلة من العالم الحقيقي من الإنترنت Internet "بحرف I كبير". هناك جزء آخر من المصطلحات قد يكون مربكًا وهو الاختلاف بين الشبكات networks، والشبكات الفرعية subnetworks، والشبكات المتشابكة internetworks. وهنا سنتجنب الشبكات الفرعية subnetworks أو subnets إلى فصل لاحق. لنستخدم حاليًا مصطلح الشبكة للإشارة إمّا إلى شبكة متصلة مباشرةً، أو شبكة تبديل switched network من النوع المُوضَّح سابقًا. تستخدم هذه الشبكة تقنيةً واحدةً، مثل 802.11 أو إيثرنت. والشبكة المتشابكة هي مجموعة مترابطة من هذه الشبكات، حيث نشير أحيانًا إلى الشبكات الأساسية التي نشبك بينها بشبكات فيزيائية physical networks. والإنترنت هو عبارة عن شبكة منطقية logical network مبنيّة على مجموعة من الشبكات الفيزيائية. ويبقى النظر إلى مجموعة مقاطع الإيثرنت المتصٍّلة بجسور أو مبدّلات على أنها شبكة واحدة. يوضح الشكل السابق مثالًا عن شبكة متشابكة يُشار إليها أحيانًا بأنها "شبكةٌ من الشبكات" لأنها تتكون من الكثير من الشبكات الأصغر. حيث نرى في هذا الشكل شبكة إيثرنت وشبكة لاسلكية ورابط من نقطة لنقطة، وكلٌّ منها هي شبكة ذات تقنية مختلفة. ويَرمز حرف H إلى مضيف host كما يَرمز حرف R إلى موجّه router. تسمى العقد التي تربط بين الشبكات موجّهات. كما يُطلق عليها أحيانًا اسم بوابات gateways، ولكن نظرًا لاحتواء هذا المصطلح على دلالات أخرى عديدة، سنستخدم مصطلح موجّه فقط. بروتوكول الإنترنت Internet Protocol هو الأداة الرئيسية المُستخدمة اليوم لبناء شبكات متشابكة غير متجانسة وقابلة للتوسّع، وقد عُرف هذا البروتوكول في الأصل باسم بروتوكول خان-سيرف Kahn-Cerf تيمُّنًا بمخترعَيه. وتتمثل إحدى طرق التفكير في IP في أنه يعمل على جميع العُقد (المضيفين والموجّهات) في مجموعة من الشبكات ويُحدِّد البنية التحتية التي تسمح لهذه العقد والشبكات بالعمل في صورة شبكة متشابكة منطقيّة واحدة. حيث يوضح الشكل السابق كيفية اتصال المضيفين H5 وH8 منطقيًا عن طريق الإنترنت، بما في ذلك الرسم البياني للبروتوكول الذي يعمل على كلّ عقدة. لابد من ملاحظة أنّ البروتوكولات ذات المستوى الأعلى، مثل البروتوكولان TCP و UDP، تعمل عادةً فوق بروتوكول IP على المضيفين. حيث ETH هو البروتوكول الذي يشغَّل عبر شبكة إيثرنت. سيتناول الجزء المتبقّي من المقال جوانب مختلفة من بروتوكول IP. ويُعَدّ بروتوكول IP هو الحالة الأهم لدراستها ببساطة، بسبب حجم الإنترنت. وعلى الرغم من إمكانية بناء شبكة متشابكة لا تستخدم بروتوكول IP، فقد كانت هناك حلول بديلة في أيام الإنترنت الأولى. ويمكن القول بأن الإنترنت عبر بروتوكول الإنترنت هو البروتوكول الوحيد الذي واجه بالفعل مشكلة الحجم، وبالتالي فهو يوفّر أفضل دراسة حالة لبروتوكول التشبيك القابل للتوسع. نموذج الخدمة Service Model أفضل مكان للبدء به عند إنشاء شبكة متشابكة هو تحديد نموذج الخدمة الخاصة بها، أي خدمات مضيف إلى مضيف التي تريد تقديمها. ويتمثل السبب الرئيسي للاهتمام بتحديد نموذج خدمة لشبكة متشابكة، في عدم قدرتنا على توفير خدمة مضيف إلى مضيف إلا إذا كان من الممكن توفير هذه الخدمة بطريقة ما عبر كلّ شبكة من الشبكات الفيزيائية الأساسية. إذ ليس من الجيّد الإقرار بأنّ نموذج خدمة الشبكة المتشابكة الخاص بنا سيوفر تسليمًا مضمونًا لكلّ رزمة في 1 ميلي ثانية أو أقل، وكان هناك تقنيات شبكة أساسية يمكنها تأخير الرزم عشوائيًا. لذلك كانت الفلسفة المُستخدمة في تحديد نموذج خدمة IP هي جعله غير متّسق بما يكفي، بحيث تستطيع أيّ تقنية شبكة قد تظهر في الشبكة المتشابكة تقديمَ الخدمة اللازمة. يمكن عدّ نموذج خدمة IP مكوَّنًا من جزأين هما: مخطط العنوَنة addressing scheme، والذي يوفِّر طريقةً لتحديد جميع المضيفين في الشبكة المتشابكة، ونموذج مخطط البيانات datagram (عديم الاتصال) لتسليم البيانات. حيث يُطلق على نموذج الخدمة هذا أحيانًا اسم أفضل جهد best effort لأنه على الرغم من بذل IP قصارى جهده لتقديم مخططات البيانات، إلا أنه لا يقدّم أيّ ضمانات. سنؤجّل مناقشة نظام العنونة في الوقت الحالي ونشرح أولًا نموذج تسليم البيانات data delivery. تسليم مخطط البيانات Datagram Delivery يُعَد مخطط بيانات IP أساسيًا لِبروتوكول الإنترنت. وللتذكير فإنَّ مخطّط البيانات عبارة عن رزمة مرسَلة بطريقة عديمة الاتصال connectionless عبر الشبكة، إذ يحمل كلّ مخطط بيانات معلومات كافية للسماح للشبكة بتمرير الرزمة إلى وجهتها الصحيحة. أي ليست هناك حاجة لأية آلية إعداد مُسبَقة لإخبار الشبكة بما يجب القيام به عند وصول الرزمة. فما عليك سوى إرسالها، وستبذُل الشبكة قصارى جهدها لإيصالها إلى الوجهة المطلوبة. وبالتالي المعنى من نموذج الخدمة أفضل جهد أنه إذا حدث خطأٌ ما وفُقدت الرزمة أو تلِفت أو سُلِّمت بصورة خاطئة أو فشلت بأيّ شكلٍ من الأشكال في الوصول إلى وجهتها المقصودة، فلن تفعل الشبكة شيئًا لأنها بذلت قصارى جهدها، وهذا كلّ ما في الأمر. إذ لا تحاول الشبكة التعافي من الفشل، ويسمى هذا أحيانًا بـخدمة غير موثوقة unreliable service. تُعتبر خدمة أفضل جهد عديمة الاتصال أبسط خدمة يمكنك طلبها من الشبكة المتشابكة، إذ تكمن قوتها في هذه النقطة. فإذا قدمّت خدمةً بأفضل جهد عبر شبكة توفّر خدمةً موثوقة مثلًا، فلا بأس بذلك، إذ سينتهي بك الأمر بخدمة بأفضل جهد والتي وُجدت لتسليم الرزم بشكل دائم. وإذا كان لديك نموذج خدمة موثوق عبر شبكة غير موثوقة، فسيتعيّن عليك وضع الكثير من الوظائف الإضافية في الموجّهات لتعويض أوجه النقص في الشبكة الأساسية. ولهذا، لابدّ من الحفاظ على الموجّهات بسيطةً قدر الإمكان، وهذا أحد أهداف تصميم بروتوكول IP الأصلية. كثيرًا ما يُشار إلى قدرة بروتوكول IP على تجاوز أيّ شيء بأنها واحدة من أهم خصائصه. والجدير بالذكر أنّ العديد من التقنيات التي تشغّل بروتوكول IP عليها اليوم لم تكن موجودةً عندما اختُرِع IP. ولم تُخترَع بعد أيّ تقنية شبكاتٍ أثبتت غرابتها الشديدة بالنسبة لبروتوكول IP. إذ يمكن وحسب المبدأ تشغيل بروتوكول IP عبر شبكة تنقل الرسائل باستخدام الحمام الزاجل. لا يعني التسليم بأفضل جهد إمكانية ضياع الرزم فقط. إنما يمكن في بعض الأحيان تسليمها مخالفةً للترتيب، وفي بعض الأحيان يمكن تسليم نفس الرزمة أكثر من مرّة بالتالي يجب أن تكون البروتوكولات أو التطبيقات ذات المستوى الأعلى التي تعمل فوق بروتوكول IP على دراية بكلّ أوضاع الفشل المحتملة هذه. شبكات L2 مقابل L3 يمكن التعامل مع شبكة إيثرنت على أنها رابط من نقطة لنقطة يربط بين زوجٍ من المبدّلات مع شبكة من المبدّلات المتشابكة لتكوّن شبكة إيثرنت مبدَّلة Switched Ethernet، ويُعرَف هذا الضبط configuration أيضًا باسم شبكة L2. ولكن يمكن التعامل مع شبكة إيثرنت (حتى عندما تُرتَّب في ضبط من نقطة لنقطة بدلًا من شبكة CSMA / CD مشتركة) على أنها شبكة تربط زوجًا من الموجهات، مع شبكة من هذه الموجهات التي تشكّل الإنترنت. يُعرف هذا الضبط أيضًا باسم شبكة L3. يتمثّل إيثرنت من نقطة لنقطة في رابط وشبكة في نفس الوقت وهذا أمرٌ مربِك (وإن كانت شبكة تافهة ثنائية العقد)، فقد تكون متصّلةً بزوج من المبدّلات L2 التي تشغّل خوارزمية الشجرة الممتدة، أو متصلةً بزوج من الموجّهات L3 التي تشغّل بروتوكول IP (بالإضافة إلى بروتوكولات التوجيه التي ستوضّح لاحقًا). إذًا لماذا تفضّل ضبطًا على الآخر؟ يعتمد ذلك جزئيًا على ما إذا كنت تريد أن تكون الشبكة مثل نطاق بثّ إذاعي (إذا كانت الإجابة نعم، فاختر L2، وما إذا كنت تريد أن يكون المضيفون المتصلين بالشبكة موجودون على شبكات مختلفة (إذا كانت الإجابة نعم، فاختر L3. الخبر السار هو أنه عندما تفهم تمامًا الآثار المترتِّبة عن هذه الازدواجية، فستكون قد تجاوزت عقبةً رئيسية في إتقان شبكات تبديل الرُّزم الحديثة. صيغة الرزمة Packet Format من الواضح أنّ جزءًا أساسيًا من نموذج خدمة IP هو نوع الرزم الممكن حملها. حيث يتكون مخطط بيانات IP مثل معظم الرزم، من ترويسة متبوعة بعدد من بايتات البيانات. حيث تظهر صيغة العنوان في الشكل التالي. نلاحظ اعتماد أسلوب مختلف لتمثيل الرزم عن ذلك الذي استخدمناه في الفصول السابقة. لأنّ صيَغ الرزم في طبقة الإنترنت وما فوقها مصمَّمة غالبًا لتتماشى مع حدود 32 بت لتبسيط مهمة معالجتها في البرمجيات. وبالتالي فالطريقة الشائعة لتمثيلها (المستخدَمة في طلبات الإنترنت للتعليقات Internet Requests for Comments على سبيل المثال) هي رسمُها على شكل سلسلة متتالية من كلمات مؤلَّفة من 32 بت. حيث تُرسَل الكلمة العليا أولًا، ليُرسل البايت الموجود في أقصى اليسار من كلّ كلمةٍ تحديدُا أولًا، وبهذا يمكن بسهولة التعرف على الحقول التي يبلغ طولها مضاعفات 8 بت في هذا التمثيل. كما يمكن تحديد أطوال الحقل من خلال النظر إلى مواضع البت المحدَّدة في الجزء العلوي من الرزمة في الحالة الفردية عندما لا تكون الحقول من مضاعفات 8 بت الزوجية. لاحظ أن نموذج مخطط البيانات البسيط للتسليم بأفضل جهد ما يزال يحتوي على بعض الميزات الدقيقة، حيث يحدِّد حقل الإصدار Version إصدار IP، وإصدار بروتوكول IP هو 4 والذي يُسمى عادةً IPv4. لاحظ أنّ وضع هذا الحقل في بداية مخطَّط البيانات يجعل من السهل إعادة تعريف كلّ شيء آخر في صيغة الرُّزمة في الإصدارات اللاحقة، حيث يبدأ برنامج معالجة الترويسة بالنظر إلى الإصدار ثمّ يتفرّع لمعالجة بقيّة الرزمة وفقًا للصيغة المناسبة. ويحدِّد الحقل التالي HLen طول الترويسة المقدَّر بكلمات 32 بت، ليكون طول الترويسة 5 كلمات (20 بايت) في حالة عدم وجود الخيارات والتي تحدث في معظم الأحيان. احتوى حقل TOS (نوع الخدمة type of service ذو 8 بتات على عددٍ من التعريفات المختلفة على مرّ السنين. ولكنّ وظيفته الأساسية تتمثّل بالسماح بمعالجة الرزم بصورة مختلفة بناءً على احتياجات التطبيق. فقد تحدِد قيمة الحقل TOS فيما إذا كان ينبغي وضع الرزمة في رتلٍ خاص ذو تأخير منخفض أم لا. تحتوي 16 بت التالية من الترويسة حقلَ Length الذي يمثِّل طول مخطَّط البيانات بما في ذلك الترويسة. ويَحسب حقل Length عدد البايتات بدلًا من عدد الكلمات words على عكس حقل HLen. وبالتالي الحد الأقصى لحجم مخطط بيانات IP هو 65.535 بايتًا. ولكن من الممكن ألا تدعم الشبكة الفيزيائية التي يعمل بروتوكول IP عليها مثل هذه الرزم الطويلة، لذلك يدعم IP عملية التجزئة fragmentation وإعادة التجميع reassembly، بحيث تحتوي الكلمة الثانية من العنوان على معلومات حول التجزئة، وسنتحدّث عن تفاصيل استخدامها لاحقًا. بالانتقال إلى الكلمة الثالثة في الترويسة حيث يكون البايت التالي هو حقل TTL (عُمر الرزمةtime to live. والهدف من هذا الحقل هو التقاط الرزم التي تدور في حلقات توجيه ثم تجاهلها بدلًا من تركها تستهلك الموارد إلى أجلٍ غير مُسمى. يُضبط حقل TTL على عددٍ محدَّد من الثواني التي يُسمح فيها بالاحتفاظ بالرزمة، وستعمل الموجّهات الموجودة على طول المسار على تقليل قيمة هذا الحقل حتى يصل إلى القيمة 0. خفّضت معظم الموجهات قيمة الحقل TTL بمقدار 1 أثناء إعادة توجيه الرزمة، نظرًا لندرة بقاء الرزمة لمدّة 1 ثانية في الموجه، ولم يكن لدى جميع الموجهات إمكانية الوصول إلى ساعة مشتركة، وبالتالي أصبح هذا الحقل عدّادًا للقفزات أكثر من كونه مؤقِّتًا. لكنه لا يزال طريقةً جيدةً لالتقاط الرزم العالقة في حلقات التوجيه. حيث لا بد من توفُّر الدقة في ضبط هذا الحقل الأولي بواسطة المضيف المرسل، فإذا ضبطته على مستوٍ عالٍ جدًا فقد تدور الرزم كثيرًا قبل إهمالها، وإذا ضبطته على مستوٍ منخفض جدًا من الممكن ألا تصل الرزم إلى وجهتها، وبالتالي القيمة 64 هي القيمة الافتراضية الحالية. حقل البروتوكول Protocol هو ببساطة مفتاح **فكّ تعدُّد ** demultiplexing، حيث يُحدِّد بروتوكول المستوى الأعلى الذي يجب أن تُمرَّر إليه رزمة IP. وهناك قيمة محدَّدة لبروتوكول TCP، وهو بروتوكول التحكم في الإرسال Transmission Control Protocol، وهي 6، أما بروتوكول UDP، وهو بروتوكول مخطط بيانات المستخدم User Datagram Protocol، فقيمته هي 17، إلى جانب العديد من البروتوكولات الأخرى التي قد توجَد فوق بروتوكول IP في رسم البروتوكول البياني. يُحسَب حقل المجموع الاختباري Checksum من خلال عدّ عنوان IP بالكامل على أنه سلسلة من الكلمات ذات 16 بت، وإضافتها باستخدام حساب متمِّم الواحد، وأخذ متمِّم الواحد للنتيجة. وبالتالي عند تلف أيّ بت في الترويسة أثناء النقل، فلن يحتوي المجموع الاختباري على القيمة الصحيحة عند استلام الرزمة. ومن المنطقي تجاهل أيّ رزمة تفشل في المجموع الاختباري نظرًا لإمكانية احتواء الترويسة التالفة على خطأ في عنوان الوجهة، كما قد يُسلّم بصورة خاطئة نتيجةً لذلك. وتجدر الإشارة إلى أنّ هذا النوع من المجموع الاختباري لا يحتوي على نفس خصائص الكشف عن الأخطاء القوية مثل CRC، ولكن حسابه يُعَدّ أسهل بكثير في البرنامج. آخر حقلين مطلوبين في ترويسة الرزمة هما SourceAddr وDestinationAddr، ويُعَدّ الحقل DestinationAddr مفتاح تسليم مخطط البيانات، إذ تحتوي كلّ رزمة على عنوان كامل لوجهتها المقصودة بحيث يمكن اتخاذ قرارات إعادة التوجيه في كلّ موجّه. أمّا عنوان المصدر SourceAddr فهو مطلوب للسماح للمستقبِلين بتحديد ما إذا كانوا يريدون قبول الرزمة لتمكينهم من الرد أم لا. سنناقش عناوين IP لاحقًا، ولكن الشيء المهم في الوقت الحالي والواجب معرفته، أنّ بروتوكول IP يحدِّد حيِّز العناوين العالمية الخاصة به، بغضّ النظر عن الشبكات الفيزيائية التي يديرها، كما سنرى أنّ هذا هو أحد مفاتيح دعم عدم التجانس. وقد يكون هناك عدد من الخيارات في نهاية الترويسة، بحيث يمكن تحديد وجود أو عدم وجود الخيارات من خلال فحص حقل طول الترويسة HLen. ورغم ندرة استخدام الخيارات options، إلا أنه يجب على تطبيق IP الكامل التعامُل معها جميعًا. التجزئة Fragmentation وإعادة التجميع Reassembly تتمثل إحدى مشكلات توفير نموذج خدمة موحّد من مضيف إلى مضيف على مجموعة غير متجانسة من الشبكات، في ميلان كلّ تقنية شبكة إلى أن تكون لها فكرتها الخاصة عن حجم الرزمة. على سبيل المثال يمكن لشبكة الإيثرنت الكلاسيكية قبول رزم يصل طولها إلى 1500 بايت، ولكن قد توفّر الشبكات الأخرى الحديثة رزمًا أكبر "ضخمة جدًا jumbo" تحمل ما يصل إلى 9000 بايت حمولة. حيث يترك هذا خيارين لنموذج خدمة IP هما: التأكد من صغر جميع مخططات بيانات IP كفاية لتناسب رزمةً واحدةً على أيّ تقنية شبكة، أو توفير وسيلة يمكن من خلالها تجزئة الرزم وإعادة تجميعها عندما تكون كبيرةً جدًا، بحيث يمكن تمريرها عبر تقنية الشبكة المعطاة. تبيّن أنّ الخيار الأخير هو اختيار جيد، خاصةً عندما تفكِّر في حقيقة ظهور تقنيات شبكات جديدة دائمًا، إلى جانب حاجة بروتوكول IP إلى تشغيلها جميعًا؛ فهذا من شأنه جعل اختيار إطار صغير مناسب لحجم مخطط البيانات صعبًا. وهو ما يعني أيضًا أنّ المضيف لن يرسل رزمًا صغيرةً بلا داعٍ، ممّا يهدر حيّز النطاق التراسلي ويستهلك موارد المعالجة عن طريق طلب المزيد من العناوين لكلّ بايت من البيانات المرسَلة. الفكرة الأساسية هنا هي أنّ لكلّ نوع شبكة وحدة نقلٍ قصوى maximum transmission unit أو اختصارًا MTU، وهي أكبر مخطط بيانات IP يمكن حمله في إطار. تُعدّ وحدة MTU لحسن الحظ، في شبكات ATM أكبر بكثير من خليةٍ واحدة، إذ تملك تقنية ATM آلية تجزئة وإعادة تجميع خاصة بها، ويسمّى إطار طبقة الربط في شبكة ATM بـوحدة بيانات بروتوكول تقارب الطبقة الفرعية convergence-sublayer protocol data unit أو اختصارًا CS-PDU. نلاحظ أنّ قيمة وحدة MTU أصغر من أكبر حجم للرزمة على تلك الشبكة لأنّ مخطّط بيانات IP يحتاج إلى احتواء حمولة payload إطار طبقة الربط. قد يختار المضيف أيّ حجم يريده عندما يرسل مخطّط بيانات IP. والاختيار المعقول هو حجم وحدة MTU للشبكة التي يتّصل بها المضيف مباشرةً، لتكون التجزئة ضروريةً فقط إذا تضمّن المسار إلى الوجهة شبكةً ذات وحدة MTU أصغر. وإذا أعطى بروتوكول النقل الموجود أعلى بروتوكول IP رزمةً أكبر من حجم وحدة MTU المحلية، فيجب على مضيف المصدر تجزئتها. تحدث التجزئة عادةً في الموجّه عندما يتلقّى مخطَّط بيانات يريد تمريره عبر شبكة تملك وحدة MTU أصغر من مخطط البيانات المستلَم. حيث لابدّ من حمل جميع الأجزاء لنفس المعرّف في الحقل Ident، ليتمكّن المضيف المتلقّي من إعادة تجميع هذه الأجزاء. ويختار المضيف المرسل هذا المعرّف ليكون فريدًا بين جميع مخططات البيانات التي قد تصل إلى الوجهة من هذا المصدر خلال فترة زمنية معقولة، بحيث سيكون المضيف الذي يعيد تجميع الأجزاء قادرًا على التعرّف على الأجزاء التي تتكامل مع بعضها. نظرًا لاحتواء جميع أجزاء مخطط البيانات الأصلي على هذا المعرّف، وفي حال عدم وصول جميع الأجزاء إلى المضيف المستلم، فسيتخلّى المضيف عن عملية إعادة التجميع ويتجاهل الأجزاء التي وصلت فعلًا، كما لا يحاول بروتوكول IP استعادة تلك الأجزاء المفقودة. لفهم كل ما يحدث، وعلى فرض يريد المضيف H5 إرسال مخططَ بيانات إلى المضيف H8 في الشكل الموضّح سابقًا. وأنّ وحدة MTU هي 1500 بايت لشبكتي إيثرنت و802.11، و532 بايتًا لشبكة نقطة لنقطة. ثم يرسَل مخطط بيانات ذو 1420 بايتًا (20 بايتًا لترويسة IP بالإضافة إلى 1400 بايت من البيانات) من المضيف H5، ليمر عبر شبكتي 802.11 والإيثرنت الأولى بدون تجزئة، بينما يجب تجزئتها إلى ثلاثة مخطّطات بيانات في الموجّه R2. ليعيد الموجّه R3 بعد ذلك توجيه هذه الأجزاء الثلاثة عبر شبكة الإيثرنت الثانية إلى المضيف الوجهة. يوضح الشكل السابق هذا الوضع، إضافةً إلى تعزيز نقطتين مهمتين: كلّ جزء هو في حدّ ذاته مخطط بيانات IP مستقل يُنقَل عبر سلسلة من الشبكات الفيزيائية مستقلًا عن الأجزاء الأخرى. يُعاد تغليف كلّ مخطط بيانات IP لكلّ شبكة فيزيائية تنتقل عبرها. يمكن فهم عملية التجزئة بالتفصيل من خلال النظر في حقول ترويسة كلّ مخطط بيانات، كما هو الحال في الشكل السابق. حيث تحتوي الرزمة غير المُجزأة unfragmented -والموضحة في القسم (أ) من الشكل السابق-، على 1400 بايت من البيانات وعلى ترويسة IP مؤلَّفة من 20 بايت. يجب تجزئة الرزمة عندما تصل إلى الموجّه R2، الذي يحتوي على وحدة MTU تبلغ 532 بايتًا. حيث تَترك وحدة MTU التي تتألف من 532 بايت 512 بايتًا للبيانات بعد ترويسة بروتوكول IP المكوَّنة من 20 بايتًا، ولهذا يحتوي الجزء fragment الأول على 512 بايت من البيانات. ويضبط الموجّه M بت في حقل الرايات Flags، مما يعني وجود المزيد من الأجزاء التي يجب اتّباعها، كما يضبط الموجّه حقلَ الإزاحة Offset بالقيمة 0، نظرًا لاحتواء هذا الجزء على الجزء الأول من مخطط البيانات الأصلي. وتبدأ البيانات المنقولة في الجزء الثاني بالبايت رقم 513 من البيانات الأصلية، لذلك يُضبَط حقل Offset في هذه الترويسة بالقيمة 64، وهو 512/8. لماذا القسمة على 8؟ تبعًا لقرار مصممي بروتوكول IP وجوب حدوث التجزئة دائمًا على حدود 8 بايت، مما يعني أنّ حقل Offset يعَدّ قطعًا chunks ذات 8 بايتات وليس البايتات. يحتوي الجزء الثالث على آخر 376 بايت من البيانات، والإزاحة offset الآن هي 2 × 512/8 = 128. حيث لم يُضبَط البت M لكون هذا هو الجزء الأخير. لاحظ أنّ عملية التجزئة تتمّ بطريقة قد تتكرّر إذا وصل جزءٌ ما إلى شبكة أخرى باستخدام وحدة MTU الأصغر. حيث تنتج التجزئة مخططات بيانات IP أصغر وصالحة، يمكن إعادة تجميعها بسهولة في مخطط البيانات الأصلي عند الاستلام، بغضّ النظر عن ترتيب وصولها. وتحدث إعادة التجميع عند المضيف المستقبل وليس في كلّ موجّه. تُعَدّ عملية إعادة تجميع IP معقدة، إذ سيبقى المستقبِل يحاول إعادة تجميع مخطَّط البيانات في حالة فقد جزء fragment واحد، ليستسلم في النهاية، وحينها سيتعيّن عليه كنس مهملات الموارد التي استخدمها لإجراء إعادة التجميع الفاشلة. وقد يكون الحصول على مضيف لربط الموارد بلا داعٍ أساسًا لهجوم الحرمان من الخدمة denial-of-service attack. لذلك يُعَد تجنب تجزئة IP أمرًا جيدًا، حيث يُشجَّع المضيفون الآن بشدة على تطبيق path MTU discovery اكتشاف مسار وحدة MTU، وهي عملية يتم من خلالها تجنّب التجزئة عن طريق إرسال رزم صغيرة بما يكفي لاجتياز الرابط مع أصغر وحدة MTU في المسار من المرسل إلى المستقبِل. العناوين العامة Global Addresses من بين الأشياء التي يوفّرها نموذج خدمة IP هي مخطط العنونة addressing scheme. إذا أردت أن تكون قادرًا على إرسال البيانات إلى أيّ مضيف على أيّ شبكة، فيجب أن تكون هناك طريقة لتحديد جميع المضيفين. وبالتالي أنت بحاجة إلى مخطّط عنوَنة عام لا يوجد فيه مضيفان لهما نفس العنوان. ويُعَدّ التفرّد العام Global uniqueness هو الخاصيّة الأولى الواجب توفيرها في مخطَّط العنوَنة. تُعَدّ عناوين إيثرنت فريدةً عالميًا، ولكن هذا وحده غير كاف لنظام العنوَنة في شبكة متشابكة كبيرة. حيث أنَّ عناوين الإيثرنت مُسطّحة flat أيضًا، مما يعني عدم امتلاكها لأية بنية structure، كما توفّر أدلةً قليلةً جدًا لبروتوكولات التوجيه. ومع ذلك، تملك عناوين إيثرنت بنيةً لأغراض الإسناد assignment، حيث يحدّد أول 24 بتًا الشركة المصنعة، ولكن هذا لا يوفِّر معلومات مفيدةً لبروتوكولات التوجيه، نظرًا لعدم وجود علاقة لهذه البنية بمخطط الشبكة. إنّ عناوين IP هرميةٌ hierarchical، وذلك يعني أنها تتكوّن من عِدّة أجزاء تتوافق مع نوع الهرمية الموجودة في الشبكة المتشابكة internetwork. إذ تتكوّن عناوين IP من جزأين، يشار إليهما عادةً بجزء الشبكة network وجزء المضيف host. وهذه بنية منطقية إلى حدٍ ما للشبكة المتشابكة التي تتكوّن من عدّة شبكات مترابطة. حيث يحدَّد جزءُ الشبكة من عنوان IP الشبكةَ التي يتصل بها المضيف، أي أنّ جميع المضيفين المتصلين بنفس الشبكة لديهم نفس جزء الشبكة في عنوان IP الخاص بهم. ويُعرّف جزء المضيف كلّ مضيف بصورة فريدة على تلك الشبكة. وبالتالي سيكون لعناوين المضيفين على الشبكة ذاتها نفس جزء الشبكة وأجزاء مضيفٍ مختلفة. لاحظ أنّ الموجّهات في الشكل السابق تتّصل بشبكتين. أي يجب أن يكون لديها عنوان على كلّ شبكة، بمعنى عنوان لكلّ واجهة. يحتوي الموجّه R1 على سبيل المثال، والذي يقع بين شبكة لاسلكية وشبكة إيثرنت، على عنوان IP على واجهة الشبكة اللاسلكية التي يكون جزء الشبكة الخاص بها هو نفسه لجميع المضيفين على تلك الشبكة. كما يحتوي أيضًا على عنوان IP على واجهة شبكة الإيثرنت التي لها نفس جزء الشبكة للمضيفين الموجودين على هذه الشبكة. وبالتالي ومع الأخذ في الحسبان إمكانية تنفيذ الموجّه router على أساس مضيفٍ بواجهتيْ شبكة، فمن الأدقّ التفكير في عناوين IP على أنها تنتمي إلى واجهات interfaces أكثر من كونها منتميةً إلى مضيفين hosts. كيف تبدو هذه العناوين الهرمية؟ تُعَدّ أحجام الجزأين غير متماثلة لجميع العناوين، على عكس بعض الأشكال الأخرى للعناوين الهرمية. وقد قُسّمت عناوين IP إلى ثلاثة أصناف classes مختلفة، كما هو موضح في الشكل الآتي، حيث يحدّد كلّ منها أجزاء شبكة وأجزاء مضيف مختلفة الحجم، وهناك أيضًا عناوين من الصنف D تحدِّد مجموعة البث المتعدّد multicast وعناوين الصنف E غير المستخدمة حاليًا. ويبلغ طول العنوان 32 بتًا في جميع الحالات. يحدَّد صنف عنوان IP في البتات القليلة الأعلى أهميةً. فإذا كان البت الأول هو 0، فهو عنوان من الصنف A. وإذا كان البت الأول 1 والثاني 0، فهو عنوان من الصنف B. أمّا إذا كان البتان الأوليان 1 والثالث 0، فسيكون عنوانًا من الصنف C. وبالتالي من بين ما يقرب 4 مليارات عنوان IP ممكن، سيكون نصفها من الصنف A، ورُبعها من الصنف B، وثُمنها من الصنف C. يخصّص كل صنف عددًا معينًا من البتات لجزء الشبكة من العنوان والباقي من أجل جزء المضيف، حيث تحتوي شبكات الصنف A على 7 بتات لجزء الشبكة و 24 بت لجزء المضيف، ممّا يعني أنّه من غير الممكن تواجُد أكثر من 126 شبكة من الصنف A (القيمتان 0 و127 محجوزة)، ولكن يمكن لكلٍ منها استيعاب ما يصل إلى 224−2 (حوالي 16 مليون) مضيف (هناك قيمتان محجوزتان). تُخصِّص عناوين الصنف B للشبكة 14 بتًا و16 بتًا للمضيف، مما يعني أنّ كلّ شبكة من الفئة B تملك حيزًا لحوالي 65,534 مضيفًا. كما تحتوي عناوين الصنف C على 8 بتات فقط للمضيف و21 بتًا لجزء الشبكة، لذلك فقد تحتوي شبكة الصنف C على 256 معرّف مضيفٍ فريد فقط، مما يعني وجود 254 مضيفًا متصلًا فقط، فمعرّف المضيف 255 محجوز للبث الإذاعي broadcast، و0 ليس رقم مضيفٍ صالح. ولكن يدعم مخطَّط العنوَنة 221 شبكة من الصنف C. يتمتع نظام العنونة هذا بالكثير من المرونة ظاهريًا، مما يسمح باستيعاب الشبكات ذات الأحجام المختلفة بصورة كبيرة وبكفاءة إلى حدٍ ما. وقد كانت الفكرة الأصلية فيه هي أن الإنترنت يتألف من عددٍ صغير من الشبكات الواسعة wide area networks (ستكون هذه شبكات من الصنف A)، وعددٍ متواضع من شبكات بحجم الموقع (الحرم الجامعي) (ستكون شبكات من الصنف B)، إلى جانب عدد كبير من الشبكات المحلية LANs (ستكون هذه شبكات من الصنف C). ولكن بعدها تبين أنّ ذلك لم يكن مرنًا بدرجة كافية -كما سنرى بعد قليل-، حيث أنّ عناوين IP اليوم عديمة التصنيف classless. من المفيد النظر في بعض الأمور العملية قبل النظر في كيفية استخدام عناوين IP، مثل كيفية كتابتها. إذ تُكتَب عناوين IP بأربعة أعداد صحيحة تفصل بينها نقاط. حيث يمثِّل كلّ عدد صحيح القيمة العشرية الموجودة في بايت واحد من العنوان، بدءًا من البايت الأكثر أهميةً، مثل العنوان 171.69.210.245. من المهم عدم الخلط بين عناوين IP وأسماء نطاقات الإنترنت Internet domain names، والتي هي أيضًا ذات تسلسل هرمي. إذ تميل أسماء النطاقات إلى أن تكون سلاسل ASCII مفصولٌ بينها بنقاط، مثل cs.princeton.edu. والشيء المهم في عناوين IP هو أنها تُنقل في ترويسات رزم IP، وتُستخدم في موجِّهات IP لاتخاذ قرارات التمرير. تمرير مخطط البيانات Datagram في بروتوكول IP نحن الآن جاهزون للنظر في الآلية الأساسية التي تُمرِر موجّهات IP من خلالها مخططات البيانات في شبكةٍ متشابكة. وتذكر أنّ عملية تمرير forwarding كما ذكرنا في قسم سابق، هي عملية أخذ رزمة من مدخل وإرسالها إلى مخرجٍ مناسب. بينما التوجيه routing، فهو عملية بناء الجداول التي تسمح بتحديد مخرج الرزمة الصحيح. حيث تركز المناقشة هنا على التمرير، اذ سنناقش التوجيه لاحقًا. إنّ النقاط الرئيسية الواجب الانتباه إليها أثناء مناقشة تمرير مخططات بيانات IP هي: يحتوي كلّ مخطط بيانات IP على عنوان IP خاص بالمضيف الوجهة. يعرِّف جزء الشبكة من عنوان IP بصورة فريدة شبكةً فيزيائية تشكل جزءًا من الإنترنت الأكبر. جميع المضيفين والموجّهات التي تشترك بنفس جزء الشبكة من عنوانها متصّلون بنفس الشبكة الفيزيائية ويمكنهم بالتالي التواصل مع بعضهم بعضًا عن طريق إرسال الإطارات عبر تلك الشبكة. تحتوي كلّ شبكة فيزيائية تشكّل جزءًا من الإنترنت على موجّهٍ واحد على الأقل، وهو متصّل أيضًا بشبكة فيزيائية أخرى على الأقل، أي يمكن لهذا الموجّه تبادل الرزم مع المضيفين أو الموجّهات الموجودة على أيٍّ من الشبكتين. لذلك يمكن معالجة تمرير مخطّطات بيانات IP بالطريقة التالية: يُرسَل مخطط البيانات من مضيف المصدر إلى مضيف الوجهة، وقد يمرّ عبر عدة موجّهات على طول الطريق. حيث تحاول أيّ عقدة في البداية -سواءً كانت مضيفًا أو موجهًا- تحديد ما إذا كانت متصلةً بالشبكة الفيزيائية نفسها الموجودة فيها الوجهة، وتقارن جزء الشبكة من عنوان الوجهة مع جزء الشبكة من عنوان كلّ واجهة من واجهات الشبكة الخاصة بها (عادةً ما يكون للمضيفين واجهة واحدة فقط، بينما تحتوي الموجّهات عادةً على اثنين أو أكثر، نظرًا لاتصالها عادةً بشبكتين أو أكثر). فإذا حدث تطابق، هذا يعني أنّ الوجهة تقع على نفس الشبكة الفيزيائية التي تقع عليها الواجهة، ويمكن تسليم الرزمة مباشرةً عبر تلك الشبكة. أمّا إن لم تكن العقدة متصلةً بنفس شبكة عقدة الوجهة الفيزيائية، فستحتاج إلى إرسال مخطَّط البيانات إلى الموجِّه. كما سيكون لكلّ عقدة القدرة على اختيار موجِّه من عدة موجّهات، ولذلك فهي بحاجة إلى اختيار أفضلها، أو على الأقل اختيار موجّهٍ يعطيها فرصةً معقولةً لتقريب مخطط البيانات من وجهتها. يُعرف الموجه الذي تختاره العقدة باسم موجّه القفزة التالية next hop router، حيث يعثر الموجّه على العقدة التوجيهية التالية الصحيحة من خلال الرجوع إلى جدول التمرير الخاص به. وجدول التمرير هو مجرّد قائمة من أزواج NetworkNum NextHop. وغالبًا ما تحوي جداول إعادة التوجيه عمليًا على بعض المعلومات الإضافية المتعلقة بالعقدة التوجيهية التالية. كما يوجد هناك أيضًا موجّه افتراضي default router يُستخدم إذا لم تتطابق أية مدخلةٍ من مدخلات الجدول مع رقم شبكة الوجهة. قد يكون من المقبول تمامًا بالنسبة للمضيف، أن يكون لديه موجّه افتراضي ولا شيء آخر، وهذا يعني أنّ جميع مخططات البيانات الموجَّهة للمضيفين غير المتصلين بالشبكة الفيزيائية التي أُرفِق المضيف المرسِل بها ستُرسَل عبر الموجه الافتراضي. يمكن وصف خوارزمية إعادة توجيه مخطط البيانات بالطريقة التالية: if (رقم شبكة الوجهة = رقم الشبكة الخاصة بإحدى واجهاتي) then سلِّم الرزمة إلى الوجهة عبر تلك الواجهة else if (رقم شبكة الوجهة موجود في جدول التمرير الخاص بي) then سلِّم الرزمة إلى العقدة التوجيهية التالية else سلِّم الرزمة إلى الموجّه الافتراضي بالنسبة لمضيفٍ بواجهة واحدة وموجّهٍ افتراضي فقط في جدول التمرير الخاص به، فهذا يبسَّط إلى: if (رقم شبكة الوجهة = رقم شبكتي) then سلِّم الرزمة إلى الوجهة مباشرةً else سلِّم الرزمة إلى الموجه الافتراضي لنشاهد الآن كيف يعمل هذا في مثال الشبكة المتشابكة الموضَّحة في الشكل الآتي. افترض أولًا أنّ المضيف H1 يريد إرسال مخطط بيانات إلى المضيف H2، والمضيفين H1 وH2 لهما نفس رقم الشبكة في عنوان IP الخاص بهما، نظرًا لوجودهم على نفس الشبكة الفيزيائية. وبالتالي يستنتج المضيف H1 إمكانية توصيل مخطط البيانات مباشرةً إلى المضيف H2 عبر الإيثرنت. والمشكلة الوحيدة التي تحتاج إلى حلّ هي كيفية اكتشاف المضيف H1 لعنوان شبكة الإيثرنت الصحيح للمضيف H2 (سنعالج آلية الحلّ هذه لاحقًا). افترِض الآن أنّ المضيف H5 يريد إرسال مخطّط بيانات إلى المضيف H8. يملك هذان المضيفان أرقامَ شبكة مختلفة نظرًا لأنهما على شبكات فيزيائية مختلفة، لذلك يستنتج المضيف H5 حاجته إلى إرسال مخطط البيانات إلى موجّه. حيث يُعَدّ الموجّه R1 هو الخيار الوحيد (الموجه الافتراضي)، لذلك يرسل المضيف H1 مخطط البيانات عبر الشبكة اللاسلكية إلى الموجّه R1. بحيث يعرف الموجّه R1 أنه لا يمكنه تسليم مخطط بيانات مباشرةً إلى المضيف H8 لأن أيًا من واجهاته ليست على نفس شبكة المضيف H8. افترِض أنّ الموجّه الافتراضي الخاص بالموجّه R1 هو الموجّه R2، حيث يرسل الموجّه R1 مخطط البيانات إلى الموجّه R2 عبر شبكة الإيثرنت، وبافتراض احتواء الموجِّه R2 على جدول التمرير الموضَّح في الجدول التالي، فسيبحث عن رقم شبكة المضيف H8 (الشبكة 4)، ويمرر مخطط البيانات عبر شبكة من نقطة لنقطة إلى الموجه R3، كما يقوم الموجه R3 بتمرير مخطط البيانات مباشرةً إلى المضيف H8 نظرًا لوجود الموجّه R3 على نفس شبكة المضيف H8. 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; } رقم الشبكة NetworkNum العقدة التوجيهية التالية NextHop 1 R1 4 R3 لاحظ أنه من الممكن تضمين معلوماتٍ عن الشبكات المتصلة مباشرةً في جدول التمرير. حيث يمكن تسمية واجهات شبكة الموجّه R2 مثل الواجهة 0 للرابط من نقطة لنقطة (الشبكة 3) والواجهة 1 لشبكة الإيثرنت (الشبكة 2). إذًا سيكون لدى الموجّه R2 جدول التمرير الموضح في الجدول التالي: رقم الشبكة NetworkNum العقدة التوجيهية التالية NextHop 1 R1 2 Interface 1 3 Interface 0 4 R3 وبالتالي يعرف الموجّه R2 ما يجب فعله عندما يصادف أيّ رقم شبكةً في رزمة. فإمّا أن تكون هذه الشبكة متصلة مباشرةً بالموجّه R2، وفي هذه الحالة يمكن تسليم الرزمة إلى وجهتها عبر تلك الشبكة. أو يمكن الوصول إلى الشبكة عبر بعض موجّهات القفزة التالية التي قد يصل إليها الموجّه R2 عبر شبكة متصلة به. سيستخدم الموجّه R2 بروتوكول ARP الموصوف أدناه، في كلتا الحالتين للعثور على عنوان MAC الخاص بالعقدة التي ستُرسَل الرزمة إليها بعد ذلك. يُعَد جدول التمرير الذي يستخدمه الموجّه R2 بسيطًا بدرجة كافية تمكّن من ضبطه يدويًا. ولكن عادةً ما تكون هذه الجداول أعقد، ويمكن إنشاؤها عن طريق تشغيل أحد بروتوكولات التوجيه التي سيتم شرحها في فصل لاحق. لاحظ أيضًا أنه عادةً ما تكون أرقام الشبكة أطول في التطبيق العملي (128.96 مثلًا). يمكنك الآن رؤية كيف أدّت العنوَنة الهرمية -أي تقسيم العنوان إلى جزء شبكة وجزء مضيف- إلى تحسين قابلية التوسع لشبكةٍ كبيرة. حيث تحتوي الموجّهات الآن على جداول تمرير تحوي فقط قائمةً بمجموعة من أرقام الشبكة بدلًا من جميع العُقد في الشبكة. وهذا يعني أنّ الموجّه R2 على سبيل المثال يمكنه تخزين المعلومات اللازمة للوصول إلى جميع المضيفين في الشبكة (التي تحوي ثمانية مضيفين) في جدولٍ من أربع مدخلات فقط. إذ سيظل الموجه R2 بحاجة فقط إلى نفس المدخلات الأربعة حتى لو كان هناك 100 مضيف على كلّ شبكة فيزيائية، وهذه خطوة أولى جيدة في تحقيق قابلية التوسع scalability، على الرغم من كونها ليست الخطوة الأخيرة بأي حال من الأحوال. ترجمة -وبتصرّف- للقسم Internet من فصل Internetworking من كتاب Computer Networks: A Systems Approach. اقرأ أيضًا المقال السابق: شبكة الإيثرنت المبدلة Switched Ethernet التشبيك Internetworking بين أنواع مختلفة من الشبكات الحاسوبية
-
برنامج Adobe Character Animator هو إضافة رائعة لسحابة أدوبي Adobe Creative Cloud. هذه الشخصية المتحركة التي يمكن التحكم بها، يمكنها قيادة عروضك التقديمية، وشرح مسائلًا في صفك، كما قد تكون نجمة مؤتمرات الفيديو، أو تدرّس دروسًا على الإنترنت، وتقدّم مدونات الفيديو، وتشرح أحدث تقنيات الألعاب، وتستمر القائمة. تُعَد هذه الشخصية المتحركة أداةً سريعةً وسهلةً وقوية لإضافة الفائدة والمشاركة، وتزيد مهاراتك في التقديم الممتع، ومهارات العرض التقديمي المهني لمساعدتك في تحسين ظهورك ضمن مجال عملك. ما هو برنامج Adobe Character Animator؟ هو برنامج رسوم متحركة طوّرته شركة أدوبي، ميزته الأساسية هي إمكانية مزامنة حركاتك وصوتك من خلال الكاميرا والميكروفون، وتتمثّل فكرة هذا البرنامج في تمكين أي شخص من إنشاء رسوم متحركة دون استخدام مهارات متخصصة، أو أدوات معقدة، وهو حلٌّ رائع لبدء وإنشاء مقاطع فيديو الرسوم المتحركة خلال دقائق. ولكنه ليس للمبتدئين، كما أنه موجه لمقاطع الفيديو الممتعة فقط، إذ يمكن استخدامه لإنشاء مقاطع فيديو احترافية عالية الجودة أيضًا. واجهة برنامج Adobe Character Animator واجهة البرنامج سهلة، لكنك تحتاج في هذه المرحلة إلى فهم بعض الأشياء الأساسية، وهي: هناك ثلاثة أوضاع Modes وهي: Rig وRecord وStream، حيث يمكنك تحرير إعدادات الدمية عند النقر على الوضع Rig، أما وضع Record فهو تسجيل الرسوم المتحركة، في حين يُستخدَم الوضع Stream عند البث المباشر، أو عند إجراء مكالمة فيديو، إذ يمكن للمشاهدين رؤية دميتك بدلًا عنك عند البث المباشر، وهذا أمرٌ مدهش لأنها تحرك شفتيها بالتزامن مع صوتك، وتقلّد تعبيراتك، وحركاتك في الوقت الحقيقي. المنبّهات والساحبات Triggers and Draggers: يحتوي برنامج Character Animator على بعض الخيارات لمساعدتك في إنشاء حركات، وإجراءات مُعدَّة مسبقًا، هوناك إيماءات يد مختلفة يمكن تغييرها بنقرة بسيطة على لوحة المفاتيح، إذ يمكنك جعل دميتك ترفع إبهامها تلقائيًا بالنقر فوقها على سبيل المثال، وهذه هي المنبّهات Triggers؛ أما الساحبات Draggers فهي النقاط التي تمكّنك من التحكم بالدمية، فإطت وضعت ساحِبًا على يد دميتك، فسيمكنك نقل اليد حيث تريد بالنقر على عليها باستخدام المؤشر. وبالتالي يمكنك تحديد شيء ما، أو القيام بأي حركةٍ أخرى تريدها. تحريك الشفاه المتزامن Lipsync، والتعبيرات Expressions: هاتان الميّزتان آليتان، حيث تحتاج ميكروفونًا، وكاميرا ويب، وملف دمية مُسمّىً بطريقة صحيحة فقط. حيث ستُضاف الميزة Lipsync، والحركات، والتعبيرات إلى الخط الزمني Timeline الخاص بالفيديو عند تسجيل المشهد، ويمكنك تعديل الأجزاء الخاصة بالتسجيل، والأجزاء السابقة لتسجيل المشاهد حسب ما تريده بالضبط. توجد نافذة خصائص Properties على الجانب الأيمن من البرنامج، ويمكنك من خلالها تحديد عناصر محددة، مثل: Lipsync، والحركة Movement، والتعابير Expressions، وحركة العيون Eyes movement، وعناصر أخرى، إذ يمكنك تسجيلها وتعديل خصائصها. الخط الزمني Timeline: يُعَدّ الخط الزمني للرسوم المتحركة مهمًا جدًا وسهل الاستخدام، ويمكنك من خلاله تعديل تسجيلاتك دون الحاجة إلى تسجيلها مرةً أخرى، كما يمكن اختيار جزء من الرسوم المتحركة التي تريد تصديرها، واستخدام الخط الزمني لتحديد الدمى التي تريد التحكم فيها، إذ يمكنك جعل الرسوم المتحركة ذات الشخصيات المختلفة التواصل مع بعضها البعض، أو لجعل الرسوم المتحركة تتحرك بسلاسةٍ أكبر، كما يمكنك تعديل كل شيء ضمن الرسوم المتحركة باستخدام الجدول الزمني، مثل: مدة المنبّهات Triggers، والساحبات Draggers، وتعديل ميزة Lipsync، وموضع الشخصيّة، وتقريب Zooming الكاميرا، وغير ذلك. كيفية صنع دمى متحركة تحتاج أولًا إلى شخصيةٍ لتتابع حركاتك وتحرك شفتيها بالتزامن مع صوتك، وتُدعَى هذه الشخصية في عالم الرسوم المتحركة بالدمية Puppet، وهي شخصية كرتونية أُعِّدت لبرنامج Adobe Character Animator، وبنية الدمية مصنوعةٌ لتندمج اندماجًا مثاليًا مع هذا البرنامج، وبالتالي قد تتحدث الدمية، وتتحرك، وتعبّر عن المشاعر المختلفة. حيث يمكنك إمّا الحصول على قالب دمية مُعَد مسبقًا، أو إنشاء دميتك الخاصة (سنتحدّث عن هذين الخيارَين). إنشاء دمية متحركة باستخدام قالب دمية معد مسبقا Premade puppet template هناك مواقع مختلفة لتحصل منها على دمية مُعَدة مسبقًا، منها المجاني، مثل: Okay Samurai، ومكتبة الدمى المتحركة في موقع GraphicMama، والتي تتضمن أكثر من 100 دمية مُعَدة مسبقًا ضمن مجموعة متنوعة من الأنماط، ولها ميزات مختلفة حسب احتياجاتك. إذا قرّرت استخدام دمية معدَّة مسبقًا، فما عليك سوى تنزيلها، وفك ضغط ملفها المضغوط، بعدها شغّل برنامج Adobe Character Animator، وأنشئ مشروعًا جديدًا "New project". ثم انتقل إلى قائمة Menu، واختر Import، ثم حدّد ملف الدمية الذي له اللاحقة puppet، حيث يمكنك اختيار الدمية من خلال: وبالتالي ستظهر الدمية، مثل الشكل الآتي: إنشاء دمية متحركة باستخدام قوالب دمى مجانية Free Puppet Templates جرّب بعض هذه الدمى المجانية التالية ضمن رسومك المتحركة: دمية رسوم متحركة مجانية لرجل أعمال تتميز هذه الدمية بمجموعة ميزات تجعلها ذات مظهر احترافي وهذه الميزات هي: 14 إعدادًا مسبقًا للفم. إمساك أشياء. إجراء إيماءات. التفاف الرأس. المشي. دمية رسوم متحركة مجانية ذكورية صُنِعت هذه الدمية باستخدام الأسلوب المسطّح الحديث، وهو أسلوب رائجٌ جدًا في الوقت الحالي، وتتضمّن مجموعةً من الميزات الرائعة مجانًا، وهي: 14 إعدادًا مسبقًا للفم. إمساك الأشياء. إجراء إيماءات. التفاف الرأس. المشي. دمية رسوم متحركة لطيفة ومجانية لرجل أعمال يُعَدّ هذا القالب مناسبًا للعروض التقديمية، وهو مصمم باحترافية ويتميز بالميزات التالية: 14 إعدادًا مسبقًا للفم. إجراء إيماءات. إمساك الأشياء. دمية رسوم متحركة أنثوية مجانية يتميز هذا القالب بكل ما تحتاجه لتحريكه، إذ يتميز بما يلي: 14 إعدادًا مسبقًا للفم. إمساك الأشياء. إجراء إيماءات. التفاف الرأس. المشي. إنشاء دميتك الخاصة يمكنك إنشاء دميتك الخاصة بدلًا من استخدام دمىً مصنوعة مسبقًا، وستحتاج من أجل هذا الخيار إلى برنامج رسوميات للشخصيات، بالإضافة إلى بعض الأصول Assets الإضافية. يعمل برنامج Adobe Character Animator مع الدمى المصنوعة باستخدام برنامجَي Adobe Illustrator، أو Adobe Photoshop، لذلك ستحتاج إلى تجهيز الشخصيات الكرتونية بأحد هذين البرنامجَين، ثم ستحتاج إلى إعداد الملف وفقًا لمتطلبات برنامج Character Animator، لتعمل الدمية بصورةٍ صحيحة. CharacterName+ : يجب أن يحتوي اسم الشخصية على إشارة زائد مع اسم الدمية (يجب أن تُسمَّى الطبقة كلها بهذه الطريقة في برنامج أدوبي إليستريتور). يجب وجود طبقتين مختلفتين داخل هذه المجموعة أو الطبقة في برنامج إليستريتور هما: الرأس Head: يجب أن تحتوي هذه المجموعة على المجموعات الآتية التي يجب أن تُسمَّى تمامًا كما يلي: Mouth Left eye Right eye Left eyebrow+ Right eyebrow+ كما يوجد أيضًا شعر، أو وجه، أو قبّعة، أو شيء آخر موجود في الرأس، ولكن يمكنك تسميتها بالطريقة التي تريدها. الجسم Body: تحتوي هذه المجموعة المجموعات التالية: left arm+ right arm+ torso and legs يمكنك إضافة مجموعات وعناصر أخرى إن لزم الأمر، فليست مجموعات الجسم Body مهمة، ولكن يُفضَّل تحريك اليدين والجسم عند تنظيم المجموعات بهذه الطريقة. مجموعة الفم Mouths: يحتاج برنامج أدوبي إليستريتور 14 شكلًا أساسيًا للفم لتشغيل عملية مزامنة الشفاه Lipsync تشغيلًا صحيحًا. ويجب تسمية هذه الأشكال بطريقة محددة، كما يجب أن تكون ضمن مجلد mouth. هناك 3 مشاعر خاصة بالفم هي: neutral، وsmile، وsurprised، ويوجد 11 شكلًا للفم لاستخدامها في تحريك الشفاه بالتزامن مع صوتك هي: Uh وR وOh وW-Oo وS وF وL وEe وAh وD وM. أمثلة عن دمى في برنامج Adobe Illustrator بنية الطبقة بنية وتسمية المجموعة Mouth مبادئ بنية المجموعات التجميع Grouping: يجب تجميع الدمية الكرتونية بطريقة محدَّدة، إذ يجب أن تكون الدمية بأكملها ضمن مجموعةٍ واحدة في برنامج فوتوشوب (أو طبقة واحدة في برنامج إليستريتور)، مع إشارة "+"، واسم الدمية؛ ثم يجب وجود مجموعتين منفصلتين للرأس والجسم، كما يجب أن تُعِد بداخلها جميع العناصر، بحيث يكون كل عنصر في مجموعة مختلفة. لن تعمل الدمية بصورةٍ صحيحة إذا وضعت العين اليسرى، والحاجب الأيسر في مجموعةٍ واحدة تسمّى left eye على سبيل المثال. التسمية Naming: يجب تسمية جميع المجموعات المتعلّقة بالعناصر الأساسية بطريقة محدَّدة يفهمها البرنامج، مثل: head، وbody، وmouth، والتي تحتوي (uh وr وoh وw-oo وs وf وl وee وah وd وm وsmile وsurprised وneutral؛ وleft eyebrow + وright eyebrow + وleft eye وleft pupil + وleft blink، وغير ذلك. وتوجد عناصر أخرى يمكنها تسميتها بالطريقة التي تريدها مثل: hair، وnose، وleft ear، وغير ذلك. اليسار واليمين: يجب تسمية بعض المجموعات من خلال تضمين كلمتَي left أو right في اسم هذه المجموعات، وهذا أمرٌ مهم لحركة العيون، وحدقة العين، والحاجبَين. وضع إشارة + مع العناصر الديناميكية: وهذا لحدقتَي العينَين التي يجب أن تتحرّك تبعًا للعيون، لذلك تُسمَّى left pupil + على سبيل المثال، وتستطيع توظيف ذلك أيضًا حسب حاجتك، حيث يمكنك وضع شعر الشخصية أمام وجهها بتضمين إشارة + في اسم مجموعة الشعر. تضمين خلفية Background للشخصية تحتاج بالطبع إلى تضمين خلفية في رسومك المتحركة، إذ يمكنك إيجاد صور ورسومات لخلفيات ضمن مواقع متعددة مجانية أو مأجورة. ولإضافة هذه الخلفيات، فما عليك سوى استيرادها من خلال القائمة menu، ثم اختيار import. بدء التحريك لنبدأ بالجزء الممتع بعد أن ضمّنا الدمية والخلفية. استخدم وضع التسجيل Record mode في أعلى البرنامج. إعداد المشهد Scene حدّد الدمية التي ضمّنتها في مشروعك، وانقر على زرّ إضافة مشهد "Add Scene" في الزاوية السفلية اليسرى من نافذة project. اسحب وأفلِت الخلفية إلى نافذة Timeline لإضافتها إلى المشهد. ابدأ التسجيل حدّد دميتك في نافذة Timeline وانقر على زرّ Record (أو استخدم الاختصار Crtl + R من لوحة المفاتيح) لبدء التحريك. استكشاف ميزات برنامج Adobe Character Animator المنبهات Triggers المنبّهات هي إجراءات وحركات آلية. تُستخدَم هذه الميزة لترفع الدمية إبهامها، أو لجعلها غاضبةً، أو راكضةً، أو جالسةً على سبيل المثال. ويمكنك استخدام هذه المنبهات من خلال نافذة Triggers الموجودة على الجهة اليسرى، إذ تحتوي هذه النافذة على المنبّهات المتوفرة لدميتك، والأزرار التي تحتاجها لتفعيل كلٍّ من هذه المنبّهات. فإن استخدمتَ دمىً مصنوعة مسبقًا، فإنّك ستجد منبّهات مبنيةً مسبقًا، وتستطيع استخدامها على الفور، ولكن إذا استخدمت قوالبًا أخرى، أو صنعت دميتك بنفسك، فيجب أن تُنشِئ منبّهات من الصفر. لقد أضفنا بعض العناصر إلى ملف الدمى في المثال الآتي، حيث أنشأنا مجموعات داخل مجموعتَي الحاجب الأيمن والأيسر في ملف إليستريتور. كما عدّلنا الحاجبَين، وجهّزناهما مثل مجموعات متعددة ضمن المجموعة eyebrow، حيث إذ سمّينا هذه المجموعات كالتالي: Normal، وAngry، وHappy، وSad، وDown، ويجب أن تكون هذه المجموعات غير ظاهرة باستثناء المجموعة Normal. لنتعرّف الآن على طريقة جعل الشخصية غاضبة. استخدم الوضع Rig، وحدّد دميتك لإنشاء منبّهات، بعدها انقر على الخيار menu الموجود في الزاوية اليمينية العليا من نافذة Triggers، ثم حدّد الخيار إنشاء مجموعة استبدال "Create Swap Set". ثم انقر على الخيار menu ضمن مجموعة الاستبدال swap set الجديدة، وحدّد الخيار إنشاء منبّه "Create Trigger"، وبالتالي أصبح لديك الآن منبّهٌ واحد في مجموعة الاستبدال. انقر بزرّ الفأرة اليميني على هذا المنبّه وأعِد تسميته ليصبح Normal، ثم أنشئ منبّهًا آخر في مجموعة الاستبدال نفسها وسمِّه Angry، بعدها حدّد المنبّه Normal، وانقر على اليد كما في الشكل التالي ليمثّل هذا المنبّه الحالةَ الافتراضية. يمكن جعل الدمية غاضبةً من خلال اختيار المجموعة Uh من مجموعة mouth، والمجموعتين Angry ضمن مجموعتَي الحاجبَين، ثم اسحبْ المجموعات المختارة، وأفلتها ضمن المنبه Angry في مجموعة الاستبدال. يمكنك الآن رؤية العناصر التي ستُفعَّل عند النقر على المنبّه Angry. ثم نضع الحالات الافتراضية للحاجبَين ضمن المنبّه Normal (ليس هناك داعٍ لعمل ذلك للفم لأنه ديناميكي وسيتغير خلال تحدّثك). بما أننا حدّدنا هذا المنبّه كافتراضي، فستظهر هذه العناصر داخله، بينما ستكون عناصر المنبّهات الأخرى غير ظاهرة إلى أن يفعَّل المنبّه. انقر على المربع الأيسر بجانب المنبّه Angry واكتب المفتاح الذي تريده لتفعيل هذا المنبّه. سنستخدم الحرف A في هذا المثال لتفعيل المنبّه. ابدأ التسجيل، واضغط على الحرف A، فهذا سيؤدي إلى تفعيل العناصر الموجودة في المنبّه Angry، وبالتالي ستختفي العناصر الموجودة في المنبّه Normal. يمكن أيضًا اختيار سلوك هذا المنبّه، مثل اختيارك لإبقاء المنبّه مفعّلًا طوال مدة ضغطك على مفتاح التفعيل، أو بقاءه مفعّلًا إلى أن تضغط على مفتاح التفعيل مرةً أخرى. يدعى هذا الإجراء بالقفل Latch، وهو مفيدٌ جدًا في بعض الحالات، حيث يمكن تفعيل هذا القفل باختيار المنبّه وتحديد الخيار Latch كما في الشكل الآتي، وسيبقى المنبّه مفعَّلًا إلى أن تضغط على مفتاح التفعيل مرةً أخرى عند تحديد الخيار Latch، وإن كان غير محدَّد، فسيفعَّل المنبّه عند الضغط على مفتاح التفعيل فقط. الساحبات Draggers تسمح الميزة Dragger في برنامج Adobe Character Animator، بسحب عنصر وتحريكه بيدك، إذ تُستخدَم هذه الميزة غالبًا لتحريك يدَي الشخصية، ولها فوائد أخرى أيضًا، فهي تسمح بإنشاء كل أنواع التشغيل الآلي باستخدام الساحبات، بحيث يمكنك إضافة حركة لشعر شخصيتك، أو إضافة هواء، أو جاذبية لبعض العناصر. استخدِم الوضع Rig لإنشاء ساحب، وحّدد الدمية التي تريدها وانقر على ذراعها. ستجد أسفل دميتك مجموعةً من الأدوات. حدّد الأداة Dragger كما في الشكل التالي، ثم ضعها على يد الدمية (حدّد النقطة التي تريد سحب اليد منها). يجب أن نضيف أيضًا عظامًا bones، ونقطةً لاتصال اليد بالجسم، حيث ستربط الذراع بالجسم أولًا من خلال اختيار أداة المقبض Handle tool، بعدها حدّد الكتف ليتداخل الذراع مع الجسم، ويُعلَّم باللون الأخضر. ثم انقر على إشارة الزائد + الموجودة بجوار نقطة المقبض التي أنشأتها، وستظهر نافذة منبثقة تحتوي على بنية الجسم. انقر على الكتف حتى يفهم البرنامج أنّ هذه النقطة هي كتف دميتك. نكرر الآن نفس الخطوة السابقة مع مِرفق اليد. استخدم أداة المِقبض لإنشاء نقطة حيث يوجد المرفق، ثم ضع علامةً على المرفق في بنية الجسم. يمكنك الانتقال إلى وضع Record، واختبار حركة اليد حتى الآن، إذ يجب أن تتحرك اليد عند سحب وإفلات اليد بالمؤشر، ولكن يمكن تحسين هذه الحركة من خلال إضافة بعض العظام وبالتالي تصبح الحركة أكثر واقعية. نضيف العظام من خلال تحديد الأداة Stick، ووضع علامة على الذراع بين الكتف، والمرفق، والمعصم كما يلي: ميزات أخرى مفيدة توجد تحديثات كبيرة لبرنامج Adobe Character Animator، حيث تقدّم هذه التحديثات ميزات جديدة لتطوير سهولة الاستخدام، ويمكنك التحكم بالدمية وتحريكها تحكمًا كاملًا، وعمل الكثير من الأشياء المفيدة، مثل: Replays الإعادة: تحفظ هذه الميزة الحركات، والمنبّهات، وغير ذلك ضمن رسوم متحركة مُعدَّة مسبقًا، بحيث تستطيع استخدامها فيما بعد مرةً أخرى ببضع خطوات. الإطارات المفتاحية Keyframes: يمكنك استخدامها لجعل حركة بعض الرسوم المتحركة أكثر سلاسة، وهناك ميزة مهمة معروفة جيدًا في برنامج After Effects، وهي الجزء الأساسي من الرسوم المتحركة ذات المظهر الاحترافي. يمكنك تفعيل ميزة الإطارات المفتاحية Keyframes للشرائح المحدَّدة، والنقر على الخاصيتين ease-in وease-out للإطارات المفتاحية المُختارة، لجعل الحركات والرسوم المتحركة أكثر سلاسة. السلوكيات Behaviors: هي ميزة مفيدة جدًا لصنع حركات لعناصر دائرية، وغمزات آلية، وتنفس، وجذب، وتمايل، وغير ذلك من السلوكيات التي تُضبَط ضمن النمط rig. إذ تضاف هذه السلوكيات إلى المجموعة المحدَّدة، وتُستخدَم أيضًا لتعديل نمط المشي، وسلوك الساحبات، والمنبّهات. الخلاصة يتطوّر جميع الأشخاص ويتقدّمون خطوةً للأمام باستخدام تقنيات مختلفة لجذب انتباه العملاء والحفاظ عليهم، وإحدى هذه التقنيات هي الرسوم، والشخصيات المتحركة التي تُعَد طريقةً ديناميكيةً، وممتعةً، وحديثةً لجذب العملاء. وقد قدّمنا من خلال هذا الدليل الخطوات الأولى لتشغيل الرسوم المتحركة بطريقة سلسة وبسيطة ترجمة -وبتصرّف- للمقال Beginners Guide to Adobe Character Animator لصاحبه Lyudmil Enchev.
-
بعد مناقشة بعض الأمور الأساسية حول التبديل، سنركّز الآن بشكل أكبر على تقنية تبديل محددة وهي الإيثرنت المبدَّل، والتي تُستخدم بكثرة في شبكات الحرم الجامعي والشركات. وتُستخدم المبدلات عادةً في بناء هذه الشبكات والمعروفة غالبًا بمبدِّلات الطبقة الثانية L2، والتي كان يُشار أكثر في وقت سابق باسم الجسور bridges لأنها اُستخدِمت "لتجسير" مقاطع الإيثرنت لبناء شبكة محلية مُوسَّعة extended LAN. لكن تعتمد معظم الشبكات اليوم تقنية الإيثرنت ضمن إعداد اتصال من نقطة لنقطة، مع هذه الروابط المتشابكة بواسطة مبدّلات L2 لتشكيل شبكة إيثرنت مبدَّلة. نبدأ بالمنظور التاريخي الآن (المُعتمد على الجسور لتوصيل مجموعة مقاطع إيثرنت، ثم ننتقل إلى الاستخدام واسع الانتشار اليوم باستخدام مبدلات L2 لتوصيل مجموعة من روابط من نقطة لنقطة). لكن سواء أطلقت على الجهاز اسم جسرٍ أو مبدّل، والشبكة المُنشَأة اسم شبكة LAN مُوسَّعة أو شبكة إيثرنت مبدَّلة، فكليهما يتصرفان بنفس الطريقة تمامًا. بفرض وجود زوج إيثرنت يُطلب ربطهما معًا. من بين أحد الأساليب الممكن تجريبها هي وضع مكرّر repeater بينهما. ولكن هذا لن يكون حلًا عمليًا، غير أنه سيتجاوز قيود الإيثرنت الفيزيائية (حيث لا يُسمح باستخدام أكثر من مكرّرين بين أيّ جهازين مضيفين وألا يزيد إجمالي الطول عن 2500 متر). والبديل هنا هو وضع عقدةٍ مع زوج محوّلات adaptors إيثرنت بين شبكتي الإيثرنت وتقوم العقدة بتمرير الإطارات من شبكة إيثرنت إلى أخرى. قد تختلف هذه العقدة عن المكرّر الذي يتعامل مع البتّات -وليس الإطارات-، وينسخ فقط البتات المُستقبلة من واجهةٍ إلى واجهة أخرى. بينما ستنفّذ هذه العقدة بدلًا من ذلك بروتوكولات كشف التصادم والوصول إلى الوسائط في شبكة الإيثرنت على كلّ واجهة. ولن تطبَّق القيود المتعلقة بإدارة التصادمات مثل طول وعدد مضيفي الإيثرنت، على زوج الإيثرنت المدمَج المتّصل بهذه الطريقة. وبهذا يعمل هذا الجهاز في الوضع المختلط promiscuous mode، ويقبل جميع الإطارات المُرسَلة على أيّ شبكة إيثرنت، ويُمررها إلى الشبكة الأخرى. تقبل الجسور ببساطة إطارات من شبكة محلية LAN على مداخلها وتُمررها إلى عدّة مخارج أخرى. وقد استخدمت الجسور القديمة هذه الإستراتيجية البسيطة، إلا أنها تحوي بعض القيود الخطيرة جدًا كما سترى لاحقًا. ولهذا أُضيفت عِدّة تحسينات على مرّ السنين لجعل الجسور آليةً فعالةً لربط مجموعة من الشبكات المحلية. تعلم الجسور Learning Bridges التحسين الأول الممكن إجراؤه على الجسر هو ملاحظة عدم حاجته إلى تمرير جميع الإطارات التي يستقبلها. إذ ما من داعٍ لتمرير الجسر للإطار من المنفذ 1 إلى المنفذ 2، عندما يصل إطارٌ من المضيف A موجَّه إلى المضيف B. والسؤال إذًا هو كيف يتعرّف الجسر على المنفذ الموافق لأيٍّ من المضيفَين المختلفين؟ تتمثل إحدى الخيارات في أن يكون هناك جدولٌ يُنزَّل يدويًا في الجسر مشابه للجدول الآتي. لن يعيد الجسر بعدئذٍ تمرير الإطار إلى المنفذ 2 عندما يتلقّى إطارًا على المنفذ 1 موجهًا إلى المضيف A، حيث لن تكون هناك حاجة لذلك، نظرًا لتلقّي المضيف A للإطار فعليًا مباشرةً على الشبكة المحلية المتصلة بالمنفذ 1. وبهذا سيُعيد الجسر تمرير الإطار إلى المنفذ 1 في أيّ وقتٍ يستلم إطارًا موجهًا إلى المضيف A على المنفذ 2. 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; } المضيف Host المنفذ Port A 1 B 1 C 1 X 2 Y 2 Z 2 إن وجود شخصٍ يُعنى بهذا الجدول أمرٌ مرهق للغاية، لذلك هناك حيلة بسيطة يمكن من خلالها تعلُّم الجسر لهذه المعلومات بنفسه. والفكرة هنا تكمن في فحص كلّ جسر لعنوان المصدر في جميع الإطارات التي يتلقاها، وبالتالي إذا أرسل المضيف A إطارًا إلى مضيفٍ آخر على جانبي الجسر، فسيتلقى الجسر هذا الإطار ويسجّل أنّ إطارًا من المضيف A قد اُستلِم للتو على المنفذ 1. وبهذه الطريقة يمكن للجسر بناء جدولٍ مماثل تمامًا للجدول السابق. لاحظ أنّ الجسر الذي يستخدم مثل هذا الجدول يطبّق إصدارًا من نموذج مخطَّط البيانات (أو عديم الاتصال) للتمرير والموصوف سابقًا. حيث تحمل كلّ رزمةٍ عنوانًا عامًا، ويقرّر الجسر أيّ مخرج سيستخدمه لإرسال رزمة من خلال البحث عن هذا العنوان في الجدول. يكون هذا الجدول فارغًا عندما يعمل الجسر لأول مرّة، ثم تُضاف المدخلات مع مرور الوقت. وتُربَط مهلة زمنية بكلّ مدخلة، حيث يتجاهل الجسر المدخلة بعد فترة زمنية محددة، وذلك للحماية من الحالة الذي قد يُنقل فيها مضيفٌ (وعنوان LAN الخاص به) من شبكةٍ إلى أخرى. وبالتالي فهذا الجدول لا يُعَدّ كاملًا بالضرورة. فإذا تلقّى الجسر إطارًا موجهًا إلى مضيف غير موجود حاليًا في الجدول، فسيمضي قُدمًا ويُمرر الإطار إلى جميع المنافذ الأخرى. ما يعني أنّ هذا الجدول هو مجرّد تحسين لتصفية filters بعض الإطارات، ولا يتُشترط صحته دائمًا. التطبيق Implementation تُعَدّ الشيفرة التي تطبق خوارزمية تعلّم الجسر بسيطةً للغاية، حيث تُعرِّف البنية BridgeEntry مدخلةً في جدول تمرير الجسر؛ وتُخزَّن في بنية Map (والتي تدعم الدوال mapCreate وmapBind وmapResolve من أجل تحديد موقع المدخلات بكفاءة عند وصول الرزم من مصادر موجودةٍ بالفعل في الجدول، ليُحدد الثابت MAX_TTL مدّة الاحتفاظ بمدخلةٍ في الجدول قبل إهمالها. #define BRIDGE_TAB_SIZE 1024 /* الحجم الأقصى لجدول الجسور */ #define MAX_TTL 120 /* الوقت (مقدرًا بالثواني) قبل حذف المدخلة */ typedef struct { MacAddr destination; /*للعقدة MAC عنوان */ int ifnumber; /* واجهة للوصول إليها */ u_short TTL; /*(العمر) time to live */ Binding binding; /* Map الربط بالبنية */ } BridgeEntry; int numEntries = 0; Map bridgeMap = mapCreate(BRIDGE_TAB_SIZE, sizeof(BridgeEntry)); تعطي الدالةُ updateTable الإجراءَ الروتيني والذي يحدّث جدول التمرير عند وصول رزمة جديدة، وتمرَّر لها الوسطاء المتمثّلة في عنوان التحكم في الوصول إلى وسائط المصدر MAC الموجود في الرزمة، ورقم الواجهة التي اُستقبل منها. حيث يُستدعى إجراءٌ آخر غير معروضٍ هنا، وذلك على فترات منتظمة، لفحص المدخلات في جدول التمريرويقلّل من حقل عمر الرزمة time to live أو اختصارًا TTL لكلّ مُدخَلة، مع تجاهل أيّ مدخَلات وصل عُمرها إلى الصفر. يُعاد ضبط حقل TTL إلى MAX_TTL في كلّ مرّة تصل فيها رزمة لتحديث مدخلة جدول موجودة مسبقًا، وتُحدَّث الواجهة التي يمكن من خلالها الوصول إلى الوجهة لتظهر أحدث رزمةٍ مستلَمة. void updateTable (MacAddr src, int inif) { BridgeEntry *b; if (mapResolve(bridgeMap, &src, (void **)&b) == FALSE ) { /* هذا العنوان غير موجود في الجدول، لذا حاول إضافته */ if (numEntries < BRIDGE_TAB_SIZE) { b = NEW(BridgeEntry); b->binding = mapBind( bridgeMap, &src, b); /* استخدم عنوان مصدر الرزمة على أنه عنوان الوجهة في الجدول */ b->destination = src; numEntries++; } else { /* لا يمكن احتواء هذا العنوان في الجدول الآن، لذا استسلم */ return; } } /* TTL أعد ضبط الحقل واستخدم أحدث واجهة إدخال */ b->TTL = MAX_TTL; b->ifnumber = inif; } لاحظ أنّ هذا التطبيق يتبنّى إستراتيجيةً بسيطةً، ففي الحالة التي تصبح فيها سعة جدول الجسر ممتلئة، يفشل ببساطة في إضافة العنوان الجديد. مع الأخذ بعين الإعتبار أنّ اكتمال جدول الجسر ليس ضروريًا لإعادة التوجيه الصحيحة، أي أنّه يحسّن الأداء فقط. فإذا كان هناك بعض المدخلات في الجدول التي لم تُستخدَم حاليًا، فستنتهي مهلتها في النهاية وستُزال، مما يوفّر مساحةً لمدخلةٍ جديدة. تتمثل الطريقة البديلة في استدعاء خوارزمية الاستبدال المؤقتة cache replacement algorithm عند العثور على الجدول ممتلئًا، وقد تُحدَّد المدخلة على سبيل المثال وتُزال باستخدام أصغر عُمر TTL لاستيعاب المدخلة الجديدة. خوارزمية الشجرة الممتدة Spanning Tree Algorithm تعمل الإستراتيجية السابقة بصورة جيدة لحين حدوث حلقةٌ في الشبكة، حيث تفشل في هذه الحالة بشكل مروّع، فمن المحتمل استمرار توجيه الإطارات إلى الأبد. ومن السهل رؤية ذلك في المثال الموضَّح في الشكل التالي، حيث تشكّل المبدلات S1 وS4 وS6 حلقة loop: لاحظ انتقالنا الآن من تسمية جهاز التمرير بالجسر (توصيل المقاطع التي يمكنها الوصول إلى عدّة أجهزة أخرى) إلى تسميتها بمبدّلات L2 (توصيل روابط من نقطة لنقطة التي يمكنها الوصول إلى جهاز واحد فقط). سنضمّن ثلاثة مضيفين فقط للحفاظ على المثال السابق قابلًا للإدارة، حيث تحتوي المبدّلات عادةً من الناحية العملية على 16 أو 24 أو 48 منفذًا، ممّا يعني قدرتها على الاتصال بالعديد من الأجهزة المضيفة (والمبدّلات الأخرى). بفرض في مثالنا على شبكة التبديل، أنّ الرزمة تدخل المبدّل S4 من المضيف C، وأنّ عنوان الوجهة ليس موجودًا بعد في أيّ جدول تمرير للمبدّلات. يرسل المبدّل S4 نسخةً من الرزمة من منفذيه الآخرين إلى المبدّلين S1 وS6، ليُعيد المبدّل S6 توجيه الرزمة إلى المبدّل S1 (ويعيد المبدّل S1 توجيه الرزمة إلى المبدّل S6 في الوقت نفسه)، ويعيد كلٌ منهما بدوره توجيه الرزمة إلى المبدّل S4. وهنا، لا يزال المبدّل S4 لا يحتوي على هذه الوجهة في جدوله، لذلك يعيد توجيه الرزمة إلى منفّذيه الآخرين. إذ لا يوجد ما يمنع هذه الدورة من التكرار إلى ما لا نهاية، مع تكرار الرزم في كلا الاتجاهين بين المبدّلات S1 وS4 وS6. ولكن لماذا توجد حلقةٌ في شبكة الإيثرنت المبدَّلة (أو شبكات LAN المُوسَّعة)؟ أحد الاحتمالات هو وجود أكثر من مديرٍ للشبكة لامتدادها عبر أقسام متعدّدة في المؤسسة على سبيل المثال. فمن الممكن ألا يُعرَف أيّ شخصٍ ضبط الشبكة كاملةً بهذه الإعدادات، مما يعني إمكانية إضافة مبدّل يكمّل حلقةً دون علم أيّ شخص. أمّا السيناريو الثاني والأكثر احتمالًا، فهو أنّ الحلقات مدمجة في الشبكة عن قصد لتوفير الخط الاحتياطي redundancy في حالة الفشل. والشبكة التي لا تحتوي على حلقات تحتاج إلى فشل رابطٍ واحد فقط لتُقسَم إلى قسمين منفصلين. يجب أن تكون المبدّلات قادرةً على التعامل مع الحلقات بصورة صحيحة مهما كان السبب، وتُعالَج هذه المشكلة من خلال جعل المبدّلات تشغّل خوارزمية شجرة ممتدّة وموزعة. فإذا اعتبرنا أنّ الشبكة ممثَّلةٌ برسمٍ بياني graph يحتوي على حلقات loops أو دورات cycles، فالشجرة الممتدة هي رسم فرعي لهذا الرسم البياني يغطي أو يضم جميع الرؤوس vertices، ولكنه لا يحتوي على دورات، أي أنّ الشجرة الممتدة تحافظ على جميع رؤوس الرسم البياني الأصلي ولكنها تستبعد بعض الأضلاع edges. يوضّح الشكل التالي رسمًا بيانيًا يحتوي حلقةً أو دورةً على اليسار وشجرةً ممتدةً على اليمين: فكرة الشجرة الممتدة بسيطة، فهي مجموعة فرعية من مخطط الشبكة الفعلي الذي لا يحتوي على حلقات، والذي يصل إلى جميع الأجهزة في الشبكة. يتمثّل الجزء الصعب بكيفية تنسيق قرارات جميع المبدّلات للوصول إلى شكلٍ واحد للشجرة الممتدة، حيث يمكن تغطية مخططٍ واحدة بعدّة أشجار ممتدة، وتكمن الإجابة على ذلك في بروتوكول الشجرة الممتدة الذي سنشرحه الآن. طوّرت راديا بيرلمان Radia Perlman خوارزمية الشجرة الممتدة، ثم طُوِّرت في شركة المعدّات الرقمية Digital Equipment Corporation، وهي بروتوكول تستخدمه مجموعة من المبدّلات للاتفاق على شجرة ممتدة لشبكة معينة. حيث تعتمد مواصفات معيار IEEE 802.1 على هذه الخوارزمية. وهذا يعني اختيار كلّ مبدّل للمنافذ التي يكون مستعد وغير مستعد لتمرير الاطارات عليها، وبهذا يصغّر الشبكة إلى شجرة لا دورية عن طريق إزالة المنافذ من مخطط الشبكة. ومن الممكن ألا يشارك مبدلٌ كامل في تمرير الإطارات، وهو الأمر الذي يبدو غريبًا للوهلة الأولى. ولكنّ هذه الخوارزمية ديناميكية، مما يعني أنّ المبدّلات مستعدة دائمًا لإعادة ضبط نفسها في شجرة ممتدة جديدة في حالة فشل بعض المبدّلات، وبالتالي توفِّر هذه المنافذ والمبدّلات غير المستخدَمة السعة الزائدة اللازمة للتعافي من حالات الفشل. الفكرة الرئيسية للشجرة الممتدة هي تحديد المبدّلات المنافذ التي ستُمرر الإطارات عليها، إذ تختار الخوارزمية المنافذ على النحو التالي: كلّ مبدّل له معرّف فريد، حيث سنستخدم التسميات S1 وS2 وS3 وما إلى ذلك، وستنتخب الخوارزمية أولًا المبدلَ الذي يحتوي على أصغر معرّف ID وتعدّه جذرًا root للشجرة الممتدة. ويُعيد المبدّل الجذرُ تمرير الإطارات عبر جميع منافذه دائمًا. ليحسب كلّ مبدّلٍ أقصر مسار إلى الجذر ويلاحظ أيًّا من منافذه يقع على هذا المسار. كما يُحدَّد هذا المنفذ أيضًا، بحيث يُعَدّ مسار المبدل المفضّل إلى الجذر. ولحساب احتمال وجود مبدّلٍ آخر متّصل بمنافذه في النهاية، يختار المبدّل مبدّلًا واحدًا مُخَصّصًا designated ليكون مسؤولًا عن تمرير الإطارات نحو الجذر، بحيث يكون كلّ مبدلٍ مخصّص هو المبدّل الأقرب إلى الجذر. وإذا كان مبدّلان أو أكثر قريبين بدرجة متساوية من الجذر، تُستخدَم معرّفات المبدّلات لكسر هذا التساوي، ويفوز أصغر معرّف. قد يوصَل كلّ مبدلٍ بأكثر من مبدّل آخر، لذلك فهو يشارك في اختيار مبدّلٍ مُخصّص لكلّ منفذ من هذا القبيل. وهذا يعني أنّ كلّ مبدّل يقرر ما إذا كان هو المبدّل المُخصص بالنسبة لكلّ منفذٍ من منافذه. ويُمرر المبدّل الإطارات خلال تلك المنافذ التي يكون هو المبدّل المُخصص لها. يوضِّح الشكل السابق الشجرة الممتدة التي تتوافق مع الشبكة التي تحوي حلقات والموضَّحة سابقًا، حيث أنّ المبدّل S1 هو المبدّل الجذر نظرًا لاحتوائه على أصغر معرّف. يمكن الملاحظة أنّ المبدّلين S3 وS5 متّصلان ببعضهما البعض، لكنّ المبدّل S5 هو المبدّل المُخصّص لأنه أقرب إلى المبدّل الجذر. وبالمثل، فالمبدّلين S5 وS7 متصلان ببعضهما البعض، ولكن في هذه الحالة يكون المبدّل S5 هو المبدّل المخصّص لاحتوائه على معرّف أصغر، لأنّ كلاهما على مسافة متساوية من المبدّل S1. من الممكن أن ينظر الشخص إلى الشبكة ويحسب الشجرة الممتدة وفقًا للقواعد المذكورة سابقًا، ولكنّ المبدّلات لا تتمتع بهذه القدرة على رؤية مخطّط الشبكة بالكامل، ناهيك عن إلقاء نظرة خاطفة داخل المبدّلات الأخرى لرؤية معرّفاتها. إذ يتعين عليها بدلًا من ذلك تبادُل رسائل الضبط configuration messages مع بعضها بعضًا، ثم تحديد ما إذا كانت تمثّل المبدّل الجذر أو المبدّل المُخصّص بناءً على هذه الرسائل. تحوي رسائل الضبط ثلاث معلومات مهمّة : معرّف المبدّل الذي يرسل الرسالة. معرّف المبدّل الذي يعتقده مبدّل الإرسال المبدّل الجذر. المسافة، مقاسةً بعدد القفزات hops، من مبدّل الإرسال إلى المبدّل الجذر. يسجّل كلّ مبدّل أفضلَ رسالة ضبط شاهدها حاليًا على كلّ من منافذه (سيُشرح معنى "الأفضل" لاحقًا)، بما في ذلك كلّ الرسائل التي تلقّاها من مبدّلات أخرى والرسائل التي أرسلها بنفسه. أولًا يعتقد كلّ مبدّل أنه هو المبدّل الجذر، ويرسل بالتالي رسالة ضبطٍ إلى كلّ منفذ من منافذه لتعريف نفسه بكونه الجذر، ويعطي مسافةً للجذر هي 0. يتحقّق المبدّل عند تلقّي رسالة ضبط عبر منفذ معيّن لمعرفة ما إذا كانت هذه الرسالة الجديدة أفضل من أفضل رسالة ضبط مُسجلة لهذا المنفذ، حيث تُعَد رسالة الضبط الجديدة أفضل من المعلومات المسجلة حاليًا إذا تحقق أيّ مما يلي: أنها تحدد جذرًا بمعرّفٍ أصغر. أنها تحدد جذرًا بمعرّف متساوٍ ولكن بمسافة أقصر. معرّف الجذر والمسافة متساويان، لكن معرّف مبدّل الإرسال أصغر. إذا كانت الرسالة الجديدة أفضل من المعلومات المسجَّلة حاليًا، فسيتجاهل المبدّل المعلومات القديمة ويحفظ المعلومات الجديدة، ولكنه يضيف أولًا 1 إلى حقل المسافة إلى الجذر distance-to-root field، نظرًا لبُعد المبدّل بمقدار قفزةٍ واحدة عن الجذر من المبدّل الذي أرسل الرسالة. إذا تلقّى المبدّل رسالة ضبط تشير إلى أنّه ليس الجذر -أي رسالة من مبدلٍ بمعرّف أصغر-، فسيتوقف المبدّل عن إنشاء رسائل الضبط من تلقاء نفسه، ويعيد توجيه رسائل الضبط من المبدّلات الأخرى فقط، بعد إضافة 1 إلى حقل المسافة أولًا. وبالمثل، إذا تلقّى المبدّل رسالة ضبط تشير إلى أنه ليس المبدّل المُخصّص عن ذلك المنفذ -أي رسالة من مبدّل أقرب إلى الجذر أو بعيدًا عن الجذر بنفس القدر ولكن بمعرّف أصغر-، سيتوقف المبدّل عن إرسال رسائل الضبط عبر هذا المنفذ. وبالتالي يظلّ المبدّل الجذر فقط هو الذي ينشئ رسائل الضبط عندما يستقر النظام، بينما تعيد المبدّلات الأخرى توجيه هذه الرسائل عبر المنافذ التي تكون المبدّلات المخصصة أو المُكلَّفة عنها فقط. وبذلك بُنيَت الشجرة الممتدة، واتفقت جميع المبدّلات على المنافذ المستخدمة للشجرة الممتدة، ويمكن استخدام هذه المنافذ فقط لتمرير رُزم البيانات. لنرى كيف يعمل هذا البروتوكول مع المثال التالي، كما هو مُوضح في الشكل السابق. إذا اُستعيدت الطاقة للتو إلى شبكة الحرم الجامعي، بحيث شُغِّلت جميع المبدّلات في نفس الوقت تقريبًا. ستبدأ جميع المبدّلات بالادعاء بأنها المبدِّل الجذر، لهذا سنشير إلى رسالة الضبط من العقدة X التي تدّعي بوجود المسافة d إلى العقدة الجذر Y بالشكل (Y, d, X)، بحيث ستكتشف سلسلةً من الأحداث على النحو التالي وذلك بالتركيز على المبدّل S3: يتلقى المبدّل S3 الرسالة (S2, 0, S2). بما أنّ 2 < 3، فيقبل المبدّلُ S3 المبدلَ S2 جذرًا. يضيف المبدّل S3 قيمة 1 إلى المسافة التي أُعلن عنها بواسطة S2 (0)، وبالتالي يرسل الرسالة (S2, 1, S3) إلى المبدّل S5. ويقبل المبدّلُ S2 المبدّلَ S1 جذرًا في الوقت نفسه، نظرًا لاحتوائه على معرّف أقل، ليرسل الرسالة (S1, 1, S2) إلى المبدّل S3. يقبل المبدّلُ S5 المبدّلَ S1 جذرًا ويرسل رسالة (S1, 1, S5) إلى المبدّل S3. يقبل المبدّل S3 المبدّلَ S1 جذرًا، ويلاحظ أنّ كلًا من المبدّلين S2 وS5 أقرب منه إلى الجذر، لكن معرّف المبدّل S2 هو الأصغر، لذلك يظلّ على مسار المبدّل S3 إلى الجذر. وهذا يترك المبدّل S3 بمنافذ نشطة، ويمكن ملاحظة عدم قدرة المضيفين A و B على الاتصال عبر أقصر مسار (عبر المبدّل S5) حيث يتوجب على الإطارات التدفق لأعلى الشجرة ثم العودة للأسفل، وهذه هي الضريبة التي تُدفع لتجنّب الحلقات. يستمر المبدّل الجذر في إرسال رسائل الضبط دوريًا حتى بعد استقرار النظام، وتستمر المبدّلات الأخرى في تمرير هذه الرسائل. لن تتلقى المبدّلات المُستقبِلة رسائل الضبط هذه في حالة فشل مبدّل معين، وستدّعي مرةً أخرى أنها الجذر بعد الانتظار لفترة زمنية محدّدة، وستبدأ الخوارزمية مرةً أخرى لاختيار جذر جديد ومبدّلات مُخصّصة جديدة. أحد الأشياء المهمة التي يجب ملاحظتها هو أنه بالرغم من قدرة هذه الخوارزمية على إعادة ضبط الشجرة الممتدة عندما يفشل مبدّل ما، إلا أنّها غير قادرة على تمرير الإطارات عبر مسارات بديلة من أجل التوجيه بعيدًا عن مبدّلٍ مزدحم. البث الإذاعي Broadcast والبث المتعدد Multicast ركزت المناقشة السابقة على كيفية تمرير الإطارات أحادية البث التي يقوم بها المبدّل من منفذٍ إلى آخر. بما أنّ الهدف من استخدام المبدّل هو توسيع شبكة محلية LAN بشفافية عبر شبكات متعددة، وبما أنّ معظم الشبكات المحلية تدعم البث الإذاعي والبث المتعدِّد، لذا يجب على المبدلات دعم هاتين الميزتين أيضًا. يُعَدّ البث الإذاعي بسيط، حيث يقوم كلّ مبدّل بتمرير الإطار مع عنوان البث الإذاعي الخاص بالوجهة على كلّ المنافذ النشطة ما عدا المنفذ الذي اُستقبِل الإطار عليه. يمكن تنفيذ البث المتعدِّد بنفس الطريقة تمامًا، حيث يقرّر كلّ مضيف بنفسه قبول الرسالة أم لا. ونظرًا لعدم كون كلّ المضيفين أعضاءً في أيّ مجموعة بث متعدد معّينة، فمن الممكن القيام بعمل أفضل. حيث يمكن توسيع خوارزمية الشجرة الممتدة لتحسين الشبكات التي لا يلزم إعادة توجيه إطارات البث المتعدد عليها، ويمكن افتراض إرسال إطار إلى المجموعة M بواسطة المضيف A، فإذا كان المضيف C لا ينتمي إلى المجموعة M، فليس هناك داعٍ للمبدّل S4 لإعادة توجيه الإطارات عبر تلك الشبكة. كيف يمكن لمبدّل معيّن معرفة ما إذا كان يجب عليه تمرير إطار البث المتعدِّد عبر منفذ معيّن؟ إنّه ببساطة يتعلم تمامًا بنفس الطريقة التي يتعلم بها المبدّل ما إذا كان يجب عليه تمرير إطار أحادي البث عبر منفذ معيّن أم لا، من خلال مراقبة عناوين المصدر التي يستقبلها عبر هذا المنفذ. وحيث أن المجموعات ليست مصدر للإطارات، يمكننا التلاعب قليلًا. بحيث يجب على كلّ مضيفٍ عضو في المجموعة M إرسال إطار دوريًا بعنوان المجموعة M في حقل المصدر لترويسة الإطار، ليكون لهذا الإطار عنوان وجهة بالنسبة للمبدّلات وهو عنوان البث المتعدِّد. على الرغم من اقتراح توسيع وتطوير البث المتعدِّد الموصوف للتو، إلا أنه لم يُعتمَد على نطاق واسع، إذ يُنفَّذ البث المتعدَّد بنفس طريقة البث الإذاعي تمامًا. الشبكات المحلية الافتراضية Virtual LANs أو اختصارًا VLANs أحد قيود المبدّلات هو أنها لا تتوسّع، كما أنّ توصيل أكثر من عدد قليل من المبدّلات معًا أمرٌ غير واقعي، حيث أن العدد القليل من الناحية العملية يعني العشرات. فأحد أسباب ذلك هو توسُّع خوارزمية الشجرة الممتدة خطيًا، بمعنى عدم وجود شرط لفرض تسلسلٍ هرميّ على مجموعة المبدّلات. أمّا السبب الثاني فهو أنّ المبدّلات تُمرر جميع إطارات البث الإذاعي، ومن الممكن رؤية جميع المضيفين لرسائل البث الإذاعي لبعضهم البعض ضمن مجال محدود (نفس القسم مثلًا)، ولكن من المُستبعد أن يرغب جميع المضيفين الموجودين في بيئة أكبر (شركة أو جامعة كبيرة مثلًا) بأن يكونوا منزعجين من رسائل البث الإذاعي لبعضهم البعض. وبالتالي لا يتوسّع البث الإذاعي ونتيجةً لذلك لا تتوسّع الشبكات القائمة على الطبقة الثانية L2. إحدى طرق زيادة قابلية التوسع scalability هي الشبكة المحلية الافتراضية VLAN، حيث تسمح شبكات VLAN بتقسيم شبكة LAN واحدة مُوسَّعة إلى عدة شبكات LAN منفصلة ظاهريًا. ويُسنَد معرّفٌ لكلّ شبكة LAN افتراضية، كما يُطلق على المعرّف أحيانًا لون color، ويمكن أن تنتقل الرُّزم من جزء إلى آخر فقط إذا كان لكلا الجزأين نفس المعرّف. وهذا له تأثيرٌ في الحدّ من عدد مقاطع شبكة LAN الممتدة التي ستتلقى أيّ رزمة بثٍ إذاعي معيّنة. يمكن رؤية كيفية عمل شبكات VLAN من خلال المثال المُوَضح في الشكل السابق حيث يوجد أربعة مضيفين ومبدِّلين. ستصل أيّ رزمة بثٍ إذاعي من أيّ مضيف إلى جميع المضيفين الآخرين في حالة عدم وجود شبكات VLAN. ولنفترض الآن تحديد للمقاطع المتصلة بالمضيفين W وX على أنها في شبكة محلية افتراضية واحدة، والتي سنسمّيها VLAN 100. كما سنحدّد أيضًا المقاطع التي تتصل بالمضيفين Y وZ على أنها في شبكة VLAN 200. وسنحتاج للقيام بذلك إلى ضبط معرّف VLAN على كلّ منفذٍ من المبدّلين S1 وS2، حيث يُعَدّ الرابط بين المبدلين S1 وS2 موجودًا في كلتا شبكتي VLAN. يُلاحِظ المبدّل S2 أنّ الرزمة التي يرسلها المضيف X جاءت على منفذٍ ضُبط على أنّه موجود في شبكة VLAN 100. وعند وصول هذه الرزمة إلى المبدّل، يحشر ترويسة VLAN بين ترويسة الإيثرنت وحمولته (الجزء المهم في ترويسة VLAN هو معرّف VLAN الذي يُضبط بالقيمة 100). سيُطبّق المبدّل الآن قواعده العادية لتمرير الرزمة، مع التقييد الإضافي الذي يقضي بعدم إمكانية إرسال الرزمة إلى واجهة ليست جزءًا من الشبكة VLAN 100. وبالتالي لن تُرسَل الرزمة تحت أي ظرفٍ، حتى ولو كانت رزمة بثٍ إذاعي، من الواجهة إلى المضيف Z الموجود في الشبكة VLAN 200، ولكن يُعاد توجيه الرزمة إلى المبدّل S1، الذي يتّبع نفس القواعد وبالتالي فقد يُمرر الرزمة إلى المضيف W، ولكن ليس إلى المضيف Y. الميزة الجذابة في شبكات VLAN هي إمكانية تغيير المخطط المنطقي دون نقل أيّ أسلاك أو تغيير أيّ عناوين. فإذا أردت جعل الرابط الذي يتصل بالمضيف Z جزءًا من شبكة VLAN 100 على سبيل المثال -بالتالي تفعيل المضيفين X وW وZ ليكونوا على نفس شبكة LAN الوهمية- ، فستحتاج فقط إلى تغيير جزء واحد من ضبط المبدّل S2. يتطلّب دعم شبكات VLAN امتدادًا بسيطًا إلى حدٍ ما لمواصفات ترويسة 802.1 الأصلية، وإدخال حقل معرّف VLAN المؤلَّف من 12 بتًا VID بين الحقلين SrcAddr وType، كما هو موضح في الشكل الآتي. (يُشار إلى المعرّف VID هذا عادةً باسم VLAN Tag. يوجد بالفعل 32 بتًا أُدخلت في منتصف الترويسة، ولكن يُستخدم أول 16 بتّا للحفاظ على التوافق العكسي مع المواصفات الأصلية (حيث تستخدم Type = 0x8100 للإشارة إلى احتواء هذا الإطار على امتداد شبكة VLAN، حيث تحتوي البتات الأربعة الأخرى على معلومات التحكم المُستخدمة لتحديد أولويات الإطارات، وهذا يعني أنه من الممكن ربط 212 = 4096 شبكةً افتراضية مع شبكة محلية فيزيائية واحدة. نختتم هذه المناقشة بملاحظة وجود قيود أخرى على الشبكات التي أُنشئت عن طريق ربط مبدّلات L2، وهي عدم وجود دعم لعدم التجانس heterogeneity. أي أنّ المبدّلات محدودة بأنواع الشبكات التي يمكن ربطها، حيث تستخدِم المبدّلات ترويسة إطار الشبكة، وبالتالي يمكنها دعم الشبكات التي لها نفس صيغة العناوين. بحيث يمكن استخدام المبدّلات لتوصيل شبكات إيثرنت والشبكات المستندة إلى المعيار 802.11 ببعضها بعضًا، نظرًا لاشتراكها في صيغة ترويسة مشتركة. لكن المبدّلات لا تعمَّم بسهولة على أنواع الشبكات الأخرى ذات صيغ العنونة المختلفة، مثل شبكات ATM، وSONET، وPON، أو الشبكة الخلوية. يوضّح المقال التالي كيفية معالجة هذا القيد، بالإضافة إلى توسيع نطاق شبكات التبديل إلى أحجامٍ أكبر. ترجمة -وبتصرّف- للقسم Switched Ethernet من فصل Internetworking من كتاب Computer Networks: A Systems Approach. اقرأ أيضًا المقال التالي: شبكة الإنترنت باستخدام بروتوكول IP المقال السابق: التشبيك Internetworking بين أنواع مختلفة من الشبكات الحاسوبية
-
هناك العديد من التقنيات التي يمكن استخدامها لبناء "روابط الميل الأخير" last-mile links أو لتوصيل عددٍ قليل من العُقد معًا، ولكن كيف يمكن بناء شبكات على نطاق عالمي؟ لا يمكن لشبكة إيثرنت واحدة ربط أكثر من 1024 مضيفًا، حيث يصل الرابط ذو النوع "من نقطة لنقطة" point-to-point link بين مضيفَين فقط، بينما تقيَّد الشبكات اللاسلكية بنطاق أجهزة الراديو الخاصة بها، وتحتاج إلى طريقةٍ لربط هذه الأنواع المختلفة من الروابط والشبكات متعددة الوصول لبناء شبكةٍ عالمية. يُعَدّ مفهوم الربط بين أنواع مختلفة من الشبكات لبناء شبكة عالمية كبيرة هو الفكرة الأساسية للإنترنت وغالبًا ما يشار إليه باسم التشبيك internetworking. يمكن تقسيم مشكلة التشبيك (عدم اتصال الشبكات ببعضها مباشرة Not All Networks are Directly Connected) إلى عددٍ قليل من المشاكل الفرعية، حيث ستحتاج أولًا إلى طريقة لوصل الروابط، إذ تسمّى غالبًا الأجهزة التي تصل بين روابط من نفس النوع بالمبدّلات switches، أو مبدلات الطبقة الثانية L2، كما يُستخدَم صنفٌ مهمٌ وخاص من مبدّلات الطبقة الثانية حاليًا وهو النوع المُستخدَم لربط أقسام الإيثرنت، وتُسمّى هذه المبدّلات أيضًا جسورًا bridges في بعض الأحيان. تتمثل المهمة الأساسية للمبدّل في أخذ الرُّزم المستقبَلة وإعادة تمريرها (أو تبديلها) إلى المخارج الصحيحة (أو الوجهة النهائية) حتى تصل إلى وجهتها المناسبة، وهناك مجموعة متنوّعة من الطرق التي يمكن للمبدّل من خلالها تحديد مخارج الرزمة الصحيحة، والتي يمكن تصنيفها غالبًا إلى طرقٍ عديمة الإتصال connectionless؛ أي أنها لا تتطلب إنشاء اتصال، وطرقٍ معتمدة على الاتصالات connection-oriented، وقد وُجدت مجالات تطبيقية مهمة لهاتين الطريقتين على مرّ السنين. نظرًا للتنوع الهائل في أنواع الشبكات، نحتاج أيضًا إلى طريقة لربط الشبكات والروابط المختلفة أي التعامل مع عدم التجانس heterogeneity . حيث تُعرف الأجهزة التي تؤدي هذه المهمة، والتي سُمِّيت في السابق بوابات gateways، باسم الموجّهات routers أو مبدّلات الطبقة الثالثة L3. اُخترع بروتوكولٌ للتعامل مع أنواع الشبكات المختلفة هو بروتوكول الإنترنت Internet Protocol أو اختصارًا IP. من المحتمل أن يكون هناك العديد من الطرق الممكنة للانتقال من نقطةٍ إلى أخرى بمجرد ربط مجموعة كبيرة من الروابط والشبكات بالمبدّلات والموجّهات، ويُعدّ العثور على مسارٍ أو توجيه مناسب عبر شبكة ما، أحد أهم المشاكل الرئيسية للشبكات. إذ يجب أن تكون هذه المسارات فعّالةً (ليست أطول من اللازم مثلًا) وخاليةً من الحلقات، وقادرةً على الاستجابة لحقيقة أنّ الشبكات ليست ثابتة، فقد تفشل العقد أو يُعاد تشغيلها، كما قد تنقطع الروابط، وتُضاف عقدٌ أو روابط جديدة. لابد من توفُّر بعض الأجهزة اللازمة لأداء عمليات التبديل والتوجيه. إذ توجد العديد من المواقف التي تُستخدَم فيها تصميمات متخصّصة لمبدّلات وموجّهات الرزم رغم تشابُه العديد منها وإلى حدٍّ كبير مع الحواسيب ذات الأغراض العامة، وهذه الحالة خاصة بالنهاية العليا، حيث يبدو أنّ هناك حاجة مُلِّحة لمزيد من سعة التبديل التي يمكنها التعامل مع حِمل حركة مرور البيانات traffic load المتزايد باستمرار في نواة شبكة الإنترنت. أساسيات التبديل Switching Basics المبدّل هو آلية تسمح بتوصيل الروابط لتشكيل شبكة أكبر، وهو جهازٌ متعدِّد المداخل والمخارج ينقل الرزم من مدخلٍ واحد إلى مخرجٍ أو أكثر، وهكذا يضيف المبدّل مخططَ الشبكة النجمي (الموضّح في الشكل الآتي) إلى مجموعة معماريات الشبكة الممكنة، ويتميز المخطط النجمي بعدّة خصائص: يحتوي المبدّل على عددٍ ثابت من المداخل والمخارج، مما يحدّ من عدد المضيفين الممكن توصيلها بمبدّلٍ واحد، ولكن يمكن بناء شبكات كبيرة عن طريق تشبيك عدد من المبدّلات ببعضها بعضًا. يمكن توصيل المبدّلات ببعضها البعض وبالمضيفين باستخدام روابط نقطة إلى نقطة point-to-point links، مما يشيرعادةً إلى إمكانية بناء شبكات ذات نطاق جغرافي كبير. لا يقلل إضافةُ مضيفٍ جديد إلى الشبكة عن طريق توصيله بمبدّل من أداء الشبكة للمضيفين الآخرين المتصلين بالشبكة مسبقًا. لا يمكن تطبيق البند الأخير على شبكات الوسائط المشتركة shared-media networks التي نوقشت سابقًا، فمن المستحيل على سبيل المثال لمضيفَين على نفس مقطع الإيثرنت بسرعة 10 ميجابت في الثانية الإرسالَ باستمرار بسرعة 10 ميجابت في الثانية، لأنهما يشتركان في نفس وسط الإرسال، لكن بما أنّ كلّ مضيفٍ على شبكةٍ مبدَّلة يملك رابطًا خاصًا به إلى المبدّل، فقد يكون من الممكن للعديد من المضيفين الإرسال بسرعة الرابط الكاملة التي تمثّل حيز النطاق التراسلي bandwidth، بشرط أن يكون المبدّل مصمَّمًا بسعة إجمالية كافية، حيث يُعدّ توفيرُ إنتاجية كليّة عالية أحدَ أهداف تصميم المبدّل، وتُعدّ الشبكات المُبدَّلة أكثر قابليةً للتوسع (أي أكثر قدرةً على النمو إلى أعدادٍ كبيرة من العقد) من شبكات الوسائط المشتركة بسبب قدرتها على دعم عدّة مضيفين بأقصى سرعة. يُوصَل المبدّل بمجموعة من الروابط، ويشغِّل بروتوكول ربط البيانات المناسب لكلٍ من هذه الروابط للتواصل مع العقدة الموجودة في الطرف الآخر من الرابط. وتتمثل مهمة المبدّل الأساسية في تلقّي الرُّزم الواردة على أحد روابطه وإرسالها على رابطٍ آخر، حيث يشار إلى هذه الوظيفة أحيانًا إمّا بالتبديل switching أو بـالتمرير forwarding، وهي الوظيفة الرئيسية لطبقة الشبكة network layer، بالنسبة لمعمارية نموذج اتصال الأنظمة المفتوحة Open Systems Interconnection أو اختصارًا OSI. السؤال إذًا هو كيف يقرِّر المبدّل اختيار رابط الخرج المناسب لإيصال الرزم إليه؟ الجواب العام هو أنّه يبحث في ترويسة header الرزمة عن المعرّف المُستخدم لاتخاذ هذا القرار. تختلف تفاصيل كيفية استخدامه لهذا المعرّف، إلا أن هناك عدّة طرق شائعة لتحديد ذلك. الأولى هي طريقة مخطط البيانات datagram أو الطريقة عديمة الإتصال connectionless، والطريقة الثانية هي الدارة الافتراضية virtual circuit أو الطريقة الموجَّهة بالاتصال connection-oriented، أمّا الطريقة الثالثة فهي توجيه المصدر source routing وهي الأقلّ شيوعًا من الأسلوبين الآخرين، ولكن لديها بعض التطبيقات المفيدة. يوجد شيءٌ واحد مشترك بين جميع الشبكات هو الحاجة إلى طريقة لتعريف العقد النهائية، وتسمّى هذه المعرّفات بالعناوين addresses، ويوجد عدّة أمثلة عن العناوين مثل عنوان 48 بت المُستخدَم لشبكة إيثرنت. ويُعَدّ الشرط الوحيد لعناوين إيثرنت هو عدم وجود عقدتين على الشبكة لهما نفس العنوان، بحيث يتحقّّق ذلك عن طريق التأكد من تخصيص معرّفٍ فريد عالميًا لجميع بطاقات إيثرنت. وسنفترض هنا امتلاك كلّ مضيف لعنوان فريد عالميًا، إضافةً إلى وجود طريقةً لتحديد منافذ الدخل والخرج لكلّ مبدّل. هناك على الأقل طريقتان مقبولتان لتحديد المنافذ هما: ترقيم كل منفذ port، والثانية تحديد المنفذ باسم العقدة (سواءً كانت مبدّلًا أو مضيفًا) التي يؤدّي إليها. تُستخدم طريقة ترقيم المنافذ حاليًا. تعدد الإرسال بتقسيم الطول الموجي الكثيف Dense Wavelength Division Multiplexing نركّز ضمن شبكات تبديل الرزم packet-switched لا سيما في شبكات المناطق الواسعة wide-area networks أو اختصارًا WAN، على حقيقة أنّ النقل الفيزيائي الأساسي يكون ضوئيًا optical بالكامل -أي لا توجد رزم-، حيث تستطيع معدّات تعدّد الإرسال تقسيم الطول الموجي الكثيف Dense Wavelength Division Multiplexing أو اختصارًا DWDM المتاحة تجاريًا نقلَ أعداد كبيرة من الأطوال الموجية الضوئية (الألوان) في هذه الطبقة خلال ليفٍ واحد. فقد تُرسَل بيانات على 100 أو أكثر من الأطوال الموجية المختلفة على سبيل المثال، وقد يحمل كلّ طول موجيّ ما يصل إلى 100 جيجابت في الثانية من البيانات. توصَل هذه الألياف بجهازٍ ضوئي يسمى معدّدات الإضافة والحذف الضوئية القابلة لإعادة الضبط Reconfigurable Optical Add/Drop Multiplexers أو اختصارًا ROADM، حيث تُشكِّل مجموعةٌ من أجهزة ROADM (التي تمثّل العقد) والألياف (التي تمثّل الروابط) شبكة نقلٍ ضوئية. تستطيع أجهزة ROADM إعادة توجيه أطوال موجيّة منفردة على طول مسار متعدّد القفزات، مما يؤدّي إلى إنشاء دارة منطقية من طرفٍ إلى طرف. ويبدو الطول الموجي الواحد من منظور شبكة تبديل الرزم التي أنشِئت فوق هذا النقل الضوئي مثل رابط نقطةٍ لنقطة واحدٍ بين مبدّلين حتى لو عبرَ هذا الطول الموجي عدّة أجهزة ROADM، ويمكن اختيار تشغيل بروتوكول SONET، أو بروتوكول إيثرنت 100 جيجابت في الثانية كبروتوكول تأطيرframing protocol. إن ميزة إعادة ضبط أجهزة ROADM تعني إمكانية تغيير هذه الأطوال الموجية الكامنة من طرف إلى طرف، ممّا يؤدّي إلى إنشاء مخططٍ جديد في طبقة تبديل الرزمة بفعالية. مخططات البيانات Datagrams فكرة مخطّطات البيانات بسيطة جدًا، فما عليك سوى تضمين معلوماتٍ كافية في كلّ رزمة لتمكين أيّ مبدّلٍ من تحديد طريقة توصيله بوجهته أي احتواء كلّ رزمة على عنوان الوجهة الكامل. ليكن مثال الشبكة الموضّح في الشكل الآتي، حيث يمتلك المضيفين A وB وC عناوينًا. يستعين المبدّل بجدول التمرير forwarding table، والمُسمى أحيانًا جدول التوجيه routing table لتحديد كيفية إعادة توجيه الرزمة. ويوضّح الجدول الآتي معلومات إعادة التوجيه التي يحتاجها المبدّل رقم 2 لإعادة توجيه مخطّطات البيانات في نموذج الشبكة. يُعَدّ اكتشاف مثل هذا الجدول أمرًا سهلًا عندما يكون هناك خارطة كاملة لشبكةٍ بسيطة مثل الشبكة الموضّحة هنا، حيث يمكن لمشغّل الشبكة ضبط الجداول بصورة ثابتة. ولكنّ إنشاء جداول إعادة التوجيه في شبكات كبيرة ومعقدة وذات مخططٍ متغيِّر ديناميكيًا ومسارات متعدّدة بين الوجهات يُعَدّ أمرًا صعبًا جدًا، وتُعرف هذه المشكلة الصعبة باسم التوجيه routing، الذي سنتكلم عنه لاحقًا. يمكن التفكير في التوجيه كعملية تحدث في الخلفية background بحيث سيكون لديك المعلومات الصحيحة في جدول إعادة التوجيه عندما تظهر رزمة بيانات لتتمكّن من إعادة توجيه الرزمة أو تبديلها. 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; } الوِجهة Destination المنفذ Port A 3 B 0 C 3 D 3 E 2 F 1 G 0 H 0 تتمتع شبكات مخطَّط البيانات بالخصائص التالية: يمكن للمضيف إرسال رزمةٍ في أيّ مكان وفي أيّ وقت، حيث يمكن إعادة توجيه أيّ رزمة تظهر عند التبديل على الفور (على افتراض وجود جدول إعادة توجيه معبّأ بصورة صحيحة)، ولهذا السبب تسمى شبكات مخطط البيانات غالبًا بـ عديمة الاتصال connectionless، ويتناقض هذا مع الشبكات الموجَّهة بالاتصال connection-oriented والتي يلزم فيها إنشاء حالة اتصال قبل إرسال رزمة البيانات الأولى. لا توجد طريقة لدى المضيف لمعرفة ما إذا كانت الشبكة قادرةً على توصيل رزمةٍ يريد إرسالها أو إذا كان المضيفُ الوجهة يعمل. يُعاد توجيه كلّ رزمة بصورة مستقلة عن الرزم السابقة التي قد تُرسَل إلى نفس الوجهة، وبالتالي قد تتّبع رزمتان متتاليتان من المضيف A إلى المضيف B مسارات مختلفة تمامًا (ربما بسبب تغيير في جدول إعادة التوجيه في بعض المبدّلات في الشبكة). قد لا يكون لفشل المبدّل أو الرابط أيّ تأثيرٍ خطير على الاتصال إذا توفّر مسارٍ بديل مع امكانية تحديث جدول التمرير وفقًا لذلك. هذه الحقيقة الأخيرة مهمة خاصةً لتاريخ شبكات البيانات، فأحد أهداف التصميم الهامة للإنترنت هو المتانة في مواجهة حالات الفشل، وقد أظهر التاريخ أنّ شبكات مخطَّط البيانات فعالة جدًا في تحقيق هذا الهدف. تبديل الدارة الافتراضية Virtual Circuit Switching تَستخدم التقنية الثانية لتبديل الرزم مفهوم الدارة الافتراضية virtual circuit أو اختصارًا VC، ويتطلّب هذا الأسلوب الذي يُشار إليه أيضًا بإسم النموذج الموجَّه بالاتصال connection-oriented model إعداد اتصال افتراضي من المضيف المصدر إلى المضيف الوجهة قبل إرسال أيّ بيانات. افترض الشكل التالي، حيث يريد المضيف A مرةً أخرى إرسال رزمٍ إلى المضيف B، ويمكنك التفكير بذلك كعملية مكوَّنة من مرحلتين: الأولى هي إعداد الاتصال connection setup، والثانية نقل البيانات data transfer، حيث تجري كل مرحلة بدورها. من الضروري إنشاء حالة اتصال في مرحلة إعداد الاتصال في كل المبدّلات الواقعة بين مضيفي المصدر والوجهة. تتكون حالة الاتصال لاتصالٍ واحد من مدخلةٍ في جدول VC في كلّ مبدّلٍ يمرّ من خلاله الاتصال، كما تحتوي المدخلة في جدول VC لكلّ مبدّل على: معرّف الدارة الافتراضية virtual circuit identifier أو اختصارًا VCI الذي يعرّف الاتصالَ في هذا المبدّل بطريقة فريدة، كما سيُحمَل داخل ترويسة الرزم التي تنتمي إلى هذا الاتصال. واجهة واردة incoming interface تصل عليها رزم VC إلى المبدّل. واجهة صادرة outgoing interface تُترك فيها الرزمُ الخاصة بهذه الدارة الافتراضية VC المبدّلَ. معرّفات VCI مختلفة مُحتملة ستُستخدَم للرزم الصادرة. دلالات إحدى هذه المدخلات هي كما يلي: إذا وصلت رزمة إلى الواجهة الواردة المعينة واحتوت تلك الرزمة على قيمة معرّف VCI معينة في ترويستها، يجب إرسال تلك الرزمة إلى الواجهة الصادرة المحدّدة مع قيمة معرّف VCI الصادرة المحدّدة التي وُضعت لأوّل مرة في ترويستها. يُحدّد الاتصال الافتراضي بصورة فريدة من خلال مزيج من معرّف VCI للرُّزم المُستلمة عند المبدّل والواجهة التي تُستلَم عليها. وقد يكون هناك بالطبع العديد من الاتصالات الافتراضية التي تُنشأ في المبدّل في وقتٍ واحد. كما أن قيم VCI الواردة والصادرة ليست متطابقة، وبالتالي فإن معرّف VCI ليس ذا أهمية اتصالٍ عالمية، بل تكمن أهميته على رابط معين (أي أنّه يحتوي على نطاق رابط محلي). لا بد من إسناد معرّفٍ VCI جديد للاتصال الجديد الذي ينشَأ على كلّ رابطٍ يجتازه هذا الاتصال، إضافةً إلى التأكد من أنّ معرّف VCI المُختار على رابطٍ معين ليس قيد الاستخدام حاليًا على هذا الرابط بواسطة بعض الاتصالات الحالية. هناك طريقتان لتأسيس حالة الاتصال: الأولى هي ضبط مسؤول الشبكة network administrator للحالة وهنا تكون الدارة الافتراضية دائمة permanent ويمكن للمسؤول حذفها أيضًا. لذلك قد يُنظر إلى الدارة الافتراضية الدائمة permanent virtual circuit أو اختصارًا PVC على أنها دارة VC طويلة العمر أو مضبوطة إداريًا. كما يمكن للمضيف بدلًا من ذلك إرسال رسائل إلى الشبكة لتأسيس الحالة، حيث يُشار إلى ذلك بعملية إصدار الإشارات signalling، ويُقال إن الدارات الافتراضية الناتجة قد بُدِّلت، أمّا السمة البارزة لـ الدارة الافتراضية المُبدَّلة switched virtual circuit أو اختصارًا SVC، فهي قدرة المضيف على إعداد وحذف مثل دارة VC هذه ديناميكيًا دون تدخُّل مسؤول الشبكة. يجب أن يُطلق على دارة SVC بصورة أدق اسم دارة VC ذات الإشارة signalled، نظرًا لأن ما يميز دارة SVC عن دارة PVC استخدام الإشارات (وليس التبديل). عند رغبة مسؤول الشبكة في إنشاء اتصال افتراضي جديد يدويًا من المضيف A إلى المضيف B، يحتاج أولًا إلى تحديد مسار عبر الشبكة من المضيف A إلى المضيف B -يوجد مسار واحد فقط في مثال الشبكة بالشكل السابق ولكن قد لا يكون هذا هو الحال دائمًا-، ثم يختار المسؤول قيمة معرّف VCI غير المستخدم حاليًا على كلّ رابطٍ للاتصال. على افتراض أنّ قيمة معرّف VCI هي 5 للرابط من المضيف A إلى المبدّل 1، واختيرت القيمة 11 للرابط من المبدّل 1 إلى المبدّل 2، وبالتالي سيحتاج المبدّل 1 مدخلةً في جدول VC الخاص به المضبوط كما هو موضح في الجدول التالي: الواجهة الواردة Incoming Interface VCI الوارد Incoming VCI الواجهة الصادرة Outgoing Interface VCI الصادر Outgoing VCI 2 5 1 11 لنفرض أنّ قيمة معرّف VCI هي 7 لتحديد هذا الاتصال على الرابط من المبدّل 2 إلى المبدل 3، وأنّ قيمة معرّف VCI هي 4 للرابط من المبدّل 3 إلى المضيف B. سيحتاج المبدّل 2 في هذه الحالة لضبطه مع مدخلات جدول VC كما هو موضح في الجدول التالي: الواجهة الواردة Incoming Interface VCI الوارد Incoming VCI الواجهة الصادرة Outgoing Interface VCI الصادر Outgoing VCI 3 11 2 7 ويحتاج المبدّل 3 لضبطه مع مدخلات جدول VC كما هو موضح في الجدول التالي: الواجهة الواردة Incoming Interface VCI الوارد Incoming VCI الواجهة الصادرة Outgoing Interface VCI الصادر Outgoing VCI 0 7 1 4 لاحظ أن قيمة معرّف VCI الصادر عند أحد المبدّلات هي قيمة معرّف VCI الواردة عند المبدّل الذي يليه. يمكن المضي قدمًا في مرحلة نقل البيانات بمجرد إعداد جداول VC، كما هو موضح في الشكل السابق. ويضع المضيف A قيمة معرّف VCI البالغة 5 في ترويسة الرزمة المراد إرسالها إلى المضيف B ويرسلها إلى المبدّل 1، ويستقبل المبدّل 1 أية رزمة من هذا القبيل على الواجهة 2 ويستخدم مزيجًا من الواجهة ومعرّف VCI في ترويسة الرزمة للعثور على مدخلة جدول VC المناسبة. وكما هو مُبين في الجدول الخاص بالمبدّل 1، ستخبر مدخلةُ الجدول في هذه الحالة المبدّلَ 1 بإعادة توجيه الرزمة من الواجهة 1، ووضع قيمة معرّف VCI التي هي 11 في الترويسة عند إرسال الرزمة. وبالتالي ستصل الرزمة إلى المبدّل 2 على الواجهة 3 حيث يحمل معرّف VCI القيمة 11، ويبحث المبدّل 2 عن الواجهة 3 ومعرّف VCI ذي القيمة 11 في جدول VC الخاص به ويرسل الرزمة للمبدّل 3 بعد تحديث قيمة معرّف VCI في ترويسة الرزمة بصورة مناسبة، كما هو مبين في الشكل الآتي. تستمر هذه العملية حتى الوصول إلى المضيف B مع معرّف VCI ذي القيمة 4 في الرزمة وهذا يحدِّد بالنسبة للمضيف B أنّ الرزمة جاءت من المضيف A. يزداد عبء ضبط جداول VC بطريقة صحيحة في عدد كبير من المبدلات بشكل متسارع باستخدام الإجراءات المذكورة أعلاه في الشبكات الحقيقية ذات الحجم المعقول، وبالتالي تُستخدَم أداة إدارة الشبكة أو نوع من إصدار الإشارات (أو كليهما) دائمًا تقريبًا، حتى عند إعداد دارات VC دائمة permanent. يبدأ مسؤول الشبكة في إصدار الإشارات signalling في حالة دارات PVC، بينما يُعِدّ أحد المضيفين دارات SVC باستخدام إصدار الإشارات. يرسل المضيف A رسالة إعداد setup message إلى الشبكة (أي إلى المبدل 1) لبدء عملية إصدار الإشارات. تحتوي رسالة الإعداد، من بين أشياء أخرى، على عنوانَ الوجهة الكامل للمضيف B. يجب أن تصل رسالة الإعداد إلى كلّ الطريق الواصل إلى المضيف B لإنشاء حالة الاتصال اللازمة في كلّ مبدل على طول ذلك الطريق. يمكن الملاحظة بأن إحضار رسالة الإعداد إلى المضيف B يشبه إلى حدٍ كبير حصول المضيف B على مخطط بيانات datagram، حيث يتعين على المبدلات معرفة المخارج التي ستُرسَل رسالة الإعداد إليها حتى تصل في النهاية إلى المضيف B. بفرض أن المبدّلات تعرف حاليًا ما يكفي عن مخطط الشبكة لمعرفة كيفية القيام بذلك، تتدفق رسالة الإعداد إلى المبدّلين 2 و3 قبل وصولها أخيرًا إلى المضيف B. ينشئ المبدّل 1 مدخلةً جديدةً في جدول دارته الافتراضية للاتصال الجديد عندما يتلقّى طلب الاتصال، إلى جانب إرساله إلى المبدّل 2. هذه المدخلة هي نفسها تمامًا كما هو موضّح سابقًا في الجدول الخاص بالمبدّل 1، ولكنّ الفرق الرئيسي هو أنّ مهمّة إسناد معرّف VCI غير مستخدم على الواجهة ينفذّها المبدّل لهذا المنفذ، فيختار المبدّل القيمة 5 في هذا المثال. يحتوي جدول الدارة الافتراضية الآن على المعلومات التالية: "عند وصول الرُّزم إلى المنفذ 2 بالمعرّف 5، أرسلْها على المنفذ 1". هناك مشكلة أخرى تتمثّل في حاجة المضيف A إلى معرفة وجوب وضع قيمة معرّف VCI البالغة 5 في الرُّزم التي يريد إرسالها إلى المضيف B. ينفّذ المبدّل 2 عمليةً مماثلةً عندما يتلقّى رسالة الإعداد، حيث يختار في هذا المثال القيمة 11 على أساس قيمة VCI الواردة، وبالمثل يختار المبدّل 3 القيمة 7 على أساس قيمة VCI الواردة، ويمكن لكلّ مبدّل اختيار أيّ رقمٍ يريد طالما أنّ هذا الرقم ليس قيد الاستخدام حاليًا لاتصالٍ آخر على هذا المنفذ من هذا المبدّل. وكما ذُكر أعلاه، تمتلك VCI نطاق رابط محلي، وهي بذلك لا تحمل أيّ أهمية عالمية. بعد أن تصل رسالة الإعداد إلى المضيف B أخيرًا، وبافتراض سلامة المضيف B واستعداده لقبول اتصالٍ من المضيف A، سيُخصّص أيضًا قيمة معرّف VCI الوارد، وهي في هذه الحالة 4، كما يمكن للمضيف B استخدام قيمة معرّف VCI هذه لتحديد جميع الرزم القادمة من المضيف A. يجب إخبار الجميع بقيمة معرّف VCI التي يستخدمها جارهم التالي من أجل هذا الاتصال، فيرسل المضيف B إشعارًا بإعداد الاتصال للمبدّل 3 ويضمّن في تلك الرسالة قيمة معرّف VCI التي اختارها (وهي 4)، وبهذا يستطيع المبدل 3 الآن إكمال مدخلة جدول الدارة الافتراضية لهذا الاتصال، فهو يعرف أن القيمة الصادرة يجب أن تكون 4، كما يرسل المبدل 3 الإشعار إلى المبدّل 2 مع تحديد قيمة معرّف VCI التي هي 7، ثم يرسل المبدّل 2 الرسالة إلى المبدّل 1 مع تحديد قيمة معرّف VCI التي هي 11 ، وبهذا يمرّر المبدّل 1 الإشعار إلى المضيف A أخيرًا، ويطلب منه استخدام قيمة معرّف VCI التي هي 5 لهذا الاتصال. يعرف الجميع في هذه المرحلة كلّ ما هو ضروري للسماح بتدفّق حركة مرور البيانات من المضيف A إلى المضيف B، حيث يحتوي كلّ مبدّلٍ على مدخلةٍ كاملةٍ لجدول الدارة الافتراضية للاتصال، كما يمتلك المضيف A علاوةً على ذلك، إقرارًا راسخًا بأنّ كلّ شيء في مكانه على طول الطريق إلى المضيف B. وتكون مدخلات جدول الاتصال في هذه المرحلة في مكانها في جميع المبدّلات الثلاثة تمامًا كما في المثال الذي ضُبِط إداريًا سابقًا، ولكن حدثت العملية بأكملها تلقائيًا استجابةً لرسالة إصدار الإشارة signalling message المرسَلة من المضيف A. ويمكن الآن البدء في مرحلة نقل البيانات وهي مماثلة لتلك المستخدمة في حالة دارة PVC. يفكّك المضيف A الاتصال عن طريق إرسال رسالة تحرير teardown إلى المبدّل 1، عندما لا يرغب المضيف A في إرسال بيانات إلى المضيف B. كما يزيل المبدّل المدخلة ذات الصلة من جدوله ويعيد توجيه الرسالة إلى المبدّلات الأخرى في المسار، والتي تحذف أيضًا مدخلات الجدول المناسبة. فإذا أرسل المضيف A رزمةً بمعرّفٍ VCI هو 5 إلى المبدل 1، ستُهمَل كما لو لم يكن الاتصال موجودًا مطلقًا. هناك العديد من الأشياء التي يجب ملاحظتها حول تبديل الدارة الافتراضية virtual circuit، وهي: يوجد تأخير واحد على الأقل ذهابًا وإيابًا round-trip time أو اختصارًا RTT قبل إرسال البيانات، لأنّ على المضيف A انتظار وصول طلب الاتصال إلى الجانب البعيد من الشبكة ثم العودة إليه قبل تمكُّنه من إرسال رزمة البيانات الأولى. يحتوي طلب الاتصال على العنوان الكامل للمضيف B، الذي قد يكون كبيرًا جدًا، لأنه معرّف عالمي global identifier على الشبكة. ولكن تحتوي كلّ رزمة بيانات على معرّف صغير واحد فريد فقط على رابطٍ واحد، وهو ما يُقلَّل حِمل كلّ رزمة ناجمٌ عن الترويسة بالنسبة إلى نموذج مخطّط البيانات. والأهم من ذلك هو سرعة البحث، نتيجة تعامله مع رقم الدارة الافتراضية على أنه دليلٌ في جدول بدلًا من عدّه مفتاحًا يجب البحث عنه. إذا فشل مبدّلٌ أو رابطٌ في الاتصال، فسيُقطع الاتصال وبالتالي يجب إنشاء اتصالٍ جديد، ولابدّ أيضًا من تفكيك الاتصال القديم لتحرير مساحة تخزين الجدول في المبدّلات. لقد أُخفيت مسألة كيفية تحديد المبدّل للرابط الذي يعيد توجيه طلب الاتصال عليه. وهي من حيث المضمون نفس مشكلة بناء جدول إعادة التوجيه الخاص بإعادة توجيه مخطط البيانات، حيث يتطلب ذلك نوعًا من خوارزمية التوجيه routing algorithm. سنتحدث عن التوجيه في قسمٍ لاحق، والخوارزميات الموضحة هناك قابلة للتطبيق عمومًا على طلبات إعداد التوجيه بالإضافة إلى مخططات البيانات. أحد الجوانب الجيدة للدارات الافتراضية أنه وبحلول الوقت الذي يحصل فيه المضيف على إشارة البدء لإرسال البيانات، سيعرف المضيف الكثير عن الشبكة كوجود مسارٍ إلى المستقبِل واستعداده وقدرته على تلقّي البيانات. من الممكن أيضًا تخصيص موارد الدارة الافتراضية في وقت إنشائها، فقد استخدمت تقنية X.25 (تقنية الشبكات القائمة على الدارات الافتراضية القديمة والتي عفا عليها الزمن الآن) على سبيل المثال الاستراتيجيةَ التالية المكونة من ثلاثة أجزاء وهي: تُخصَّص المخازن المؤقَّتة Buffers لكلّ دارة افتراضية عند تهيئة الدارة. يُشغَّل بروتوكول النافذة المنزلقة sliding window protocol بين كلّ زوج من العقد على طول الدارة الافتراضية، ويُعزَّز هذا البروتوكول بالتحكم في التدفق لمنع عقدة الإرسال من الإفراط في تشغيل المخازن المؤقَّتة المخصَّصة في العقدة المستقبلة. ترفض عقدةٌ معينة الدارة، إذا لم تتوفّر مخازن مؤقتّة كافية في تلك العقدة عند معالجة رسالة طلب الاتصال. يجب التأكد من احتواء كل عقدة على المخازن المؤقّتة التي تحتاجها لوضع الرُّزم التي تصل إلى تلك الدارة في الرتل عند القيام بهذه الأشياء الثلاثة، حيث تُسمى هذه الإستراتيجية الأساسية التحكم في التدفق قفزةً بقفزة hop-by-hop flow control. لا تحتوي هذه الشبكة، على عكس شبكة مخطّط البيانات datagram، على مرحلة إنشاء اتصال والتي يُعالِج فيها كلّ مبدّل كلّ رزمةٍ بصورة مستقلة، مما يجعل كيفية تخصيص شبكة مخطط البيانات للموارد بطريقةٍ مفيدة أمرًا مُبهمًا. بينما تتنافس هنا كلّ رزمة قادمة مع جميع الرزم الأخرى على مساحة التخزين المؤقت، وإذا لم تكن هناك مخازن مؤقَّتة حرّة، فيجب إهمال الرزمة الواردة، ولكن نلاحظ أنّه غالبًا ما يرسل مضيف المصدر سلسلةً من الرزم إلى مضيف الوجهة نفسه حتى في الشبكة القائمة على مخطّط البيانات، كما يمكن لكلّ مبدّل التمييز بين مجموعة الرزم التي وُضعت في الرتل حاليًا بناءً على زوج مصدر / وجهة source/destination، وبالتالي يضمن المبدّل تلقِّي الرزم التي تنتمي إلى كلّ زوج مصدر / وجهة حصةً عادلة من مخازن المبدّل المؤقَّتة. تزوَّد كلّ دارة بجودة خدمة quality of service أو اختصارًا QoS مختلفة في نموذج الدارة الافتراضية. ويُفهم مصطلح جودة الخدمة عادةً على أنّ الشبكة تمنح المستخدِم نوعًا من الضمان المتعلِّق بالأداء، وهذا بدوره يعني تخصيص المبدلات للموارد التي تحتاجها من أجل الوفاء بهذا الضمان. يمكن تخصيص المبدّلات الموجودة على طول دارة افتراضية معيّنة نسبةً مئويةً من حيّز النطاق التراسلي لكلّ رابطٍ صادر لتلك الدارة، كما قد تضمَن سلسلة المبدّلات عدم تأخير الرزم التي تنتمي إلى دارة معيّنة (في الرتل) لأكثر من فترة زمنيّة معيّنة على سبيل المثال. كان هناك عدد من الأمثلة الناجحة لتقنيات الدارات الافتراضية على مرّ السنين، ولا سيما تقنيات X.25 ترحيل الإطارات Frame Relay ووضع النقل غير المتزامنAsynchronous Transfer Mode أو اختصارًا ATM، ولكن لم يَعُد يتمتّع أيٌّ منها بشعبية كبيرة اليوم بعد نجاح نموذج الإنترنت عديم الاتصال Internet’s connectionless model. كان أحد أكثر تطبيقات الدارات الافتراضية شيوعًا لسنوات عديدة هو إنشاء الشبكات الخاصة الوهمية virtual private networks أو اختصارًا VPN، ولكن حتى هذا التطبيق يُدعَم الآن في الغالب بإستخدام التقنيات المستندة إلى الإنترنت اليوم. وضع النقل اللاتزامني Asynchronous Transfer Mode أو اختصارًا ATM قد تكون تقنية وضع النقل اللاتزامني ATM أكثر تقنيات الشبكات القائمة على الدارات الافتراضية شهرةً، وكانت تقنية ATM مهمةً في الثمانينات وأوائل التسعينات لمجموعة متنوعة من الأسباب، منها احتضان صناعة الهاتف لهذه التقنية، والتي كانت في ذلك الوقت أقلّ نشاطًا في شبكات الحاسوب (بخلاف كونها مزوّدًا للروابط التي بنى الأشخاص الآخرون شبكاتٍ منها). كما تصادَف وجود تقنية ATM في المكان المناسب وفي الوقت المناسب، حيث ظهرت في صورة تقنية تبديل عالية السرعة على الساحة عندما بدأت الوسائط المشتركة، مثل: الإيثرنت، وشبكة الحلقات الرمزية token rings تبدو بطيئةً بعض الشيء بالنسبة للعديد من مستخدمي شبكات الحاسوب، كما كانت تقنية ATM منافسة لتقنية الإيثرنت التبديلية Ethernet switching، وقد عدّها الكثيرون منافسًا لبروتوكول الإنترنت أيضًا. يحتوي الأسلوب الذي تتّبعه تقنية ATM على بعض الخصائص المثيرة للإهتمام، مما يجعل الأمر يستحقّ المزيد من الدراسة. يوضّح الشكل السابق صورة صيغة رزم تقنية ATM والتي تُسمى خلية ATM. يتم تخطِّي بتات التحكم في تدفق التحكم المعمَّم generic flow control أو اختصارًا GFC، والتي لم تشهد استخدامًا كبيرًا من قبل، ونبدأ بالـ 24 بت والتي يُشار إليها بمعرّف VPI (معرّف المسار الافتراضي virtual path identifier -bits 8 وVCI (معرّف الدارة الافتراضية virtual circuit identifier - bits 16. إذا كانت هذه البتات معًا مثل حقل واحد 24 بت، ستتوافق مع معرّف الدارة الافتراضية، وسبب تقسيم الحقل إلى جزئين هو السماح بمستوى من الهرمية، إذ يمكن في بعض الحالات التعامل مع جميع الدارات التي لها نفس معرّف VPI مثل مجموعة (مسار افتراضي)، ويمكن تبديلها معًا بالنظر فقط إلى معرّف VPI، مما يبسّط عمل المبدّل الذي يمكنه تجاهل جميع بتات معرّف VCI وتقليل حجم جدول دارة VC بصورة كبيرة. بالانتقال إلى آخر بايت في الترويسة، نجد فحص التكرار الدوري cyclic redundancy check أو اختصارًا CRC ذو 8 بتات، والمعروف باسم فحص خطأ الترويسة header error check، واختصارًا HEC، والذي يَستخدم آلية CRC-8 ويوفِّر إمكانية اكتشاف الأخطاء وتصحيح الخطأ أحادي البت في ترويسة الخلية فقط. تُعَدّ حماية ترويسة الخلية مهمةً خاصةً لأن أيّ خطأ في VCI، يؤدي إلى خطأٍ في تسليم الخلية. ربما يكون أهم شيء يجب ملاحظته بشأن خلية ATM هو إتيانها بحجم واحد فقط هو 53 بايتًا، وهو السبب في تسميتها خلية cell وليس رزمة packet. ولكن ما هو السبب في ذلك؟ كان أحد الأسباب الرئيسية هو تسهيل تنفيذ عتاد المبدّلات، حيث كانت شبكة إيثرنت بسرعة 10 ميجابت في الثانية هي أحدث التقنيات من حيث السرعة عندما أُنشئت تقنية ATM في منتصف وأواخر الثمانينات. يفكّر الناس الذين تعاملوا مع عالم الهاتف أن المبدّلات شيءٍ كبير، حيث تخدّم مبدّلات الهاتف عشرات الآلاف من العملاء. تُعَد الرزم ذات الطول الثابت شيئًا مفيدًا للغاية عند إنشاء مبدّلات سريعة وقابلة للتوسع بدرجة كبيرة. وهناك سببان رئيسيان لهذا: من الأسهل بناء عتاد للقيام بمهامٍ بسيطة، حيث تكون مهمة معالجة الرزم أبسط عندما تعرف بالفعل المدّة التي تستغرقها معالجة كل رزمة. إذا كانت جميع الرزم بنفس الطول، فقد يكون لديك الكثير من عناصر التبديل التي تقوم جميعها بنفس الشيء على التوازي، ويستغرق كلٌّ منها نفس الوقت لأداء وظيفته. أمّا السبب الثاني وهو تفعيل التوازي enabling of parallelism، فيحسّن بدرجةٍ كبيرة قابلية التوسع في تصميمات المبدّلات، وسيكون من المبالغة القول أنّ عتاد المبدّلات المتوازية السريعة لا يمكن بناؤها إلا باستخدام خلايا ذات طول ثابت، ولكن من المؤكّد أنّ الخلايا تسهّل مهمّة بناء مثل هذا العتاد وأنّ هناك الكثير من المعلومات المُتاحة حول كيفية بناء مبدّلات الخلايا في العتاد في الوقت الذي حُدِّدت فيه معايير تقينة ATM. لا يزال هذا المبدأ نفسه مطبقًا في العديد من المبدّلات والموجّهات اليوم، حتى لو تعاملت مع رزم متغيّرة الطول، حيث قُطِّعت هذه الرزم إلى نوع من الخلايا من أجل إعادة توجيهها من منفذ الدخل إلى منفذ الخرج، ولكن كلّ هذا داخليٌّ بالنسبة للمبدّل. هناك نقطة جيدة أخرى تُحسب لصالح خلايا ATM الصغيرة تتعلّق بوقت الاستجابة من طرفٍ إلى طرف. فقد صُمِّمت تقنية ATM لنقل المكالمات الهاتفية الصوتية (وهو الاستخدام السائد في ذلك الوقت) ولنقل البيانات، ولعلّ آخر شيء تريده هو وجود رزمة صوت صغيرة في رتل خلف رزمة بيانات كبيرة في المبدّل، نظرًا لكون الصوت ذا حيز نطاق تراسلي صغير ولكن له متطلبات تأخير صارمة. وإذا أُجبِرت جميع الرزم على أن تكون صغيرة (أي بحجم الخلية)، لا يزال من الممكن دعم رزم البيانات الكبيرة عن طريق إعادة تجميع مجموعةٍ من الخلايا في رزمة، وستحصل على ميزة القدرة على تداخل interleave خلايا الصوت المُعاد توجيهها مع خلايا البيانات في كلّ مبدّلٍ على طول المسار من المصدر إلى الوجهة. كما تُعَدّ فكرة استخدام الخلايا الصغيرة لتحسين زمن الاستجابة من طرفٍ إلى طرف جيدة وفعّالة وما زالت مُستخدمة حتى اليوم في شبكات الوصول الخلوية. يوجد سؤالٌ آخر بعد أن قرّرتَ استخدام رزم صغيرة ثابتة الطول، والذي يقول ما هو لطول الثابت المناسب؟ إذا كانت قصيرة جدًا، فكمية معلومات الترويسة التي يجب نقلها بالنسبة إلى كمية البيانات التي تناسبها في خلية واحدة تصبح أكبر، وبالتالي تنخفض النسبة المئوية لحيز النطاق التراسلي للرابط المستخدم فعليًا لنقل البيانات. إذا بنيت جهازًا يعالج الخلايا باستخدام أقصى عددٍ من الخلايا في الثانية، فعندها تصبح الخلايا أقصر، وبالتالي ينخفض إجمالي معدّل البيانات بالنسبة لحجم الخلية. قد يكون أحد الأمثلة على مثل هذا الجهاز هو محوّل الشبكة network adaptor الذي يعيد تجميع الخلايا في وحدات أكبر قبل تسليمها إلى المضيف. يعتمد أداء مثل هذا الجهاز مباشرةً على حجم الخلية. ومن ناحية أخرى، إذا كانت الخلايا كبيرة جدًا، هناك مشكلة في حيّز النطاق التراسلي الضائع بسبب الحاجة إلى حشو البيانات المنقولة لملء خلية كاملة. فإذا كان حجم حمولة payload الخلية 48 بايتًا ونريد إرسال 1 بايت، فسنحتاج إلى إرسال حاشية padding قدرها 47 بايتًا، وستكون استخدامية utilization الرابط منخفضةً جدًا، عند الحدوث المتكرر لذلك الأمر. أدى المزج بين معدَّل الترويسة إلى الحمولة العالية نسبيًا مع تكرار إرسال الخلايا المملوءة جزئيًا إلى ضعفٍ ملحوظ في كفاءة شبكات ATM والذي أطلق عليه بعض المنتقدين اسم ضريبة الخلية cell tax. اختير العدد 48 بايتًا لحمولة خلية ATM كحلٍّ وسط وكانت هناك مبررات جيدة لكلٍّ من الخلايا الأكبر والأصغر، ولكن لم يرضِ هذا العدد 48 أحدًا، فإذا كان هذا العدد ناتجًا عن قوى العدد 2 فهو أفضل لأجهزة الحاسوب من أجل المعالجة. توجيه المصدر Source Routing يُعرَف الأسلوب الثالث للتبديل والذي لا يستخدم الدارات الافتراضية ولا مخطّطات البيانات التقليدية بإسم توجيه المصدر Source Routing، ويُشتق هذا الاسم من حقيقة أنّ جميع المعلومات حول مخطّط الشبكة المطلوبة لتبديل رزمة عبر الشبكة يوفّره مضيف المصدر. هناك طرق مختلفة لتطبيق توجيه المصدر. قد تكون إحداها هي إسناد رقم لكلّ مخرج ضمن كلّ مبدّل، ووضع هذا الرقم في ترويسة الرزمة. عندئذٍ تكون وظيفة التبديل بسيطةً جدًا، وتتمثّل بقراءة المبدّل رقم المنفذ الموجود في ترويسة كلّ رزمة واصلة إلى أحد مداخل هذا المبدّل ونقل الرزمة على هذا المخرج. ولكن يجب أن تحتوي ترويسة الرزمة على معلومات كافية للسماح لكلّ مبدّل في المسار بتحديد المخرج الذي يجب وضع الرزمة عليه، نظرًا لأنه سيكون هناك أكثر من مبدّلٍ واحد في المسار بين مضيف الإرسال ومضيف الاستقبال. وتتمثّل إحدى طرق القيام بذلك في وضع قائمةٍ مرتبة بمنافذ المبدّل في الترويسة وتدوير القائمة بحيث يكون المبدّل التالي في المسار دائمًا في مقدّمة القائمة، ويوضح الشكل التالي هذه الفكرة: تحتاج الرزمة إلى اجتياز ثلاثة مبدّلات للانتقال من المضيف A إلى المضيف B في هذا المثال، حيث يجب الخروج من المنفَذ 1 في المبدّل 1، كما يجب الخروج عند المنفذ 0 من المبدّل التالي، ومن المنفذ 3 في المبدّل الثالث. وبالتالي يحتوي العنوان الأصلي عندما تغادر الرزمة المضيف A على قائمة المنافذ (1, 0, 3)، حيث نفترض قراءة كلّ مبدلّ للعنصر الموجود في أقصى اليمين من القائمة. وللتأكد من حصول المبدّل التالي على المعلومات المناسبة، يدوِّر كلّ مبدّلٍ القائمة بعد قراءته للمدخلة الخاصة به. وبالتالي يكون مسار ترويسة الرزمة التي تترك المبدّل 1 إلى المبدّل 2 هو (0 , 3 , 1)، كما يجري المبدّل 2 تدويرًا آخر للقائمة ويرسل رزمةً بها (3 , 1 , 0) في الترويسة. ويجري المبدّل 3 دورانًا آخر على الرغم من عدم ظهوره، بحيث يُعيد الترويسة إلى ما كانت عليه عندما أرسلها المضيف A. هناك العديد من الأشياء التي يجب ملاحظتها في هذه الطريقة، إذ يُفترض أولًا أنّ المضيف A يعرف ما يكفي عن مخطَّط topology الشبكة لتشكيل ترويسة تحتوي على جميع الإتجاهات الصحيحة لكلّ مبدّل في المسار، وهذا مشابه إلى حدٍ ما لمشكلة بناء جداول إعادة التوجيه في شبكة مخطّط بيانات أو معرفة مكان إرسال رزمة الإعداد في شبكة دارة افتراضية. ولكن من الناحية العملية، فأول مبدّلٍ يدخل إلى الشبكة (على عكس المضيف النهائي المتصل بهذا المبدّل) هو الذي يلحق مسار المصدر. ثانيًا، لا يمكن التنبؤ بحجم الترويسة، حيث لابدّ وأن تكون قادرةً على الاحتفاظ بكلمةٍ واحدة من المعلومات لكلّ مبدّل على المسار. هذا يعني أنّ الترويسات قد تكون ذات طول متغّير بدون حدٍّ أعلى، ما لم تتمكن من التنبؤ يقينًا بعدد المبدّلات الأقصى الذي ستحتاجه الرزمة للمرور من خلالها. ثالثًا، هناك بعض الإختلافات في هذه الطريقة. فبدلًا من تدوير الترويسة على سبيل المثال، يمكن لكلّ مبدّل تجريد العنصر الأول فقط أثناء استخدامه. حيث للتدوير ميزة على التجريد، ومع ذلك يحصل المضيف B على نسخة من الترويسة الكاملة، مما قد يساعده في معرفة كيفية العودة إلى المضيف A. وهناك بديل آخر وهو جعل الترويسة تحمل مؤشرًا إلى مدخلة "المنفذ التالي next port" الحالي بحيث يحدّث كلّ مبدّلٍ المؤشر فقط بدلًا من تدوير الترويسة؛ فقد يكون هذا أكثر كفاءةً في التطبيق. نعرض هذه الطرق الثلاث لتوجيه المصدر في الشكل الآتي، حيث سيحتاج المبدّل في كلّ حالة إلى المدخلة A لقراءتها، أمّا المدخلة التي يحتاج المبدّل التالي لقراءتها فهي B؛ وتعرض الحالة (أ) طريقة التدوير rotation، كما تعرض الحالة (ب) طريقة التجريد stripping، بينما تعرض الحالة (ج) طريقة المؤشر pointer، وتُقرأ العناوين من اليمين إلى اليسار: يمكن استخدام توجيه المصدر في كلٍّ من شبكات مخطّطات البيانات وشبكات الدارات الافتراضية. يتضمّن بروتوكول الإنترنت، وهو بروتوكول مخطّط بيانات، خيار مسار المصدر الذي يسمح بتوجيه الرُّزم المحدّدة إلى المصدر، بينما تُبدَّل الغالبية على أنها مخطّطات بيانات تقليدية. يُستخدم توجيه المصدر أيضًا في بعض شبكات الدارات الافتراضية كوسيلة للحصول على طلب الإعداد الأولي على طول المسار من المصدر إلى الوجهة. تُصنَّف أحيانًا مسارات المصدر على أنها صارمة strict أو غير صارمة loose، ويجب تحديد كلّ عقدة على طول المسار في مسار المصدر الصارم، بينما يحدِّد مسار المصدر غير الصارم فقط مجموعة العقد المراد اجتيازها دون تحديد كيفية الانتقال من عقدةٍ إلى أخرى. يمكن عَدُّ مسار المصدر غير الصارم على أنه مجموعة من الإحداثيات وليس مسارًا محددًا تمامًا. كما قد يكون الخيار غير الصارم مفيدًا في تحديد كمية المعلومات التي يجب على المصدر الحصول عليها لإنشاء مسار مصدر. فمن المحتمل أن يكون من الصعب على المضيف الحصول على معلومات المسار الكاملة التي يحتاجها لإنشاء مسار مصدر صارم صحيح إلى أيّ وجهة في أيّ شبكة كبيرة بدرجة معقولة، ولكن يجد كلا النوعين من مسارات المصدر تطبيقًا في سيناريوهات معينة، كما سنرى في الفصول اللاحقة. ترجمة -وبتصرّف- للقسم Switching Basics من الفصل Internetworking من كتاب Computer Networks: A Systems Approach. اقرأ أيضًا المقال التالي: شبكة الإيثرنت المبدلة Switched Ethernet المقال السابق: شبكة الإنترنت باستخدام بروتوكول IP
-
يتحدّث هذا المقال عن أساسيات نظرية الألوان، إذ سنتعلّم كل شيء عن الألوان ابتداءً بخصائصها، ومرورًا بكيفية دمجها، وكيفية التأثير على عملائك من خلال استخدام الألوان بهدف اتخاذ الإجراءات المرغوبة. ما هي الألوان؟ خصائص الألوان نبدأ نظرية الألوان من خلال تعريفها، فتعريف الألوان الأقرب هو أنها تُحدَّد من خلال الطرق المختلفة التي تدرك بها أعيننا الضوء عندما يصطدم بجسم ما، أي يمكن تعريف كل لون من خلال ثلاث خصائص رئيسية تخلق التنوع الهائل لتأثير هذا اللون، وهذه الخصائص هي: الصِبغة Hue: وهي خاصية اللون التي تشير إلى عائلته، أي إلى كل قطعةٍ من عجلة الألوان. توجد 12 قطعة على عجلة الألوان التقليدية، وتمثل كلٌّ منها عائلة ألوان. كثافة اللون Intensity: تمثّل هذه الخاصية تشبّع اللون الذي يحدّد مدى سطوع اللون أو مدى بهتانه. القيمة Value: تشكّل هذه الخاصية الثالثة درجات سطوع tints وتظليلات shades كل لون. تشير هذه الخاصية إلى مدى كون هذا اللون ساطعًا أو كونه داكنًا، إذ يمكنك إنشاء درجات سطوع لونٍ ما بإضافة اللون الأبيض إليه، ويمكنك إنشاء تظليلات لونٍ ما عند إضافة اللون الأسود إليه. تمتلك الألوان أربع خصائص أخرى متعلّقة بصِبغة اللون وكثافته وقيمته. تعلّمنا نظريةُ الألوان أن صِبغة اللون هي قطعة عائلة ألوان معيّنة على عجلة الألوان، لذلك تُعَد هذه الصِبغة أيضًا حالة اللون الأنقى، وبالتالي يمكنك إنشاء درجات لونية وسطوع وتظليلات من خلال تغيير كثافة وقيمة اللون. الدرجات اللونية Tones: يمكنك تشكيل درجات لونية عند إضافة اللون الرمادي إلى صِبغةٍ معينة. درجات السطوع Tints: هي الألوان التي ننشئها عند إضافة اللون الأبيض لصِبغةٍ معيّنة. التظليلات Shades: يمكنك إنشاء تظليلات عند إضافة اللون الأسود إلى صبغة معيّنة. ترغب في الحصول على تصاميم جرافيك مميزة وجذابة؟ وظّف مصمم جرافيك خبير من مستقل لابتكار تصاميم إبداعية تعكس هوية نشاطك التجاري أضف مشروعك الآن عجلة الألوان تُعَد هذه العجلة في نظرية الألوان طريقةً توضيحية لتنظيم وإعطاء تصوّرٍ عن صِبغات الألوان، والعلاقة بينها ضمن هذه العجلة. حيث تظهِر عجلةُ الألوان التقليدية المكوَّنة من 12 صِبغة، الألوانَ الأساسية والثانوية والثالثية، وعلاقاتها كما في الشكل الآتي. إذ يمكنك بسهولة تحديد الألوان التي تتوافق مع بعضها لتكوين تركيبات ألوان متناغمة بطرق متنوعة بفضل هذه النظرية البصرية. أنواع الألوان في نظرية الألوان تبدأ أساسيات الألوان بعجلة الألوان التي تُظهر العلاقات بين جميع أنواع هذه الألوان. تُقسَم الألوان إلى ثلاثة أنواع هي: الألوان الأساسية Ps والتي هي اختصار لـ Primary colors s: كل من اللون الأحمر، والأصفر، والأزرق، هي ألوان الصباغ pigment الثلاثة الأساسية، إذ لا يمكن إنشاء هذه الألوان عن طريق مزج تركيباتٍ أخرى من الألوان، ولكن تعطينا تركيباتُ هذه الصبغات الأساسية جميع الألوان الأخرى. الألوان الثانوية S التي هي اختصار لـ Secondary colors: وتشمل كلًا من اللون: البرتقالي، والأخضر، والبنفسجي، هي الألوان الأولى التي نحصل عليها مباشرةً عند مزج الألوان الأساسية، إذ نحصل على اللون البرتقالي من خلال دمج اللونين الأصفر والأحمر، ونحصل على اللون الأخضر من خلال دمج اللونين الأصفر والأزرق، ونحصل على اللون البنفسجي بدمج اللونين الأحمر والأزرق. الألوان الثالثية Ts والتي هي اختصار لـ Tertiary colors: وتُعرَف أيضًا باسم الألوان الوسيطة intermediates، وهي الصبغات التي نحصل عليها عند دمج اللون الأساسي مع اللون الثانوي. لذلك يتكون اسم كل صِبغةٍ من الألوان الثالثية الستة من كلمتين كالتالي: البرتقالي المائل للأصفر yellow-orange، والبرتقالي المائل للأحمر red-orange، والبنفسجي المائل للأحمر red-violet، والبنفسجي المائل للأزرق blue-violet، والأخضر المائل للأزرق blue-green، والأخضر المائل للأصفر yellow-green. درجة حرارة اللون للألوان درجة حرارة أيضًا في نظرية الألوان، إذ تشير هذه الخاصية إلى البرودة أو الدفء النسبي لكل لون. إذا قسمت عجلة الألوان إلى نصفين، فستبدأ الألوان الباردة باللون البنفسجي وتنتهي بالأخضر المائل للأصفر، بينما تبدأ الألوان الدافئة باللون الأصفر وتنتهي باللون البنفسجي المائل للأحمر. الألوان الباردة Cool colors: تشمل اللون الأزرق وأي لونٍ يتضمن اللون الأزرق مثل مكوّنٍ طاغٍ، حيث كلما اقترب لونٌ ما من اللون الأزرق على عجلة الألوان (أي كلما كان أكثر زرقة)، كان هذا اللون أبرد. الألوان الدافئة Warm colors: تشمل اللون الأصفر وأي لونٍ يتضمن اللون الأصفر كمكوّن طاغٍ. كلما اقترب لونٌ ما من اللون الأصفر على عجلة الألوان (أي كلما كان أكثر اصفرارًا)، كلما كان اللون أدفأ. يُعَد التفاوت بين هذين النوعين من الألوان من حيث درجة الحرارة مفيدًا للغاية في التصميم، ليس فقط بسبب التأثير النفسي للألوان الباردة والدافئة المختلف اختلافًا كبيرًا، بل بسبب الخاصية التي تُظهِر الألوان الباردة بعيدةً عن عين الناظر، وتظهِر الألوان الدافئة أقرب إليه. احصل على التصاميم التي تحتاجها لمشروعك التجاري استعن بأفضل المصممين على خمسات للحصول على تصاميم إبداعية وجذابة اطلب خدمتك الآن الألوان المحايدة Neutral Colors هناك ألوان تكاد لا تحقّق تعريف الألوان، وتُعرف باسم الألوان المحايدة، حيث لا تنتمي إلى فئة الألوان الدافئة ولا إلى فئة الألوان الباردة. تستطيع الألوان المحايدة، وخاصةً الأسود والأبيض، على إنشاء تصميمات مذهلة بمفردها دون استخدام الألوان الحيوية. اللون الأسود: اللون الأسود هو غياب الضوء علميًا، بينما يُنشَأ في التصميم باستخدام أصباغ pigments. يَستخدِم المصممون في الواقع الألوان لإنشاء الألوان السوداء الأدكن تقريبيًا قدر المستطاع، لأن صنع اللون الأسود الحقيقي كصِباغ يُعَد أمرًا مستحيلًا. اللون الأبيض: اللون الأبيض هو غياب اللون ولا يمكنك مزج الألوان لإنشائه مثل اللون الأسود، وتُعَد إعادة إنشاء اللون الأبيض الحقيقي أمرًا مستحيلًا باستثناء ضوء الشمس غير المرشَّح. الألوان المحايدة Neutral colors: هي تظليلات باهتة أو داكنة من الألوان الطبيعية التي تكاد تخلو من الصبغات، وتوجد في مركز عجلة الألوان ومحيطها البعيد. تشمل الألوان المحايدة الأسود، والأبيض، وتدرجات الرمادي، والبني، والقمحي tans. أنواع التركيبات اللونية في نظرية الألوان هناك خمس طرق في هذه النظرية لدمج الألوان باستخدام عجلة الألوان.، حيث يمكنك إنشاء مخططات ولوحات لونية متناغمة بمقدار وُسع خيالك، ولكنّ النتائج ستندرج دائمًا في إحدى الفئات التالية، إذًا لنتعرّف على طريقة عملها. تركيبات الألوان أحادية اللون Monochrome Color Combinations لون واحد وتظليلات متعددة تتمثل الطريقة الأولى والأبسط لدمج الألوان في نظرية الألوان، في إنشاء تركيبة من تباينات مختلفة لصِبغة hue واحدة. ضمّنا في الشكل السابق التظليلات shades، ودرجات السطوع tints المختلفة من صِبغة اللون الأصفر النقي فقط، ولكن يمكنك أيضًا تجربة درجات لونية مماثلة. قد تبدو هذه الطريقة محدودةً، إلا أنها تجربة ممتعة وستعطي دائمًا تصميماتك مظهرًا مبسّطًا وجذابًا بصريًا. وتُعَدّ هذه الطريقة مفيدةً خاصةً للمشاريع التي تتضمن بيانات كثيرة، وتصميمات معقدة بصورةٍ عامة. الميزة الأخرى لهذه الطريقة هي تمييز عملائك لعلامتك التجارية من خلال لون معين، حيث سيؤدي الدمج بين التظليلات ودرجات السطوع والدرجات اللونية المختلفة للون علامتك التجارية، إلى تخصيص هوية علامتك التجارية لك بصورةٍ أكبر. لدينا في المثال الأول الآتي مخطط ألوان أحادي اللون بدرجتين لونيتين مختلفتين من اللون الأزرق اللتين تضيفان الغنى والتنوع على هذا المخطط، بسبب التظليلات ودرجات السطوع المختلفة التي أنشأها التدرج اللوني gradient. ينطبق الأمر نفسه على المثال الثاني الآتي الذي يستخدم تدرجات لونية أيضًا لإثراء درجات اللون البرتقالي. تركيبات الألوان المكمّلة Complementary Color Combinations تجاذب الأضداد الألوان المكمّلة هي الألوان التي تقع مباشرةً مقابل بعضها البعض على عجلة الألوان. يوضّح الشكل التالي مثالَين عن الألوان المكمّلة هما: البرتقالي المائل إلى الأصفر مقابل البنفسجي المائل إلى الأزرق، والأخضر المائل إلى الأزرق مقابل البرتقالي المائل إلى الأحمر. تخلق هذه الألوان تباينًا كبيرًا، وتبرز العناصر التي تريد توجيه انتباه عملائك إليها في تصميمك. يمكن تحقيق ذلك بسهولة عند اختيار اللون المسيطر الذي يكون لونًا باردًا عادةً، ثم استخدام اللون الدافئ المكمّل مع الأقسام الأهم، أو مع الدعوة لاتخاذ إجراء CTA فقط. بما أن هذه الألوان عالية التباين حيويةٌ عند التشبع الكامل، فيجب إدارتها بعناية لتكون متوازنةً وغير متنافرة ومربكة. الألوان المكمّلة الرئيسية هي البنفسجي والأصفر في المثال الأول الآتي. نرى أيضًا إضافةً جميلةً للون الأخضر المُزرَق، واللون الليمي lime، ولكن لا يوجد أي من درجات اللون الأخضر في هذا المثال مكمّلةٌ للبنفسجي أو الأصفر. تًنشئ درجات السطوع الفاتحة pastel من اللون الأخضر المائل إلى الأزرق والبرتقالي المائل إلى الأحمر، تركيبًا مكمّلًا في المثال الثاني الآتي. وهناك أيضًا لونٌ بارز ثالث هو اللون الأصفر، ولكنّه مشابه للمثال الأول، فهو ليس لونًا مكمّلًا لأيٍّ من اللونَين الطاغيين. التركيبات المنقسمة المكملة Split Complementary ثلاثة ألوان مع لمسة إضافية تختلف هذه الطريقة عن الطريقة السابقة في نظرية الألوان، حيث تشكّل لوحاتٍ لونية غنيّة بمزيد من الألوان. يمكنك استخدام ثلاثة ألوان في التركيبات المنقسمة المكمّلة بدلًا من لونين فقط في تركيبات الألوان المكمّلة، إذ تتوضّع هذه الألوان الثلاثة مباشرةً مقابل بعضها البعض على عجلة الألوان. تتضمن اللوحات اللونية في هذه الطريقة ألوانًا باردةً ودافئة/ وتُحقق الكثير من التوازن في تصميماتك. يمكنك استخدام لونين باردين لتصميمك العام، مثل استخدام خلفية زرقاء مع أقسام بنفسجية كما في اللوحات اللونية المكمّلة، ثم تضبط اللون الدافئ للعناصر المستهدَفة وهو اللون البرتقالي في مثالنا. نرى في المثال الأول الآتي تركيبةً منقسمةً مكمّلةً للدرجات اللونية من الأحمر والبنفسجي المائل إلى الأحمر والأخضر، مع إضافة اللون الأبيض من أجل خلق تباين أكبر، بينما يحتوي المثال الثاني على تبايناتٍ من الأصفر، والأرجواني، والزهري. تركيبات الألوان المتشابهة Analogous Color Combinations التناغم المثالي تتوضّع هذه الصبغات بجانب بعضها البعض على عجلة الألوان بعكس الألوان المكمّلة، مما يخلق لوحاتٍ لونية متناغمة ومتوازنة، وتُعَدّ هذه التركيبات طبيعية، إذ يكون أحد هذه الألوان طاغيًا والألوان الأخرى تبرزه وتكمّله. يتيح التناغم استخدام مزيدٍ من الألوان دون تعقيد التصميم. قد يؤدي استخدام لونين أو ثلاثة ألوانٍ فقط في هذه الطريقة إلى جعل التصميم باهتًا أحيانًا، ولمنع حدوث ذلك، يستخدم المصممون ألوانًا محايدةً عالية التباين، مثل: الأسود والأبيض كما سنرى في المثالين الآتيين. حيث يتضمن مخطط الألوان المعتاد لونًا واحدًا مهيمنًا، ولونًا ثانيًا لدعمه، ولونًا ثالثًا محايدًا بارزًا. راهن المصمّم في المثال الأول الآتي على اللون الأزرق والبنفسجي المائل إلى الأزرق، والبنفسجي، والبنفسجي المائل إلى الأحمر التي تمتزج مع بعضها البعض مثل نمط، وتشكّل خلفيةً رائعةً للشعار الأسود. بينما تتباين درجات اللون الأزرق، ودرجات اللون الأخضر تباينًا مثاليًا مع اللون الأبيض في المثال الثاني. التركيبات اللونية الثلاثية Triad كيفية إنشاء لوحات لونية بثلاثة ألوان تُستخدم تركيباتُ الألوان الثلاثية الألوانَ المتساوية على عجلة الألوان، إذ يسمح ذلك بوجود ثلاثة ألوان مختلفة تعطي تباينًا لطيفًا حتى إن لم تكُن مشبعة. نستخدم لونًا طاغيًا في التصميم مع لونين آخرين بارزين في معظم حالات إنشاء لوحة لونية ثلاثية متوازنة تمامًا كما هو الحال مع الطرق الأخرى. ويمكن الحصول على أربع تركيبات لونية ثلاثية في عجلة الألوان المكوّنة من 12 لونًا الموضَّحة في الشكل السابق، مثل المجموعات التالية: الأخضر المائل إلى الأزرق، والبرتقالي المائل إلى الأصفر، والبنفسجي المائل إلى الأحمر؛ والأخضر المائل إلى الأصفر، والبرتقالي المائل إلى الأحمر، والبنفسجي المائل إلى الأزرق؛ والأحمر، والأصفر، والأزرق؛ والبرتقالي، والأخضر، والبنفسجي. يظهِر المثال التالي توازنًا ثلاثيًا مثاليًا. حيث أنّ اللون الطاغي في الصورة هو اللون الأخضر، واللون الطاغي مع لونين ثانويين بارزين هما الزهري والبرتقالي. التركيبات اللونية الرباعية Tetrad كيفية إنشاء لوحات لونية بأربعة ألوان تُعرَف هذه الطريقة أيضًا باسم مخطط الألوان المستطيل rectangle color scheme، وتَستخدم أربعة ألوان موجودة ضمن زوجين من الألوان المكمّلة كما هو موضّح في الشكل الآتي. هناك نوع آخر من تركيبات الألوان التي تستخدم مربعًا للحصول على نتائج مماثلة، حيث تتوضّع الألوان الأربعة بالتساوي على عجلة الألوان. تقدّم الطريقة الرباعية لوحات ألوان أكثر تنوعًا، واحتمالات متعددة من التباين، حيث يجب مراعاة التوازن بين الألوان الباردة، والدافئة في تصميمك العام، عند استخدام طريقة المستطيل لدمج ألوانك. نرى في المثال الأول الآتي الذي يَستخدم تركيباتٍ رباعية، شعارًا. حيث يسمح التصميم باستخدام الألوان الأربعة بدون لونٍ طاغٍ إذا استبعدنا الخلفية المحايدة، وتتباين العناصر الأربعة للعبة عرض الفرسان تباينًا مثاليًا؛ في حين يوضّح الشكل الثاني الآتي تبايناتٍ أخرى من الأخضر، والأزرق، والأحمر، والأصفر، ويستخدم درجات اللون الأخضر على أساس لون طاغٍ. تركيبات الألوان الفردية Individual Color Combinations ما هي الألوان التي تتوافق مع بعضها البعض بصورة عامة؟ يُعَد ذلك أمرًا شخصيًا، إذ يمكن دمج كل لونين حسب الدرجة اللونية المناسبة، أو السطوع، أو التظليل المناسب. لكن هناك بعض التركيبات التقليدية التي ستجدها في تصميمات معينة في مجال الأزياء، والتصميم الداخلي، والجرافيك، وتصميم الويب. لنلقِ نظرةً على بعض هذه الأزواج اللونية فيما يلي: الألوان المحايدة Neutrals اللون الأسود: بما أنه لون عالمي، فهو رائعٌ مع أي لون آخر، إذ يندمج جيدًا مع البرتقالي، والأخضر، والأبيض، والأحمر، والأصفر. اللون الأبيض: هو لون عالمي آخر يتناسب تناسبًا مثاليًا مع الأزرق، والأحمر، والأسود. اللون البيج Beige: يتناسب مع الأزرق، والبني، والأخضرن والأحمر. اللون البني: يتلاءم مع السماوي الفاتحن واللون القِشدي cream، والزهري والبيج. اللون الرمادي: يتلاءم مع اللون الفوشيّ Fuchsia، والبنفسجي، والزهري، والأزرق. الألوان المعدنية Metallics اللون الذهبي: يتوافق مع اللون الأسود، والأرجواني المُحمّر (بورجوندي burgundy)، والوردي، والأخضر العسكري. اللون الذهبي الوردي Rose Gold: متوافق مع البنفسجي المائل إلى الأحمر، والفلامينجو الزهريّ، والخوخي. اللون الفضي: يتلاءم مع الأزرق، والبني، والذهبي العتيق. اللون النحاسي: متوافق مع الأبيض، والأخضر المحايد، والكحلي. الألوان الباردة Cool Colors البنفسجي: يتناسب مع البني الذهبي، والأصفر الباهت، ولون النعناع. البنفسجي المائل إلى الأزرق: متوافق مع البرتقالي، والزهري، والأصفر، والأبيض. الأزرق: يتوافق اللون الليلكي، والسماوي، والأخضر المصفَر، والبني، والرمادي. الأخضر المائل إلى الأزرق: يتناسب مع البني، والبرتقالي، والزهري، والأحمر الكرزي، والبيج. الأخضر: متوافق مع البرتقالي، والأصفر، والبني، والأبيض القشدي. الأخضر المصفَر: متوافق مع الأحمر الكرزي، والأزرق، والرمادي. الألوان الدافئة Warm Colors الأصفر: متوافق مع الرمادي، واللون اللازوردي azure، والليلكي، والأسود. البرتقالي المُصفَر: متوافق مع الرمادي، والبني، والزيتوني. البرتقالي: متوافق مع السماوي، والأزرق، والليلكي. البرتقالي المحمَر: متوافق مع السماوي، ولون النعناع، والأبيض القشدي. الأحمر: متوافق مع الأصفر، والأخضر، والأزرق، والأسود. البنفسجي المحمَر: يتناسب مع الرمادي، والليمي، ولون النعناع، واللازوردي، والبيج. الألوان المتدرجة Gradient Colors توسع الألوان لقد أُبعِدت التدرجات اللونية عن التصميم الجرافيكي وتصميم الويب لفترة من الوقت، مع استخدام النمط المسطح flat style فقط، ولكنها عادت مرةً أخرى إلى المشهد منذ عام 2018، إذ يتطور التيار الدارج trend باستمرار، بحيث يتقن المصممون مهاراتهم لإنشاء انتقالات لونية جميلة، واستخدامها بصورةٍ أفضل بالموازنة مع التصاميم ذات الألوان المتدرجة التي كانت موجودةً في التسعينات. فهل تتذكر أزرار CTA الكبيرة ذات اللون الأحمر عالي التباين مع أضواء وظلال وأنماط؟ لن تعود هذه الأشياء قريبًا لحسن الحظ. إذًا ما هي التدرجات اللونية؟ هي انتقالات لونية تمتزج من لون إلى آخر ولا تقتصر على صِبغتين فقط، كما لا توجد قواعد لنوع الألوان التي تمزجها، حيث يمكنك الانتقال بين الألوان المتشابهة، أو الألوان المتباينة. يوضّح الشكل الآتي عشرة أمثلة مختلفةً عن التدرجات اللونية، حيث يتضمن بعضها الانتقال بين لونين دافئين، في حين ينتقل بعضها الآخر بين درجات لونية باردة، مع وجود انتقالاتٍ مختلطة في حالات أخرى. تُعَدّ طرق دمج الألوان في نظرية الألوان في التصاميم ذات التدرجات اللونية، هي الطرق ذاتها في التصاميم المسطّحة، ولكن ما تفعله التدرجات اللونية بصورةٍ أفضل من التصميم المسطح، هو أنها تضيف عمقًا أكثر وتنشئ خامة texture، كما أنّ تركيبات الألوان المتدرجة غنية وملفتة للانتباه، وقد أصبحت منذ عودتها في عام 2018 أكثر تألّقًا وإشراقًا وعصريّة. تركيبات الألوان في علم النفس كيف تؤثر الألوان على الحالة المزاجية والعواطف؟ لا يقتصر الهدف من دمج الألوان على الجماليات، وتحسين تصميماتك، وجعلها جميلة وملفتةً للنظر. فقد لا تكفي نظرية الألوان لتصمّم تصميمًا عصريًا، ويكاد إنشاء اللوحات اللونية أن يتمثّل في اختيار الألوان المحدَّدة استراتيجيًا، بهدف نقل رسالتك بنجاح، والتأثير على عملائك ليستجيبوا بالطريقة التي تريدها. تثير الألوان المشاعر، ولا توجد طريقة للتغلب عليها، إذ يختلف علم النفس مع المعنى الكامن وراء كل درجة لونية من درجات الصبغات باختلاف الثقافات، والحالات، والتركيبات. ولكن هناك إرشاداتٌ قليلة تساعدك على البدء في معرفة معاني وتأثير الألوان، ومن بين الادعاءات الأكثر شيوعًا، هي أنّ الألوان الدافئة إيجابية، بينما الألوان الباردة سلبية، وهذا صحيح إلى حدٍ ما، لكنه ليس قاعدة، فاللون الأحمر على سبيل المثال هو لون دافئ ولكنه يثير الشعور بالغضب أو الخطر في معظم درجاته اللونية، وخاصةً مع كثافةٍ ونقاء أعلى؛ كما قد يثير اللون الأصفر، وهو لون أساسي دافئ، القلق والشعور بالإلحاح، وهناك بعض درجات اللون الأصفر التي ترتبط باليرقان وتعطي شعورًا بالمرض. إذًا لنتعرّف على الصبغات في أنقى درجاتها اللونية بإيجاز ونرى كيف قد يؤثِر كل منها على سلوك جمهورك المستهدف. الصبغات الفردية في التسويق يستجيب الأشخاص عادةً بطريقة معيَّنة تجاه الألوان الفردية، لكن يجب أن تضع في حساباتك أنّ تأثير كل صِبغةٍ يعتمد على عوامل متعددة هي: التركيبات، والسياقات، والتجربة، والذوق الشخصي، والعمر، والجنس، والاختلافات الثقافية. إذ يجب أن تبحث أكثر عند اختيار ألوانك لجمهور مستهدف محدّد. الألوان الدافئة اللون الأصفر: لونٌ ساطع، وكثيف، وملفت للانتباه، ودافئ، وحيوي؛ لكنه صعب القراءة، ومربكٌ للعيون، وقد يخلق مشاعر إحباطًا وقلقًا أيضًا، وهو يُستخدَم في مجال المبيعات مع المشترين المندفعين. اللون البرتقالي: جذابٌ للغاية، وشائعٌ للدعوة لاتخاذ إجراء CTA، ويُستخدَم مع الشعارات، والألوان المستخدَمة للإبراز، لقدرتها على جذب الانتباه. يُستخدَم اللون البرتقالي باستمرار بهدف إبراز شيءٍ ما، لأنه لون نشط للغاية ويحرّك مشاعر الإثارة والحماس، لكن الكثير من اللون البرتقالي مزعجٌ لزوار موقعك. اللون الأحمر: شائع الاستخدام في مجال المبيعات، فهو لون قوي يؤدّي إلى ردود أفعال أسرع. حيث يرفع اللون الأحمر من ضغط الدم، وهو أيضًا رائع للاستخدام بهدف المشاركة، والتواصل الاجتماعي، لذلك إذا اُستخدِم بكثرة، فقد يكون له تأثير سلبي على الجمهور، ويؤدي إلى إبعاد الزائرين. اللون الزهري: اللون الأكثر أنوثةً وشاعرية، فهو مثالي لألعاب الأطفال، ودور الحضانة، ومنتجات صحة المرأة. وكلما طالت فترة التعرّض للون الزهري، كلما أصبح الشخص أهدأ بالموازنة مع التعرّض للون الأحمر الأساسي. اللون الأرجواني Purple: لون ملَكي مرتبط بالثروة، والحسيّة، والحكمة، فهذا هو السبب في أنه يُستخدم بكثرة مع السلع الفاخرة، ومنتجات التجميل الراقية، وبما أن له طبيعةً درامية، فإنه يعطي أحاسيسَ شاعرية وغامضة أيضًا. الألوان الباردة والمحايدة اللون الأخضر: لونٌ مريحٌ للعين وممتع للنظر. يرتبط ارتباطًا وثيقًا بالطبيعة، والمنتجات الحيوية، والحظ السعيد، والصحة، والثروة؛ لكنّه أيضًا لون الحسد، والسم، لذلك فلدرجته اللونية وتظليله المناسب أهمية كبيرة. ** اللون الأزرق**: وهو اللون الأكثر شعبيةً، والأحب عند الرجال والنساء وفقًا لاستبيانٍ شامل، كما أنّ له استخدامات ضخمة في مجال الاتصالات، والمصارف، والتأمين؛ لأنه يثير مشاعر الأمن، والولاء، والصدق، والقوة، والوثوقية. وقد يثير اللون الأزرق أيضًا مشاعر الحزن، والوحدة اعتمادًا على تظليله. ** اللون الأسود**: لون عالمي أنيق، ومتطور يَشيع استخدامه في العلامات التجارية الراقية، فهو مرتبط بالرقي والقوة، ويُستخَدم في مجال الاتصالات غالبًا. اللون الأبيض: لون عالمي ذو تباينٍ عالٍ يضيف فراغًا، ويحمل معاني النقاء، والطهارة، والنضارة، والبساطة، ولكنه قد يوحي بالنضوب والبرودة. يُستخدَم بكثرة في مجال الرعاية الصحية، والمجال التقني. اللون الرمادي: لون لطيف للأشخاص اللطيفين الذين يفضِّلون عدم الظهور، إذ يُستخدَم لتهدئة الزوار، وجعلهم يشعرون بالراحة نظرًا لبساطته، وهو لون شائع في المجال التقني. المزاج والعواطف التي تنقلها اللوحات اللونية كانت العواطف هي التأثيرات الرئيسية التي تنقلها لنا حالة الألوان الأنقى وفقًا لنظرية الألوان، وإذا أخذنا جميع العوامل في الحسبان وحدّدنا المشاعر والعواطف التي نرغب في نقلها، فإن هذا التأثير يعتمد على نصوع الألوان، ودرجتها اللونية، وسطوعها، ودرجة حرارتها. فهل تستخدم لونًا برتقاليًا مفعمًا بالطاقة للغاية؟ إذًا يمكنك تقليل كثافته، وإضافة المزيد من اللون الأبيض لإنشاء لون فاتحٍ مريح. هل يوجد الكثير من اللون الأزرق في تصميمك الذي يوحي بالشعور بالحزن؟ إذًا امزجه مع درجة لونية دافئة للشعور بالفرح. الألوان الهادئة Calm colors: هي الألوان ذات درجات السطوع الأفتح من درجات اللون الأزرق والأخضر، وأكثر مخططات الألوان المهدّئة هي لوحات الألوان الفاتحة pastel palettes، والتي تحتوي ألوانًا، مثل: اللون الأزرق الفاتح، ولون النعناع، والليلكي، والوردي، والزهري، والأصفر الفاتح؛ وخاصةً عند دمجها مع ألوان محايدة، مثل: البيج، والأبيض، والرمادي، الفاتح. ألوان الطاقة Energy colors: أكثر درجات الألوان حيويةً وسطوعًا، مثل: اللون الأحمر الساطع، والأخضر النيونيّ، والقرمزي magenta، والسماوي، والأصفر الساطع، والأزرق الحيوي. حيث أنّ هذه الألوان تحفّز، وتنشّط، ولكنّها قد تسبب الغضب والإرهاق أيضًا. ألوان السعادة: مثل درجات الزهري، والبرتقالي، والأحمر الدافئة. وقد تتضمّن الألوان الفاتحة pastel، وألوان الحلوى، كما قد تكون حيويةً وجذابة. يجب أن تكون هذه الألوان عالية الكثافة، مما يعني أنه يمكنك تغيير قيمتها، ولكن يجب تجنّب إضافة اللون الرمادي إليها. الألوان الحزينة: هي درجات لونية رمادية، وغير مشبعة، وداكنة من الألوان الباردة. حيث تنقل الألوان التي تخلو من الحيوية والدفء شعورًا بالفراغ، والوحدة، والاكتئاب. اللوحات اللونية الباردة هي مخططات الألوان التي تتضمن تظليلات الألوان الباردة، مثل: الأزرق، والأخضر، والبنفسجي؛ وتُمزَج مع الألوان المحايدة للحصول على تباين أفضل. حيث تبعث الألوان الباردة على الهدوء والاسترخاء أغلب الأحيان، ولكن يمكن أن تنقل اللوحات اللونية الباردة الحزن، والاكتئاب اعتمادًا على درجتها اللونية، وتتضمن مثل هذه المخططات كلًا من اللونَ الرمادي، ودرجات الأزرق، والرمادي غير المشبعة. قد تنقل هذه الألوان نفسها شعورًا بالإيجابية، والصحة، والجمال، والوثوقية ،وحتى النضارة عند زيادة كثافتها. لنلقِ نظرةً على بعض اللوحات اللونية الباردة المستوحاة من الطبيعة. حزن وكآبة تهدئة وارتياح نضارة ورقي سلام وهدوء برودة وتجمّد ولاء ووثوقية ويمكن أن تنقل الألوان الباردة لنا السعادة أيضًا. مرح وسرور دفء وبهجة اللوحات اللونية الدافئة الألوان الدافئة هي أيضًا سيف ذو حدين كما هو الحال مع الألوان الباردة، إذ تنقل الألوان الدافئة مشاعرَ التفاؤل، والسعادة، والطاقة، والحماس، والشغف؛ لكنها تنقل أيضًا مشاعر القلق، والإلحاح، وإشارة الخطر، والغضب. حيث يثير اللون الأحمر والأصفر ردود أفعال سريعة، ويزيدان من معدل ضربات القلب والشهية. لنلقِ نظرةً على استخدامات الألوان الدافئة المختلفة في مخططات الألوان، والحالات المزاجية التي تثيرها. طاقة سعادة شاعرية وحسيّة دفء قلق ذعر وخوف الخلاصة تُعَد الألوان أداةً مهمةً جدًا في التصميم للتأثير على المزاج والعواطف، لذلك يجب فهم علم الألوان، وكيفية عملها، وشرحنا أساسيات نظرية الألوان، وما تعنيه بالنسبة للتصميم الجرافيكي. ترجمة -وبتصرّف- للمقال Color Theory Basics For Non-Designers: Everything You Should Know لصاحبته Al Boicheva. اقرأ أيضًا كيف تختار أنسب الألوان لمشاريعك التصميمية سيكولوجية الألوان في عالمي التسويق والعلامات التجارية
-
الشبكات اللاسلكية (Wireless Networks) تختلف التقنيات اللاسلكية عن الروابط السلكية في بعض النواحي المهمة، بينما تشتركان في نفس الوقت في العديد من الخصائص المشتركة، حيث تَعدّ التقنياتُ اللاسلكية مشكلاتِ أخطاء البت مصدرَ قلقٍ كبير مثل الروابط السلكية (wired links)، بل أكثر من ذلك بسبب بيئة التشويش غير المتوقعة لمعظم الروابط اللاسلكية، ويجب أيضًا معالجة مشكلتَي التأطير (Framing) والوثوقية (reliability). تُعَد الطاقة مشكلة كبيرة بالنسبة للشبكات اللاسلكية على عكس الروابط السلكية، خاصةً لأن الروابط اللاسلكية غالبًا ما تستخدمها الأجهزة المحمولة الصغيرة (مثل الهواتف وأجهزة الاستشعار) التي لديها وصول محدود إلى الطاقة (مُدَّخرة صغيرة مثلًا). علاوة على ذلك، لا يمكنك التخلص من الطاقة العالية العشوائية باستخدام مرسل راديوي، فهناك مخاوف بشأن التداخل مع الأجهزة الأخرى وعادة ما تكون هناك تعليمات تحدد مقدار الطاقة التي قد تنبعث من الجهاز عند تردد معين. تُعد الوسائط اللاسلكية أيضًا متعددة الوصول بطبيعتها، فمن الصعب توجيه الإرسال اللاسلكي إلى مستقبل واحد فقط أو تجنب استقبال إشارات الراديو من أي مرسل بطاقة كافية في منطقتك، وبالتالي يُعد التحكم في الوصول إلى الوسائط قضية أساسية بالنسبة للوصلات اللاسلكية، وقد يتعين أيضًا معالجة مشكلات التنصت نظرًا لصعوبة التحكم فيمَن يتلقى إشارتك عند الإرسال عبر الهواء. هناك مجموعة متنوعة ومحيرة من التقنيات اللاسلكية المختلفة، وكل منها يقوم بمقايضات مختلفة في أبعاد مختلفة، حيث تتمثل إحدى الطرق البسيطة لتصنيف التقنيات المختلفة في معدلات البيانات التي توفرها ومدى تباعد عقد الاتصال، وتشمل الاختلافات المهمة الأخرى الجزء المستخدَم من الطيف الكهرومغناطيسي (بما في ذلك إذا كان يتطلب ترخيصًا) ومقدار الطاقة المستهلَكة. سنناقش تقنيتين لاسلكيتين بارزتين: واي فاي Wi-Fi (المعروفة رسميًا باسم 802.11) وبلوتوث Bluetooth، ويناقش القسم الذي بعده الشبكات الخلوية في سياق خدمات وصول مزود خدمة الإنترنت. يعطي الجدول التالي نظرة عامة عن هذه التقنيات وكيفية موازنتها مع بعضها البعض: Bluetooth البلوتوث (802.15.1) Wi-Fi الواي فاي (802.11) الشبكة الخلوية 4G Cellular طول الرابط القياسي (Typical link length) يصل إلى 10 أمتار 100 متر عشرات الكيلومترات معدل البيانات القياسي (Typical data rate) يصل إلى 2 ميجابت في الثانية (مشترَك) 150-450 ميجابت في الثانية 1-5 ميجابت في الثانية الاستخدام الأساسي (Typical use) ربط جهاز طرفي بالحاسوب ربط الحاسوب بقاعدة سلكية ربط الهاتف المحمول ببرج سلكي التقنية السلكية التماثلية (Wired technology analogy) تقنية USB تقنية Ethernet تقنية PON 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) يعني أحيانًا عرض النطاق الترددي بالهرتز وأحيانًا معدل بيانات (data rate) الرابط، ونظرًا لظهور هذين المفهومين في المناقشات حول الشبكات اللاسلكية، سنستخدم حيز النطاق التراسلي هنا بمعناه الأكثر صرامة (عرض النطاق الترددي)، وسنستخدم مصطلح معدل البيانات لوصف عدد البتات في الثانية التي يمكن إرسالها عبر الرابط كما في الجدول السابق. قضايا أساسية (Basic Issues) يكمن التحدي في الروابط اللاسلكية في مشاركة الوسيط بكفاءة دون التدخل غير الضروري مع بعضها البعض، نظرًا لأنها تشترك جميعها في نفس ذلك الوسيط، حيث تتحقق معظم هذه المشاركة من خلال تقسيمها على أبعاد التردد والمساحة. يمكن تخصيص الاستخدام الحصري لتردد معين في منطقة جغرافية معينة لكيان فردي مثل شركة، ومن الممكن حصر المنطقة التي تغطيها إشارة كهرومغناطيسية لأن هذه الإشارات تضعف أو تخف (attenuate) كلما زادت المسافة عن مصدرها، لذلك قلّل قوة جهاز إرسالك لتقليل المنطقة التي تغطيها إشارتك. تحدّد الوكالات الحكومية، مثل لجنة الاتصالات الفيدرالية (FCC) في الولايات المتحدة هذه التخصيصات، حيث تخصّص نطاقات محددة (نطاقات التردد) لاستخدامات معينة، فتُخصَّص بعض النطاقات للاستخدام الحكومي، وتُحجَز النطاقات الأخرى لاستخدامات معينة مثل راديو AM وراديو FM والتلفاز واتصالات الأقمار الصناعية والهواتف الخلوية، ثم تُرخَّص الترددات المحددة داخل هذه النطاقات للمؤسسات الفردية لاستخدامها في مناطق جغرافية معينة، ووُضِعت العديد من نطاقات التردد جانبًا للاستخدام المُعفى من الترخيص، وهي نطاقات ليست بحاجة ترخيص. لا تزال تخضع الأجهزة التي تستخدم ترددات مُعفاة من الترخيص لقيود معينة لجعل هذا التشارك المختلف وغير المقيد ناجحًا. والأهم من ذلك هو تحديد قدرة الإرسال حيث يحدّ ذلك من نطاق الإشارة، مما يجعله أقل احتمالًا للتداخل مع إشارة أخرى. قد يصل نطاق الهاتف اللاسلكي (جهاز شائع غير مرخَّص) إلى حوالي 100 قدم على سبيل المثال. إحدى الأفكار التي تظهر كثيرًا عند مشاركة الطيف بين العديد من الأجهزة والتطبيقات هي الطيف المنتشر (spread spectrum)، وتكمن الفكرة وراء الطيف المنتشر في نشر الإشارة على نطاق ترددي أوسع، وذلك لتقليل تأثير التداخل مع الأجهزة الأخرى. صُمِّم الطيف المنتشر في الأصل للاستخدام العسكري، لذلك كانت هذه (الأجهزة الأخرى) تحاول في كثير من الأحيان تشويش الإشارة، فقفز التردد (frequency hopping) هي تقنية طيفٍ منتشر تتضمن إرسال الإشارة عبر سلسلة عشوائية من الترددات، أي الإرسال الأول بتردد، ثم الإرسال الثاني بترددٍ آخر وهكذا. ليست سلسلة الترددات عشوائيةً حقًا، ولكنها تُحسَب بواسطة مولّد أرقام شبه عشوائية (pseudorandom number generator). يستخدم المستقبل نفس الخوارزمية التي يستخدمها المرسل ويهيئها بنفس القيمة الابتدائية (seed)، ثم يصبح قادرًا على القفز إلى الترددات المتزامنة مع المرسل لاستقبال الإطار بصورة صحيحة. يقلل هذا المخطط من التداخل من خلال جعل استخدام إشارتين نفسَ التردد غير محتمَلٍ لأكثر من البت المعزول النادر. تضيف تقنية الطيف المنتشر الثانية التي تسمى التسلسل المباشر (direct sequence) التكرارَ (redundancy) لتتحمّل التداخل بصورةٍ أكبر. يُمثَّل كل بت من البيانات بواسطة بتات متعددة في الإشارة المرسلة، بحيث يكون هناك تكرار كافٍ لاستعادة البت الأصلي في حالة تلف بعض البتات المرسلة بسبب التداخل. يرسل المرسل ناتج عملية XOR لكل بت يرغب المرسل في إرساله مع n بت عشوائي، حيث تنشأ سلسلة البتات العشوائية بواسطة مولّد أرقام شبه عشوائية معروف لكل من المرسل والمستقبل كما هو الحال مع قفز التردد. تنشر القيمُ المرسلَة والمعروفة باسم شيفرة التقطيع (chipping code) ذات n بت الإشارةَ عبر نطاق تردد أكبر بمقدار n مرة من الإطار المطلوب. يعطي الشكل التالي مثالًا عن سلسلة تقطيع مؤلفة من 4 بتات: تملك الأجزاء المختلفة من الطيف الكهرومغناطيسي خصائصًا مختلفة، مما يجعل بعضها أكثر ملاءمة للاتصال وبعضها أقل ملاءمة، حيث يمكن للبعض اختراق المباني والبعض الآخر لا يستطيع ذلك. تنظّم الحكومات فقط جزء الاتصال الأساسي كنطاقات الراديو والموجات الميكروية. هناك اهتمام كبير بالطيف الذي أصبح متاحًا بعد التخلص التدريجي من التلفزيون التناظري لصالح الرقمي مع زيادة الطلب على الطيف الرئيسي. لاحظ وجود فئتين مختلفتين من النقاط النهائية في العديد من الشبكات اللاسلكية اليوم. لا تملك النقطة النهائية التي توصف أحيانًا بالمحطة القاعدية (base station) قابليةَ التنقل، ولكن لديها اتصال سلكي (أو على الأقل حيز نطاق تراسلي كبير) بالإنترنت أو بشبكات أخرى، كما هو موضح في الشكل الآتي. تكون العقدة الموجودة في الطرف الآخر من الرابط، المعروضة هنا كعقدة عميل (client node)، غالبًا متنقلةً وتعتمد على رابطها بالمحطة القاعدية لجميع اتصالاتها مع العقد الأخرى. لاحظ أنه في الشكل الآتي استخدمنا زوجًا مموجًا من الخطوط لتمثيل تجريد الرابط اللاسلكي الموجود بين جهازين (بين محطة قاعدية وإحدى عقد العميل الخاصة بها على سبيل المثال). أحد الجوانب المثيرة للاهتمام في الاتصال اللاسلكي هو أنه يدعم الاتصال من نقطة إلى عدة نقاط، لأن موجات الراديو التي يرسلها جهاز واحد يمكن استقبالها في نفس الوقت بواسطة العديد من الأجهزة، ولكن غالبًا ما يكون من المفيد إنشاء تجريد رابط من نقطة لنقطة لبروتوكولات الطبقة العليا، وسنرى أمثلة عن كيفية عمل ذلك لاحقًا. لاحظ أيضًا في الشكل الآتي توجيه الاتصال بين العقد غير القاعدية (العميلة) عبر المحطة القاعدية، على الرغم من حقيقة أن الموجات الراديوية المنبعثة من عقدة عميل واحدة يمكن استقبالها بصورة جيدة بواسطة عقد العميل الأخرى، ولا يسمح نموذج المحطة القاعدية المشترك بالاتصال المباشر بين عقد العميل. يتضمن مخطط الشبكة (topology) هذا ثلاثة مستوياتٍ مختلفة نوعيًا من التنقل (mobility). المستوى الأول هو عدم القدرة على التنقل كما هو الحال عندما يكون المستقبل في موقعٍ ثابت لاستقبال إرسال موجَّه من المحطة القاعدية، والمستوى الثاني هو التنقل ضمن نطاق القاعدة، كما هو الحال مع البلوتوث، والمستوى الثالث هو التنقل بين القاعدات كما هو الحال مع الهواتف المحمولة والواي فاي. المخطَّط البديل الذي يشهد اهتمامًا متزايدًا هو الشبكة المتداخلة (mesh) أو الشبكة المُخصَّصة (ad hoc). العقد هي نظائر (peers) في الشبكة اللاسلكية المتداخلة، أي أنه لا توجد عقدة محطة قاعدية خاصة، ويمكن إعادة توجيه الرسائل عبر سلسلة من العقد النظيرة طالما أن كل عقدة تقع ضمن نطاق العقدة السابقة، وهذا موضَّح في الشكل السابق. هذا يسمح للجزء اللاسلكي من الشبكة أن يمتد إلى خارج نطاق الراديو المحدود، فيسمح ذلك للتقنية قصيرة المدى بتوسيع مداها وبالتالي التنافس المحتمل مع تقنية بعيدة المدى من وجهة نظر المنافسة بين التقنيات. توفر الشبكات المتداخلة أيضًا إمكانية تحمّل الخطأ من خلال توفير مسارات متعددة لرسالةٍ ما للانتقال من النقطة A إلى النقطة B، ويمكن توسيع الشبكة المتداخلة بصورة تدريجية وبتكاليف تزايدية. لكن تتطلب الشبكة المتداخلة أن تتمتع العقد غير القاعدية بمستوى معين من التطور في عتادها وبرامجها، مما قد يؤدي إلى زيادة التكاليف لكل وحدة وزيادة استهلاك الطاقة المهم للأجهزة التي تعمل بالمدَّخرات. تحظى الشبكات المتداخلة اللاسلكية باهتمام بحثي كبير، لكنها لا تزال بدائية نسبيًا مقارنة بالشبكات ذات المحطات القاعدية، وغالبًا ما تشكل شبكات الاستشعار اللاسلكية (Wireless sensor networks) شبكاتٍ لاسلكية متداخلة، وهي تقنية ناشئة مهمة أخرى. لنلقِ نظرة الآن على تفاصيل تقنيتين لاسلكيتين شائعتين هما الواي فاي والبلوتوث. 802.11/Wi-Fi يستخدم معظم الناس شبكة لاسلكية تستند إلى معايير IEEE 802.11 والتي يشار إليها غالبًا باسم واي فاي (Wi-Fi)، تعد شبكة Wi-Fi علامة تجارية مملوكة لمجموعة تجارية تسمى Wi-Fi Alliance، والتي تصادق على امتثال المنتج للمعيار 802.11. صُمِّم المعيار 802.11 للاستخدام في منطقة جغرافية محدودة (المنازل والمباني المكتبية والحرم الجامعي) مثل شبكة إيثرنت، ويتمثل التحدي الأساسي في التوسط في الوصول إلى وسيط اتصال مشترك، وهو في هذه الحالة، انتشار الإشارات عبر الفضاء. الخصائص الفيزيائية (Physical Properties) يحدد معيار 802.11 عددًا من الطبقات الفيزيائية المختلفة التي تعمل في نطاقات تردد مختلفة وتوفر نطاقًا من معدلات البيانات المختلفة، حيث حدد معيار 802.11 الأصلي معيارين من الطبقات الفيزيائية القائمة على الراديو، يستخدم أحدهما قفز التردد (أكثر من 79 حيز نطاق تردد بعرض 1 ميجاهرتز)، والآخر يستخدم طيفًا منتشرًا متسلسلًا مباشرًا (مع سلسلة تقطيع 11 بت). وفّر كلاهما معدلات بيانات في نطاق 2 ميجابت في الثانية، ثم أُضيف معيار الطبقة الفيزيائية 802.11b، ودُعم باستخدامٍ مغاير عن التسلسل المباشر حتى 11 ميجابت في الثانية. تعمل هذه المعايير الثلاثة جميعها في نطاق التردد 2.4 جيجاهرتز المُعفى من الترخيص للطيف الكهرومغناطيسي، ثم جاء المعيار 802.11a، الذي قدّم حتى 54 ميجابت في الثانية باستخدامٍ مغاير عن دمج الإرسال بتقسيم التردد يسمى تعدد الإرسال بتقسيم التردد المتعامد (orthogonal frequency division multiplexing أو اختصارًا OFDM). يعمل المعيار 802.11a في نطاق 5 جيجاهرتز المعفى من الترخيص، ثم تبعه المعيار 802.11g الذي استخدم أيضًا OFDM حتى 54 ميجابت في الثانية. المعيار 802.11g متوافق مع الإصدارات السابقة للمعيار 802.11b (ويعود إلى النطاق 2.4 جيجاهرتز). دعمت العديد من الأجهزة المعيارين 802.11n أو 802.11ac في وقت كتابة هذا الكتاب، والتي تحقق عادةً معدلات بيانات لكل جهاز من 150 ميجابت في الثانية إلى 450 ميجابت في الثانية على التوالي. يرجع هذا التحسن جزئيًا إلى استخدام هوائيات متعددة والسماح بحيز نطاقٍ تراسلي أكبر للقنوات اللاسلكية، وغالبًا ما يطلق على استخدام الهوائيات المتعددة اسم MIMO للمدخلات المتعددة (multiple-input) والمخرجات المتعددة (multiple-output). يَعِد أحدث معيارٍ ناشئ وهو المعيار 802.11ax بتحسّن جوهري آخر في الإنتاجية من خلال اعتماد العديد من تقنيات الترميز والتعديل جزئيًا المستخدمة في شبكة 4G / 5G الخلوية، والتي سنشرحها لاحقًا. من الشائع أن تدعم المنتجات التجارية أكثر من نكهة من المعيار 802.11، حيث تدعم العديد من المحطات القاعدية المغايرات الخمسة (a و b و g و n و ac)، لا يضمن ذلك التوافق مع أي جهاز يدعم أي معيار من المعايير فحسب، بل يتيح أيضًا لمنتجَين من هذا النوع اختيار خيار حيز النطاق التراسلي الأعلى الخاص ببيئة معينة. تجدر الإشارة إلى أنه في حين أن جميع معايير 802.11 تحدد الحد الأقصى لمعدل البت الذي يمكن دعمه، إلّا أنها تدعم في الغالب معدلات بت أقل أيضًا (يسمح المعيار 802.11a بمعدلات بت تبلغ 6 و 9 و 12 و 18 و 24 و 36 و 48 و 54 ميجابت في الثانية على سبيل المثال). يكون من السهل فك تشفير الإشارات المرسلة مع وجود تشويش عند معدلات بتات منخفضة، وتُستخدم مخططات تعديل مختلفة لتحقيق معدلات بتات مختلفة، وبالإضافة إلى أنه تتنوع كمية المعلومات الزائدة في صيغة شيفرات تصحيح الأخطاء، حيث تعني المعلومات الزائدة مرونة أعلى في مواجهة أخطاء البتات على حساب خفض معدل البيانات الفعال، نظرًا لأن المزيد من البتات المرسلة زائدةٌ (redundant). تحاول الأنظمة اختيار معدل بت مثالي بناءً على بيئة التشويش التي تجد نفسها فيها، ويمكن أن تكون خوارزميات اختيار معدل البت معقدة للغاية، ومن المثير للاهتمام أن معايير 802.11 لا تحدد نهجًا معينًا ولكنها تترك خيار اختيار الخوارزميات لمختلف المصنّعين. تتمثل الطريقة الأساسية لانتقاء معدل البتات في تقدير معدل خطأ البتات إما عن طريق القياس المباشر لنسبة الإشارة إلى الضجيج (signal-to-noise ratio أو اختصارًا SNR) في الطبقة الفيزيائية، أو بواسطة تقدير نسبة SNR عن طريق قياس عدد المرات التي تُرسَل فيها الرزم بنجاح مع وصول إشعارٍ باستلامها. يتحقق المرسل في بعض الطرق أحيانًا من معدل بت أعلى عن طريق إرسال رزمة واحدة أو أكثر بهذا المعدل لمعرفة إذا نجح أم لا. تجنّب التصادم (Collision Avoidance) قد يبدو للوهلة الأولى أن بروتوكولًا لاسلكيًا يتّبع نفس الخوارزمية التي يتّبعها بروتوكول إيثرنت، ولكن انتظر حتى يصبح الرابط خاملًا قبل الإرسال وانتظر التراجع في حالة حدوث تصادم، وهو التقدير الأول لما يفعله بروتوكول 802.11. يتمثل التعقيد الإضافي للشبكة اللاسلكية في أن العقدة الموجودة على شبكة إيثرنت تستطيع استقبال عمليات إرسال كل عقدة أخرى ويمكنها الإرسال والاستقبال في نفس الوقت، ولا ينطبق أي من هذه الشروط على العقد اللاسلكية، وهذا يجعل الكشف عن التصادمات أعقد. السبب وراء عدم قدرة العقد اللاسلكية على الإرسال والاستقبال في نفس الوقت (على نفس التردد) هو أن الطاقة التي يولدها المرسل أعلى بكثير من أي طاقة مستقبَلة، وبالتالي تغرَق دائرة الاستقبال، والسبب وراء عدم استقبال عقدة من عقدة أخرى هو أن هذه العقدة قد تكون بعيدة جدًا أو قد حُظِرت بواسطة حاجز. هذا الموقف أعقد قليلًا مما يبدو لأول مرة. افترض حدوث الموقف الموضح في الشكل السابق، حيث تقع كل من العقدتين A و C في نطاق العقدة B ولكن لا تقع كل منهما في نطاق العقدة الأخرى، وافترض أن كلًا من العقدتين A و C تريدان التواصل مع العقدة B فترسل كل منهما إطارًا. لا تعرف العقدتان A و C بعضهما البعض. يتصادم هذان الإطاران مع بعضهما البعض عند العقدة B، ولكن لا تدرك العقدتان A و C هذا التصادم على عكس شبكة إيثرنت. يُقال أن العقدتين A و C عقدتان مخفيتان (hidden nodes) بالنسبة لبعضهما البعض. تحدث مشكلة أخرى تسمى مشكلة العقدة المكشوفة (exposed node problem) في ظل الظروف الموضحة في الشكل السابق، حيث تكون كل من العقد الأربعة قادرةً على إرسال واستقبال الإشارات التي تصل فقط إلى العقد الواقعة على يسارها ويمينها المباشرين، فيمكن أن تتبادل العقدة B الإطارات مع العقدتين A و C على سبيل المثال، ولكن لا يمكن أن تصل إلى العقدة D، بينما يمكن أن تصل العقدة C إلى العقدتين B و D ولكن لا تصل إلى العقدة A. افترض أن العقدة B ترسل إلى العقدة A، وتكون العقدة C على علمٍ بهذا الاتصال لأنها تسمع إرسال العقدة B، ولكن سيكون من الخطأ أن تستنتج العقدة C أنها لا تستطيع الإرسال إلى أي عقدة أخرى لمجرد أنها تستطيع سماع إرسال العقدة B. افترض أن العقدة C تريد الإرسال إلى العقدة D على سبيل المثال. هذه ليست مشكلة لأن إرسال العقدة C إلى العقدة D لن يتداخل مع قدرة العقدة A على الاستلام من العقدة B. (قد يتداخل مع إرسال العقدة A إلى العقدة B، ولكن العقدة B هي المرسل في هذا المثال). يعالج المعيار 802.11 هذه المشكلات باستخدام المعيار CSMA / CA، حيث يرمز CA إلى تجنب التصادم (collision avoidance)، على عكس اكتشاف التصادم (collision detection) في المعيار CSMA / CD المستخدم في شبكة إيثرنت. يبدو جزء تحسس الحامل (Carrier Sense) بسيطًا بدرجة كافية، حيث يتحقق المرسل فيما إذا كان يمكنه سماع أية عمليات إرسال أخرى قبل إرسال رزمة، إذا لم يكن كذلك فإنه يرسل، ولكن إن مجرد انتظار عدم وجود إشارات من أجهزة الإرسال الأخرى لا يضمن عدم حدوث تصادم من منظور المستقبل بسبب مشكلة العقدة المخفيّة. لذلك إن أحد أجزاء المعيار CSMA / CA عبارة عن إشعارٍ صريح من المستقبل إلى المرسل. إذا فُك تشفير الرزمة بنجاح ومُرِّر حقل CRC الخاص بها إلى المستقبل، فسيرسل جهاز المستقبل إشعارًا مرة أخرى إلى المرسل. لاحظ أنه في حالة حدوث تصادم سيؤدي ذلك إلى جعل الرزمة بأكملها عديمة الفائدة، لذلك يضيف المعيار 802.11 آلية اختيارية تسمى RTS-CTS جاهز للإرسال-واضح للإرسال (Ready to Send-Clear to Send)، وهذا يساعد بطريقة ما في معالجة مشكلة العقدة المخفية. يرسل المرسل رزمة RTS، وهي رزمة قصيرة، إلى المستقبل المقصود، فإذا اُستلمت هذه الرزمة بنجاح، سيستجيب المستقبل برزمة قصيرة أخرى هي رزمة CTS. لم تسمع العقدة المخفية رزمة RTS، لكن من المحتمل أن تسمع رزمة CTS. هذا يخبر العقد الموجودة في نطاق المستقبل بطريقةٍ فعالة أنه لا ينبغي عليهم إرسال أي شيء لفترة من الوقت، يكون مقدار الوقت اللازم لعملية الإرسال هذه مُضمَّنًا في رزم RTS و CTS. يمكن افتراض أن الحامل متاح مرة أخرى بعد مرور هذا الوقت بالإضافة إلى فترة زمنية صغيرة، وبالتالي يمكن لعقدة أخرى محاولة الإرسال. قد تكتشف عقدتان رابطًا خاملًا وتحاولان إرسال إطار RTS في نفس الوقت، مما يتسبب في تصادم إطارات RTS مع بعضها البعض. يدرك المرسلون أن التصادم قد حدث عندما لا يتلقون إطار CTS بعد فترة زمنية، وفي هذه الحالة ينتظر كل منهم فترة عشوائية من الوقت قبل المحاولة مرة أخرى. يُحدَّد مقدار الوقت الذي تتأخر فيه العقدة من خلال خوارزمية التراجع الأسية (exponential backoff algorithm) التي تشبه إلى حد كبير تلك المستخدمة على شبكة إيثرنت. يرسل المرسل رزمة البيانات الخاصة به بعد تبادل RTS-CTS بنجاح، وإذا سارت الأمور على ما يرام، فسيتلقى إشعارًا بهذه الرزمة. سيحاول المرسل طلب استخدام القناة مرة أخرى في حالة عدم وجود إشعار في الوقت المناسب، باستخدام نفس العملية الموضحة أعلاه، وقد تحاول العقد الأخرى مرة أخرى الوصول إلى القناة أيضًا. نظام التوزيع (Distribution System) سيكون المعيار 802.11 مناسبًا للشبكة ذات المخطط المتداخل (mesh) أو المخصَّص (ad hoc). أوشك تطوير معيار 802.11s للشبكات المتداخلة على الانتهاء، ولكن تستخدم جميع شبكات 802.11 تقريبًا مخططًا موجَّهًا بالمحطة القاعدية في الوقت الحالي. يُسمح لبعض العقد بالتجوّل (roam)، الحاسوب المحمول مثلًا، وبعضها متصل بالبنية التحتية للشبكة السلكية بدلًا من إنشاء جميع العقد بالتساوي. يسمي المعيارُ 802.11 المحطاتِ القاعدية نقاط وصول (access points أو اختصارًا APs)، وهي متصلة ببعضها البعض من خلال ما يسمى بنظام التوزيع (distribution system). يوضّح الشكل التالي نظام توزيعٍ يربط ثلاث نقاط وصول، تخدّم كل منها العقدَ في بعض المناطق. تعمل كل نقطة وصول على قناةٍ ما في النطاق الترددي المناسب، وستكون كل نقطة وصول عادةً على قناة مختلفة عن جيرانها. تفاصيل نظام التوزيع ليست مهمة، حيث يمكن أن تكون إيثرنت على سبيل المثال، ولكن النقطة المهمة الوحيدة هي أن شبكة التوزيع تعمل على طبقة الربط، وهي نفس طبقة بروتوكول الروابط اللاسلكية، أي لا يعتمد على أي بروتوكولات ذات مستوى أعلى (مثل طبقة الشبكة). إن الفكرة وراء نظام التوزيع هذا هي أن كل عقدة تربط نفسها بنقطة وصول واحدة، على الرغم من أن عقدتين يمكن أن تتواصلا مباشرة مع بعضهما إذا كانتا في متناول بعضهما البعض. لكي تتواصل العقدة A مع العقدة E، على سبيل المثال، ترسل العقدة A أولًا إطارًا إلى نقطة الوصول الخاصة بها (AP-1)، والتي تعيد توجيه الإطار عبر نظام التوزيع إلى نقطة الوصول AP-3، والتي ترسل في النهاية الإطار إلى العقدة E، ولكن كيف عرفت نقطة الوصول AP-1 أن إعادة توجيه الرسالة إلى نقطة الوصول AP-3 خارج نطاق المعيار 802.11؟ ربما استخدمت بروتوكول تجسير (bridging protocol). يحدد المعيار 802.11 كيفية تحديد العقد لنقاط الوصول الخاصة بها وكيفية عمل هذه الخوارزمية في ضوء انتقال العقد من خلية إلى أخرى. تسمى تقنية اختيار نقطة الوصول بالمسح (scanning) وتتضمن الخطوات الأربع التالية: ترسل العقدة إطار بحث Probe. تستجيب جميع نقاط الوصول الموجودة في نطاق العقدة بإطار استجابة Probe Response. تختار العقدة إحدى نقاط الوصول وترسل إلى نقطة الوصول إطار طلب ارتباط Association Request. تستجيب نقطة الوصول AP بإطار استجابة Association Response. تشغّل العقدة هذا البروتوكول عندما تنضم إلى الشبكة، وكذلك عندما تصبح غير راضية عن نقطة الوصول الحالية الخاصة بها، وقد يحدث هذا، على سبيل المثال، لأن الإشارة من نقطة الوصول الحالية الخاصة بها ضعفت بسبب ابتعاد العقدة عنها. تُعلِم نقطةُ الوصول الجديدة نقطةَ الوصول القديمة بالتغيير (يحدث هذا في الخطوة 4) عبر نظام التوزيع عندما تحصل العقدة على نقطة وصول جديدة. افترض الموقف الموضح في الشكل السابق، حيث تنتقل العقدة C من الخلية التي تخدّمها نقطة الوصول AP-1 إلى الخلية التي تخدّمها نقطة الوصول AP-2. ترسل العقدة C إطارات Probe أثناء تحركها، فينتج عنها في النهاية إطارات Probe Response من AP-2، ثم تفضّل العقدة C نقطة الوصول AP-2 على نقطة الوصول AP-1، ولذلك ترتبط بنقطة الوصول هذه. تدعى هذه الآلية المسح النشط (active scanning) حيث أن العقدة تبحث بنشاط عن نقطة وصول. كما ترسل نقاط الوصول دوريًا إطار Beacon الذي يعلن عن قدرات نقطة الوصول، والتي تشمل معدلات الإرسال التي تدعمها نقطة الوصول AP، ويسمى ذلك المسح السلبي (passive scanning)، ويمكن أن تتغير العقدة إلى نقطة الوصول هذه اعتمادًا على إطار Beacon ببساطة عن طريق إرسال إطار Association Request مرة أخرى إلى نقطة الوصول. صيغة الإطار (Frame Format) يحتوي الإطار على عناوين عقدة المصدر والوجهة التي يبلغ طول كل منها 48 بتًا، و 2312 بايت من البيانات، و 32 بت CRC. يحتوي حقل Control على ثلاثة حقول فرعية ذات أهمية (غير موضّحة في الشكل التالي): حقل Type مؤلف من 6 بتات يشير إلى ما إذا كان الإطار يحمل بيانات أو إلى إنه إطار RTS أو CTS أو أنه إطار تستخدمه خوارزمية المسح، وزوج حقول يؤلَّف كلٌ منهما من 1 بت تسمى ToDS و FromDS. الشيء الغريب في صيغة إطار 802.11 هو أنه يحتوي على أربعة عناوين بدلًا من عنوانين. تعتمد كيفية تفسير هذه العناوين على إعدادات البتين ToDS و FromDS في حقل Control من الإطار، وذلك لمراعاة احتمال إعادة توجيه الإطار عبر نظام التوزيع، مما يعني أن المرسل الأصلي ليس بالضرورة هو نفسه أحدث عقدة إرسال، ويُطبَّق نفس الأمر على عنوان الوجهة. يكون كلا بتَي DS صفرًا، عندما ترسل إحدى العقد في أبسط الحالات مباشرةً إلى عقدةٍ أخرى، ويحدّد الحقل Addr1 العقدة المستهدفة، ويحدّد الحقل Addr2 العقدة المصدر. تُضبَط بتات DS بالقيمة 1 في الحالة الأعقدا، مما يشير إلى أن الرسالة انتقلت من عقدة لاسلكية إلى نظام التوزيع، ثم من نظام التوزيع إلى عقدة لاسلكية أخرى. يحدد الحقل Addr1 الوجهة النهائية ويحدد الحقل Addr2 المرسل المباشر (المرسل الذي أعاد توجيه الإطار من نظام التوزيع إلى الوجهة النهائية) بعد ضبط بتي DS. يحدّد الحقل Addr3 الوجهة الوسيطة (تلك التي قبلت الإطار من عقدة لاسلكية وأعادت توجيهه عبر نظام التوزيع)، ويحدّد الحقل Addr4 المصدر الأصلي. يقابل الحقل Addr1 العقدة E، ويحدّد الحقل Addr2 نقطة الوصول AP-3، ويقابل الحقل Addr3 نقطة الوصول AP-1، ويحدّد الجقل Addr4 العقدة A باستخدام المثال الموضّح في الشكل التالي: أمن الروابط اللاسلكية (Security of Wireless Links) تتمثل إحدى المشكلات الواضحة إلى حدٍ ما في الروابط اللاسلكية مقارنةً بالأسلاك أو الألياف في أنك لا تستطيع أن تكون متأكدًا تمامًا من مكان وصول بياناتك. يمكنك على الأرجح معرفة ما إذا كان المستقبل المقصود قد استقبل الإرسال، ولكن لا يوجد ما يشير إلى عدد أجهزة الاستقبال الأخرى التي ربما قد التقطت إرسالك، لذلك إذا كنت قلقًا بشأن خصوصية بياناتك، فإن الشبكات اللاسلكية تمثل تحديًا، وحتى إذا لم تكن مهتمًا بخصوصية البيانات أو ربما تهتم بها بطريقة أخرى، فقد تكون قلقًا بشأن أن يحقن مستخدمٌ غير مصرَّح له بياناتٍ في شبكتك، أو قد يكون هذا المستخدم قادرًا على استهلاك الموارد التي تفضل أن تستهلكها بنفسك، مثل حيز النطاق التراسلي المحدود بين منزلك ومزوّد خدمة الإنترنت. لذلك تأتي الشبكات اللاسلكية عادةً بنوع من الآليات للتحكم في الوصول إلى كل من الرابط نفسه والبيانات المرسلة، حيث تُصنَّف هذه الآليات على أنها أمن لاسلكي (wireless security). البلوتوث 802.15.1 تملأ تقنية البلوتوث نطاق الاتصال قصير المدى للغاية بين الهواتف المحمولة وأجهزة المساعد الرقمي الشخصي (PDAs) وأجهزة الحاسوب المحمولة والأجهزة الشخصية أو الطرفية الأخرى، فعلى سبيل المثال، يمكن استخدام تقنية البلوتوث لتوصيل هاتف محمول بسماعة رأس أو حاسوب محمول. تُعد تقنية البلوتوث بديلًا أكثر ملاءمة لتوصيل جهازين بسلك، حيث ليس من الضروري توفير نطاق أو حيز نطاقٍ تراسلي كبير في مثل هذه التطبيقات، وهذا يعني أن أجهزة راديو البلوتوث يمكنها استخدام نقل ذو طاقة منخفضة جدًا، نظرًا لأن قوة الإرسال هي أحد العوامل الرئيسية التي تؤثر على حيز النطاق التراسلي ونطاق الروابط اللاسلكية. يتطابق هذا مع التطبيقات المستهدفة للأجهزة التي تدعم تقنية البلوتوث التي تعمل معظمها باستخدام المدَّخرة (مثل سماعة الهاتف واسعة الانتشار)، وبالتالي من المهم ألا تستهلك الكثير من الطاقة. تعمل تقنية البلوتوث في النطاق المُعفى من الترخيص عند 2.45 جيجاهرتز. تحتوي روابط البلوتوث على حيز نطاقٍ تراسلي نموذجي يتراوح من 1 إلى 3 ميجابت في الثانية ونطاق يبلغ حوالي 10 أمتار. لذلك تُصنَّف تقنية البلوتوث أحيانًا على أنها شبكة منطقة شخصية (Personal Area Network أو اختصارًا PAN) نظرًا لأن أجهزة الاتصال تنتمي عادةً إلى فرد واحد أو مجموعة. حدّد اتحادٌ صناعي يسمى مجموعة الاهتمامات الخاصة بتقنية البلوتوث (Bluetooth Special Interest Group) تقنيةَ البلوتوث التي تحدد مجموعةً كاملة من البروتوكولات تتجاوز طبقة الربط لتعريف بروتوكولات التطبيق، والتي تسمى ملفات التعريف (profiles)، لمجموعة من التطبيقات. يوجد ملف تعريف لمزامنة جهاز PDA مع حاسوب شخصي، ويتيح ملف تعريفٍ آخر للحاسوب المحمول الوصول إلى شبكة LAN سلكية باستخدام المعيار 802.11، على الرغم من أن هذا لم يكن هدف تقنية البلوتوث الأصلي. يعتمد معيار IEEE 802.15.1 على تقنية البلوتوث ولكنه يستثني بروتوكولات التطبيق. يتكون الضبط الأساسي لشبكة البلوتوث، المسمَّى piconet، من جهاز رئيسي (master device) وأجهزة تابعة (slave devices) يصل عددها إلى 7 أجهزة، كما هو موضَّح في الشكل الآتي. يكون أي اتصال بين الجهاز الرئيسي والأجهزة التابعة، فلا تتواصل الأجهزة التابعة مباشرةً مع بعضها البعض، ويمكن أن يكون عتاد وبرمجيات البلوتوث الخاصة بالأجهزة التابعة أبسط وأرخص نظرًا لأن لديهم دورًا أبسط. يجب استخدام تقنية الطيف المنتشر للتعامل مع التداخل المحتمَل في النطاق نظرًا لأن تقنية البلوتوث تعمل في نطاقٍ مُعفى من الترخيص، وتستخدم قفز التردد مع 79 قناةً (ترددًا) باستخدام 625 ميكرو ثانية لكلٍ منها في المرة الواحدة، ويوفّر هذا فتحةً (slot) زمنية للبلوتوث لاستخدامها في الدمج بتقسيم الوقت المتزامن. يشغّل الإطار 1 أو 3 أو 5 فتحات زمنية متعاقبة، ويمكن للجهاز الرئيسي فقط البدء بالإرسال في فتحات ذات أرقام فردية، ويمكن أن يبدأ الجهاز التابع بالإرسال في فتحةٍ ذات رقم زوجي، ولكن فقط استجابةً لطلبٍ من الجهاز الرئيسي أثناء الفتحة السابقة، وبالتالي منعَ أي خلاف بين الأجهزة التابعة. يمكن إيقاف (parked) الجهاز التابع، أي ضبطه على حالة غير نشطة ومنخفضة الطاقة، ولا يمكن للجهاز المتوقف الاتصال على شبكة piconet، ولا يمكن إعادة تنشيطه إلا بواسطة الجهاز الأساسي. يمكن أن تحتوي شبكة piconet على ما يصل إلى 255 جهازًا متوقفًا بالإضافة إلى الأجهزة التابعة النشطة. هناك عدد قليل من التقنيات الأخرى إلى جانب البلوتوث في عالم الاتصالات قصيرة المدى ومنخفضة الطاقة للغاية، إحداها تقنية زيجبي (ZigBee)، التي ابتكرها تحالف ZigBee ووُحّد وفقًا لمعيار IEEE 802.15.4، وهي مصمَّمة للحالات التي تكون فيها متطلبات حيز النطاق التراسلي منخفضة ويجب أن يكون استهلاك الطاقة منخفضًا جدًا لإعطاء البطارية عمرًا طويلًا جدًا، وأن تكون هذه التقنية أيضًا أبسط وأرخص من البلوتوث، مما يجعل من الممكن دمجه ضمن أجهزة أرخص مثل أجهزة الاستشعار (sensors). أصبحت أجهزة الاستشعار فئة مهمة بصورة متزايدة من الأجهزة المتصلة بالشبكة مع تقدم التكنولوجيا إلى المرحلة التي يمكن فيها نشر أجهزة صغيرة ورخيصة جدًا بكميات كبيرة لمراقبة أشياء مثل درجة الحرارة والرطوبة واستهلاك الطاقة في مبنى. شبكات الوصول (Access Networks) يتصل معظمنا بالإنترنت عبر الوصول (access) أو خدمة النطاق العريض (broadband) التي نشتريها من مزود خدمة الإنترنت بالإضافة إلى اتصالات الإيثرنت والواي فاي التي نستخدمها عادةً للاتصال بالإنترنت في المنزل وفي العمل وفي المدرسة وفي العديد من الأماكن العامة. يعرض هذا القسم تقنيتين من هذه التقنيات: الشبكات الضوئية السلبية (Passive Optical Networks أو اختصارًا PON) التي يُشار إليها عادة باسم ليف إلى شقق (fiber-to-the-home)، والشبكات الخلوية (Cellular Networks) التي تربط أجهزتنا المحمولة. تكون الشبكات متعددة الوصول في كلتا الحالتين (مثل شبكتَي الإيثرنت والواي فاي)، ولكن نهجها في التوسط في الوصول مختلف تمامًا. يشغّل مزودو خدمات الإنترنت (مثل شركتَي Telco أو Cable) الشبكة الأساسية الوطنية، ويتصل بمحيط هذه الشبكة مئات أو آلاف المواقع الطرفية، وكل منها يخدّم مدينة أو حيًا. تسمى هذه المواقع الطرفية عادةً بالمكاتب المركزية (Central Offices) في عالم Telco والنهايات الرأسية (Head Ends) في عالم Cable. تقع هذه المواقع في أقصى حدود شبكة مزود خدمة الإنترنت من جانب مزوّد ISP في الميل الأخير الذي يتصل مباشرة بالعملاء، على الرغم من أن أسماء هذه المواقع تشير إلى المركزية وجذر التسلسل الهرمي. ترتكز شبكات الوصول PON و Cellular على هذه الوسائل، فتقنية DSL هي نظير شبكة PON القديم القائم على النحاس، حيث تنهي مكاتب Telco المركزية روابط DSL (لن نصِف هذه التقنية نظرًا لأنه يجري التخلص التدريجي منها حاليًا). الشبكة الضوئية السلبية (Passive Optical Network) شبكة PON هي التقنية الأكثر استخدامًا لتقديم النطاق العريض القائم على الألياف إلى المنازل والشركات. تتبنى PON تصميمًا من نقطة إلى عدة نقاط، مما يعني أن الشبكة مبنية على شكل شجرة، مع نقطة واحدة تبدأ في شبكة مزود خدمة الإنترنت ثم تنتشر لتصل إلى 1024 منزلًا. تحصل شبكة PON على اسمها من حقيقة أن الفواصل (splitters) سلبية، فهي توجه الإشارات الضوئية الصاعدة والنازلة دون تخزين الإطارات أو إعادة توجيهها بصورة نشطة. وبالتالي هي البديل الضوئي للمكررات المستخدمة في الإيثرنت الكلاسيكي، ثم يحدث التأطير عند المصدر في مباني مزود خدمة الإنترنت في جهاز يسمى طرفية الخط الضوئي (Optical Line Terminal أو اختصارًا OLT)، ويحدث التأطير في النقاط النهائية في المنازل الفردية في جهاز يسمى وحدة الشبكة الضوئية (Optical Network Unit أو اختصارًا ONU). يوضح الشكل الآتي مثالًا عن شبكة PON، فالشكل مبسّط بوحدة ONU واحد وطرفية OLT واحدة، حيث يشمل المكتب المركزي عدة طرفيات OLT متصلة بآلاف منازل العملاء عمليًا، ويتضمن الشكل الآتي أيضًا تفصيلين آخرين حول كيفية توصيل شبكة PON بالشبكة الأساسية لمزود خدمة الإنترنت (وبالتالي ببقية الإنترنت). يجمّع مبدّل Agg حركة مرور البيانات من مجموعة طرفيات OLT، وبوابة شبكة النطاق العريض (Broadband Network Gateway أو اختصارًا BNG) وهي قطعة من معدات Telco التي، من بين أشياء أخرى كثيرة، تقيس حركة مرور بيانات الإنترنت بغرض الفوترة. إن بوابة BNG هي فعليًا البوابة بين شبكة الوصول (كل شيء على يسار BNG) والإنترنت (كل شيء على يمين BNG). يتعيّن على تقنية PON تنفيذ شكلٍ من أشكال بروتوكول الوصول المتعدد نظرًا لأن الفواصل سلبية، ويمكن تلخيص النهج الذي تعتمده على النحو التالي: أولًا تُرسل حركة مرور البيانات الصاعدة والنازلة على طولين موجيين ضوئيين مختلفين، لذلك يكون كل منهما مستقلًا تمامًا عن الآخر. تبدأ حركة المرور النازلة عند طرفية OLT، وتُنشَر الإشارة أسفل كل رابط في شبكة PON، لذلك يصل كل إطار إلى كل وحدة ONU، ثم ينظر هذا الجهاز بعد ذلك إلى معرّفٍ فريد في الإطارات المرسَلة عبر الطول الموجي، ويحتفظ بالإطار (إذا كان المعرّف مناسبًا له) أو يستبعده (إذا لم يكن كذلك). يُستخدَم التشفير لمنع وحدات ONU من التنصت على حركة مرور جيرانهم، ثم تُدمَج حركة المرور الصاعدة بالتقسيم الزمني على طول الموجة الصاعدة، مع حصول كل وحدة ONU دوريًا على دور للإرسال. ليس من العملي بالنسبة لوحدات ONU الإرسال استنادًا إلى الساعات المتزامنة، كما هو الحال في تقنية SONET، نظرًا لأن وحدات ONU موزَّعة على مساحة واسعة إلى حد ما (تقاس بالكيلومترات) وعلى مسافات مختلفة من طرفيات OLT، فترسل طرفية الشبكة الضوئية ONT بدلًا من ذلك مِنحًا (grants) إلى وحدات ONU، مما يمنحها فترة زمنية يمكنها الإرسال خلالها. أي أن طرفية OLT مسؤولة عن التطبيق المركزي لمشاركة التخصيص الدوري (Round-robin) لشبكة PON المشتركة، ويتضمن ذلك إمكانية أن يمنح OLT كل وحدة ONU حصةً مختلفة من الوقت، وتنفيذ مستويات مختلفة من الخدمة بصورة فعالة. تشبه شبكة PON شبكة إيثرنت بمعنى أنها تحدد خوارزميةً متشارَكةً تطورت بمرور الوقت لاستيعاب نطاقات أعلى وأعلى. شبكة Gigabit-PON أو اختصارًا G-PON هي الأكثر انتشارًا اليوم، حيث تدعم حيز النطاق التراسلي 2.25 جيجابت في الثانية، وبدأ الآن نشر شبكة 10Gigabit-PON أو اختصارًا XGS-PON. الشبكة الخلوية (Cellular Network) أصبحت خدمات البيانات القائمة على المعايير الخلوية الآن هي المعيار، على الرغم من أن تقنية الهاتف الخلوي لها جذورها في الاتصالات الصوتية التناظرية. تنقل الشبكات الخلوية البيانات عند حيز نطاق تراسلي معين في الطيف الراديوي مثل شبكة Wi-Fi. بِيع الاستخدام الحصري لنطاقات التردد المختلفة بالمزاد العلني ورُخِّص لمزودي الخدمة الذين يبيعون بدورهم خدمة الوصول عبر الهاتف المحمول لمشتركيهم على عكس شبكة Wi-Fi التي تسمح لأي شخص باستخدام قناة بتردد 2.4 أو 5 جيجاهرتز (كل ما عليك فعله هو إنشاء محطة قاعدية، كما يفعل الكثير منا في منازلنا). تختلف نطاقات التردد المستخدمة للشبكات الخلوية في جميع أنحاء العالم، وهي معقدة بسبب حقيقة أن مزودي خدمة الإنترنت غالبًا ما يدعمون في نفس الوقت التقنيات القديمة / السابقة وتقنيات الجيل الجديد / التالي، وكل منها يشغّل نطاق تردد مختلف. التقنيات الخلوية التقليدية تتراوح من 700 ميجاهرتز إلى 2400 ميجاهرتز، مع تخصيصات جديدة متوسطة الطيف تحدث الآن عند 6 جيجاهرتز وتخصيصات الموجات المليمترية (mmWave) التي تُفتح فوق 24 جيجاهرتز. تعتمد التقنية الخلوية على استخدام المحطات القاعدية المتصلة بشبكة سلكية مثل المعيار 802.11، وتسمى المحطات القاعدية وحدات النطاق العريض القاعدية (Broadband Base Units أو اختصارًا BBU)، وعادة ما يشار إلى الأجهزة المحمولة التي تتصل بها باسم معدات المستخدم (User Equipment أو اختصارًا UE)، وتُضبَط مجموعة وحدات BBU في مركز رزم متطور (Evolved Packet Core أو اختصارًا EPC) مُستضاف في مكتب مركزي، وتسمى الشبكة اللاسلكية التي يخدّمها مركز EPC بشبكة الوصول الراديوي (Radio Access Network أو اختصارًا RAN). تحمل وحدات BBU رسميًا اسمًا آخر هو NodeB المطورة (Evolved NodeB)، وتُختصر إلى eNodeB أو eNB، حيث أن NodeB سُمِّيت وحدة الراديو في تجسيدٍ قديم للشبكات الخلوية (وتطورت منذ ذلك الحين). قررنا استخدام وحدة BBU الأعم والأقل تشفيرًا نظرًا لاستمرار العالم الخلوي في التطور بوتيرة سريعة حيث ستُرقّى قريبًا وحدات eNB إلى وحدات gNB. يوضح الشكل الآتي إعدادًا واحدًا محتملًا لسيناريو شبكة نقطة لنقطة، مع بضع بتات إضافية من التفاصيل. يحتوي مركز EPC على مكونات فرعية متعددة، بما في ذلك كيان MME كيان إدارة التنقل (Mobility Management Entity)، وخادوم HSS خادوم المشترِك الرئيسي (Home Subscriber Server)، وزوج S / PGW جلسة / بوابة الرزمة (Session/Packet Gateway). يتتبّع ويدير كيانُ MME حركةَ معدات UE عبر شبكة RAN، والخادوم HSS هو عبارة عن قاعدة بيانات تحتوي على المعلومات المتعلقة بالمشترِك، ويعالج زوج البوابة الرزمَ ويعيد توجيهها بين شبكة RAN والإنترنت، أي يشكّل مستوى المستخدم (user plane) لمركز EPC. نقول إعدادًا واحدًا محتملًا (one possible configuration) لأن المعايير الخلوية تسمح بتنوع كبير في عدد أزواج S / PGW التي يتحملها كيان MME معين، مما يجعل من الممكن لكيان MME إدارة التنقل عبر منطقة جغرافية واسعة تخدّمها عدة مكاتب مركزية. تُستخدَم في بعض الأحيان شبكة PON الخاصة بمزود خدمة الإنترنت لتوصيل وحدات BBU البعيدة بالمكتب المركزي على الرغم من عدم توضيحها صراحةً في الشكل التالي: تسمى المنطقة الجغرافية التي يخدّمها هوائي BBU بالخلية (cell)، فيمكن أن تخدّم وحدة BBU خلية واحدة أو تستخدم هوائيات متجهة متعددة لخدمة خلايا متعددة. ليس للخلايا حدود واضحة وهي متداخلة، فإذا تتداخلت، يمكن أن تتواصل معدات UE مع العديد من وحدات BBU، ولكن تكون معدات UE على اتصال مع وحدة BBU واحدة فقط وتحت سيطرتها في أي وقت. ينتقل الجهاز إلى منطقة تداخل مع خلية أخرى أو أكثر عندما يبدأ بمغادرة خلية، ثم تستشعر وحدة BBU الحالية الإشارة الضعيفة من الهاتف وتمنح التحكم بذلك الجهاز لأي محطة قاعدية تتلقى أقوى إشارة منها. إذا كان الجهاز مشتركًا في مكالمة أو جلسة شبكة أخرى في ذلك الوقت، فيجب نقل الجلسة إلى المحطة القاعدية الجديدة، حيث يسمى ذلك بالتسليم (handoff). تندرج عملية اتخاذ القرار لعمليات التسليم ضمن اختصاص كيان MME، والذي كان تاريخيًا جانبًا مملوكًا لبائعي المعدات الخلوية (على الرغم من أن تطبيقات كيان MME مفتوحة المصدر بدأت الآن أن تصبح متاحة). كانت هناك أجيال متعددة من البروتوكولات التي تنفّذ الشبكة الخلوية، والمعروفة بالعامية باسم 1G و 2G و 3G وما إلى ذلك. دعمَ الجيلان الأولان الصوت فقط، ودعم الجيل الثالث معدلات البيانات المقاسة بمئات الكيلوبتات في الثانية مع تحديده الانتقال للوصول إلى النطاق العريض، وصلت الصناعة اليوم إلى الجيل الرابع (تقاس معدلات البيانات الداعمة عادةً في بضع ميجابتات في الثانية)، وهو في طور الانتقال إلى 5G (مع وعدٍ بزيادة معدلات البيانات بمقدار عشرة أضعاف). يتوافق تعريف الأجيال فعليًا مع معيارٍ يُعرّفه مشروع شراكة الجيل الثالث (3rd Generation Partnership Project أو اختصارًا 3GPP) ابتداءً من الجيل الثالث. يواصل مشروع 3GPP تحديد معيارَي 4G و 5G على الرغم من أن اسمها يحتوي على 3G، حيث يتوافق كلٌّ منهما مع إصدارٍ لهذا المعيار. يُعَد الإصدار 15، الذي نُشر الآن، هو النقطة الفاصلة بين 4G و 5G. يُطلق على سلسلة الإصدارات والأجيال هذه اسم التطور طويل الأمد (Long-Term Evolution أو اختصارًا LTE). الخلاصة الرئيسية هي أنه في حين تُنشَر المعايير كسلسلة من الإصدارات المنفصلة، فإن الصناعة ككل كانت على مسار تطوري محدد يُعرف باسم LTE. يستخدم هذا القسم مصطلحات LTE، ولكنه يسلّط الضوء على التغييرات القادمة مع 5G عند الحاجة إلى ذلك. يتمثل الابتكار الرئيسي لواجهة LTE الهوائية في كيفية تخصيص الطيف الراديوي المتاح لتجهيزات UE. تستخدم تقنية LTE استراتيجية قائمة على الحجز (reservation) بعكس شبكة Wi-Fi القائمة على التنازع. يعود هذا الاختلاف إلى الافتراض الأساسي لكل نظام حول الاستخدامية، حيث تفترض شبكة Wi-Fi وجود شبكة محمّلة بطريقة خفيفة، وبالتالي تنقل بصورة متفائلة عندما يكون الرابط اللاسلكي خاملًا ويتراجع إذا اُكتشف الخلاف، بينما تفترض الشبكات الخلوية، بل وتسعى جاهدةً، إلى وجود استخداميةٍ مرتفعة (ومن ثم تعيين مستخدمين مختلفين بصورة صريحة إلى مشاركات مختلفة من الطيف الراديوي المتاح). تُعرَف آلية وصول LTE إلى الوسائط الحديثة باسم الوصول المتعدد المتعامد بتقسيم التردد (Orthogonal Frequency-Division Multiple Access أو اختصارًا OFDMA). تكمن الفكرة في دمج البيانات عبر مجموعة من 12 ترددًا متعامدًا من الموجات الحاملة الفرعية، وتُعدَّل كلٌ منها بصورة مستقلة. يشير الوصول المتعدد (Multiple Access) في OFDMA إلى أنه يمكن إرسال البيانات في نفس الوقت لمستخدمين متعددين، كل منها على تردد موجة حاملة فرعية مختلفة ولمدة زمنية مختلفة. النطاقات الفرعية ضيقة (15 كيلوهرتز مثلًا)، ولكن تشفير بيانات المستخدم إلى رموز OFDMA مصمَّمٌ لتقليل مخاطر فقدان البيانات بسبب التداخل بين النطاقات المجاورة. يؤدي استخدام تقنية OFDMA بطبيعة الحال إلى تصور الطيف الراديوي كمورد ثنائي الأبعاد، كما هو مبين في الشكل الآتي. تتوافق الوحدة الدنيا القابلة للجدولة والتي تسمى عنصر المورد (Resource Element أو اختصارًا RE) مع نطاقٍ عرضه 15 كيلوهرتز حول تردد موجة حاملة فرعية واحدة، وتتوافق مع الوقت المستغرق لإرسال رمز OFDMA واحد. يعتمد عدد البتات التي يمكن تشفيرها في كل رمز على معدل التعديل، لذلك ينتج عن 16 QAM (أربعة بتات لكل رمز)، وينتج عن 64 QAM ستة بتات لكل رمز باستخدام تعديل سعة التربيع (Quadrature Amplitude Modulation أو اختصارًا QAM) على سبيل المثال. يتّخذ المجدول (scheduler) قرارات التخصيص على مستوى تقسيمات الكتل، أي 7 × 12 = 84 عنصر مورد تسمى كتلة الموارد الفيزيائية (Physical Resource Block أو اختصارًا PRB). يوضّح الشكل السابق اثنين من أجهزة PRB المتتالية، حيث تُوصَف معدات UE بكتلٍ ملونة مختلفة. يستمر الوقت في التدفق على طول محور واحد، وقد يكون هناك العديد من فتحات الموجات الحاملة الفرعية (وبالتالي العديد من كتل PRB) المتاحة على طول المحور الآخر اعتمادًا على حجم نطاق التردد المرخص، لذلك يجدول المجدول سلسلةً من كتل PRB للانتقال. يتوافق فاصل الإرسال الزمني (Transmission Time Interval أو اختصارًا TTI) البالغ 1 ميلي ثانية والموضّح في الشكل السابق مع الإطار الزمني الذي تتلقى فيه وحدة BBU تغذيةً راجعة من مجموعة معدات UE حول جودة الإشارة التي يواجهونها. تُبلِّغ هذه التغذية الراجعة، التي تسمى *مؤشر جودة القناة (Channel Quality Indicator أو اختصارًا CQI)، عن نسبة الإشارة إلى الضجيج المُلاحَظة، والتي تؤثر على قدرة معدات UE على استعادة بتات البيانات، ثم تستخدم المحطة القاعدية هذه المعلومات لتكييف طريقة تخصيصها للطيف الراديوي المتاح مع مجموعة معدات UE التي تخدّمها. إن وصف كيفية جدولة الطيف الراديوي خاصٌ بالتقنية 4G. يقدم الانتقال من 4G إلى 5G درجات حُريّة إضافية في كيفية جدولة الطيف الراديوي، مما يجعل من الممكن تكييف الشبكة الخلوية مع مجموعة أكثر تنوعًا من مجالات الأجهزة والتطبيقات. تحدد تقنية 5G عائلةً من أشكال الموجة (waveforms) على عكس تقينة 4G التي حددت شكل موجة واحد فقط. حُسِّن كل شكلٍ من أشكال الموجة من أجل نطاقٍ مختلف في الطيف الراديوي، حيث شكل الموجة (waveform) هو خاصية التردد والسعة وانزياح الطور المستقلة أو الشكل (shape) الخاص بالإشارة، فالموجة الجيبية (sine wave) هي مثالٌ على شكل موجة. صُمِّمت النطاقات ذات الترددات الحاملة التي تقل عن 1 جيجاهرتز لتقديم خدمات النطاق العريض المتنقلة وخدمات إنترنت الأشياء (IoT) الضخمة مع التركيز الأساسي على النطاق، وصُمِّمت ترددات الموجة الحاملة بين 1 جيجاهرتز و 6 جيجاهرتز لتقديم نطاقات أوسع مع التركيز على النطاق العريض المتنقل والتطبيقات ذات المهام الحرجة، وصُمِّمت ترددات الموجات الحاملة التي تزيد عن 24 جيجاهرتز (mmWaves) لتوفير نطاقات عريضة فائقة عبر تغطية قصيرة لخط النظر (line-of-sight). تؤثر هذه الأشكال الموجية المختلفة على الجدولة وفترات الموجات الحاملة الفرعية (أي حجم عناصر المورد الموصوفة سابقًا): بالنسبة للنطاقات الفرعية 1 جيجاهرتز، فإن 5 جيجاهرتز تسمح بحد أقصى 50 ميجاهرتز. هناك شكلين موجيين في هذه الحالة: يوجد في أحدهما تباعد بين الموجات الحاملة الفرعية 15 كيلوهرتز والآخر فيه تباعد 30 كيلوهرتز. (استخدمنا 15 كيلوهرتز في المثال الموضّح في الشكل السابق، وفترات الجدولة المقابلة هي 0.5 ميلي ثانية و 0.25 ميلي ثانية على التوالي، حيث استخدمنا 0.5 ميلي ثانية في المثال الموضح في الشكل السابق). بالنسبة للنطاقات من 1 جيجاهرتز إلى 6 جيجاهرتز، يصل الحد الأقصى لحيز النطاق التراسلي إلى 100 ميجاهرتز، وبالمقابل هناك ثلاثة أشكال موجية مع مباعدة حاملة فرعية 15 كيلوهرتز و 30 كيلوهرتز و 60 كيلوهرتز، المقابلة لفترات جدولة 0.5 ميلي ثانية و 0.25 ميلي ثانية و 0.125 ميلي ثانية على التوالي. بالنسبة للنطاقات المليمترية، قد يرتفع حيز النطاق التراسلي إلى 400 ميجاهرتز، وهناك نوعان من أشكال الموجات مع مباعدة الموجات الفرعية 60 كيلوهرتز و 120 كيلوهرتز. كلاهما له فترات جدولة مقدارها 0.125 ميلي ثانية. مجال الخيارات هذا مهمٌ لأنه يضيف درجةً أخرى من الحريّة للمجدول، فلديه القدرة على ضبط حجم كتل الموارد ديناميكيًا عن طريق تغيير شكل الموجة المستخدم في النطاق المسؤول عن الجدولة بالإضافة إلى تخصيص كتل الموارد للمستخدمين. إن خوارزمية الجدولة هي مسألة تحسينٍ صعبة سواءً في الجيل الرابع أو الخامس، بهدف: زيادة استخدامية نطاق التردد المتاح إلى الحد الأقصى، وضمان أن معدات UE تستقبل مستوى الخدمة التي تتطلبها. لم يحدد مشروع 3GPP هذه الخوارزمية، بل هي ملكية فكرية لمصنّعي وحدات BBU. منظور الفصل الثاني: سباقٌ إلى حافة الشبكة (Race to the Edge) يجب أن تدرك أن شبكة الوصول التي تربط المنازل والشركات ومستخدمي الهاتف المحمول بالإنترنت هي التي تخضع للتغيير الأكثر جذرية عندما تبدأ في استكشاف كيفية تغيير البرمجيات في الشبكة، حيث تُبنى حاليًا شبكات ليف إلى شقق والشبكات الخلوية الموضحة سابقًا من الأجهزة المعقدة (مثل طرفيات OLT وبوابات BNG ووحدات BBU ومراكز EPC). لم يقتصر الأمر على تملّك هذه الأجهزة تاريخيًا، ولكن يجمّع البائعون الذين يبيعونها عادةً مجموعة واسعة ومتنوعة من الوظائف في كل منها، لذلك أصبح بناؤها مكلفًا ومعقد التشغيل وبطيء التغيير. فاستجابة لذلك، ينتقل مشغّلو الشبكات بنشاط من هذه الأجهزة المصمَّمة لهذا الغرض لفتح البرامج التي تعمل على الخواديم السلعيّة والمبدّلات وأجهزة الوصول. تسمى هذه المبادرة CORD، وهي اختصار للمكتب المركزي المُعاد تصميمه كمركز بيانات (Central Office Re-architected as a Datacenter). وكما يوحي الاسم، فإن الفكرة هي بناء مكتب مركزي (Central Office) لشركة Telco (أو نهاية رأسية (Head End) لشركة Cable الذي يُختصر إلى HERD) باستخدام نفس التقنيات الموجودة في مراكز البيانات الكبيرة التي تشكّل السحابة. الدافع وراء قيام المشغلين بذلك هو الاستفادة جزئيًا من توفير التكلفة التي تأتي من استبدال الأجهزة المصمَّمة لغرض معين بأجهزة سلعيّة، ولكن الدافع في الغالب هو الحاجة إلى تسريع وتيرة الابتكار، وهدفهم هو تفعيل فئاتٍ جديدة من الخدمات المتطورة مثل: السلامة العامة والمركبات ذاتية القيادة والمصانع الآلية وإنترنت الأشياء (IoT) وواجهات المستخدم الغامرة، التي تستفيد من الاتصال بزمن استجابة منخفض للمستخدمين النهائيين. والأهم من ذلك، العدد المتزايد من الأجهزة التي يحاط هؤلاء المستخدمون بها، فينتج عن هذا سحابة متعددة المستويات (multi-tier) مماثلة لتلك الموضحة في الشكل التالي: هذا كله جزء من الاتجاه المتزايد لنقل الوظائف خارج مركز البيانات وأقرب إلى حافة الشبكة، وهو اتجاه يضع مزودي الخدمات السحابية ومشغلي الشبكات في مسار تصادمي، حيث ينتقل مزودو السحابة، سعيًا وراء تطبيقات ذات وقت استجابة منخفض مع حيز نطاق تراسلي عالٍ، من مركز البيانات ونحو الحافة، في نفس الوقت الذي يتبنى فيه مشغلو الشبكات أفضل الممارسات والتقنيات الخاصة بالسحابة إلى الحافة الموجودة بالفعل، ويطبّقون شبكة الوصول. من المستحيل القول كيف سينتهي الأمر بمرور الوقت، فكلتا الصناعتين لها مزاياها الخاصة. يعتقد مزودو الخدمات السحابية من ناحية أخرى أنه يمكنهم بناء تواجد متطور مع وقت استجابة منخفض بدرجة كافية وحيز نطاق تراسلي مرتفع بما يكفي لخدمة الجيل التالي من التطبيقات المتطورة من خلال تشبيع مناطق المترو بعناقيد الحواف والتخلص من شبكة الوصول. تظل شبكة الوصول عبارة عن أنبوب خبيث في هذا السيناريو، مما يسمح لمزودي الخدمات السحابية بالتفوق فيما يفعلونه بصورة أفضل، والذي هو تشغيل خدمات سحابية قابلة للتوسّع على أجهزة سلعية. يعتقد مشغلو الشبكات من ناحية أخرى أنهم قادرون على تحديد موقع التطبيقات المتطورة في شبكة الوصول من خلال بناء الجيل التالي من شبكات الوصول باستخدام التقنية السحابية، حيث يأتي هذا السيناريو مع مزايا مضمنة وهي بصمة فيزيائية قائمة وموزعة على نطاق واسع ودعم تشغيلي قائم ودعم محلي لكل من التنقل والخدمة المضمونة. هناك نتيجة ثالثة مع الاعتراف بكل من هذين الاحتمالين لا تستحق الدراسة فحسب، بل تستحق أيضًا العمل عليها، وهي إضفاء الطابع الديمقراطي على حافة الشبكة. تكمن الفكرة في إتاحة الوصول إلى سحابة حافة الوصول لأي شخص بطريقة غير صارمة إلى مجال مزودي السحابة الحاليين أو مشغلي الشبكات. هناك ثلاثة أسباب تجعلنا متفائلين بهذا الاحتمال هي: أصبحت الأجهزة والبرامج الخاصة بشبكة الوصول سلعيةً ومفتوحة، وهذا عامل تمكينٍ رئيسي تحدثنا عنه للتو، فإذا كان يساعد شركات Telco و CableCo على أن تكون نشطة، فسيمكنها توفير نفس القيمة لأي شخص. ترغب الشركات في مجال السيارات والتصنيع والمستودعات بصورة متزايدة في نشر شبكات 5G خاصة بمجموعة متنوعة من حالات استخدام الأتمتة الفيزيائية، مثل مرآب (garage) بحيث يوقِفُ خادومٌ عن بعد سيارتك أو كاستخدام أرضية مصنع روبوتات الأتمتة. أصبح الطيف متاحًا، حيث فُتحت تقنية 5G للاستخدام في نموذج غير مرخَّص أو مرخص قليلًا في الولايات المتحدة وألمانيا كمثالين رئيسيين، وستتبعه دول أخرى قريبًا. هذا يعني أن تقنية 5G يجب أن يكون لديها حوالي 100-200 ميجاهرتز من الطيف المتاح للاستخدام الخاص. يمكن القول باختصار أن شبكة الوصول كانت تاريخياً من اختصاص شركات Telco و CableCo والبائعين الذين يبيعونها كصناديق ملكية، لكن برمجية ووهمية شبكة الوصول تفتح الباب لأي شخص (من المدن المتطورة إلى المناطق الريفية إلى مجمعات الأبنية والمصانع) لإنشاء سحابة وصول وتوصيلها بالإنترنت العام. نتوقع أن يصبح القيام بذلك سهلًا كما هو الحال اليوم بنشر موجّه WiFi. لا يؤدي القيام بذلك إلى جلب حافة الوصول إلى بيئات جديدة (أكثر حداثة) فحسب، بل لديه أيضًا القدرة على فتح شبكة الوصول للمطورين الذين يذهبون إلى مكان تواجد فرصٍ للابتكار. ترجمة -وبتصرّف- للقسمين Wireless Networks و Access Networks من فصل Direct Links من كتاب Computer Networks: A Systems Approach
-
طوّر باحثون في مركز أبحاث (Xerox Palo Alto Research Center أو اختصارًا PARC) شبكة الإيثرنت (Ethernet) في منتصف السبعينات، ثم أصبحت في النهاية تقنية الشبكات المحلية المهيمنة، التي انبثقت عن مجموعة من التقنيات المنافسة، وتتنافس اليوم بصورةٍ أساسية مع الشبكات اللاسلكية 802.11، ولكنها لا تزال تحظى بشعبية كبيرة في شبكات الحرم الجامعي ومراكز البيانات. الاسم الأعم للتقنية الكامنة وراء الإيثرنت هو تحسس الحامل، والوصول المتعدد مع كشف التصادم (Carrier Sense, Multiple Access with Collision Detect أو اختصارًا CSMA / CD). شبكة الإيثرنت عبارة عن شبكةٍ متعددة الوصول، مما يعني أن مجموعةً من العقد ترسل وتستقبل الإطارات عبر رابطٍ (link) مشترك، لذلك يمكنك التفكير في شبكة الإيثرنت على أنها مثل الحافلة التي لديها محطات متعددة متصلة بها. يعني المصطلح carrier sense في CSMA / CD أن جميع العقد يمكنها التمييز بين الرابط الخامل والرابط المشغول، ويعني المصطلح collision detect أن العقدة تستمع أثناء الإرسال، فيمكنها اكتشاف ما إذا كان الإطار الذي ترسله قد تداخل أو تصادم مع إطارٍ مُرسَل بواسطة عقدة أخرى. تعود جذور الإيثرنت إلى شبكة رزمٍ راديوية قديمة تسمى ألوها (Aloha) طُوِّرت في جامعة هاواي لدعم اتصالات الحاسوب عبر جزر هاواي. إن المشكلة الأساسية التي تواجهها شبكة إيثرنت، مثل شبكة ألوها، هي كيفية التوسط في الوصول إلى وسيط مشترك بصورة عادلة وفعالة (كان الوسيط في شبكة ألوها هو الغلاف الجوي، بينما الوسيط في شبكة إيثرنت في الأصل هو الكبل المحوري). الفكرة الأساسية في كلٍّ من شبكتَي ألوها وإيثرنت هي خوارزمية تتحكم في وقت إرسال كل عقدة. أصبحت روابط إيثرنت الحديثة الآن إلى حد كبير من نقطة لنقطة، أي أنها تصل مضيفًا واحد بمبدّل إيثرنت (Ethernet switch)، أو أنها تربط المبدّلات ببعضها، نتيجة لذلك لا تُستخدَم خوارزمية الوصول المتعدد كثيرًا في شبكات إيثرنت السلكية حاليًا. لكن يُستخدم البديل الآن في الشبكات اللاسلكية، مثل شبكات 802.11 (المعروفة أيضًا باسم Wi-Fi). اخترنا وصف الخوارزمية الكلاسيكية هنا نظرًا للتأثير الهائل لشبكة إيثرنت، ثم سنشرح كيف تكيفت مع شبكة Wi-Fi في القسم التالي، وسنركز على كيفية عمل رابط إيثرنت واحد في الوقت الحالي. انضمت شركتا Digital Equipment Corporation و Intel Corporation إلى مركز Xerox لتحديد معيار إيثرنت بسرعة 10 ميجابت في الثانية في عام 1978. ثم شكّل هذا المعيار أساسًا لمعيار IEEE 802.3، والذي يحدد أيضًا مجموعة أكبر بكثير من الوسائط الفيزيائية التي يمكن لشبكة إيثرنت العمل عليها، بما في ذلك إصدارات 100 ميجابت في الثانية و 1 جيجابت في الثانية و 10 جيجابت في الثانية و 40 جيجابت في الثانية و 100 جيجابت في الثانية. الخصائص الفيزيائية (Physical Properties) نُفِّذت مقاطع إيثرنت في الأصل باستخدام كبل محوري بطول يصل إلى 500 متر، وكان هذا الكبل مشابهًا للنوع المستخدَم في تلفاز الكابل. تستخدم شبكة الإيثرنت الحديثة أزواجًا نحاسية ملتوية (twisted copper pairs) وعادةً ما يكون نوعًا معينًا يُعرف باسم Category 5، أو الألياف الضوئية، وفي بعض الحالات يمكن أن يكون أطول بكثير من 500 متر. يتصل المضيفون بمقطع إيثرنت من خلال وصله به. يكتشف جهاز الإرسال والاستقبال (transceiver)، وهو جهاز صغير متصل مباشرة بالقابس (tap)، إذا كان الخط خاملًا، كما أنه يقود الإشارة عندما يرسل المضيف، ويستقبل الإشارات الواردة. جهاز الإرسال والاستقبال بدوره متصلٌ بمحوّل (adaptor) إيثرنت يوصَل بالمضيف. يظهر هذا الإعداد (configuration) في الشكل التالي: يمكن ربط مقاطع الإيثرنت المتعددة معًا بواسطة المكرّرات (repeaters)، أو جهازٍ متعدد المنافذ مغايرٍٍ عن المكرّر، يسمى الموزع (hub). المكرّر هو جهاز يمرر الإشارات الرقمية، كمكبّر صوت يمرر الإشارات التناظرية، حيث لا تفهم المكررات البتات أو الإطارات، ولا يمكن وضع أكثر من أربعة مكررات بين أي زوج من الأجهزة المضيفة، مما يعني أن شبكة الإيثرنت الكلاسيكية يبلغ إجمالي وصولها 2500 متر فقط، فاستخدام مكررين فقط على سبيل المثال بين أي زوج من الأجهزة المضيفة يدعم ضبطًا مشابهًا للضبط الموضح في الشكل التالي، أي يمتد المقطع الأساسي أسفل المبنى مع وجود مقطعٍ في كل طابق:ِ تُبَث أي إشارة توضع على شبكة الإيثرنت بواسطة مضيف عبر الشبكة بأكملها، أي أن الإشارة تنتشر في كلا الاتجاهين، وتعيد المكررات والموزعات توجيه الإشارة على جميع المقاطع الصادرة. تمتص الوصلات النهائية (Terminators) المتصلة بنهاية كل مقطع الإشارة وتمنعها من الارتداد والتداخل مع الإشارات اللاحقة. استخدمت مواصفاتُ إيثرنت الأصلية مخططَ ترميز مانشستر الموضَّح سابقًا، بينما يُستخدم تشفير 4B / 5B (أو مخطط 8B / 10B المماثل) اليوم على شبكات إيثرنت عالية السرعة. من المهم أن تفهم أنه إذا كانت شبكة إيثرنت معينة تمتد على مقطع واحد، أو على تسلسل خطي من المقاطع المتصلة بواسطة مكررات، أو مقاطع متعددة متصلة في إعداد شبكة نجمة (star)، فإن البيانات التي يرسلها أي مضيف واحد على شبكة الإيثرنت هذه تصل إلى جميع المضيفين الآخرين، وهذه هي الأخبار الجيدة، أما النبأ السيئ فهو أن كل هؤلاء المضيفين يتنافسون للوصول إلى نفس الرابط، ونتيجة لذلك يقال إنهم في نفس مجال التصادم (collision domain). يتعلق الجزء متعدد الوصول من الإيثرنت بالتعامل مع المنافسة على الرابط الذي ينشأ في مجال التصادم. بروتوكول الوصول (Access Protocol) وجّه انتباهك الآن إلى الخوارزمية التي تتحكم في الوصول إلى رابط إيثرنت مشترك. يُطلق على هذه الخوارزمية اسم التحكم في الوصول إلى الوسائط (media access control أو اختصارًا MAC) الخاص بشبكة إيثرنت، ويُنفَّذ عادةً في الأجهزة الموجودة على محوّل الشبكة. لن نشرح العتاد في حد ذاته، ولكن بدلًا من ذلك سنركز على الخوارزمية التي تنفّذها، وسنشرح أولًا صيغة إطار وعناوين إيثرنت. صيغة الإطار (Frame Format) يُعرَّف كل إطار من إطارات إيثرنت بالتنسيق الوارد في الشكل الآتي، حيث تسمح المقدمة (preamble) ذات 64 بت للمستقبل بأن يتزامن مع الإشارة، وهذه المقدمة هي سلسلة من الأصفار والواحدات المتناوبة. يُحدَّد كل من مضيفَي المصدر والوجهة بعنوان 48 بت. يعمل حقل نوع الرزمة كمفتاح فك دمج (demultiplexing key)، حيث يحدِّد أي من بروتوكولات المستوى الأعلى التي يجب تسليم هذا الإطار إليها. يحتوي كل إطار على ما يصل إلى 1500 بايت من البيانات، ويجب أن يحتوي الإطار على 46 بايتًا على الأقل من البيانات، حتى لو كان هذا يعني أن المضيف يجب أن يحشو الإطار قبل إرساله، والسبب في هذا الحجم الأدنى للإطار هو أن الإطار يجب أن يكون طويلًا بما يكفي لاكتشاف التصادم. أخيرًا، يتضمن كل إطار 32 بت لفحص التكرار الدوري (CRC) من أجل كشف الأخطاء. بروتوكول إيثرنت عبارة عن بروتوكول تأطير موجَّهٌ بالبت مثل بروتوكول HDLC الموضّح سابقًا. لاحظ أنه من منظور المضيف، يحتوي إطار إيثرنت على ترويسة ذات 14 بايتًا: عنوانان مؤلفان من 6 بايتات وحقل نوع مؤلف من 2 بايت، ويضيف محولُ الإرسال المقدمةََ وحقل CRC قبل الإرسال، ثم يزيلهما محوّل الاستقبال. العناوين (Addresses) يملك كل مضيفٍ على شبكة إيثرنت، بالأحرى كل مضيف إيثرنت في العالم، عنوانَ إيثرنت فريد. ينتمي العنوان إلى المحوّل وليس إلى المضيف، ويُحرَق عادةً على الذاكرة ROM. تُطبع عناوين إيثرنت عادةً في شكلٍ قابلٍ للقراءة من خلال سلسلةٍ من ستة أرقام مفصول بينها بنقطتين. يقابل كل رقم بايتًا واحدًا من العنوان المكوّن من 6 بايتات، حيث يُوفَّر من خلال زوجٍ من الأرقام الست عشرية، أي رقمٌ لكل 4 بتات من البايت الواحد، وتُهمل الأصفار البادئة. العنوان 8:0:2b:e4:b1:2 على سبيل المثال هو تمثيلٌ قابل للقراءة لعنوان الإيثرنت التالي: 00001000 00000000 00101011 11100100 10110001 00000010 تُخصَّص بادئةٌ (prefix) مختلفة لكل مُصنِّعٍ لأجهزة إيثرنت والتي يجب أن تُضاف في بداية العنوان الموجود على كل محولٍ مُنشَأ لضمان حصول كل محول على عنوان فريد، حيث تُسنَد بادئة مكونة من 24 بت 080020 أو 8:0:20 للأجهزة الدقيقة المتقدمة (Advanced Micro Devices) على سبيل المثال، ثم تتأكد الشركة المصنّعة أن لواحق (suffixes) العنوان التي ينتجها فريدة. يُستقبَل كل إطار مُرسَل عبر إيثرنت بواسطة كل محول متصل بشبكة إيثرنت، ويتعرّف كل محول على تلك الإطارات الموجهة إلى عنوانه ويمرر تلك الإطارات فقط إلى المضيف، ولكن يمكن أيضًا برمجة المحول ليعمل في الوضع العشوائي (promiscuous mode)، حيث يسلّم جميع الإطارات المستلمة إلى المضيف في هذه الحالة، لكن ليس هذا الوضع العادي. يُعامَل أيضًا عنوان إيثرنت الذي يتكون من كل الواحدات كعنوان بث إذاعي (broadcast address) بالإضافة إلى عناوين البث الأحادي (unicast addresses). تمرر جميعُ المحوّلات الإطاراتِ الموجهة إلى عنوان البث الإذاعي إلى المضيف. وبالمثل، يُضبَط البت الأول من العنوان بالقيمة 1 ولكنه ليس عنوان بث إذاعي بحيث يُسمى عنوان البث المتعدد (multicast address)، يمكن لمضيفٍ معين برمجة محوّله لقبول مجموعة من عناوين البث المتعدد. تُستخدم عناوين البث المتعدد لإرسال رسائل إلى مجموعة فرعية من المضيفين على شبكة إيثرنت (جميع خواديم الملفات على سبيل المثال)، حيث يستقبل محول الإيثرنت جميع الإطارات ويقبل ما يلي: إطارات موجهة إلى عنوانها الخاص. إطارات موجهة إلى عنوان البث الإذاعي. إطارات موجهة إلى عنوان البث المتعدد، إذا وُجِّه للاستماع إلى هذا العنوان. جميع الإطارات إذا وُضَعت في الوضع العشوائي. ولكنه يمرّر إلى المضيف فقط الإطارات التي يقبلها. خوارزمية المرسل (Transmitter Algorithm) إن جانب المستقبل من بروتوكول إيثرنت بسيط، وتُعرَّف خوارزمية المرسل على النحو التالي: ينقل المحوّل الإطار على الفور دون وجود تفاوضٍ مع المحولات الأخرى عندما يملك المحول إطارًا لإرساله ويكون الخط خاملًا. يعني الحد الأعلى البالغ 1500 بايت في الرسالة أن المحول يمكنه شغل الخط لفترة زمنية ثابتة فقط. إذا ملك المحولُ إطارًا لإرساله ولكن الخط مشغول فإنه ينتظر أن يصبح الخط خاملًا ثم يرسله على الفور، حيث تنتظر جميع المحولات 9.6 ميكرو ثانية بعد نهاية إطار واحد قبل البدء في إرسال الإطار التالي، وينطبق هذا على كل من مرسل الإطار الأول والعقد التي تستمع إلى الخط حتى يصبح خاملًا. يُقال إن إيثرنت هو بروتوكول واحد ثابت (1-persistent) لأنه مع وجود إطارٍ لإرساله، يرسل المحول هذا الإطار باحتمال 1 عندما يصبح الخط المشغول خاملًا، وترسل خوارزمية p-persistent باحتمال 0≤ p ≤1 بعد أن يصبح الخط خاملًا وتتأخر باحتمال q = 1 - p. السبب وراء اختيار p < 1 هو أنه قد يكون هناك محولات متعددة في انتظار أن يصبح الخط المشغول خاملًا، ولا نريد أن يبدأ كل منهم بالإرسال في نفس الوقت. إذا أرسل كل محول على الفور باحتمال، 33% مثلًا، فيمكن أن ينتظر ما يصل إلى ثلاثة محولات للإرسال بحيث يبدأ محولٌ واحد فقط الإرسال عندما يصبح الخط خاملًا، ولكن يرسل محول إيثرنت دائمًا وفورًا بعد ملاحظة أن الشبكة أصبحت خاملة وهذا فعالٌ جدًا. قد تتساءل عن المدة التي يتعين على المرسل، الذي يقرر التأجيل، أن ينتظرها قبل أن يتمكن من الإرسال بالنسبة لبروتوكولات p-persistent عندما تكون p < 1. كانت الإجابة بالنسبة لشبكة ألوها، التي طوَّرت في الأصل هذا النمط من البروتوكول، هي تقسيم الوقت إلى فترات منفصلة، بحيث تتوافق كل فترة مع طول الوقت الذي يستغرقه إرسال إطار كامل، وكلما كان للعقدة إطار لإرساله واستشعرت فترةً فارغة (خاملة)، فإنها ترسل باحتمال p وتؤجل حتى الفترة التالية ذات الاحتمال q = 1 - p. إذا كانت الفترة التالية فارغة أيضًا، تقرر العقدة مرة أخرى الإرسال أو التأجيل، مع الاحتمالين p و q على التوالي. إذا لم تكن الفترة التالية فارغة، أي أن بعض المحطات الأخرى قررت الإرسال، فإن العقدة تنتظر ببساطة الفترة التالية الخاملة وتتكرر الخوارزمية. أما بالنسبة لشبكة إيثرنت، فنظرًا لعدم وجود تحكم مركزي، فمن الممكن لمحوّلين (أو أكثر) بدء الإرسال في نفس الوقت، إما لأن كليهما وجد الخط خاملًا أو لأنها ينتظران خطًا مشغولًا ليصبح خاملًا، وبالتالي يُقال أن الإطارين (أو أكثر) يتصادمان على الشبكة عندما يحدث ذلك. يستطيع كل مرسل تحديد وجود تصادم نظرًا لأن الإيثرنت يدعم اكتشاف التصادم. يتأكد المحوّل أولًا من إرسال سلسلة تشويش (jamming sequence) مؤلفة من 32 بت في اللحظة التي يكتشف فيها أن إطاره يصطدم بآخر ثم يوقف الإرسال، وبالتالي سيرسل جهاز الإرسال 96 بتًا على الأقل في حالة حدوث تصادم: مقدمة (preamble) مؤلفة من 64 بت بالإضافة إلى سلسلة تشويش (jamming sequence) مؤلفة من 32 بت. تُستخدَم إحدى الطرق التي يرسل بها المحول 96 بتًا فقط، حيث يسمى أحيانًا إطارًا ضعيفًا (runt frame) وهو إطار أصغر من أدنى حجم، إذا كان المضيفان قريبان من بعضهما البعض. إذا كان المضيفان بعيدان عن بعضهما البعض، فيجب عليهما إرسال إطارات أطول، وبالتالي إرسال المزيد من البتات قبل اكتشاف التصادم. يحدث أسوأ سيناريو عندما يكون المضيفان على طرفي شبكة إيثرنت، فقد يحتاج المرسل إلى إرسال ما يصل إلى 512 بتًا للتأكد من أن الإطار الذي أرسله للتو لم يتعارض مع إطار آخر، لذلك ليس من قبيل الصدفة أن يكون طول كل إطار إيثرنت 512 بتًا (64 بايتًا) على الأقل: 14 بايتًا ترويسة بالإضافة إلى 46 بايتًا من البيانات و 4 بايتات لحقل CRC. لماذا 512 بتًا؟ تتعلق الإجابة بسؤال آخر قد تطرحه عن شبكة إيثرنت: لماذا يقتصر طول هذه الشبكة على 2500 متر فقط؟ لماذا ليست 10 أو 1000 كم؟ تتعلق الإجابة عن هذين السؤالين بحقيقة أنه كلما تباعدت عقدتان، كلما ازداد الوقت الذي يستغرقه الإطار الذي ترسله إحداهما للوصول إلى الأخرى، وتكون الشبكة عرضة للتصادم خلال هذا الوقت. يوضح الشكل السابق السيناريو الأسوأ، حيث يكون المضيفان A و B على طرفي الشبكة. افترض أن المضيف A يبدأ في إرسال إطار في الوقت t، كما هو موضح في القسم (أ) من الشكل السابق، حيث يستغرق الأمر وقت استجابة (latency) رابط واحد (يُشار إلى وقت الاستجابة d) حتى يصل الإطار إلى المضيف B، وبالتالي يصل البت الأول من إطار المضيف A إلى المضيف B في الوقت t + d كما هو موضح في القسم (ب) من الشكل السابق. افترض وجود لحظة قبل وصول إطار المضيف A (كأن يرى المضيف B أن الخط مازال خاملًا مثلًا)، فيبدأ المضيف B في إرسال إطاره الخاص. سيتصادم إطار المضيف B على الفور مع إطار المضيف A، وسيكتشف المضيف B هذا التصادم كما في القسم (ج) من الشكل السابق. سيرسل المضيف B سلسلة التشويش 32 بت (سيكون إطار B عبارة عن إطار ضعيف). لن يعرف المضيف A حدوث التصادم حتى يصل إطار المضيف B إليه لسوء الحظ، وسيحدث وقت استجابة رابط واحد لاحقًا في الوقت t + 2 × d، كما هو موضح في القسم (د) من الشكل السابق. يجب أن يستمر المضيف A في الإرسال حتى هذا الوقت لاكتشاف التصادم، أي يجب أن يرسل المضيف A لمدة 2 × d للتأكد من أنه يكتشف جميع التصادمات المحتملة، وبما أن طول إيثرنت المضبوط بحد أقصى هو 2500 متر، وأنه قد يكون هناك ما يصل إلى أربعة مكررات بين أي مضيفين، فقد حُدِّد تأخير الرحلة ذهابًا وإيابًا (round-trip) ليكون 51.2 ميكرو ثانية، والذي يتوافق مع 512 بت على شبكة إيثرنت 10 ميجابت في الثانية. الطريقة الأخرى للنظر إلى هذا الموقف هي أننا بحاجة إلى تقييد أقصى وقت استجابة لشبكة إيثرنت إلى قيمة صغيرة إلى حد ما، 51.2 ميكرو ثانية على سبيل المثال، حتى تعمل خوارزمية الوصول، ومن ثم يجب أن يكون الحد الأقصى لطول شبكة إيثرنت في حدود 2500 متر. ينتظر المحول قدرًا معينًا من الوقت بمجرد أن يكتشف المحوّل تصادمًا ويوقف الإرسال ثم يحاول مرة أخرى، حيث يضاعف المحول مقدار الوقت الذي ينتظره قبل المحاولة مرة أخرى في كل مرة يحاول الإرسال ويفشل. تدعى هذه الإستراتيجية لمضاعفة فاصل التأخير الزمني بين كل محاولة لإعادة الإرسال باسم التراجع الأسي (exponential backoff)، أي يؤخر المحول أولًا إما 0 أو 51.2 ميكرو ثانية، حيث يُختار عشوائيًا، وإذا فشل ذلك، فإنه ينتظر عندئذٍ 0 أو 51.2 أو 102.4 أو 153.6 ميكرو ثانية (يُختار عشوائيًا) قبل المحاولة مرة أخرى، أي هو k × 51.2 من أجل k = 0..3، ثم ينتظر k × 51.2 من أجل k = 0.23 - 1 بعد الاصطدام الثالث، ويُختار مرة أخرى عشوائيًا. تختار الخوارزمية عشوائيًا k بين 0 و 2n - 1 وتنتظر k × 51.2 ميكرو ثانية، حيث n هو عدد التصادمات التي حدثت حتى الآن. يستسلم المحول بعد عدد معين من المحاولات ويبلّغ عن خطأٍ في الإرسال إلى المضيف. تعيد المحوّلات عادةً المحاولة حتى 16 مرة، على الرغم من أن خوارزمية التراجع تحدد n بالقيمة 10. طول عمر شبكة إيثرنت (Longevity of Ethernet) كانت شبكة إيثرنت هي تقنية الشبكات المحلية المهيمنة لأكثر من 30 عامًا، ولكن تُنشَر اليوم عادةً لشبكات من نقطة لنقطة بدلًا من توصيلها على كبلٍ ملتوٍ، وغالبًا ما تُشغَّل بسرعات 1 أو 10 جيجابت في الثانية بدلًا من 10 ميجابت في الثانية، وتسمح برزم ضخمة تصل إلى 9000 بايت من البيانات بدلًا من 1500 بايت، ولكنها تظل متوافقةً مع المعيار الأصلي. هذا يجعل الأمر يستحق قول بضع كلمات حول سبب نجاح الإيثرنت، حتى نتمكن من فهم الخصائص التي يجب أن نحاكيها أية تقنية تحاول استخدامها بدلًا من شبكة إيثرنت. أولًا من السهل للغاية إدارة وصيانة شبكة إيثرنت: لا توجد جداول توجيه أو ضبط يجب تحديثها، ومن السهل إضافة مضيف جديد إلى الشبكة، فمن الصعب تخيل شبكة أبسط لإدارتها. ثانيًا إنها غير مكلفة: الكبل / الألياف رخيصة نسبيًا، والتكلفة الأخرى الوحيدة هي محوّل الشبكة على كل مضيف. أصبحت شبكة إيثرنت راسخة بعمق لهذه الأسباب، وإن أي نهج قائم على التبديل (switch) يطمح إلى استبدالها يتطلب استثمارًا إضافيًا في البنية التحتية كالمبدّلات (switches)، بالإضافة إلى تكلفة كل محوّل. نجحت الشبكات القائمة على التبديل المغايرة عن شبكة إيثرنت في النهاية في استبدال الإيثرنت متعدد الوصول، ولكن هذا استبدال أولي لأنه يمكن نشره بصورة تدريجية مع بعض المضيفين المتصلين عن طريق روابط من نقطة لنقطة بالمبدّلات، بينما بقي المضيفون الآخرون متصلين بالأسلاك الملتوية إلى المكررات أو الموزعات مع الحفاظ على بساطة إدارة الشبكة. ترجمة -وبتصرّف- للقسم Multi-Access Networks من فصل Direct Links من كتاب Computer Networks: A Systems Approach
-
تكون الإطارات تالفةً أحيانًا أثناء النقل كما ذُكر سابقًا، لذلك تُستخدَم شيفرة خطأ كشيفرة CRC لاكتشاف هذه الأخطاء. على الرغم من أنّ بعض شيفرات الأخطاء قويّة بما يكفي لتصحيح الأخطاء، إلا أنّ عدد البتات الإضافية عمليّا يكون أكبر من أن يعالِج نطاقَ أخطاء البتات وأخطاء الرشقات (burst) التي يمكن إدخالها إلى رابط (link) شبكة. ستكون بعض الأخطاء شديدة جدًا بحيث لا يمكن تصحيحها حتى عند استخدام شيفرات تصحيح الأخطاء (على الروابط اللاسلكية على سبيل المثال)، لذلك يجب إهمال بعض الإطارات الفاسدة. يجب أيضًا أن يستعيد بروتوكول مستوى الرابط، الذي يريد تسليم الإطارات بطريقةٍ موثوقة، بعضًا من هذه الإطارات المهمَلة أو المفقودة. تجدر الإشارة إلى أن الوثوقية هي وظيفة يمكن توفيرها على مستوى الرابط، ولكن تهمل العديد من تقنيات الروابط الحديثة هذه الوظيفة، وعلاوةً على ذلك يُوفَّر التسليم الموثوق في كثيرٍ من الأحيان في مستويات أعلى، بما في ذلك طبقة النقل (transport) وأحيانًا طبقة التطبيق (application)، ولكن المكان الذي يجب توفيره فيه بالضبط هو موضوعٌ للنقاش ويعتمد على العديد من العوامل. سنشرح أساسيات التسليم الموثوق هنا، نظرًا لأن المبادئ شائعة عبر الطبقات، ولكن يجب أن تدرك أننا لا نتحدث عن وظيفة طبقة الربط فقط. يُنجَز التسليم الموثوق باستخدام مزيجٍ من آليتين أساسيتين هما إشعارات الاستلام (acknowledgments) والمهلات الزمنية (timeouts). الإشعار (acknowledgment أو اختصارًا ACK) هو إطار تحكم (control frame) صغير يرسله البروتوكول إلى نظيره يخبره فيه أنه تلقى إطارًا سابقًا. يُقصد بإطار التحكم أنه ترويسة (header) بدون أي بيانات، وعلى الرغم من أن البروتوكول يمكن أن يحمِّل (piggyback) الإشعار على إطار البيانات، إلا أنه يرسَل في الاتجاه المعاكس فقط، حيث يشير "مستلم الإشعار" إلى أنه مرسل الإطار الأصلي الذي سُلِّم إطارُه بنجاح. إذا لم يتلقَّ المرسل إشعارًا بعد فترة زمنية معينة، فإنه يعيد إرسال الإطار الأصلي. يسمى هذا الإجراء المتمثل في الانتظار لفترة زمنية معينة مهلةً زمنية (timeout)، وتدعى الاستراتيجية العامة لاستخدام إشعارات الاستلام والمهلة الزمنية لتطبيق التسليم الموثوق أحيانًا طلب التكرار الآلي (automatic repeat request أو اختصارًا ARQ). يصف هذا القسم ثلاث خوارزميات ARQ مختلفة باستخدام لغة عامة، أي أننا لا نقدم معلومات مفصَّلة حول حقول ترويسة بروتوكولٍ معين. خوارزمية توقف وانتظر (Stop-and-Wait) أبسط مخطط لآلية ARQ هو خوارزمية توقف وانتظر. فكرة هذه الخوارزمية واضحة: ينتظر المرسل إشعارًا بعد إرسال إطارٍ واحد، قبل إرسال الإطار التالي، وإذا لم يصل الإشعار بعد فترة زمنية معينة، تنتهي مهلة المرسل ويعيد إرسال الإطار الأصلي. يوضح الشكل السابق الخطوط الزمنية لأربعة سيناريوهات مختلفة ناتجة عن الخوارزمية الأساسية، حيث يُمثَّل جانب الإرسال على اليسار وجانب الاستقبال على اليمين، ويتدفق الوقت من الأعلى إلى الأسفل. يوضح الشكل (أ) الحالة التي يُستلم بها إشعار ACK قبل انتهاء مدة المؤقت. يوضح الشكلان (ب) و (ج) الحالة التي فُقد فيها الإطار الأصلي والإشعار ACK على التوالي، ويوضح الشكل (د) الحالة التي تنتهي فيها المهلة في وقتٍ مبكرٍ جدًا. تذكر أن كلمة (فَقد) تعني أن الإطار تالف أثناء النقل، وأن هذا التلف اُكتشف بواسطة شيفرة خطأٍ على المستقبل الذي أهمل هذا الإطار لاحقًا. تُعد خطوط الرزم الزمنية الموضحة في هذا القسم أمثلةً لأداة مستخدمة بصورة متكررة في تدريس البروتوكولات وشرحها وتصميمها، فهي مفيدة لأنها توضح سلوك النظام الموزع بمرور الوقت، وهو أمر قد يكون من الصعب جدًا تحليله. يجب أن تكون مستعدًا لما هو غير متوقع عند تصميم بروتوكول مثل تعطل النظام أو فقد رسالة أو شيء توقعتَ حدوثه بسرعة ثم يتبين أنه يستغرق وقتًا طويلًا. يمكن أن تساعد هذه الأنواع من الرسوم البيانية في كثير من الأحيان في فهم الخطأ الذي قد يحدث في مثل هذه الحالات، وبالتالي مساعدة مصمم البروتوكول على الاستعداد لكل احتمال. افترض أن المرسل يرسل إطارًا ثم يرسل المستقبل إشعار الاستلام، لكن هذا الإشعار إما فُقد أو تأخر في الوصول، حيث وُضحت هذه الحالة في الخطين الزمنيين (ج) و (د) من الشكل السابق. تنتهي مهلة المرسل في كلتا الحالتين ويعيد إرسال الإطار الأصلي، ولكن سيعتقد المستقبل أنه الإطار التالي، لأنه استلم الإطار الأول بصورة صحيحة وأرسل إشعارًا بذلك، وبالتالي ستزداد احتمالية التسبب في إنشاء نسخٍ مكرَّرة من الإطار لتسليمها. لمعالجة هذه المشكلة، تتضمن ترويسة بروتوكول توقف وانتظر عادةً رقمًا تسلسليًا مؤلفًا من بتٍ واحد، أي يمكن أن يأخذ الرقم التسلسلي القيمتين 0 و 1، وتتضمن الترويسةُ أيضًا الأرقامَ التسلسلية المستخدمة لكل إطار بديل، مثل ما هو موضح في الشكل الآتي. وهكذا عندما يعيد المرسل إرسال الإطار 0، يمكن للمستقبل أن يحدد أنه يرى نسخة ثانية من الإطار 0 بدلًا من أن يعتقد أنه النسخة الأولى من الإطار 1، وبالتالي يمكنه إهماله (لا يزال على المستقبل أن يرسل إشعارًا باستلامه، في حالة ضياع أول إشعار ACK). يتمثل العيب الرئيسي في خوارزمية توقف وانتظر في أنها تسمح للمرسل بالحصول على إطار واحد فقط عن طريق الرابط في كل مرة، وقد يكون هذا أقل بكثير من سعة الرابط. افترض وجود رابط 1.5 ميجابت في الثانية مع وقت ذهاب وإياب (round-trip time أو اختصارًا RTT) يبلغ 45 ميلي ثانية على سبيل المثال. هذا الرابط لديه ناتج تأخير × حيز النطاق التراسلي (delay × bandwidth) يساوي 67.5 كيلو بت أو حوالي 8 كيلو بايت، ونظرًا لأن المرسل يمكنه إرسال إطار واحد فقط في كل RTT، وبافتراض أن حجم الإطار يبلغ 1 كيلو بايت، فهذا يعني أن الحد الأقصى لمعدل الإرسال يبلغ: Bits-Per-Frame / Time-Per-Frame = 1024 x 8 / 0.045 = 182 kbps أو يبلغ حوالي ثُمن سعة الرابط، وإذا كنت تريد استخدام الرابط بشكل كامل، فهذا يعني أن يتمكن المرسل من إرسال ما يصل إلى ثمانية إطارات قبل الاضطرار إلى انتظار الإشعار. النافذة المنزلقة (Sliding Window) افترض مرةً أخرى السيناريو الذي يحتوي فيه الرابط على تأخير × حيز النطاق التراسلي يبلغ 8 كيلو بايت، ويكون حجم الإطارات 1 كيلو بايت. يجب أن يكون المرسل جاهزًا لإرسال الإطار التاسع في نفس اللحظة تقريبًا التي يصل فيها الإشعار ACK للإطار الأول. تسمى الخوارزمية التي تسمح لنا بالقيام بذلك بخوارزمية النافذة المنزلقة (sliding window)، ويُعطى الخط الزمني التوضيحي في الشكل التالي: خوارزمية النافذة المنزلقة (The Sliding Window Algorithm) تعمل خوارزمية النافذة المنزلقة على النحو التالي: أولًا يسند المرسل رقمًا تسلسليًا، يُرمز له SeqNum، لكل إطار. افترض حاليًا تجاهل حقيقة أن SeqNum يُطبَّق بواسطة حقل ترويسة ذي حجمٍ محدود، وافترض بدلًا من ذلك أنه يمكن أن يزداد لا نهائيًا. يحتفظ المرسل بثلاثة متغيرات هي: حجم نافذة الإرسال (send window size)، المشار إليه SWS، الذي يعطي الحد الأعلى لعدد الإطارات المعلَّقة (غير المعترف بها) التي يمكن للمرسل إرسالها. المتغير الثاني هو LAR الذي يشير إلى الرقم التسلسلي لآخر إشعار مُستلَم (last acknowledgment received). المتغير الثالث LFS ويشير إلى الرقم التسلسلي لآخر إطارٍ مُرسَل (last frame sent). يحتفظ المرسل أيضًا بالثابت التالي: LFS - LAR <= SWS هذه الحالة موضحة في الشكل التالي: يحرّك المرسل المتغير LAR إلى اليمين عند وصول إشعارٍ بالاستلام، مما يسمح للمرسل بإرسال إطار آخر، ويربط المرسل مؤقِّتًا (timer) بكل إطارٍ يرسله، ويعيد إرسال الإطار في حالة انتهاء صلاحية المؤقت قبل استلام الإشعار ACK. لاحظ أن المرسل يجب أن يكون على استعداد لتخزين إطارات SWS مؤقتًا لأنه يجب أن يكون مستعدًا لإعادة إرسالها حتى يستلم إشعارًا بوصولها. يحافظ المستقبل على المتغيرات الثلاثة التالية: متغير حجم نافذة الاستلام (receive window size)، والمشار إليه RWS، الذي يعطي الحد الأعلى لعدد الإطارات المخالفة للترتيب التي يرغب المستقبل في قبولها. المتغير الثاني هو LAF ويشير إلى الرقم التسلسلي لأكبر إطار مقبول (largest acceptable frame). المتغير الثالث هو LFR ويشير إلى الرقم التسلسلي لآخر إطارٍ مُستقبَلٍ (last frame received). يحافظ المستقبل أيضًا على الثابت التالي: LAF - LFR <= RWS هذه الحالة موضحة في الشكل التالي: يتخذ المستقبل الإجراء التالي عند وصول إطار برقم تسلسلي SeqNum: إذا كان SeqNum <= LFR أو SeqNum > LAF، فسيكون الإطار خارج نافذة المستقبل وبالتالي يُهمَل. إذا كان LFR < SeqNum <= LAF، فسيكون الإطار داخل نافذة المستقبل ويُقبَل، ويحتاج المستقبل الآن أن يقرر ما إذا كان سيرسل إشعارًا ACK أم لا. افترض أن الرقم التسلسلي SeqNumToAck يشير إلى أكبر رقم تسلسلي لم يُرسَل إشعار استلامه بعد، بحيث تُستلَم جميع الإطارات ذات الأرقام التسلسلية الأقل من هذا الرقم التسلسلي أو تساويه. يرسل المستقبل إشعارًا باستلام الرقم التسلسلي SeqNumToAck، حتى إذا استلم رزمًا ذات أرقامٍ أعلى. يُقال أن هذه الإشعارات تراكمية (cumulative)، ثم يعيّن المستقبل LFR = SeqNumToAck ويضبط LAF = LFR + RWS. افترض أن LFR = 5 على سبيل المثال (أي أن آخر إشعارٍ ACK أرسله المستقبل كان للرقم التسلسلي 5) وأن RWS = 4، وهذا يعني أن LAF = 9. ستُخزَّن الإطارات 7 و 8 مؤقتًا في حالة وصولها لأنها ضمن نافذة المستقبل، ولكن لا يلزم إرسال إشعار نظرًا لأن الإطار 6 لم يصل بعد، حيث يقال أن الإطارات 7 و 8 قد وصلت مخالفةً للترتيب. يمكن للمستقبل إعادة إرسال إشعار ACK للإطار 5 عند وصول الإطارات 7 و 8، ولكن هل سيصل الإطار 6؟ ربما أصبح الوقت متأخرًا لأنه فُقد في المرة الأولى وكان لا بد من إعادة إرساله، أو ربما تأخر ببساطة. يرسل المستقبل إشعارًا بوصول الإطار 8، ويزيد LFR إلى 8، ويضبط LAF على 12، في حين أنه من غير المحتمل أن تتأخر الرزمة أو تصل مخالفةً للترتيب على رابط نقطةٍ لنقطة. تُستخدم هذه الخوارزمية ذاتها في الاتصالات متعددة القفزات، حيث يكون مثل هذا التأخير ممكنًا. إذا فُقد الإطار 6 بالفعل، فستنتهي مهلة الانتظار (timeout) عند المرسل، مما يؤدي إلى إعادة إرسال الإطار 6. لاحظ أنة تقل كمية البيانات المُرسَلة عند انتهاء المهلة، نظرًا لأن المرسل غير قادر على زيادة نافذته حتى يُرسَل إشعارٌ بوصول الإطار 6، وهذا يعني أن هذا المخطط لم يعد يحافظ على الأنبوب ممتلئًا عند حدوث فقدٍ لرزمة، وكلما طالت مدة ملاحظة حدوث فقد للرزمة، زادت خطورة هذه المشكلة. لاحظ أنه في هذا المثال كان من الممكن أن يرسل المستقبل إشعارًا سلبيًا (negative acknowledgment أو اختصارًا NAK) للإطار 6 بمجرد وصول الإطار 7، ولكن هذا غير ضروري لأن آلية مهلة المرسل الزمنية كافيةٌ لاكتشاف هذه الحالة، حيث يضيف إرسال إشعارات NAK تعقيدًا إضافيًا للمستقبل. يُسمَح أيضًا إرسال إشعارات إضافية للإطار 5 عند وصول الإطارات 7 و 8، ويمكن للمرسل في بعض الحالات استخدام إشعار ACK مُكرَّر كدليلٍ على فقد إطار. يساعد كلا الأسلوبين على تحسين الأداء من خلال السماح بالكشف المبكر عن فقدان الرزم، وهناك اختلاف آخر في هذا المخطط وهو استخدام إشعارات انتقائية (selective acknowledgments)، أي أن المستقبل يمكنه إرسال إشعارات بوصول تلك الإطارات التي استلمها بدلًا من مجرد استلام أعلى إطار مرقّمٍ بالترتيب، لذلك يمكن للمستقبل أن يرسل إشعارات باستلام الإطارات 7 و 8 في المثال أعلاه. يسهّل تقديم المزيد من المعلومات إلى المرسل عليه الحفاظ على الأنبوب ممتلئًا ولكنه يضيف تعقيدًا للتطبيق. يُحدَّد حجم نافذة الإرسال وفقًا لعدد الإطارات التي نريد أن تكون معلّقة على الرابط في وقت معين، ومن السهل حساب SWS للتأخير × حيز النطاق التراسلي، ويمكن للمستقبل من ناحية أخرى ضبط RWS بالقيمة التي يريد. هناك إعدادان شائعان هما RWS = 1 الذي يعني أن المستقبل لن يخزن مؤقتًا أي إطارات تصل مخالفة للترتيب، و RWS = SWS الذي يعني أن المستقبل يمكنه تخزين أي من الإطارات التي يرسلها المرسل مؤقتًا. ليس من المنطقي تعيين RWS > SWS نظرًا لأنه من المستحيل وصول إطارات أكثر من SWS مخالفة للترتيب. الأرقام التسلسلية المحدودة والنافذة المنزلقة (Finite Sequence Numbers and Sliding Window) بالعودة إلى التبسيط الذي أُدخل في الخوارزمية وهو الافتراض أن الأرقام التسلسلية يمكن أن تزداد كثيرًا بصورة لا نهائية، ولكن يُحدَّد، من الناحية العملية بالطبع، رقم الإطار التسلسلي في حقل ترويسة بحجم محدد. يعني الحقل 3 بت على سبيل المثال أن هناك ثمانية أرقام تسلسلية محتملة، 0..7، وهذا يجعل من الضروري إعادة استخدام الأرقام التسلسلية أو، بطريقة أخرى، التفاف الأرقام التسلسلية (wrap around)، فيؤدي ذلك إلى مشكلة القدرة على التمييز بين التجسيدات المختلفة لنفس الأرقام التسلسلية، مما يعني أن عدد الأرقام التسلسلية الممكنة يجب أن يكون أكبر من عدد الإطارات المعلّقة المسموح بها. سمحت خوارزمية توقف وانتظر على سبيل المثال بإطار واحد في كل مرة وله رقمان تسلسليان متميزان. افترض أن لديك رقمًا واحدًا في فضاء الأرقام التسلسلية أكثر من عدد الإطارات التي يحتمل أن تكون مميزة، وهذا يعني أن SWS <= MaxSeqNum - 1، حيث MaxSeqNum هو عدد الأرقام التسلسلية المتاحة، فهل هذا كافٍ؟ يعتمد الجواب على RWS، فإذا كانت RWS = 1، فإن MaxSeqNum > = SWS + 1 كافٍ، وإذا كانت RWS تساوي RWS، فإن وجود MaxSeqNum أكبر من حجم نافذة الإرسال ليس جيدًا بما يكفي. لفهم ذلك، افترض الحالة التي تكون فيها الأرقام التسلسلية الثمانية من 0 إلى 7، و SWS = RWS = 7، وافترض أن المرسل يرسل الإطارات 0..6، ثم تُستلم بنجاح، ولكن تُفقد إشعاراتها. يتوقع المستقبل الآن الإطارات 7 و 0..5، ولكن تنتهي مهلة المرسل ويرسل الإطارات 0..6، وبالتالي يتوقع المستقبل لسوء الحظ التجسيد الثاني للإطارات 0..5 لكنه يحصل على التجسيد الأول لهذه الإطارات، وهذه هي بالضبط الحالة التي يجب تجنبها. اتضح أن حجم نافذة الإرسال لا يمكن أن يكون أكبر من نصف عدد الأرقام التسلسلية المتاحة عندما تكون RWS = SWS، أو تُحدَّد بدقة أكبر كما يلي: SWS < (MaxSeqNum + 1)/ 2 وهذا يعني أن بروتوكول النافذة المنزلقة يتناوب بين نصفي فضاء الأرقام التسلسلية، تمامًا كما تبدّل خوارزمية توقف وانتظر بين الرقمين التسلسليين 0 و 1، والفرق الوحيد هو أنه ينزلق باستمرار بين النصفين بدلًا من التناوب بينهما. ولكن لاحظ أن هذه القاعدة خاصة بالحالة RWS = SWS. سنترك لك تمرين تحديد القاعدة الأعم التي تعمل مع قيم RWS و SWS العشوائية. لاحظ أيضًا أن العلاقة بين حجم النافذة وفضاء الأرقام التسلسلية تعتمد على افتراضٍ واضح جدًا بحيث يسهل التغاضي عنه وهو أن الإطارات لا يُعاد ترتيبها أثناء النقل. لا يمكن أن يحدث هذا على الروابط المباشرة نقطة لنقطة لأنه لا توجد طريقة تمكّن إطارًا ما من تجاوز إطارٍ آخر أثناء الإرسال، ولكنك سترى خوارزمية النافذة المنزلقة المستخدمة في بيئات مختلفة، وستحتاج إلى وضع قاعدة أخرى. تطبيق النافذة المنزلقة (Implementation of Sliding Window) توضح الشيفرة الآتية كيف يمكن تطبيق جانبي الإرسال والاستقبال لخوارزمية النافذة المنزلقة، حيث أن هذه الشيفرة مأخوذة من بروتوكول عمل يسمى بروتوكول النافذة المنزلقة (Sliding Window Protocol أو اختصارًا SWP). يُشار إلى البروتوكول الموجود فوق بروتوكول SWP على أنه بروتوكول عالي المستوى (high-level protocol ويُختصر إلى HLP)، ويشار إلى البروتوكول الموجود أسفل بروتوكول SWP على أنه بروتوكول مستوى الرابط (link-level protocol أو اختصارًا LLP). نبدأ بتعريف زوجٍ من بنيات البيانات، حيث أولًا ترويسة الإطار بسيطة للغاية، فهي تحتوي على رقم تسلسلي (SeqNum) ورقم إشعار (AckNum)، وتحتوي أيضًا على حقل الرايات Flags الذي يحدد إذا كان الإطار عبارة عن إشعار ACK أو أنه يحمل بيانات. typedef u_char SwpSeqno; typedef struct { SwpSeqno SeqNum; /* رقم الإطار التسلسلي */ SwpSeqno AckNum; /* إشعار وصول الإطار المُستلَم */ u_char Flags; /*(flags) ما يصل إلى 8 بتات من الرايات */ } SwpHdr; تحتوي حالة خوارزمية النافذة المنزلقة على البنية التالية: تتضمن هذه الحالة من جانب إرسال البروتوكول على المتغيرين LAR و LFS، كما هو موضح سابقًا، بالإضافة إلى طابور يحتوي على الإطارات التي أُرسلت ولكن لم تُرسَل إشعارات وصولها بعد (sendQ). تتضمن حالة الإرسال أيضًا متغير تقييد وصول خاصٍ بالعد (counting semaphore) يسمى sendWindowNotFull. يُعد متغير تقييد الوصول أداة مزامنة أولية تدعم عمليات semWait و semSignal. يزيد كل استدعاء للعملية semSignal متغيرَ تقييد الوصول بمقدار 1، وينقص كل استدعاءٍ للعملية semWait المتغير s بمقدار 1، ويجب أن يؤدي توقف عملية الاستدعاء أو تعليقها إلى تقليل قيمة متغير تقييد الوصول إلى أقل من 0، وسيُسمح للعملية التي توقفت أثناء استدعائها باستئناف العملية semWait بمجرد إجراء عمليات semSignal كافيةٍ لرفع قيمة متغير تقييد الوصول إلى أعلى من 0. تتضمن هذه الحالة من جانب استلام البروتوكول على المتغير NFE، وهو الإطار التالي المتوقع (next frame expected)، وهو الإطار الذي يحتوي على رقم تسلسلي واحد أكثر من آخر إطار مُستلَم (LFR). يوجد أيضًا طابور يحتوي على الإطارات المستلَمة المخالفة للترتيب (recvQ)، وتُحدَّد أخيرًا أحجام نافذة المرسل والمستقبل المنزلقة بواسطة الثوابت SWS و RWS على التوالي: typedef struct { /* :حالة جانب المرسل */ SwpSeqno LAR; /* الرقم التسلسلي لآخر إشعار مستلَم */ SwpSeqno LFS; /* آخر إطار مُرسَل */ Semaphore sendWindowNotFull; SwpHdr hdr; /* ترويسة مُهيَّأة مسبقًا */ struct sendQ_slot { Event timeout; /* الحدث المرتبط بمهلة الإرسال الزمنية */ Msg msg; } sendQ[SWS]; /* :حالة جانب المستقبل */ SwpSeqno NFE; /* الرقم التسلسلي للإطار التالي المتوقَّع */ struct recvQ_slot { int received; /* هل الرسالة صالحة؟ */ Msg msg; } recvQ[RWS]; } SwpState; يُطبَّق جانب الإرسال من بروتوكول SWP بواسطة الإجرائية sendSWP البسيطة نوعًا ما، حيث أولًا تتسبب العملية semWait في أن تحظر هذه الإجرائية الوصول إلى متغير تقييد الوصول إلى أن يُسمح بإرسال إطار آخر، حيث تضبط الإجرائيةُ sendSWP الرقمَ التسلسلي في ترويسة الإطار بمجرد السماح بالمتابعة، وتحفظ نسخةً من الإطار في طابور الإرسال (sendQ)، وتجدول حدث انتهاء المهلة لمعالجة الحالة التي لا يُرسَل فيها إشعار وصول الإطار، وترسل الإطار إلى بروتوكول المستوى الأدنى التالي الذي نشير إليه بـ LINK. أحد التفاصيل الجديرة بالملاحظة هو استدعاء الدالة store_swp_hdr قبل استدعاء الدالة msgAddHdr، حيث تترجم هذه الشيفرة بنية لغة C التي تحتفظ بترويسة SWP (state-> hdr) كسلسلة بايتات يمكن ربطها بأمان بمقدمة الرسالة (hbuf). يجب أن تترجم هذه الإجرائية كل حقل عدد صحيح في الترويسة إلى ترتيب بايت شبكة وإزالة أي حشو أضافه المصرِّف (compiler) إلى بنية C. مسألة ترتيب البايتات هي مسألة غير بسيطة، ولكن يكفي افتراض أن هذه الإجرائية في الوقت الحالي تضع البت الأعلى أهمية من عددٍ صحيح متعدد الكلمات (multiword) في البايت ذي العنوان الأعلى. جزء آخر من التعقيد في هذه الشيفرة هو استخدام العملية semWait ومتغير تقييد الوصول sendWindowNotFull. يُهيَّأ المتغير sendWindowNotFull بحجم نافذة المرسل المنزلقة SWS (لا تُعرَض هذه التهيئة)، ثم تقلل العملية semWait هذا العدد في كل مرة يرسل فيها المرسل إطارًا وتوقِف المرسل إذا انتقل العدد إلى 0. تزيد العمليةُ semSignal التي تُستدعى ضمن الإجرائية deliverySWP هذا العددَ في كل مرة يُستلَم فيها إشعار ACK، وبالتالي يُستأنف أي مرسلٍ منتظرٍ. static int sendSWP(SwpState *state, Msg *frame) { struct sendQ_slot *slot; hbuf[HLEN]; /* انتظر فتحَ نافذة المرسل */ semWait(&state->sendWindowNotFull); state->hdr.SeqNum = ++state->LFS; slot = &state->sendQ[state->hdr.SeqNum % SWS]; store_swp_hdr(state->hdr, hbuf); msgAddHdr(frame, hbuf, HLEN); msgSaveCopy(&slot->msg, frame); slot->timeout = evSchedule(swpTimeout, slot, SWP_SEND_TIMEOUT); return send(LINK, frame); } يجب إصلاح بعض التناقض قبل المتابعة إلى جانب الاستلام، حيث قلنا أن البروتوكول عالي المستوى يستدعي خدمات بروتوكول مستوٍ منخفض عن طريق استدعاء العملية send، لذلك نتوقع أن يستدعي البروتوكول الذي يريد إرسال رسالة عبر SWP الدالة '(send(SWP, packet، ولكن يُطلق على الإجرائية التي تطبّق عملية إرسال SWP اسمsendSWP، وأول وسطائها هو متغير الحالة (SwpState)، حيث يوفّر نظام التشغيل شيفرةً لاصقة (glue code) تترجم استدعاءsendالعام إلى استدعاء برتوكولٍ خاصsendSWP. تربط الشيفرة اللاصقة الوسيطَ الأول من العمليةsend(متغير البروتوكول السحريSWP) مع كلٍ من الدالة المؤشرة إلى الإجرائيةsendSWP` والمؤشر إلى حالة البروتوكول التي يحتاجها SWP للقيام بعمله. السبب في أن البروتوكول عالي المستوى يستدعي بطريقة غير مباشرة الدالةََ الخاصة بالبروتوكول من خلال استدعاء الدالة العامة هو أننا نريد تحديد مقدار المعلومات التي شفّرها البروتوكول عالي المستوى حول البروتوكول منخفض المستوى، وهذا يجعل تغيير ضبط رسم البروتوكول البياني في وقت ما في المستقبل أمرًا سهلًا. ننتقل الآن إلى تطبيق بروتوكول SWP المحدّد للعملية deliver الموجود ضمن الإجرائية deliverSWP، حيث تعالج هذه الإجرائية نوعين مختلفين من الرسائل الواردة: إشعارات الإطارات المرسلة سابقًا من هذه العقدة وإطارات البيانات التي تصل إلى هذه العقدة، أي نٍصفُ إشعارات هذه الإجرائية هو المقابل لجانب المرسل من الخوارزمية الواردة في الإجرائية sendSWP. يُتخذ قرار بشأن ما إذا كانت الرسالة الواردة عبارة عن إشعار ACK أو إطار بيانات عن طريق التحقق من الحقل Flags في الترويسة. لاحظ أن هذا التطبيق لا يدعم حَملَ الإشعارات على إطارات البيانات. تبحث الإجرائية deliverySWP ببساطة عن الفتحة الموجودة في طابور الإرسال (sendQ) التي تتوافق مع الإشعار عندما يكون الإطار الوارد عبارة عن إشعار وتلغي حدث المهلة، وتحرر الإطار المحفوظ في تلك الفتحة. يُطبَّق هذا العمل في الواقع ضمن حلقة لأن الإشعار قد يكون تراكميًا. الشيء الآخر الوحيد الذي يجب ملاحظته حول هذه الحالة هو استدعاء الإجرائية الفرعية swpInWindow، حيث تضمن هذه الإجرائية الفرعية، الواردة أدناه، أن يكون رقم الإطار التسلسلي الذي يُرسَل إشعارٌ باستلامه ضمن نطاق مجموعة الإشعارات التي يتوقع المرسل استلامها حاليًا. تستدعي الإجرائية deliverSWP أولًا الإجرائيتين msgStripHdr و load_swp_hdr عندما يحتوي الإطار الوارد على بياناتٍ لاستخراج الترويسة من الإطار، حيث تُعد الإجرائية load_swp_hdr هي المقابل للإجرائية store_swp_hdr التي نوقشت سابقًا، فهي تترجم سلسلة بايتات إلى بنية بيانات C التي تحتوي على ترويسة SW، ثم تستدعي الإجرائيةُ DeliverySWP الإجرائيةَ swpInWindow للتأكد من أن رقم الإطار التسلسلي يقع ضمن نطاق الأرقام التسلسلية المتوقعة. إذا كان الأمر كذلك، فستدور الإجرائية عبر مجموعة الإطارات المتعاقبة المستلَمة وتمررها إلى بروتوكول المستوى الأعلى من خلال استدعاء الإجرائية deliveryHLP. كما ترسل أيضًا إشعارًا تراكميًا إلى المرسل، ولكنها تفعل ذلك عن طريق تكرار طابور الاستلام (ولا تستخدم متغير الإجرائية deliveryHLP). static int deliverSWP(SwpState state, Msg *frame) { SwpHdr hdr; char *hbuf; hbuf = msgStripHdr(frame, HLEN); load_swp_hdr(&hdr, hbuf) if (hdr->Flags & FLAG_ACK_VALID) { /* استلمتَ إشعارًا، إذًا نفّذ جانب المرسل*/ if (swpInWindow(hdr.AckNum, state->LAR + 1, state->LFS)) { do { struct sendQ_slot *slot; slot = &state->sendQ[++state->LAR % SWS]; evCancel(slot->timeout); msgDestroy(&slot->msg); semSignal(&state->sendWindowNotFull); } while (state->LAR != hdr.AckNum); } } if (hdr.Flags & FLAG_HAS_DATA) { struct recvQ_slot *slot; /* استلمتَ رزمة بيانات، إذًا نفّذ جانب المستقبل */ slot = &state->recvQ[hdr.SeqNum % RWS]; if (!swpInWindow(hdr.SeqNum, state->NFE, state->NFE + RWS - 1)) { /* أهمل الرسالة */ return SUCCESS; } msgSaveCopy(&slot->msg, frame); slot->received = TRUE; if (hdr.SeqNum == state->NFE) { Msg m; while (slot->received) { deliver(HLP, &slot->msg); msgDestroy(&slot->msg); slot->received = FALSE; slot = &state->recvQ[++state->NFE % RWS]; } /* :أرسل إشعارًا */ prepare_ack(&m, state->NFE - 1); send(LINK, &m); msgDestroy(&m); } } return SUCCESS; } الإجرائية swpInWindow هي إجرائية فرعية بسيطة تتحقق فيما إذا كان الرقم التسلسلي يقع بين حدي الرقم التسلسلي الأدنى والأعلى كما يلي: static bool swpInWindow(SwpSeqno seqno, SwpSeqno min, SwpSeqno max) { SwpSeqno pos, maxpos; pos = seqno - min; /* [0..MAX) يجب أن يكون ضمن المجال pos المتغير */ maxpos = max - min + 1; /* [0..MAX] يجب أن يكون ضمن المجال maxpos المتغير */ return pos < maxpos; } ترتيب الإطارات والتحكم في التدفق (Frame Order and Flow Control) قد يكون بروتوكول النافذة المنزلقة هو أفضل خوارزمية معروفة في شبكات الحاسوب، ولكن ما يربك بسهولة حول هذه الخوارزمية هو أنه يمكن استخدامها لإنجاز ثلاثة أدوار مختلفة. الدور الأول هو توصيل الإطارات بصورة موثوقة عبر رابطٍ غير موثوق به، أي يمكن استخدام الخوارزمية لتوصيل الرسائل بطريقة موثوقة عبر شبكة غير موثوقة، وهذه هي الوظيفة الأساسية للخوارزمية. الدور الثاني الذي يمكن أن تؤديه خوارزمية النافذة المنزلقة هو الحفاظ على الترتيب الذي تُرسَل الإطارات به، حيث من السهل القيام بذلك عند المستقبل، نظرًا لأن كل إطار يحتوي على رقم تسلسلي، وبالتالي يتأكد المستقبل فقط من أنه لا يمرر إطارًا إلى بروتوكول المستوى الأعلى التالي حتى يمرر بالفعل جميع الإطارات ذات الأرقام التسلسلية الأصغر، وهذا يعني أن مخازن المستقبل المؤقتة لا تمرر إطارات مخالفة للترتيب. يحافظ إصدار خوارزمية النافذة المنزلقة الموصوف في هذا القسم على ترتيب الإطارات، على الرغم من أننا يمكن أن نتخيل اختلافًا عندما يمرر المستقبل الإطارات إلى البروتوكول التالي دون انتظار تسليم جميع الإطارات السابقة. السؤال الذي يجب طرحه الآن هو ما إذا كنا نحتاج حقًا إلى بروتوكول النافذة المنزلقة للحفاظ على ترتيب الإطارات على مستوى الرابط، أو يجب بدلًا من ذلك تطبيق هذه الوظيفة بواسطة بروتوكول أعلى في المكدس. يتمثل الدور الثالث الذي تلعبه خوارزمية النافذة المنزلقة أحيانًا في دعم التحكم في التدفق (flow control)، وهي آلية للتغذية الراجعة التي يستطيع المستقبل بواسطتها خنق المرسل، حيث تُستخدم مثل هذه الآلية لمنع المرسل من الإفراط في تشغيل المستقبل، أي عدم إرسال بيانات أكثر مما يستطيع المستقبل معالجته. يتحقق ذلك عادةً عن طريق زيادة بروتوكول النافذة المنزلقة بحيث لا يرسل المستقبل إشعارًا باستلام الإطارات التي استقبلها فحسب، بل يُعلم المرسل أيضًا بعدد الإطارات التي يمكنه استقبالها. يتوافق عدد الإطارات التي يمكن للمستقبل استقبالها مع مقدار مساحة المخزَن المؤقت الحرة الموجودة. تحتاج، كما في حالة التسليم المرتّب، إلى التأكد من أن التحكم في التدفق ضروري على مستوى الرابط قبل دمجه في بروتوكول النافذة المنزلقة. القنوات المنطقية المتزامنة (Concurrent Logical Channels) يوفّر بروتوكول ربط البيانات المستخدم في شبكات أربانت ARPANET الأصلية بديلًا مثيرًا للاهتمام لبروتوكول النافذة المنزلقة، حيث يمكنه الحفاظ على الأنبوب ممتلئًا مع الاستمرار في استخدام خوارزمية توقف وانتظر البسيطة. إحدى النتائج المهمة لهذا الأسلوب هي أن الإطارات المرسلَة عبر رابطٍ معين لا يُحتفَظ بها بأي ترتيب محدد، ولا يشير البروتوكول أيضًا إلى أي شيء يتعلق بالتحكم في التدفق. الفكرة الأساسية لبروتوكول ARPANET، والتي يشار إليها بالقنوات المنطقية المتزامنة، هي دمج عدة قنوات منطقية على رابط من نقطة لنقطة واحدٍ وتشغيل خوارزمية توقف وانتظر على كل من هذه القنوات المنطقية. لا توجد علاقة محفوظة بين الإطارات المرسلة على أي من القنوات المنطقية، ولكن نظرًا لأن إطارًا مختلفًا يمكن أن يكون موجودًا على كل من القنوات المنطقية المتعددة، فيمكن للمرسل الاحتفاظ بالرابط ممتلئًا، وبتعبيرٍ أدق يحتفظ المرسل بثلاثة بتات من أجل حالة كل قناة: بت بولياني يوضح ما إذا كانت القناة مشغولة حاليًا، ورقم تسلسلي مؤلف من 1 بت لاستخدامه في المرة التالية التي يُرسَل فيها إطار على هذه القناة المنطقية، والرقم التسلسلي التالي الذي يمكن توقعه في إطار يصل إلى هذه القناة. تستخدم العقدةُ القناة الأدنى خمولًا عندما يكون لديها إطارٌ لإرساله، وبخلاف ذلك تتصرّف تمامًا مثل خوارزمية توقف وانتظر. تدعم شبكات ARPANET ثماني قنوات منطقية عبر كل رابط أرضي و 16 قناة عبر كل رابط فضائي. تضمنت ترويسة كل إطار في حالة الرابط الأرضي رقم قناة مؤلف من 3 بتات ورقمًا تسلسليًا مؤلفًا من بت واحد، ليصبح المجموع 4 بتات، وهذا هو بالضبط عدد البتات الذي يتطلبه بروتوكول النافذة المنزلقة لدعم ما يصل إلى 8 إطارات على الرابط عندما تكون RWS = SWS. ترجمة -وبتصرّف- للقسم Reliable Transmission من فصل Direct Links من كتاب Computer Networks: A Systems Approach
-
تُدخَل أحيانًا أخطاء البت في الإطارات، ويحدث هذا على سبيل المثال بسبب التداخل الكهربائي (electrical interference) أو التّشويش الحراري (thermal noise)، وعلى الرّغم من ندرة الأخطاء خاصًّة على الروابط الضوئيّة، إلا أنّ هناك حاجة إلى بعض الآليات لاكتشاف هذه الأخطاء، وذلك من أجل اتخاذ الإجراءات الصحيحة، بينما يُترك المستخدم النهائي بخلاف ذلك يتساءل عن سبب ظهور خطأ صياغي (syntax error) فجأةً في برنامج مكتوب بلغة C يكون قد صُرِّف بنجاح منذ لحظة واحدة فقط، رغم أنّ كلّ ما حدث في غضون ذلك هو نسخه عبر نظام ملفّات الشبكة. هناك تاريخ طويل من تقنيّات التعامل مع أخطاء البت في أنظمة الحاسوب، حيث يعود تاريخه إلى الأربعينات على الأقل، وتُعَد شيفرات هامينغ (Hamming) وريد-سولومون (Reed-Solomon) مثالين بارزين طُوِّرا للاستخدام في قارئات البطاقات المُثقَّبة (punch card readers) عند تخزين البيانات على أقراص مغناطيسيّة (magnetic disks) وفي الذواكر الأساسيّة القديمة، حيث يشرح هذا القسم بعض تقنيّات اكتشاف الأخطاء الأكثر استخدامًا في الشبكات. يُعدّ اكتشاف الأخطاء جزءًا من المشكلة فقط، والجزء الآخر هو تصحيح الأخطاء بمجرد اكتشافها، ويمكن اتّباع طريقتين أساسيّتين عندما يكتشف مستلم الرسالة خطأً، والطريقة الأولى هي إبلاغ المرسل بأن الرسالة تالفة حتّى يتمكّن المرسل من إعادة إرسال نسخة من الرسالة، وبالتالي إذا كانت أخطاء البت ناذرة، فمن المحتمل أن تكون النسخة المعاد إرسالها خاليةً من الأخطاء؛ أمّا الطريقة الثانية، فتتمثّل في سماح بعض أنواع خوارزميّات اكتشاف الأخطاء للمستلم بإعادة بناء الرسالة الصحيحة حتّى بعد تلفها، حيث تعتمد مثل هذه الخوارزميات على شيفرات تصحيح الأخطاء (error-correcting codes) الموضّحة أدناه. وواحدة من أكثر التقنيّات شيوعًا لاكتشاف أخطاء الإرسال هي تقنيّة تُعرف باسم فحص التّكرار الدوري (cyclic redundancy check ويختصر إلى CRC)، والتي تُستخدم في جميع بروتوكولات مستوى الربط التي ستناقَش في هذا المقال تقريبًا، حيث سيوضّح هذا القسم خوارزميّة CRC الأساسيّة، ولكنّه سيشرح أوّلًا مخطّط المجموع الاختباري (checksum) الأبسط الذي تستخدمه العديد من بروتوكولات الإنترنت. الفكرة الأساسيّة وراء أيّ مخطّط اكتشاف أخطاء هي إضافة معلومات زائدة إلى إطار، بحيث يمكن استخدامها لتحديد فيما إذا كانت الأخطاء قد أُدخلت أم لا، ويمكنك تخيّل إرسال نسختين كاملتين من البيانات في أسوأ الأحوال، فإذا كانت النسختان متطابقتين في المستقبل، فمن المحتمل أن تكون كلتا النسختين صحيحتين، وإذا اختلفتا، فقد أُدخِل خطأٌ في إحدى النسختين (أو كلتيهما) وبالتالي يجب إهمالها، لكن هذا يُعدّ مخطّطًا سيّئًا إلى حدّ ما لاكتشاف الأخطاء وذلك لسببين، أوّلهما إرسال هذا المخطّط n بت زائدة (redundant) لرسالة بحجم n بت، وثانيهما عدم اكتشاف العديد من الأخطاء مثل أيّ خطأٍ يحدث لإتلاف مواضع البت نفسها في النسختين الأولى والثانية من الرسالة، ولكن هدف شيفرات اكتشاف الأخطاء هو توفير احتمال كبير لاكتشاف الأخطاء مع عدد قليل نسبيًّا من البتّات الزائدة (redundant bits)، ولحسن الحظ يمكن القيام بأفضل بكثير من هذا المخطط البسيط، حيث يمكن توفير قدرة قويّة جدًّا لاكتشاف الأخطاء مع إرسال k بتّ زائدة فقط لرسالة بحجم n بت، حيث k أصغر بكثير من n، ففي شبكة إيثرنت على سبيل المثال لا يتطلّب الإطار الذي يحمل ما يصل إلى 12000 بتًّا (1500 بايت) من البيانات سوى شيفرة CRC مؤلّفة من 32 بتًا، أو كما يُعبَّرعنها CRC-32، حيث ستلتقط مثل هذه الشيفرة الغالبيّة العظمى من الأخطاء كما سترى لاحقًا. يمكننا القول أنّ البتات الإضافية التي نرسلها زائدةٌ نظرًا لعدم إضافتها لمعلومات جديدة إلى الرسالة، بل تُشتَق مباشرةً من الرسالة الأصليّة باستخدام خوارزميّة معروفة جيّدًا، بحيث يعرف كلّ من المرسل والمستقبل بالضّبط ما هي هذه الخوارزميّة. ويطبّق المرسل الخوارزميّة على الرسالة لتوليد تلك البتات الزائدة، ثم ينقل الرسالة وتلك الأجزاء الإضافية القليلة. وإذا طبّق المستقبل نفس الخوارزميّة على الرسالة المستلمة، فيجب إنتاج نفس نتيجة المرسل (في حالة عدم وجود أخطاء)، حيث يوازن المستقبل تلك النّتيجة مع النّتيجة التي أرسلها المرسل إليه، فإذا تطابقت، يمكنه استنتاج (مع احتمال كبير) عدم حدوث إدخال أخطاءٍ في الرسالة أثناء الإرسال، وإذا لم تتطابق يمكن التأكّد من تلف الرسالة أو البتّات الزائدة، مع وجوب اتّخاذ الإجراء المناسب، أي إهمال الرسالة أو تصحيحها إذا كان ذلك ممكنًا. توجد ملاحظةٌ واحدة حول المصطلحات الخاصّة بهذه البتات الإضافيّة، حيث يشار إليها باسم شيفرات اكتشاف الأخطاء، وقد يطلق عليها في حالات محدّدة، عندما تعتمد الخوارزميّة على الجمع (addition) لإنشاء الشيفرة مثلًا، اسم المجموع الاختباري (checksum)، حيث سترى أنّ المجموع الاختباري للإنترنت قد سُمي بطريقة مناسبة، فهو فحص خطأ يستخدم خوارزميّة جمع، ولكن لسوء الحظ تُستخدَم غالبًا كلمة المجموع الاختباري بصورة غير دقيقة للإشارة إلى أي نوع من أنواع شيفرة اكتشاف الأخطاء بما في ذلك شيفرات CRC، وبالتالي قد يكون هذا محيّرًا، لذلك يمكنك استخدام المجموع الاختباري للتطبيق على الشيفرات التي تستخدم الجمع بالفعل، ويمكنك استخدام شيفرة اكتشاف الأخطاء للإشارة إلى صنف الشيفرات العامّة الموضّحة في هذا القسم. خوارزمية مجموع الإنترنت الاختباري (Internet Checksum Algorithm) تتمثل الطّريقة الأولى لاكتشاف الأخطاء في مجموع الإنترنت الاختباري، وعلى الرّغم من عدم استخدامه على مستوى الرابط، إلا أنّه يوفّر نفس نوع وظائف آليّة CRC. وتُعدّ الفكرة الكامنة وراء مجموع الإنترنت الاختباري بسيطةً للغاية، حيث تضاف كلّ الكلمات المرسَلة ثمّ ترسَل نتيجة هذا المجموع، والنتيجة هي المجموع الاختباري، حيث يجري المستقبل نفس العمليّات الحسابيّة على البيانات المستلَمة ويوازن النتيجة مع المجموع الاختباري المستلَم، وفي حالة تلف أي بيانات مرسلَة، بما في ذلك المجموع الاختباري نفسه، فلن تتطابق النتائج، لذلك يعلم المستقبل بحدوث خطأ. يمكنك تخيّل العديد من الاختلافات حول فكرة المجموع الاختباري الأساسيّة، ويعمل المخطط الذي تستخدمه بروتوكولات الإنترنت على النحو التالي: افترض أنّ البيانات التي سيطبّق عليها المجموع الاختباري هي سلسلة من الأعداد الصحيحة المؤلفة من 16 بتًا، ثم اجمعهم معًا باستخدام متمّم الواحد (ones’ complement) ذو 16 بت (الموضح أدناه)، ثم خذ متمّم الواحد للنتيجة، فهذا الرقم المؤلّف من 16 بتًا هو المجموع الاختباري، حيث يُمثَّل العدد الصحيح السالب -x باستخدام متمّم الواحد كمتمم للعدد x، أي يُقلَب كل بت من x، ويجب إضافة حِمل من البت الأكثر أهميّةً إلى النتيجة عند جمع الأعداد باستخدام مُتمّم الواحد. افترض على سبيل المثال جمع العددين -5 و -3 باستخدام مُتمّم الواحد على أعداد صحيحة مؤلّفة من 4 بتات: +5هي 0101 لذا -5 هي 1010، و +3 هي 0011 لذا -3 يساوي 1100. إذا جمعت العددين 1010، و1100، مع تجاهل الحمل، ستحصل على 0110. لكن بسبب حقيقة أنّ هذه العمليّة تسببت في حمل من البت الأكثر أهميّة باستخدام متمّم الواحد لذلك يجب زيادة النتيجة، قتصبح 0111، وهو تمثيل متمّم الواحد للعدد -8 الذي تحصل عليه من خلال قلب بتات العدد 1000. تعطي الشيفرة الآتية تطبيقًا مباشرًا لخوارزمية مجموع الإنترنت الاختباري، ويعطي الوسيط count طول المتغيّر buf المُقاس بطول 16 بت، حيث تفترض الشيفرة أنّ المتغيّر buf محشوٌّ أصفارًا إلى حد 16 بت: u_short cksum(u_short *buf, int count) { register u_long sum = 0; while (count--) { sum += *buf++; if (sum & 0xFFFF0000) { /* ظهر حِمل في البت الأعلى أهميةً، لذلك أضف واحدًا إلى المجموع */ sum &= 0xFFFF; sum++; } } return ~(sum & 0xFFFF); } تضمن الشيفرة السابقة استخدام العمليّة الحسابيّة لمتمّم الواحد بدلًا من المتمّم الثنائي المستخدم في معظم الأجهزة، ويمكنك ملاحظة استخدام عبارة if داخل حلقة while، وإذا وُجِد حِمل في البت الأعلى من 16 بت في المتغيّر sum الذي يُمثّل المجموع، فيجب زيادة المجموع كما في المثال المذكور سابقًا، وتحقق خوارزمية المجموع الاختباري نتائجًا جيّدةً عند استخدام عددٍ قليل من البتّات الزائدة، 16 بتًا فقط لأية رسالةٍ ذات أيّ طول، ولكنها لا تحقق نتائجًا جيدة للغاية بالنسبة لاكتشاف الأخطاء الأقوى، إذ لن يُكتشَف على سبيل المثال زوجٌ من الأخطاء أحاديّة البت، أحدهما يزيد كلمةً والآخر ينقص كلمةً أخرى بنفس المقدار، ويعود سبب استخدام مثل هذه الخوارزميّة رغم كون حمايتها ضعيفةً نسبيًّا ضدّ الأخطاء (مقارنةً بخوارزميّة CRC على سبيل المثال)، هو أنها خوارزميّة بسيطة، فهذه الخوارزميّة تُعدّ أسهل بكثير في التطبيق ضمن البرمجيّات، وقد أشارت التجربة إلى أنّ المجموع الاختباري (checksum) لهذا النموذج مناسب، ولكن أحد أسباب عدّه مناسبًا يعود لكون المجموع الاختباري بمثابة خطّ الدفاع الأخير في بروتوكول نقطة لنقطة، حيث تلتقط خوارزميّاتٍ أقوى لاكتشاف الأخطاء، مثل خوارزمية CRC، باكتشافها لغالبيّة الأخطاء على مستوى الروابط. فحص التكرار الدوري (Cyclic Redundancy Check أو اختصارًا CRC) يجب أن يكون واضحًا الآن أن الهدف الرئيسي في تصميم خوارزميات اكتشاف الأخطاء هو تكبير احتمالية اكتشاف الأخطاء إلى الحدّ الأقصى باستخدام عدد صغير فقط من البتّات الزائدة، حيث تُستخدم خوارزميّة فحص التكرار الدوري بعض الحسابات القويّة إلى حدّ ما لتحقيق هذا الهدف، وتوفّر خوارزميّة CRC ذات 32 بتًا على سبيل المثال حمايةً قويّةً ضدّ أخطاء البت الشائعة الموجودة في الرسائل التي يبلغ طولها آلاف البايتات. الأساس النظري لهذه الخوارزمية مُتجذّر في فرعٍ من فروع الرياضيات يسمّى الحقول المحدودة (finite fields). قد يبدو هذا صعبًا، ولكن يمكن فهم الأفكار الأساسيّة بسهولة، ابدأ بافتراض أن رسالةً مؤلّفةً من (n + 1) بت ممثّلةٌ بواسطة كثير حدود (polynomial) من الدّرجة n، أي كثير الحدود الذي حدّه الأعلى رتبةً هو xn. تُمثَّل الرسالة بواسطة كثير حدود باستخدام قيمة كلّ بت في الرسالة كمعاملٍ لكلّ حدٍ من كثير الحدود، بدءًا من البت الأعلى أهميّةً لتمثيل الحدّ الأعلى رتبةً، حيث تتكوّن رسالةٌ مؤلّفة من 8 بتات، وهي البتات 10011010 على سبيل المثال التي تتوافق مع كثير الحدود التالي: بالتالي يمكن التفكير في المرسل والمستقبل على أنهما يتبادلان كثيرات الحدود مع بعضهما البعض. يجب على المرسل والمستقبل الاتفاق على كثير الحدود القاسم (divisor polynomial) الذي يُرمز له C (x) لحساب CRC، حيث C (x) هو كثير حدود من الدرجة k. افترض أن C (x) = x3 + x2 + 1 على سبيل المثال، حيث k = 3 في هذه الحالة؛ أمّا الإجابة على السؤال (من أين أتى كثير الحدود C (x)؟) هي (ابحث عنه في السلسلة)، فإن اختياره له تأثير كبير على أنواع الأخطاء التي يمكن اكتشافها بطريقة موثوقة. هناك عدد قليل من كثيرات الحدود القاسمة التي تُعد اختيارات جيدة جدًا لبيئات مختلفة، ويُضاف ذلك الاختيار الدقيق كجزءٍ من تصميم البروتوكول، كما يستخدم معيار إيثرنت على سبيل المثال كثير الحدود المعروف ذو الدرجة 32. إذا أراد المرسل إرسال رسالة M (x) بطول n + 1 بت، فما يُرسَل بالفعل هو الرسالة التي طولها (n + 1) بت بالإضافة إلى k بت. وتدعى الرسالة المرسلة بالكامل بما في ذلك البتات الزائدة P (x). يجب جعل كثير الحدود الذي يمثّل P (x) قابلًا للقسمة تمامًا على C (x)، فإذا أُرسل P (x) عبر رابط دون حدوث أخطاء أثناء الإرسال، فيجب أن يكون المستقبل قادرًا على قسمة P (x)على C (x) تمامًا بلا باقٍ. ومن ناحية أخرى، إذا حدث خطأٌ ما في P (x) أثناء الإرسال، فلن يقبل كثير الحدود المستقبل القسمة تمامًا علىC (x)، وبالتالي سيحصل المستقبل على باقٍ غير صفريّ مما يعني حدوث خطأ. سيساعدك فهم ما يلي إذا كنت تعرف القليل عن حساب كثيرات الحدود، فهو يختلف قليلًا عن حساب الأعداد الصحيحة العاديّة، حيث ستتعامل هنا مع صنفٍ خاصّ من حساب كثيرات الحدود، فقد تكون المعامِلات (coefficients) واحدًا أو صفرًا فقط، وتُجرى العمليّات على المعاملات باستخدام نظام الحساب modulo 2، الذي يُشار إليه باسم نظام حساب modulo 2 لكثير الحدود. لكن نظرًا لأن هذه السلسلة عن الشبكات، وليست عن الرياضيات، فيجب التركيز فقط على الخصائص الرئيسيّة لهذا النوع من الحساب (والتي نطلب منك قبولها بناءً على الثّقة): يمكن تقسيم أيّ كثير حدود B (x) على كثير الحدود القاسم C (x) إذا كان B (x) من درجة أعلى من C (x). يمكن تقسيم أيّ كثير حدود B (x) مرةً واحدة بواسطة كثير الحدود القاسم C (x) إذا كان B (x) من نفس درجة C (x). ينتج باقي قسمة B (x) على C (x) من خلال إجراء عمليّة XOR على كلّ زوج من المعاملات المتطابقة. يمكن قسمة كثير الحدود x3 + 1 مثلًا على كثير الحدود x3 + x2 + 1 (لأنّ كليهما من الدرجة 3) والباقي هو 0×x3+1×x2+0×x1+0×x0=x2 (الذي نتج عن طريق إجراء عملية XOR على معاملات كل حد)، وبالتالي يمكن القول أنهّ يمكن قسمة 1001 على 1101 مع باقٍ هو 0100 (يجب أن تكون قادرًا الآن على رؤية أن الباقي هو مجرد تطبيق لعمليّة XOR ثنائيّة على الرسالتين)، وبعد أن عرفت القواعد الأساسيّة لتقسيم كثيرات الحدود، يمكنك إجراء قسمة طويلة، وهو أمر ضروري للتعامل مع الرسائل الأطول. تذكر أنك تريد إنشاء كثير حدود للإرسال مشتق من الرسالة الأصلية M (x)، فهل k بت أطول من M (x)، وهل M (x) قابلة للقسمة تمامًا على C (x)؟ يمكنك القيام بذلك بالطريقة التالية: اضرب M (x) بـ xk وهذا يعني إضافة k صفرًا في نهاية الرسالة. ادعُ هذه الرسالة الصفرية الموسعة T (x). اقسم T (x) على C (x) وجِد الباقي. اطرح الباقي من T (x). يجب أن يكون واضحًا أن ما تبقّى في هذه المرحلة هو رسالة قابلة للقسمة تمامًا على C (x)، وقد تلاحظ أيضًا أنّ الرسالة الناتجة تتكوّن من M (x) متبوعةً بالباقي الناتج عن الخطوة 2، فعند طرح الباقي (والذي لا يمكن أن يزيد طوله عن k بت)، فكأنّك أجريت عمليّة XOR فقط للباقي مع k صفرًا التي أُضيفت في الخطوة 1، وسيصبح هذا الجزء أوضح بمثال: افترِض أنّ الرسالة هي x7 + x4 + x3 + x1 أو 10011010. ابدأ بالضرب بـ x3، فكثير الحدود القاسم هو من الدرجة 3، وهذا يعطي 10011010000، ثمّ اقسم النتيجة السابقة على C (x) الذي يقابل 1101 في هذه الحالة. يوضح الشكل الآتي عمليّة قسمة كثير حدود طويلة، وبالنظر إلى قواعد حساب كثيرات الحدود الموصوفة سابقًا، تستمر عمليّة القسمة الطويلة كما لو كنت تقسم الأعداد الصحيحة، وهكذا ترى في الخطوة الأولى من المثال أنّ المقسوم عليه 1101 يُقسم عليه مرّةً واحدةً أوّل أربعة بتات من الرسالة (1001)، نظرًا لأنهما من نفس الدرجة، والباقي هو 100، أو (1101 XOR 1001). تتمثّل الخطوة التالية في إنزال رقم من كثير حدود الرسالة لتحصل على كثير حدود آخر بنفس درجة C (x)، وفي هذه الحالة هو 1001، ثمّ تحسب الباقي مرّةً أخرى وهو (100) وتستمر حتّى اكتمال الحساب. لاحظ أنّ نتيجة القسمة الطويلة (long division)، التي تظهر في الجزء العلويّ من الحساب، ليست ذات أهميّة كبيرة حقيقةً، وإنّما الباقي (remainder) في النهاية هو المهم. يمكنك الرّؤية في أسفل الشّكل الآتي أنّ باقي القسمة هو 101، لذلك ستعلم أنّ 10011010000 ناقص 101 سيكون قابلًا للقسمة تمامًا على C (x)، وهذا الذي سيُرسَل. عمليّة الطرح في حساب كثير الحدود هي عمليّة XOR منطقية، لذلك ما يُرسَل فعليًّا هو 10011010101، والذي هو عبارة عن الرسالة الأصلية فقط ملحوقًا بها باقي حساب القسمة الطويلة. يقسم المستقبل كثير الحدود المستلَم على C (x)، وإذا كانت النتيجة 0، فسيستنتج عدم وجود أخطاء؛ أمّا إذا كانت النتيجة غير صفريّة، فقد يكون من الضروري تجاهل الرسالة التالفة، ولكن قد يكون من الممكن تصحيح خطأٍ صغير مع وجود بعض الشيفرات (إذا أثر الخطأ على بت واحد فقط على سبيل المثال). يُطلق على الشيفرة التي تفعّل تصحيح الخطأ شيفرة تصحيح الخطأ (error-correcting code أو اختصارًا ECC). ولكن من أين أتى كثير الحدود C (x)؟ تكمن الفكرة في اختيار كثير الحدود هذا، بحيث لا يمكن تقسيم رسالة بها أخطاء عليه، فإذا كانت الرسالة المرسلة هي P (x)، فيمكن افتراض أنّ إدخال الأخطاء هو عبارة عن إضافة كثير حدود آخر هو E (x)، لذلك يرى المستقبل P (x) + E (x). الطريقة الوحيدة التي قد يمرّ بها الخطأ دون اكتشافه هي إذا كان من الممكن تقسيم الرّسالة المستلمة على C (x)، وبما أنك تعلم أن P (x) يمكن تقسيمها على C (x)، فقد يحدث هذا فقط إذا أمكن قسمة E (x) على C (x) أيضًا، ولكن الحل هو اختيار C (x) بحيث يكون غير محتملٍ جدًا بالنسبة لأنواع الأخطاء الشائعة، فمن بين أنواع الأخطاء الشائعة هو الخطأ أحادي البت (single-bit error)، والذي يمكن التعبير عنه بـ E (x) = xi عندما يؤثّر على موضع البت i إذا اخترت كثير الحدود ،C (x) بحيث يكون الحدّ الأوّل والأخير (أي الحدان xk و x0) غير صفريّين، فعندئذ يكون لديك بالفعل حدَّا كثير حدود لا يمكن تقسيمهما على حدٍّ واحد E (x)، وبالتالي يستطيع C (x) اكتشاف جميع الأخطاء أحادية البت. من الممكن إثبات أن الأنواع التالية من الأخطاء يمكن اكتشافها بواسطة كثير الحدود C (x): جميع الأخطاء أحادية البت (single-bit errors)، طالما أنّ الحدين xk وx0 لهما معاملات غير صفريّة. جميع أخطاء البت المضاعفة (double-bit errors)، طالما أنّ كثير الحدود C (x) له معامل بثلاثة حدود على الأقلّ. أيّ عدد فردي من الأخطاء (odd number of errors)، طالما يتضمّن كثير الحدود C (x) المعامل (x + 1). من الممكن استخدام الشيفرات التي لا تكتشف وجود الأخطاء فحسب، بل تتيح أيضًا تصحيح الأخطاء، ولن نتناول تفاصيل هذه الشيفرات هنا نظرًا لأنها تتطلّب رياضيات أعقد من تلك المطلوبة لفهم خوارزميّة CRC، ومع ذلك يجب معرفة مزايا تصحيح الأخطاء مقابل اكتشافها، فقد يبدو تصحيح (correction) الأخطاء للوهلة الأولى أفضل دائمًا من اكتشافها (detection)، لأنه يجب التخلّص من الرسالة عند اكتشاف الأخطاء، ثمّ طلب إرسال نسخةٍ أخرى، وبالتالي يُستهلك حيّز النطاق التراسلي وقد يؤدّي إلى التأخير أثناء انتظار إعادة الإرسال، لكن هناك جانب سلبي للتصحيح، إذ يتطلّب عمومًا عددًا أكبر من البتّات الزائدة لإرسال شيفرة تصحيح أخطاء قويّة (أي قادرة على التعامل مع نفس نطاق الأخطاء) مثل الشيفرة التي تكتشف أخطاءً فقط، وبالتالي بينما يتطلّب اكتشاف الخطأ إرسال مزيدٍ من البتّات عند حدوث أخطاء، فيتطلّب تصحيح الخطأ إرسال مزيدٍ من البتات طوال الوقت، لذلك يميل تصحيح الخطأ إلى أن يكون ذو فائدة أكبر عندما: (1) تكون الأخطاء محتملةً تمامًا، مثل البيئة اللّاسلكية على سبيل المثال، أو (2) تكلفة إعادة الإرسال مرتفعة للغاية، بسبب احتواء التأخير إعادة إرسال رزمة عبر رابط فضائي على سبيل المثال. يُشار أحيانًا إلى استخدام شيفرات تصحيح الأخطاء في الشبكات باسم تصحيح الأخطاء الأمامي (forward error correction أو اختصارًا FEC)، لأن تصحيح الأخطاء يُعالَج مسبقًا عن طريق إرسال معلومات إضافية، بدلًا من انتظار حدوث الأخطاء والتعامل معها لاحقًا عن طريق إعادة الإرسال، حيث يشيع استخدام آلية FEC في الشبكات اللاسلكية، مثل: 802.11. أي رشقة (burst) أخطاء (أي سلسلة بتات خاطئة متعاقبة) يكون طول الرشقة فيها أقل من k بت (معظم أخطاء الرشقات ذات طول أكبر من k يمكن أيضًا اكتشافها). تُستخدم ستّة إصدارات من كثير الحدود C (x)على نطاق واسع في بروتوكولات مستوى الرابط، حيث يستخدم الإيثرنت آليّة CRC-32 على سبيل المثال، والذي يُعرَّف على النحو التالي: لاحظ أخيرًا أنّ خوارزميّة CRC، رغم أنّها تبدو معقدة، ولكنها تُطبَّق بسهولة في العتاد باستخدام مسجّل إزاحة بحجم k بت وبوّابات XOR، فعدد البتات في مسجل الإزاحة يساوي درجة كثير الحدود المولد (k)، ويوضح الشّكل الآتي العتاد الذي سيستخدمه المولّد x3 + x2 + 1 من المثال السابق. حيث تُزاح الرسالة من اليسار بدءًا من البت الأكثر أهميّة وتنتهي بسلسلة k صفرًا المرفقة بالرسالة، فكما في مثال القسمة الطويلة إذا أُزيحت جميع البتّات وطُبِّق عليها XOR بطريقة مناسبة، فسيحتوي المسجّل على الباقي، وهذه هي خوارزميّة CRC (البت الأعلى أهميّةً على اليمين). يُحدَّد موضع بوابات XOR على النحو التالي: إذا سُميَّت البتات في مسجل الإزاحة من 0 إلى k − 1 من اليسار إلى اليمين، فضع بوّابة XOR أمام البت n إذا كان هناك حد xn في كثير الحدود المولّد، وبالتالي ترى بوابة XOR أمام الموضعين 0 و2 للمولد x3 + x2 + x0. ترجمة -وبتصرّف- للقسم Error Detection من فصل Direct Links من كتاب Computer Networks: A Systems Approach
-
التشفير (Encoding) تتمثّل الخطوة الأولى في تحويل العُقد (nodes) والرّوابط (links) إلى لبنات أساسيّة قابلة للاستخدام من خلال فهم كيفيّة توصيلها بطريقة يمكن بها نقل البتّات من عقدة إلى أخرى، حيث تنتشر الإشارات عبر الرّوابط الفيزيائية، وتُشفَّر البيانات الثنائية التي تريد العقدة المصدر إرسالها إلى إشارات تستطيع الرّوابط حملها، ثم يُفكّ تشفير الإشارة مرّةً أخرى إلى البيانات الثّنائية المقابلة في العقدة المستقبلّة، يمكن تجاهل تفاصيل التّعديل (modulation) وافتراض أنّك تعمل مع إشارتين منفصلتين: مرتفعة ومنخفضة، ولكن قد تتوافق هذه الإشارات من الناّحية العمليّة مع جهدين (voltages) مختلفين على رابط نحاسي، أو مستويين مختلفين من القدرة (power) على رابط ضوئيّ، أو سعتين (amplitudes) مختلفتين على الإرسال الراديوي، وتُنفَّذ معظم الوظائف الموجودة في هذا المقال بواسطة محوّل الشّبكة (network adaptor) الذي هو عبارة عن قطعة عتاد تصل بين عقدةٍ ورابط، ويحتوي محوّل الشّبكة على مكوّن إشارة (signalling component) يشفّر فعليًّا البتّات إلى إشارات عند عقدة الإرسال ويفكّ تشفير الإشارات إلى بتات في عقدة الاستقبال، حيث تنتقل الإشارات عبر رابط بين مكوّنَي الإشارة، وتتدفّق البتات بين محوّلات الشّبكة (network adaptors) كما هو موضّح في الشّكل التّالي: بالعودة إلى مشكلة تشفير البتات إلى إشارات، فالشيء الواضح الذي يجب فعله هو ربط القيمة 1 بالإشارة المرتفعة (high signal) والقيمة 0 بالإشارة المنخفضة (low signal)، وهذا هو بالضّبط ما يستخدمه مخطّط تشفير (encoding scheme) مشفَّرٌ بدرجة كافية يدعى عدم العودة إلى الصّفر (non-return to zero ويختصر إلى NRZ)، ويوضّح الشّكل التّالي على سبيل المثال بيانيًّا إشارة NRZ المشفَّرة (في أسفل الشّكل) التي تقابل إرسال سلسلة محدّدة من البتات (في أعلى الشّكل): تكمن مشكلة ترميز NRZ بوجود سلسلة واحدات متعاقبة والتي تعني بقاء الإشارة مرتفعة على الرّابط لمدّة طويلة من الزّمن، وبالمثل يشير وجود عدّة أصفار متعاقبة إلى بقاء الإشارة منخفضةً لمدّة طويلة. توجد مشكلتان أساسيّتان تسبّبهما سلاسل الواحدات أو الأصفار الطّويلة، حيث تؤدّي المشكلة الأولى إلى حالةٍ تدعى التجوّل الأساسي (baseline wander)، حيث يحتفظ المستقبِل على وجه التّحديد بمتوسّط الإشارة التي شاهدها حتى الآن، ثمّ يستخدم هذا المتوسّط للتّمييز بين الإشارات المنخفضة والمرتفعة، فيستنتج المستقبِل أنه قد رأى صفرًا للتّو عندما تكون الإشارة أقلّ بكثير من هذا المتوسط، وبالمثل تُفسَّر الإشارة التي تكون أعلى بكثير من المتوسّط على أنّها 1. تكمن المشكلة بالطبع في أن عددًا كبيرًا جدًا من الواحدات أو الأصفار المتعاقبة يتسبّب في تغيير هذا المتوسّط، مما يجعل اكتشاف تغيير كبير في الإشارة أمرًا صعبًا. تتمثل المشكلة الثّانية في أنّ التّحولات المتكرّرة من الأعلى إلى الأسفل والعكس ضروريّة لتفعيل استعادة السّاعة (clock recovery)، فتتمثل مشكلة استعادة الساّعة في أن كلًا من عمليات التّشفير وفكّ التّشفير مُساقة بواسطة ساعة، حيث يرسل المرسل بتًا ويستقبل المستقبل بتًا في كل دورة ساعة. يجب أن تكون ساعات المرسل والمستقبل متزامنة بدقّة من أجل استعادة المستقبل لنفس البتات التي يرسلها المرسل، فإذا كانت ساعة المستقبل أسرع أو أبطأ قليلًا من ساعة المرسل، فلن يستطيع فكّ تشفير الإشارة بصورة صحيحة. يمكنك تخيل إرسال السّاعة إلى المستقبل عبر سلك منفصل، ولكن يجب تجنب ذلك إذ سيزيد من تكلفة توصيل الكابلات مرّتين، لذلك بدلًا من ذلك يستخرج المستقبل السّاعة من الإشارة المستقبلة حيث تدعى هذه العمليّة بعمليّة استعادة السّاعة، حيث يعرف المستقبل أنّه على حدود دورة ساعة عندما تتغيّر الإشارة كما هو الحال عند الانتقال من القيمة 1 إلى القيمة 0 أو من القيمة 0 إلى القيمة 1، وبالتالي يستطيع المستقبل إعادة مزامنة نفسه، ومع ذلك يؤدّي مرور فترة طويلة من الزّمن دون حدوث مثل هذا الانتقال إلى انجراف السّاعة (clock drift)، وبالتالي تعتمد استعادة السّاعة على وجود الكثير من الانتقالات في الإشارة بغضّ النّظر عن البيانات التي تُرسَل. تجعل إحدى الطّرق التي تعالج هذه المشكلة المرسل ينتقل من الإشارة الحاليّة من أجل تشفير القيمة ،1 ويبقى عند الإشارة الحاليّة من أجل تشفير القيمة 0، وتدعى هذه الطّريقة عدم العودة إلى الصفر المعكوس (non-return to zero inverted ويُختصر إلى NRZI)، حيث تحلّ هذه الطّريقة مشكلة الواحدات المتعاقبة، ولكن من الواضح أنّها لا تفعل شيئًا بالنسبة للأصفار المتعاقبة، ويوضّح الشّكل التّالي ترميز NRZI. يوجد بديل يدعى ترميز مانشستر (Manchester encoding) الذي يقوم بأمرٍ أوضح لدمج السّاعة مع الإشارة خلال إرسال عمليّة "أو" المقصورة (exclusive OR أو اختصارًا XOR) لبيانات NRZ المشفَّرة والساعة. يمكنك التّفكير بالسّاعة المحليّة كإشارة داخليّة تتناوب من المنخفض إلى المرتفع، حيث يُعدّ الزّوجُ (منخفض / مرتفع) دورةَ ساعةٍ واحدة. ويوضح الشّكل الآتي ترميز مانشستر أيضًا، حيث يُرمَّز ترميز مانشستر الذي ينتج عنه القيمة 0 على أنّه انتقالٌ من منخفض إلى مرتفع ويُرمَّز ترميز مانشستر الذي ينتج عنه القيمة 1 على أنّه انتقال من مرتفع إلى منخفض، ويمكن استعادة السّاعة بفعاليّة في المستقبل لأن كلًّا من القيمتين 0 و1 يسبّبان الانتقال إلى الإشارة. ويوجد أيضًا ترميز مغاير عن ترميز مانشستر، يُسمى تفاضل مانشستر (Differential Manchester)، حيث تساوي القيمةُ 1 المُشفَّرة مع النّصف الأوّل من الإشارة النصفَ الأخير من إشارة البت السابق، وتعاكس القيمةُ 0 المُشفَّرة مع النصف الأوّل من الإشارة النصفَ الأخير من إشارة البت السابق. تكمن مشكلة مخطّط ترميز مانشستر في أنّه يضاعف معدّل انتقالات الإشارة على الرابط، مما يعني أنّه لدى المستقبل نصف الوقت لاكتشاف كلّ نبضة إشارة، ويُطلق على المعدّل الذي تتغيّر به الإشارة بمعدل الباود (baud rate) للرابط، ويكون معدّل البت في حالة ترميز مانشستر نصف معدّل الباود، لذلك يُعَد الترميز فعّالًا بنسبة 50% فقط. ضع في حساباتك أنه إذا كان المستقبل قادرًا على مواكبة معدّل الباود الأسرع الذي يتطلّبه ترميز مانشستر في الشّكل السابق، فيمكن لكلّ من ترميزَي NRZ وNRZI إرسال ضعف عدد البتّات في نفس الفترة الزمنيّة. لاحظ أنه ليس بالضرورة أن يكون معدل البت أقل من معدّل الباود أو يساويه كما يوحي ترميز مانشستر، فإذا كان مخطّط التعديل قادرًا على استخدام (والتعرف على) أربع إشارات مختلفة بدلًا من اثنتين فقط (مرتفعة ومنخفضة على سبيل المثال)، فمن الممكن تشفير بتّين في كلّ فترة ساعة، مما ينتج عنه معدّل بت يعادل ضعف معدّل الباود. تعني القدرة على التعدّيل بين ثماني إشارات مختلفة القدرةَ على إرسال ثلاثة بتات لكلّ فترة ساعة، ومن المهمّ وضعك في بالك لوجود تعديلٍ مبسّط بإفراط، وهو أعقد من إرسال إشارات مرتفعة ومنخفضة، فمن المألوف تغيير مجموعة أطوار وسعات إشارة، مما يؤدي إلى تشفير 16 أو حتى 64 نمطًا مختلفًا، غالبًا رموز مظلمة (dalled symbols)، خلال كلّ فاصل زمنيّ على مدار السّاعة، حيث تعديل سعة التربيع (Quadrature Amplitude Modulation ويختصر إلى QAM) هو مثال مستخدم على نطاق واسع لمخطط التعديل هذا. يحاول التّرميز النهائي المسمّى 4B / 5B، معالجة عدم كفاءة ترميز مانشستر دون المعاناة من مشكلة تمديد فترات الإشارات المرتفعة أو المنخفضة، وتتمثّل فكرة ترميز 4B / 5B في إدخال بتات إضافية إلى مجرى البتات لتفكيك سلاسل طويلة من الأصفار أو الواحدات، وتُشفَّر كل 4 بتات من البيانات الفعليّة في شيفرة مكوّنة من 5 بتات تُرسَل بعد ذلك إلى المستقبل، حيث جاء الاسم 4B / 5B من ذلك. تُحدَّد الشيفرات المكونة من 5 بتات بحيث لا يحتوي كلّ منها على أكثر من صفرٍ واحد في بدايتها ولا يزيد عن صفرين في النهاية، وبالتالي لا ينتج عن أيّ زوج من الشيفرات ذات 5 بتات إرسال أكثر من ثلاثة أصفار متعاقبة وذلك عند الإرسال بالتّتالي، ثم تُرسَل الشيفرات ذات الـ 5 بتات الناتجة باستخدام ترميز NRZI، وهذا ما يفسّر سبب اهتمام الشيفرة بالأصفار المتعاقبة فقط، حيث يحلّ ترميز NRZI مشكلة الوحدات المتعاقبة. لاحظ أنّ ترميز 4B / 5B ينتج كفاءةً بنسبة 80%. يعطي الجدول التّالي شيفرات 5 بتات التي تتوافق مع كلّ رمز من 16 رمزًا من بيانات ذات 4 بتات ممكنة: رمز بيانات ذو 4 بتات (4-bit Data Symbol) شيفرة ذات 5 بتات 0000 11110 0001 01001 0010 10100 0011 10101 0100 01010 0101 01011 0110 01110 0111 01111 1000 10010 1001 10011 1010 10110 1011 10111 1100 11010 1101 11011 1110 11100 1111 11101 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; } لاحظ أن 5 بتّات كافية لترميز 32 شيفرة مختلفة حيث تُستخدم 16 شيفرة منها فقط للبيانات، فهناك 16 شيفرة متبقّية يمكن استخدامها لأغراض أخرى من بينها الشيفرة 11111 التي تُستخدم عندما يكون الخطّ خاملًا بدون عمل، وتقابل الشيفرة 00000 ما يشير إلى تعطُّل الخطّ (dead)، وتُفسَّر الشيفرة 00100 بأن الخطّ مقطوع (halt)، ويوجد 7 شيفرات من بين 13 شيفرةً متبقية غير صالحة لأنها تنتهك قاعدة وجود صفر واحد في البداية وصفرين في النهاية، وتمثل الـ 6 شيفرات الأخرى رموز تحكم مختلفة. تستخدم بعض بروتوكولات التأطير (framing protocols) الموضحة لاحقًا في هذا المقال رموز التحكم هذه. التأطير (Framing) فكّر في السيناريو الموجود في الشكل الآتي بعد معرفتك بكيفية نقل سلسلة من البتّات عبر رابط نقطة لنقطة أو من محوّل إلى محوّل، وتذكّر أننا نركز على شبكات تبديل الرّزم (packet-switched networks)، ممّا يعني أن كتل البيانات تسمى إطارات (frames) عند هذا المستوى، وليس مجرى بتات تتبادلها العُقد، حيث يمكّن محوّل الشبكة العُقد من تبادل الإطارات، وتخبر العقدة A محوّلها بإرسال إطار من ذاكرة العقدة عندما ترغب في إرسال إطار إلى العقدة B، فينتج عن هذا سلسلة من البتات تُرسَل عبر الرابط. ثم يجمع المحوّل الموجود على العقدة B سلسلة البتات الواصلة إلى الرابط معًا ويودِع الإطارَ المقابل في ذاكرة العقدة B، ويُعدّ التعرف على مجموعة البتات التي تشكّل إطارًا بالضبط، أي تحديد مكان بدء الإطار ونهايته، هو التّحدي الأساسي الذي يواجهه المحوّل. توجد عدّة طرق لمعالجة مشكلة التأطير، حيث يستخدم هذا القسم ثلاثة بروتوكولات مختلفة لذلك. لاحظ أنه بينما نناقش مشكلة التأطير في سياق الرّوابط من نقطة لنقطة، فهذه المشكلة هي مشكلة أساسيّة ويجب معالجتها أيضًا في شبكات الوصول المتعدّد (multiple-access)، مثل: شبكات الإيثرنت، والشبكات اللّاسلكية. البروتوكولات الموجّهة بالبايت (Byte-Oriented Protocols مثل بروتوكول PPP) إحدى أقدم الطرق المستخدمة للتأطير والتي لها جذورها في توصيل الطرفيات بالحواسيب المركزيّة هي التي تَعدّ كل إطار على أنه مجموعة من البايتات أو الأحرف بدلًا من كونها مجموعة من البتات، ومن الأمثلة القديمة لهذه البروتوكولات الموجَّهة بالبايت بروتوكول الاتصال الثنائي المتزامن (Binary Synchronous Communication ويختصر إلى BISYNC) الذي طورته شركة IBM في أواخر الستينات، وبروتوكول رسائل اتصالات البيانات الرقمية (Digital Data Communication Message Protocol واختصارًا DDCMP) المستخدم في بروتوكولات DECNET التي أنشأتها شركة Digital Equipment Corporation، وبنت شركات الحواسيب الكبيرة، مثل: شركتي IBM، وDEC ذات مرّة أيضًا شبكاتٍ خاصةً لعملائها، وبروتوكول نقطة لنقطة (Point-to-Point Protocol واختصارًا PPP) المستخدم على نطاق واسع هو مثال حديث للطرق المستخدمة للتأطير. توجد طريقتان للتأطير الموجّه بالبايت على مستوى عالٍ، الطريقة الأولى هي استخدام أحرف خاصّة معروفة باسم الأحرف الحارسة (sentinel characters) لتحديد مكان بدء الإطارات ونهايتها، والفكرة هي الإشارة إلى بداية الإطار عن طريق إرسال حرفٍ خاصّ بالتزامن هو SYN. ويُحتوى أحيانًا جزء البيانات من الإطار بين حرفين خاصّين آخرين هما: STX (بداية النصّ)، وETX (نهاية النصّ)، ويستخدم بروتوكول الاتصال الثنائي المتزامن BISYNC هذه الطّريقة، تكمن مشكلة طريقة الحارس (sentinel approach) في أن أحد الأحرف الخاصّة قد يظهر في جزء البيانات من الإطار، الطّريقة القياسيةّ للتغلّب على هذه المشكلة عن طريق تحويل هذا الحرف بوضع حرف تحويل رابط البيانات (data-link-escape أو اختصارًا DLE) قبله كلّما ظهر في جسم الإطار، حيث يجري تخطّي حرف DLE أيضًا (بوضع حرف DLE إضافي قبله) في جسم الإطار. قد يلاحظ مبرمجو لغة البرمجة C تشابه هذا مع الطريقة التي تحوَّل بها علامة الاقتباس (quotation mark) بواسطة الشرطة المائلة العكسيّة (backslash) عند ظهورها داخل سلسلة (string)، ويُطلق على هذا الأسلوب غالبًا حشو الأحرف (character stuffing) بسبب إدخال أحرف إضافيّة في جزء البيانات من الإطار. بديل اكتشاف نهاية إطار باستخدام قيمة حارسة (sentinel value) هو تضمين عدد بايتات الإطار في بداية الإطار وتحديدًا في ترويسة الإطار، حيث يستخدم بروتوكول DDCMP هذه الطريقة، ويتمثّل أحد مخاطر هذه الطريقة ، في إمكانيّة إفساد خطأ الإرسال لحقل العدّ (count field)، وفي هذه الحالة لن يُكتشف نهاية الإطار بصورة صحيحة. توجد مشكلة مماثلة مع الطريقة القائمة على الحارس إذا فسد حقل ETX، فإذا حدث ذلك، فسيجمّع المستقبل عدد البايتات كما يشير حقل العدّ التالف، ثم يستخدم حقل اكتشاف الخطأ لتحديد تلف الإطار، ويسمى هذا أحيانًا بخطأ التأطير (framing error)، ثمّ سينتظر المستقبل حتّى يرى حرف SYN التالي ليبدأ بجمع البايتات التي تُشكّل الإطار التالي، لذلك من الممكن تسبب خطأ التأطير في تلقّي إطارات متتالية بصورة غير صحيحة، ويستخدم بروتوكول نقطة لنقطة (Point-to-Point Protocol أو اختصارًا PPP)، والذي يشيع استخدامه لنقل رزم بروتوكول الإنترنت (Internet Protocol) عبر أنواع مختلفة من روابط نقطة لنقطة، ولنقل الحرّاس (sentinels)، وحشو الأحرف (character stuffing). تجد صيغة إطار PPP في الشّكل التالي: يعرض الشّكل السّابق الرّزمة مثل سلسلة من الحقول المصنَّفة، ويوجد فوق كلّ حقل رقمٌ يشير إلى طول هذا الحقل بالبتات، ولاحظ أنّ الرّزم تُرسَل بدءًا من الحقل الموجود في أقصى اليسار، فحرف بداية النصّ (start-of-text) الخاصّ الذي يُشار إليه على أنه حقل الراية Flag هو 01111110، ويحتوي حقلًا العنوان Address والتّحكم Control عادةً قيمًا افتراضية وبالتالي فهي غير مهمّة. ويُستخدم حقل البروتوكول (Protocol) لفكّ تعدُّد الإرسال، حيث يحدّد البروتوكول عالي المستوى مثل بروتوكول IP. يمكن التفاوض على حجم حِمل (payload) الإطار، ولكنّه يبلغ 1500 بايت افتراضيًا. يكون حقل المجموع الاختباري Checksum إمّا 2 (افتراضيًا) أو 4 بايتات. لاحظ أنه على الرّغم من الاسم الشائع لهذا الحقل إلا أنه في الواقع عبارة عن CRC، وليس checksum (كما سنوضّح لاحقًا). تختلف صيغة إطار بروتوكول PPP في مسألة التفاوض على العديد من أحجام الحقول بدلًا من إصلاحها، حيث يُجرى هذا التفاوض بواسطة بروتوكول يُسمّى بروتوكول التحكّم بالرابط (Link Control Protocol ويختصر إلى LCP). يعمل كلّ من بروتوكولي PPP، وLCP جنبًا إلى جنب، فيرسل بروتوكول LCP رسائل تحكّم مغلَّفة ضمن إطارات بروتوكول PPP، ويشار إلى هذه الرسائل بواسطة معرّف LCP في حقل PPP (حقل Protocol)، ثم يغيّر بروتوكول LCP صيغة إطار PPP استنادًا إلى المعلومات الواردة في رسائل التحكم هذه، ويشارك بروتوكول LCP أيضًا في إنشاء رابط بين نظيرين (peers) عندما يكتشف كلا الجانبين أن الاتّصال عبر هذا الرّابط ممكن (عندما يكتشف كلّ مستقبل ضوئي إشارةً واردةً من الألياف التي يتّصل بها على سبيل المثال). البروتوكولات الموجّهة بالبت (Bit-Oriented Protocols مثل بروتوكول HDLC) لا تهتمّ البروتوكولات الموجّهة بالبتّ بحدود البايت على عكس البروتوكولات الموجّهة بالبايت، حيث تنظر البروتوكولات الموجّهة بالبتّ ببساطة إلى الإطار على أنه مجموعة من البتات، وقد تأتي هذه البتات من بعض مجموعات الأحرف كنظام ASCII، وقد تكون قيم بكسلات في صورة، كما قد تكون تعليمات ومُعامَلات من ملف تنفيذيّ. بروتوكول التّحكم في رابط البيانات المتزامن (Synchronous Data Link Control الذي يختصر إلى SDLC) الذي طوّرته شركة IBM هو مثال على بروتوكولٍ موجَّه بالبت. وحّدت منظّمة ISO لاحقًا بروتوكول SDLC مثل بروتوكول التحكم في رابط البيانات عالي المستوى (High-Level Data Link Control واختصارًا HDLC). وستجد صيغة إطار HDLC في الشّكل التالي: يشير بروتوكول HDLC إلى بداية ونهاية الإطار مع سلسلة بتات مميّزة هي 01111110، وتُرسَل هذه السّلسلة أيضًا أثناء أيّ وقت يكون فيه الرّابط خاملًا بحيث يمكن للمرسل والمستقبل إبقاء ساعاتهما متزامنةً، باستخدام كلا البروتوكولين بهذه الطريقة طريقةَ الحارس (sentinel approach)، ونظرًا لأنّ سلسلة البتات هذه قد تظهر في أيّ مكان في جسم الإطار، فقد تعبر البتّات 01111110 حدود البايت، حيث تستخدم البروتوكولات الموجَّهة بالبتّ حرف DLE التناظري، وهي تقنيّة تُعرّف باسم حشو البتات (bit stuffing). يعمل حشو البتات في بروتوكول HDLC على النحو التالي: تُرسل خمسة واحدات متعاقبة على جانب الإرسال في أيّ وقت من نصّ الرسالة (باستثناء عندما يحاول المرسل إرسال السلسلة المميزة 01111110)، ويحشو المرسل 0 قبل إرسال البتّ التالي؛ أمّا على الجانب المستقبل وفي حالة وصول خمسة واحدات متعاقبة، فيتّخذ المستقبل قراره بناءً على البتّ التالي الذي يراه (أي البت الذي يتبع الواحدات الخمسة)، فإذا كان البت التالي يساوي 0، فلابدّ أنّها محشوّة وبالتالي يزيلها المستقبل، وإذا كان البت التالي 1، فسيكون أحد الأمرين صحيحًا، فإمّا أن تكون هذه علامة نهاية الإطار، أوقد أُدخِل خطأٌ في مجرى البتات، ويمكن للمستقبل التمييز بين هاتين الحالتين بالنظر إلى البت التالي، فإذا شاهد 0 (أي أنّ آخر 8 بتات نظر إليها هي01111110) فهذا يعني أنهّا علامة نهاية الإطار، وإذا شاهد 1 (أي أن آخر 8 بتات نظر إليها هي01111111)، فلا بد من وجود خطأ ثم يتجاهل الإطار بأكمله. يتعيّن على المستقبل في الحالة الأخيرة انتظار السلسلة 01111110 التالية قبل بدئه في الاستلام مرّةً أخرى، ونتيجةً لذلك هناك احتمال فشل المستقبل في استلام إطارين متتاليين. ومن الواضح أنه لا تزال هناك طرق يمكن من خلالها عدم اكتشاف أخطاء التأطير، كما هو الحال عند إنشاء نمط نهاية الإطار الزائف بالكامل بسبب الأخطاء، ولكن هذه الإخفاقات غير مُرجّحة نسبيًّا، وستناقش الطرق القوية لاكتشاف الأخطاء في قسم لاحق. من الخصائص المثيرة للاهتمام لحشو البتات، بالإضافة إلى حشو الأحرف، أن حجم الإطار يعتمد على البيانات التي تُرسَل في حِمل الإطار. في الواقع ليس ممكنًا جعل جميع الإطارات بنفس الحجم تمامًا، نظرًا لأن البيانات التي يمكن حملها في أي إطار عشوائية، ولإقناع نفسك بهذا، ضع في بالك ما يحدث إذا كان آخر بايت من جسم الإطار هو الحرف ETX. ستُشرح صيغة التأطير التي تضمن أن جميع الإطارات لها نفس الحجم في الفقرة التالية. التأطير المعتمد على الساعة (Clock-Based Framing مثل معيار SONET) يمثّل معيار الشّبكة الضوئيّة المتزامنة (Synchronous Optical Network أو اختصارًا SONET) الطريقةَ الثالثة للتأطير، ويشار إلى هذه الطريقة ببساطة على أنّها تأطير معتمد على الساعة لعدم وجود مصطلح عامّ مقبول على نطاق واسع. اقترحت أبحاث بيل للاتصالات (Bell Communications Research أو Bellcore) معيار SONET لأوّل مرّة، ثمّ طوّره المعهد القومي الأمريكي للمواصفات القياسيّة (American National Standards Institute وتُختصر إلى ANSI) للإرسال الرقمي عبر الألياف الضوئيّة، واعتمده الاتحاد الدولي للاتصالات ITU-T منذ ذلك الحين، وكان معيار SONET لسنوات عديدة هو المعيار المهيمن لنقل البيانات لمسافات طويلة عبر الشبكات الضوئيّة. يجب توضيح نقطة مهمّة حول معيار SONET وهي أنّ مواصفاته الكاملة أكبر بكثير من هذا الكتاب، وبالتالي ستغطّي المناقشة التالية النقاط الهامّة للمعيار فقط. يعالج معيار SONET كلًا من مشكلة التأطير ومشكلة التشفير، كما أنه يعالج مشكلة مهمّةً جدًّا لشركات الهاتف وهي مشكلة دمج (multiplexing) عدّة روابط منخفضة السّرعة على رابطٍ واحد عالي السّرعة، يعكس تصميم هذا المعيار في الواقع حقيقة أنّ شركات الهاتف يجب عليها الاهتمام بدمج أعداد كبيرة من القنوات التي تبلغ سرعتها 64 كيلوبت في الثانية والتي تُستخدم تقليديًا للمكالمات الهاتفيّة. يحتوي إطار SONET على بعض المعلومات الخاصّة التي تخبر المستقبل بمكان بدء الإطار ونهايته كما هو الحال مع مخطّطات الإطارات التي نوقشت سابقًا، ومع ذلك فهذا هو وجه التّشابه الوحيد بينهما، ومن الجدير بالذّكر أنه لا يستخدم حشو البتات، بحيث لا يعتمد طول الإطار على البيانات المرسلة، لذا فالسؤال الذي يجب طرحه هو كيف يعرف المستقبل أين يبدأ كلّ إطار وأين ينتهي؟ يُعدّ هذا السؤال مرتبطًا برابط SONET الأقلّ سرعةً، والذي يُعرف باسم STS-1 ويعمل بسرعة 51.84 ميجابت في الثانية، حيث يظهر إطار STS-1 في الشكل الآتي، وهو مُرتَّب على شكل 9 صفوف ويأخذ كل صفّ 90 بايتًا، وتكون البايتات الثلاثة الأولى من كلّ صفّ بايتات إضافيّة (overhead)، وتتاح باقي البايتات للبيانات المرسَلة عبر الرّابط. يحتوي البايتان الأوّليان من الإطار على نمط بت خاصّ، وهذه البايتات هي التي تُمكّن المستقبل من تحديد مكان بدء الإطار، ولا يوجد سبب لعدم ظهور هذا النّمط أحيانًا في جزء الحمولة (payload) من الإطار، نظرًا لعدم استخدام حشو البتات، لذلك يبحث المستقبل عن نمط البت الخاصّ باستمرار على أمل رؤيته مرةً واحدة كلّ 810 بايت، لأنّ كلّ إطار يبلغ طوله 9 × 90 = 810 بايتات، وبالتالي يستنتج المستقبل أنه متزامن ويمكنه بعد ذلك تفسير الإطار بصورة صحيحة عندما يظهر النمط الخاصّ في المكان المناسب مراتٍ كافية. أحد الأشياء التي لن نشرحها بسبب تعقيد معيار SONET هو الاستخدام التفصيلي لجميع البايتات الإضافية (overhead) الأخرى، وقد يُعزى جزء من هذا التّعقيد إلى حقيقة أنّ معيار SONET يعمل عبر شبكة المشغّل الضّوئية، وليس عبر رابط واحد فقط، تذكّر أنّنا نتخلى عن حقيقة أنّ شركات الاتصالات تنفّذ شبكة، ونركز بدلًا من ذلك على حقيقة قدرتنا على استئجار رابط SONET منها، ثم استخدام هذا الرّابط لبناء شبكتنا الخاصّة ذات نوع تبديل الرّزم (packet-switched). يأتي تعقيدٌ إضافي من حقيقة أنّ هذا المعيار يوفّر مجموعة خدمات أكثر ثراءً من مجرد نقل البيانات، حيث تُخصَّص على سبيل المثال 64 كيلوبت في الثانية من سعة رابط SONET لقناةٍ صوتية تُستخدم للصيانة. تُرمَّز بايتات إطار SONET الإضافية باستخدام ترميز NRZ، وهو التّرميز البسيط الذي نوقش سابقًا، حيث تكون سلسلة الواحدات مرتفعة وسلسلة الأصفار منخفضة، ويجب خلط (scrambled) بايتات الحِمل لضمان وجود الكثير من الانتقالات للسّماح للمستقبل باستعادة ساعة المرسل، حيث يتمّ ذلك عن طريق حساب عمليّة XOR للبيانات المراد إرسالها باستخدام نمط بتّات معروف. يحتوي نمط البت الذي يبلغ طوله 127 بتًّا على الكثير من الانتقالات من 1 إلى 0، لذلك من المحتمل أن ينتج عن عملية XOR لنمط البتّ مع البيانات المرسلَة إشارةٌ ذات انتقالات كافية لتفعيل استعادة الساعة. يدعم معيار SONET دمج عدّة روابط منخفضة السرعة بالطريقة التالية: يعمل رابط SONET المحدّد بمعدّلٍ من مجموعة محدودة من المعدّلات المحتملة، والتي تتراوح من 51.84 ميجابت في الثانية (STS-1) إلى 39813120 ميجابت في الثانية (STS-768). لاحظ أنّ كلّ هذه المعدّلات عبارة عن مضاعفات STS-1 العددية الصحيحة. تكمن أهمية التأطير في أن إطار SONET الواحد قد يحتوي على إطارات فرعيّة لقنوات متعدّدة ذات معدّلات أقلّ؛ أمّا الميزة الثانية فهي أن كلّ إطار يبلغ طوله 125 ميكرو ثانية، وهذا يعني أنّ طول إطار SONET يبلغ 810 بايت في معدلات STS-1، بينما في معدلات STS-3 يبلغ طول كلّ إطار SONET حوالي 2430 بايت. لاحظ الارتباط بين هاتين الميزتين حيث: 3 × 810 = 2430، مما يعني تلاؤم ثلاثة إطارات STS-1 تمامًا مع إطار STS-3 واحد. ترمز STS إلى إشارة النقل المتزامن (Synchronous Transport Signal)، وهي الطريقة التي يتحدّث بها معيار SONET عن الإطارات، ويوجد مصطلحٌ موازٍ هو الناقل الضوئي (Optical Carrier واختصارًا OC) الذي يُستخدم للتّحدث عن الإشارة الضوئية الأساسيّة التي تحمل إطارات SONET. يمكن القول أنّ هذين المصطلحين متوازيان لأن STS-3 و OC-3 على سبيل المثال يشيران إلى معدّل إرسال يبلغ 155.52 ميجابت في الثانية. سنلتزم بـالمصطلح STS نظرًا لأنّنا نركّز على التأطير هنا، ولكن من المرجح أن تسمع شخصًا يشير إلى رابط ضوئي باسم OC. يمكن القول بأنّ إطار STS-N يتكوّن من N إطار من النّوع STS-1، حيث تكون البايتات في هذه الإطارات متداخلة (interleaved)، أي يرسَل بايت من الإطار الأول، ثمّ يرسَل بايت من الإطار الثاني وهكذا. والسبّب في تداخل (interleaving) البايتات في كلّ إطار STS-N هو التأكّد من أنّ البايتات في كلّ إطار STS-1 موجودة بالتساوي، أي أنّ البايتات تظهر في المستقبل بسرعة تبلغ 51 ميجابت في الثانية بسهولة، بدلًا من تجميعها بالكامل خلال 1 / Nth من الفاصل الزّمني 125 ميكرو ثانية. يمكن ربط حِمل إطارات STS-1 معًا لتكوين حِمل STS-N أكبر على الرّغم من صحّة افتراض أنّ إشارة STS-N تُستخدم لتجميع N إطار من النّوع STS-1، مثل الإشارة إلى هذا الرّابط باستخدام STS-Nc ،على التّسلسل (concatenated)، حيث يُستخدَم أحد الحقول الموجودة في القسم الإضافي للإطار لهذا الغرض. يبين الشّكل السّابق بيانيًا التسلسل (concatenation) في حالة ثلاثة إطارات STS-1 متسلسلة في إطار STS-3c واحد. تكمن أهميّة رابط SONET في كونه من النوع STS-3c بدلًا من النوع STS-3، فيمكن لمستخدم هذا الرّابط في الحالة الأولى مشاهدته على أنه أنبوب واحد بسرعة 155.25 ميجابت في الثانية، بينما يجب عرض الرابط STS-3 على شكل ثلاثة روابط بسرعة 51.84 ميجابت في الثانية تُستخدَم لمشاركة الألياف. وأخيرًا، وصفُ معيار SONET السابق بسيطٌ جدًا فهو يفترض أنّ حِمل كلّ إطار موجود بالكامل داخل الإطار، إذًا لماذا لا يحدث ذلك؟ يجب في الواقع عرض إطار STS-1 الموصوف للتّو على أنه مجرّد عنصرٍ نائب للإطار، حيث قد يطفو الحمل الفعلي (actual payload) خارج حدود الإطار، ويوضح الشّكل السابق هذه الحالة، فيطفو هنا كلٌ من حِمل الإطار STS-1 بين إطاري STS-1 و يزيح الحِمل عددًا من البايتات إلى اليمين، وبالتالي تلتفّ هذه البايتات. يشير أحد الحقول الموجودة في قسم الإطار الإضافي إلى بداية الحِمل، فتكمن أهميّة هذه الإمكانية في أنها تبسّط مهمّة مزامنة الساعات المستخدمة عبر شبكات شركات الاتصالات، حيث تقضي شركات الاتصالات الكثير من وقتها قلقةً بشأن مزامنة الساعات. ترجمة -وبتصرّف- للقسمين Encoding و Framing من فصل Direct Links من كتاب Computer Networks: A Systems Approach
-
المشكلة: الاتصال بشبكة (Connecting to a Network) تتكوّن الشبّكات الحاسوبيةّ من عُقدٍ (nodes) متّصلة عن طريق روابط (links) كما لاحظتَ في المقال الأوّل من هذه السلسلة، أساسيات الشبكات، فمن بين المشاكل الأساسيةّ التي يمكن مواجهتها هي كيفية توصيل عقدتين مع بعضهما، ولاحظت أيضًا تقديم تجريد السّحابة (cloud abstraction) لتمثيل الشّبكة دون كشف تعقيدات الشّبكة الدّاخلية، لذلك يجب أيضًا معالجة مشكلة مشابهة تتمثّل في توصيل مضيفٍ بسحابة، وهذه هي المشكلة التي يواجهها كلّ مزوّد خدمة إنترنت (Internet Service Provider ويختصَر إلى ISP) عندما يريد توصيل عميلٍ جديد بشبكته. يجب معالجة مجموعة شائعة من المشاكل سواءً عند بناء شبكة بسيطة مؤلّفة من عقدتين ورابطٍ بينهما، أو عند توصيل المضيف المليار إلى شبكة موجودة مسبقًا مثل الإنترنت، حيث تحتاج أوّلًا إلى وسيط فيزيائي (physical medium) يمكنك إجراء الاتّصال من خلاله، فقد يكون هذا الوسيط عبارةً عن جزءٍ من سلك (wire)، أو قطعة من ألياف ضوئيّة (optical fiber) أو وسيطًا غير ملموس مثل الهواء الذي يمكن نقل الإشعاع الكهرومغناطيسي، مثل موجات الراديو، خلاله. وقد تغطّي هذه الشّبكة مساحةً صغيرةً، مثل: مبنى، أو مساحة واسعة مثل المساحة العابرة للقارّات (transcontinental). لا يُعدّ توصيل عقدتين بوسيطٍ مناسبًا إلّا الخطوةَ الأولى، فيجب معالجة خمس مشكلات إضافية قبل تمكُّن العقد من تبادل الرّزم (packets) بنجاح، وستوفرّ معالجة هذه المشاكل اتصال الطّبقة 2 (L2)، باستخدام مصطلحات من معماريّة OSI. المشكلة الأولى هي ترميز (encoding) البتات ضمن وسيط الإرسال (transmission medium)، بحيث قد تفهمها عقدة الاستقبال (receiving node)؛ أمّا والمشكلة الثّانية، فهي مسألة تحديد سلسلة البتات المنقولة عبر الرّابط (link) ضمن رسائل كاملة يمكن تسليمها إلى العقدة النّهائية، حيث تدعى هذه المشكلة بالتّأطير (framing)، وتدعى الرّسائل التي يمكن توصيلها إلى المضيفين النهّائيين أحيانًا بالإطارات (frames)، وبالرّزم (packets) أحيانًا أخرى؛ بينما المشكلة الثالثة، ونظرًا لتعرّض الإطارات أحيانًا للتّلف أثناء الإرسال، فمن الضّروري اكتشاف هذه الأخطاء واتخاذ الإجراء المناسب، وهذه هي مشكلة كشف الأخطاء (error detection)؛ في حين تتمثّل المشكلة الرّابعة في ظهور الرّابط على أساس رابطٍ موثوق، على الرّغم من حقيقة إفساده للإطارات من وقتٍ لآخر. وفي المشكلة الخامسة والأخيرة وهي في الحالات التي يتشارك فيها مضيفون متعدّدون بنفس الرّابط، مثل الرّوابط اللاّسلكية (wireless links)، فمن الضّروري التوسّط في الوصول إلى هذا الرّابط، وهذه هي مشكلة التحّكم بالوصول إلى الوسائط (media access control). على الرّغم من إمكانيّة مناقشة هذه المشاكل الخمس، التّرميز (encoding)، والتّأطير (framing)، وكشف الأخطاء (error detection) والتّسليم الموثوق (reliable delivery)، وتوسّط الوصول (access mediation)، إلّا أنها تُعدّ مشاكلًا حقيقيّة تُعالَج بطرقٍ مختلفة باستخدام تقنيّات شبكيّة مختلفة، وسيتناول هذا المقال هذه المشاكل في سياق تقنيّات شبكيّة محدّدة، مثل روابط الألياف نقطةً لنقطة (point-to-point fiber links)، والمثال السّائد عنها شبكات SONET، وشبكات الوصول المتعدّد باستشعار الحامل (Carrier Sense Multiple Access واختصارًا CSMA)، والمثال الأشهر عنها شبكات إيثرنت (Ethernet)، والشّبكات اللّاسلكية (Wi-Fi) التّقليديّة، وتقنيّة ليف إلى المنزل (fiber-to-the home)، التي تَعدّ تقنية PON هي المعيار السّائد عنها، وشبكات الهاتف المحمول اللّاسلكية (mobile wireless)، حيث تتحوّل الآن شبكة 4G إلى شبكة 5G بسرعة. الهدف من هذا المقال هو إجراء مسحٍ للتّقنيات المتاحة على مستوى الرّابط واكتشاف هذه المشاكل الخمس الأساسيّة، حيث سنختبر ما يتطلّبه الأمر لجعل مجموعة متنوّعة من الوسائط الفيزيائيّة المختلفة وتقنيّات الرّبط مفيدةً كلبناتٍ أساسيّة لبناء شبكات متينة وقابلة للتّوسع. المخطط التقني (Technology Landscape) من المفيد أوّلًا الحصول على موقعٍ على أرض الواقع قبل الخوض في التّحديات الموضّحة في عرض المشكلة في بداية هذا المقال، حيث يتضمّن هذا الموقع مصفوفةً واسعةً من تقنيّات الرّبط، وهذا يرجع جزئيًّا إلى الظّروف المتنوّعة التي يحاول المستخدمون توصيل أجهزتهم في ظلّها، ويجب على مشغّلي الشّبكات الذين يُنشئون شبكات عالميّة (global networks) في أحد طرفيّ الشّبكة، التّعامل مع الرّوابط (links) التي تمتدّ لمئات وآلاف الكيلومترات، والتي تربط موجّهاتٍ (routers) بحجم الثّلاجة؛ أمّا في الطّرف الآخر، فيستعمل المستخدم العاديّ الروابطَ غالبًا مثل وسيلةٍ لربط الحاسوب بالإنترنت الموجود، ويكون هذا الرّابط أحيانًا لاسلكيًّا (Wi-Fi) مثل الرّوابط الموجودة في المقاهي، ويكون أحيانًا رابط إيثرنت (Ethernet) مثل الرّوابط الموجودة في مبنى مكتبيّ، أو في الجامعة؛ أو قد يكون هاتفًا ذكيًا متّصلًا بشبكة خلويّة (cellular network)؛ كما قد يكون الراّبط أليافًا ضوئيّةً (fiber optic) يوفّرها مزوّد خدمة الانترنت ISP لشريحة كبيرة من النّاس، ويستخدم العديد من النّاس روابطًا ذات أسلاك نحاسيّة (copper wire) أو كابلات، وتوجد عدّة استراتيجيّات شائعة مستخدمة مع هذه الرّوابط المختلفة، بحيث يمكن جعلها موثوقةً ومفيدةً للطّبقات الأعلى من البروتوكول المستخدم، حيث سيشرح هذا المقال تلك الاستراتيجياّت جميعها. يوضّح الشّكل السّابق أنواع الرّوابط المختلفة التي يمكن وجودها ضمن شبكة الإنترنت اليوم، فتجد يسار الشّكل السّابق مجموعةً متنوّعةً من أجهزة المستخدم النّهائي (end-user) التي تتراوح من الهواتف الذّكية (smartphones) إلى الأجهزة اللّوحيّة (tablets)، وحتّى أجهزة الحاسوب الكاملة (full-fledged computers) المتّصلة بمزوّد خدمة الانترنت عبر وسائل مختلفة. قد تستخدم هذه الرّوابط تقنيّات مختلفة ولكنّها تبدو متشابهةً مع الشّكل السّابق، إذ يربط خطٌ مستقيم الجهاز بموجّه، وتوجد روابط تربط الموجّهات مع بعضها البعض داخل مزوّد خدمة الإنترنت، بالإضافة إلى وجود روابط تربط مزوّد خدمة الانترنت مع بقيةّ شبكة الانترنت (rest of the Internet) التي تتكون من الكثير من مزوّدي خدمة الإنترنت الآخرين، والمضيفين الذين يتّصلون بهم. تبدو جميع هذه الرّوابط متشابهةً، وهذا ليس فقط لأننا لسنا فنانين جيّدين جدًّا، بل لأن جزءًا من دور معماريّة الشّبكة هو توفير تجريدٍ مشترك لشيء معقّد ومتنّوع مثل الرّوابط (links)، فلا يجب على حاسوبك المحمول أو هاتفك الذّكي الاهتمام بنوع الرّابط المتصّل به، والشّيء الوحيد المهم هو امتلاكه لرابط بشبكة الإنترنت، ولا يتعيّن على الموجّه (router) أيضًا الاهتمام بنوع الرّابط الذي يربطه مع الموجهات الأخرى، حيث قد يرسل الموجّه رزمةً عبر الرّابط مع توقّعٍ جيّد بأن الرّزمة ستصل إلى الطّرف الآخر من الرّابط، لكن كيف يمكن جعل جميع هذه الأنواع المختلفة من الرّوابط متشابهةً بدرجة كافية للمستخدمين النّهائيين والموجّهات؟ يجب أوّلًا التّعامل مع جميع قيود الرّوابط الفيزيائيّة ونقاط ضعفها الموجودة في العالم الحقيقي، حيث أظهرت فقرة المشكلة في بداية هذا المقال بعضًا من هذه المشاكل، ولكن يجب أوّلًا تقديم بعضٍ من الفيزياء البسيطة قبل مناقشتها. تُصنع جميع هذه الرّوابط من بعض المواد الفيزيائيةّ التي يمكنها نشر الإشارات، مثل: الأمواج الراديويّة، أو أنواع أخرى من الإشعاع الكهرومغناطيسي. ولكنّ ما تحتاجه حقًّا هو إرسال البِتّات. سترى كيفية تشفير البتّات لإرسالها، من خلال وسيط فيزيائي في الأقسام اللّاحقة من هذا المقال وبعض المشاكل الأخرى ثم ستفهم كيفيّة إرسال رزمٍ كاملة عبر أيّ نوع من الرّوابط بنهاية هذا المقال بغضّ النّظر عن الوسيط الفيزيائيّ المُستخدَم. تتمثّل إحدى طرق توصيف الرّوابط في الوسيط (medium) الذي تستخدمه عادةً، مثل: الأسلاك النحاسيّة (copper wire)، ومنها مثلا: السّلك المزدوج الملتوي (twisted pair) الذي تستخدمه بعض شبكات الإيثرنت والهواتف الأرضيّة، أو السّلك المحوري (coaxial) الذي يستخدمه الكابل (cable)؛ أو مثل الألياف الضّوئية (optical fiber) التي تستخدمها تقنيّة ليف إلى منزل (fiber-to-the-home)، والعديد من الرّوابط بعيدة المدى ضمن بنية شبكة الإنترنت الأساسيّة (Internet’s backbone)؛ أو مثل الهواء (air)، أو الفراغ (free space) الذي تستخدمه الرّوابط اللّاسلكية (wireless links). يُعدّ التّردّد (frequency) من خصائص الرّوابط المهمّة الأخرى الذي يُقاس بوحدة الهرتز (hertz)، والذي تهتزّ به الموجات الكهرومغناطيسيّة، وتسمّى المسافة بين زوجٍ من حدود الموجة القصوى أو الصغرى المتجاورة بطول الموجة الموجيّ (wavelength) ويُقاس بالمتر. تنتقل جميع الموجات الكهرومغناطيسيّة بسرعة الضّوء، والتي تعتمد بدورها على الوسيط (medium)، حيث يساوي الطّول الموجيّ السّرعةَ مقسومةً على تردّد الموجة، فيحمل خطّ الهاتف للدّرجة الصّوتية (voice-grade telephone line) إشاراتٍ كهرومغناطيسيّة مستمرةً تتراوح بين 300 هرتز، و3300 هرتز، وقد يكون للموجة ذات التّردّد 300 هرتز التي تنتقل عبر النّحاس طولًا موجيًّا يساوي سرعة الضّوء في النّحاس مقسومةً على التّردد، بحيث يساوي: = 2/3 × 3 × 108 / 300 = 667 × 103 متر تمتدّ الموجات الكهرومغناطيسيّة على نطاق أوسع بكثير من التّرددات بدءًا بالموجات الراديويّة، ثم ضوء الأشعّة تحت الحمراء (infrared light)، ثم الضّوء المرئيّ (visible light)، ثم الأشعّة السّينيّة (x-rays)، وأشعّة جاما (gamma rays)، ويبيّن الشّكل التاّلي الطّيف الكهرومغناطيسي، ويوضح الوسائط الشّائعة المستخدمة لحمل نطاقات التّردد: لا يُظهر الشّكل السّابق المكانَ المناسب للشّبكة الخلويّة، فهذا أمر معقّد بعض الشّيء لأن نطاقات التّردد المحدّدة المرخَّصة للشّبكات الخلويّة تختلف حول العالم، وهو أمرٌ أعقد من حقيقة أن مشغّلي الشّبكات غالبًا يدعمون التّقنيات القديمة، أو السّابقة وتقنيّات الجيل الجديد أو التالي، حيث يشغَل كلّ منها نطاقَ تردّد مختلفًا. ويمكننا القول باختصار أنّ التّقنيات الخلويّة التّقليديّة تتراوح بين 700 ميجاهرتز إلى 2400 ميجاهرتز مع تخصيصاتٍ متوسّطة الطّيف وجديدةٍ تحدث عند 6 جيجاهرتز الآن، وتخصيصات الموجة المليمتريّة (millimeter-wave وتُختصر إلى mmWave) المفتوحة فوق 24 جيجاهرتز، حيث من المحتمل أن يصبح نطاق الموجة المليمتريّة هذا جزءًا مهمًّا من شبكة الهاتف المحمول 5G. يمكن فهم الرّابط على أنّه وسيط فيزيائي يحمل إشارات على شكل موجات كهرومغناطيسيّة، وتوفّر هذه الرّوابط أساس إرسال جميع أنواع المعلومات بما في ذلك نوع البيانات التي نهتمّ بنقلها، والتي هي البيانات الثّنائيّة (أصفار وواحدات)، ويمكن القول بأنّ البيانات الثنائية مشفّرةٌ في الإشارة، فمشكلة تشفير البيانات الثّنائية على الإشارات الكهرومغناطيسيّة موضوعٌ معقّد، ويمكن جعل ذلك أكثر قابليّةً للإدارة من خلال التّفكير في تشفير البيانات الثّنائية على أنّه مقسَّم إلى طبقتين، حيث تُعنى الطّبقة السّفلية بالتعّديل (modulation)، أيّ تغيير تردّد (frequency)، أو سعة (amplitude)، أو طور (phase) الإشارة للتّأثير على إرسال المعلومات، فتغيير قدرة (power) أو سعة (amplitude) طولٍ موجيّ هو مثالٌ بسيط عن التّعديل (modulation)، وهذا يكافئ تشغيل وإطفاء النور، فمسألة التّعديل ثانويّةً بالنّسبة للرّوابط التي تُعَد لبنةً أساسيّةً في الشّبكات الحاسوبيّة، لذلك يمكن الافتراض ببساطة أنّه من الممكن إرسال زوج من الإشارات القابلة للتمّييز، حيث يمكن عَد زوج الإشارات كإشارة مرتفعة (high signal)، وأخرى منخفضة (low)؛ أمّا الطّبقة العلويّة، وهي الطّبقة التي تهمّنا الآن، فتهتم بالمشكلة الأبسط بكثير وهي تشفير البيانات الثّنائية على هاتين الإشارتين. يمكن تصنيف الرّوابط بطريقة أخرى وذلك من حيث طريقة استخدامها، حيث تميل الأمور الاقتصاديّة وقضايا النّشر المختلفة إلى التّأثير على مكان وجود أنواع روابط مختلفة، فيتفاعل معظم المستخدمين مع الإنترنت إمّا من خلال الشّبكات اللّاسلكية الموجودة في المقاهي، والمطارات، والجامعات وما إلى ذلك؛ أو من خلال ما يسمى روابط الميل الأخير (last-mile links)؛ أو شبكات الوصول (access networks) بدلًا من ذلك، والتي يوفّرها مزود خدمة الإنترنت. لُخّصت أنواع هذه الرّوابط في الجدول الآتي، وقد اختيرت هذه الأنواع لأنها طرق فعّالة من حيث التّكلفة للوصول إلى ملايين المستخدمين، فتقنيّة خطّ المشترك الرّقمي (Digital Subscriber Line واختصارها DSL) على سبيل المثال هي تقنية قديمة نُشرت على الأسلاك النّحاسية المزدوجة الملتوية الموجودة مسبقًا لخدمات الهاتف القديمة العاديّة؛ أمّا تقنيّة G.Fast، فهي تقنيّة قائمة على النّحاس تُستخدم عادةً في المباني السّكنية متعدّدة المساكن، وتقنيّة الشّبكة الضّوئية السّلبية (Passive Optical Network واختصارها PON) هي تقنيّة أحدث تُستخدم عادةً لربط المنازل والشّركات عبر الألياف التي نُشرت مؤخّرًا. الخدمة (Service) حيّز النّطاق التراسلي (Bandwidth) تقنيّة DSL خطّ المشترك الرّقمي (أسلاك نحاسية) تصل إلى 100 ميجابت في الثّانية تقنيّة G.Fast (أسلاك نحاسيّة) تصل إلى 1 جيجابت في الثّانية تقنيّة PON الشّبكة الضّوئية السّلبية (ألياف ضوئيّة) تصل إلى 10 جيجابت في الثّانية 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; } ويوجد أيضًا شبكة الهاتف المحمول (mobile) أو الشّبكة الخلويّة (cellular)، حيث يشار إليها باسم 4G ولكنّها تتطوّر بسرعة إلى شبكة 5G في وقت ترجمة هذه السلسلة، التي تربط أجهزة الهاتف المحمولة بالإنترنت، حيث يمكن لهذه التقّنية أيضًا العمل مثل وصلة الإنترنت الوحيدة في المنازل أو المكاتب، ولكنّها تأتي مع ميزة إضافية تتمثّل في السّماح بالحفاظ على الاتّصال بالإنترنت أثناء الانتقال من مكان إلى آخر. تُعدّ هذه التّقنيات خيارات شائعة لاتّصال الميل الأخير بمنزلك أو عملك، ولكنّها ليست كافيةً لبناء شبكة كاملة من البداية، لذلك ستحتاج أيضًا إلى بعض الرّوابط الأساسيّة أو روابط شبكة العمود الفقري بعيدة المدى (long-distance backbone links) لتوصيل المدن، فالرّوابط الأساسية الحديثة هي عبارة عن ألياف فقط تقريبًا اليوم، والتي تستخدم عادةً تقنيّةً تسمّى الشّبكة الضّوئية المتزامنة (Synchronous Optical Network وتختصر إلى SONET)، والتي طُوّرت في الأصل لتلبية المتطلّبات ذات الإدارة الصّعبة لشركات الهاتف. ويوجد، بالإضافة إلى روابط الميل الأخير (last-mile) والرّوابط الأساسيّة (backbone) وروابط شبكة الهاتف المحمول (mobile links)، روابطٌ تجدها داخل مبنى أو داخل جامعة ويشار إليها عمومًا باسم الشّبكات المحلّية (local area networks وتختصر إلى LANs)، حيث تُعَد تقنيّة الإيثرنت والتّقنية اللّاسلكية (Wi-Fi) من التّقنيات المهيمنة في هذا المجال. ليس هذا الاستطلاع لأنواع الرّوابط شاملًا، ولكن لابد له من منحك لمحةً عن تنوّع أنواع الرّوابط الموجودة وأسباب هذا التّنوع، سترى في الأقسام القادمة كيف يمكن لبروتوكولات الشّبكات الاستفادة من هذا التّنوع وتقديم رؤية مستقرّة للشّبكة للطّبقات الأعلى على الرّغم من كل التعّقيدات والعوامل الاقتصاديّة منخفضة المستوى. ترجمة -وبتصرّف- للقسم Technology Landscape من فصل Direct Links من كتاب Computer Networks: A Systems Approach
-
متغيرات تقييد الوصول (Semaphores) طريقةٌ جيدة للتعرف على التزامن، ولكنها ليست مستخدمة على نطاق واسع من الناحية العملية كاستخدام كائنات المزامنة (mutexes) والمتغيرات الشرطية (condition variables)، ومع ذلك توجد بعض مشاكل المزامنة التي يمكن حلها ببساطة باستخدام متغيرات تقييد الوصول، مما يؤدي إلى الوصول إلى حلول صحيحة ودقيقة. تقدّم هذه المقالة واجهة برمجة التطبيقات بلغة C للعمل مع متغيرات تقييد الوصول، وكتابة تطبيق لمتغير تقييد الوصول (semaphore) باستخدام كائنات المزامنة (mutexes) والمتغيرات الشرطية (condition variables). POSIX Semaphores متغير تقييد الوصول (semaphore) هو بنية بيانات تُستخدم لمساعدة الخيوط أن تعمل مع بعضها البعض دون تداخلٍ فيما بينها، يحدد POSIX القياسي واجهةً لمتغيرات تقييد الوصول، وهي ليست جزءًا من الخيوط Pthreads، ولكن توفّر معظم نظم التشغيل التي تعتمد على يونكس والتي تطبق Pthreads متغيرات تقييد الوصول أيضًا. لمتغيرات تقييد الوصول POSIX نوع هو sem_t، ووضع مغلّف له لجعل استخدامه أسهل كالعادة: typedef sem_t Semaphore; Semaphore *make_semaphore(int value); void semaphore_wait(Semaphore *sem); void semaphore_signal(Semaphore *sem); Semaphore هو مرادف للنوع sem_t، ولكنني، يقول الكاتب، وجدت Semaphore أسهل للقراءة وذكّرني الحرف الكبير في أوله بمعاملته ككائن (object) وتمريره كمؤشر (pointer): Semaphore *make_semaphore(int value) { Semaphore *sem = check_malloc(sizeof(Semaphore)); int n = sem_init(sem, 0, value); if (n != 0) perror_exit("sem_init failed"); return sem; } تأخذ الدالة make_semaphore القيمة الابتدائية لمتغير تقييد الوصول كمعاملٍ لها، وتخصص حيزًا له وتهيئه ثم تعيد مؤشرًا إلى Semaphore. تعيد الدالة sem_init القيمة 0 إذا نجح تنفيذها وتعيد -1 إذا حدث خطأ ما. أحد الأمور الجيدة لاستخدام الدوال المغلّفة هو أنك تستطيع تغليف (encapsulate) شيفرة التحقق من الخطأ، مما يجعل الشيفرة التي تستخدم هذه الدوال أسهل للقراءة. يمكن تطبيق الدالة semaphore_wait كما يلي: void semaphore_wait(Semaphore *sem) { int n = sem_wait(sem); if (n != 0) perror_exit("sem_wait failed"); } والدالة semaphore_signal: void semaphore_signal(Semaphore *sem) { int n = sem_post(sem); if (n != 0) perror_exit("sem_post failed"); } أفضّل، يقول الكاتب، أن أسمي عملية تنبيه الخيط المتوقف بالمصطلح signal على أن أسميها بالمصطلح post على الرغم أن كلا المصطلحين شائعي الاستخدام. يظهر المثال التالي كيفية استخدام متغير تقييد الوصول ككائن مزامنة: Semaphore *mutex = make_semaphore(1); semaphore_wait(mutex); // protected code goes here semaphore_signal(mutex); يجب أن تهيئ متغير تقييد الوصول الذي تستخدمه ككائن مزامنة بالقيمة 1 لتحدد أن كائن المزامنة غير مقفل، أي يستطيع خيطٌ واحد تمرير متغير تقييد الوصول دون توقف. استخدم اسم المتغير mutex للدلالة على أن متغير تقييد الوصول استخدم ككائن مزامنة، ولكن تذكّر أن سلوك متغير تقييد الوصول مختلف عن كائن مزامنة الخيط Pthread. المنتجون والمستهلكون مع متغيرات تقييد الوصول (Producers and consumers with semaphores) يمكن كتابة حل لمشكلة منتج-مستهلك باستخدام دوال مغلّفة لمتغير تقييد الوصول، حيث يصبح التعريف الجديد للبنية Queue باستبدال كائن المزامنة والمتغيرات الشرطية بمتغيرات تقييد الوصول كما يلي: typedef struct { int *array; int length; int next_in; int next_out; Semaphore *mutex; //-- جديد Semaphore *items; //-- جديد Semaphore *spaces; //-- جديد } Queue; والنسخة الجديدة من الدالة make_queue هي: Queue *make_queue(int length) { Queue *queue = (Queue *)malloc(sizeof(Queue)); queue->length = length; queue->array = (int *)malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; queue->mutex = make_semaphore(1); queue->items = make_semaphore(0); queue->spaces = make_semaphore(length - 1); return queue; } يُستخدم المتغير mutex لضمان الوصول الحصري إلى الطابور، حيث قيمته الابتدائية هي 1 وبالتالي كائن المزامنة غير مقفل مبدئيًا. المتغير items هو عدد العناصر الموجودة في الطابور والذي هو أيضًا عدد الخيوط المستهلكة التي يمكن أن تنفذ الدالة queue_pop دون توقف، ولا يوجد أي عنصر في الطابور مبدئيًا. المتغير spaces هو عدد المساحات الفارغة في الطابور وهو أيضًا عدد الخيوط المنتجة التي يمكن أن تنفّذ الدالة queue_push دون توقف، ويمثل عدد المساحات مبدئيًا سعة الطابور وتساوي length-1. النسخة الجديدة من الدالة queue_push التي تشغّلها الخيوط المنتجة هي كما يلي: void queue_push(Queue *queue, int item) { semaphore_wait(queue->spaces); semaphore_wait(queue->mutex); queue->array[queue->next_in] = item; queue->next_in = queue_incr(queue, queue->next_in); semaphore_signal(queue->mutex); semaphore_signal(queue->items); } لاحظ أنه لا ينبغي على الدالة queue_push استدعاء الدالة queue_full مرة أخرى، حيث بدلًا من ذلك يتتبّع متغير تقييد الوصول عدد المساحات المتاحة ويوقف الخيوط المنتجة إذا كان الطابور ممتلئًا. النسخة الجديدة من من الدالة queue_pop هي: int queue_pop(Queue *queue) { semaphore_wait(queue->items); semaphore_wait(queue->mutex); int item = queue->array[queue->next_out]; queue->next_out = queue_incr(queue, queue->next_out); semaphore_signal(queue->mutex); semaphore_signal(queue->spaces); return item; } شُرح هذا الحل باستخدام شيفرة عامة (pseudo-code) في الفصل الرابع من كتاب The Little Book of Semaphores. صناعة متغيرات تقييد وصول خاصة أية مشكلةٍ تُحَل باستخدام متغيرات تقييد الوصول تُحل أيضًا باستخدام المتغيرات الشرطية و كائنات المزامنة، ويمكن إثبات ذلك من خلال استخدام المتغيرات الشرطية وكائنات المزامنة لتطبيق متغير تقييد الوصول، حيث يمكن تعريف البنية Semaphore كما يلي: typedef struct { int value, wakeups; Mutex *mutex; Cond *cond; } Semaphore; المتغير value هو قيمة متغير تقييد الوصول، ويحصي المتغير wakeups عدد التنبيهات المعلقة (pending signals)، أي عدد الخيوط التي تنبّهت ولكنها لم تستأنف تنفيذها بعد، والسبب وراء استخدام wakeups هو التأكد من أن متغيرات تقييد الوصول الخاصة بك لديها الخاصية 3 المشروحة في كتاب The Little Book of Semaphores. يوفر المتغير mutex الوصول الحصري إلى لمتغيرين value و wakeups، المتغير cond هو المتغير الشرطي الذي تنتظره الخيوط إذا كانت تنتظر متغير تقييد الوصول. تمثل الشيفرة التالية شيفرة التهيئة للبنية Semaphore: Semaphore *make_semaphore(int value) { Semaphore *semaphore = check_malloc(sizeof(Semaphore)); semaphore->value = value; semaphore->wakeups = 0; semaphore->mutex = make_mutex(); semaphore->cond = make_cond(); return semaphore; } تطبيق متغير تقييد الوصول (Semaphore implementation) تطبيقي، يقول الكاتب، لمتغيرات تقييد الوصول باستخدام كائنات المزامنة POSIX والمتغيرات الشرطية كما يلي: void semaphore_wait(Semaphore *semaphore) { mutex_lock(semaphore->mutex); semaphore->value--; if (semaphore->value < 0) { do { cond_wait(semaphore->cond, semaphore->mutex); } while (semaphore->wakeups < 1); semaphore->wakeups--; } mutex_unlock(semaphore->mutex); } يجب على الخيط الذي ينتظر متغير تقييد الوصول أن يقفل كائن المزامنة قبل إنقاص قيمة المتغير value، وإذا أصبحت قيمة متغير تقييد الوصول سالبة سيتوقف الخيط حتى يصبح التنبه (wakeup) متاحًا، وطالما الخيط متوقف فإن كائن المزامنة غير مقفل، وبالتالي يمكن أن يتنبه (signal) خيطٌ آخر. شيفرة الدالة semaphore_signal هي: void semaphore_signal(Semaphore *semaphore) { mutex_lock(semaphore->mutex); semaphore->value++; if (semaphore->value <= 0) { semaphore->wakeups++; cond_signal(semaphore->cond); } mutex_unlock(semaphore->mutex); } يجب على الخيط مرة أخرى أن يقفل كائن المزامنة قبل زيادة قيمة المتغير value، وإذا كانت قيمة متغير تقييد الوصول سالبة فهذا يعني أن الخيوط منتظرة، وبالتالي يزيد تنبيه الخيط قيمة المتغير wakeups ثم ينبه المتغير الشرطي،وعند ذلك قد تتنبه أحد الخيوط المنتظرة ولكن يبقى كائن المزامنة مقفلًا حتى يفك الخيط المتنبه قفله، وعند ذلك أيضًا تعيد أحد الخيوط المنتظرة من الدالة cond_wait ثم تتحقق من أن التنبيه ما زال متاحًا، فإذا لم يكن متاحًا فإن الخيط يعود وينتظر المتغير الشرطي مرة أخرى، أما إذا كان التنبيه متاحًا فإن الخيط ينقص قيمة المتغير wakeups ويفك قفل كائن المزامنة ثم يغادر. قد يوجد شيء واحد ليس واضحًا في هذا الحل وهو استخدام حلقة do...while، هل يمكنك معرفة سبب عدم كونها حلقة while تقليدية؟ وما الخطأ الذي سيحدث؟ المشكلة مع حلقة while هي أنه قد لا يملك هذا التطبيق الخاصية 3، فمن الممكن أن يتنبه الخيط ثم يُشغّل ويلتقط تنبيهه الخاص. من المضمون مع حلقة do...while أن يلتقط أحد الخيوط المنتظرة التنبيه الذي أنشأه خيطٌ ما، حتى إذا شُغّل خيط التنبيه وحصل على كائن المزامنة قبل استئناف أحد الخيوط المنتظرة، ولكن اتضح أنه يمكن أن ينتهك التنبيه الزائف في الوقت المناسب (well-timed spurious wakeup) هذا الضمان. ترجمة -وبتصرّف- للفصل Semaphores in C من كتاب Think OS A Brief Introduction to Operating Systems
-
يمكن حل العديد من مشاكل التزامن (synchronization) البسيطة باستخدام كائنات المزامنة (mutexes)، ولكن يوجد مشكلة أكبر هي مشكلة منتج-مستهلك (Producer-Consumer problem) التي تُحل باستخدام أداة جديدة هي المتغير الشرطي (condition variable). طابور العمل (The work queue) تُنظَّم الخيوط في بعض البرامج ذات الخيوط المتعددة لتجري عدة مهام، وتتواصل هذه الخيوط مع بعضها البعض غالبًا عن طريق طابور (queue)، حيث تدعى الخيوط التي تضع بيانات في الطابور بالخيوط المنتجة (producers)، وتدعى الخيوط التي تأخذ بيانات من الطابور بالخيوط المستهلكة (consumers). يمكن أن يوجد خيطٌ يشغّل واجهة المستخدم الرسومية (graphical user interface وتختصر إلى GUI) للاستجابة لأحداث المستخدم في التطبيقات التي لديها واجهة مستخدم رسومية على سبيل المثال، ويمكن أن يوجد خيطٌ آخر يعالج طلبات المستخدم، حيث يمكن أن يضع خيطُ واجهة المستخدم الرسومية الطلبات في طابورٍ ثم يأخذ الخيط المقابل هذه الطلبات ويعالجها. تحتاج تطبيق طابور لدعم هذا التنظيم، بحيث يحافظ تطبيق الطابور على الخيوط (thread safe)، وهذا يعني أنه يستطيع كلا الخيطين (أو أكثر من خيطين في بعض الأحيان) الوصول إلى الطابور في نفس الوقت، وتحتاج أيضًا أن تعالج الحالات الخاصة مثل أن يكون الطابور فارغًا (empty) وأن يكون حجم الطابور منتهٍ عندما يمتلئ (full). سأبدأ، يقول الكاتب، بطابورٍ بسيط لا يحافظ على الخيوط ثم ترى كيف يكون ذلك خاطئًا وكيف يُصحَّح ذلك الخطأ. شيفرة هذا المثال موجودة في المجلد queue حيث يتضمن الملف queue.c التطبيق الأساسي للمخزَن الدائري circular buffer. تجد تعريف البنية Queue فيما يلي: typedef struct { int *array; int length; int next_in; int next_out; } Queue; array هو المصفوفة التي تتضمن عناصر الطابور وهي أعداد صحيحة (ints) في هذا المثال، ولكنها يمكن أن تكون بنى (structures) تتضمن أحداث المستخدم وعناصر العمل وغير ذلك. length هو طول المصفوفة، و next_in هو دليل (index) المصفوفة الذي يحدد مكان إضافة العنصر التالي في الطابور، أما next_out هو دليل العنصر التالي الذي يجب حذفه من الطابور. تخصص الدالة make_queue حيزًا للبنية Queue وتهيئ حقولها كما يلي: Queue *make_queue(int length) { Queue *queue = (Queue *)malloc(sizeof(Queue)); queue->length = length + 1; queue->array = (int *)malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; return queue; } تحتاج القيمة الابتدائية للمتغير next_out بعض الشرح، فبما أن الطابور فارغ مبدئيًا فلا وجود لعنصر تالٍ لحذفه، لذلك يكون المتغير next_out غير صالح (invalid)، وضبط next_out == next_in هي حالة خاصة تحدد أن الطابور فارغ، فيمكن كتابة ما يلي: int queue_empty(Queue *queue) { return (queue->next_in == queue->next_out); } يمكنك الآن إضافة عناصر إلى الطابور باستخدام الدالة queue_push: void queue_push(Queue *queue, int item) { if (queue_full(queue)) { perror_exit("queue is full"); } queue->array[queue->next_in] = item; queue->next_in = queue_incr(queue, queue->next_in); } إذا كان الطابور ممتلئًا فإن الدالة queue_push تطبع رسالة خطأ وتغادر، أما إذا كان الطابور غير ممتلئ فتدخِل الدالة queue_push عنصرًا جديدًا ثم تزيد قيمة المتغير next_in باستخدام الدالة queue_incr كما يلي: int queue_incr(Queue *queue, int i) { return (i + 1) % queue->length; } تعود قيمة الدليل i إلى الصفر عندما يصل الدليل إلى نهاية المصفوفة، وهذا هو المكان الذي نواجه فيه الجزء الصعب، فإذا واصلنا إضافة عناصر إلى الطابور فسيعود المتغير next_in ويلحق بالمتغير next_out، وإذا كان next_in == next_out ستستنتج بصورة غير صحيحة أن الطابور فارغ، لذلك يجب تعريف حالة خاصة أخرى لتحديد أن الطابور ممتلئ لتجنب ذلك: int queue_full(Queue *queue) { return (queue_incr(queue, queue->next_in) == queue->next_out); } حيث إذا واصلت زيادة المتغير next_in ليصل إلى قيمة المتغير next_out فهذا يعني أنك لا تستطيع إضافة عنصر آخر إلى الطابور بدون جعل الطابور يبدو فارغًا، لذلك يجب التوقف عن إضافة عناصر أخرى قبل نهاية الطابور بعنصر واحد (يجب أن تعرف أن نهاية الطابور يمكن أن تكون في أي مكان وليس بالضرورة عند نهاية المصفوفة). يمكن الآن كتابة الدالة queue_pop التي تحذف وتعيد العنصر التالي من الطابور كما يلي: int queue_pop(Queue *queue) { if (queue_empty(queue)) { perror_exit("queue is empty"); } int item = queue->array[queue->next_out]; queue->next_out = queue_incr(queue, queue->next_out); return item; } وإذا جربت سحب (pop) عنصر من طابور فارغ فستطبع الدالة queue_pop رسالة خطأ وتغادر. المستهلكون والمنتجون (Producers and consumers) تنشئ الآن بعض الخيوط لتصل إلى هذا الطابور، حيث شيفرة المنتج (producer) هي كما يلي: void *producer_entry(void *arg) { Shared *shared = (Shared *)arg; for (int i = 0; i < QUEUE_LENGTH - 1; i++) { printf("adding item %d\n", i); queue_push(shared->queue, i); } pthread_exit(NULL); } أما شيفرة المستهلك (consumer) هي: void *consumer_entry(void *arg) { int item; Shared *shared = (Shared *)arg; for (int i = 0; i < QUEUE_LENGTH - 1; i++) { item = queue_pop(shared->queue); printf("consuming item %d\n", item); } pthread_exit(NULL); } وشيفرة الخيط الأب الذي يبدأ الخيوط وينتظرها لتنتهي هي: pthread_t child[NUM_CHILDREN]; Shared *shared = make_shared(); child[0] = make_thread(producer_entry, shared); child[1] = make_thread(consumer_entry, shared); for (int i = 0; i < NUM_CHILDREN; i++) { join_thread(child[i]); } والبنية المشتركة التي تتضمن الطابور هي: typedef struct { Queue *queue; } Shared; Shared *make_shared() { Shared *shared = check_malloc(sizeof(Shared)); shared->queue = make_queue(QUEUE_LENGTH); return shared; } تمثل الشيفرة السابقة التي حصلت عليها حتى الآن بدايةً جيدة ولكن لديها بعض المشاكل هي: لا يحافظ الوصول إلى الطابور على الخيوط، حيث يمكن أن تصل خيوط متعددة إلى المتغيرات array و next_in و next_out في نفس الوقت، وهذا يترك الطابور تالفًا وفي حالة غير مستقرة. إذا جُدوِل الخيط المستهلك أولًا فسيجد الطابور فارغًا، وبالتالي يطبع رسالة خطأ وينتهي، لذلك من الأفضل أن يتوقف المستهلك حتى يصبح الطابور غير فارغ. وبالمثل يجب إيقاف المنتج إذا كان الطابور ممتلئًا. ستُحل المشكلة الأولى في الفقرة القادمة باستخدام Mutex، وستحل المشكلة الثانية في الفقرة التي بعدها باستخدام المتغيرات الشرطية. الإقصاء المتبادل (Mutual exclusion) يحافظ الطابور على الخيوط باستخدام كائن المزامنة (mutex)، حيث تضيف أولًا المؤشر Mutex إلى بنية الطابور: typedef struct { int *array; int length; int next_in; int next_out; Mutex *mutex; //-- هذا السطر جديد } Queue; ثم تهيئه في الدالة make_queue: Queue *make_queue(int length) { Queue *queue = (Queue *)malloc(sizeof(Queue)); queue->length = length; queue->array = (int *)malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; queue->mutex = make_mutex(); //-- جديد return queue; } ثم تضيف شيفرة التزامن إلى الدالة queue_push: void queue_push(Queue *queue, int item) { mutex_lock(queue->mutex); //-- جديد if (queue_full(queue)) { mutex_unlock(queue->mutex); //-- جديد perror_exit("queue is full"); } queue->array[queue->next_in] = item; queue->next_in = queue_incr(queue, queue->next_in); mutex_unlock(queue->mutex); //-- جديد } يجب قفل Mutex قبل التحقق إذا كان الطابور ممتلئًا أم لا، فإذا كان ممتلئًا يجب فك قفل Mutex قبل المغادرة، وإلا سيتركه الخيط مقفلًا فلا يستطيع أي خيطٍ آخر أن يستأنف عمله. شيفرة التزامن للدالة queue_pop هي: int queue_pop(Queue *queue) { mutex_lock(queue->mutex); if (queue_empty(queue)) { mutex_unlock(queue->mutex); perror_exit("queue is empty"); } int item = queue->array[queue->next_out]; queue->next_out = queue_incr(queue, queue->next_out); mutex_unlock(queue->mutex); return item; } لاحظ أن دوال Queue الأخرى والتي هي queue_full و queue_empty و queue_incr لا تحاول قفل كائن المزامنة، فيجب على كل خيط يستدعي هذه الدوال أن يقفل كائن المزامنة أولًا. أصبح الطابور محافظًا على الخيوط باستخدام الشيفرة الجديدة التي أضيفت، ولا يجب أن ترى أخطاء تزامن إذا شغلت هذه الشيفرة، ولكنك سترى أن الخيط المستهلك يغادر أحيانًا لأن الطابور فارغ، أو قد ترى الخيط المنتج يغادر بسبب أن الطابور ممتلئ أو كلا الأمرين معًا، وبالتالي الخطوة القادمة هي إضافة المتغيرات الشرطية (condition variables). المتغيرات الشرطية (Condition variables) المتغير الشرطي هو عبارة عن بينة بيانات مرتبطة بشرط (condition)، ويسمح المتغير الشرطي بإيقاف الخيوط حتى يتحقق الشرط أو تصبح قيمته true، فقد تتحقق الدالة thread_pop على سبيل المثال فيما إذا كان الطابور فارغًا أم لا، فإذا كان فارغًا تنتظر شرطًا هو (الطابور غير فارغ). وقد تتحقق الدالة thread_push أيضًا فيما إذا كان الطابور ممتلئًا، فإذا كان ممتلئًا تتوقف حتى يصبح غير ممتلئ. تعالج الشيفرة التالية الشرط الأول، حيث تضيف أولًا متغيرًا شرطيًا إلى البنية Queue: typedef struct { int *array; int length; int next_in; int next_out; Mutex *mutex; Cond *nonempty; //-- جديد } Queue; ثم تهيئه في الدالة make_queue: Queue *make_queue(int length) { Queue *queue = (Queue *)malloc(sizeof(Queue)); queue->length = length; queue->array = (int *)malloc(length * sizeof(int)); queue->next_in = 0; queue->next_out = 0; queue->mutex = make_mutex(); queue->nonempty = make_cond(); //-- جديد return queue; } إذا وجدت الطابور فارغًا في الدالة queue_pop لا تغادر بل استخدم المتغير الشرطي لتوقف التنفيذ: int queue_pop(Queue *queue) { mutex_lock(queue->mutex); while (queue_empty(queue)) { cond_wait(queue->nonempty, queue->mutex); //-- جديد } int item = queue->array[queue->next_out]; queue->next_out = queue_incr(queue, queue->next_out); mutex_unlock(queue->mutex); cond_signal(queue->nonfull); //-- جديد return item; } الدالة cond_wait معقدة، فوسيطها الأول هو المتغير الشرطي والشرط الذي يجب انتظاره في هذه الحالة هو (الطابور غير فارغ)، أما وسيطها الثاني هو كائن المزامنة الذي يحمي الطابور. يفك الخيط قفل كائن المزامنة ثم يتوقف عندما يستدعي الخيط الذي قفل كائن المزامنة الدالةَ cond_wait، وهذا شيء مهم جدًا. إذا لم تقفل الدالة cond_wait كائن المزامنة قبل التوقف فلن يستطيع أي خيطٍ آخر أن يصل إلى الطابور ولن تضاف أي عناصر أخرى إلى الطابور، وبالتالي قد يبقى الطابور فارغًا دائمًا، فيمكن أن يشغّل المنتج بينما يكون المستهلك متوقفًا عند nonempty. تبين الشيفرة التالية ما يحدث عنما يشغّل المنتج الدالة queue_push: void queue_push(Queue *queue, int item) { mutex_lock(queue->mutex); if (queue_full(queue)) { mutex_unlock(queue->mutex); perror_exit("queue is full"); } queue->array[queue->next_in] = item; queue->next_in = queue_incr(queue, queue->next_in); mutex_unlock(queue->mutex); cond_signal(queue->nonempty); //-- جديد } تقفل الدالة queue_push المتغير Mutex وتتحقق فيما إذا كان الطابور ممتلئًا أم لا، وعلى فرض أن الطابور ليس ممتلئًا حيث تضيف الدالة queue_push عنصرًا جديدًا إلى الطابور ثم تفك قفل المتغير Mutex، ولكن تقوم هذه الدالة بشيء آخر قبل أن تعيد شيئًا، حيث تنبّه (signals) المتغير الشرطي nonempty، ويحدد تنبيه (Signalling) المتغير الشرطي أن الشرط صحيح (true)، وليس لإشارة التنبيه أي تأثير إذا لم يوجد خيوطٌ تنتظر المتغير الشرطي. إذا وجد خيوط تنتظر المتغير الشرطي فيعود أحد هذه الخيوط إلى العمل ويستأنف تنفيذ الدالة cond_wait، ولكن يجب على الخيط الذي استأنف عمله أن ينتظر المتغير Mutex ويقفله مرة أخرى قبل أن ينهي تنفيذ الدالة cond_wait. عُد الآن إلى الدالة queue_pop وشاهد ما يحدث عندما ينهي الخيط تنفيذ الدالة cond_wait، حيث يعود الخيط مرة أخرى إلى بداية حلقة while ويتحقق من الشرط مرة أخرى. افترض أنه تحقق الشرط أي أن الطابور غير فارغ، فعندما يغادر الخيط المستهلك حلقة while، هذا يؤدي إلى شيئين: (1) تحقق الشرط أي يوجد عنصر واحد على الأقل في الطابور، و (2) قُفِل المتغير Mutex أي أن الوصول إلى الطابور آمن. تفك الدالة queue_pop قفل كائن المزامنة وتنتهي بعد حذف عنصر من الطابور، سأبين، يقول الكاتب، كيفية عمل شيفرة Cond ولكن يجب أولًا الإجابة عن سؤالين مهمين هما: لماذا توجد الدالة cond_wait ضمن حلقة while بدلًا من وجودها ضمن عبارة if، أي لماذا يجب التحقق من الشرط مرة أخرى بعد انتهاء تنفيذ الدالة cond_wait؟ السبب الرئيسي لإعادة التحقق من الشرط هو إمكانية اعتراض إشارة تنبيه، حيث افترض أن الخيط A ينتظر nonempty، ويضيف الخيط B عنصرًا إلى الطابور ثم ينبه nonempty، فيستيقظ الخيط A ويحاول قفل كائن المزامنة، ولكن قبل أن يقوم الخيط A بذلك، يأتي الخيط الشرير C ويقفل كائن المزامنة ويسحب عنصرًا من الطابور ثم يفك قفل كائن المزامنة، وبالتالي أصبح الطابور فارغًا الآن مرة أخرى، ولكن لا يتوقف الخيط A مرة أخرى، ويستطيع الخيط A قفل كائن المزامنة وينهي تنفيذ الدالة cond_wait، فإذا لم يتحقق الخيط A من الشرط مرة أخرى فقد يحاول سحب عنصر من طابورٍ فارغ، وقد يسبب ذلك خطأ. أما السؤال الثاني الذي يظهر عندما يتعلم الناس المتغيرات الشرطية هو: كيف يعرف المتغير الشرطي الشرطَ الذي يتعلق به؟ هذا السؤال مفهوم لأنه لا يوجد اتصال صريح بين بنية Cond والشرط المتعلق بها، حيث يكون الاتصال مضمّنًا في طريقة استخدامه، وهذه إحدى الطرق للتفكير في ذلك: فالشرط المتعلق ب Cond هو الشي الذي تكون قيمته خاطئة (false) عندما تستدعي الدالة cond_wait، وتكون قيمته صحيحة (true) عندما تستدعي الدالة cond_signal. ليس من الضروري تمامًا استدعاء الدالة cond_signal فقط عندما يكون الشرط صحيحًا، نظرًا لأن الخيوط يجب أن تتحقق من الشرط عند انتهاء تنفيذها للدالة cond_wait. إذا كان لديك سبب للاعتقاد بأن الشرط قد يكون صحيحًا فيمكنك استدعاء الدالة cond_signal كاقتراحٍ للتحقق من ذلك. تطبيق المتغير الشرطي (Condition variable implementation) البنية Cond التي استخدمت في الفقرة السابقة هي مغلّف لنوعٍ يدعى pthread_cond_t المعرّف في واجهة برمجة التطبيقات للخيوط POSIX. البنية Cond شبيهة جدًا بالبنية Mutex والتي هي مغلّفة للنوع pthread_mutex_t، حيث تعريف النوع Cond كما يلي: typedef pthread_cond_t Cond; تخصص الدالة make_cond حيزًا وتهيئ المتغير الشرطي وتعيد مؤشرًا: Cond *make_cond() { Cond *cond = check_malloc(sizeof(Cond)); int n = pthread_cond_init(cond, NULL); if (n != 0) perror_exit("make_cond failed"); return cond; } أما الدالتان المغلّفتان للدالتين cond_wait و cond_signal: void cond_wait(Cond *cond, Mutex *mutex) { int n = pthread_cond_wait(cond, mutex); if (n != 0) perror_exit("cond_wait failed"); } void cond_signal(Cond *cond) { int n = pthread_cond_signal(cond); if (n != 0) perror_exit("cond_signal failed"); } ترجمة -وبتصرّف- للفصل Condition variables من كتاب Think OS A Brief Introduction to Operating Systems
-
الخيط (Thread) هو نوع معين أو خاص من العمليات، حيث ينشئ نظام التشغيل حيز عناوين جديدًا عند إنشاء عملية، ويتضمن هذا الحيز جزء الشيفرة أو نص البرنامج (text segment) والجزء الساكن (static segment) وجزء الكومة (heap)، وينشئ نظام التشغيل أيضًا خيط تنفيذ (thread of execution) جديدًا يتضمن عداد البرنامج (program counter) وحالة عتاد أخرى واستدعاء المكدس. العمليات التي رأيتها لحد الآن هي عمليات ذات خيط وحيد (single-threaded) أي يوجد خيط تنفيذ واحد فقط يعمل في كل حيز عناوين، وستتعرف على العمليات ذات الخيوط المتعددة (multi-threaded)، أي التي تملك خيوطًا متعددة تعمل في نفس حيز العناوين. تتشارك كل الخيوط بنفس جزء الشيفرة ضمن العملية الواحدة أي أنها تشغّل نفس الشيفرة، ولكن تشغّل هذه الخيوط المختلفة أجزاءً مختلفة من تلك الشيفرة، وتتشارك الخيوط ضمن العملية الواحدة بنفس الجزء الساكن (static segment)، لذلك إذا غيّر أحد الخيوط متغيرًا عامًا (global variable) فإن بقية الخيوط ترى هذا التغيير، ويتشاركون أيضًا بالكومة (heap) لذلك تستطيع الخيوط التشارك بقطع الذاكرة المخصصة ديناميكيًا (dynamically-allocated chunks)، ولكن يكون لكل خيطٍ جزء المكدس الخاص به لذلك تستطيع الخيوط استدعاء دوالٍ دون التداخل مع بعضها البعض، ولا تصل الخيوط عادةً إلى المتغيرات المحلية لخيطٍ آخر، حيث لا تستطيع الوصول إليها في بعض الأحيان. إنشاء الخيوط (Creating threads) الخيوط القياسية الأكثر شيوعًا والمستخدمة مع C هي خيوط POSIX أو اختصارًا Pthreads. تعرّف خيوط POSIX القياسية نموذج خيط (thread model) وواجهةًَ (interface) لإنشاء الخيوط والتحكم بها، وتوفّر معظم نسخ UNIX تطبيقًا ل Pthreads. يشبه استخدامُ Pthreads استخدامَ معظم مكتبات لغة C حيث: تضمّن ملفات الترويسات (headers files) في بداية برنامجك. تكتب الشيفرة التي تستدعي دوالًا معرّفة باستخدام Pthreads. تربط (link) البرنامج عند تصريفه (compile) مع مكتبة Pthread. يضمِّن البرنامج ملفات الترويسات التالية: #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> أول اثنين من ملفات الترويسات السابقة هما تضمين لمكتبات قياسية، أما ملف الترويسات الثالث فيُستخدم من أجل Pthreads، ويُستخدم ملف الترويسات الرابع من أجل متغيرات تقييد الوصول (semaphores). يمكنك استخدام الخيار -l في سطر الأوامر لتصريف البرنامج مع مكتبة Pthread باستخدام الأداة gcc كما يلي: gcc -g -O2 -o array array.c -lpthread يصرّف الأمر السابق ملفًا مصدريًا يدعى array.c مع معلومات تنقيح الأخطاء (debugging info) والتحسين (optimization) ويربطه مع مكتبة Pthread ثم يولّد ملفًا تنفيذيًا يدعى array. إنشاء الخيوط (Creating threads) تدعى دالة Pthread التي تنشئ خيوطًا pthread_create، وتُظهر الدالة التالية كيفية استخدامها: pthread_t make_thread(void *(*entry)(void *), Shared *shared) { int n; pthread_t thread; n = pthread_create(&thread, NULL, entry, (void *)shared); if (n != 0) { perror("pthread_create failed"); exit(-1); } return thread; } الدالة make_thread هي دالة مغلّفة (wrapper) وكُتبت لجعل الدالة pthread_create سهلة الاستخدام ولتوفير التحقق من الأخطاء (error-checking). نوع القيمة المعادة من الدالة pthread_create هو pthread_t والذي يمكنك التفكير به كمعرّف (id) أو مِقبض (handle) للخيط الجديد. إذا نجح تنفيذ الدالة pthread_create فستعيد القيمة 0 وتعيد الدالة make_thread مقبض الخيط الجديد، وإذا ظهر خطأ فتعيد الدالة pthread_create شيفرة الخطأ وتطبع الدالة make_thread رسالة خطأ وتنتهي. Shared المعامل الثاني للدالة make_thread هو عبارة عن بنية (structure) عُرِّفت لتتضمن القيم المشتركة بين الخيوط، حيث يمكنك تعريف نوع جديد من خلال استخدام عبارة typedef كما يلي: typedef struct { int counter; } Shared; والمتغير المشترك الوحيد في هذه الحالة هو counter، وتخصص الدالة make_shared حيّزًا للبنية Shared وتهيئ محتوياتها كما يلي: Shared *make_shared() { Shared *shared = check_malloc(sizeof(Shared)); shared->counter = 0; return shared; } لديك الآن بنية بيانات مشتركة وإذا عدتَ إلى الدالة make_thread وتحديدًا المعامل الأول الذي هو عبارة عن مؤشر (pointer) إلى دالة، وتأخذ هذه الدالة مؤشر void وتعيد مؤشر void أيضًا. إذا أصبح نظرك مشوشًا بسبب صيغة تصريح هذا النوع فلست الوحيد في ذلك، على كل حال إن الهدف الأساسي من هذا المعامل هو أن يحدد للدالة مكان بدء تنفيذ الخيط الجديد، وتدعى هذه الدالة entry: void *entry(void *arg) { Shared *shared = (Shared *)arg; child_code(shared); pthread_exit(NULL); } يجب أن يُصرَّح عن معامل الدالة entry كمؤشر void، ولكنه في هذا البرنامج مؤشرٌ إلى بنية Shared لذلك يمكن تبديل نوعه (typecast) ثم تمريره إلى الدالة child_code التي تقوم بالعمل الحقيقي، حيث تطبع الدالة child_code قيمة المتغير المشترك counter ثم تزيد قيمته كما يلي: void child_code(Shared *shared) { printf("counter = %d\n", shared->counter); shared->counter++; } تستدعي الدالةُ entry الدالةََ pthread_exit بعد أن تنتهي الدالة child code وتعيد قيمةً، حيث يمكن أن تُستخدم الدالة pthread_exit لتمرير قيمة إلى الخيط الذي يُضم (join) مع الخيط الحالي، وبالتالي في هذه الحالة لا يبقى شيء للخيط الابن لعمله فتُمرَّر القيمة الخالية NULL، وأخيرًا تنشئ الشيفرة التالية الخيوط الأبناء (child threads) كما يلي: int i; pthread_t child[NUM_CHILDREN]; Shared *shared = make_shared(1000000); for (i = 0; i < NUM_CHILDREN; i++) { child[i] = make_thread(entry, shared); } NUM_CHILDREN هو ثابت وقت التصريف (compile-time constant) الذي يحدد عدد الخيوط الأبناء، و child هي مصفوفة مقابض الخيوط (thread handles). ضم الخيوط (Joining threads) إذا أراد خيطٌ انتظار خيطٍ آخر ليكتمل فإنه يستدعي الدالة pthread_join، وتجد فيما يلي الدالة المغلّفة للدالة pthread_join: void join_thread(pthread_t thread) { int ret = pthread_join(thread, NULL); if (ret == -1) { perror("pthread_join failed"); exit(-1); } } معامل الدالة المغلّفة هو مقبض الخيط الذي تنتظره ليكتمل، وعمل الدالة المغلّفة هو فقط استدعاء الدالة pthread_join والتحقق من النتيجة. يستطيع أي خيط أن يضم أي خيطٍ آخر، ولكن في النماذج الأكثر شيوعًا ينشئ الخيط الأب (parent thread) كل الخيوط الأبناء ويضمها (join). تجد فيما يلي الشيفرة التي تنتظر الخيوط الأبناء بها: for (i = 0; i < NUM_CHILDREN; i++) { join_thread(child[i]); } تنتظر هذه الحلقات أحد الخيوط الأبناء في كل مرة وذلك حسب ترتيب إنشائها، ولا يوجد ضمان أن تكتمل الخيوط الأبناء في هذا الترتيب ولكن تعمل هذه الحلقة بصورة صحيحة حتى في حال لم يحدث ذلك، فإذا تأخر أحد الخيوط الأبناء فيجب أن تنتظر الحلقة، ويمكن أن تكتمل الخيوط الأبناء الأخرى خلال وقت الانتظار هذا، حيث لا يمكن أن تنتهي هذه الحلقة إلا في حال اكتمال جميع الخيوط الأبناء. يمكنك الاطلاع على المثال ضمن counter/counter.c ثم تصريفه وتشغيله كما يلي: $ make counter gcc -Wall counter.c -o counter -lpthread $ ./counter فعند تشغيله مع 5 خيوط أبناء سينتج الخرج التالي: counter = 0 counter = 0 counter = 1 counter = 0 counter = 3 وسينتج خرج آخر عندما تشغله على حاسوبك، وإذا شغلته مرة أخرى سينتج خرج مختلف أيضًا، فماذا يحدث؟ الأخطاء المتزامنة (Synchronization errors) مشكلة البرنامج السابق أن الخيوط الأبناء تستطيع الوصول إلى المتغير المشترك counter بدون تزامن، لذلك تستطيع عدة خيوط قراءة نفس قيمة المتغير counter قبل أن يزيد أي خيطٍ قيمته. يمكن أن تشرح سلسلة الأحداث التالية الخرج الذي حصلت عليه سابقًا: Child A reads 0 Child B reads 0 Child C reads 0 Child A prints 0 Child B prints 0 Child A sets counter=1 Child D reads 1 Child D prints 1 Child C prints 0 Child A sets counter=1 Child B sets counter=2 Child C sets counter=3 Child E reads 3 Child E prints 3 Child D sets counter=4 Child E sets counter=5 يمكن أن تُقاطَع الخيوط في أماكن مختلفة في كل مرة تشغّل فيها البرنامج، أو قد يختار المجدول خيوطًا مختلفة ليشغّلها، لذلك ستكون سلسلة الأحداث والنتائج مختلفة. افترض أنك تريد فرض بعض الترتيب، أي مثلًا تريد أن يقرأ كل خيط قيمةً مختلفة للمتغير counter ثم يزيدها، وبالتالي تُظهر قيمة المتغير counter عدد الخيوط التي نفّذت الدالة child_code، ويمكنك استخدام كائن المزامنة (mutex) لتطبيق ذلك، حيث كائن المزامنة (mutex) هو عبارة عن كائن (object) يضمن حدوث إقصاء متبادل (mutual exclusion) لكتلة من الشيفرة، أي ينفّذ خيطٌ واحد فقط كتلة الشيفرة في نفس الوقت. كتبتُ، يقول الكاتب، نموذجًا يدعى mutex.c يوفر كائنات المزامنة، ستجد فيما يلي نسخةً من الدالة child_code التي تستخدم كائن المزامنة لتأمين تزامن الخيوط: void child_code(Shared *shared) { mutex_lock(shared->mutex); printf("counter = %d\n", shared->counter); shared->counter++; mutex_unlock(shared->mutex); } حيث يجب على كل خيط أن يقفل (lock) كائن المزامنة قبل أن يصل أي خيطٍ آخر إلى المتغير المشترك counter، وهذا يؤدي إلى حظر كل الخيوط الأخرى من الوصول إلى هذا المتغير. افترض أن الخيط A قفل كائن المزامنة وهو في منتصف الدالة child_code، فإذا وصل الخيط B ونفّذ الدالة mutex_lock يتوقف تنفيذ الخيط B. ينفّذ الخيط A الدالة mutex_unlock عندما ينتهي، وبالتالي يسمح للخيط B متابعة تنفيذه، أي تنفّذ الخيوط الدالة child_code على التوالي بحيث ينفّذها خيطٌ واحدٌ فقط في نفس الوقت، وبالتالي لا يتعارض أي خيط مع الخيوط الأخرى، وإذا شغّلت الشيفرة مع 5 خيوط أبناء سينتج: counter = 0 counter = 1 counter = 2 counter = 3 counter = 4 وهذا هو المطلوب. يجب إضافة كائن المزامنة Mutex إلى البنية Shared لكي يعمل هذا الحل بالصورة الصحيحة: typedef struct { int counter; Mutex *mutex; } Shared; وتهيئته في الدالة make_shared: Shared *make_shared(int end) { Shared *shared = check_malloc(sizeof(Shared)); shared->counter = 0; shared->mutex = make_mutex(); //-- هذا السطر جديد return shared; } كائن المزامنة (Mutex) تعريفي، يقول الكاتب، ل Mutex هو مغلّف لنوعٍ يدعى pthread_mutex_t وهو معرّفٌ في واجهة برمجة التطبيقات للخيوط POSIX، ولإنشاء كائن مزامنة POSIX يجب تخصيص حيزٍ للنوع pthread_mutex_t ثم استدعاء الدالة pthread_mutex_init. إحدى مشاكل واجهة برمجة التطبيقات هذه أن النوع pthread_mutex_t يتصرف كبنية (structure)، لذلك إذا مررته كوسيط سينشئ نسخةً تجعل كائن المزامنة يتصرف بصورة غير صحيحة، ويمكنك تجنب ذلك من خلال تمرير النوع pthread_mutex_t باستخدام عنوانه. تجعل الشيفرة التي كتبتها، يقول الكاتب، الأمور أسهل من خلال تعريف نوعٍ هو النوع Mutex الذي هو عبارة عن اسم للنوع pthread_mutex_t يمكن قراءته بطريقة أسهل: #include <pthread.h> typedef pthread_mutex_t Mutex; ثم تعريف دالةٍ هي الدالة make_mutex التي تخصص حيّزًا لكائن المزامنة وتهيئته: Mutex *make_mutex() { Mutex *mutex = check_malloc(sizeof(Mutex)); int n = pthread_mutex_init(mutex, NULL); if (n != 0) perror_exit("make_lock failed"); return mutex; } القيمة المعادة هي مؤشر يمكن أن تمرره كوسيط دون أن يسبب نسخًا غير مرغوبة. الدوال التي تستخدم لقفل وفك قفل كائن المزامنة هي دوالٌ مغلّفة بسيطة لدوال POSIX: void mutex_lock(Mutex *mutex) { int n = pthread_mutex_lock(mutex); if (n != 0) perror_exit("lock failed"); } void mutex_unlock(Mutex *mutex) { int n = pthread_mutex_unlock(mutex); if (n != 0) perror_exit("unlock failed"); } ترجمة -وبتصرّف- للفصل Threads من كتاب Think OS A Brief Introduction to Operating Systems