عبد اللطيف ايمش

الأعضاء
  • المساهمات

    946
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • Days Won

    63

كل منشورات العضو عبد اللطيف ايمش

  1. يملك لينُكس أنظمةً صلبةً وأدواتٍ عمليةً لإدارة الأجهزة والعتاد، بما في ذلك أجهزة التخزين. سنشرح في درسنا هذا كيفية تمثيل تلك الأجهزة في لينكس وكيف يمكن تحويل المساحات الخام إلى مساحاتٍ تخزينيةٍ قابلةٍ للاستخدام على الخواديم. ما هو التخزين الكتلي؟ التخزين الكتلي (Block storage) هو اسمٌ آخر لما تدعوه نواة لينُكس بالجهاز الكتلي (block device). والجهاز الكتلي هو قطعةٌ من العتاد التي يمكن استعمالها لتخزين البيانات، مثل أقراص التخزين الصلبة الاعتيادية (HDD) أو أقراص التخزين ذات الحالة الثابتة (solid state drive أي SSD) أو وحدات الذاكرة الفلاشية (flash memory stick) …إلخ. تلك تسمى «أجهزةً كتليةً» لأنَّ النواة تتعامل مع العتاد على أنَّه كتلٌ ثابتةُ الحجم، أو قطعٌ من المساحة. بشكلٍ أساسي، التخزين الكتلي هو ما نعتبر أنَّه التخزين الاعتيادي المتواجد في الحواسيب، والذي –بعد ضبطه وإعداده– سيعمل على أنَّه جزءٌ من شجرة نظام الملفات الحالية، وستتمكن من قراءة أو كتابة المعلومات منه وإليه بسلاسة. ما هي الأقسام في الأقراص؟ الأقسام (partitions) هي طريقةٌ لتقسيم جهاز التخزين إلى وحدات قابلة للاستخدام أصغر حجمًا، إذ أنَّ القسم هو جزءٌ من جهاز التخزين الذي يمكن معاملته بطريقةٍ مشابهةٍ لطريقة التعامل مع القرص نفسه. يسمح لك التقسيم بتجزئة المساحة المتوافرة لديك واستخدام كل قسمٍ لغرضٍ مختلف. وهذا يعطي المستخدمين الكثير من المرونة سامحًا لهم بتجزئة النظام لديهم لتحديثه بسهولة أو لتثبيت أكثر من نظام تشغيل أو لإنشاء مساحة تبديل (swap) أو لاستخدام أنظمة ملفات خاصة على تلك الأجزاء. وصحيحٌ أنَّ الأقراص يمكن أن تُهيّئ (format) وتُستعمَل دون تقسيم، إلا أنَّ بعض أنظمة التشغيل تتوقع وجود «جدول أقسام» (partition table) حتى ولو كان هنالك قسمٌ وحيدٌ في القرص؛ لذا يُستحسَن ويُنصَح عمومًا إنشاء أقسام في الأجهزة الجديدة لضمان مرونة استخدامها مهما كانت الظروف. MBR أم GPT؟ من المهم عند تقسيم القرص معرفة ما هي «صيغة» التقسيم التي ستستعملها، وسينتهي بك المطاف بالاختيار بين MBR (اختصار للعبارة Master Boot Record) و GPT (اختصار للعبارة GUID Partition Table). MBR هو نظام التقسيم التقليدي الذي بقي مُستخدَمًا طيلة 30 عامًا الماضية؛ ونتيجةً لعمره الطويل، فهو يعاني من بعض المحدوديات التي لها وقعٌ كبير. فمثلًا لا يمكننا استخدامه للأقراص التي حجمها التخزيني أكبر من 2 تيرابايت، ولا يمكن إنشاء أكثر من أربعة أقسام رئيسية (primary partitions)؛ ونتيجةً لذلك نضبط عادةً القسم الرابع على أنَّه «قسمٌ ممتد» (extended partition) الذي سيُنشَأ داخله «أقسامٌ منطقيةٌ» (logical partitions). وهذا يسمح لك بتجزئة آخر قسم لإنشاء أي عدد إضافي من الأقسام. GPT على الجانب الآخر هو تخطيط حديث للتقسيم الذي يحاول حلّ بعضًا من المشكلات الموروثة من MBR، الأنظمة التي تستعمل GPT يمكن فيها إنشاء أي عددٍ نريده من الأقسام، لكن هذا محدودٌ عادةً بالقيود المفروضة من نظام التشغيل نفسه. إضافةً إلى ما سبق، لا تعاني أقراص GPT من محدوديات في حجم القرص، ومعلوماتُ جدولِ الأقسامِ متوافرةٌ في مواضعَ عدَّة مما يحميها من التلف. يمكن أيضًا كتابة سجل «protective MBR» الذي يخبر الأدوات التي تتعامل مع أقراص MBR فقط أنَّ القرص قيد الاستخدام حاليًا. من الأفضل في أغلبية الحالات اختيار GPT ما لم يمنعك نظام تشغيلك أو الأدوات التي ستستعملها من ذلك. التهيئة وأنظمة الملفات صحيحٌ أنَّ نواة لينكس يمكنها التعرف على الأقراص الخام (raw disks) إلا أنَّ القرص لا يمكن أن يُستعمل كما هو؛ وإنما يجب تهيئته (format) قبل استعماله. التهيئة هي عملية كتابة نظام ملفات إلى القرص وتجهيزه لإجراء عمليات لها علاقة بالملفات. أما نظام الملفات (filesystem) فهو النظام الذي يُنظِّم البيانات ويتحكم بكيفية كتابة المعلومات إلى القرص والحصول على المعلومات من القرص؛ فبدون نظام الملفات لن تتمكن من استخدام جهاز التخزين لأيّة عمليات لها علاقة بالملفات. هنالك الكثير من صيغ أنظمة الملفات المختلفة، والتي تتباين فيما بينها بامتلاكها لميزاتٍ مختلفة، بما في ذلك دعمُ أنظمة التشغيل. لكن بشكلٍ أساسي، تمنح جميع أنظمة الملفات للمستخدم تمثيلًا مألوفًا للقرص، لكن الميزات التي يدعمها كل نظام ملفات وآلية سماحه للمستخدم بالتعامل وإجراء عمليات على القسم مختلفةٌ تمامًا. بعضٌ من أشهر أنظمة الملفات المتاحة للينكس: Ext4: أشهر نظام ملفاتٍ افتراضيٍ في لينكس هو Ext4 (اختصار للعبارة the fourth version of the extended filesystem) وهو نظام ملفات ذو سجل (journaled)، ومتوافق مع الأنظمة القديمة، ومستقر للغاية، ومدعومٌ دعمًا واسعًا وتتوافر له أدواتٌ كثيرة؛ وهو خيارٌ جيدٌ إن لم تكن لديك احتياجاتٌ خاصة. XFS: نظام ملفات XFS متخصصٌ بموضوع الأداء وبالملفات كبيرة الحجم، وستتم تهيئته بسرعة وأداؤه جيد عند التعامل مع الملفات الكبيرة ومع الأقراص الضخمة. ولديه ميزة أخذ snapshot من نظام الملفات. يعتمدXFS على تسجيل البيانات الوصفية (metadata journaling) فقط والذي يختلف عن تسجيل البيانات الوصفية والبيانات نفسها؛ وهذا يؤدي إلى سرعةٍ في الأداء، لكن قد يؤدي في الوقت نفسه إلى حدوث تلفٍ في البيانات في حال حدوث فقدان غير متوقع للطاقة الكهربائية. Btrfs: نظام ملفات Btrfs هو نظامٌ حديثٌ له ميزاتٌ كثيرة وهو من نمط copy-on-write بدل كونه journaled، هذه المعمارية تسمح لبعض وظائف إدارة الحجوم (volume management) بأن تُدمَج مع طبقة نظام الملفات، بما في ذلك snapshots، والنسخ (cloning)، والحجوم (volumes) …إلخ. لكن نظام ملفات Btrfs ما يزال يواجه مشاكل عند التعامل مع الأقراص الممتلئة. هنالك بعض الجدال الدائر حول جاهزية نظام الملفات هذا لاستعماله في بيئات العمل الإنتاجية، وينتظر الكثير من مدراء الأنظمة أن يصل Btrfs إلى درجةً أكبر من الدعم والانتشار. ZFS: هو نظام ملفاتٍ من نمط copy-on-write وفيه مدير حجوم (volume manager) بمجموعة متينةٍ ومستقرةٍ من الميزات. يحتوي أيضًا على ميزاتٍ ممتازةٍ لضمان سلامة البيانات المُخزَّنة عليه، ويمكنه التعامل مع أقسام ذات مساحات تخزينية كبيرة، وفيه ميزات إدارة الحجوم التقليدية مثل snapshotting و cloning، ويمكن فيه تنظيم الحجوم (volumes) إلى مصفوفة RAID أو مصفوفات شبيهة بمصفوفات RAID لغرض إنشاء نظام تخزيني مستقر وذي أداءٍ عالٍ. أما عن وضع دعم ZFS في لينكس، فيجدر بالذكر أنَّ له تاريخٌ جدليٌ نتيجةً لمخاوف من رخصة استعماله. أصبحت توزيعة أوبنتو توفِّر وحدة ثنائية (binary module) من وحدات النواة للتعامل معه، وتضع توزيعة دبيان الشيفرة المصدرية له في مستودعاتها، لكن لم يُحدَّد دعمه في بقية التوزيعات بعد. كيف يُدير لينُكس أقراص التخزين ملفات التخزين الموجودة في ‎/dev من المعروف أنَّ كل شيء في لينُكس (تقريبًا) يُمثَّل بملف؛ بما في ذلك الأجهزة العتادية مثل أجهزة التخزين والتي تُمثَّل في النظام كملفات في مجلد ‎/dev، وعمومًا تبدأ أسماء الملفات التي تُمثِّل أجهزة التخزين بالحرفين sd أو hd متبوعَين بحرفٍ آخر؛ فمثلًا: أوّل قرص تخزين على الخادوم يكون اسمه شبيهًا بالاسم ‎/dev/sda. تملك الأقسام على تلك الأجهزة ملفاتٍ هي الأخرى ضمن مجلد ‎/dev، ممثلةً بإضافة رقم القسم إلى نهاية اسم الجهاز، فعلى سبيل المثال، أوّل قسمٍ في القرص المذكور في المثال السابق سيكون على الشكل ‎/dev/sda1. وعلى الرغم من أنَّ ملفات الأجهزة ‎/dev/sd*‎ و ‎/dev/hd*‎ هي الطريقة التقليدية للإشارة إلى الأجهزة والأقسام، إلا أنَّ هنالك جانبٌ سلبيٌ لاستخدام تلك المسارات، إذ أنَّ نواة لينكس تُقرِّر ما هو الجهاز الذي سيحصل على الاسم الفلاني عند كل إقلاعٍ للنظام، لذا قد يودي ذلك إلى تضاربات حيث تتغير أسماء عقد الأجهزة. حلٌ التفافيٌ على هذه المشكلة هو احتواء المجلد ‎/dev/disk على مجلدات فرعية تَنظُمُ الأقراص والأقسام بطرائق ثابتةٍ لا تتغير؛ وتلك المجلدات تحتوي على وصلاتٍ رمزيةٍ (symbolic links) التي تُنشَأ عند الإقلاع لتشير إلى ملفات ‎/dev/[sh]da*‎ الصحيحة. تُسمى تلك الوصلات وفقًا لنوع طريقة التنظيم والموضَّحة باسم المجلد (على سبيل المثال، ستسمى الوصلات حسب «لُصيقة» [label] القسم في مجلد ‎/dev/disk/by-partlabel). ستُشير تلك الوصلات دومًا إلى الأجهزة الصحيحة، لذا يمكننا استخدامها كمُعرِّفات ثابتة لأجهزة التخزين. بعض (أو جميع) المجلدات الآتية موجودةٌ ضمن مجلد ‎/dev/disk: by-label: أغلبية أنظمة الملفات لها آلية لإعطاء لُصيقة سامحةً بإسناد أسماء يُحدِّدها المستخدم إلى القرص أو القسم؛ يحتوي هذا المجلد على وصلاتٍ مسماةٍ تِبعًا للُصيقات التي كتبها المستخدم. by-uuid: المُعرِّفات العالمية الفريدة (اختصارًا UUIDs) هي سلسلةٌ طويلةٌ فريدةٌ من الحروف والأرقام التي يمكن أن تُستعمَل كمُعرِّف لوسيط التخزين. تلك المُعرِّفات ليست سهلة القراءة من البشر، لكنها فريدة، وستبقى ثابتةً حتى لو بدَّلنا الخادوم أو النظام؛ لذا من الأفضل استخدام مُعرِّفات UUID للإشارة إلى أجهزة التخزين التي قد تُنقَل بين الأنظمة بين الحين والآخر، لأنَّ من غير المحتمل أن يحدث تضاربٌ في الأسماء. by-partlabel و by-partuuid: توفِّر جداول GPT لافتاتٍ ومعرِّفات UUID خاصة بها، والتي يمكن أن تُستعمَل أيضًا بغرض تمييز الأقسام، وتعمَل بنفس طريقة عَمَل المجلدين السابقين، إلا أنَّها تستعمل مُعرِّفات خاصة بجداول GPT. by-id: يحتوي هذا المجلد على وصلات مُولَّدةٌ أسماؤها من الرقم التسلسلي لجهاز التخزين وللجهاز الموصول إليه، وتلك الأسماء غير ثابتة تمامًا، لأنَّ طريقة وصل الجهاز إلى النظام قد تُغيّر من اسم وصلات المجلد by-id. by-path: وكما في مجلد by-id، تعتمد الوصلات الموجودة في هذا المجلد على أجهزة التخزين الموصول إلى النظام نفسه، وتُبنى تلك الوصلات اعتمادًا على طريقة تمثيل العتاد الذي يُستعمَل للوصول إلى وسيط التخزين في نظام التشغيل. وللوصلات الموجودة في هذا المجلد نفس الإشكاليات التي تواجهها تلك الموجودة في by-id لأنَّ وصل جهاز التخزين إلى منفذٍ آخر قد يؤدي إلى تغيير هذه القيمة. يُفضَّل عادةً استخدام by-label أو by-uuid إذ أنَّ تمثيلها للأقراص ثابتٌ. وصل أجهزة التخزين الكتلية تُستعمَل ملفات الأجهزة الموجودة في ‎/dev للتواصل مع التعريف القادر على التعامل مع الجهاز المُعيّن في النواة؛ لكن يجب إنشاء طبقة تُمكّننا من معاملة الجهاز كوسيط تخزين يحتوي على مساحةٍ تخزينيةٍ قابلةٍ للاستعمال. في لينكس وغيره من الأنظمة الشبيهة بيونكس (Unix-like)، يُمثَّل نظام التشغيل كشجرة ملفات موحّدة بغض النظر عن عدد الأجهزة الفيزيائية التي تُستعمَل فيه؛ ولكي يُستعمَل نظامُ ملفاتٍ أو قرصٌ في النظام، فيجب ربطه بمكانٍ ما في تلك الشجرة. عملية «الوصل» (mounting) تعني ربط قسم مُهيئ أو قرص إلى مجلدٍ موجودٍ ضمن نظام ملفات لينُكس؛ ومن ثم سنتمكّن من الوصول إلى محتويات القرص أو القسم من ذاك المجلد. توصل الأقراص أو الأقسام دومًا في مجلدات فارغة مخصصة لهذا الغرض (الوصل في مجلد غير فارغ يعني أنَّنا لن نتمكن من الوصول إلى محتويات المجلد حتى نفصل [unmount] القرص أو القسم). هنالك الكثير من خيارات الوصل التي يمكن ضبطها لتعديل سلوك الأجهزة الموصولة، على سبيل المثال، يمكن أن يوصل القرص بوضع «القراءة فقط» لضمان عدم تغيير محتوياته. ينصح معيار هيكلة نظام الملفات باستخدام ‎/mnt أو مجلدٍ فرعيٍ داخله لوصل أنظمة الملفات مؤقتًا. إذا كان وصلك للأقراص مؤقتًا فهذا أفضل مكانٍ لوصلها؛ لكن المعيار لم يُقدِّم أيّة اقتراحات لمكان وصل وسائط التخزين الدائمة، لذا يمكنك وصلها أينما تشاء؛ لكن في أغلبية الحالات توصل وسائط التخزين الدائمة في مجلد ‎/mnt أو في مجلدٍ فرعيٍ داخله. جعل الوصل دائمًا باستخدام ‎/etc/fstab تنظر أنظمة لينكس إلى ملفٍ يدعى ‎/etc/fstab (أي filesystem table) الذي يُحدِّد ما هي أنظمة الملفات التي يجب وصلها أثناء الإقلاع. توصل أنظمة الملفات غير الموجودة في ذاك الملف تلقائيًا (باستثناء تلك المُعرَّفة بملفات systemd‏ ‎.mount، التي ليست شائعةً حاليًا). ملف ‎/etc/fstab بسيطٌ جدًا، فكلُ سطرٍ فيه يُمثِّل نظام ملفاتٍ مختلفٍ الذي يجب أن يوصل؛ يُحدِّد هذا السطر ما هو الجهاز الكتلي، وما هي نقطة الوصل (mount point) التي سيُربَط إليها، وما هي صيغة القسم، وما هي خيارات الوصل، بالإضافة إلى معلوماتٍ أخرى. إدارة متقدمة لأجهزة التخزين صحيحٌ أنَّ أغلبية الاستخدامات البسيطة لا تحتاج إلى بُنى إدارية إضافية، إلا أنَّنا سنحصل على أداءٍ عالٍ ومرونة وقدرة على تعويض تلف الأقراص عند استخدامنا لطرائق الإدارة المتقدمة. ما هي مصفوفات RAID؟ مصفوفات RAID ترمز إلى «redundant array of independent disks»، وهي تقنية إدارة تخزين تسمح لك بتجميع الأجهزة مع بعضها لإدارتها كجهاز تخزين وحيد له ميزاتٌ إضافيةٌ. خصائص مصفوفة RAID تعتمد على مستوى RAID المستعمل، والذي يُعرِّف ما هو عدد الأقراص في المصفوفة وكيف تتعلق ببعضها. للمستوى المختار تأثيرٌ على الأداء والقدرة على تعويض تلف الأقراص، بعض المستويات الشائعة هي: RAID 0: يعتمد هذا المستوى على «توزيع البيانات» (drive striping) والذي يعني أنَّه عندما تُكتَب البيانات إلى المصفوفة، فستُقسَّم وتوزَّع على الأقراص الموجودة في المصفوفة، وهذا يعني زيادةً في الأداء لأنَّ بالإمكان الكتابة على أو القراءة من أكثر من قرص في آنٍ واحد. الجانب السلبي لهذا المستوى هو عندما يحدث عطبٌ في أحد الأقراص فسنفقد جميع المعلومات في كامل المصفوفة، لعدم وجود قرص يحتوي على معلوماتٍ كافيةٍ لإعادة بناء المصفوفة. RAID 1: مستوى RAID 1 يعتمد على إنشاء نسخة مماثلة للبيانات (drive mirroring). فأي شيء يُكتَب إلى مصفوفة RAID 1 سيُكتَب على عدِّة أقراص؛ الميزة الأساسية لهذا المستوى هو القدرة على تعويض الأقراص، مما يعني أنَّ البيانات ستبقى موجودةً في المصفوفة حتى لو حدث عطبٌ في أحد الأقراص؛ وذلك لأنَّ عدِّة أقراص تحتوي على نفس البيانات، لكن في المقابل سيؤدي ذلك تقليل المساحة التخزينية للمصفوفة إلى النصف. RAID 5: مستوى RAID 5 يوزِّع البيانات على عدِّة أقراص بشكلٍ شبيهٍ بمستوى RAID 0؛ لكن هذا المستوى يتضمن تكرار توزيع جزء من البيانات على قرصٍ آخر، وهذا يعني أنَّه لو حدثت مشكلة في أحد الأقراص، فستتمكن بقية الأقراص من إعادة بناء المصفوفة باستخدام البيانات المُكرَّرة التي يمكن تجميعها معًا. تلك البيانات المكررة كافية لإعادة بناء قرصٍ وحيد، وهذا يعني أنَّ المصفوفة ستتمكن من إعادة بناء نفسها إن حدث عطبٌ في قرصٍ وحيدٍ فقط. يؤدي تكرار توزيع البيانات إلى تقليل المساحة التخزينية لكامل المصفوفة إلى ما يعادل المساحة التخزينية لقرصٍ وحيد. RAID 6: يملك المستوى RAID 6 نفس خصائص RAID 5، إلا أنَّه يُكرِّر جزءًا من البيانات على قرصين، وهذا يعني أنَّ مصفوفات RAID 6 ستتمكن من إعادة بناء نفسها إن فقدت قرصين؛ وستتأثر المساحة التخزينية لكامل المصفوفة بتكرار البيانات، وهذا يعني أنَّ المساحة التخزينية القابلة للاستخدام لكامل المصفوفة مساويةٌ للمساحة التخزينية لقرصين. RAID 10: هذا المستوى هو دمجٌ بين المستويين 1 و 0، فبدايةً ستُنشَأ مجموعتين متماثلتين (mirrored) من المصفوفات؛ ثم ستُوزَّع البيانات عليها، وهذا يُنشِئ مصفوفةً لها نفس القدرة التعويضية لكن أداءها عالٍ. لكن هذا المستوى يتطلب عددًا كبيرًا نسبيًا من الأقراص، والمساحة التخزينية القابلة للاستخدام هي نصف مساحة جميع الأقراص. ما هو LVM؟ LVM، أو مدير الحجوم المنطقية (Logical Volume Manager) هو نظامٌ يُشكِّل «طبقةً» تعلو البنية الفيزيائية لوسائط التخزين وخصائصها لتوفير مرونة عالية وقدرات كبيرة. يسمح لك LVM بإنشاء مجموعة من الأجهزة الفيزيائية وإدارتها كما لو أنَّها قرصٌ وحيد، ويمكنك تقسيم المساحة عند الحاجة إلى «حجوم منطقية» (logical volumes) والتي تعمل عمل الأقسام. يعمل LVM بناءً على الأقسام العادية، ويحّل الكثير من المحدوديات الموجودة في الأقسام التقليدية، فعلى سبيل المثال، يمكنك بكل سهولة عند استخدام حجوم LVM أن توسِّع الأقسام وتُنشِئ أقسامًا تمتد على أكثر من قرص، وتأخذ نسخ snapshot من الأقسام، وتنقل الحجوم إلى أقراص فيزيائية مختلفة. يجدر بالذكر أنَّ بالإمكان استخدام LVM مع مصفوفات RAID ذات الأداء والوفرة العالية لتوفير نظام إدارة مرن. ما هي الخطوة القادمة؟ إذا كان لديك جهاز تخزين جديد تريد استخدامه مع نظام لينكس، فألقِ نظرةً على هذه المقالة التي ستُرشِدُكَ إلى طريقة تقسيم وتهيئة ووصل نظام الملفات الجديد الذي ستُنشِئه. يجب أن تكفيك المقالة السابقة لأغلبية حالات الاستخدام حيث سيكون همّك الرئيسي هو زيادة القدرات التخزينية. لتعلم المزيد عن مهام إدارة أجهزة التخزين الأساسية، فانظر إلى هذه المقالة ترجمة -وبتصرّف- للمقال An Introduction to Storage Terminology and Concepts in Linux لصاحبه Justin Ellingwood
  2. يهرع الكثير من المبتدئين إلى طرائق تحديد مواقع العناصر في CSS معتقدين أنها ستحل لهم جميع المشاكل التي يواجهونها في تخطيط الصفحة، لكن هذا ليس صحيحًا بالمطلق: هنالك جوانب أخرى في CSS مسؤولةٌ عن تخطيط الصفحة. وصحيحٌ أنَّ طرائق تحديد المواقع العناصر لها دورٌ لتلعبه في تخطيط الصفحة، لكن من الأحسن أن تعرف كيف ومتى عليك استخدام مختلف أنماط تحديد المواقع، عوضًا عن محاولة تجريبها لربما «حلّت» لك مشكلتك! طريقة static لتحديد مواقع العناصر افتراضيًا، يملك كل عنصر في صفحتك القاعدة position: static مطبقةً عليه، ولهذا السبب لن نحتاج إلى التصريح عن هذه الطريقة، إلا إذا كان ذلك ضروريًا لإلغاء تأثير خاصية position أخرى قد ورثها العنصر من غيره. الكلمة static لا تعني أنَّ العنصر سيبقى في مكانه في الصفحة، وفي الواقع أرى أنَّ هذه الكلمة غير دقيقة وكان يجب استخدام كلمة أخرى (مثل fluid) بدلًا عنها. طريقة تحديد مواقع العناصر الافتراضية تعني أنَّ العناصر لن تتداخل وتظهر فوق بعضها، أي أنَّ كل عنصر «سيدفع» العناصر الأخرى بعيدًا عنه، مستجيبًا إلى قياس ودقة والنسبة بين طول وعرض الجهاز الذي يعرض صفحة الويب. لنأخذ مثالًا بسيطًا لمحتوى صفحة: <p><img src="assets/images/pericles.jpg" style="float: left;" alt="Bust of Pericles"> Pericles was a prominent statesman, orator, and naval general of Athens during the city-states's <q>Golden Age</q>, from 448BCE until his death in 429. Pericles was a promoter of the arts (particularly plays), architecture (it was under his patronage that the Parthenon was built), and the principles of democracy, but he was also an instigator of war: Pericles is widely held to be responsible for maneuvering Athens into the disastrous Peloponnesian War with Sparta.</p> حجز كل عنصرٍ –في المثال السابق– مساحةً خاصةً به، فلن تظهر الصورة فوق النص، وسيبتعد النص قليلًا عن الصورة. تغيير قياس نافذة المتصفح سيُسبِّب بتضييق عرض الصفحة، وستلتف أسطر الفقرة حول الصورة وستدفع أي محتوى أدناها إلى الأسفل. وهذا جيد، لأنَّ الصفحة ستتأقلم مع أيّ قياس للشاشة وأي نسبة عرض إلى ارتفاع وأي دقة، ولن تظهر أيّة عناصر فوق بعضها. لاحظ أنَّ قاعدة «لا شيء سيتداخل، وكل شيء سينساب حول بقية العناصر» هي المبدأ الرئيسي لطريقة position: static إلا أنَّ هنالك بعض الاستثناءات. فمثلًا سيظهر النص فوق صورة الخلفية، ويمكن أن نلغي انسيابية العناصر بتحديد عرض ثابت على عناصر div الحاوية لبقية العناصر، ويمكن أن تتداخل العناصر أو تُزاح من الصفحة إذا طبقنا هامشًا (margin) سلبيًا عليها. لكن في الحالة العامة ستُطبَّق قاعدة static كما هي. العناصر المُطبَّق عليها القاعدة position: static –سواءً بتصريحنا بذلك، أو افتراضيًا– لا يمكن أن تملك الخاصيات التي سنتحدث عنها في الأقسام التالية (وهي top و left و bottom و right). العناصر التي لها القيمة static للخاصية position يمكن أن تُحرَّك فقط بتعديل قيم الخاصيتَين margin أو padding، أو عبر تعديل موقعها في شيفرة HTML. وهذا أمرٌ مقبولٌ بين المطورين وبسيطٌ وسهل التطبيق في أغلبية التصاميم. طريقة relative لتحديد مواقع العناصر من المهم ملاحظة أنَّ تطبيق القاعدة position: relative على أحد العناصر لن يُغيّر شيئًا بمفردها، فسيبقى العنصر يسلك سلوك العناصر ذات القيمة static لخاصية position (كما في القسم السابق). لكن القيمة relative قد أعطتنا وصولًا إلى الخاصيات top و left و bottom و right. فعند تطبيق القاعدة position: relative بالإضافة إلى إحدى الخاصيات السابقة، فسيحدث أمران: سيَخرُجُ العنصر من مكانه في المستند، لكن ستبقى المساحة الفارغة المحجوزة له باقيةً (كما لو كان static). سيُزاح العنصر بمقدارٍ مساوٍ للقيم المنسدة إلى الخاصيات top و left و bottom و right، نسبةً إلى موقعه الأصلي (static). ما يزال بالإمكان تطبيق الخاصية float على العناصر ذات القاعدة position: relative. سنُعدِّل في المثال السابق ليصبح كما يلي: <p><img src="assets/images/pericles.jpg" style="position: relative; top: 2em; right: 4em;" alt="Bust of Pericles"> Pericles was a prominent statesman, orator, and naval general of Athens during the city-states's <q>Golden Age</q>, from 448BCE until his death in 429. Pericles was a promoter of the arts (particularly plays), architecture (it was under his patronage that the Parthenon was built), and the principles of democracy, but he was also an instigator of war: Pericles is widely held to be responsible for maneuvering Athens into the disastrous Peloponnesian War with Sparta.</p> كما لاحظت، ستُزاح الصورة بمقدار 2em إلى الأسفل انطلاقًا من أعلى موقعها الأصلي، و 4em من اليمين. لاحظ كيف بقيت المساحة محجوزةً للعنصر الأصلي، وكيف يتلف النص حولها، وأنَّ الصورة ستتداخل مع بعض الأسطر النصية. ربما أسهل طريقة لكي تفهم فيها position: relative هي أنَّ تتخيل أنَّها تستخدم «لإزاحة» العناصر لكنك لا ترغب بالتأثير على تخطيط بقية الصفحة. وذلك لأنَّ المساحة المعطاة إلى العنصر الأصلي ما تزال موجودةً. إذ يمكنك بكل سهولة إعطاء قيم إلى خاصيات top و left و bottom و right (يمكن أيضًا استخدام القيم السلبية) دون أن تقلق من تأثير ذلك على بقية عناصر الصفحة. طريقة absolute لتحديد مواقع العناصر المطورون الذين يملكون المعلومات الكافية في CSS لكي يقعوا في مشاكل، مع المصممين المهووسين بأن تكون تصاميمهم دقيقة جدًا، سيجنحون إلى استخدام position: absolute استخدامًا مفرطًا؛ ويجادلون قائلين «بإمكاننا وضع أي شيء في صفحة الويب في المكان الذي نريده». لكنهم للأسف يغفلون عدِّة نقط مهمة، وسيقعون حتمًا في حالتين اللتين ستؤديان إلى حدوث «متاهة» مقعدة في الصفحة. لكن دعنا أولًا نرى ماذا تفعل قاعدة position: absolute بصفحتنا. ستصبح الشيفرة كما يلي: <p><img src="assets/images/pericles.jpg" style="absolute; top: 0; left: 30px;" alt="Bust of Pericles"> Pericles was a prominent statesman, orator, and naval general of Athens during the city-states's <q>Golden Age</q>, from 448BCE until his death in 429. Pericles was a promoter of the arts (particularly plays), architecture (it was under his patronage that the Parthenon was built), and the principles of democracy, but he was also an instigator of war: Pericles is widely held to be responsible for maneuvering Athens into the disastrous Peloponnesian War with Sparta.</p> عند تطبيق قاعدة position: absolute، فستفقد الخاصتان float و margin تأثيرهما، لذا أزلتُهما. تؤدي القيمة absolute إلى نزع الصورة من مكانها في المستند تمامًا، أي ستؤخذ وتُرفَع إلى أعلى المستند الذي سيظهر تحتها. باختصار: ستسلك صفحة الويب سلوكًا مشابهًا لسلوكها كما لو أنَّ الصورة غير موجودة من الأساس. لماذا إذًا يستعمل الكثيرون position: absolute؟ لأنَّنا نستطيع تحديد موضع العنصر –عند استخدام absolute– انطلاقًا من الزاوية العليا اليسرى للعنصر الحاوي لها، وهو العنصر body في حالتنا. قد تبدو لك position: absolute جذابةً، حيث يبدو أنَّها تعدك بوضع العناصر في مكانها بدقة شديدة. وهذا مغرٍ جدًا للمصممين التقليديين الذين يصممون تصاميم لسطح المكتب أو للطباعة، والمعتادين على التحكم بمكان كل شيء في صفحات A4، والذي لا يرون داعٍ للتصميمات المتجاوبة. لكنهم يرفضون أن يلاحظوا بضع نقاط: صفحات الويب ليست كالورق ذي القياس المعياري. فالشاشات والمتصفحات والأجهزة تملك أحجام ونسب ودقة مختلفة. واستخدام absolute لوضع العناصر في الصفحة يعني افتراض مجموعة من المتغيرات عن جهاز المستخدم، مما يؤثِّر سلبًا في مرونة الويب. بعد أن تُطبِّق position: absolute على أحد العناصر، فستجد نفسك تُطبِّق نفس القاعدة على كل العناصر الأخرى. وذلك لأنَّ position: absolute سينتزع العنصر من المستند، ويجب علينا تعديل موضع بقية العناصر للتأقلم مع ذلك ولضمان عدم تداخل العناصر التي لا تريدها أن تتداخل. وهذا سيؤدي إلى إنشاء قواعد CSS معقدة والتي لن تعمل كما يجب عند إضافة محتوى جديد إلى الصفحة (أكرِّر أنَّ الويب ليس صفحةً مطبوعةً، حيث تُعدَّل المحتويات وتُضاف إضافات بين الحين والآخر، ويجب أن يكون تصميمك مرنًا كفايةً للاستجابة إلى تلك التعديلات). واستخدام position: absolute يجعل التعديلات على الصفحة تأخذ وقتًا طويلًا وجهدًا كبيرًا. لماذا نستخدم إذًا position: absolute من الأساس؟ حسنًا، إذا استخدمنا absolute استخدامًا حكيمًا، فيمكن أن نستفيد منها لتداخل العناصر المنفصلة التي كانت لتُدمَج في صورةٍ وحيدةٍ. على سبيل المثال، لنقل أنَّك تريد الإضافة على المقالة السابقة ووضع صور أخرى من العصر الذهبي لأثينا. أي لديك عدِّة صور (إسخيلوس وأفلاطون وألكيبيادس)، وتريد أن تضعها على الجانب الأيمن لمستندك، وتريدها أن تتداخل مع بعضها. أحد الحلول هي تعديل الصور باستخدام فوتوشوب، بدمجها مع بعضها في صورةٍ وحيدة، لكن هذا سيمنعك من تعديل ترتيبها ومحاذاتها والتباعد بينها لاحقًا، وعليك حينها العودة إلى ملف فوتوشوب لإجراء تعديلاتك ثم إعادة التصدير ورفع الصورة من جديد. لكن بدلًا من كل ما سبق، لنحاول الإبقاء على الصور معزولةً ونضعها داخل عنصر <div>. شيفرة HTML هي: <div id="greek-figures"> <img src="aeschylus-bust.jpg" alt="Marble bust of Aeschylus" id="aeschylus"> <img src="plato-bust.jpg" alt="Marble bust of Plato" id="plato"> <img src="alcibiades-bust.jpg" alt="Marble bust of Alcibiades" id="alcibiades"> </div> نعلم أنَّ لهذه الصور نفس الأبعاد، لذا لن نحتاج إلى تحديد خاصيات height و width لكل واحدة على حدة. وإنما سنجعل ذلك ضمن أنماط CSS: div#greek-figures { float: right; } div#greek-figures img { height: 150px; width: 150px; position: absolute; } إذا حاولتَ عرض الصفحة الآن، فستجد أنَّ عنصر <div> قد تضائل، وظهرت صورةٌ وحيدةٌ فقط وهي خارجة عن مكانها. هل لديك أيِّة فكرة عن السبب؟ …[تريّث قليلًا وفكِّر بالسبب قبل إكمال القراءة]… الجواب: لقد طُبِّقَت القاعدة position: absolute على الصورة، لذا تم انتزاعها من مكانها في الصفحة، ولم تعد تستطيع «دفع» العناصر التي حولها. أما عنصر div بعد وضع الخاصية float له فسيحاول تحديد عرضه عبر محتوياته التي بداخله؛ لكن المحتوى (أي الصور) لها القيمة absolute، فلن تُحتَسَب، والصور هي المحتوى الوحيد الموجود في العنصر <div>، أي أنَّ العنصر <div> ليس له عرض! في النهاية، ستحاول كل صورة أن تضع نفسها داخل عنصر <div> في الزاوية العليا اليسرى، وهذا يعني أنَّ الصور ستتكدس فوق بعضها. لاحظ أنَّ آخر صورة داخل العنصر div ستكون في الأعلى (وسنتحدث عن هذا الأمر في درسٍ لاحق). لنحاول الآن حلّ المشاكل السابقة بتعديل CSS: body p { text-align: justify; } div#greek-figures { float: right; width: 250px; height: 450px; margin-left: 2em; } div#greek-figures img { height: 150px; width: 150px; position: absolute; } img#plato { top: 155px; right: 15px; } img#alcibiades { top: 290px; } (وفرنا خاصية height لعنصر div لأنَّ الصور التي موضعها absolute لن تساهم في توفير ارتفاع للعنصر؛ وبدون ارتفاع فلن تجد الأسطر النصية شيئًا لتلتف حوله. أضفنا بقية الخاصيات مثل text-align والهوامش لإظهار الصفحة بشكل جميل). سيعمل ما سبق كما ينبغي، لكنك ستتكشف شيئًا غريبًا. إذا عدَّلتَ الخاصية right لصورة أفلاطون إلى left، فلن تحصل على ما كنتَ تتوقعه. فبدلًا من قياس الموضع من الحاوية، فستُنسَب الصورة نفسها إلى أكبر حاوية وهي العنصر <body>. يمكننا الالتفاف على هذه المشكلة بإضافة قاعدة في أنماط CSS: div#greek-figures { float: right; width: 250px; height: 450px; margin-left: 2em; position: relative; } وستكون النتيجة النهائية هي: إذا كان العنصر الذي له القيمة absolute للخاصية position موجودًا ضمن عنصرٍ آخر تُطبَّق عليه القاعدة position: relative، فستُقاس إحداثيات العنصر انطلاقًا من الزاوية العليا اليسرى للحاوية التي يقع فيها؛ وإلا فستُقاس الإحداثيات انطلاقًا من الزاوية العليا اليسرى من العنصر body. عمومًا، إذا كنتَ تُصرّ على استخدام position: absolute فأنصحك بوضع عدِّة عناصر (التي لها القاعدة position: absolute) في «حاوية» (إما عنصر <div> عادي أو حتى <canvas>). مما يسمح لك بنقلها مع العناصر الموجودة داخلها دون مشاكل. ترجمة -وبتصرّف- للمقالات CSS Positioning: static, the default CSS Positioning: relative, the underappreciated CSS Positioning: absolute, the overused لصاحبها Dudley Storey
  3. تأتيني عادةً أسئلةٌ عمّا إذا كانت شبكةٌ متعددة المواقع تعمل على ووردبريس هي خيارٌ مناسبٌ لمواقع الشركات التي لديها أقسامٌ متنوعةٌ ذات طابعٍ مختلف. ويكون جوابي عادةً هو «نعم»، يمكن لشبكةٍ متعددة المواقع فعل ذلك. لكن ليس من الضروري إنشاء موقعٍ منفصلٍ لكل قسمٍ من أقسام شركتك (حتى لو استعملتَ شبكةً متعددة المواقع تعتمد على ووردبريس)؛ فإذا أردتَ مشاركة المحتوى غير الخاص بقسمٍ معيّن، أو كانت «هوية» (identity) أقسام شركتك تتشابه كثيرًا، أو إذا كان عندك موقعٌ مستقل ولا ترغب بتحويله إلى شبكةٍ متعددة المواقع، فهنالك دومًا طريقةٌ للالتفاف على هذه الإشكالية دون تفعيل الشبكة متعددة المواقع. سأريك في هذا المنشور طريقة فعل ذلك باستخدام «التصنيفات المخصصة» (custom taxonomies). حيث سنُنشِئ تصنيفًا باسم «division» الذي يمكن إسناد المنشورات والصفحات إليه، لذا ستتمكن من تحديد ما هي الأقسام التي يجب وضع كل منشور أو صفحة فيها. ثم سنُنشِئ ملف قالب لذاك التصنيف، مما يعني إمكانية عرض المحتوى الموجود في كل قسم بالشكل الذي تريده. سنحتاج إلى كتابة بعض الشيفرات لإنشاء إضافة (plugin) وإنشاء ملف في قالبك، لكن الشيفرة لن تكون صعبةً، وسنستخدم «قالب ابن» تابع للقالب الافتراضي Twenty Sixteen لكن يمكنك استخدام هذه الطريقة على أيّ قالب تشاء. سنُنشِئ أيضًا ملفًا لتسجيل (register) التصنيف المخصص، ومن الأفضل فعل ذلك عبر إضافة، لكيلا تخسر الشيفرة التي تُنشِئ التصنيف المخصص في حال تغيّر قالب مستقبلًا. لنبدأ بالعمل. تجهيز القالب الابن قبل أن نبدأ، يجب أن نملك: موقعًا تطويريًا أو مخصصًا للتجريب يعمل على ووردبريس، والذي يُمثِّل نسخةً من موقع الشركة الذي لديك. لكن أحذِّرك أن تفعل ذلك على موقعٍ إنتاجي، وإنما ارفع الملفات إلى الموقع الإنتاجي بعد أن تتأكد أنَّها تعمل دون مشاكل. محرِّر شيفرات. أحد القوالب، الذي يمكن أن يكون قالبًا خاصًا بشركتك، أو قالب ابن للقالب Twenty Sixteen (كالذي أستعمله)، إذا كنتَ ستستخدم قالب ابن فتأكَّد أنَّ قالب Twenty Sixteen مثبّتٌ لديك. ابدأ بإنشاء قالب ابن وتفعيله، إلا أنّي لن أشرح هذا بالتفصيل، وإنما سأحيلك إلى درسٍ آخر. هذه هي الشيفرة التي سأستخدمها في ملف style.css في القالب الابن: /* Theme Name: WPMU DEV Taxonomy for Company Website Divisions Theme URI: https://github.com/rachelmccollin/wpmu-taxonomy-company-divisions Description: Theme to support WPMU DEV post on custom menu items Author: Rachel McCollin Author URI: http://rachelmccollin.co.uk/ Template: twentysixteen Version: 1.0 */ @import url("../twentysixteen/style.css"); ربما تلاحظ من الشيفرة السابقة أنني رفعتُ الملفات الخاصة بهذا الدرس على GitHub، يمكنك أن تنزلها من هناك وتستعملها بدلًا من إنشائها يدويًا. أنشَأتُ أيضًا موقعًا تجريبيًا. بعد أن تفعِّل القالب الابن، فستلاحظ أنَّه يبدو كقالب Twenty Sixteen الافتراضي: تسجيل التصنيف المخصص في ووردبريس الخطوة التالية هي تسجيل التصنيف المخصص عبر إنشاء إضافة. إلا أنَّك تستطيع إضافة الشيفرة إلى ملف functions.php في قالبك، لكن المشكلة هي أنَّ هذه الشيفرة ستُحذف (وسيختفي التصنيف المخصص الجديد) في حال حدَّثتَ قالبك في المستقبل. أنشِئ ملفًا جديدًا في مجلد الإضافات plugins (الموجود في مجلد wp-content) وأعطهِ اسمًا مناسبًا، وافتحه وأضف إليه التعليقات الآتية: <?php /** * Plugin Name: WPMU DEV Register Division Taxonomy * Plugin URI: https://github.com/rachelmccollin/wpmu-taxonomy-company-divisions * Description: Registers a 'division' taxomy for use in your copmany website. * Version: 1.0 * Author: Rachel McCollin * Author URI: http://rachelmccollin.co.uk */ أضف الآن هذه الدالة لتسجيل التصنيف المخصص: function wpmudev_register_taxonomy() { $labels = array( 'name' => __( 'Divisions' ), 'singular_name' => __( 'Division' ), 'search_items' => __( 'Search Divisions' ), 'all_items' => __( 'All Divisions' ), 'edit_item' => __( 'Edit Divisions' ), 'update_item' => __( 'Update Divisions' ), 'add_new_item' => __( 'Add New Division' ), 'new_item_name' => __( 'New Division Name' ), 'menu_name' => __( 'Divisions' ), ); $args = array( 'labels' => $labels, 'hierarchical' => true, 'sort' => true, 'args' => array( 'orderby' => 'term_order' ), 'show_admin_column' => true ); register_taxonomy( 'division', array( 'post', 'page' ), $args); } add_action( 'init', 'wpmudev_register_taxonomy' ); الشيفرة السابقة ستُسجِّل تصنيفًا باسم division وتعطي لافتاتٍ مناسبةً له وتضبط عنوانًا سيظهر في القائمة… وتحدِّد الشيفرة السابقة أيضًا أنَّنا نستطيع إضافة هذا التصنيف إلى المنشورات والمقالات وذلك عبر تمرير الوسيط array( 'post', 'page' ) إلى دالة register_taxonomy()‎. فعِّل الإضافة في موقعك، ويجب أن تملك الآن وصولًا إلى تصنيفٍ جديد عندما تحاول تحرير الصفحات والمنشورات: يمكنك الآن إنشاء عناصر ضمن التصنيف الجديد تُمثِّل أقسام شركتك، ثم تُسنِد إليها المنشورات والصفحات. عرض أقسام شركتك في الموقع لقد أنشأتُ بعض المحتوى من منشوراتٍ وصفحاتٍ وأسندته إلى أقسامٍ مختلفة. هذه بضعة منشوراتٍ من التي أضفتُها: أنشأتُ أيضًا بعض الصفحات للأقسام، وأنشأتُ أيضًا صفحاتٍ عامةً: يمكنك الآن إضافة جميع صفحاتك وأقسامك إلى قائمة التنقل الأساسية في موقعك، لكن لا تُضف المنشورات، لأنها ستُعرضَ في صفحات الأرشيف. لقد فعلتُ ما سبق في صفحة «Menus» (القوائم) في لوحة التحكم: ستُنشِئ ووردبريس صفحة أرشيف تلقائيًا لكل قسم من أقسام شركتك، وستعرض تلك الصفحات باستعمال أكثر صفحات القالب تحديدًا والموجودة في قالبك (وفقًا لهيكلية ملفات القوالب). هذه هي صفحة الأرشيف لتصنيف «Research and Development»: قامت ووردبريس بعملها على أتم وجه، فوضعت المنشورات والصفحات المُسنَدَة إلى التصنيف. لكنها تعرضها بترتيبٍ زمني كما قد تتوقع، لكنني أفضِّل عرض جميع الصفحات أولًا متبوعةً بالمنشورات، ولفعل ذلك سأُنشِئ صفحة أرشيف للتصنيف المُخصص وأستعمل فيها نسخةً مخصصةً من حلقة الدوران في ووردبريس (يسمونها the loop). إنشاء صفحة أرشيف للتصنيفات المخصصة لعرض صفحة أرشيف التصنيفات المخصصة كما نشاء، فعلينا إنشاء ملف قالب باسم taxonomy-divsion.php ولنفعل ذلك بنسخ ملف قالب موجود مسبقًا ثم تعديله. إذا كان في قالب ملفٌ باسم archive.php فأنشِئ نسخةً منه وسمِّها taxonomy-divsion.php، أما إذا لم يكن في قالبك الملف السابق، فانسخ الملف index.php. ولأنني أعمل مع قالب Twenty Sixteen فأُنشِئ نسخةً من ملف archive.php وأضعه في مجلد القالب الابن باسم taxonomy-divsion.php. علينا أولّا تعديل التعليقات في بداية الملف لكي تصف بدقة محتويات هذا الملف: <?php /** * The template for displaying division archive pages */ اعثر الآن على الشيفرة المسؤولة عن حلقة التكرار، وهي تبدو كالآتي في حال نسختَها من قالب Twenty Sixteen: <?php // Start the Loop. while ( have_posts() ) : the_post(); /* * Include the Post-Format-specific template for the content. * If you want to override this in a child theme, then include a file * called content-___.php (where ___ is the Post Format name) and that will be used instead. */ get_template_part( 'template-parts/content', get_post_format() ); // End the loop. Endwhile; الشيفرة السابقة تستدعي ملفًا من Twenty Sixteen باسم content.php، سنبقي على الشيفرة السابقة، لكننا سنُشغِّلها مرتين: مرة للمنشورات ومرة للصفحات. عدِّل حلقة التكرار في ملف القالب لتصبح كما يلي: <?php // Start the first Loop - pages. while ( have_posts() ) : the_post(); $posttype = get_post_type( get_the_ID() ); if ( $posttype == 'page' ) { get_template_part( 'template-parts/content', get_post_format() ); } // End the loop. endwhile; rewind_posts(); // Start the second Loop - posts. while ( have_posts() ) : the_post(); $posttype = get_post_type( get_the_ID() ); if ( $posttype == 'post' ) { get_template_part( 'template-parts/content', get_post_format() ); } // End the loop. Endwhile; الشيفرة السابقة ستؤدي إلى استدعاء حلقة التكرار مرتين، لكنها ستطلب الصفحات والمنشورات من قاعدة البيانات مرةً واحدةً فقط، وهذا أفضل من استخدام WP-Query لإنشاء طلبية جديدة. سنتحقق في بداية الحلقة فيما إذا كان «نوع المنشور» (post type) مساوٍ للقيمة page وفي حال تحقق الشرط فسنعرض الصفحة، ثم سنُعيد الكرّة مرةً أخرى للمنشورات العادية ذات النوع post. احفظ الملف السابق وستجد أنَّ صفحة الأرشيف أصبحت تعرض الصفحات أولًا ثم المنشورات: هذه هي شيفرة ملف القالب كاملةً: <?php /** * The template for displaying division archive pages */ get_header(); ?> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php if ( have_posts() ) : ?> <header class="page-header"> <?php the_archive_title( '<h1 class="page-title">', '</h1>' ); the_archive_description( '<div class="taxonomy-description">', '</div>' ); ?> </header><!-- .page-header --> <?php // Start the first Loop - pages. while ( have_posts() ) : the_post(); $posttype = get_post_type( get_the_ID() ); if ( $posttype == 'page' ) { get_template_part( 'template-parts/content', get_post_format() ); } // End the loop. endwhile; rewind_posts(); // Start the second Loop - posts. while ( have_posts() ) : the_post(); $posttype = get_post_type( get_the_ID() ); if ( $posttype == 'post' ) { get_template_part( 'template-parts/content', get_post_format() ); } // End the loop. endwhile; // Previous/next page navigation. the_posts_pagination( array( 'prev_text' => __( 'Previous page', 'twentysixteen' ), 'next_text' => __( 'Next page', 'twentysixteen' ), 'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentysixteen' ) . ' </span>', ) ); // If no content, include the "No posts found" template. else : get_template_part( 'template-parts/content', 'none' ); endif; ?> </main><!-- .site-main --> </div><!-- .content-area --> <?php get_sidebar(); ?> <?php get_footer(); ?> تنسيق أقسام الشركة بشكلٍ مختلف أصبح لدينا الآن ملف قالب يعرض صفحات ومنشورات أقسم الشركة بالطريقة التي نرغب بها، وحان الوقت الآن لجعل صفحات الأقسام تختلف بصريًا عن بعضها بإضافة بعض التنسيق إليها. يمكنك أن تُنسِّق أقسام موقعك كما تشاء، وربما ستُنسِّقها أكثر مما سأريك إياه في هذا الدرس، إلا أنني سأريك كيف تغيّر ألوان بعض أجزاء الصفحات والمنشورات وصفحات الأرشيف لكل قسم، لجعلها تتميز عن بعضها. يمكنك أن تفعل ذلك في صفحة الأنماط التابعة للقالب الابن (أو في صفحة الأنماط في القالب الأساسي إن لم تكن تستعمل قالب ابن). افتح ملف style.css وأضف القواعد الآتية إليه: .term-research-development .page-header { border-top: 4px solid #d8a518; } .term-research-development .page-title { color: #d8a518; } .term-operations .page-header { border-top: 4px solid #5674A0; } .term-operations .page-title { color: #5674A0; } .term-sales .page-header { border-top: 4px solid #FE6763; } .term-sales .page-title { color: #FE6763; } .term-sales .page-header { border-top: 4px solid #78D400; } .term-sales .page-title { color: #78D400; } هذا سيُضيف تنسيقًا لترويسات صفحات الأرشيف باستهداف الأنماط (classes) المُطبَّقة على العنصر body وذلك اعتمادًا على التصنيفات التي استخدمتها. ستحتاج إلى تعديل القيم السابقة بما يتوافق مع أسماء أقسام شركتك، يمكنك أن ترى أسماء الأصناف المولّدة تلقائيًا عبر تفحص شيفرة HTML في صفحة أرشيف القسم في موقعك، وستكون مرتبطةً بالعنصر body. استعملتُ اللون الأصفر في صفحة تصنيف «Research and Development» لتمييزها: يمكنك إضافة المزيد إلى صفحة الأنماط، فربما تريد تنسيق المنشورات التابعة لمدونتك العامة بشكلٍ يختلف عن تنسيق منشورات بقية الأقسام الأخرى، ويمكنك أيضًا تنسيق الصفحات والمنشورات التابعة لمختلف الأقسام بأشكالٍ متنوعة. يمكنك أيضًا تنسيق قائمة التنقل الرئيسية لكي تُطابِق تنسيق بقية الصفحة. أي أنَّ خياراتك ليست محدودة، ومن الممكن أن تجعل مظهر صفحات أقسام شركتك مختلفةً عن بعضها تمامًا. الخلاصة باستخدام التقنيات التي شرحناها في هذا الدرس، يمكننا إنشاء موقع لشركة فيه أقسامٌ مختلفة، وتعرض تلك الأقسام المحتوى المتعلق بها فقط، ونستطيع استخدام فئات CSS التي تُضيفها ووردبريس إلى عنصر body لتنسيق تلك الأقسام بشكلٍ مختلف. يمكنك أن تكمل المشوار في تنسيق الصفحات، وذلك بإضافة صور أو خلفيات أو يمكنك تغيير الخطوط وذلك عبر صفحة الأنماط. وتستطيع أيضًا إنشاء ملف قالب مختلف لكل قسم، وذلك باستعمال هيكلية ملفات القوالب استعمالًا صحيحًا لتعرف طريقة تسمية الملفات. كل ما سبق يعني أنَّك إذا كنتَ تعمل على موقعٍ موجودٍ مسبقًا ولم تشأ إنشاء مواقع مخصصة لكل قسم من أقسام شركتك، فيمكن لموقع ووردبريس وحيد أن يضفي طابعًا خاصًا لكل قسم من أقسام الشركة. ترجمة -وبتصرّف- للمقال How to Create a Custom Taxonomy for Departments or Divisions on a Company WordPress Siteلصاحبته Rachel McCollin.
  4. "أريد تعلم البرمجة لكنني لا أعرف من أين أبدأ!" هذه هي أكثر عبارة تتردد على سمعي من حديثي العهد بالبرمجة، إذ يأتيني هذا السؤال مرارًا وتكرارًا؛ وفي كل مرة أحاول أن أجيب عنه في سياقه، أجد أنني أضيف معلومات جديدة على إجاباتي السابقة، لذا قررت كتابة هذا المقال بعنوان "تعلم البرمجة" لعله يفيد الراغبين في تعلم تطوير التطبيقات في بدء رحلتهم مع البرمجة. جدول المحتويات حرصًا على تنظيم المقالة ولتسهيل الوصول إلى القسم الذي تريده بسهولة، سنذكر هنا جدول المحتويات باختصار: ما هي البرمجة؟ لماذا تتعلم البرمجة؟ ما عليك معرفته لتصبح مبرمجًا الأدوات اللازمة للبدء في تعلم البرمجة لماذا هناك العديد من لغات البرمجة؟ مفاهيم البرمجة مصادر تعلم البرمجة تطوير واجهات المستخدم تطوير الواجهات الخلفية تعلم تطوير تطبيقات الجوال تطوير الألعاب تطوير الأنظمة المدمجة تطوير تطبيقات سطح المكتب كيفية اختيار لغة البرمجة التي تناسبك نصائح لتعلم البرمجة ما هي البرمجة؟ البرمجة هي عملية تقسيم مهمة معينة يراد تنفيذها عبر الحاسوب إلى أجزاء صغيرة ومترابطة وقابلة للتنفيذ بأوامر بسيطة. بعد ذلك، يجري كتابة هذه الأوامر والتعليمات بإحدى لغات البرمجة، والتي هي وسيلة للتخاطب مع الحاسوب. إليك المثال العملي التالي الذي يشرح ماهية البرمجة: إن كنت تتوقع زيارة صديق لك اليوم، واتصل بك ليقول لك: "أنا واقف بجانب الحديقة ولا أعرف كيف أصل إلى منزلك". أنت عادةً تمر كل يوم من جانب الحديقة وتعرف الطريق بينها وبين منزلك شبرًا بشبر. برأيك هل ينفع إن قلت له: "منزلي معروف وقريب من الحديقة وأنا كل يوم أمر من جانبها"؟ لا، بالتأكيد. تحتاج إلى أن تقسِّم المشكلة إلى أجزاء تمثل خطوات بسيطة يستطيع صديقك فهمها وتنفيذها. مثلًا، أخبره أن ينفذ الأوامر التالية: "سر إلى الأمام عشرة أمتار" ثم "اتجه إلى اليمين" ثم "سر إلى نهاية الشارع" ثم "اتجه إلى اليسار". أخبره بعد ذلك: "عُدَّ الأبنية الموجودة على اليسار حتى تصل إلى البناء الرابع" ثم "اصعد إلى الطابق الثاني" ثم "اطرق على الباب الذي سيظهر أمامك". مبارك! بهذه الطريقة، تستطيع أن تدل صديقك على منزلك بدقة. البرمجة هي الشيء نفسه تمامًا. فهل ترى التعابير المكتوبة بين قوسين؟ إنها التعابير التي تكتب بإحدى لغات البرمجة والتي تخاطب الحاسوب بدلًا من صديقك السابق. لغات البرمجة هي مجموعة من المفردات والقواعد اللغوية التي تشكل لغةً وسيطةً للتخاطب مع الحاسوب وأمره بتنفيذ تعليمات وأشياء محدَّدة. فلا الحاسوب يفهم لغة البشر ولا البشر يفهمون لغة الحاسوب، لذا كان هنالك حاجة ملحة لوجود لغة وسيطة يفهمها كلاهما؛ نتيجةً لذلك، انبثق مفهوم لغة البرمجة. بعبارة أخرى، لو أردنا أن نقول للحاسوب "افعل كذا"، فسنحتاج إلى لغةٍ مشتركةٍ بيننا وبينه ليفهم ما نبتغيه، وهنا يأتي دور لغات البرمجة، إذ يمكنك أن تعدّ لغات البرمجة على أنها وسيط بين المبرمج والحاسوب. يهتم المبرمج بالتفكير في تسلسل الخطوات التي على الحاسوب القيام بها لإتمام العمل المطلوب منه (مثل حساب العمر اعتمادًا على تاريخ الولادة)، ثم كتابة هذه الخطوات بترتيب منطقي بإحدى لغات البرمجة. ربما لاحظتَ في الجملة السابقة أن جزءًا من مهمة المبرمج هو التفكير المنطقي، وهذا يجعلنا ننتقل إلى السؤال الشائع "هل أستطيع تعلم البرمجة وأصبح مبرمجًا؟" أو "هل أنا مؤهل لأصبح مبرمجًا؟". لماذا تتعلم البرمجة؟ يبدو أن تعلم البرمجة ليس بالصعوبة التي توقعتها، لكنك تريد حافزًا يجعلك تتعلم البرمجة. تسمع كثيرًا أن البرمجة هي مجال المستقبل، وأن وظائف المبرمجين ستكتسح مجال التوظيف في السنوات القادمة؟ أستطيع أن أؤكد لك ذلك، كما أنَّ وظائف البرمجة هي من أعلى الوظائف دخلًا. فلو كنت تريد بدء مشوارك الاحترافي وتريد عملًا مستقرًا وذا دخلٍ ممتاز، فإن تعلم البرمجة والعمل بها هو أفضل خيارٍ أمامك. وظائف البرمجة مريحة عمومًا، فالعمل كله مكتبي أمام حاسوب في بيئة مريحة ومناسبة، وأغلبية الشركات تتبع نظام العمل 40 ساعة في الأسبوع (أي 5 أيام لمدة 8 ساعات يوميًا)، ولا تغفل عن قدرتك على العمل عن بعد من خلال الانترنت أو كمستقل في أوقات فراغك. تعلم البرمجة سيوسع أفق تفكيرك كثيرًا، خصوصًا أن تعاملك مع الحاسوب يتبع إلى التفكير المنطقي، وستجد أن البرمجة ستسهل لك القيام بأمور أخرى في الحاسوب. ما عليك معرفته لتصبح مبرمجًا يتردد الكثيرون في تعلم البرمجة متذرعين بأن مستواهم في الرياضيات ليس ممتازًا، وهذا ليس صحيحًا، فصحيحٌ أنَّ هنالك أمور تعترضك أثناء أداء عملك كمبرمج تتطلب خبرة في الرياضيات، إلا أنَّه قد تمر عليك فترات طويلة لا تحتاج فيها إلى مسائل رياضية. كل ما يلزمك للبدء في تعلم البرمجة هو الأساسيات التي يعرفها الجميع. إلى حين اعتراضك أية مسألة أو مشكلة تتطلب مهارة في الرياضيات، هنالك الكثير من المصادر والمراجع التي تستطيع الرجوع إليها آنذاك. بعبارة أخرى، أجِّل هذا الأمر قليلًا ولا تخف. الأهم من ذلك هو أن تكون قادرًا على التفكير بشكل منطقي. التفكير المنطقي التفكير المنطقي هو المهارة التي تجمع كافة المبرمجين تحت مظلة واحدة، وهي أساس كتابة الخوارزميات، إذ يجب أن تكون قادرًا على اكتساب هذه المهارة وتطويرها. الخوارزميات كلمة "الخوارزميات" هي الكلمة المرعبة التي ينفر منها البعض، فكل ما يتخيلونه عند ذكرها هو الرياضيات المعقدة والمعادلات الطويلة والرموز العجيبة، لكن الأمر بسيط جدًا؛ فالخوازرميات هي تطبيقٌ للتفكير المنطقي في خطوات متسلسلة واضحة تمامًا لحل مشكلة ما. لكي أوضِّح لك أن الخوارزميات ليست أمرًا معقدًا، سأخبرك بكيفية كتابة برنامج يسأل المستخدم عن سنة ميلاده، ثم يعيد عمره الحالي بالسنوات. الخطوة الأولى: إظهار رسالة نصية نطلب فيها من المستخدم إدخال تاريخ ميلاده. الخطوة الثانية: تخزين سنة الميلاد التي أدخلها المستخدم. الخطوة الثالثة: الحصول على السنة الحالية. الخطوة الرابعة: طرح مدخلات المستخدم من السنة الحالية. الخطوة الخامسة والأخيرة: إظهار الناتج. ما سبق هو خوارزمية بسيطة تتألف من خطوات متسلسلة، لكن إذا أمعنا النظر فيها سنجد خللًا في حال أدخل المستخدم تاريخًا أكبر من التاريخ الحالي، أي لو أدخل 2050 مثلًا بدلًا من 1995. عندها سيصبح العمر المعاد من الخوارزمية سالبًا، ويمكننا أن نحل هذه الإشكالية منطقيًا بوضع شرط يمنع المستخدم من إدخال تاريخ أكبر من التاريخ الحالي. إطارات العمل كلمة أخرى شائعة جدًا في عالم البرمجة هي "إطارات العمل" frameworks، إطارات العمل هي مجموعة من الشيفرات البرمجية التي تسهل على المبرمج إنشاء التطبيقات، بتوفير وحدات جاهزة تقدم خدمات مثل تسجيل المستخدمين، وإرسال البريد الإلكتروني، والتعامل مع قواعد البيانات. أي يمكنك أن تعدّها أدوات برمجية تساعدك في برمجة تطبيقك وتسهِّل لك فعل ذلك. الأدوات اللازمة للبدء في تعلم البرمجة تحتاج إلى حاسوبٍ بمواصفات جيدة (ليس من الضروري أن يكون من أفضل الحواسيب، وإنما أن يمتلك مقدارًا جيدًا من الذاكرة العشوائية). لا ننصح بمواصفات معينة أو نظام تشغيل معين، استعمل ما يحلو لك وما ترى نفسك معتادًا عليه (سواءً كان ويندوز أو لينكس أو ماك). ستحتاج أيضًا إلى اتصالٍ جيد بالإنترنت للوصول إلى المواد التعليمية، ولتنزيل البرمجيات والمكتبات اللازمة للتطوير. أما بخصوص أدوات التطوير، فستحتاج إلى برمجية لكتابة الشيفرات، وهنالك نوعان رئيسيان لها: المحررات النصية: مثل Visual Studio Code أو Atom أو Sublime Text أو Bracktes أو Notepad++‎. وهذه المحررات النصية تكون بسيطة في أغلبها، وتوفر ميزات أساسية مثل تلوين الشيفرات، وبعض ميزات الإكمال التلقائي، وتدعم أغلبيتها إضافات لزيادة وظائفها. وظيفة هذه المحررات النصية عمومًا هي تعديل الشيفرات بسهولة وسرعة. ننصحك بتجربة Visual Studio Code لشهرته حاليًا وكثرة إضافاته ودعمه الممتاز من شركة Microsoft. بيئات التطوير المدمجة: مثل Visual Studio و Eclipse و Android Studio و NetBeans و Apple Xcode وغيرها. وهذه البيئات توفر ميزات أكثر بكثير من المحررات النصية، مثل تشغيل الشيفرات وتنقيحها (debugging) وميزات التحكم بالإصدارات والاتصال بقواعد البيانات وخلاف ذلك. لماذا هناك العديد من لغات البرمجة؟ قد تتساءل، لماذا هناك العديد من لغات البرمجة؟ أليست هذه اللغات كلها تنفذ الهدف ذاته؟ لماذا لا يكون هنالك لغة موحدة بين المبرمجين والحاسوب؟ الحقيقة أنّه توجد لغة برمجة واحدة ولكن ليست إحدى اللغات التي تراها أمامك في الصورة. اللغة التي نشير إليها هي "لغة الآلة" التي يستطيع معالج الحاسوب قراءتها وفهمها. أتتساءل ما هي لغة الآلة وكيف تبدو؟ إليك مقطعًا منها: معلومٌ أنّ معالج الحاسوب لا يفهم شيئًا سوى الأصفار والواحدات، وهذه اللغة -أي لغة الآلة- هي تمثيل للأصفار والواحدات بطريقة تخبر الحاسوب بما يجب عليه فعله. الجدير بالذكر أن هذه اللغة عصية الفهم على البشر، إذ حتى إن استطعت كتابة شيفرة مثل الشيفرة الموضحة بالصورة (كما في السنوات الأولى من بداية اختراع الحاسوب)، لن يفهمها الآخرون ولن يستطيع أحد التعديل على الشيفرة وتطويرها لاحقًا باستثنائك. سعيًا لإيجاد لغة قريبة من لغة البشر، انقسمت لغات البرمجية إلى قسمين: لغات البرمجة منخفضة المستوى، ولغات البرمجة عالية المستوى وذلك تبعًا لمدى قربها من لغة الآلة أو لغة البشر على التوالي. أي أنّ لغات البرمجة منخفضة المستوى هي اللغات الأقرب للغة الآلة آنفة الذكر مثل لغة التجميع، ولغات البرمجة عالية المستوى هي اللغات الأقرب للغة البشر مثل لغة بايثون وجافا. تنفيذ البرامج المكتوبة بلغات برمجة عالية المستوى الحديث عن اللغات عالية المستوى واللغات منخفضة المستوى يقودنا إلى الحديث عن كيفية تنفيذ المعالج للشيفرة المكتوبة بلغة عالية المستوى لا يفهمها المعالج (أليس هذا ما تفكر به الآن؟). عرفنا أن المعالج يفهم الأوامر والتعليمات المكتوبة بلغة منخفضة المستوى (لغة الآلة)، إذ مَثَلُ هذه العملية كمَثَلِ شخصٍ أجنبي تعلم اللغة العربية وبدأ التحدث مع ناطقٍ باللغة العربية، إذ يمكن لهما التواصل مباشرةً - ليخبر كل منها ما يريد من الآخر فعله - دون وسيط. أمَّا مَثَلُ كتابة برنامج بلغة عالية المستوى أقرب إلى لغة البشر والطلب من الحاسوب تنفيذه كمثل ناطق باللغة الهندية يريد التخاطب مع ناطق باللغة العربية دون أن يفقه أحدهما لغة الآخر. في هذه الحالة، لن يستطيع أحدهما فهم ما يتكلم به الآخر وستفشل عملية التواصل. قد تقول: لماذا لا يحضران مترجمًا يترجم ما يقوله كل منها للآخر؟ حسنًا، هذا ما يحصل تمامًا عندما يراد تنفيذ برنامج بلغة لا يفهمها معالج الحاسوب. في اللغات البشرية، هنالك نوع واحد من المترجمين يعرفه الجميع للترجمة من لغة إلى آخرى؛ أما في لغات البرمجة، هنالك نوعان من المترجمين بين اللغات هما: المفسر، والمترجم. بناءً على ذلك، تنقسم لغات البرمجة إلى لغات مفسرة ولغات مترجمة. (من الآن وصاعدًا، كلما ذكرنا لغات البرمجة، فنحن نشير إلى لغات البرمجة عالية المستوى.) المفسر (interpreter): وهو برنامج خاصٌ يفسِّر الشيفرة المصدرية لبرنامج مكتوب بلغة عالية المستوى سطرًا بسطر ويحولها إلى لغة منخفضة المستوى لينفذها الحاسوب مباشرةً. المترجم (compiler): وهو برنامج خاصٌ يحوِّل الملفات المصدرية لبرنامج مكتوب بلغة عالية المستوى إلى ملف تنفيذي مكتوب بلغة الآلة دفعةً واحدةً، ثم يمكن تشغيل الملف التنفيذي على الحاسوب للقيام بالمهمة المطلوبة. لماذا يوجد الكثير من لغات البرمجة عالية المستوى؟ الآن وبعد أن عرفت الفرق بين لغة الآلة ولغة البشر، لربّما ما زلت تتساءل عن كثرة اللغات البرمجية عالية المستوى المتوافرة وعدم وجود لغة واحدة. نستطيع القول أنك خطوت خطوةً جيدةً للأمام إذ أصبحت الآن أكثر دقة. جواب سؤلك هو أنّ كل لغات البرمجة تُستخدم لتحويل فكرة منطقية إلى سلسلة أوامر يمكن للحاسوب أن ينفذها. فعلى سبيل المثال لا الحصر يمكنك استخدام أي من Ruby أو Java أو Python أو C#‎ أو Go أو JavaScript لبناء موقع ويب. لكن يمكنك أن تعدّ لغات البرمجة على أنها أدوات، وكل أداة تسهّل مهمة دونًا عن أخرى. فعلى سبيل المثال، السيارة والحافلة والدراجة والمحراث الزراعي كلها وسائط نقل، لكنها مختلفة الاستخدام؛ فلا يمكنك أن تذهب وعائلتك لقضاء إجازة صيفية مستخدمين المحراث الزراعي، كما لا يمكنك استخدام سيارة سباق في مدينة مكتظة ذات شوارع ضيقة للذهاب بها إلى العمل. مع أن آلية عمل هذه المركبات متشابهة. والأمر سيانٌ بالنسبة إلى البرمجة. خلاصة القول أنّ هنالك لغات برمجة متخصصة بإنشاء تطبيقات سطح المكتب، وأخرى متخصصة بإنشاء تطبيقات الجوال، وأخرى تستعمل خصيصًا لمواقع الويب، وأخرى لبرمجة العتاد، وهذا ما يحيلنا إلى الحديث عن مجالات البرمجة واللغات الأنسب لكلٍ منها. مفاهيم البرمجة "حسنًا، اقتنعتُ أن البرمجة مناسبة لي وليست صعبة كما كنتُ أتخيل، من أين أبدأ طريقي في تعلم البرمجة إذًا؟" قبل الإجابة عن السؤال السابق، سآخذ وقتي لأشرح لك بعض المفاهيم الخاصة بالبرمجة، ثم سنتحدث عن مجالات العمل فيها وما المسار الأفضل لتعلمك كلًا منها. أنت تعلم أن البرنامج هو سلسلة أوامر ينفذها الحاسوب لحل مشكلة ما، والبرنامج نفسه مكتوب بلغة يفهمها الحاسوب تسمى لغة الآلة. من الأمور الملحوظة التركيز كثيرًا على لغة البرمجة ذاتها أثناء بداية تعلم البرمجة. سأخبرك حقيقةً صادمةً: "لغة البرمجة التي تستعملها ليست بتلك الأهمية التي تتوقعها"، أنا لا أقول لك أن جميع لغات البرمجة متماثلة أو تُستعمل لنفس الاستعمالات، لكن لا تركِّز كثيرًا على تعلم كيفية الكتابة في لغة برمجة ما وتهمل المفاهيم البرمجية التي تقف وراءها. المتغيرات والثوابت عليك أن تتعرف على مفهوم المتغيرات variables المستعمل في جميع لغات البرمجة، والذي يعني إسناد قيمة ما إلى رمز أو كلمة وتخزين هذه القيمة في الذاكرة. فلو أردنا أن نخزن العبارة "Hello World" في متغير ما فنكتب شيئًا شبيهًا بما يلي: var variable_name = "Hello World"; أي أننا نسند الجزء الموجود على يمين إشارة المساواة إلى المتغير المذكور على يسار إشارة المساواة. يمكننا أن نستنتج من اسم "المتغيرات" أن قيمتها قابلة للتغيير خلال تنفيذ البرنامج، فيمكننا في مكانٍ ما من الملف المصدري أن نعيد تعريف المتغير السابق بكتابة: var variable_name = "New value"; أما الثوابت فهي تتشابه مع المتغيرات في كثيرٍ من النواحي، إلا أنك لا تستطيع إعادة تعريف قيمتها بعد تعريفها أول مرة. قد تستفيد من الثوابت عندما تكون متأكدًا تمامًا من عدم تغيير القيمة خلال فترة تنفيذ البرنامج. فلو أردنا تعريف ثابت اسمه pi يحتوي على القيمة 3.14 (والتي سنعرف أنها لن تتغير مطلقًا)، فيمكننا أن نكتب: const pi = 3.14; وإذا حاولتَ تغيير قيمة الثابت بعد تعريفه فستحصل على رسالة خطأ. الشروط تدعم جميع لغات البرمجة تعريف شروط تُنفَّذ في حالات معينة. ففي الخوازرمية السابقة التي شرحنا فيها حساب العمر، يمكننا أن نكتب الشرط بالعربية كما يلي: إذا كان (تاريخ الميلاد أكبر من التاريخ الحالي): نقول للمستخدم أن هنالك خطأ وإلا: سنحسب العمر بطرح تاريخ الميلاد من التاريخ الحالي وإذا أردنا كتابتها بإحدى لغات البرمجة فستبدو شبيهةً بما يلي: if ( user_birth > current_year ) { // ERROR! } else { age = current_year - user_birth; } لا تلقِ للأقواس بالًا، فهي جزء من لغة البرمجة، وقد تختلف من لغة لأخرى، وليست موضع اهتمامنا حاليًا. حلقات التكرار ماذا لو كانت لدينا قاعدة بيانات فيها أكثر من مستخدم ولكل مستخدم تاريخ ميلاد. لا تقل لي سنأخذ التواريخ يدويًا وندخلها إلى البرنامج! هذا مضيعةٌ للوقت، والصواب هو إنشاء حلقة تكرار تأخذ قيمة تاريخ الميلاد الخاص بكل مستخدم ثم تحسب عمره كما أسلفنا في القسم السابق. دعنا نعدل الخوارزمية البسيطة لنضيف تكرارًا فيها: ما أجمل البرمجة! تخيل لو كان عندك ألف مستخدم، وكان عليك حساب أعمارهم، يمكنك بضغطة زر أن تحسبها كلها. الدوال الدالة function هي مجموعة من التعليمات البرمجية التي تقبل مدخلات وتعيد القيمة المطلوبة. تكون الدوال عادةً قصيرةً وتقوم بمهمة وحيدة فقط. فمثلًا لو أردنا تعريف دالة باسم divide تقبل عددين، وتعيد ناتج قسمة العدد الكبير على الصغير، فيمكننا أن نكتب الخورزمية الآتية: مصادر تعلم البرمجة أول ما سيتبادر إلى ذهنك بعد قرارك تعلم البرمجة هو من أين سأتعلم؟ هنا يأتي دور القسم التعليمي المتكامل في حسوب ليقدم للمبتدئ (والمحترف على حدٍ سواء) محتوى علمي مميز ومبسط. تزخر أكاديمية حسوب بالمحتوى البرمجي على كافة مستوياته عن تعلم البرمجة، ستجد فيها أقسامًا تشرح لغات البرمجة وتقنياتها كلها. ولدينا قسم للأسئلة البرمجية التي يمكنك أن تطرح فيه سؤالك وسيجيب عليه أحد أفراد مجتمع أكاديمية حسوب. أضف إلى ذلك أن الأكاديمية توفر قسمًا للدورات المتخصصة التي تبدأ معك من الصفر وحتى احتراف لغة البرمجة التي تريد تعلمها مع كادر من المدربين المختصين الذي يقدمون لك المساعدة ويجيبون عن جميع استفساراتك. وهنالك قناة للأكاديمية على يوتيوب ننشر فيها دوريًا دروسًا قصيرةً عن تساؤلات محددة ومفاهيم البرمجة وخلافه. لا تنسَ الاشتراك في قناة الأكاديمية لتصلك الفيديوهات الجديدة. ماذا لو أردتَ التعمق أكثر في لغة معيّنة؟ تأتي هنا موسوعة حسوب التي توفِّر توثيقًا عربيًا كاملًا وعالي الجودة، مدعّمًا بالأمثلة لمختلف لغات البرمجة وتقنيات تطوير الويب والجوال. ستكون الموسوعة مرجعًا تعود إليه في مسيرتك البرمجية، وتستعين بها لمعرفة التفاصيل الدقيقة عن لغات البرمجة. فأنت لست مضطرًا لحفظ كل شيء في لغة البرمجة، إذ حتى المبرمجين المختصين ذوي الخبرة يعودون إلى التوثيقات بين الفينة والأخرى أثناء عملهم. لننطلق الآن للتحدث عن مجالات البرمجة الأساسية وما اللغات والتقنيات المستعملة فيها. تطوير واجهات المستخدم يبدأ أغلبية المطورين مشوارهم من خلال تعلم تطوير واجهات المستخدم عند اتخاذ قرارهم لدخول مجال تطوير وبرمجة مواقع الويب، وذلك لسهولة اللغات المستعملة في هذا المجال. هدف هذا المجال هو تطوير صفحات الويب التي تعرض محتوى مختلف مواقع الويب، وهي الصفحات التي تراها عند زيارتك لموقع أكاديمية حسوب أو موسوعة حسوب أو مستقل أو أي موقع آخر. تتألف صفحة الويب من مجموعة من المكونات، وتُكتَب هذه المكونات باستخدام لغة HTML، وبعد كتابة البينة الهيكلية للصفحة سنأتي على تنسيقها باستخدام لغة CSS، وهي اللغة المستعملة لإضفاء شكل وهيئة على عناصر HTML. أي أن عناصر HTML تصف محتوى الصفحة (مثل الترويسات والقوائم والمحتوى الرئيسي والفقرات والروابط والصور والفيدوهات)، وقواعد CSS تُعرِّف كيف يجب أن تبدو هذه العناصر (سواءً من ناحية الألوان أو المساحات أو الخلفيات أو الخطوط أو خلاف ذلك). تأتي لغة JavaScript مكملةً لهما وتستعمل لإعطاء بعض عناصر الصفحة صفاتٍ تفاعلية، مثل شريط متحرك من الصور أو قوائم تظهر عند وقوع حدث معيّن ...إلخ. هنالك تقنيات كثيرة تستعمل في تسهيل إنشاء الواجهات الأمامية وسنذكر بعضها: إطار Bootstrap لتسهيل تنسيق عناصر الصفحة. مكتبة jQuery لتسهيل التعامل مع عناصر الصفحة باستخدام JavaScript. لغة Sass لإنشاء ملفات CSS بسرعة وسلاسة. أدوات بناء مثل Gulp الذي يسهِّل تحويل الملفات المصدرية للتطبيق إلى النسخة النهائية التي ستعرَض للمستخدم. لتعلم تطوير واجهات المستخدم، ننصحك بالتسجيل في دورة تطوير واجهات المستخدم المقدمة من أكاديمية حسوب، والتي تحتوي على 34 ساعة فيديو تتوزع على ستة مسارات تعليمية تشرح أمثلة عملية تطبيقية شرحًا مفصلًا. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب لتتعرف على توثيق لغات البرمجة المذكورة، وذلك للاطلاع على تفاصيل وأمثلة أكثر عن كل جزئية من الجزئيات المشروحة في دورة تطوير واجهات المستخدم. اللغات والتقنيات المستخدمة في تطوير واجهات المستخدم: HTML و CSS و JavaScript و Bootstrap و Sass و jQuery و Gulp. تطوير الواجهات الخلفية قد تتساءل: ماذا يعني تطوير الواجهات الخلفية (backend)؟ وما الفرق بينه وبين تطوير واجهات المستخدم (frontend)؟ الفرق بينهما هو أن الواجهات الخلفية هي البرمجيات التي تُنفَّذ على الخوادم وتجري عمليات عليها مثل التعامل مع قواعد البيانات والملفات والخدمات الخارجية، أما واجهات المستخدم فهي الصفحات التي تظهر على شاشة الزائر في متصفحه. سأطرح عليك الخيارات المتاحة أمامك للبدء في مجال تطوير الواجهات الخلفية، وجميع اللغات المذكورة هنا هي لغات ناجحة وقوية ولا يهم أي لغة تختار منها، المهم أن تتطلع على شيفرات بسيطة من كل لغة وتتخذ قرار تعلمها، واحذر من تضييع وقتك في التنقل بين لغات البرمجة والبحث عن أفضلها، فكلُ لغةٍ ممتازةٌ في مجالها. تعلم البرمجة باستخدام لغة PHP بعد تبيان الفرق بين واجهات المستخدم والواجهات الخلفية، يمكن القول بأن أشهر لغة لتطوير الواجهات الخلفية هي لغة PHP، وتتفوق على اللغات المنافسة لها أضعافًا مضاعفة. تعلم البرمجة بلغة PHP أمر سلس، فهي لغة سهلة التعلم وبسيطة الشكل، والمجتمع حولها كبير وتطويرها مستمر. هذه اللغة هي خيار استراتيجي لمن يريد الدخول إلى مجال تطوير الواجهات الخلفية. هنالك عدد من البرمجيات المكتوبة بلغة PHP مثل ووردبريس WordPress ودروبال Drupal وميدياويكي MediaWiki (التي تشغِّل ويكيبيديا وموسوعة حسوب) وغيرها الكثير؛ إضافةً إلى عددٍ كبير من إطارات العمل مثل Laravel و Zend و CodeIgniter و Symfony و CakePHP و Yii وغيرها، وهذا ما يدل على إمكانيات اللغة الكبيرة والمجتمع الكبير الذي يحيط بها. لتعلم تطوير الواجهات الخلفية باستخدام PHP، ننصحك بالتسجيل في دورة تطوير تطبيقات الويب باستخدام PHP المقدمة من أكاديمية حسوب، والتي تحتوي على 19 ساعة فيديو تتوزع على خمسة مسارات تعليمية تبدأ بأساسيات لغة البرمجة PHP للمبتدئين، مرورًا بشرح أمثلة عملية تطبيقية بالتفصيل، ووصولًا لتطوير التطبيقات باستخدام إطار العمل Laravel. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة PHP وإطار العمل Laravel. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام PHP هي: PHP و Laravel وقواعد البيانات (مثل MySQL و PostgreSQL وغيرها). تعلم البرمجة باستخدام لغة روبي - Ruby إذا كنتَ تبحث عن لغةٍ أنيقة وسهلة الاستعمال فستجد ضالتك في لغة روبي Ruby فهي من أجمل اللغات وأسلسها كتابةً، وهي لغة برمجة عامة يمكن استخدامها لتطوير مختلف أنواع التطبيقات ومن ضمنها تطوير تطبيقات الويب. ذاع صيت روبي في تطوير الويب بعد نشر إطار العمل Ruby on Rails (يشار إليه اختصارًا "ريلز"). هنالك إطارات عمل أخرى مثل Sinatra لكن يبقى ريلز أشهرها. لتعلم تطوير الواجهات الخلفية باستخدام روبي، ننصحك بالتسجيل في دورة تطوير تطبيقات الويب باستخدام روبي المقدمة من أكاديمية حسوب، والتي تحتوي على 20 ساعة فيديو تتوزع على أربعة مسارات تعليمية تشرح أمثلة عملية تطبيقية شرحًا مفصلًا، وتشرح تطوير التطبيقات باستخدام إطار العمل ريلز. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة روبي وإطار العمل ريلز. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام روبي: روبي و ريلز وقواعد البيانات (مثل MySQL و PostgreSQL وغيرها). تعلم البرمجة باستخدام لغة جافا سكربت - JavaScript نعم! تستعمل JavaScript في تطوير الواجهات الخلفية أيضًا. الفضل يعود لبيئة Node.js التي تسمح للمطورين باستخدام JavaScript لكتابة برمجيات تعمل من جهة الخادم وذلك لتوليد صفحات ويب ديناميكية قبل إرسالها إلى المتصفح، وتستطيع Node.js التعامل مع الملفات وقواعد البيانات ومختلف أنظمة الشبكات وخدمات أنظمة التشغيل. هل يوجد أجمل من استخدام نفس اللغة لبرمجة الواجهات الأمامية لمواقع الويب والواجهات الخلفية؟ وكل ذلك باستخدام لغة سهلة التعلم والاستعمال ومدعومة دعمًا ممتازًا من المجتمع. لتعلم تعلم لغة JavaScript لتطوير الواجهات الخلفية من خلال التسجيل في دورة تطوير التطبيقات باستخدام JavaScript المقدمة من أكاديمية حسوب، والتي تحتوي على 13 ساعة فيديو تتوزع على ثلاث مسارات تعليمية تشرح أمثلة عملية تطبيقية شرحًا مفصلًا، وتشرح تطوير الواجهة الخلفية باستخدام Node.js. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة JavaScript وبيئة العمل Node.js. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام JavaScript: لغة JavaScript وبيئة Node.js وإطار العمل Express.js وقواعد البيانات (مثل MongoDB و MySQL و PostgreSQL وغيرها). تعلم البرمجة باستخدام لغة بايثون - Python لغة بايثون متعددة الاستعمالات، ويمكن عدّها على أنها أسهل لغة برمجة على الإطلاق، إذ تبدو شيفرتها البرمجية كأنها مقالة مكتوبة باللغة الإنكليزية. إذا أردتَ لغةً سهلةً ومدعومةً دعمًا ممتازًا ولها أطر عمل كثيرة فأنت تبحث عن لغة بايثون. الخيارات المتاحة أمامك هي إطار العمل جانغو (Django) وفلاسك (Flask) وغيرها، يمكنك تعلم لغة البرمجة بايثون لتطوير الواجهات الخلفية من خلال قراءة سلاسل المقالات عن تعلم بايثون في قسم البرمجة في أكاديمية حسوب، ثم الانتقال إلى تعلم إطار العمل جانغو أو فلاسك. يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة بايثون. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام بايثون: لغة بايثون وإطارات العمل المبنية عليها (مثل جانغو وفلاسك) وقواعد البيانات (مثل MySQL و PostgreSQL وغيرها). تعلم تطوير تطبيقات الجوال ازداد عدد تطبيقات الجوال لأنظمة أندرويد و iOS ازديادًا كبيرًا في الفترة الماضية، وأصبح لكل شركة أو خدمة تطبيق خاص بها يسهِّل على مستخدميها الوصول إلى الخدمات التي توفرها. النظامان الرئيسيان المسيطران على سوق الجوال حاليًا هما أندرويد ثم iOS. يمكن برمجة تطبيقات أندرويد بلغة Java أو Kotlin (أو غيرهما) وبرمجة تطبيقات iOS باستخدام Swift (وغيرها). ستكتشف أنَّ عليك تطوير تطبيقين منفصلين تمامًا، واحد لهواتف أندرويد وآخر لهواتف iOS، وذلك يسبب زيادةً في حجم العمل المطلوب وصعوبةً في إدارة التغييرات. بسبب ذلك، ظهر مفهوم "التطبيقات الهجينة"، وهي تطبيقات تعمل على نظام أندرويد و iOS دون أي تعديلات، وذلك باستخدام تقنيات مشتركة وهي تقنيات الويب. أي أصبح بإمكان مطوري الويب الاستفادة من معلوماتهم في تطوير تطبيقات الجوال باستخدام منصة كوردوفا Cordova. تسمح منصة كوردوفا للمبرمجين بالتعامل مع مختلف وظائف الجهاز باستخدام لغة JavaScript، مثل الوصول إلى الموقع الجغرافي، والتقاط صور بالكاميرا، والتعامل مع الملفات وخلاف ذلك. طوِّرت في الفترة الماضية تقنيات أخرى مبنية على JavaScript مثل ReactNative المبنية على مكتبة React.js والتي تسمح للمطورين بكتابة تطبيقات أصيلة (وليست هجينة) باستخدام تقنيات الويب. تستطيع تعلم تطوير تطبيقات الجوال عبر كوردوفا من خلال التسجيل في دورة تطوير تطبيقات الجوال باستخدام تقنيات الويب المقدمة من أكاديمية حسوب، والتي تحتوي على 15 ساعة فيديو تتوزع على أربعة مسارات تعليمية تشرح أمثلة عملية تطبيقية شرحًا مفصلًا. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق منصة كوردوفا. اللغات والتقنيات المستخدمة في تطوير تطبيقات الجوال: Java و Swift و Kotlin و Cordova و ReactNative. تطوير الألعاب تطوير الألعاب هو المجال الذي يحلم جميع مستخدمي الحاسوب بالدخول إليه. فالأغلبية تعرفوا على الحاسوب من خلال ألعاب الفيديو ومن ثم بدؤوا برحلة الاستكشاف عن البرمجة والتطوير. أغلب من يجيب عن تطوير الألعاب يقول "عليك بتعلم لغة C++‎" لكن دعني أفصِّل لك الأمر قليلًا. برمجة الألعاب تتطلب عملًا كثيرًا من فريق عمل كبير، مدعوم من شركة تجارية. من الصعب على مطوِّر وحيد أن ينشئ لعبة كاملة من الصفر دون فريق. تُطور أغلبية الألعاب باستخدام محرِّك (engine) والذي يسهِّل الأمر على المطورين ويتيح بيئة تطوير مناسبة للألعاب، ويتيح الميزات الأساسية لجميع الألعاب مثل التحكم بالكاميرا ونمذجة الشخصيات ثلاثية الأبعاد وتحريكها والأمور الفيزيائية الأخرى. هنالك عدد كبير من محركات تطوير الألعاب، ومن المرجح أنك شاهدت شعارها في الألعاب التي لعبتها من قبل، ومن أشهرها: Unreal Engine و Unity. يمكن التعامل مع هذه المحركات باستخدام عدِّة لغات، مثل C++‎ (وهي أشهرها)، وجافا (خصوصًا للألعاب على هواتف أندرويد) وحتى يمكن استخدام JavaScript في التعامل مع بعضها. تذكر أنّ الألعاب غير محدودة بتطبيقات سطح المكتب أو الهواتف، فهنالك ألعاب كثيرة تعمل على المتصفحات باستخدام تقنيات HTML5 و JavaScript. اللغات والتقنيات المستخدمة في تطوير الألعاب: C++‎ و Java و JavaScript ومحركات Unity و Unreal Engine. تطوير الأنظمة المدمجة الأنظمة المدمجة هي أنظمة حاسوبية شبيهة بالحاسوب ولكنها لا تملك كل ميزات الحاسوب الذي تراه أمامك الآن. بعبارة أخرى، النظام المدمج هو حاسوب صغير مبرمج لأداء مهام محددة فقط ومدمج ضمن الجهاز أو البيئة المراد استخدامه فيها. أنت الآن محاط بالكثير من الأنظمة المدمجة الآن مثل جهاز مقياس مستوى المياه وجهاز التحكم بالتلفاز وجهاز إنذار الحريق وأجهزة المراقبة ...إلخ. حتى إشارات المرور وتنظيم السير وألعاب الأطفال الآلية تصنَّف على أنها أنظمة مدمجة. هل سمعت أيضًا بمصطلح "إنترنت الأشياء"؟ إنترنت الأشياء هو نظام مدمج متصل بالإنترنت. نعم، بهذه البساطة! لابد الآن أن يتبادر إلى ذهنك الساعات والثلاجات والغسالات الذكية وطائرات الدرون وأنظمة المراقبة عن بعد وأنظمة البيوت الذكية، إذ كلها أمثلة على إنترنت الأشياء. كيفية برمجة الأنظمة المدمجة أشهر وأكثر لغة برمجة تستعمَل في برمجة الأنظمة المدمجة وإنترنت الأشياء هي لغة C (أي لغة سي) وكل اللغات المشتقة منها (مثل‎ لغة أردوينو C). تُستعمَل لغة C++‎ كثيرًا في هذا المجال، إذ تعدُّ لغة ذات مستوى أعلى من لغة C لدعمها للبرمجة كائنية التوجه. أضف إلى ذلك أنه بدأ حديثًا استعمال لغة بايثون في برمجة تطبيقات الأنظمة المدمجة مع أنها لم ترتبط تقليديًّا بهذا المجال سابقًا. صحيح أنَّ لغة بايثون ليست بقوة لغة C و C++‎ في هذا المجال إلا أنها تستمد ميزاتها وفعاليتها من المكتبات الهائلة المتوافرة فيها. بعيدًا عن C وبايثون، تستعمل في مجال الأنظمة المدمجة أيضًا لغات أخرى تنضوي ضمن "لغات توصيف العتاد" (Hardware Description Languages)؛ لغتي VHDL و Verilog هما من أشهر لغات توصيف العتاد المستعملة في هذا المجال. تُستعمَل مثل هذه اللغات في برمجة "مصفوفة البوابات المنطقية القابلة للبرمجة" (FPGA أي Field Programmable Gate Array). أخيرًا، قد تجد بعض المراجع تشرح برمجة الأنظمة المدمجة بلغة أخرى تدعى "لغة التجميع" (Assembly Language) التي تصنف من اللغات منخفضة المستوى. يتطلب تعلم البرمجة باستخدام هذه اللغة فهمًا واسعًا بمعمارية وحدة التحكم المركزية والمعالج بالمجمل لأنها أقرب لغة يفهمها الحاسوب. الانتقال إلى هذه اللغة قد يكون في مستويات متقدمة من تعلمك لبرمجة الأنظمة المدمجة وتطبيقات إنترنت الأشياء. من ميزات البرمجة بهذه اللغة هي التحكم الواسع بالعتاد والمعالج الذي لا توفره لغات أخرى. يقال أن هذه اللغة صعبة بعض الشيء ومعقدة، ولكن لا أرى ذلك! قد يكون سبب قول ذلك هو أن لغة التجميع هي لغة منخفضة المستوى وأقرب شيء إلى لغة الآلة ولا يستطيع من يلقي نظرة على شيفرة مكتوبة فيها فهمها مطلقًا إن لم يعرفها. تطوير تطبيقات سطح المكتب مجال تطوير تطبيقات سطح المكتب كالمحيط الواسع؛ إن لم تملك بوصلة وتعرف إلى أين تريد الاتجاه، ستضيع فيه حتمًا. هنالك الكثير من أنظمة التشغيل أشهرها - وأكثرها سيطرةً على السوق حاليًا - هي: نظام التشغيل ويندوز، ولينكس، وماك (macOS)، ويملك كل نظام تشغيل تطبيقات مكتبية خاصة به. لذلك، يجب عليك أولًا -قبل الدخول إلى سوق برمجة تطبيقات سطح المكتب- تحديد نظام التشغيل المستهدف. أي يجب الإجابة على السؤال التالي: هل يستهدف تطبيقك نظام تشغيل محدد، أم تريد لتطبيقك أن يعمل على عدة أنظمة تشغيل في آن واحد؟! بعد تحديد نظام التشغيل المستهدف، اطلع على اللغات المفضل استعمالها في ذلك النظام لبرمجة تطبيقاته؛ فعلى سبيل المثال، اللغات C و C++‎ و C#‎ و VB.NET هي الأكثر استعمالًا في برمجة تطبيقات نظام التشغيل ويندوز، واللغات C و C++‎ و Bash هي الأكثر استعمالًا في برمجة تطبيقات توزيعات نظام التشغيل لينكس. أمَّا نظام الشغيل ماك، فينفرد باستعمال لغة Objective-C. حسنًا، دعني أخبرك الحقيقة، كل لغة برمجة عامية الغرض يمكن استعمالها في برمجة التطبيقات، إذ أشهر اللغات التي تُدرَّس أكاديميًّا في هذا المجال هي لغة جافا (Java). لا يخفى على القارئ دخول لغة بايثون بقوة على هذا المجال نظرًا لامتلاكها الكثير من المكتبات الرائعة وسهولة صياغتها. دخلت مؤخرًا لغة جافاسكربت على سوق برمجة تطبيقات سطح المكتب عبر إطار العمل Electron (إلكترون)، إذ توظف في هذا المجال تقنيات تطوير الويب (HTML و CSS و JavaScript ...إلخ.). بدأ هذا الإطار ينتشر كالنار في الهشيم مما دفع شركات كبيرة لتطوير تطبيقات سطح المكتب الخاصة بها باستعمال هذا الإطار ومنها شركة Slack التي استعملت هذا الإطار لتطوير تطبيقها المكتبي. أعلم أنك الآن تشعر بالضياع من كثرة لغات البرمجة والتقنيات المستعملة في هذا المجال؛ معك حق، فقد أخبرتك بذلك منذ قليل. دخول هذا السوق يحتاج منك تحديد هدفك منه بالضبط. هل لديك فكرة تطبيق وتريد إنشاءه والربح منه؟ هل تريد العمل لدى شركة محددة؟ ما هي مواصفات التطبيق الذي تريد إنشاءه أو تريد العمل على تطويره؟ كل ذلك يلعب دورًا في تحديد لغة البرمجة الأنسب لك لتعلمها. في النهاية، إن تعلمت أساسيات البرمجة وأتقنت العمل على لغة برمجية محددة، سيسهل عليك الانتقال إلى لغة برمجة أخرى، إذ أغلب لغات البرمجة تشبه بعضها بعضًا من ناحية المفهوم والمضمون وتختلف بعض الشيء من ناحية الصياغة والشكل. لذلك، اطمئن من هذه الناحية. كيفية اختيار لغة البرمجة التي تناسبك يمكنك اختيار لغة البرمجة اعتمادًا على المجال الذي تحب العمل فيه، سألخص لك مسار التعلم لمختلف مجالات العمل: العمل كمطور ويب full-stack: يعني ذلك تعلم تطوير واجهات المستخدم، وتطوير الواجهات الخلفية. يمكن التخصص بمجال واحد من هذين المجالين فقط، إذ يُطلَب كثيرًا في سوق العمل مبرمجين متخصصين في واجهات المستخدم أو الواجهات الخلفية. العمل كمطور تطبيقات للهواتف المحمولة: يمكنك تعلم برمجة تطبيقات أندرويد أو iOS كلًا على حدة، أو استعمال تقنيات مثل كوردوفا للتطوير لكلا النظامين معًا. العمل كمطور تطبيقات سطح المكتب: يمكنك البدء بالتخصص في تطوير تطبيقات مكتبية لنظام تشغيل محدَّد (مثل نظام التشغيل ويندوز أو لينكس) عبر تعلم لغة البرمجة المستعملة في ذاك المجال (كما أشرنا إلى ذلك في قسم تطوير تطبيقات سطح المكتب)؛ خيار آخر هو تعلم اللغات والتقنيات التي تمكنك من تطوير تطبيقات عابرة للمنصات (تعمل على عدة أنظمة تشغيل) مثل استعمال إطار العمل Electron. العمل كمطور للأنظمة المدمجة والأنظمة الذكية: لغة C هي أساس هذا المجال، سواءً كنتَ تتعامل مع المتحكمات مباشرةً، أو تتعامل مع شريحة مثل أردوينو (والتي تمتلك لغةً مشتقةً من C). نصائح لتعلم البرمجة مشوار تعلم البرمجة طويل وشائق، وجميل ومسلٍ، لكنك قد تصاب بالإحباط في بداية طريقك لكثرة الأمور التي عليك الإلمام بها، لذا جهزت إليك النصائح الآتية من تجربتي في البرمجة: حدد هدفك من تعلم لغة البرمجة وسوق العمل الذي تريد دخوله واجعله واقعيًا. بدون هدف، أبشرك بأنك ستتخلى عن فكرة تعلم البرمجة بعد حين. انتبه إلى أن يكون هدفك واقعيًا وقابلًا للقياس والتجزيء على مراحل. بدون ذلك، ستفشل من أول عقبة وتترك تعلم البرمجة. أعرف نفسك جيدًا ونقاط قوتك وضعفك. كلنا لديه نقاط قوة وضعف، ولكن المفلح من عمل على ترميم وتحسين نقاط ضعفه في المجال الذي يرغب بتعلمه. رشح دورة واحدة وكتابًا واحدًا وابدأ بقراءة الكتاب ومتابعة الدورة تدريجيًّا ثم انتقل بعد الانتهاء إلى دورة أخرى وكتاب آخر، إذ سيجنبك ذلك التشتت بين الدورات الكثيرة والكتب العديدة. الشيء الذي أفعله قبل بداية تعلم شيء جديد هو ترشيح قائمة من عدة كتب ودورات ثم ترتيب هذه الكتب والدورات بحسب جودتها ومدى بساطتها وتعقيدها. أرقم الكتب والدورات وأبدأ بالخيار الأول منها. أحدد الوقت التقريبي الذي يأخذه كل خيار لدراسته وأجدول الخيارات البقية على رزنامتي الخاصة. لا تأخذ العلم إلا ممن تثق بعلمه، فالكثير من المبتدئين يحاولون مساعدة غيرهم وقد يضعون معلومات مغلوطة دون قصد. طبق ما تعلمته مباشرة، وأنشئ أي شيء من كل أمر جديد تتعلمه حتى لو كان رسمة بسيطة أو شيفرة من عدة أسطر فقط. فرحة إنجاز شيء مما تعلمته تدفعك لتعلم المزيد والاستمرار في طلب العلم. نظم وقتك بورقة وقلم، حدد بداية كل أسبوع خطةً لسائره والتزم بتنفيذها. أخبر أصدقائك أن لديك إلتزام وأمور مهمة عليك إنجازها. خصص وقتًا للاستراحة بالطبع ولا تنسَ نصيبك منها. في نهاية كل أسبوع، وازن مدى الإنجاز الذي حققته ومدى تطبيق الخطة التي وضعها وحاول أن تصل النسبة إلى 100%. أنصحك بقراءة ومتابعة استراتيجيات تنظيم الوقت ورفع الإنتاجية. تمرس على حل المشكلات وتحدى نفسك باستمرار وتابع المسابقات البرمجية واشترك بها إن استطعت، أنصحك بقراءة مقالة حل المشكلات وأهميتها في احتراف البرمجة بعد هذه المقالة. لا تنسَ أن تكافئ نفسك في كل مرة تنهي فيها كتابًا أو تكمل العمل على مشروع. لا تنسَ حظك من الاستراحة، لأن طريق البرمجة قد يكون له بداية ولكن النهاية بعيدة ومتعبة -مثله مثل أي مجال آخر-. في النهاية أرجو لك كل التوفيق في مشوارك البرمجي. وأرجو منك أن تشاركنا تجربتك في تعلم البرمجة، لعل غيرك يستفيد منها.
  5. دليل تعلم react

    سنناقش في هذا الدرس حالة المكوِّنات (component state). ما هي حالة المكون (Component State)؟ أغلبية المكونات تأخذ الخاصيات props وتصيّر العنصر، لكن تتيح المكونات الحالة أيضًا، والتي يمكن أن تستخدم لتخزين معلومات حول المكوِّن التي يمكن أن تتغير مع مرور الوقت. وعادةً يأتي التغيير نتيجةً لأحداث المستخدم أو أحداث النظام (مثل رد لمدخلات المستخدم، أو طلبية للخادم بعد مرور فترة زمنية معيّنة). بعض الأمور التي يجب أخذها بالحسبان حول حالة مكوِّنات React: إذا كان للمكوِّن حالة فيمكن ضبط الحالة الافتراضية this.setState()‎ في الدالة البانية‎. تغيرات الحالة هي ما تجعلنا نعيد تصيير المكوِّن وجميع المكونات الفرعية التابعة له. يمكنك إعلام المكوِّن بتغيّر الحالة باستخدام this.setState()‎ لضبط حالةٍ جديدة. يمكن أن تدمج تغيرات الحالة البيانات الجديدة مع البيانات القديمة التي ما تزال محتواةً في الحالة (أي this.state). عند تغيير الحالة، فستجري عملية إعادة التصيير داخليًا، ولا يفترض بك استدعاء this.render()‎ مباشرةً أبدًا. يجب أن يحتوي كائن الحالة على القدر الأدنى من البيانات اللازم لواجهة المستخدم؛ فلا تضع البيانات المحسوبة أو مكونات React الأخرى أو الخاصيات props في كائن الحالة. العمل مع حالة المكونات يتطلب التعامل مع حالة المكونات عادةً ضبط الحالة الافتراضية، والوصول إلى الحالة الحالية، وتحديث الحالة. سننشِئ في المثال الآتي المكوِّن الذي يبيّن استخدام this.state.[STATE]‎ وthis.setState()‎. إذا ضغطتَ على المكوِّن في متصفح الويب (أي الوجه المبتسم) فستجد أنَّ المكوِّن سيبدِّل بين الحالات المتاحة (أي الأوجه المبتسمة)، وبالتالي تكون هنالك ثلاثة حالات ممكنة للمكوِّن وهي مرتبطة بالواجهة الرسومية ومعتمدة على نقرات المستخدم في واجهة المستخدم: class MoodComponent extends React.Component { state = {mood: ':|'}; constructor(props){ super(props); this.changeMood = this.changeMood.bind(this) } changeMood(event,a){ const moods = [':)',':|',':(']; const current = moods.indexOf(event.target.textContent); this.setState({mood: current === 2 ? moods[0] : moods[current+1]}); } render() { return ( <span style={{fontSize:'60',border:'1px solid #333',cursor:'pointer'}} onClick={this.changeMood}> {this.state.mood} </span> ) } }; ReactDOM.render(< MoodComponent />, app); لاحظ أنَّ للمكوِّن حالةً افتراضيةً هي :|، وهي مضبوطة باستخدام state = {mood: ':|'};‎ وهي تستخدم في المكوِّن عند تصييره لأول مرة عبر {this.state.mood}. أضفنا مستمعًا للأحداث لتغيير الحالة، وهي هذه الحالة سيؤدي حدث النقر (onClick) على عقدة إلى استدعاء الدالة changeMood، وداخل هذه الدالة سنستخدم this.setState()‎ للتبديل إلى الحالة التالية اعتمادًا على قيمة الحالة الحالية. بعد إجراء هذا التحديث (لاحظ أنَّ setState()‎ ستدمج التعديلات) فسيعاد تصيير العنصر وستتغير واجهة المستخدم. بعض الأمور التي علينا إبقاؤها في ذهننا عند الحديث عن حالة مكوِّنات React: إذا كان للمكوِّن حالة فيمكن ضبط الحالة الافتراضية الخاصية state‎. تغيرات الحالة هي ما تجعلنا نعيد تصيير المكوِّن وجميع المكونات الفرعية التابعة له. يمكنك إعلام المكوِّن بتغيّر الحالة باستخدام this.setState()‎ لضبط حالةٍ جديدة. هنالك طرائق أخرى (مثل forceUpdate()‎) ولكن لا يجدر بناء استخدامها إلا إذا أردنا دمج React مع مكتباتٍ من طرف ثالث. يمكن أن تدمج تغيرات الحالة البيانات الجديدة مع البيانات القديمة التي ما تزال محتواةً في الحالة (أي this.state). لكن هذا دمجٌ أو تحديثٌ سطحي، فلن يجرى عملية دمج عميقة. عند تغيير الحالة، فستجري عملية إعادة التصيير داخليًا، ولا يفترض بك استدعاء this.render()‎ مباشرةً أبدًا. يجب أن يحتوي كائن الحالة على القدر الأدنى من البيانات اللازم لواجهة المستخدم؛ فلا تضع البيانات المحسوبة أو مكونات React الأخرى أو الخاصيات props في كائن الحالة. الفروقات بين الحالة والخاصيات props هنالك أرضيةٌ مشتركة بين الحالة state والخاصيات props: كلاهما كائنات JavaScript عادية. يمكن لكليهما أن يمتلك قيمًا افتراضية. يمكن الوصول إليها باستخدام this.props أو this.state، لكن لا يجوز أن نضبط قيمهما بهذه الطريقة، إذ سيكون كلاهما للقراءة فقط عند استخدام this. لكنهما يستخدمان لأغراضٍ مختلفة وبطرائق مختلفة. الخاصيات props: تُمرَّر الخاصيات إلى المكوِّنات من البنية الأعلى منها، سواءً كانت من مكوِّنٍ أب أو بداية المجال حيث صُيَّرت React من الأساس. الغرض من الخاصيات هو تمرير قيم الضبط إلى المكوِّن. تخيل أنها كالوسائط المُمرَّرة إلى دالة (وإن لم تكن تستعمل صيغة JSX فهذا ما تفعله تحديدًا). الخاصيات غير قابلة للتعديل في المكوِّن الذي يستقبلها، أي لا يمكننا تعديل الخاصيات المُمرَّرة إلى المكوِّن من داخل المكوِّن نفسه. الحالة (state): الحالة هي تمثيلٌ للبيانات الذي سيرتبط في مرحلةٍ ما مع الواجهة الرسومية. يجب أن تبدأ الحالة دومًا بقيمةٍ افتراضية، ثم ستُعدّل الحالة داخليًا في المكوِّن باستخدام setState()‎. يمكن تعديل الحالة باستخدام المكوِّن الذي يحتوي عليها فقط، أي أنها خاصة. لا يفترض تعديل حالة المكوِّنات الأبناء، ويجب ألا يشارك المكوِّن حالةً قابلةً للتعديل. يجب أن يحتوي كائن الحالة على القدر الأدنى من البيانات اللازم لواجهة المستخدم؛ فلا تضع البيانات المحسوبة أو مكونات React الأخرى أو الخاصيات props في كائن الحالة. إنشاء مكونات عديمة الحالة (Stateless Components) عندما يكون المكون نتيجةً لاستخدام الخاصيات props فقط دون وجود حالة state، فيمكن كتابة المكوِّن على شكل دالة صرفة مما يجعلنا نتفادى إنشاء نسخة من مكوِّن React. ففي المثال الآتي سيكون MyComponent نتيجةً لاستدعاء دالة ناتجة عن React.createElement()‎. var MyComponent = function(props){ return <div>Hello {props.name}</div>; }; ReactDOM.render(<MyComponent name="doug" />, app); إذا ألقينا نظرةً على شيفرة JavaScript الناتجة عن عملية تحويل JSX، فستبدو الأمور جليةً وواضحةً لنا: var MyComponent = function MyComponent(props) { return React.createElement( "div", null, "Hello ", props.name ); }; ReactDOM.render(React.createElement(MyComponent, { name: "doug" }), app); إنشاء مكوِّن React دون اشتقاق الصنف React.Component‎ يشار إليه عادةً بمكوِّن عديم الحالة. لا يمكن تمرير خيارات الضبط إلى المكونات عديمة الحالة (مثل render أو componentWillUnmount …إلخ.)؛ لكن يمكن ضبط ‎.propTypes و ‎.defaultProps على الدالة. الشيفرة الآتية توضِّح مكوِّنًا عديم الحالة يستخدم ‎.propTypes و ‎.defaultProps: import PropTypes from 'prop-types'; var MyComponent = function(props){ return <div>Hello {props.name}</div>; }; MyComponent.defaultProps = {name:"John Doe"}; MyComponent.propTyes = {name: PropTypes.string}; ReactDOM.render(<MyComponent />, app); ملاحظات حاول أن تجعل أكبر عدد من المكونات عديمَ الحالة. ترجمة -وبتصرف- للفصل React Component State من كتاب React Enlightenment
  6. سنناقش في هذا الدرس استخدام خاصيات مكوِّنات React والتي تعرف بالخاصيات props. ما هي خاصيات المكونات؟ 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; } أسهل طريقة لشرح خاصيات المكوِّنات هي القول أنَّها تسلك سلوك خاصيات HTML. بعبارةٍ أخرى، توفِّر الخاصيات خيارات الضبط للمكوِّن. فمثلًا، الشيفرة الآتية فيها المكوِّن Badge الذي يتوقع إرسال الخاصية name عند تهيئة المكوِّن: class Badge extends React.Component { render() { return <div>{this.props.name}</div>; } }; class BadgeList extends React.Component { render() { return (<div> <Badge name="Bill" /> <Badge name="Tom" /> </div>); } }; ReactDOM.render(<BadgeList />, document.getElementById('app')); داخل دالة التصيير للمكوِّن وعندما نستخدم المكوِّن ستُضاف الخاصية name إلى المكوِّن بنفس الطريقة التي نضيف فيها خاصية HTML إلى عنصر HTML (أي)؛ ثم ستستخدم الخاصية name من المكوِّن Badge (عبر this.props.name) كعقدة نصية للعقدة التي ستصيَّر عبر المكون Badge. هذا شبيهٌ بطريقة أخذ العنصر في HTML الخاصية value التي ستُستخدَم قيمتها لعرض نص داخل حقل الإدخال. طريقة أخرى للتفكير في خاصيات المكوِّنات هي تخيلها كأنها قيم لخيارات الضبط المُرسَلة إلى المكوِّن. فإذا نظرتَ إلى نسخة لا تحتوي على صيغة JSX من المثال السابق فسيبدو لك جليًا أنَّ خاصيات المكوِّن ما هي إلا كائنٌ يُمرَّر إلى الخاصية createElement()‎ (أي React.createElement(Badge, { name: "Bill" })‎): class Badge extends React.Component { render() { return React.createElement( "div", null, // null لم تُعرَّف خاصيات لذا ستكون القيمة this.props.name // كقيمة نصية this.prop.name استخدام ); } }; class BadgeList extends React.Component { render() { return React.createElement( "div", null, React.createElement(Badge, { name: "Bill" }), React.createElement(Badge, { name: "Tom" }) ); } }; ReactDOM.render(React.createElement(BadgeList, null), document.getElementById('app')); هذا شبيهٌ بطريقة ضبط الخاصيات مباشرةً على عقد React. لكن عند تمرير تعريف المكوِّن Badge إلى الدالة createElement()‎ بدلًا من قعدة، فستصبح الخاصيات props متاحةً على المكوِّن نفسه (أي this.props.name). تُمكِّننا خاصيات المكوِّنات من إعادة استخدام المكوِّن مع أي اسم. في الشيفرة التي ألقينا إليها نظرةً في هذا القسم، لاحظنا أنَّ المكوِّن BadgeList يستخدم مكونَي Badge مع كائن this.props خاصٌ بكلٍ واحدٍ منها. يمكننا التأكد من ذلك بعرض قيمة this.props عندما يُهيَّئ المكوِّن Badge: class Badge extends React.Component { render() { return <div>{this.props.name}{console.log(this.props)}</div>; } }; class BadgeList extends React.Component { render() { return (<div> <Badge name="Bill" /> <Badge name="Tom" /> </div>); } }; ReactDOM.render(<BadgeList />, document.getElementById('app')); نلاحظ أنَّ كل نسخة من مكوِّنات React تملك نسخةً خاصةً بها من خاصيةٍ اسمها props التي تكون كائن JavaScript فارغ، ثم سيُملَأ هذا الكائن عبر المكوِّن الأب باستخدام أي قيمة أو مرجعية في JavaScript، ثم ستُستخدَم هذه القيمة من المكوِّن أو تُمرَّر إلى المكونات الأبناء. ملاحظات في البيئات التي تستخدم ES5، لن نتمكن من تعديل الخاصية this.props لأنها كائنٌ مجمَّد (أي Object.isFrozen(this.props) === true;‎). يمكنك أن تعدّ this.props على أنها كائنٌ للقراءة فقط. إرسال الخاصيات props إلى مكوِّن تُرسَل الخاصيات إلى المكوِّن عند إضافة قيم شبيهة بخاصيات HTML إلى المكوِّن عند استخدمه وليس عند تعريفه، فمثلًا، سنجد في الشيفرة الآتية أنَّ المكوِّن Badge قد عُرِّفَ أولًا، ثم أرسلنا خاصيةً له وهي name="Bill"‎ أثناء استخدامه (أي عند تصيير ``): class Badge extends React.Component { render() { return <div>{this.props.name}</div>; } }; ReactDOM.render(<Badge name="Bill" />, document.getElementById('app')); أبقِ في ذهنك أنَّ بإمكاننا إرسال خاصية إلى المكوِّن في أي مكان يمكن أن يُستخدَم المكوِّن فيه. فعلى سبيل المثال، يبيّن المثال من القسم السابقة استخدام المكوِّن Badge والخاصية name ضمن المكوِّن BadgeList: class Badge extends React.Component { render() { return <div>{this.props.name}</div>; } }; class BadgeList extends React.Component { render() { return (<div> <Badge name="Bill" /> <Badge name="Tom" /> </div> ); } }; ReactDOM.render(<BadgeList />, document.getElementById('app')); ملاحظات يجب أن تُعدّ خاصيات المكوِّن غيرُ قابلةٍ للتعديل، ويمكن عدم تعديل الخاصيات المُرسَلة من مكوِّن آخر. فلو احتجتَ إلى تعديل قيمة خاصيات أحد المكوِّنات ثم إعادة تصييره، فلا تضبط الخاصيات باستخدام this.props.[PROP] = [NEW PROP]. الحصول على خاصيات المكوِّن كما ناقشنا في الدرس السابق، يمكن الوصول إلى إلى نسخة المكوِّن من أيٍّ من خيارات الضبط التي تستعمل دالةً عبر الكلمة المحجوزة this. ففي المثال الآتي استخدمنا الكلمة المحجوزة this للوصول إلى خاصيات props المكوِّن Badge من خيار الضبط render بكتابة this.props.name: class Badge extends React.Component { render() { return <div>{this.props.name}</div>; } }; ReactDOM.render(<Badge name="Bill" />, document.getElementById('app')); ليس من الصعب معرفة ما يحدث إذا ألقينا نظرةً على شيفرة JavaScript المحوَّلة من JSX: class Badge extends React.Component { render() { return React.createElement( "div", null, this.props.name ); } }; ReactDOM.render(React.createElement(Badge, { name: "Bill" }), document.getElementById('app')); أُرسِل الكائن { name: "Bill"‎ } إلى الدالة createElement()‎ إضافةً إلى مرجعيةٍ إلى المكوِّن Badge. القيمة { name: "Bill"‎ } ستُضبَط كخاصية للمكوِّن قابلةٌ للوصول من الكائن props، أي أنَّ this.props.name === "Bill"‎. ملاحظات تذكَّر أنَّ this.props للقراءة فقط، ولا يجوز ضبط الخاصيات باستخدام this.props.PROP = 'foo'‎. ضبط قيم افتراضية لخاصيات المكوِّن يمكن ضبط الخاصيات الافتراضية عند تعريف المكوِّن باستخدام خيار الضبط getDefaultProps. المثال الآتي يبيّن كيف عرَّفنا خيار ضبط افتراضي للمكوِّن Badge للخاصية name: class Badge extends React.Component { static defaultProps = { name:'John Doe' } render() { return <div>{this.props.name}</div>; } }; class BadgeList extends React.Component { render() { return (<div> <Badge /> <Badge name="Tom Willy" /> </div>); } }; ReactDOM.render(<BadgeList />, document.getElementById('app')); ستُضبَط الخاصيات الافتراضية على الكائن this.props إذا لم تُرسَل خاصيات إلى المكوِّن. يمكنك التحقق من ذلك بملاحظة أنَّ المكوِّن Badge الذي لم تُضبَط الخاصية name فيه ستأخذ القيمة الافتراضية 'John Doe'. خاصيات المكونات هي أكثر من مجرد سلاسل نصية قبل أن نلقي نظرةً على التحقق من الخاصيات، علينا أن نستوعب أولًا أنَّ خاصيات المكونات يمكن أن تكون أي قيمة صالحة في JavaScript. في المثال أدناه، سنضبط عدِّة خاصيات افتراضية تحتوي على مختلف قيم JavaScript: class MyComponent extends React.Component { static defaultProps = { propArray: [], propBool: false, propFunc: function(){}, propNumber: 5, propObject: {}, propString: 'string' } render() { return (<div> propArray: {this.props.propArray.toString()} <br /><br /> propFunc returns: {this.props.propFunc()} </div>) ; } }; ReactDOM.render(<MyComponent propArray={[1,2,3]} propFunc={function(){return 2;}} />, document.getElementById('app')); لاحظ كيف أعيدت الكتابة على الخاصيتين propArray و propObject مع قيم جديدة عند إنشاء نسخة من المكوِّن MyComponent. الفكرة الرئيسية من هذا القسم هو توضيح أنَّنا لسنا محدودين بالقيم النصية عند تمرير قيم للخاصيات. التحقق من خاصيات المكوِّنات لاستخدامٍ سليمٍ للخاصيات ضمن المكوِّنات، يجب أن نتحقق من قيمتها عند إنشاء نسخ المكوِّنات. عند تعريف خيار الضبط propTypes يمكننا أن نضبط كيف يجب أن تكون الخاصيات وكيف نتحقق منها. سنتحقق في المثال أدناه لنرى إن كانت الخاصيتان propArray و propObject من نوع البيانات الصحيح وسنرسلها إلى المكوِّن عند تهيئته: import PropTypes from 'prop-types'; class MyComponent extends React.Component { static propTypes = { propArray: PropTypes.array.isRequired, propFunc: PropTypes.func.isRequired, } render() { return (<div> propArray: {this.props.propArray.toString()} <br /><br /> propFunc returns: {this.props.propFunc()} </div>); } }; // لهذا المكوِّن خاصياتٌ خطأ ReactDOM.render(<MyComponent propArray={{test:'test'}} />, document.getElementById('app')); // لهذا المكوِّن خاصياتٌ صحيحة // ReactDOM.render(<MyComponent propArray={[1,2]} propFunc={function(){return 3;}} />, document.getElementById('app')); لم نرسل الخاصيات الصحيحة المُحدَّدة عبر propTypes لتوضيح أنَّ فعل ذلك سيؤدي إلى حدوث خطأ. ستؤدي الشيفرة السابقة إلى ظهور رسالة الخطأ الآتية: Warning: Failed propType: Invalid prop `propArray` of type `object` supplied to `MyComponent`, expected `array` Warning: Failed propType: Required prop `propFunc` was not specified in `MyComponent`. Uncaught TypeError: this.props.propFunc is not a function توفِّر React عددًا من المتحققات الداخلية (مثل PropTypes[VALIDATOR]‎) والتي سأشرحها بإيجاز فيما يلي، إضافةً إلى إمكانية إنشاء متحققات مخصصة. (انتقلت إلى مكتبة مختلفة*) المتحققات الأساسية من الأنواع React.PropTypes.string إذا اُستخدِمَت خاصيةٌ، فتحقق أنها سلسلة نصية React.PropTypes.bool إذا اُستخدِمَت خاصيةٌ، فتحقق أنها قيمة منطقية React.PropTypes.func إذا اُستخدِمَت خاصيةٌ، فتحقق أنها دالة React.PropTypes.number إذا اُستخدِمَت خاصيةٌ، فتحقق أنها عدد React.PropTypes.object إذا اُستخدِمَت خاصيةٌ، فتحقق أنها كائن React.PropTypes.array إذا اُستخدِمَت خاصيةٌ، فتحقق أنها مصفوفة React.PropTypes.any إذا اُستخدِمَت خاصيةٌ، فتحقق أنها من أي نوع من الأنواع متحققات القيم المطلوبة React.PropTypes.[TYPE].isRequired‎ إضافة ‎.isRequired إلى أي نوع من المتحققات سيؤدي إلى جعل الخاصية مطلوبةً (مثال ذلك propTypes:{propFunc:React.PropTypes.func.isRequired}) متحققات العناصر React.PropTypes.element الخاصية هي عنصر React. React.PropTypes.node أي شيء يمكن تصييره: الأرقام، أو السلاسل النصية، أو العناصر، أو مصفوفة تحتوي هذه الأنواع المتحققات المتعددة React.PropTypes.oneOf(['Mon','Fri'])‎ الخاصية هي أحد أنواع القيم المُحدَّدة React.PropTypes.oneOfType([React.PropTypes.string,React.PropTypes.number])‎ الخاصية هي كائن يمكن أن يكون أحد أنواع القيم المُحدَّدة متحققات المصفوفات والكائنات React.PropTypes.arrayOf(React.PropTypes.number)‎ الخاصية هي مصفوفة تحتوي على نوع واحد من القيم React.PropTypes.objectOf(React.PropTypes.number)‎ هي كائن يحتوي على أحد أنواع القيم React.PropTypes.instanceOf(People)‎ هي كائن يكون نسخةً من دالةٍ بانية معينة (كما في الكلمة المحجوزة instanceof) React.PropTypes.shape({color:React.PropTypes.string,size: React.PropTypes.number})‎ هي كائن يحتوي على خاصيات من أنواعٍ معينة المتحققات المخصصة function(props, propName, componentName){}‎ توفير دالة خاصة بك للتحقق ترجمة -وبتصرف- للفصل React Component Properties من كتاب React Enlightenment
  7. دليل تعلم react

    سيناقش هذا المقال إنشاء عقد React ‏(React Nodes) سواءً النصية (text nodes) أو عقد العناصر (element nodes) باستخدام JavaScript. ما هي عقدة React؟ النوع الأساسي أو القيمة التي تُنشَأ عند استخدام مكتبة React تسمى «عقدة React»، ويمكن تعريف عقدة React على أنها «تمثيل افتراضي خفيف وعديم الحالة وغير قابلٍ للتعديل لعقدة DOM» (لا تخف من الكلام السابق، هذا هو التعريف الرسمي، ما باليد حيلة :-) ). عقد React ليست عقد DOM حقيقية، وإنما تمثيل عن عقدة DOM محتملة، وهذا التمثيل يعد على أنه شجرة DOM افتراضية، ويُستخدم React لتعريف شجرة DOM الافتراضية باستخدام عقد React، والتي تُشكِّل البنية الأساسية لمكوِّنات React، والتي في نهاية المطاف ستُستخدَم لإنشاء بنية DOM الحقيقة وغير ذلك من البنى (مثل React Native). يمكن أن تُنشَأ عقد React باستخدام JSX أو JavaScript. سنلقي في هذا المقال نظرةً على إنشاء عقد React باستخدام JavaScript بمفردها دون استخدام JSX. إذ أرى أنَّ عليك فهم ما الذي تخفيه JSX وراء الكواليس لكي تفهم JSX فهمًا جيدًا. قد تحدثك نفسك بتجاوز هذا المقال لأنك تعرف مسبقًا أننا لن نستخدم JSX. لا تطعها! أقترح عليك أن تكمل قراءة هذا المقال لكي تعرف ما الذي تفعله لك JSX. ربما هذا أهم مقال في السلسلة ليتغلغل في ذهنك! إنشاء عقد العناصر سيُفضِّل المطورون في أغلبية الأوقات استخدام JSX مع React لإنشاء عقد العناصر، وبغض النظر عن ذلك، سنتعرّف في هذا المقال على طريقة إنشاء عقد React دون استخدام JSX باستعمال JavaScript فقط. أما المقال القادم فهو يناقش كيفية إنشاء عقد React باستخدام JSX. إنشاء عقد React سهلٌ جدًا فكل ما نحتاج له هو استخدام الدالة React.createElement(type, props, children)‎ وتمرير مجموعة من الوسائط إليها والتي تُعرِّف عقدة DOM الفعلية (مثالًا نضبط قيمة type إلى عنصر من عناصر HTML مثل <li> أو عنصر مخصص مثل <my-li>). وسائط الدالة React.createElement())‎ مشروحة أدناه: type (string | React.createClass())‎ يمكن أن تكون سلسلة نصية تُمثِّل عنصر HTML (أو عنصر HTML مخصص) أو نسخة من مكوِّنات React. props (null | object)‎ يمكن أن يكون null أو كائن يحتوي على خاصيات وقيم مرتبطة بها. children (null | string | React.Component | React.createElement())‎ يمكن أن تكون null أو سلسلة نصية التي ستحوّل إلى عقدة نصية، أو نسخة من React.Component‎ أو React.createElement()‎. سأستخدم في المثال الآتي الدالة React.createElement()‎ لإنشاء تمثيل في شجرة DOM الافتراضية لعقدة العنصر <li> والتي تحتوي على عقدة نصية فيها one (أي عقدة نصية في React) ومُعرِّف id يساوي li1. var reactNodeLi = React.createElement('li', {id:'li1'}, 'one'); لاحظ أنَّ أول وسيط يُعرِّف ما هو عنصر HTML الذي نريد تمثيله، ويعُرِّف الوسيط الثاني ما هي الخاصيات التي ستُضبَط على العناصر <li>، وأخيرًا سيُعرِّف الوسيط الثالث ما هي العقدة الموجودة داخل العنصر، وفي هذه الحالة وضعنا ببساطة عقدةً نصية (أي 'one') داخل <li>. لاحظ أنَّ آخر وسيط الذي سيصبح ابنًا للعقدة المُنشَأة يمكن أن يكون عقدة React نصية، أو عقدة عنصر في React، أو نسخة من مكوِّن React. كل ما فعلناه إلى الآن هو إنشاء عقدة عنصر في React تحتوي على عقدة React نصية، والتي خزناها في المتغير reactNodeLi، ولإنشاء شجرة DOM الوهمية فعلينا تصيير عقدة عنصر React في شجرة DOM الحقيقية، ولفعل ذلك سنستخدم الدالة ReactDOM.render()‎: ReactDOM.render(reactNodeLi, document.getElementById('app')); إذا أردنا وصف الشيفرة السابقة ببساطة، فهي تتضمن: إنشاء شجرة DOM افتراضية مبنية من عقدة عنصر React المُمرَّرة (أي reactNodeLi)، استخدام شجرة DOM الافتراضية لإعادة إنشاء فرع من شجرة DOM الحقيقية، إضافة الفرع المُنشَأ (أي <li id="li1">one</li>) إلى شجرة DOM الحقيقة كأحد أبناء العنصر <div id="app"></div>. بعبارةٍ أخرى، ستتغير شجرة DOM لمستند HTML من: <div id="app"></div> إلى: <div id="app"> // data-reactid قد أضافت الخاصية React لاحظ أنَّ <li id="li1" data-reactid=".0">one</li> </div> بيّن المثال السابق استخدامًا بسيطًا للدالة React.createElement()‎. يمكن للدالة React.createElement()‎ إنشاء بنى معقدة أيضًا. فعلى سبيل المثال سنستخدم الدالة React.createElement()‎ لإنشاء فرع من عقد React يُمثِّل قائمة غير مرتبة من العناصر (أي <ul>): // React في <li> إنشاء عقد عناصر var rElmLi1 = React.createElement('li', {id:'li1'}, 'one'); var rElmLi2 = React.createElement('li', {id:'li2'}, 'two'); var rElmLi3 = React.createElement('li', {id:'li3'}, 'three'); // السابقة إليها <li> وإضافة عناصر React في <ul> إنشاء عقدة العنصر var reactElementUl = React.createElement('ul', {className: 'myList'}, rElmLi1, rElmLi2, rElmLi3); قبل تصيير القائمة غير المرتبة إلى شجرة DOM، أرى إخبارك أنَّه يمكن تبسيط الشيفرة السابقة باستخدام React.createElement()‎ بدلًا من المتغيرات. هذا المثال يوضِّح كيف يمكن تعريف الهيكلية باستخدام JavaScript: var reactElementUl = React.createElement( 'ul', { className: 'myList' }, React.createElement('li', {id: 'li1'},'one'), React.createElement('li', {id: 'li2'},'two'), React.createElement('li', {id: 'li3'},'three') ); عند تصيير الشيفرة السابقة إلى DOM فستبدو شيفرة HTML الناتجة كما يلي: <ul class="myList" data-reactid=".0"> <li id="li1" data-reactid=".0.0">one</li> <li id="li2" data-reactid=".0.1">two</li> <li id="li3" data-reactid=".0.2">three</li> </ul> يجب أن يكون واضحًا أنَّ عقد React هي كائنات JavaScript في شجرةٍ تمثِّل عقد DOM حقيقية داخل شجرة DOM الافتراضية. ثم تُستخدَم شجرة DOM الافتراضية لتعديل شجرة DOM الحقيقية داخل صفحة HTML. ملاحظات يمكن أن يكون الوسيط type المُمرَّر إلى الدالة React.createElement()‎ سلسلةً نصية تُشير إلى عنصر من عناصر HTML القياسية (مثل 'li' الذي يمُثِّل العنصر <li>)، أو عنصرًا مخصصًا (مثل 'foo-bar' الذي يُمثِّل العنصر <foo-bar>)، أو نسخة من مكوِّن في React (أي نسخة من React.Component). هذه هي قائمة عناصر HTML التي تدعمها React (أي تمرير هذه العناصر كسلسلة نصية مكان المعامل type إلى الدالة createElement()‎ سيؤدي إلى إنشاء عنصر HTML القياسي في DOM): a abbr address area article aside audio b base bdi bdo big blockquote body br button canvas caption cite code col colgroup data datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li link main map mark menu menuitem meta meter nav noscript object ol optgroup option output p param picture pre progress q rp rt ruby s samp script section select small source span strong style sub summary sup table tbody td textarea tfoot th thead time title tr track u ul var video wbr تصيير (rendering) العناصر إلى شجرة DOM توفِّر React الدالة React.render()‎ من الملف react-dom.js التي يمكن أن تُستخدَم لتصيير عقد عناصر React إلى شجرة DOM. لقد رأينا الدالة render()‎ مستخدمةً في هذا المقال. سنستخدم في المثال الآتي الدالة ReactDOM.render()‎ وستُصيّر عقد العناصر '<li>' و '<foo-bar>' إلى شجرة DOM: // حقيقي DOM والتي تُمثِّل عقدة عنصر React عقدة var HTMLLi = React.createElement('li', {className:'bar'}, 'foo'); // مخصص HTML والتي تُمثِّل عقد عنصر React عقدة var HTMLCustom = React.createElement('foo-bar', {className:'bar'}, 'foo'); // <div id="app1"></div> إلى HTMLLi تصيير عقدة العنصر ReactDOM.render(HTMLLi, document.getElementById('app1')); // <div id="app2"></div> إلى HTMLCustom تصيير عقدة العنصر ReactDOM.render(HTMLCustom, document.getElementById('app2')); بعد تصيير العناصر إلى شجرة DOM، فسيبدو مستند HTML المُحدَّث كما يلي: <body> <div id="app1"><li class="bar" data-reactid=".0">foo</li></div> <div id="app2"><foo-bar classname="bar" children="foo" data-reactid=".1">foo</foo-bar></div> </body> الدالة ReactDOM.render()‎ هي الطريقة المبدئية التي تمكننا من نقل عقد العناصر في React إلى شجرة DOM الوهمية، ثم إلى شجرة DOM الحقيقية. ملاحظات ستستبدل أي عقد DOM داخل عناصر DOM التي سيُصيَّر إليها (أي أنها ستُحذَف ويحلّ المحتوى الجديد محلها). الدالة ReactDOM.render()‎ لا تعدِّل عقدة عنصر DOM الذي تُصيّر React إليه، وإنما تتطلَّب React ملكيةً كاملةً للعقدة النصية عند التصيير، فلا يجدر بك إضافة أبناء أو إزالة أبناء من العقدة التي تضيف React فيها المكوِّن أو العقدة. التصيير إلى شجرة HTML DOM هو أحد الخيارات فقط، فهنالك خياراتٌ أخرى ممكنة، فمثلًا تستطيع التصيير إلى سلسلة نصية (أي ReactDOMServer.renderToString()‎) في جهة الخادم. إعادة تصيير نفس عنصر DOM سيؤدي إلى تحديث العقد الأبناء الحاليين إذا حدث تغييرٌ فيها، أو إذا أُضيفت عقدة عنصر ابن جديدة. تعريف خاصيات العقد الوسيط الثاني الذي يُمرَّر إلى الدالة React.createElement(type, props, children)‎ هو كائنٌ يحتوي على خاصيات ذات أسماء ترتبط بها قيم. تمتلك الخاصيات عدِّة أدوار: يمكن أن تتحول إلى خاصيات HTML. فلو طابقت إحدى الخاصيات خاصية HTML معروفة، فستُضاف إلى عنصر HTML النهائي في DOM. الخاصيات المُمرَّرة إلى createElement()‎ ستصبح قيمًا مخزنةً في الكائن prop كنسخة من React.createElement()‎ (أي ‎[INSTANCE].props.[NAME_OF_PROP]). تستخدم الخاصيات بكثرة لإدخال قيم إلى المكوِّنات. تمتلك بعض الخاصيات تأثيراتٍ جانبية (مثل key و ref و dangerouslySetInnerHTML). يمكنك أن تتخيل الخاصيات على أنها خيارات ضبط لعقد React، ويمكنك أن تتخيلها كخاصيات HTML. سنُعرِّف في المثال الآتي عقدة العنصر <li> مع خمس خاصيات، إحدى تلك الخاصيات غير قياسية في HTML (أقصد بها foo:'bar'‎) وبقية الخاصيات معروفة في HTML: var reactNodeLi = React.createElement('li', { foo:'bar', id:'li1', // للإشارة إلى صنف الأنماط في جافاسكربت className لاحظ استخدام الخاصية className: 'blue', 'data-test': 'test', 'aria-test': 'test', // CSS لضبط خاصية backgroundColor لاحظ استخدام الخاصية style: {backgroundColor: 'red'} }, 'text' ); ستبدو الشيفرة المُصيَّرة إلى صفحة HTML كما يلي: <li id="li1" data-test="test" class="blue" aria-test="test" style="background-color:red;" data-reactid=".0">text</li> ما عليك إدراكه من المثال السابق أنَّ خاصيات HTML القياسية فقط، وخاصيات data-*‎ و aria-*‎ هي الخاصيات الوحيدة التي تنتقل إلى شجرة DOM الحقيقية من شجرة DOM الافتراضية. لاحظ أنَّ الخاصية foo لن تظهر في شجرة DOM الحقيقية، فهذه الخاصية غير القياسية ستكون متاحةً في نسخة الكائن li لعقدة React (أي reactNodeLi.props.foo): var reactNodeLi = React.createElement('div',{ foo:'bar', id:'li1', className: 'blue', 'data-test': 'test', 'aria-test': 'test', style: {backgroundColor: 'red'} }, 'text' ); console.log(reactNodeLi.props.foo); // bar ReactDOM.render(reactNodeLi, document.getElementById('app')); ليس استخدام خاصيات React مقتصرًا على تحويلها إلى خاصيات HTML حقيقية، لكن يمكن أن تلعب دورًا في إعدادات الضبط المُمرَّرة إلى مكونات React. هذا الجانب من جوانب استخدام الخاصيات سيغطى في مقالٍ خاصٍ به، أما الآن فكل ما علينا إدراكه هو أنَّ تمرير خاصية إلى عقدة React هو أمرٌ يختلف عن تعريف خاصية في مكوِّن لكي تُستخدم لمدخلات ضبط ضمن ذاك المكوِّن. ملاحظات ترك قيمة إحدى الخاصيات فارغةً سيؤدي إلى جعل قيمتها مساويةً إلى true (أي id=""‎ ستصبح id="true"‎، و test ستصبح test="true"‎). إذا كانت خاصيةٌ ما مكررةً فستؤخذ آخر قيمة لها. إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<x-my-component custom-attribute="foo" />‎). الخاصية class يجب أن تكتب className. الخاصية for يجب أن تكتب htmlFor. الخاصية style تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي background-color تصبح backgroundColor). خاصيات النماذج في HTML (مثل <input> أو <textarea></textarea> …إلخ.) المُنشَأة كعقد React ستدعم خاصيات التي يمكن تغييرها عبر تفاعل المستخدم مع العنصر؛ وهذه الخاصيات هي value و checked و selected. توفِّر React الخاصيات key و ref و dangerouslySetInnerHTML) التي لا تتوافر في DOM وتأخذ دورًا فريدًا. يجب أن تكتب جميع الخاصيات مع حذف الشرطة - وجعل أول حرف يليها مكتوبًا بحرفٍ كبير، أي أنَّ الخاصية accept-charset ستُكتَب acceptCharset. هذه هي خاصيات HTML التي تدعمها تطبيقات React: accept acceptCharset accessKey action allowFullScreen allowTransparency alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge charSet checked classID className colSpan cols content contentEditable contextMenu controls coords crossOrigin data dateTime default defer dir disabled download draggable encType form formAction formEncType formMethod formNoValidate formTarget frameBorder headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media mediaGroup method min minLength multiple muted name noValidate nonce open optimum pattern placeholder poster preload radioGroup readOnly rel required reversed role rowSpan rows sandbox scope scoped scrolling seamless selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step style summary tabIndex target title type useMap value width wmode wrap تضمين أنماط CSS السطرية في عقد العناصر لتطبيق أنماط CSS السطرية (inline CSS styles) على عقدة React، فعليك تمرير كائن يحتوي على خاصيات CSS والقيم المرتبطة بها إلى الخاصية style. على سبيل المثال، سنمرر مرجعيةً إلى الكائن inlineStyles إلى الخاصية style: var inlineStyles = {backgroundColor: 'red', fontSize: 20}; var reactNodeLi = React.createElement('div', {style: inlineStyles}, 'styled') ReactDOM.render(reactNodeLi, document.getElementById('app1')); ستبدو شيفرة HTML الناتجة شبيهةً بما يلي: <div id="app1"> <div style="background-color:red;font-size:20px;" data-reactid=".0">styled</div> </div> هنالك أمران عليك الانتباه إليهما في الشيفرة السابقة: لم نضف الواحدة "px" إلى الخاصية fontSize لأنَّ React أضافته عوضًا عنّا. عند كتابة خاصيات CSS في JavaScript، يجب حذف الشرطة وجعل الحرف الذي يليها مكتوبًا بحرفٍ كبير (أي backgroundColor بدلًا من background-color). ملاحظات يجب أن تبدأ السابقات الخاصة بالمتصفحات (باستثناء ms) بحرفٍ كبير، لهذا السبب تبدأ الخاصية WebkitTransition بحرف W كبير (ولم أعد أنصح بإضافة هذه الخاصيات إلا لدعم المتصفحات القديمة جدًا). يجب ألا يفاجئك استخدام الأحرف الكبيرة في أسماء خاصيات CSS بدلًا من الشرطات، فهذه هي الطريقة المتبعة للوصول إلى تلك الخاصيات في شجرة DOM عبر JavaScript (كما في document.body.style.backgroundImage). عند تحديد قيمة بواحدة البكسل، فستضيف React السلسلة النصية "px" تلقائيًا بعد القيم الرقمية باستثناء الخاصيات الآتية: columnCount fillOpacity flex flexGrow flexShrink fontWeight lineClamp lineHeight opacity order orphans strokeOpacity widows zIndex zoom استخدام مصانع العناصر المُضمَّنة في React توفِّر React اختصارات مضمَّنة لإنشاء عقد عناصر HTML شائعة الاستخدام. تسمى هذه الاختصارات بمصانع عقد React. قبل الإصدار 16.0 من مكتبة React.js، كانت هذه المصانع مضمنة في المكتبة نفسها، لكن بعد الإصدار 16.0 فقد أسقط الدعم عنها، وظهرت وحدة باسم react-dom-factories) التي تتيح استخدام المصانع التي كانت مضمنة في React.js مع الإصدارات الجديدة من المكتبة. مصنع لعقد React هو دالةٌ تولِّد ReactElement مع قيمة معينة لخاصية type. باستخدام المصنع المضمن React.DOM.li()‎، يمكننا إنشاء عقدة العنصر <li>one</li> في React كما يلي: // DOM.li(props, children); import DOM from 'react-dom-factories'; var reactNodeLi = DOM.li({id:'li1'}, 'one'); وذلك بدلًا من استخدام: // React.createElement(type, prop, children) var reactNodeLi = React.createElement('li', null, 'one'); هذه قائمة بجميع المصانع المُضمَّنة في React: a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,big,blockquote,body,br,button, canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl, dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup, hr,html,i,iframe,img,input,ins,kbd,keygen,label,legend,li,link,main,map,mark,menu, menuitem,meta,meter,nav,noscript,object,ol,optgroup,option,output,p,param,picture, pre,progress,q,rp,rt,ruby,s,samp,script,section,select,small,source,span,strong, style,sub,summary,sup,table,tbody,td,textarea,tfoot,th,thead,time,title,tr,track, u,ul,var,video,wbr,circle,clipPath,defs,ellipse,g,image,line,linearGradient,mask, path,pattern,polygon,polyline,radialGradient,rect,stop,svg,text,tspa ملاحظات إذا كنتَ تستخدم JSX فقد لا تحتاج إلى استخدام المصانع إطلاقًا. يمكن إنشاء مصانع مخصصة إن كان ذلك ضروريًا. تعريف أحداث عقد React يمكن إضافة الأحداث إلى عقد React كما لو أردنا إضافة الأحداث إلى عقد DOM. سنضيف في المثال الآتي حدثين بسيطين click و mouseover إلى عقدة <div>: var mouseOverHandler = function mouseOverHandler() { console.log('you moused over'); }; var clickhandler = function clickhandler() { console.log('you clicked'); }; var reactNode = React.createElement( 'div', { onClick: clickhandler, onMouseOver: mouseOverHandler }, 'click or mouse over' ); ReactDOM.render(reactNode, document.getElementById('app')); لاحظ أنَّ اسم الخاصية لأحداث React تبدأ بالحرفين 'on' وتُمرِّر في الكائن props المُمرَّر إلى الدالة ReactElement()‎. تُنشئ React ما تسميه SyntheticEvent لكل حدث، والذي يحتوي على تفاصيل الحدث، وهي شبيهة بتفاصيل الأحداث المُعرَّفة في DOM. يمكن مثلًا الاستفادة من نسخة الكائن SyntheticEvent بتمريره إلى معالجات الأحداث، وسأفعل ذلك في المثال الآتي لتسجيل تفاصيل الحدث SyntheticEvent. var clickhandler = function clickhandler(SyntheticEvent) { console.log(SyntheticEvent); }; var reactNode = React.createElement( 'div', { onClick: clickhandler}, 'click' ); ReactDOM.render(reactNode, document.getElementById('app')); كل كائن من النوع syntheticEvent يملك الخاصيات الآتية: bubbles cancelable DOMEventTarget currentTarget defaultPrevented eventPhase isTrusted DOMEvent nativeEvent void preventDefault()‎ isDefaultPrevented()‎ void stopPropagation()‎ isPropagationStopped()‎ DOMEventTarget target timeStamp type هنالك خاصيات إضافية متوافرة اعتمادًا على نوع أو تصنيف الحدث المستخدم. فعلى سبيل المثال، الحدث onClick يحتوي على الخاصيات الآتية: altKey button buttons clientX clientY ctrlKey getModifierState(key‎)‎ metaKey pageX pageY DOMEventTarget relatedTarget screenX screenY shiftKey يحتوي الجدول الآتي على خصائص syntheticEvent المتاحة لكل تصنيف من تصنيفات الأحداث: نوع الحدث الأحداث خاصيات متعلقة به الحافظة onCopy onCut onPaste DOMDataTransfer clipboardData التركيب onCompositionEnd onCompositionStart onCompositionUpdate data لوحة المفاتيح onKeyDown onKeyPress onKeyUp altKey charCode ctrlKey getModifierState(key)‎ key keyCode locale location metaKey repeat shiftKey which التركيز onChange onInput onSubmit DOMEventTarget relatedTarget النماذج OnFocus onBlur الفأرة onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp altKey button buttons clientX clientY ctrlKey getModifierState(key)‎ metaKey pageX pageY DOMEventTarget relatedTarget screenX screenY shiftKey الاختيار onSelect اللمس onTouchCancel onTouchEnd onTouchMove onTouchStart AltKey DOMTouchList changedTouches ctrlKey getModifierState(key)‎ metaKey shiftKey DOMTouchList targetTouches DOMTouchList touches واجهة المستخدم onScroll detail DOMAbstractView view الدولاب onWheel deltaMode deltaX deltaY deltaZ الوسائط onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting الصور onLoad onError الحركات onAnimationStart onAnimationEnd onAnimationIteration animationName pseudoElement elapsedTime الانتقالات onTransitionEnd propertyName pseudoElement elapsedTime ملاحظات توحِّد React التعامل مع الأحداث لكي تسلك سلوكًا متماثلًا في جميع المتصفحات. تنطلق الأحداث في React في مرحلة الفقاعات (bubbling phase). لإطلاق حدث في مرحلة الالتقاط (capturing phase) فأضف الكلمة "Capture" إلى اسم الحدث، أي أنَّ الحدث onClick سيصبح onClickCapture. إذا احتجتَ إلى تفاصيل كائن الأحداث المُنشَأ من المتصفح، فيمكنك الوصول إليه باستخدام الخاصية nativeEvent في كائن SyntheticEvent المُمرَّر إلى دالة معالجة الأحداث في React. لا تربط React الأحداث إلى العقد نفسها، وإنما تستخدم «تفويض الأحداث» (event delegation). يجب استخدام e.stopPropagation()‎ أو e.preventDefault()‎ يدويًا لإيقاف انتشار الأحداث بدلًا من استخدام return false;‎. لا تدعم React جميع أحداث DOM، لكن ما يزال بإمكاننا الاستفادة منها باستخدام توابع دورة الحياة في React. ترجمة وبتصرف للفصل React Nodes‎ من كتاب React Enlightenment 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; }
  8. تعلمنا في المقال السابق كيفية إنشاء عقد React باستخدام شيفرات JavaScript العادية، وسنلقي في هذا المقال نظرةً على إنشاء عقد React باستخدام صيغة JSX. إن لم تقرأ المقال السابق، عقد React، فانتقل إليه أولًا لقراءته ثم عد إلى هذا المقال. سنستخدم صيغة JSX بعد هذا المقال في بقية الكتاب ما لم نستعمل الدالة React.createElement()‎ لأغراض التوضيح. بعد انتهائك من قراءة هذا المقال، يمكنك الاطلاع على شرح تفصيلي لجميع ميزات JSX في موسوعة حسوب. ما هي صيغة JSX؟ JSX هي صيغة شبيهة بصيغة XML أو HTML التي تستخدمها React لتوسعة ECMAScript لكي نستطيع كتابة تعابير شبيهة بلغة XML أو HTML داخل شيفرة JavaScript. هذه الصيغة مهيئة للعمل مع برمجيات التحويل مثل Babel لتحويل النص الشبيه بشيفرات HTML في ملفات JavaScript إلى كائنات JavaScript التي تستطيع محركات JavaScript تفسيرها. أساسيًا، عند استخدمنا لصيغة JSX يمكننا أن نكتب بنى شبيهة ببنى HTML (أي هياكل من العناصر كما في DOM) بنفس الملف الذي تكتب فيه شيفرة JavaScript، ثم يحوِّل Babel هذه التعابير إلى شيفرة JavaScript حقيقية. وعلى عكس ما جرت عليه العادة بوضع شيفرات JavaScript داخل HTML، تسمح لنا صيغة JSX بوضع شيفرات HTML داخل JavaScript. تسمح لنا JSX بكتابة شيفرة JavaScript الآتية: var nav = ( <ul id="nav"> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Clients</a></li> <li><a href="#">Contact Us</a></li> </ul> ); وسيحولها Babel إلى الشيفرة الآتية: var nav = React.createElement( "ul", { id: "nav" }, React.createElement( "li", null, React.createElement( "a", { href: "#" }, "Home" ) ), React.createElement( "li", null, React.createElement( "a", { href: "#" }, "About" ) ), React.createElement( "li", null, React.createElement( "a", { href: "#" }, "Clients" ) ), React.createElement( "li", null, React.createElement( "a", { href: "#" }, "Contact Us" ) ) ); لذا يمكننا أن نعدّ JSX على أنها اختصار لاستدعاء React.createElement()‎. فكرة دمج شيفرات HTML و JavaScript في نفس الملف هي فكرة مثيرة للجدال، حاول أن تتجاهل ذلك وتستعملها إذا وجدتها مفيدةً، وإذا لم تجدها مفيدةً فاكتب شيفرة JavaScript الضرورية لإنشاء عقد React يدويًا، فالخيار عائد لك تمامًا. أرى شخصيًا أنَّ JSX توفِّر صيغة مختصرة ومألوفةً لتعريف بنى هيكلية مع الخاصيات اللازمة لها والتي لا تتطلب تعلّم صيغة قوالب خاصة أو تتطلب الخروج من شيفرة JavaScript؛ وكلا الميزتين السابقتين مفيدتان عند إنشاء التطبيقات الكبيرة. من الواضح أنَّ صيغة JSX أسهل قراءةً وكتابةً من الأهرامات الكبيرة من استدعاءات دوال JavaScript مع تعريف الكائنات داخلها (قارن الشيفرتين السابقتين في هذا القسم لتتأكد من ذلك). أضف إلى ذلك أنَّ فريق تطوير React يعتقد أنَّ JSX أفضل لتعريف واجهات المستخدم من أحد حلول القوالب (مثل Handlebars): «إنَّ الشيفرة البرمجية والبنى الهيكلية مرتبطتان مع بعضهما بعضًا ارتباطًا وثيقًا. أضف إلى ذلك أنَّ الشيفرات البرمجية معقدة جدًا واستخدام لغات القوالب ستجعل الأمر صعبًا جدًا. وجدنا أنَّ أفضل حل لهذه المشكلة هو توليد شيفرات HTML مباشرةً من شيفرة JavaScript، وبهذا نستطيع استخدام كامل قدرات لغة برمجية حقيقية لبناء واجهات المستخدم.» ملاحظات لا تفكر في JSX على أنها لغة قوالب، وإنما هي صيغة JavaScript خاصة يمكن تصريفها، أي أنَّ JSX هي صيغة تسمح بتحويل بنى شبيهة ببنى HTML إلى شيفرات JavaScript. أداة Babel هي الأداة التي اختارها فريق تطوير React لتحويل شيفرات ES*‎ و JSX إلى شيفرة ES5. يمكنك معرفة المزيد عن Babel بقراءة توثيقه الرسمي. باستخدام صيغة JSX: أصبح بإمكان الأشخاص غير المتخصصين تقنيًا فهم وتعديل الأجزاء المطلوبة. فيجد مطورو CSS والمصممون صيغة JSX أكثر ألفةً من شيفرة JavaScript. يمكنك استثمار كامل قدرات JavaScript في HTML وتتجنب تعلّم أو استخدام لغة خاصة بالقوالب. لكن اعلم أن JSX ليس محرّك قوالب، وإنما صيغة تصريحية للتعبير عن البنية الهيكلية الشجرية لمكونات UI. سيجد المُصرِّف (compiler) أخطاءً في شيفرة HTML الخاصة بك كنتَ ستغفل عنها. تحث صياغة JSX على فكر استخدام الأنماط السطرية (inline styles) وهو أمرٌ حسن. صيغة JSX منفصلة عن React، ولا تحاول JSX أن تتفق مع أي مواصفة تخص HTML أو XML، وإنما هي مصممة كميزة ECMAScript وهي تشبه HTML ظاهريًا فقط، وتجري كتابة مواصفة JSX كمسودة لكي تُستخدَم من أي شخص كإضافة لصياغة ECMAScript. في صيغة JSX، يجوز استخدام ‎<foo-bar />‎ بمفرده، لكن لا يجوز استخدام <foo-bar>. أي عليك إغلاق جميع الوسوم دومًا. إنشاء عقد React باستخدام JSX بإكمالنا لما تعلمناه في المقال الماضي، يجب أن تكون قادرًا على إنشاء عقد React باستخدام الدالة React.createElement()‎. فيمكن مثلًا استخدام هذه الدالة لإنشاء عقد React التي تُمثِّل عقدًا حقيقيةً في HTML DOM إضافةً إلى عقدٍ مخصصة. سأريك حالتي الاستخدام السابقتين في المثال الآتي: // حقيقية HTML DOM التي تمثِّل عقدة React عقدة var HTMLLi = React.createElement('li', {className:'bar'}, 'foo'); // مخصصة HTML DOM التي تمثِّل عقدة React عقدة var HTMLCustom = React.createElement('foo-bar', {className:'bar'}, 'foo'); لاستخدام صيغة JSX بدلًا من React.createElement()‎ لإنشاء هذه العقد، فكل ما علينا فعله هو تبديل استدعاءات الدالة React.createElement()‎ إلى وسوم شبيهة بوسوم HTML التي تُمثِّل عناصر HTML التي تريد إنشاء شجرة DOM الافتراضية بها. يمكننا أن نكتب الشيفرة السابقة بصيغة JSX كما يلي: // حقيقية HTML DOM التي تمثِّل عقدة React عقدة var HTMLLi = <li className="bar">foo</li>; // مخصصة HTML DOM التي تمثِّل عقدة React عقدة var HTMLCustom = <foo-bar className="bar" >foo</foo-bar>; لاحظ أنَّ صيغة JSX غير محتواة في سلسلة نصية في JavaScript، وتكتبها كأنك تكتب الشيفرة داخل ملف ‎.htmlعادي، وكما ذكرنا لعدّة مرات، ستحوِّل صيغة JSX إلى استدعاءات للدالة React.createElement()‎ باستخدام Babel: // حقيقية HTML DOM التي تمثِّل عقدة React عقدة var HTMLLi = <li className="bar">foo</li>; // مخصصة HTML DOM التي تمثِّل عقدة React عقدة var HTMLCustom = <foo-bar className="bar" >foo</foo-bar>; ReactDOM.render(HTMLLi, document.getElementById('app1')); ReactDOM.render(HTMLCustom, document.getElementById('app2')); إذا أردتَ تفحص شيفرة HTML الناتجة عن المثال السابق، فستجد أنَّها شبيهة بهذه الشيفرة: <body> <div id="app1"><li class="bar" data-reactid=".0">foo</li></div> <div id="app2"><foo-bar class="bar" data-reactid=".1">foo</foo-bar></div> </body> إنشاء عقد React باستخدام JSX سهل جدًا كما لو كنتَ تكتب شيفرة HTML داخل ملفات JavaScript. ملاحظات تدعم JSX صيغة إغلاق الوسوم الخاصة بلغة XML، لذا يمكنك أن تهمل إضافة وسم الإغلاق إذا لم يمتلك العنصر أي أبناء. إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<``x-my-component custom-attribute="foo" />‎). الخاصية class يجب أن تكتب className. الخاصية for يجب أن تكتب htmlFor. الخاصية style تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي background-color تصبح backgroundColor). جميع الخاصيات مكتوبة بالصيغة المستخدمة في JavaScript، وذلك بحذف الشرطة وجعل الحرف الذي يليها كبيرًا (أي accept-charset ستصبح acceptCharset). لتمثيل عناصر HTML احرص على كتابة الوسوم بحرفٍ صغير. هذه هي قائمة بجميع خاصيات HTML التي تدعمها React: accept acceptCharset accessKey action allowFullScreen allowTransparency alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge charSet checked classID className colSpan cols content contentEditable contextMenu controls coords crossOrigin data dateTime default defer dir disabled download draggable encType form formAction formEncType formMethod formNoValidate formTarget frameBorder headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media mediaGroup method min minLength multiple muted name noValidate nonce open optimum pattern placeholder poster preload radioGroup readOnly rel required reversed role rowSpan rows sandbox scope scoped scrolling seamless selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step style summary tabIndex target title type useMap value width wmode wrap تصيير JSX إلى DOM يمكن استخدام الدالة ReactDOM.render()‎ لتصيير تعابير JSX إلى DOM. في الواقع، كل ما تفعله Babel هو تحوي JSX إلى React.createElement()‎. في المثال الآتي، سنُصيّر العنصر <li> والعنصر المخصص <foo-bar> إلى DOM باستخدام تعابير JSX: // حقيقية HTML DOM التي تمثِّل عقدة React عقدة var HTMLLi = <li className="bar">foo</li>; // مخصصة HTML DOM التي تمثِّل عقدة React عقدة var HTMLCustom = <foo-bar className="bar" >foo</foo-bar>; // <div id="app1"></div> إلى HTMLLi باسم React تصيير عقدة ReactDOM.render(HTMLLi, document.getElementById('app1')); // <div id="app2"></div> إلى HTMLCustom باسم React تصيير عقدة ReactDOM.render(HTMLCustom, document.getElementById('app2')); ستبدو شيفرة HTML كما يلي بعد تصيير العناصر إلى DOM: <body> <div id="app1"><li class="bar" data-reactid=".0">foo</li></div> <div id="app2"><foo-bar classname="bar" children="foo" data-reactid=".1">foo</foo-bar></div> </body> تذكّر أنَّ Babel يأخذ JSX ويحولها إلى عقد React (أي استدعاءات الدالة React.createElement()‎) ثم باستخدام هذه العقد المُنشَأة باستخدام React (في شجرة DOM الافتراضية) سنُصيّر العناصر إلى شجرة DOM الحقيقية. ما تفعله الدالة ReactDOM.render()‎ هو تحويل عقد React إلى عقد DOM حقيقة ثم إضافتها إلى مستند HTML. ملاحظات ستستبدل أي عقد DOM داخل عناصر DOM التي سيُصيَّر إليها (أي أنها ستُحذَف ويحلّ المحتوى الجديد محلها). الدالة ReactDOM.render()‎ لا تعدِّل عقدة عنصر DOM الذي تُصيّر React إليه، وإنما تتطلَّب React ملكيةً كاملةً للعقدة النصية عند التصيير، فلا يجدر بك إضافة أبناء أو إزالة أبناء من العقدة التي تضيف React فيها المكوِّن أو العقدة. التصيير إلى شجرة HTML DOM هو أحد الخيارات فقط، فهنالك خياراتٌ أخرى ممكنة، فمثلًا تستطيع التصيير إلى سلسلة نصية (أي ReactDOMServer.renderToString()‎) في جهة الخادم. إعادة تصيير نفس عنصر DOM سيؤدي إلى تحديث العقد الأبناء الحاليين إذا حدث تغييرٌ فيها، أو إذا أُضيفت عقدة عنصر ابن جديدة. لا تستدعي this.render()‎ يدويًا أبدًا، اترك الأمر إلى React. استخدام تعابير JavaScript داخل JSX آمل الآن أن يكون واضحًا أنَّ JSX هي صيغة بسيطة ستحوَّل في نهاية المطاف إلى شيفرة JavaScript حقيقة، لكن ماذا سيحدث عندما نريد تضمين شيفرة JavaScript حقيقية داخل JSX؟ كل ما علينا فعله لكتابة تعابير JavaScript داخل JSX هو وضعها ضمن قوسين معقوفين {}. في شيفرة React الآتية، سنضيف تعبيرًا من تعابير JavaScript (وهو 2+2) محاطًا بقوسين معقوفين {} التي ستُفسَّر من معالج JavaScript: var label = '2 + 2'; var inputType = 'input'; // JSX لاحظ كيفية استخدام تعابير أو قيم جافاسكربت بين القوسين المعقوفين داخل صيغة var reactNode = <label>{label} = <input type={inputType} value={2+2} /></label>; ReactDOM.render(reactNode, document.getElementById('app')); ستحوَّل شيفرة JSX إلى النتيجة الآتية: var label = '2 + 2'; var inputType = 'input'; var reactNode = React.createElement( 'label', null, label, ' = ', React.createElement('input', { type: inputType, value: 2 + 2 }) ); ReactDOM.render(reactNode, document.getElementById('app')); بعد أن تُفسَّر الشيفرة السابقة من محرِّك JavaScript (أي المتصفح)، فستُقدَّر قيمة تعابير JavaScript وستبدو شيفرة HTML كما يلي: <div id="app"> <label data-reactid=".0"><span data-reactid=".0.0">2 + 2</span><span data-reactid=".0.1"> = </span><input type="input" value="4" data-reactid=".0.2"></label> </div> لا يوجد شيءٌ معقد في المثال السابق، بعد الأخذ بالحسبان أنَّ الأقواس ستُهرِّب شيفرة JSX. فالقوسان {} سيخبران JSX أنَّ المحتوى الموجود داخلهما هو شيفرة JavaScript فستتركها دون تعديل لكي يفسرها مُحرِّك JavaScript (أي التعبير 2+2) لاحظ أنَّ القوسين {} يمكن أن يستخدما في أي مكان داخل تعابير JSX لطالما كانت نتيجتها هو تعبيرٌ صالحٌ في JavaScript. استخدام تعليقات JavaScript داخل JSX يمكنك وضع تعليقات JavaScript في أي مكان في شيفرة JSX عدا المواضع التي تتوقع فيها JSX عقدة React ابن. في هذه الحالة ستحتاج إلى تهريب (escape) التعليق باستخدام {} لكي تعلم JSX أنَّ عليها تمرير المحتوى كشيفرة JavaScript. تفحص الشيفرة الآتية، واحرص على فهم متى عليك إخبار JSX أن تُهرِّب تعليق JavaScript لكيلا تُنشَأ عقدة React ابن: var reactNode = <div /*comment*/>{/* use {} here to comment*/}</div>; إذا لم نضع التعليق في الشيفرة السابقة الموجود داخل العقدة ضمن القوسين {} فسيحاول Babel تحويل التعليق إلى عقدة React نصية، وسيكون الناتج -غير المتوقع- دون استخدام {} كما يلي: var reactNode = React.createElement( "div", null, "/* use ", " here to comment*/" ); مما سينُتِج شيفرة HTML الآتية التي تحتوي على عقد نصية أُنشِئت خطأً: <div data-reactid=".0"> <span data-reactid=".0.0">/* use </span><span data-reactid=".0.1"> here to comment*/</span> </div> 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; } استخدام أنماط CSS داخل JSX لتعريف أنماط CSS ضمن صيغة JSX، فعلينا تمرير مرجعية إلى كائنٍ يحتوي على خاصيات CSS وقيمها إلى الخاصية style. سنُهيّئ في بداية المثال الآتي كائن JavaScript باسم styles يحتوي على الأنماط التي نريد تضمينها سطريًا في JSX، ثم سنستخدم القوسين {} للإشارة إلى الكائن الذي يجب أن يُستخدَم كقيمة للأنماط (مثل style={styles}‎): var styles = { color: 'red', backgroundColor: 'black', fontWeight: 'bold' }; var reactNode = <div style={styles}>test</div>; ReactDOM.render(reactNode, document.getElementById('app1')); لاحظ أنَّ خاصيات CSS المُضمَّنة سطريًا مكتوبة بطريقة كتابة خاصيات CSS في JavaScript، وهذا ضروريٌ لأنَّ JavaScript لا تسمح باستخدام الشرطات – في أسماء الخاصيات. عند تحويل شيفرة JSX السابقة باستخدام Babel، ثم تفسيرها من محرِّك JavaScript فستكون شيفرة HTML الناتجة: <div style="color:red;background-color:black;font-weight:bold;" data-reactid=".0">test</div> ملاحظات يجب أن تبدأ السابقات الخاصة بالمتصفحات (باستثناء ms) بحرفٍ كبير، لهذا السبب تبدأ الخاصية WebkitTransition بحرف W كبير. يجب ألا يفاجئك استخدام الأحرف الكبيرة في أسماء خاصيات CSS بدلًا من الشرطات، فهذه هي الطريقة المتبعة للوصول إلى تلك الخاصيات في شجرة DOM عبر JavaScript (كما في document.body.style.backgroundImage). عند تحديد قيمة بواحدة البكسل، فستضيف React السلسلة النصية "px" تلقائيًا بعد القيم الرقمية باستثناء الخاصيات الآتية: columnCount fillOpacity flex flexGrow flexShrink fontWeight lineClamp lineHeight opacity order orphans strokeOpacity widows zIndex zoom تعريف الخاصيات في JSX في المقال السابق، ناقشنا تمرير خاصيات إلى الدالة React.createElement(type, props, children)‎ عند إنشاء عقد React. ولمّا كانت صيغة JSX ستحوِّل إلى استدعاءات للدالة React.createElement()‎ فأنت تملك فكرةً (من المقال السابق) كيف تعمل خاصيات React. لكن لمّا كانت JSX تُستخدَم للتعبير عن عناصر HTML فإنَّ الخاصيات المُعرَّفة ستُضاف إلى عنصر HTML الناتج. في المثال الآتي سأعرِّف عقدة <li> في React باستخدام JSX، ولها خمس خاصيات، لاحظ أنَّ إحداها هي خاصيةٌ غيرُ قياسيةٍ في HTML (وهي foo: 'bar'‎) أما البقية فهي خاصيات HTML عادية: var styles = {backgroundColor:'red'}; var tested = true; var text = 'text'; var reactNodeLi = <li id="" data-test={tested?'test':'false'} className="blue" aria-test="test" style={styles} foo="bar"> {text} </li>; ReactDOM.render(reactNodeLi, document.getElementById('app1')); ستبدو شيفرة JSX بعد تحويلها كما يلي، لاحظي أنَّ الخاصيات أصبح وسائط مُمرَّرة إلى الدالة: var reactNodeLi = React.createElement( 'li', { id: '', 'data-test': tested ? 'test' : 'false', className: 'blue', 'aria-test': 'test', style: styles, foo: 'bar' }, text ); عند تصيير العقد reactNodeLi إلى DOM، فستبدو كما يلي: <div id="app1"> <li id="true" data-test="test" class="blue" aria-test="test" style="background-color:red;" data-reactid=".0"> text </li> </div> يجب أن تلاحظ الأمور الأربعة الآتية: ترك قيمة إحدى الخاصيات فارغةً سيؤدي إلى جعل قيمتها مساويةً إلى true (أي id=""‎ ستصبح id="true"‎، و test ستصبح test="true"‎). الخاصية foo لن تُضاف إلى العنصر النهائي لأنها ليست خاصية HTML قياسية. لا يمكنك كتابة أنماط سطرية في JSX. عليك أن تُشير إلى كائنٍ يقطع في مجال تعريف شيفرة JSX أو تمرير كائن يحتوي على خاصيات CSS مكتوبةً كخاصيات JavaScript. يمكن أن تُضاف قيم JavaScript ضمن JSX باستخدام القوسين المعقوفين {} (كما في test={text}‎ و data-test={tested?'test':'false'}‎). ملاحظات إذا كانت خاصيةٌ ما مكررةً فستؤخذ آخر قيمة لها. إذا مررت خاصيات إلى عناصر HTML التي ليست موجودة في مواصفة HTML فلن تعرضها React. أما إذا استخدمتَ عناصر HTML مخصصة (أي أنها ليست قياسية) فستُضاف الخاصيات التي ليست موجودةً في مواصفة HTML إلى العناصر المخصصة (فمثلًا ‎<x-my-component custom-attribute="foo" />‎). الخاصية class يجب أن تكتب className. الخاصية for يجب أن تكتب htmlFor. الخاصية style تقبل إشارةً مرجعيةً إلى كائنٍ يحتوي على خاصيات CSS بالصيغة المتعارف عليها في JavaScript (أي background-color تصبح backgroundColor). خاصيات النماذج في HTML (مثل <input> أو <textarea></textarea> …إلخ.) المُنشَأة كعقد React ستدعم خاصيات التي يمكن تغييرها عبر تفاعل المستخدم مع العنصر؛ وهذه الخاصيات هي value و checked و selected. توفِّر React الخاصيات key و ref و dangerouslySetInnerHTML التي لا تتوافر في DOM وتأخذ دورًا فريدًا. يجب أن تكتب جميع الخاصيات مع حذف الشرطة - وجعل أول حرف يليها مكتوبًا بحرفٍ كبير، أي أنَّ الخاصية accept-charset ستُكتَب acceptCharset. هذه هي خاصيات HTML التي تدعمها تطبيقات React: accept acceptCharset accessKey action allowFullScreen allowTransparency alt async autoComplete autoFocus autoPlay capture cellPadding cellSpacing challenge charSet checked classID className colSpan cols content contentEditable contextMenu controls coords crossOrigin data dateTime default defer dir disabled download draggable encType form formAction formEncType formMethod formNoValidate formTarget frameBorder headers height hidden high href hrefLang htmlFor httpEquiv icon id inputMode integrity is keyParams keyType kind label lang list loop low manifest marginHeight marginWidth max maxLength media mediaGroup method min minLength multiple muted name noValidate nonce open optimum pattern placeholder poster preload radioGroup readOnly rel required reversed role rowSpan rows sandbox scope scoped scrolling seamless selected shape size sizes span spellCheck src srcDoc srcLang srcSet start step style summary tabIndex target title type useMap value width wmode wrap تعريف الأحداث في JSX في المقال السابق، شرحنا ووضحنا كيف يمكن أن ترتبط الأحدث مع عقد React. لفعل المثل في JSX عليك إضافة الأحداث ودالة المعالجة الخاصة بها كخاصية لشيفرة JSX التي تُمثِّل عقدة React. أُخِذ المثال الآتي من المقال السابق ويبيّن طريقة إضافة حدث إلى عقدة React دون استخدام JSX: var mouseOverHandler = function mouseOverHandler() { console.log('you moused over'); }; var clickhandler = function clickhandler() { console.log('you clicked'); }; var reactNode = React.createElement( 'div', { onClick: clickhandler, onMouseOver: mouseOverHandler }, 'click or mouse over' ); ReactDOM.render(reactNode, document.getElementById('app')); يمكن أن تُكتَب الشيفرة السابقة باستخدام JSX: var mouseOverHandler = function mouseOverHandler() { console.log('you moused over'); }; var clickHandler = function clickhandler() { console.log('you clicked'); }; var reactNode = <div onClick={clickHandler} onMouseOver={mouseOverHandler} >click or mouse over</div>; ReactDOM.render(reactNode, document.getElementById('app')); لاحظ أننا استخدمنا القوسين {} لربط دالة JavaScript إلى الحدث (أي onMouseOver={mouseOverHandler}‎)، وهذه الطريقة تشابه طريقة ربط الأحداث السطرية في DOM. الأحداث التي تدعمها React موجودةٌ في الجدول الآتي: نوع الحدث الأحداث خاصيات متعلقة به الحافظة onCopy onCut onPaste DOMDataTransfer clipboardData التركيب onCompositionEnd onCompositionStart onCompositionUpdate data لوحة المفاتيح onKeyDown onKeyPress onKeyUp altKey charCode ctrlKey getModifierState(key)‎ key keyCode locale location metaKey repeat shiftKey which التركيز onChange onInput onSubmit DOMEventTarget relatedTarget النماذج OnFocus onBlur الفأرة onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp altKey button buttons clientX clientY ctrlKey getModifierState(key)‎ metaKey pageX pageY DOMEventTarget relatedTarget screenX screenY shiftKey الاختيار onSelect اللمس onTouchCancel onTouchEnd onTouchMove onTouchStart altKey DOMTouchList changedTouches ctrlKey getModifierState(key)‎ metaKey shiftKey DOMTouchList targetTouches DOMTouchList touches واجهة المستخدم onScroll detail DOMAbstractView view الدولاب onWheel deltaMode deltaX deltaY deltaZ الوسائط onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting الصور onLoad onError الحركات onAnimationStart onAnimationEnd onAnimationIteration animationName pseudoElement elapsedTime الانتقالات onTransitionEnd propertyName pseudoElement elapsedTime ملاحظات توحِّد React التعامل مع الأحداث لكي تسلك سلوكًا متماثلًا في جميع المتصفحات. تنطلق الأحداث في React في مرحلة الفقاعات (bubbling phase). لإطلاق حدث في مرحلة الالتقاط (capturing phase) فأضف الكلمة "Capture" إلى اسم الحدث، أي أنَّ الحدث onClick سيصبح onClickCapture). إذا احتجتَ إلى تفاصيل كائن الأحداث المُنشَأ من المتصفح، فيمكنك الوصول إليه باستخدام الخاصية nativeEvent في كائن SyntheticEvent المُمرَّر إلى دالة معالجة الأحداث في React. لا تربط React الأحداث إلى العقد نفسها، وإنما تستخدم «تفويض الأحداث» (event delegation). يجب استخدام e.stopPropagation()‎ أو e.preventDefault()‎ يدويًا لإيقاف انتشار الأحداث بدلًا من استخدام return false;‎. لا تدعم React جميع أحداث DOM، لكن ما يزال بإمكاننا الاستفادة منها باستخدام توابع دورة الحياة في React. ترجمة وبتصرف للفصل JavaScript Syntax Extension (a.k.a, JSX)‎ من كتاب React Enlightenment
  9. يبيّن هذا الدرس كيفية استخدام عقد React لإنشاء مكوِّنات React أساسية. ما هي مكونات React؟ سنشرح في هذا القسم طبيعة مكونات React ونغطي بعض التفاصيل التي تتعلق بإنشاء مكونات React. عادةً تكون واجهة المستخدم (تدعى بالشجرة tree) مقسمةً إلى أقسامٍ منطقية تسمى بالفروع (branches)، وتصبح هذه الشجرة نقطة البداية للمكوِّن وكل قسم في واجهة المستخدم يصبح مكونًا فرعيًا التي يمكن بدورها أن تُقسَّم إلى مكونات فرعية؛ ويؤدي ذلك إلى تنظيم واجهة المستخدم ويسمح أيضًا لتغيرات البيانات والحالات أن تمر من الشجرة إلى الفروع ومنها إلى الفروع الداخلية. إذا كان الشرح السابق لمكونات React مبهمًا فأقترح عليك أن تعاين واجهة المستخدم لأي تطبيق وتحاول ذهنيًا تقسيمها إلى أقسام منطقية. من المحتمل تسمية هذه الأقسام بالمكونات. مكوِّنات React هي تجريد برمجي (programmatic abstraction) لعناصر واجهة المستخدم وللأحداث ولتغيرات الحالة ولتغيرات DOM والغرض منها هو تسهيل إنشاء هذه الأقسام والأقسام الفرعية. فعلى سبيل المثال، الكثير من واجهات المستخدم للتطبيقات تحتوي على مكوِّن للتخطيط (layout) كأحد المكونات الرئيسية في واجهة المستخدم، وهذا المكون يحتوي بدوره على على مكونات فرعية مثل مكوِّن البحث ومكوِّن قائمة التنقل. ويمكن تقسيم مكوِّن البحث مثلًا إلى مكونات فرعية، فيمكن أن يكون حقل الإدخال منفصلًا عن زر البحث. وكما ترى، يمكن بسهولة أن تصبح واجهة المستخدم مكونةً من شجرةٍ من المكونات، وتُنشَأ العديد من واجهات المستخدم للتطبيقات حاليًا باستخدام مكونات ذاتُ غرضٍ وحيد. توفِّر React الطرائق اللازمة لإنشاء هذه المكونات عبر React.Component إذا كنتَ تستخدم الأصناف في ES6. تقبل الدالة createReactClass()‎ من الحزمة create-react-class كائن ضبط وتُعيد نسخةً (instance) من مكوِّن React. يمكننا أن نقول أنَّ مكوِّن React هو أي جزء من الواجهة البرمجية التي تحتوي على عقد React (عبر React.createElement()‎ أو صيغة JSX). أمضينا وقتًا طويلًا في بداية هذا الكتاب ونحن نتحدث عن عقد React، لذا أتوقع أنَّ محتويات مكوِّن React أصبح واضحةً وجليةً لك. كل ذلك يبدو سهلًا وبسيطًا حتى ندرك أنَّ مكوِّنات React يمكنها أن تحتوي على مكونات React فرعية، وهذا لا يختلف عن فكرة أنَّ عقد React يمكنها أن تحتوي على عقد React أخرى في شجرة DOM الافتراضية. قد يؤلمك رأسك من الكلام السابق، لكن إذا فكرتَ مليًا فستجد أنَّ المكوِّن يحيط نفسه بمجموعة منطقية من الفروع في شجرة من العقد. وبهذا يمكنك تعريف واجهة المستخدم كلها باستخدام مكوِّنات React وستكون النتيجة النهائية هي شجرة من عقد React التي يمكن تحويلها بسهولة إلى مستند HTML (الذي يتكون من عقد DOM التي تؤلِّف واجهة المستخدم). إنشاء مكونات React يمكن إنشاء مكوِّن React الذي قد تكون له حالة state باستدعاء الدالة createReactClass()‎ من الحزمة create-react-class (أو اشتقاق React.Component إذا كنتَ تستخدم الأصناف في ES6). هذه الدالة (أو الدالة البانية) تأخذ وسيطًا واحدًا هو كائن يُستخدَم لتوفير تفاصيل المكوِّن. الجدول الآتي يبيّن خيارات الضبط المتاحة لمكوِّنات React: خيار الضبط الشرح render قيمة مطلوبة، وتُمثِّل عادةً دالةً تُعيد عقد React أو مكوِّنات React الأخرى أو القيمة null أو false. getInitialState كائن يحتوي على القيمة الابتدائية للخاصية this.state، يمكنك الحصول على قيمتها إذا كنت تستعمل الأصناف في ES6 عبر استخدام this.state في الدالة البانية. getDefaultProps كائن يحتوي على القيم التي ستُضبَط في الخاصية this.props، يمكنك ضبط قيمتها إذا كنت تستعمل الأصناف في ES6 باستخدام الخاصية static defaultProps في الصنف المشتق. propTypes كائن يحتوي على مواصفات التحقق من الخاصيات props. mixins مصفوفة من المخاليط (mixins، وهي كائنات تحتوي على توابع [methods]) التي يمكن مشاركتها بين المكوِّنات. لاحظ أن ES6 لا تدعم المخاليط، فلن تتمكن من استعمالها إذا كنتَ تستعمل الأصناف في ES6. statics كائن يحتوي على التوابع الساكنة (static methods). displayName سلسلة نصية تعطي اسمًا للمكوِّن، وتُستخدَم في رسائل التنقيح، وستُضبَط هذه القيمة تلقائيًا إذا كنّا نستعمل JSX. componentWillMount دالة رد نداء (callback function) التي ستستدعى مرةً واحدةً تلقائيًا قبل التصيير الابتدائي مباشرةً‎. componentDidMount دالة رد نداء (callback function) التي ستستدعى مرةً واحدةً تلقائيًا بعد التصيير الابتدائي مباشرةً‎. UNSAFE_componentWillReceiveProps دالة رد نداء (callback function) التي ستستدعى تلقائيًا عندما يستلم المكوِّن خاصياتٍ props جديدة‎. shouldComponentUpdate دالة رد نداء (callback function) التي ستستدعى تلقائيًا عندما يستلم المكوِّن خاصياتٍ props جديدة‎ أو تغيّرت حالته state. UNSAFE_componentWillUpdate دالة رد نداء (callback function) التي ستستدعى تلقائيًا قبل أن يستلم المكوِّن خاصياتٍ props جديدة‎ أو تغيّرت حالته state. componentDidUpdate دالة رد نداء (callback function) التي ستستدعى تلقائيًا بعد نقل التحديثات التي جرت على المكوِّن إلى DOM. componentWillUnmount دالة رد نداء (callback function) التي ستستدعى تلقائيًا قبل إزالة المكوِّن من شجرة DOM. أهم خيارات ضبط المكوِّنات هو render، وهذا الخيار مطلوبٌ وهو دالةٌ تعيد عقد ومكونات React. وجميع خيارات ضبط المكوِّنات الأخرى اختيارية. الشيفرة الآتية هي مثالٌ عن إنشاء المكوِّن Timer من عقد React باستخدام createReactClass()‎ (سنستخدم الحزمة create-react-class في هذا المثال لترى كيف تستعمل، وسنستعمل الأصناف في ES6 لإنشاء بقية مكونات React لاحقًا). احرص على قراءة التعليقات في الشيفرة: var createReactClass = require('create-react-class'); // وتمرير كائن من خيارات الضبط Timer إنشاء المكون var Timer = createReactClass({ // this.state دالة تعيد كائنًا والذي سيصبح قيمة getInitialState: function() { return { secondsElapsed: Number(this.props.startTime) || 0 }; }, tick: function() { // تابع مخصص this.setState({ secondsElapsed: this.state.secondsElapsed + 1 }); }, componentDidMount: function() { // دالة رد النداء لدورة حياة المكوِّن this.interval = setInterval(this.tick, 1000); }, componentWillUnmount: function() { // دالة رد النداء لدورة حياة المكوِّن clearInterval(this.interval); }, render: function() { // JSX باستخدام صيغة React دالة تعيد عقد return ( <div> Seconds Elapsed: {this.state.secondsElapsed} </div> ); } }); ReactDOM.render(< Timer startTime="60" />, app); // startTime تمرير قيمة الخاصية تبدو الشيفرة السابقة طويلةً، لكن أغلبية الشيفرة السابقة تُنشِئ المكوِّن بتمرير كائن إلى الدالة createReactClass()‎ لإنشاء مكوِّنٍ مع كائن ضبط يحتوي على خمس خاصيات (وهي getInitialState و tick و componentDidMount و componentWillUnmount و render). لاحظ أنَّ اسم المكوِّن Timer يبدأ بحرفٍ كبير، فعند إنشاء مكوِّنات React مخصصة، عليك أن تجعل أول حرفٍ من اسمها كبيرًا. أضف إلى ذلك أنَّ القيمة this ضمن خيارات الضبط تُشير إلى نسخة المكوِّن المُنشَأة. سنناقش الواجهة البرمجية للمكوِّنات بالتفصيل في نهاية هذا الدرس، لكن دعنا نتأمل خيارات الضبط المتاحة عند تعريف مكوِّن React وكيف استطعنا الإشارة إلى المكوِّن باستخدام الكلمة المحجوزة this. لاحظ أيضًا أنني أضفت في المثال السابق تابعًا خاصًا بالمكوِّن (وهو tick). بعد تركيب (mount) المكوِّن، فيمكننا استخدام الواجهة البرمجية التي تحتوي على أربعة توابع، وهي مبيّنة في الجدول الآتي: التابع مثال الشرح setState()‎ this.setState({mykey: 'my new value'}); this.setState(function(previousState, currentProps) { return {myInteger: previousState.myInteger + 1}; });‎ التابع الرئيسي التي يُستخدَم لإعادة تصيير المكوِّن ومكوناته الفرعية. ForceUpdate()‎ this.forceUpdate(function(){//callback});‎ استدعاء التابع forceUpdate()‎ سيؤدي إلى استخدام التابع render()‎ دون استدعاء shouldComponentUpdate()‎. أكثر تابع مستخدم في واجهة المكوِّنات البرمجية هو التابع setState()‎، وسيُشرَح استخدامه في درس حالة مكونات React. ملاحظات تسمى دوال رد النداء في خيارات ضبط المكوِّن (وهي componentWillUnmount و componentDidUpdate و UNSAFE_componentWillUpdate و shouldComponentUpdate و UNSAFE_componentWillReceiveProps و componentDidMount و UNSAFE_componentWillMount)‎ بتوابع دورة الحياة (lifecycle methods) لأنَّ هذه التوابع المختلفة ستُنفَّذ في نقاط معيّنة في دورة حياة المكوِّن. الدالة createReactClass هي دالة تُنشِئ نسخةً من المكوِّنات وهي موجودة في الحزمة create-react-class. الدالة render()‎ هي دالة صرفة، وهذا يعني أنها لا تعدّل حالة المكوِّن، وتعيد نفس النتيجة في كل مرة تستدعى فيها، ولا تقرأ أو تكتب إلى DOM أو تتفاعل مع المتصفح (باستخدام setTimout على سبيل المثال). فإذا أردت التعامل مع المتصفح، فافعل ذلك في التابع componentDidMount()‎ أو غيره من توابع دورة الحياة. الإبقاء على الدالة render()‎ صرفةً يجعل التصيير عمليًا ويُسهِّل التفكير في المكوِّنات. المكونات تعيد عقدة أو مكون واحد قيمة خيار الضبط render التي تُعرَّف عند إنشاء المكوِّن يجب أن تعيد مكوِّن أو عقدة React واحدة فقط. هذه العقدة أو المكون يمكن أن تحتوي على أي عدد من الأبناء. عقدة البداية في الشيفرة الآتية يمكن أن تحتوي هذه العقدة على أي عدد من العقد الأبناء: class MyComponent extends React.Component { render() { return <reactNode> <span>test</span> <span>test</span> </reactNode>; } }; ReactDOM.render(<MyComponent />, app); لاحظ أننا تستطيع إعادة عقد React بجعلها على عدّة أسطر، ويمكنك أن تحيط القيمة المعادة بقوسين هلاليين (). لاحظ كيف أعدنا المكوِّن MyComponent المُعرَّف باستخدام JSX بوضعه بين قوسين: class MyComponent extends React.Component { render() { return ( <reactNode> <span>test</span> <span>test</span> </reactNode> ); } }; ReactDOM.render(<MyComponent />, app); سيحدث خطأ إذا حاولنا إعادة أكثر من عقدة React واحدة. يمكنك أن تفكر فيها مليًا، فالخطأ يحدث لأنَّ من غير الممكن إعادة دالتَي React.createElement()‎ باستخدام JavaScript. class MyComponent extends React.Component { render() { return ( <span>test</span> <span>test</span> ); } }; ReactDOM.render(<MyComponent />, app); ستؤدي الشيفرة السابقة إلى حدوث الخطأ الآتي: Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag (8:3) 6 | return ( 7 | <span>test</span> \> 8 | <span>test</span> | ^ 9 | ); 10 | } 11 | }); من الشائع أن نرى المطورين يضيفون عنصر حاوي لتفادي هذا الخطأ. هذه المشكلة تؤثر على المكوِّنات أيضًا كما تؤثر على عقد React. فلا يمكن إعادة إلا مكوِّنٍ وحيد، ولكن يمكن أن يمتلك هذا المكوِّن عددًا غير محدودٍ من الأبناء. class MyComponent extends React.Component { render() { return ( <MyChildComponent/> ); } }; class MyChildComponent extends React.Component { render() { return <test>test</test>; } }; ReactDOM.render(<MyComponent />, app); إذا أعدتَ مكونين متجاورين، فسيحدث نفس الخطأ: var MyComponent = createReactClass({ render: function() { return ( <MyChildComponent/> <AnotherChildComponent/> ); } }); var MyChildComponent = createReactClass({ render: function() {return <test>test</test>;} }); var AnotherChildComponent = createReactClass({ render: function() {return <test>test</test>;} }); ReactDOM.render(<MyComponent />, app); رسالة الخطأ: Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag (8:2) 6 | return ( 7 | <MyChildComponent/> \> 8 | <AnotherChildComponent/> | ^ 9 | ); 10 | } 11 | }); الإشارة إلى نسخة المكون عندما يُصيّر أحد العناصر (render) فستُنشأ نسخة من مكوِّن React من الخيارات المُمرَّرة إليه، يمكننا الوصول إلى هذه النسخة (instance) وخاصياتها (مثل this.props) وتوابعها (مثل this.setState()‎) بطريقتين. أوّل طريقة هي استخدام الكلمة المحجوزة this داخل دالة ضبط المكوِّن. ففي المثال الآتي، جميع تعابير console.log(this) ستُشير إلى نسخة المكوِّن: class Foo extends React.Component { componentWillMount(){ console.log(this); } componentDidMount(){ console.log(this); } render() { return <div>{console.log(this)}</div>; } }; ReactDOM.render(<Foo />, document.getElementById('app')); الطريقة الأخرى للحصول على مرجعية لنسخة المكوِّن تتضمن استخدام القيمة المُعادة من استدعاء الدالة ReactDOM.render()‎. بعبارةٍ أخرى، ستُعيد الدالة ReactDOM.render()‎ مرجعيةً إلى أعلى مكوِّن جرى تصييره: class Bar extends React.Component { render() { return <div></div>; } }; var foo; // تخزين مرجعية إلى النسخة خارج دالة class Foo extends React.Component { render() { return <Bar>{foo = this}</Bar>; } }; var FooInstance = ReactDOM.render(<Foo />, document.getElementById('app')); // Foo التأكد أنَّ القيمة المُعادة هي مرجعية إلى نسخة console.log(FooInstance === foo); // true الناتج ملاحظات تُستخدَم الكلمة المحجوزة this داخل المكوِّن للوصول إلى خصائص المكوِّن كما في this.props.[NAME OF PROP] و this.props.children و this.state. يمكن أن تستخدم أيضًا لاستدعاء خاصيات وتوابع الصنف التي تتشاركها جميع المكوِّنات مثل this.setState‎. تعريف الأحداث في المكونات يمكن إضافة الأحداث إلى عقد React داخل خيار الضبط render كما ناقشنا سابقًا. سنضبط -في المثال الآتي- حدثَي React (وهما onClick و onMouseOver) على عقد React بصيغة JSX كما لو كنّا نضبط خيارات المكوِّن: class MyComponent extends React.Component { mouseOverHandler(e) { console.log('you moused over'); console.log(e); // sysnthetic event instance } clickHandler(e) { console.log('you clicked'); console.log(e); // sysnthetic event instance } render(){ return ( <div onClick={this.clickHandler} onMouseOver={this.mouseOverHandler}>click or mouse over</div> ) } }; ReactDOM.render(<MyComponent />, document.getElementById('app')); عندما تُصيّر React مكوِّنًا فستبحث عن خاصيات ضبط الأحداث في React (مثل onClick)، وتعامل هذه الخاصيات معاملةً مختلفةً عن بقية الخاصيات (جميع أحداث React مذكورة في الجدول أدناه). ومن الجلي أنَّ الأحداث في شجرة DOM الحقيقية سترتبط مع معالجاتها وراء الكواليس. أحد جوانب هذا الارتباط هو جعل سياق دالة معالجة الحدث في نفس مجال (scope) نسخة المكوِّن. لاحظ أنَّ قيمة this داخل دالة معالجة الحدث ففي المثال الآتي ستُشير إلى نسخة المكوِّن نفسها. class MyComponent extends React.Component { constructor(props) { super(props); // this هذا الربط ضروري لتعمل this.mouseOverHandler = this.mouseOverHandler.bind(this); } mouseOverHandler(e) { console.log(this); // إلى نسخة الكائن this تشير console.log(e); // sysnthetic event instance } render(){ return ( <div onMouseOver={this.mouseOverHandler}>mouse over me</div> ) } }; ReactDOM.render(<MyComponent />, document.getElementById('app')); تدعم React الأحداث الآتية: نوع الحدث الأحداث خاصيات متعلقة به الحافظة OnCopy onCut onPaste DOMDataTransfer clipboardData التركيب OnCompositionEnd onCompositionStart onCompositionUpdate data لوحة المفاتيح OnKeyDown onKeyPress onKeyUp AltKey charCode ctrlKey getModifierState(key) key keyCode locale location metaKey repeat shiftKey which التركيز OnChange onInput onSubmit DOMEventTarget relatedTarget النماذج OnFocus onBlur الفأرة OnClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp AltKey button buttons clientX clientY ctrlKey getModifierState(key) metaKey pageX pageY DOMEventTarget relatedTarget screenX screenY shiftKey الاختيار onSelect اللمس OnTouchCancel onTouchEnd onTouchMove onTouchStart AltKey DOMTouchList changedTouches ctrlKey getModifierState(key) metaKey shiftKey DOMTouchList targetTouches DOMTouchList touches واجهة المستخدم onScroll Detail DOMAbstractView view الدولاب onWheel DeltaMode deltaX deltaY deltaZ الوسائط OnAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPauseonPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting الصور onLoad onError الحركات onAnimationStart onAnimationEnd onAnimationIteration animationName pseudoElement elapsedTime الانتقالات onTransitionEnd propertyName pseudoElement elapsedTime ملاحظات توحِّد React التعامل مع الأحداث لكي تسلك سلوكًا متماثلًا في جميع المتصفحات. تنطلق الأحداث في React في مرحلة الفقاعات (bubbling phase). لإطلاق حدث في مرحلة الالتقاط (capturing phase) فأضف الكلمة "Capture" إلى اسم الحدث، أي أنَّ الحدث onClick سيصبح onClickCapture). إذا احتجتَ إلى تفاصيل كائن الأحداث المُنشَأ من المتصفح، فيمكنك الوصول إليه باستخدام الخاصية nativeEvent في كائن SyntheticEvent المُمرَّر إلى دالة معالجة الأحداث في React. لا تربط React الأحداث إلى العقد نفسها، وإنما تستخدم «تفويض الأحداث» (event delegation). يجب استخدام e.stopPropagation()‎ أو e.preventDefault()‎ يدويًا لإيقاف انتشار الأحداث بدلًا من استخدام return false;‎. لا تدعم React جميع أحداث DOM، لكن ما يزال بإمكاننا الاستفادة منها باستخدام توابع دورة الحياة في React. تركيب المكونات إذا لم يكن واضحًا لك أنَّ مكوِّنات React تستطيع أن تستخدم مكوِّنات React الأخرى فاعلم أنَّها تستطيع فعل ذلك. فيمكن أن تحتوي دالة الضبط render عند تعريف أحد مكوِّنات React إشارةً إلى المكونات الأخرى. فعندما يحتوي مكوِّنٌ ما على مكوِّنٍ آخر فيمكننا أن نقول أنَّ المكوِّن الأب «يمتلك» مكوِّنًا ابنًا (وهذا يسمى بالتركيب [composition]). في الشيفرة أدناه، يحتوي (أو يمتلك) المكوِّن BadgeList المكوِّنين BadgeBill و BadgeTom: class BadgeBill extends React.Component { render() {return <div>Bill</div>;} }; class BadgeTom extends React.Component { render() {return <div>Tom</div>;} }; class BadgeList extends React.Component { render() { return ( <div> <BadgeBill/> <BadgeTom /> </div>); } }; ReactDOM.render(<BadgeList />, document.getElementById('app')); جعلتُ الشيفرة السابقة بسيطةً عمدًا لتوضيح كيفية تركيب المكونات، وسنلقي في الدرس القادم نظرةً عن كيفية كتابة شيفرات التي تستخدم الخاصيات props لإنشاء مكوِّن Badge عام (generic). يمكن أن يأخذ المكوِّن العام Badge أي قيمة مقارنةً مع كتابة Badge مكتوبٌ فيه الاسم سابقًا. ملاحظات سمة أساسية لكتابة واجهات مستخدم قابلة للصيانة والإدارة هو تركيب المكوِّنات. صُمِّمَت مكوِّنات React لتحتوي على مكوِّناتٍ أخرى. لاحظ كيف تندمج شيفرة HTML والمكونات المُعرَّفة مسبقًا مع بعضهما بعضًا في دالة الضبط render()‎. استيعاب دورة حياة المكوِّن تمرّ مكوِّنات React بأحداث خلال حياتها وتسمى هذه الأحداث بدورة الحياة (lifecycle events). ترتبط هذه الأحدث بتوابع دورة الحياة. يمكنك أن تتذكر أننا ناقشنا بعض تلك التوابع في بداية هذا الدرس عندما ناقشنا عملية إنشاء المكوِّنات. توابع دورة الحياة توفِّر ارتباطات مع مراحل وطبيعة المكوِّن. ففي المثال الآتي الذي استعرته من أحد الأقسام السابقة، سنُسجِّل وقوع أحداث دورة الحياة componentDidMount و componentWillUnmount و getInitialState: var createReactClass = require('create-react-class'); // وتمرير كائن من خيارات الضبط Timer إنشاء المكون var Timer = createReactClass({ // this.state دالة تعيد كائنًا والذي سيصبح قيمة getInitialState: function() { return { secondsElapsed: Number(this.props.startTime) || 0 }; }, tick: function() { // تابع مخصص this.setState({ secondsElapsed: this.state.secondsElapsed + 1 }); }, componentDidMount: function() { // دالة رد النداء لدورة حياة المكوِّن this.interval = setInterval(this.tick, 1000); }, componentWillUnmount: function() { // دالة رد النداء لدورة حياة المكوِّن clearInterval(this.interval); }, render: function() { // JSX باستخدام صيغة React دالة تعيد عقد return ( <div> Seconds Elapsed: {this.state.secondsElapsed} </div> ); } }); ReactDOM.render(< Timer startTime="60" />, app); // startTime تمرير قيمة الخاصية يمكن تقسيم هذه التوابع إلى ثلاثة تصنيفات: مرحلة التركيب (mount) والتحديث (update) والإزالة (unmount). سأعرض جدولًا في كل تصنيف يحتوي على توابع دورة الحياة الخاصة به. مرحلة التركيب تحدث مرحلة التركيب (mounting phase) مرةً واحدةً في دورة حياة المكوِّن، وهي أول مرحلة وتبدأ عندما نُهيِّئ المكوِّن، وفي هذه المرحلة ستُعرَّف وتُضبَط خاصيات وحالة المكوِّن، وسيُركَّب المكوِّن مع جميع أبنائه إلى واجهة المستخدم المُحدَّدة (سواءً كانت DOM أو UIView أو غيرها). وفي النهاية يمكننا أن نجري بعض عمليات المعالجة إن كان ذلك لازمًا. التابع الشرح getInitialState()‎ سيستدعى قبل تركيب المكوِّن، ويجب أن تعرِّف المكونات ذات الحالة (stateful) هذا التابع وتعيد بيانات الحالة الابتدائية. componentWillMount()‎ سيستدعى مباشرةً قبل تركيب المكوِّن. componentDidMount()‎ سيستدعى مباشرةً بعد تركيب المكوِّن. عملية التهيئة التي تتطلب وجود عقد DOM ستُعرَّف في هذا التابع. مرحلة التحديث تقع مرحلة التحديث (updating phase) مرارًا وتكرارًا خلال دورة حياة المكوِّن، وفي هذه المرحلة يمكننا إضافة خاصيات جديدة أو تغيير الحالة أو معالجة تفاعلات المستخدم أو التواصل مع شجرة المكوِّنات، وسنقضي جُلَّ وقتنا في هذه المرحلة. التابع الشرح componentWillReceiveProps(object nextProps)‎ * shouldComponentUpdate(object nextProps, object nextState)‎ سيستدعى عندما يقرر المكوِّن أنَّ أي تغييرات ستحتاج إلى تحديث شجرة DOM. إذا أردت استخدامه فيجب أن تقارن this.props مع nextProps و this.state مع nextState وتُعيد القيمة false لتخبر React بإمكانية تجاوز التحديث. componentWillUpdate(object nextProps, object nextState)‎ سيستدعى مباشرةً قبل وقوع التحديث. لا يمكنك استدعاء this.setState()‎ هنا. componentDidUpdate(object prevProps, object prevState)‎ سيستدعى مباشرةً بعد وقوع التحديث. مرحلة الإزالة تقع مرحلة الإزالة (unmounting phase) مرةً واحدةً في دورة حياة المكوِّنات، وهي تحدث عند إزالة نسخة المكوِّن من واجهة المستخدم. ويمكن أن يحدث ذلك عندما ينتقل المستخدم إلى صفحة أخرى أو تتغير واجهة المستخدم أو اختفى المكوِّن …إلخ. التابع الشرح componentWillUnmount()‎ سيستدعى مباشرةً قبل إزالة المكوِّن وحذفه. يجب أن تأتي عمليات «التنظيف» هنا. ملاحظات التابعان componentDidMount و componentDidUpdate هما مكانان جيدان تضع فيهما البنى المنطقية للمكتبات. راجع توثيق React في موسوعة حسوب لتأخذ نظرةً تفصيليةً حول أحداث دورة حياة مكونات React. ترتيب مرحلة التركيب: التهيئة الابتدائية getDefaultProps()‎ ‏(React.createClass) أو MyComponent.defaultProps (صنف ES6) getInitialState()‎ ‏(React.createClass) أو this.state (دالة بانية في ES6) componentWillMount()‎ render()‎ عملية تهيئة الأبناء وضبط دورة حياتهم componentDidMount()‎ ترتيب مرحلة التحديث: componentWillReceiveProps()‎ shouldComponentUpdate()‎ render()‎ توابع دورة الحياة للأبناء componentWillUpdate()‎ ترتيب مرحلة الإزالة: componentWillUnmount()‎ توابع دورة الحياة للأبناء إزالة نسخة المكوِّن الوصول إلى المكونات أو العقد الأبناء إذا احتوى مكوِّنٌ على مكونات أبناء أو عقد React داخله (كما في أو test) فيمكن الوصول إلى عقد React أو نسخ المكوِّنات الأبناء باستخدام الخاصية this.props.children. عند استخدام المكوِّن Parent في الشيفرة التالية، الذي يحتوي على عنصرَي والتي بدورها تحتوي على عقد React نصية. يمكن الوصول إلى جميع نسخ الأبناء داخل المكوِّن باستخدام this.props.children. وسأحاول في المثال الآتي أن أصل إليها داخل تابع دورة الحياة componentDidMount للعنصر الأب Parent: class Parent2 extends React.Component { componentDidMount() { // <span>child2text</span> الوصول إلى // ولا حاجة لاستخدام مصفوفة لطالما كان هنالك ابن واحد فقط console.log(this.props.children); // <span> لأننا نحصل على ابن العنصر child2text سينتج console.log(this.props.children.props.children); } render() {return <div />;} } class Parent extends React.Component { componentDidMount() { // <div>test</div><div>test</div> الوصول إلى مصفوفة تحتوي على console.log(this.props.children); // في المصفوفة <div> لأننا نصل إلى أول عنصر childtext سينتج console.log(this.props.children[1].props.children); } render() {return <Parent2><span>child2text</span></Parent2>;} } ReactDOM.render( <Parent><div>child</div><div>childtext</div></Parent>, document.getElementById('app') ); تعيد الخاصية this.props.children للمكوِّن Parent مصفوفةً تحتوي على إشارات لنسخ كائنات عقد React الأبناء. سنعرض هذه المصفوفة باستخدام console.log، أضف إلى ذلك أننا سنعرض في المكوِّن Parent قيمة العنصر الابن للعقدة الأولى (أي سنعرض قيمة العقدة النصية). لاحظ عندما استخدمنا المكوِّن Parent2 داخل المكوِّن Parent كان المكوِّن Parent2 يحتوي على عقدة React وحيدة هي child2text وبالتالي ستكون قيمة الخاصية this.props.children في تابع دورة الحياة componentDidMount للمكوِّن Parent2 هي إشارة مباشرة إلى عقدة في React، وليست مصفوفةً تحتوي على عنصرٍ وحيد. ولمّا كان من المحتمل أن تعيد الخاصية this.props.children مجموعةً واسعةً من العقد، فتوفِّر React مجموعةً من الأدوات للتعامل معها، وهذه الأدوات مذكورة في الجدول أدناه. الأداة الشرح React.Children.map(this.props.children, function(){})‎ تستدعي دالة لكل عنصر ابن مباشر موجود ضمن children مع تعيين this إلى قيمة thisArg. إن كان children عبارة عن جزء (fragment) مع مفتاح أو مصفوفة فلن تُمرَّر الدالة للكائن الحاوي. إن كانت قيمة children هي null أو undefined فستُعيد null أو undefined بدلًا من المصفوفة. React.Children.forEach(this.props.children, function(){})‎ مماثلة للتابع React.Children.map()‎ ولكن لا تُعيد مصفوفة. React.Children.count(this.props.children)‎ تُعيد العدد الكلي للمكوّنات الموجود ضمن children، مُكافئ لعدد المرات التي يُمرَّر فيها رد النداء إلى map أو التي يُستدعى فيها forEach. React.Children.only(this.props.children)‎ تتحقّق من أنّ children يمتلك فقط ابنًا واحدًا (عنصر React) وتُعيده. فيما عدا ذلك سيرمي هذا التابع خطأً. React.Children.toArray(this.props.children)‎ تُعيد بنية البيانات children كمصفوفة مع تعيين مفتاح لكل عنصر ابن. تكون مفيدةً إن أردت التعامل مع مجموعة من العناصر الأبناء في توابع التصيير لديك، خاصّة إن أردت إعادة ترتيب أو تجزئة this.props.children قبل تمريره. ملاحظات عندما يكون هنالك عنصرٌ ابن وحيد، فستكون قيمة this.props.children هي العنصر نفسه دون أن يحتوى في مصفوفة. وهذا يوفِّر عملية تهيئة المصفوفة. قد يربكك بدايةً أنَّ قيمة children ليست ما يعيده المكوِّن، وإنما ما هو محتوى داخل المكوِّن. استخدام الخاصيات ref تجعل الخاصية ref من الممكن تخزين نسخة من عنصر أو مكوِّن React معيّن باستخدام دالة الضبط render()‎. وهذا مفيدٌ جدًا عندما تريد الإشارة من داخل المكوِّن إلى عنصر أو مكوِّن آخر محتوى داخل الدالة render()‎. لإنشاء مرجعية، ضع الخاصية ref مع ضبط دالة كقيمةٍ لها في أي عنصر أو مكوِّن، ثم من داخل الدالة سيكون أول معامل (parameter) داخل مجال الدالة يشير إلى العنصر أو المكوِّن الذي عُرِّفَت الخاصية ref عليه. على سبيل المثال، سنعرض المحتويات المرجعية المشار إليها باستخدام ref عبر console.log: class C2 extends React.Component { render() {return <span ref={function(span) {console.log(span)}} />} } class C1 extends React.Component { render() { return( <div> <C2 ref={function(c2) {console.log(c2)}}></C2> <div ref={function(div) {console.log(div)}}></div> </div>); } } ReactDOM.render(<C1 ref={function(ci) {console.log(ci)}} />,document.getElementById('app')); لاحظ أنَّ الإشارات إلى المرجعيات تعيد نسخ المكوِّنات، بينما الإشارات إلى عناصر React تعيد مرجعيات إلى عناصر DOM في شجرة DOM الحقيقية (أي ليست مرجعيةً تشير إلى شجرة DOM الافتراضية، وإنما شجرة DOM الحقيقية). استخدامٌ شائعٌ للخاصية ref هو تخزين مرجعية إلى نسخة المكوِّن. ففي الشيفرة الآتية سأستخدم دالة رد نداء ref على حقل إدخال input نصي لتخزين مرجعية لنسخة المكوِّن لكي تستطيع التوابع الأخرى الوصول إليها عبر الكلمة المحجوزة this (كما في this.textInput.focus()‎): class MyComponent extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this) } handleClick() { // DOM API التركيز على المحتوى النصية باستخدام this.textInput.focus(); } render() { // قيمة الخاصية ref هي دالة رد نداء التي تؤدي إلى // عند تركيب المكون this.textInput الإشارة إلى return ( <div> <input type="text" ref={(thisInput) => {this.textInput = thisInput}} /> <input type="button" value="Focus the text input" onClick={this.handleClick} /> </div> ); } } ReactDOM.render( <MyComponent />, document.getElementById('app') ); ملاحظات لا يمكن ربط ref مع دالة عديم الحالة لأنَّ المكوِّن لا يملك نسخةً (instance) بعد. ربما تشاهد الخاصية ref مع سلسلة نصية بدلًا من دالة؛ وهذا أمرٌ مهمل في الإصدارات المستقبلية، ومن المُفضَّل استخدام الدوال. ستستدعى دالة رد نداء ref مباشرةً بعد تركيب المكوِّن. تسمح لنا الإشارات إلى نسخة المكوِّن باستدعاء توابع مخصصة على المكوِّن إذا كانت موجودةً عند تعريفه. كتابة المراجع مع تعبير تعريف دالة سطري يعني أنَّ React سترى كائن دالة مختلف في كل تحديث، وستستدعى ref مع القيمة null مباشرةً قبل استدعائها مع نسخة المكوِّن، أي أنَّ نسخة المكون ستزال في كل تغيير لقيمة ref وستستدعى ref القديمة مع القيمة null كوسيط. يبين توثيق React ملاحظةً مهمةً «ربّما تكون رغبتك الأولى لاستخدام المراجع هي تحقيق كل ما تُريده في تطبيقك. إن كانت هذه حالتك فخُذ لحظة للتفكير حول المكان المُلائم لوضع الحالة في التسلسل الهرمي للمُكوِّنات. يتضح عادةً أنّ المكان المناسب لوضع الحالة هو في المستويات العليا من التسلسل الهرمي للمُكوِّنات.». إجبار إعادة تصيير العنصر من المرجّح أنَّ: لاحظتَ أنَّ استدعاء ReactDOM.render()‎ هو عملية التحميل الابتدائية للمكوِّن وجميع المكونات الفرعية له. وبعد عملية التركيب الابتدائية للمكوِّنات، ستحدث إعادة التصيير عندما: استدعي التابع setState()‎ في المكوِّن استدعي التابع forceUpdate()‎ في المكوِّن في أي وقت يجير إعادة تصيير المكوِّن (أو يُصيّر التصيير الابتدائي) فستُصيّر جميع المكوِّنات الأبناء التابعة له داخل شجرة DOM الافتراضية والتي قد تُسبِّب تغييرًا في شجرة DOM الحقيقية (أي واجهة المستخدم). ما أريد إيصاله لك هنا هو أنَّ إعادة تصيير أحد المكوِّنات في شجرة DOM الافتراضية لا يعني بالضرورة أنَّ تحديثًا سيطرأ على شجرة DOM الحقيقية. في المثال أدناه، سيبدأ استدعاء ReactDOM.render(< App / >, app);‎ عملية التصيير، والذي سيؤدي إلى تصيير و ، عملية إعادة التصيير التالية ستحدث عند استخدام setInterval()‎ لتابع المكوِّن setState()‎ الذي سيؤدي إلى إعادة تصيير و ، لاحظ كيف ستتغير واجهة المستخدم عند تغيير حالة now: var Timer = createReactClass({ render: function() { return ( <div>{this.props.now}</div> ) } }); var App = createReactClass({ getInitialState: function() { return {now: Date.now()}; }, componentDidMount: function() { var foo = setInterval(function() { this.setState({now: Date.now()}); }.bind(this), 1000); setTimeout(function(){ clearInterval(foo); }, 5000); // .forceUpdate() لا تفعل هذا! هذا مجرد مثال توضيحي عن استخدام setTimeout(function(){ this.state.now = 'foo'; this.forceUpdate() }.bind(this), 10000); }, render: function() { return ( <Timer now={this.state.now}></Timer> ) } }); ReactDOM.render(< App />, app); تحدث عملية إعادة التصيير الآتية عند تشغيل setTimout()‎ واستدعاء التابع this.forceUpdate()‎ لاحظ أنَّ تحديث الحالة (this.state.now = 'foo';‎) لن تؤدي بمفردها إلى إعادة التصيير. ضبنا بداية الحالة باستخدام this.state ثم استدعينا this.forceUpdate()‎ لكي يعاد تصيير العنصر مع الحالة الجديدة. ملاحظات لا تُحدِّث الحالة باستخدام this.state إطلاقًا! فعلنا ذلك في المثال السابق لتبيين طريقة استخدام this.forceUpdate()‎ فحسب. ترجمة -وبتصرف- للفصل Basic React Components من كتاب React Enlightenment 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; }
  10. تقودنا معرفتنا بالأعداد الثنائية إلى التعرف على بنية عناوين IP وأفضل الطرق لحجزها؛ إذ سنشرح في هذا الدرس العمليات على الشبكات ذات الفئات (classful) أو عديمة الفئات (classless)، بما في ذلك استعمال الشبكات الفرعية (subnets)؛ وسنشرح مستخدمين أمثلةً واقعيةً تصف عملية حساب عناوينIP للمضيفين؛ وسنشرح أيضًا استعمال قناع الشبكة الفرعية (subnet mask)، وكيف تُستعمَل من الموجِّهات. وستتاح لك الفرصة للتدرب على العمليات على قناع الشبكة الفرعية بعناوين IP ذات الفئات A، و B، و C. مخطط الشبكات المسطحة عندما نتحدث عن التوجيه، فنميل إلى التفكير بتمرير الرزم الشبكية إلى الوجهات البعيدة؛ وأول ما سيطرأ ببالنا هي شبكات WAN والإنترنت؛ لكن من المنطقي استعمال التوجيه في شبكة الحرم الجامعي مثلًا، أو حتى في شبكات محلية صغيرة لخدمة غرض تقسيم البيانات التراسليّة (traffic segmentation)؛ فإن لم يكن لديك موجه في شبكتك، فهذا يعني أننا نتحدث عن شبكة مسطحة (flat) حيث فيها كل الأجهزة متصلة إلى نفس «القطعة» (segment) المنطقية؛ تُمثِّل القطعة المنطقية مجالًا إذاعيًا، ولهذا السبب ستتشارك جميع الأجهزة في شبكةٍ مسطحةٍ مجالَ الإذاعة نفسه مما يعني أنَّها ستشاهد جميع الرسائل الإذاعية المُرسَلة من بقية الأجهزة، مما يؤثِّر على أداء الشبكة. المُكوِّن الوحيد الذكي في آلية ترشيح الرزم الشبكية هي المبدِّلات التي تعمل في الطبقة الثانية، التي تمرِّر الرزم الشبكيّة بناءً على عناوين MAC؛ وتلك العناوين ليست ذاتُ بنيةٍ هيكليةٍ مما يجعل الشبكة «مسطحة». وكلما أضفت أجهزةً إلى الشبكة، فسيقل مستوى الأداء؛ يمكن أن تُستعمَل الموجِّهات في مثل هذه الحالات لتقسيم الشبكة إلى عدِّة مجالاتٍ إذاعية أو شبكاتٍ فرعية. الشبكات الفرعية المزايا التي سنحصل عليها لا ترتبط بتحسين الأداء فحسب، بل عندما تُقطِّع الشبكة إلى شبكاتٍ فرعيّة مختلفة، فسيقل تراسل البيانات الإجمالي، وستمثِّل كل شبكة فرعية مجالًا إذاعيًا مختلفًا، ولهذا فلن تستطيع البيانات الإذاعية القادمة من قسم «الهندسة» -في هذا المثال- الوصول إلى قسم «التصنيع». يمنع الموجِّه مرور الرسائل الإذاعية؛ لكن هنالك المزيد من الميزات التي تأتي من الشبكات الفرعية؛ إذ يُمكِّنك تُقسيم الشبكة إلى قطعٍ صغيرة من اتباع منهجية «فرِّق تسد» لتسهيل الإدارة؛ ويُمكِّنك أيضًا من تطبيق سياسات (polices) مختلفة خاصة بكل قطعة من قطع الشبكة؛ إذ يُطبِّق الموجِّه السياسة المُعتمَدة، لأنه يتحكم بمرور البيانات من شبكةٍ فرعيةٍ إلى أخرى، وهذا يؤدي أيضًا إلى عزل مشاكل الشبكات؛ فلو حدث عطبٌ ما في شبكةٍ فرعيةٍ، فلن يكون له تأثيرٌ يُذكر على بقيّة الشبكات. تتعلق المزايا الأخرى بالأمان؛ فلن تستطيع هجمات الحرمان من الخدمة (denial of service) الوصول إلى الشبكات الفرعية الأخرى إن كان يعمل الموجِّه كجدارٍ ناريٍ بينهم. وبغض النظر عن سبب تقسيمك للشبكة إلى شبكاتٍ فرعية، فيجب أن نُسنِد لكل شبكةٍ فرعيةٍ مُعرِّفًا فريدًا (subnet ID) ثم سيكون للمضيفين في تلك الشبكة الفرعية «مُعرِّف مضيف» (host ID) فريد في عنوان IP. ماذا يفعل قناع الشبكة الفرعية كيف نستطيع معرفة أي قسم من عنوان IP خاصٌ بالشبكة أو خاصٌ بالمضيف؟ في الشبكات ذات الفئات (classful)، ستخبرنا الفئة أيّة بايتات مخصصة لمعرِّف الشبكة وأيّة بايتات مخصصة للمضيف؛ وعندما نُنشِئ شبكة فرعية لعنوان IP ذي فئةٍ معيّنة، فإننا «نسرق» بعض البتات من قسم المضيف من العنوان ونجعلها جزءًا من قسم الشبكة الفرعية في العنوان؛ وبهذا تصبح لدينا «طبقة» جديدة في الهيكلية، إذ لدينا شبكة مُعرَّفة عبر فئة (class) ثم شبكة فرعية ثم المضيف؛ حيث نُقسِّم الشبكات إلى شبكاتٍ فرعية ثم ستحتوي تلك الشبكات الفرعية المضيفين. تلك الهيكلية شبيهة بنظام الترقيم الهاتفي؛ لدينا رمز الدولة ثم رمز المدينة ثم أرقام الهواتف؛ وهذه بيئة عديمة الفئات؛ أما في بيئة ذات فئات، فإن الفئة لا تخبرنا أيّ جزء من العنوان مخصص للشبكة أو للشبكة الفرعية أو للمضيفين؛ إذ أنَّ تلك المعلومات موجودة في قناع الشبكة الفرعية، الذي يخبرنا بآلية تقسيم العناوين. وفي هذا السياق، لا يشبه قناع الشبكة الفرعية الأقنعة التي يرتديها الأولاد الصغار؛ وإنما مَثَلُه كمَثَلِ نظارةٍ لتنظر إلى العناوين بشكلٍ مختلف. وهو أداة قياس تخبرك بطول قسم الشبكة من العنوان، ثم قسم الشبكة الفرعية، ثم ما بقي مُخصصٌ للمضيفين. الشبكات الفرعية والمضيفون المحتملون في شبكة ذات الفئة C سيُستعمَل قناع الشبكة الفرعية من المضيفين للتعرف على بيانات التراسل التي تخرج من شبكتهم الفرعية، وسيُستعمَل أيضًا من الموجِّهات للتعرف على الشبكات والشبكات الفرعية ليكون قادرًا على تمرير الرزم الشبكيّة بينها. وإذا ابتغينا الدقة، القناع ما هو إلا آليةٌ لاقتراض البتات، فالمثال هنا يتحدث عن شبكة ذات الفئة C؛ تخبرنا الفئة C أنَّ أول ثلاثة بايتات من العنوان تُمثِّل قسم الشبكة، بينما يمثِّل آخر بايت قسم المضيفين؛ وعندما نُنشِئ شبكةً فرعيةً فستبقى بايتات الشبكة ثابتةً، وسنحتاج إلى استخدام بعض البايتات المخصصة للمضيفين للشبكة الفرعية؛ القاعدة العامة هنا هي أننا «نقترض» البايتات، بكلامٍ آخر، كلما أخذنا بايتات أكثر من قسم المضيف، كلما قلّ عدد المضيفين الذي يمكن أن يتواجدوا في الشبكة الفرعية، لكن سيزداد بذلك عدد الشبكات الفرعية التي سنُنشِئها؛ حيث يعتمد عدد الشبكات الفرعية وعدد المضيفين على عدد البتات التي سنقترضها، الذي سيكون من قوى الأساس 2. table{border: 1px solid black; border-collapse: collapse} table, th, td{border: 1px solid black;} th{background-color: white;} عدد البتات المُقتَرَضة (s) عدد الشبكات الفرعية المحتملة (2s) عدد البتات الباقية في قسم مُعرِّف المضيف (8 - s = h) عدد المضيفين المحتملين في كل شبكة فرعية (2h - s) 1 2 7 128 2 4 6 64 3 8 5 32 4 16 4 16 5 32 3 8 6 64 2 4 7 128 1 2 في هذا المثال عن الفئة C، يمكننا أن نفرض عدد البتات التي سنقترضها (رمزنا لها بالرمز S)، ثم سيعطينا ذلك H الذي هو عدد المضيفين، إذ أنَّ H هو ناتج ‎8-S. تذكَّر أنَّه كلما اقترضنا بتات للشبكات الفرعية، كلما قلَّ عدد المضيفين الذي يمكن أن يصبحوا جزءًا منها، وأنَّ عدد البتات الكلي الذي يمكنك اقتراضه في شبكات ذات الفئة C هو 8. إذا استعملنا بتًا وحيدًا، فيمكننا تمثيل «2 للأس 1» كعدد للشبكات الفرعية التي حاصلها هو شبكتان فرعيتان؛ مما يبقي لنا 7 بتات للمضيف، وهذا يعني 126 احتمالًا مختلفًا لعناوين المضيفين في كل شبكة فرعية؛ لاحظ أنَّ 2 للأس 7 تُعطي 128، لكن هنالك عنوانان محجوزان يُمثِّلان الشبكة نفسها وعنوان الإذاعة. ستحصل على نتائج مشابهة إذ اقترضت المزيد من البتات؛ لكن تذكر أنَّه كلما اقترضت بتاتٍ أكثر، كلما قل عدد المضيفين في شبكتك الفرعية. الشبكات الفرعية والمضيفون المحتملون في شبكة ذات الفئة B لدينا المزيد من البتات في قسم المضيف لنقترض منها في الفئة B؛ حيث أنَّ الطريقة مشابهة جدًا لما شرحناه أعلاه؛ ففي هذا المثال سنقترض -مثلًا- 4 بتات (إذ لدينا 16 شبكة فرعية في شبكةٍ ذات الفئة B) مما يُبقي لدينا 12 بت للمضيفين؛ وفي هذه المرة لدينا 16 بت ناقص 4 يساوي 12؛ و2 للقوة 12 تُنتِج 4096؛ ثم سنطرح عنوانين محجوزين مما يُبقي 4094 مضيفًا في كل شبكة فرعية. عدد البتات المُقتَرَضة (s) عدد الشبكات الفرعية المحتملة (2s) عدد البتات الباقية في قسم مُعرِّف المضيف (8 - s = h) عدد المضيفين المحتملين في كل شبكة فرعية (2h - s) 1 2 15 32766 2 4 14 16382 3 8 13 8190 4 16 12 4094 5 32 11 2046 6 64 10 1022 7 128 9 510 ... ... ... ... الشبكات الفرعية والمضيفون المحتملون في شبكة ذات الفئة A والأمر سيانٌ للشبكات ذات الفئة A؛ لكننا نتملك هذه المرة عددًا أكبر من البتات لنقترضها، وهذه الفئة هي أكثر الفئات مرونةً فيما يتعلق بموضوع الشبكات الفرعية، وهذا هو سبب اشتهار الشبكة 10 (عنوان من الفئة A للشبكات الخاصة [private]) كأكثر عناوين الشبكات الخاصة استعمالًا. وبهذا يمكننا أن نقترض البايت الثاني بأكمله لتمثيل الشبكة الفرعية، وتبقى لدينا إمكانية وصل عدِّة آلاف من المضيفين في كل شبكة فرعية. عدد البتات المُقتَرَضة (s) عدد الشبكات الفرعية المحتملة (2s) عدد البتات الباقية في قسم مُعرِّف المضيف (8 - s = h) عدد المضيفين المحتملين في كل شبكة فرعية (2h - s) 1 2 23 8388606 2 4 22 4194302 3 8 21 2097150 4 16 20 1048574 5 32 19 524286 6 64 18 262142 7 128 17 131070 ... ... ... ... آلية عمل القناع في المضيفين سيستخدم المضيفون قناع الشبكة الفرعية للتعرف على الشبكة التي يتواجدون فيها من ناحية هيكلية عنوان IP؛ ثم سيقارنون تلك الشبكة مع عنوان الوجهة للرزم الشبكية المُرسَلة منهم؛ فإن طابق عنوانُ الوجهة الشبكةَ التي يتواجدون فيها اعتمادًا على قيمة القناع، فسيحاولون إرسال طلبية ARP لمحاولة الحصول على عنوان MAC للوجهة، ثم سيمررون الرزم مباشرةً إلى الوجهة في الشبكة الفرعية المحلية. أما لو لم تتطابق الشبكة في المصدر والوجهة، فهذا يعني أنَّ الوجهة في شبكةٍ أخرى وسنحتاج إلى عنوان IP للموجِّه لتمرير الرزم إلى الوجهة البعيدة؛ وعنوان الموجه ما هو إلا البوابة الافتراضية المضبوطة في كل جهاز من أجهزة الشبكة. كيف تستعمل الموجهات قناع الشبكة الفرعية آلية عمل قناع الشبكة الفرعية هي ذاتها في الموجِّهات، لكن الموجِّهات ستستعمل هذه المعلومات بطريقةٍ مختلفة، إذ أنها تستلم الرزم الشبكيّة لكي تمررها إلى الوجهة المطلوبة؛ وستستخدم القناع لمقارنة عنوان IP الوجهة بعناوين الشبكات الموجودة في جدول التوجيه. أعراف تسمية قناع الشبكة الفرعية هي / ثم رقم، الذي يخبر الموجِّه أيّة بايتات ستمثِّل قسم الشبكة من العنوان؛ الرمز ‎/24 يعني أنَّ أول 3 بايتات أو أول 24 بت هي قسم الشبكة من العنوان. يحاول المضيف A -في هذا المثال- إرسال رزم شبكيّة إلى الوجهة 10.3.1.23، ويستعمل ذاك المضيف القناع ‎/24 لمقارنة مُعرِّف شبكته الفرعية التي هي 10.1.1، لكن وجد أنَّ أول 3 بايت من مُعرِّف الشبكة الفرعية للوجهة التي هي 10.3.1 لا تتطابق، لهذا سيُرسِل المضيف A الرزم إلى الموجِّه؛ ثم سيستعمل الموجِّه معلومات القناع لمطابقة الشبكة الفرعية الوجهة في جدول التوجيه الخاص به، وكما هو ظاهر في المخطط أعلاه، الشبكات الموجودة في جدول التوجيه هي شبكات ‎/24 لذلك سيُقارِن الموجِّه أول 3 بايتات مع عنوان IP للوجهة كي يرى إن كانت هنالك مُدخَلة تُطابِق الوجهة. ثم سيكمل الموجِّه عمله بتمرير الرزم إلى المنفذ الموافق للوجهة الذي هو Fa0/0؛ ومن هنا تصل الرزمة إلى الموجِّه B، الذي يجري العملية ذاتها لتوصيل الرزمة إلى الشبكة الفرعية المتصلة به مباشرةً. خطة تطبيق الشبكات الفرعية علينا التأكد من عدِّة أشياء قبل أن نُقسِّم شبكاتنا إلى شبكاتٍ فرعية؛ فعلينا أولًا تخطيط لاستراتيجية التقسيم، ثم نقترض عدد البتات الملائم من قسم المضيف في العنوان لتمثيل الشبكات الفرعية؛ وبعد اكتمال مرحلة التصميم، سنحتاج إلى حجز وإسناد الشبكات الفرعية إلى مختلف القطع الشبكيّة. إذ أنَّ قناع الشبكة الفرعية هو أداةٌ تُخبِرُ الأجهزةَ والمضيفين والموجهات كيف ستقرأ وتُمرِّر الرزم الشبكيّة إلى الوجهة. القيم الثمانية لقناع الشبكة الفرعية أصبحنا الآن نعرف لماذا نحتاج إلى قناع الشبكة الفرعية، لكن كيف يبدو وكيف نصممه؟ حسنًا، القناع ما هو إلا سلسلة مكونة من 4 بايتات شبيهة بعنوان IP؛ أي بكلامٍ آخر، سلسلة من 32 بت، إما 1 أو 0. لذلك يشابه القناع عناوين IP لكنه ليس منهم؛ فهو يأتي مع عناوين IP للسماح لك بالتعرف على قسم المضيف وقسم الشبكة من العنوان؛ وفي هذا السياق، كل 1 في القناع يعني أنَّ البت الموافق له في عنوان IP هو جزء من قسم الشبكة من العنوان؛ وكل 0 في القناع يُشير إلى أنّ البت الموافق له في عنوان IP سيكون من قسم المضيف. تذكر أننا قلنا أن قناع الشبكة الفرعية هو آلية «اقتراض»؛ فسننقل (shift) القناع الافتراضي إلى اليمين ونقترض البتات من قسم المضيفين من العنوان، وهذا سيُنتِج ميزةً محوريةً في قناع الشبكة، ألا وهي أنَّ الواحدات (1) متتالية ومتعاقبة دومًا، وكذلك الأصفار. عندما ننتقل إلى الأسفل في الرسم التوضيحي السابق، نجد أنَّ تتالي الأرقام منطقي بعد تعلمنا للتحويل من النظام الثنائي إلى النظام العشري. وفي النهاية، سترى أنَّ وجود الرقم 1 في جميع البتات يساوي الرقم 255، الذي هو أكبر قناع للشبكة الفرعية، أو تمثيل للقناع كعدد عشري لأي بايت؛ وهذا هو سبب كون ناتج 24 بت متتالي يحتوي على 1 هو قناع الشبكة الفرعية 255.255.225.0؛ أصبح الأمر مربكًا الآن، لنلقِ نظرةً على بعض الأمثلة كي تتضح بعض الأمور. الأقنعة الافتراضية للشبكات الفرعية في حالة عناوين IP من الفئة A ‏(10.0.0.0) يُعرِّف القناع الافتراضي -الذي يخبرنا ما هي فئة العنوان- قسم الشبكة من العنوان الذي سيكون البايت الأول كله واحدات (1) وبقية البايتات الثلاثة كلها أصفار (0)، الذي قيمته هي 255.0.0.0 في النظام العشري. لكن ما هي ‎/8؟ نحن البشر كسالى! فبدلًا من كتابة 255.0.0.0 نود أن نختصر ونكتب ‎/8 الذي يعني أنَّه في القناع 8 بتات متتالية قيمتها 1 والباقي أصفار. عنوان من الفئة A (عشري) 10.0.0.0 عنوان من الفئة A (ثنائي) 00001010.00000000.00000000.00000000 القناع الافتراضي للفئة A (ثنائي) 11111111.00000000.00000000.00000000 القناع الافتراضي للفئة A (عشري) 255.0.0.0 طول اللاحقة الافتراضي ‎/8 عنوان من الفئة B (عشري) 172.16.0.0 عنوان من الفئة B (ثنائي) 10101100.00010000.00000000.00000000 القناع الافتراضي للفئة B (ثنائي) 11111111.11111111.00000000.00000000 القناع الافتراضي للفئة B (عشري) 255.255.0.0 طول اللاحقة الافتراضي ‎/16 عنوان من الفئة C (عشري) 192.168.42.0 عنوان من الفئة C (ثنائي) 11000000.10101000.00101010.00000000 القناع الافتراضي للفئة C (ثنائي) 11111111.11111111.11111111.00000000 القناع الافتراضي للفئة C (عشري) 255.255.255.0 طول اللاحقة الافتراضي ‎/24 عندما نُنشِئ الشبكات الفرعية، فإننا نبدأ من اليسار وننتقل إلى اليمين عند تعريف عدد البتات التي ستكون قيمتها 1 التي تحدد قيمة معرِّف الشبكة؛ وبمعرفتنا أنَّ قناع الشبكة الفرعية فيه 32 بت، فكل ما علينا معرفته هو عدد البتات التي قيمتها 1، لأننا نعلم أنَّ بقية البتات ستكون سلسلة متتالية من الأصفار؛ والمِثلُ أيضًا لفئات B و C؛ فالقناع الافتراضي للفئة B ‏(172.16.0.0) -الذي يخبرنا أنَّ أول بايتين من الفئة يحتويان على واحدات- هو 255.255.0.0 أو ‎/16؛ والأمر سيانٌ لعناوين الفئة C، التي يكون قناعها هو ‎/24. آلية استعمال الشبكات الفرعية حان الوقت الآن لإلقاء نظرة على الحصول على عنوان IP من هيئة تسجيل العناوين مثل IANA ‏(Internet Assigned Numbers Authority) ثم تقسيم ذاك العنوان إلى عدِّة شبكات فرعية. إذ نحصل بادئ الأمر على شبكةٍ واحدة، لكننا نحتاج إلى أكثر من شبكة، لأنه من غير المحتمل أن يكون لدينا مخطط مسطح (flat) للشبكة. عدد القطع في شبكتنا سيعطينا فكرة عن عدد الشبكات الفرعية التي سنحتاج لها. وقد تعلمنا في هذا الدرس أن قناع الشبكة هو أداة اقتراض، فلنمضي قدمًا ولنحسب عدد البتات التي سنحتاج لها لتمثيل عدد الشبكات الفرعية التي نحتاج. تذكَّر أن كل بت نقترضه من قسم المضيف سيقلل من عدد المضيفين؛ فكلما ازداد عدد الشبكات الفرعية، كلما نقص عدد المضيفين في كل شبكة. وبعد أخذ ما سبق بعين الاعتبار، فسنُنشِئ قناعًا جديدًا الذي سيكون سلسلةً من الأصفار والواحدات المتتالية؛ ثم سيكون على عاتقنا تحويله إلى قيمة عشرية وتمثيله بصيغةٍ شبيهةٍ بعناوين IP بوضع نقطةٍ بين كل بايتين. بعد إنشائنا للقناع الجديد، حان الآن الوقت لتعريف الشبكات الفرعية؛ أي بكلامٍ آخر، هذه العملية شبيهة بتوليد أرقام المناطق في أنظمة الهواتف؛ فلو قارنا الشبكة التي أعطتنا إياها هيئة تسجيل العناوين بالرمز الدولي للاتصال، فستكون الخطوة التالية هي إنشاء رموز للمناطق من رمز الدولة؛ وسنحجز لكل قطعة شبكية مُعرِّف شبكة فرعية مختلف في الشبكة، ثم سيحصل كل مضيف في تلك الشبكة على مُعرِّف خاص به... وبعد انتهاء التخطيط، فسيحين الوقت للذهاب إلى كل مضيف وجهاز وموجِّه ثم تطبيق مخططنا لعناوين IP مع القناع الملائم. ترجمة -وبتصرّف- للمقال Constructing an IP Network Addressing Scheme.
  11. يقدِّم لك هذا الدرس أدواتٍ لتحسين الأداء للبنية التحتية للمبدِّلات عندك لكي تواجه متطلباتٍ قاسيةً متعلقةً بالتراسل الشبكي؛ وهذا يتضمَّن التجزئة المُصغَّرة (micro segmentation) عبر مجالات التصادمات (collision domains)، واستخدام الاتصالات ثنائية الاتجاه (full-duplex)، ومعدَّلات تدفق مختلفة للوسائط مثل اتصال 1 غيغابت و10 غيغابت؛ وسنشرح أيضًا بروتوكول الشجرة الممتدة (spanning tree) كطريقة لاكتشاف الحلقات (loops) ومنعها. التجزئة المصغرة إحدى ميزات المبدِّلات هي قدرتها على التجزئة المُصغَّرة (micro segmentation)، التي ليس لها أيّة علاقة بتمرير الرزم الشبكية بذكاء بين المنافذ الوجهة والمصدر؛ إذ أنها القدرة على تقسيم الأجهزة المتصلة إلى عدِّة مجالات تصادمات؛ ففي الأيام الخالية، كان للموزِّع (hub) مجالَ تصادماتٍ وحيدًا وهذا يعني أنَّ جميع الأجهزة التي تتصل إلى الموزِّع سترى بعضها عندما تحاول الإرسال. يمكنك القول أنَّ جهازًا واحدًا سيستطيع الإرسال في وقتٍ معيّن، حيث يتحسس بقية الأجهزة القناة (channel) ويتراجعون عن الإرسال ثم سيحاولون لاحقًا استنادًا إلى بروتوكول CSMA/CD الذي يحكم آلية عمل بروتوكول إيثرنت. وفي حالة المبدِّلات، يمثِّل كل منفذٍ مجال تصادمات، ولهذا تستطيع القول أنَّه لا توجد تصادماتٌ في بيئةٍ تعتمد على المبدِّلات؛ وهنالك مكوِّن داخلي في المبدلات يسمح بأن تُجرى عدِّة «محادثات» (conversations) في نفس الوقت (تسمى هذه الميزة بالمصطلح switching fabric). ولكي يحصل هذان الأمران سويةً، فيجب أن يكون كل منفذٍ مجالَ تصادماتٍ منفصل وأنَّ يسمح switching fabric بأن تُجرى عدِّة محادثات في نفس الوقت. هذا شبيهٌ بعملية انتقال كل سيارة إلى العمل في «حارة» في الطريق السريع الذي يحتوي على عدِّة خطوط (أو حارات) للسماح لعدِّة سيارات بالمرور في نفس الوقت؛ تُحدِّد كميّة switching fabric عدد المحادثات التي تجري في وقتٍ واحدٍ في المبدِّل، لذا كلما كان الرقم أكبر كان ذلك أفضل؛ يُقاس switching fabric بوحدة البت في الثانية، وبعض المبدلات العصرية يمكنها تحتوي switching fabric بوحدة الغيغابت في الثانية، أو حتى تيرابت في الثانية. لمحة عن Duplex الاتصالات ثنائية الاتجاه (full-duplex) هي ميزةٌ أخرى من ميزات المبدِّلات؛ حيث تُستخدَم لحل مشاكل التراسل الشبكي. ففي الاتصالات ثنائية الاتجاه -مثلًا بين الخادوم والمبدِّل- يمكن زيادة التراسل الشبكي الفعال (effective bandwidth) بالسماح للأجهزة بالإرسال والاستقبال في نفس الوقت؛ أي بكلامٍ آخر، إذا كانت لديك وصلةٌ بسرعة ‎100 Mb/s ثنائية الاتجاه، فإن التراسل الشبكي الفعال سيكون ‎200 Mb/s؛ وهذا يكون للاتصالات من نقطة إلى نقطة فقط؛ أي بكلامٍ آخر، إذا أردت وصل موزِّع إلى مبدِّل (الأمر الذي يُعتَبَر وصل نقطة إلى عدِّة نقط، لأن الموزِّع يجب أن يحدد ويفهم أين حصلت التصادمات) فيجب استخدام اتصالات أحاديّة الاتجاه (half-duplex). في هذه المرحلة، سيكون لديك مرور للبيانات باتجاه وحيد مع احتمالٍ كبير بحدوث تصادمات، وستحصل على أيّة حال على تصادمات في بيئةٍ تستعمل موزِّعًا؛ فستستعمل إحدى القنوات للإرسال أو الاستقبال، وستستعمل الأخرى لتحسس التصادم؛ أما الاتصالات ثنائية الاتجاه (full-duplex) فهي تضمن اتصالاتٍ خاليةً من التصادمات بناءً على افتراض وجود بيئة تعتمد على التجزئة المُصغَّرة. مثالٌ على ذلك هو محادثةٌ عبر جهاز الراديو الذي يشبه الاتصال أحادي الاتجاه؛ فإذا كنت تتحدث، فعليك التوقف عن ذلك كي تسمح للطرف الآخر بالتحدث؛ أما الاتصالات ثنائية الاتجاه فهي تشبه المحادثات الهاتفية، حيث يمكن للطرفين التحدث في نفس الوقت. ضبط خيارات Duplex وخيارات السرعة يمكنك تغيير إعدادات Duplex والسرعة عبر استخدام هذه الأوامر: بعد الذهاب إلى نمط ضبط البطاقات (interface configuration mode) يمكنك استخدام الأمر duplex لإنشاء ضبط ثابت إما باتجاهٍ واحد (half-duplex) أو باتجاهين (full-duplex)؛ أما لو استخدمت الكلمة المحجوزة auto، فستُفعِّل استخدام المفاوضات التلقائية (auto negotiating) لاختيار أيهما أفضل. الأمر speed موجودٌ أيضًا في نمط ضبط البطاقات، ويمكنك تحديد السرعة التي تريدها إما 10 أو 100 أو 1000 ميغابت في الثانية، أو ربما تريد أن يتم اختيارها تلقائيًا باستخدام الكلمة auto؛ القيمة الافتراضية لمنافذ Fast Ethernet بسرعة 10/100/1000 هي «المفاوضة التلقائية» (auto negotiating)، أما القيمة الافتراضية لمنافذ Gb/s التي تستعمل الأكبال الضوئية هي ثنائية الاتجاه (full-duplex). يمكن عرض الضبط باستخدام الأمر show interfaces لترى إن كان قد ضُبِطَ ضبطًا ثابتًا أم كان تلقائيًا، إذ سيظهر عندك ضبط duplex وحالته وخيارات السرعة. يجدر بالذكر أنه قد تفشل المفاوضات التلقائية وبهذا سيُضبَط المنفذ إلى نمط الاتصال باتجاه وحيد، وهذا قد لا يتلاءم مع الجهاز، ولمنع حدوث هذه المشكلة فيجب عليك ضبط إعدادات duplex يدويًا. التسلسل الهرمي للاتصالات – نموذج الطبقات الثلاث عندما تفكِّر في السرعة والتراسل الشبكي وفي خطوط ‎10 Gb/s كخطوطٍ تستعمل للخوادم في الوقت الراهن، فربما تجد أنه من المثالي أن تستطيع توفير خطوط بسرعات ‎10 Gb/s لجميع اتصالات الشبكة؛ لكن هذا الأمر مكلفٌ للغاية؛ إحدى النهج في التصميم هي تقطيع الشبكة إلى أقسام وتحديد مقدار التراسل الشبكي بناءً على حاجة كل قسم. نموذج الطبقات «الأساس – التوزيع – الوصول» (core distribution access) يدعو إلى وجود طبقة وصول لتوفير الاتصالات إلى النهايات الشبكيّة ثم يُخصَّص التراسل الشبكي وغيره من الميزات والوظائف تبعًا للنهايات المتصلة؛ على سبيل المثال، يمكن أن تتصل مجموعة خواديم إلى طبقة الوصول وربما تجد وصلات 1‎ ‎Gb/s أو حتى ‎10 Gb/s هناك؛ لكن طبقة الوصول لمبنى خدمي ستحتوي على وصلات بسرعات ‎100 Mb/s أو ‎1 ‎Gb/s؛ تجمع طبقة التوزيع بين عدِّة مجموعات وصول وتصب فيها الخطوط الصاعدة (uplinks) القادمة من مبدِّلات طبقة الوصول. هذا سببٌ لزيادتك لاشتراكك في التراسل الشبكي، لأنك تعلم أنَّه من المستبعد أن تُرسِل جميع الأجهزة في مجموعات الوصول في نفس الوقت. فطبقة الأساس (core) ستصل بين عدِّة مجموعات توزيع وهنا مكان نقل غالبية بيانات الشبكة، وخصوصًا أنَّ الموارد (resources) في شبكاتنا العصرية تكون خارج مجموعات الوصول مثل شبكة الإنترنت. ليست كمية التراسل الشبكي هي الخاصية أو المورد الوحيد الذي يُخصَّص عبر هذا النموذج، يمكنك مثلًا أن تجعل حماية طبقة الوصول قويةً، وبهذا سنستطيع الإمساك بالأشخاص السيئين قبل أن يصلوا إلى الشبكة؛ وهنالك أدواتٌ مثل الجدر النارية وجودة الخدمة (quality of service) موجودةٌ في طبقة التوزيع وطبقة الأساس. الحلقات عند بناءك للتسلسل الهرمي، فربما تضع به بعض الآليات التعويضية (redundancy) في بعض الوحدات؛ على سبيل المثال، تتطلب طبقة الأساس مستوى معيّن من القدرات التعويضية والوثوقية لأنها ستنقل أغلبية بيانات التراسل الشبكي، وخصوصًا البيانات القادمة من مجموعات طبقة التوزيع. عندما تبني آليات التعويض، فربما ستنشِئ حلقات من المبدلات كما هو مبيّن في الشكل. استخدام الحلقات فكرةٌ جيدة عندما تريد أن يكون لديك تعويض ووثوقية وتوفر دائم لشبكة؛ فإذا أنشَأت حلقاتٍ مثل الموضَّحة بالشكل، فلن يشكل لك خروج جزءٍ من الشبكة انقطاعًا للاتصال، لأن البيانات ستجد طريقًا آخر لتصل إلى وجهتها. البيانات المُرسَلة إلى وجهاتٍ غير معروفةٍ ستتبع طريقًا مشابهًا وخصوصًا بيانات الإذاعة؛ مما سيؤدي إلى تقليل جودة أداء المبدلات والتسبب في مرور بيانات غير مرغوبة في الشبكة؛ التي ستُعالَج من جميع الأجهزة على الشبكة، وستسبب تخفيضًا في أداء الحواسيب والخوادم. بروتوكول الشجرة الممتدة (Spanning Tree Protocol) الحل الرئيسي لمنع تشكيل حلقات هو بروتوكول الشجرة الممتدة المعروف باسم STP؛ الذي يدير الوصلات (links) عبر عملية معيّنة؛ حيث سيمنع تشكيل الحلقات عبر حجب المنافذ والتخلص منطقيًّا من الحلقة. وهذا لا يعني أن يُعطَّل المنفذ أو يقطع عنه الاتصال؛ بل سيُحجَب من وجهة نظر الشجرة الممتدة. وعبر حجب ذاك المنفذ، سيمنع تشكيل الحلقة وستتوقف المشاكل الناتجة عن الحلقات. آلية العمل في الشجرة الممتدة هي تعيين مدير للشبكة يسمى الجسر الجذر (root bridge)؛ الذي يُرسِل ما يسمى PBDU أو bridge protocol data units لإنشاء بنية شجريّة متناسقة على الشبكة؛ وهذا يعني أنَّ اختيار الجسر الجذر ديناميكي، وسيتم اختيار الطريق ذي الأولوية القصوى ليكون جسرًا، وهذا يعني لو أن ذاك الطريق قد توقف عن العمل، فإن مبدِّلات أخرى ستأخذ مكانه وتصبح جذورًا (roots). الجزء الثاني من العملية هو اختيار المنفذ الذي سيُحجَب لمنع تشكيل الحلقة، ويتم اختياره ليكون أبعد المنافذ عن الجذر؛ وفي النهاية، سيُحجَب منفذٌ وحيد وستعلم تلك المبدلات أن عليها ألا تنقل البيانات عبره؛ مما يشكِّل مخططًا شبكيًّا خاليًا من الحلقات، مما يخلصنا من المشاكل المتعلقة بالمعدات التعويضية في الشبكة. ترجمة -وبتصرّف- للمقال Maximizing the Benefits of Switching.
  12. cisco icnd1

    يمكننا رؤية أمن المبدِّلات بعدِّة أبعاد؛ أحدها هو البعد الفيزيائي والبيئي الذي يتضمّن عدِّة فئات وتصنيفات -المذكورة هنا- تتعلق تهديدات الأجهزة بالضرر الفيزيائي للمعدّات، قد يكون سوء الاستعمال سببًا في هذا وليس بالضرورة أن يكون الضرر متعمّدًا؛ فقد يكون السبب قادمًا من الإدارة السيئة للتغييرات أو السياسات غير الحريصة في تثبيت العتاد الفيزيائي؛ وعدم وجود سياسة خاصّة بالتعامل مع المعدات. أما التهديدات البيئية فهي متعلقة بدرجات الحرارة الكبيرة والرطوبة؛ لكن مركزَ بياناتٍ بتصميم جيد لحاويات الأسلاك (wiring closet) -يتّبِع أفضل الممارسات العملية المتعلقة بالمكان الفيزيائي والتبريد ...إلخ. سيساعد في تخفيف هذه الأخطار. قد تكون التهديدات الكهربائية أكثر شيوعًا وهي تتراوح بين ارتفاع مفاجئ في الجهد (voltage spikes) إلى التيار الكهربائي غير المستقر أو إلى فقدان تام للطاقة الكهربائية. يمكن تجنب هذه المخاطر باستخدام وحدات عدم انقطاع التيار (UPS). تهديدات الصيانة متعلقة بمنهجية وعملية تصميم المكان الفيزيائي للمعدات، إذ ستشكِّل تمديدات الأكبال السيئة تهديدًا أمنيًا إذا سببت في مشكلة كهربائية أو مشكلة في العتاد إذا أدّت إلى إسقاط المعدات على الأرض. وقد يُشكِّل أيضًا نقصان قطع التبديل تهديدًا أمنيًا؛ الذي يُثبِت مدى سوء التصميم والتخطيط من ناحية إمكانية تعويض المعدات. ضبط كلمة مرور للمبدل قد تكون التهديدات الأخرى متعلقةً بالاستيثاق وإدارة الهويات؛ وهذه هو السبب وراء ضبطنا لكلمات المرور وتوفير تحكم بالوصول مع استخدام كلمات المرور. قد يتعلق إعدادٌ بسيطٌ لكلمة المرور بخطوط وصولٍ (access lines) معيّنة إلى المبدِّل -على سبيل المثال- الطرفية (console)، وخطوط VTY المتعلقة بوصول الطرفية إلى المعدات؛ وهنالك قواعد للتحكم بالوصول عبر Telnet و SSH، لكن بعد أن تتصل إلى المعدات باستخدام طرفية أو Telnet، فستتمكن من الدخول إلى وضع المستخدم ذي الامتيازات بكلمة مرور، وهذا أمرٌ أخرٌ يجب علينا أخذه بعين الاعتبار. أحد الأمور الشائعة لكل كلمات المرور تلك هي أنها مضبوطة وثابتة لكل خط وصول أو لكل وظيفة مثل enable password. SwitchX(config)#no aaa new-model SwitchX(config)#line console 0 SwitchX(config-line)#login % Login disabled on line 0, until 'password' is set SwitchX(config-line)#password cisco SwitchX(config-line)#exi SwitchX(config)#line vty 0 4 SwitchX(config-line)#login % Login disabled on line 2, until 'password' is set % Login disabled on line 3, until 'password' is set % Login disabled on line 4, until 'password' is set % Login disabled on line 5, until 'password' is set % Login disabled on line 6, until 'password' is set SwitchX(config-line)#password sanjose SwitchX(config-line)#exi SwitchX(config)#enable password cisco SwitchX(config)#enable secret sanfran SwitchX(config)#service password-encryption طريقةٌ أخرى أكثر تقدمًا هي ربطها إما مع مستخدمين محليين أو مستخدمين مركزيين، وبهذا تستطيع استخدام تحكم بالوصول مستند إلى الدور (role-based access control) لإدارة الجهاز. تُستعمَل الأوامر المذكورة في الأعلى لإعداد كلمات مرور للخطوط؛ ربما تريد أن تُفعِّل عملية الاستيثاق على أحد الخطوط؛ ثم يمكنك ببساطة إعداد كلمة مرور دون تشفير لكن هنالك طريقة مُحسّنة هي تفعيل كلمة المرور مع تشفير أو إخفاء كلمة المرور باستخدام آليات التعمية (hashing mechanisms). تكون جميع كلمات المرور بنصٍ واضح وتُعرَض كما هي في أوامر: show running-config و show startup-config إذا أردت إخفاء الأوامر وتشفيرها تشفيرًا بسيطًا، فيمكنك استخدام الأمر last، بعد أن تنفِّذ ذاك الأمر، فسيتم تشفير جميع كلمات المرور الجديدة، ويمكنك تعطيل هذه الآلية باستخدام نسخة no من ذاك الأمر. ضبط لافتة تسجيل الدخول ستساعدك لافتات تسجيل الدخول على إيصال رسالة معيّنة إلى المستخدمين الذين تم الاستيثاق من دخولهم إلى المبدِّل؛ يمكن للافتات خدمة غرض إظهار معلومات، وعرض السياسة للمستخدمين الذين لم يتم الاستيثاق من دخولهم. يمكنك ضبط اللافتة بواسطة الأمر banner. الوصول عبر Telnet أو SSH تاريخيًا، كان Telnet أشهر الخيارات للوصل بين موجَّهَين لأغراض الإدارة، وكذلك للاتصال إلى المبدِّلات؛ لكنه غير آمن لأنه لا يوفر تشفيرًا للاتصال؛ أي بكلامٍ آخر، يمكن لمتلصصٍ أن يجمع رزماتٍ شبكيّة من الاتصال ويعلم الأوامر التي تستعملها وقد يستطيع سرقة كلمات مرورك، إذ أنها لا تشفَّر؛ أما SSH بإصدارَيه 1 و 2، سيشفِّر عملية نقل البيانات وسيخدم بنفس الوقت غرض الاتصال إلى جهازٍ لضبطه؛ وربما يوفِّر الإصدار الثاني من SSH خوارزمية تشفير أكثر تعقيدًا. إذا أردت استخدام SSH، فعليك إنشاء مفاتيح للتشفير، وعليك استخدام الأمر: crypto key generate rsa لإنشاء المفاتيح، وتلك المفاتيح مرتبطة أو تحتوي على اسم نطاق (domain name)، وهذا هو السبب وراء حاجتنا لذاك الأمر. يمكنك أيضًا تعريف قاعدة بيانات مستخدمين محليّين؛ يمكنك إضافة المستخدمين بالأمر username. طريقة ضبط أكثر تقدمًا هي استخدام خواديم AAA، أي خواديم الاستيثاق والتصريح والحسابات (authentication authorization and accounting servers) لجعل قاعدة بيانات المستخدمين مركزية وتوفير إمكانية التوسع لعدِّة أجهزة، التي تتشارك قاعدة البيانات نفسها من خادوم مركزي. ضبط حماية المنافذ آلية تأمينٍ إضافيةٌ في المبدِّلات مثل Catalyst 2960 هي حماية المنفذ؛ وتسمح لك تلك الميزة بتحديد عدد عناوين MAC التي يمكنك تعلمها في منفذ معيّن، ويمكنك أيضًا تحديد عناوين MAC التي تسمح لها في منفذٍ معيّن. هذا نوعٌ من آليات التأمين في الطبقة الثانية التي تساعد في الحماية الفيزيائية عبر تحديد من يمكنه الاتصال عبر منفذٍ ما، وكم جهازًا يستطيع الاتصال. عملية الضبط سهلة جدًا، حيث تبدأ بالأمر switchport في نمط ضبط المنافذ. لنلقِ نظرةً على بعض الخيارات بالنظر إلى مثال ضبط قياسي، أول شيء ستفعله لضبط البطاقة fa0/5 هو تفعيل المنفذ كمنفذ وصول (access port) وليس كمنفذ trunk؛ يسمح منفذ الوصول بوصل النهايات مثل محطات العمل والحواسيب المحمولة. الخطوة الثانية هي تفعيل تأمين المنفذ؛ الخطوة الثالثة هي تعريف العدد الأقصى من عناوين MAC، الوسيط maximum 1 يعني أنك ستسمح بعنوان MAC وحيد بالاتصال إلى هذا المنفذ. Switch(config)#interface fa0/5 Switch(config-if)#switchport mode access Switch(config-if)#switchport port-security Switch(config-if)#switchport port-security maximum 1 Switch(config-if)#switchport port-security mac-address sticky Switch(config-if)#switchport port-security violation shutdown وكما نعلم، تتعلم المبدِّلات عناوين MAC، ولهذا سيكون العنوان المُسنَد إلى المنفذ ديناميكيًا، ولكن بعد أن يتعلم المبدِّل عنوان MAC، فلن يقبل أي شيءٍ أكثر من العدد الأقصى؛ فلنقل أنك ضبطت العدد الأقصى إلى 10، فإن أعيد تشغيل المبدِّل، فسيتم نسيان تلك العناوين، وإذا أردت من المبدِّل أن يتذكرها، فعليك أن تجعلها ثابتةً باستخدام الكلمة المحجوزة sticky. في النهاية، عليك تحديد ماذا سيحصل عندما يتم تجاوز الحدود التي ضبطتها؛ هنالك عدِّة خيارات، يمكنك أن تعطِّل المنفذ (shutdown) وعليك إعادة تفعيله يدويًا بعد ذلك؛ أو يمكنك أن تعطِّل المنفذ مؤقتًا، أو أن تترك المنفذ على حاله لكن سترسِل رسالة syslog لكي يعلم المدراء أن الحدود قد تم تجاوزها. تستطيع عرض الإعداد والحالة لجميع البطاقات أو بطاقات معيّنة بعد ضبط حماية المنافذ، يمكنك استخدام الكلمة address لعرض عناوين MAC المرتبطة بالبطاقة؛ وهو أمرٌ بسيط سيعرض إن كان تأمين المنفذ مُفعّلًا وحالته إن كان كذلك؛ وفي هذه الحالة، «secure up» تعني أنه لم تحدث تجاوزات للحماية. ما سيحدث عندما يحصل تجاوز ما هو تعطيل المنفذ، فعدما يتصل عنوان MAC غير معروف أو تتجاوز عناوين MAC الحد المعيّن، فسيتم تعطيل المنفذ. عندما تُحدَّد قيمة بالدقائق لعناوين MAC المُسجَّلة، فيمكن أن تُزال تلقائيًا بعد أن يفصل اتصالها دون الحاجة إلى إزالتها يدويًا. أخيرًا، عدد عناوين MAC هو العدد الكلي لعناوين MAC التي يمكن للمنفذ تعلمها، وستُعرَض الإعدادات الثابتة (sticky configuration) وعدد التجاوزات التي حصلت في منفذ المبدِّل. تأمين المنافذ غير المستخدمة أفضل الممارسات العملية هي تأمين المنافذ غير المُستخدَمة التي قد تُشكِّل ثغراتٍ أمنيةً لأنها مفعَّلة افتراضيًا؛ إن كان لديك DHCP على شبكتك ولم تكن توفِّر حمايةً فيزيائيةً لها، فيمكن الوصول إلى شبكتك دون إذنك؛ لذا يُنصَح بتعطيل بطاقات المنافذ غير المُستعمَلة. ولهذا سنستخدم الأمر shutdown بالذهاب إلى وضع ضبط البطاقات وتحديد البطاقات التي نريد تعطيلها. في الإصدارات الحديثة من نظام تشغيل IOS، ستعثر على خيار لتحديد مجال من البطاقات لتعطلها في آن واحد؛ تذكر أنك تستطيع إعادة تفعيل البطاقة باستخدام نسخة no من أمر التعطيل؛ أي بكلامٍ آخر، الأمر shutdown سيعطِّل البطاقة إداريًا، بينما no shutdown سيفعِّلها. ترجمة -وبتصرّف- للمقال Understanding Switch Security.
  13. cisco icnd1

    لا يمكننا ضبط المبدِّلات إن لم تكن مُهيّئة بعد؛ سنشرح في هذا الدرس عملية بدء تشغيل نظام سيسكو IOS للمبدِّلات ونساعدك في التعرّف على الخطوات بالنظر إلى مخرجات الإقلاع. ثم سندخل إلى المبدِّل ونضبطه عبر واجهة سطر الأوامر، ثم سنتأكد من عمله عبر استخدام أوامر show المناسبة. الضبط الابتدائي لمبدلات Catalyst تكون مبدِّلات سيسكو جاهزةً لتوفير قابلية الاتصال ووظائف الطبقة الثانية عند إقلاعها. تتضمن عملية الإقلاع سلسلةً من إجراءات الإقلاع لتهيئة النظام وجعل وظائفه متوفرةً. الضبط الافتراضي يتضمن إنشاء مِحَث للمبدِّل، وتعريف أساسي للمنافذ (أو البطاقات) الذي هو تمكينها جميعًا؛ وإذا أردت مراقبة العملية، فتأكد من أنَّك تملك اتصالًا للمبدِّل عبر طرفية (console)، أو أنَّ لديك عميل طرفية مثل HyperTerminal أو PuTTY. في المبدِّلات الأبسط، يؤدي وصل شريط الطاقة مباشرةً إلى تشغيل المبدِّل وبدء عملية التهيئة. وفي هذه المبدِّلات البسيطة، لن تجد زر «on» أو «off» كما في المبدِّلات الأكثر تعقيدًا مثل المبدِّلات في طبقة التوزيع (distribution layer) والمبدِّلات الأساسية (core layer switches)؛ يمكنك مراقبة تسلسل عملية الإقلاع فيزيائيًا بالنظر إلى المبدِّل وملاحظة أضواء LED في هيكل المبدِّل، وأيضًا عبر اتصال الطرفية بالنظر إلى مخرجات نظام IOS، التي تعرض معلوماتٍ عن التشخيص وعملية التهيئة بأكملها. لاحظ أن هذه الدورة التدريبية مبنية على المبدِّل Catalyst 2960، وقد تختلف المخرجات أو الأوامر عن غيرها من المبدِّلات. إشارات أضواء LED في مبدِّلات Catalyst 2960 تُظهِر الصورة أضواء LED في Catalyst 2960، تعرض الأضواء المختلفة معلوماتٍ قيّمة عن حالة وإمكانيات المبدِّل. فضوء النظام (system LED) سيضيء بالأخضر لو كان النظام مشغلًا ويعمل عملًا سليمًا، ولكنه سيصفر إذا كانت هنالك أخطاء عند الإقلاع أو مشكلة في النظام؛ وسيومض لونٌ أصفرٌ في ضوء مزود الطاقة (power supply LED) إن فشل مزود الطاقة الرئيسية بإمداد المبدِّل بالطاقة وأصبح مزود الطاقة التعويضي يعمل بدلًا عنه. أما أضواء المنافذ فلها معانٍ مختلفة. مهمة زر «النمط» (mode) هي التبديل بين الأنماط المختلفة التي تُعطي معانٍ مختلفة لأضواء المنافذ؛ على سبيل المثال، إذا اخترت نمط «stat» أو «الحالة» فهذا سيجعل أضواء المنافذ تومض باللون الأخضر إن كان هنالك اتصالٌ وكان ذاك الاتصال نشطًا؛ لكنها ستصفر إن أُغلِق المنفذ من المدير أو حُجِبَ بواسطة بروتوكول الشجرة الممتدة (spanning tree)؛ ومثلًا، لو بدَّلت إلى نمط «الاستعمال» (utilization)، فإن عددًا من المنافذ ستضيء بالأخضر، مُظهِرةً حجم مرور البيانات في المبدِّل؛ فمثلًا، عندما تُظهِر كل أضواء LED لونًا أخضرًا فهذا يعني أن المبدِّل يعمل بنسبة 50% من قدرته، ويشير عدد أضواءٍ آخر إلى نسبٍ أخرى. مخرجات الإقلاع سيُظهِر نظام IOS معلوماتٍ أكثر تحديدًا، فيعرض -بالإضافة لغير ذلك من الأمور- عنوان MAC للمبدِّل ومختلف مراحل عملية التهيئة؛ ويُظهِر أيضًا مسار صورة نظام التشغيل الذي تُحمِّل منه، وحالة عملية التحميل؛ وبعد إتمام عملية التهيئة، سنحصل على وصول إلى واجهة سطر الأوامر؛ لكن إن كانت ملفات ضبط المبدِّل فارغةً، فسنحوَّل مباشرةً إلى نمط الإعداد الذي سيبدأ بسؤالنا أسئلةً عن الضبط الأساسي؛ يمكنك الانتقال إلى نمط الإعداد في أيّ وقتٍ باستدعاء الأمر setup. الدخول إلى المبدل والتحويل إلى نمط EXEC بمستخدم ذي امتيازات ستكون في نمط EXEC عندما تدخل إلى واجهة سطر الأوامر، حيث يسمح لك ذاك النمط بمراقبة وعرض وصيانة المبدِّل، لكنه يعتمد على الدور المُسنَد لك؛ فالأدوار هي نمط المستخدم العادي، أو نمط المستخدم ذو الامتيازات؛ يملك نمط المستخدم العادي وصولًا محدودًا إلى أدوات المراقبة البسيطة، بينما يسمح نمط المستخدم ذو الامتيازات لك بمراقبة وصيانة المبدِّل؛ على سبيل المثال، يمكنك نسخ ملفات الضبط من الشبكة، أو بإمكانك ببساطة حذفها، وحتى حذف صورة ملف IOS. لذا، ذاك النمط أكثر خطورةً وقدرةً على إدارة وصيانة المبدِّل؛ ولكي تنتقل من نمط المستخدم العادي إلى نمط المستخدم ذو الامتيازات، فعليك استخدام الأمر enable؛ ثم سيُطلَب منك إدخال كلمة المرور إن كانت موجودةً؛ إذ لا توجد كلمة مرور افتراضيًا، ويمكنك معرفة أنك انتقلت إلى نمط المستخدم ذي الامتيازات باختلاف شكل المِحَث (prompt). User Access Verification Username: admin Password: Switch>enable Password: Switch# حيث يظهر في نمط المستخدم العادي إشارة «أكبر من» كمحث، أما نمط المستخدم ذو الامتيازات فيظهر فيه إشارة المربع؛ ولأسبابٍ أمنيّة، لن تظهر كلمة المرور التي تكتبها على الشاشة؛ لكن إن كنت تتصل عبر جلسة Telnet، فستُرسَل كلمة المرور بنصٍ صريحٍ دون تشفير؛ ولهذه يُنصَح بشّدة استخدام بروتوكولات فيها تشفير مثل SSH لتوفير خصوصية وأمان نقل البيانات. ضبط المبدل يمكنك استخدام أوامر المراقبة والصيانة مثل الأمر copy في نمط المستخدم ذو الامتيازات؛ إذا أردت ضبط المبدِّل، عليك أن تدخل إلى وضع الضبط؛ وهنالك عدِّة طبقات من أنماط الضبط؛ أكثرها شموليةً هو نمط الضبط العام، الذي يمكنك الدخول إليه بكتابة الأمر configure terminal، ثم ستشاهد المحث يتغيّر لكن إشارة المربع ستبقى موجودةً فيه لتخبرك أنّك في نمط المستخدم ذي الامتيازات، وستجد اسم طبقة نمط الضبط التي أنت فيها مكتوبةً في المِحَث بين قوسين. تتعلق جميع الأوامر في الضبط العام بالمبدِّل كجهاز. Switch# Switch#configure terminal Enter configuration commands, one per line. End with CNTL/Z. Switch(config)# فمثلًا، يمكنك تغيير المِحَث، ويمكنك تفعيل كلمة المرور للجهاز أو تغييرها إن كانت مُفعّلةً، وتستطيع عرض لافتات (banners) للمستخدمين الذين يسجلون الدخول إلى المبدِّل، أو يمكنك تعديل ترتيب عملية الإقلاع. وإذا أردت ضبط مكوناتٍ مخصصة، فعليك الانتقال من وضع الضبط العام إلى وضع الضبط لذاك المكوِّن؛ فمثلًا، لو أردت ضبط البطاقات، فعليك كتابة الأمر interface متبوعًا بمرجع البطاقة، وفي هذه الحالة، سندخل إلى بطاقة fast Ethernet في الفتحة (slot 0)، والمنفذ (port 1)؛ وهذا مثالٌ تقليديٌ عن الأجهزة ذات الضبط الثابت (fixed configuration) مثل 2960؛ وستعرف أنَّك في وضع ضبط البطاقة وذلك بتغيّر المِحَث ليعرض الكلمة «config-if». Switch(config)#interface FastEthernet 0/1 Switch(config-if)# هنالك عدِّة أنماط ضبط لبروتوكولات التوجيه في حالة المبدِّلات متعددة الطبقات (multilayer switch)؛ يمكنك من وضع الضبط العام الدخول إلى وضع ضبط بروتوكول التوجيه. ويمكن أيضًا ضبط وصلة الطرفية وأسطر VTY لوصول Telnet أو الدخول إليها من نمط الضبط العام. وإذا أردت العودة إلى النمط السابق؛ فأدخِل الأمر exit؛ الذي سيأخذك -على سبيل المثال- من نمط ضبط البطاقات إلى نمط الضبط العام. وإذا أردت العودة مباشرةً إلى طبقة EXEC بمستخدمٍ ذي امتيازات، فيمكنك الضغط على Ctrl-Z أو end وستذهب إلى أول طبقة، التي هي نمط EXEC. أولى المهام في نمط الضبط العام هي تسمية المبدِّل؛ يسمح لك الأمر hostname بإعطاء اسم للمبدِّل، وسيتغيّر المِحَث لأن اسم المبدِّل سيصبح جزءًا منه. ويمكن أيضًا أن يُستعمَل اسم المبدِّل لأغراضٍ إدارية للتعرف بسرعة إلى المبدِّل بالنظر إلى المِحَث، أو لغيرها من الأغراض بما في ذلك تفعيل DNS في المبدِّل. Switch(config-if)#^Z Switch# Switch#conf t Enter configuration commands, one per line. End with CNTL/Z. Switch(config)#hostname DSTR2 DSTR2(config)# يمكنك أيضًا توفير عناوين IP للمبدِّل بالذهاب إلى بطاقاتٍ معيّنة بالأمر interface من نمط الضبط العام ثم استخدام الأمر ip address كما هو موضّح في المثال لتعريف عنوان IP وقناع الشبكة الفرعية؛ وفي هذه الحالة، نحن نستعمل مبدِّل في الطبقة الثانية في 2960 ولذا ستكون بطاقات الطبقة الثالثة المتوفرة هي بطاقات VLAN لأغراضٍ إدارية. يمكنك أيضًا أن ترى بعض الاستعمالات للأمر shutdown؛ يمكننا استخدام الأمر مع الكلمة المحجوزة «no» وهذا شائعٌ في أغلبية أوامر سيسكو؛ بكلامٍ آخر، تنفيذ الأمر shutdown سيعطِّل البطاقة إداريًا، لكن تنفيذ الأمر no shutdown سيعيد تفعيلها. وبهذه الطريقة يمكنك إزالة عناوين IP التي أسندتها عبر استخدام الأمر no ip. DSTR2(config)#vlan 10 DSTR2(config-vlan)#name Management DSTR2(config-vlan)#exi % Applying VLAN changes may take few minutes. Please wait... DSTR2(config)#int vlan 10 DSTR2(config-if)#ip address 192.168.0.10 255.255.255.0 DSTR2(config-if)# ضبط البوابة الافتراضية في المبدل سيتكمل ضبط IP في مبدِّلات الطبقة الثانية مثل 2960 عند ضبط البوابة الافتراضية. ليس لدى المبدِّل جدول توجيهات، ولهذا سيحتاج إلى عنوان IP للبوابة الافتراضية، مَثَلُهُ كَمَثِلِ أيّة نهايةٍ شبكيّة. يمكنك تحديد عنوان IP للبوابة الافتراضية باستخدام هذا الأمر في نمط الضبط العام؛ وبهذا يكون المبدِّل قادرًا على الوصول إلى الوجهات البعيدة. وهذا يُستعمل عادةً لأغراضٍ إدارية لتمكّن من الاتصال عبر Telnet و SNMP للوجهات البعيدة. DSTR2(config)#ip default-gateway 192.168.0.1 DSTR2(config)# حفظ الضبط علينا أن نتذكر أن تلك الأوامر مُفعّلةٌ وتعمل على المبدِّل؛ لكنه موجودةٌ في الضبط التشغيلي؛ أي أنها لم تُحفَظ إلى الضبط الإقلاعي، الذي سيقرأه المبدِّل بعد إعادة الإقلاع. حفظ الضبط هو عمليةٌ يدويةٌ والأمر المستخدم هو: copy running-config startup-config command وستُسأل عن اسم الملف الهدف، الذي هو مضبوطٌ افتراضيًا؛ يمكنك ببساطة الحفظ إلى ملف ضبطٍ موجودٌ مسبقًا اسمه startup-config موجودٌ في NVRAM؛ مما يضمن أن الضبط جاهزٌ ومتوفرٌ لكي يقرأه المبدِّل بعد الإقلاع القادم؛ إذا لم تفعل ذلك، فستفقد الضبط التشغيلي في ذاكرة RAM عندما يفقد المبدِّل الطاقة الكهربائية أو عندما تُعيد تشغيل المبدِّل. عرض حالة التشغيل المبدئية للمبدل يمكنك التأكد من ضبطك والحالة الإجمالية وإمكانيات المبدِّل بالأوامر الآتية: show running-configuration الذي -كما ذكرنا سابقًا- يعرض الضبط الفعال حاليًا في المبدِّل؛ بينما الأمر: show startup-configuration سيُظهِر الضبط المحفوظ في NVRAM، و show version يُظهِر الإعدادات الإجمالية وإمكانيات المبدِّل بما في ذلك العتاد وإصدار البرمجيات، وملفات الضبط وصور الإقلاع. تسمح الأوامر الأخرى لك برؤية حالة البطاقات مثل الأمر show interfaces، الذي لا يُظهِر الحالة فقط، بل وإحصائيات متعلقة بالبطاقات. هذا مثالٌ عن ناتج الأمر show version، الذي يُظهِر خصائص نظام IOS بما في ذلك أرقام الإصدارات ومجموعة الميزات، ويعرض النسخة المُصغَّرة من IOS ‏(mini IOS) الموجودة في ROM، ومحمِّل الإقلاع الذي قد يكون إصداره مختلفًا؛ وزمن التشغيل (uptime) المهم لتحديد إن أُعيد إقلاع المبدِّل في الآونة الأخيرة. ثم ستُعرَض صورة IOS التي تم تحميلها من ذاكرة flash (وهذا ما يتم افتراضيًا)، لكن يمكن أن يكون المبدِّل قد حمَّل الصورة من الشبكة. Cisco IOS Software, C2960S Software (C2960S-UNIVERSALK9-M), Version 15.0(1)SE1, RELEASE SOFTWARE (fc3) Technical Support: http://www.cisco.com/techsupport Copyright (c) 1986-2011 by Cisco Systems, Inc. Compiled Thu 01-Dec-11 14:53 by prod_rel_tea ROM: Bootstrap program is Alpha board boot loader BOOTLDR: C2960S Boot Loader (C2960S-HBOOT-M) Version 12.2(55r)SE, RELEASE SOFTWARE (fc1) Switch uptime is 28 weeks, 2 days, 6 hours, 15 minutes System returned to ROM by power-on System restarted at 18:16:59 EET Wed Dec 14 2011 System image file is "flash:/c2960s-universalk9-mz.150-1.SE1.bin" ... cisco WS-C2960S-48TS-L (PowerPC) processor (revision F0) with 131072K bytes of memory. Processor board ID XXXXXXXXXXX Last reset from power-on 2 Virtual Ethernet interfaces 1 FastEthernet interface 104 Gigabit Ethernet interfaces The password-recovery mechanism is enabled. ثم ستظهر إعدادات العتاد الإجمالية، بما في ذلك كميّة الذاكرة، التي تُعرَض على هيئة رقمين: الذاكرة المشتركة (shared memory) والذاكرة المتوفرة لبقية النظام؛ إذا جمعت هذين الرقمين، فستحصل على كميّة ذاكرة RAM الإجمالية الموجودة في المبدِّل. ويظهر أيضًا العدد الإجمالي للبطاقات الفيزيائية، وتُظهِر بقية الناتج (التي لم تُعرَض هنا) كميّة ذاكرة flash وقيمة مسجِّل الضبط (configuration register). يُستخدَم الأمر show interfaces عادةً للضبط الدقيق، لكنه يستعمل أيضًا للمراقبة واستكشاف الأخطاء وإصلاحها؛ يمكنك استعمال الأمر show interfaces لإظهار معلومات عن جميع البطاقات، أو يمكنك تحديد البطاقة التي تريد عرض معلوماتها. يَعرض الأمر حالة الطبقة الأولى، والثانية التي تتضمن عنوان MAC وحالة duplex وسرعة البطاقة متبوعةً بسلسلة من الإحصائيات تتضمن آخر إزالة للعدادات (counters)، واستراتيجية الطابور (queuing strategy)، ومعدلات الدخل والخرج في آخر 5 دقائق بوحدات «بت في الثانية» و «رزمة في الثانية»، ثم إحصائيات متعلقة بالرزم الإجمالية والأخطاء المتعلقة بعدِّة تصنيفات. Switch#sh int gi 1/0/2 GigabitEthernet1/0/2 is up, line protocol is up (connected) Hardware is Gigabit Ethernet, address is d4d7.48ef.9e82 (bia d4d7.48ef.9e82) MTU 9000 bytes, BW 1000000 Kbit/sec, DLY 10 usec, reliability 255/255, txload 1/255, rxload 1/255 Encapsulation ARPA, loopback not set Keepalive set (10 sec) Full-duplex, 1000Mb/s, media type is 10/100/1000BaseTX input flow-control is off, output flow-control is unsupported ARP type: ARPA, ARP Timeout 04:00:00 Last input never, output 00:00:00, output hang never Last clearing of "show interface" counters never Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0 Queueing strategy: fifo Output queue: 0/40 (size/max) 5 minute input rate 0 bits/sec, 0 packets/sec 5 minute output rate 0 bits/sec, 0 packets/sec 59814322 packets input, 25857763788 bytes, 0 no buffer Received 7326867 broadcasts (7172259 multicasts) 0 runts, 0 giants, 0 throttles 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored 0watchdog, 7172259 multicast, 0 pause input 0 input packets with dribble condition detected 98618698 packets output, 90904769164 bytes, 0 underruns 0 output errors, 0 collisions, 1 interface resets 0 unknown protocol drops 0 babbles, 0 late collision, 0 deferred 0 lost carrier, 0 no carrier, 0 pause output 0 output buffer failures, 0 output buffers swapped out وكجهازٍ في الطبقة الثانية، ستحافظ المبدِّلات على جدول عناوين MAC، حيث ستتعلم عناوين MAC ديناميكيًا بالنظر إلى ترويسات الإطارات ثم ستتمكن من تحديد أماكن تلك العناوين وربطها مع المنافذ لتمكين تمرير الرزم أو الإطارات بشكلٍ ذكي. يمكنك عرض جدول عناوين MAC بالأمر: show mac address-table الذي سيُظهِر عناوين MAC ونوعها والمنفذ الذي تتصل الأجهزة حاملةُ عناوين MAC السابقة منه. قد تكون بعض عناوين MAC ثابتة، فجزءٌ منها متعلقٌ بالاستخدام الداخلي لمبدِّلات Catalyst 2960؛ تذكّر أن بعض المدخلات في الجدول ستنتهي صلاحيتها، وتُحذَف، ثم ستُضاف مرةً أخرى... ترجمة -وبتصرّف- للمقال: Starting a Switch and Basic Configuration.
  14. وأخيرًا لقد أصبحنا جاهزين لضبط مبدِّلات إيثرنت، وسنستخدم في هذا الدرس نظام تشغيل IOS التابع لسيسكو؛ حيث سنشرح ميزاته ووظائفه إضافةً إلى واجهة سطر الأوامر الخاصة به. وسيتضمن هذا الدرس أيضًا بدء تشغيل جلسة EXEC واستخدام الميزات الأساسية مثل المساعدة على الإنترنت (online help) والتعديل المُحسَّن (enhanced editing) وخاصية تأريخ الأوامر (command history). برمجية سيسكو IOS IOS هو نظام تشغيل ومعمارية البرمجيات المضمَّنة (embedded software architecture) لجميع أجهزة سيسكو؛ وفي الواقع، يشير اسمه إلى «نظام تشغيل الشبكة البينية» (internetwork operating system)؛ ويمنح الجهاز واجهة سطر أوامر للضبط، ويُمثِّل البرمجيّة التي تُعرِّف الميزات والوظيفة جنبًا إلى جنب مع البروتوكولات المدعومة من ذاك الجهاز. وهذا يتضمَّن -في المبدِّلات- الذكاء لتوفير اتصالات ومعالجة إطارات إيثرنت؛ بما في ذلك الوظائف الأمنية للتحكم بالوصول ومنع الاستخدام غير المُصرَّح به للشبكة؛ بالإضافة إلى ميزات خاصة بقابليّة التوسّع، والوثوقيّة، وغيرها. إن IOS هو نظام تشغيل مبدِّلات «Cisco Catalyst». ضبط الأجهزة الشبكية تسمح لك واجهة سطر الأوامر لنظام IOS بضبط المبدِّل؛ لكن الضبط الافتراضي كافٍ لكي يعمل المبدِّل عمله في الطبقة الثانية؛ أي بكلامٍ آخر، تكون المنافذ مُفعَّلةً افتراضيًا وتبدأ وظائف التبديل (switching) عند إقلاع الجهاز. أي أنك لو وصلت أجهزتك إلى المبدِّل، فيمكنك استخدام بروتوكول إيثرنت وتكون وظيفة التبديل جاهزةً للاستعمال. لكن ما يزال عليك ضبط وظائف الطبقة الثالثة لأتمتة عملية الضبط وإخفاء تعقيدات الأوامر عن المدراء. ستطلب أجهزة سيسكو ضبطًا ابتدائيًا إذا لم يتوفر ضبطٌ في الذاكرة؛ فعندما تُقلِع وتكون ملفات الضبط فارغةً، فستبدأ عمليةٌ اسمها «setup». يمكن أن تُستعدى عملية الضبط بعد إقلاع المبدِّل؛ حيث يظهر مربع حوار الإعداد الذي يتضمّن أسئلةً متعلقةً بمهام الضبط لإعداد الجهاز، بما في ذلك بروتوكول العناوين وبعض الخيارات المتعلقة بالطبقة 3 بما في ذلك عنوان IP وقناع الشبكة الفرعيّة (subnet mask). تتضمن الخيارات الأخرى -المتعلقة بالإدارة- إمكانية ضبط كلمة مرور وتعريف بروتوكولات الإدارة. لمحة عن عملية بدء تشغيل جهاز سيسكو إذًا، تتحقق أجهزة سيسكو من ملفات الضبط عندما تُقلِع، لكن هذا ليس الشيء الوحيد الذي تفعله، حيث تتأكد من عتاد الجهاز وتبدأ سلسلة من الاختبارات التشخصيّة المعروفة بالمصطلح «power-on self-test» أو اختصارًا POST. وبعد التأكد من سلامة العتاد، فسيبدأ الموزِّع سلسلةً من خطوات التهيئة تتضمن تحميل صورة نظام تشغيل IOS، لتشغيله والتمكن من استعمال واجهة سطر الأوامر. وأخيرًا وليس آخرًا، يستعد الجهاز لتحميل الضبط الحالي، حيث سيحاول العثور على ملف الضبط، الذي يجب أن يكون صالحًا وبصيغةٍ صحيحة، ومن ثم يحمِّله إلى الذاكرة لإعطاء الجهاز ضبطه الابتدائي؛ مكان وجود صورة نظام تشغيل IOS وملفات ضبط الجهاز مُعرَّفةٌ مسبقًا، لكن هنالك إجراءات احتياطية في حال لم تكن موجودةً مكانها، أو كانت معطوبة، أو نُقِلَت إلى مكانٍ آخر؛ تكون الإجراءات الاحتياطيّة تلقائيةً وجزءًا من عمليّة الإقلاع. مصادر خارجية للضبط أصبحنا جاهزين في هذه المرحلة لضبط الجهاز. يمكن أن يأتي الضبط من عدِّة مصادر وستُنفَّذ الأوامر مباشرةً على الجهاز؛ أي بمجرد أن أكتب أمرًا أو أحمِّل ملف ضبط، فسيحمَّل الضبط مباشرةً إلى الذاكرة ويُنشَّط. هنالك عدِّة طرق للوصول إلى الجهاز لضبطه أو إدارته. أولها هو منفذ الطرفية (console port) الموجود في أغلبية أجهزة سيسكو وهو منفذ تسلسلي يسمح بالوصول إلى واجهة سطر الأوامر لبدء الضبط. منفذ مشابهٌ له هو المنفذ البديل (auxiliary port) الذي يوفِّر وصولًا إلى سطر الأوامر، لكنه موجودٌ فقط في الموجِّهات ويسمح باتصالٍ من نمط الموديم (modem type) لإدارةٍ من خارج النطاق (out-of-band management)، عدا ذلك، تستطيع الوصول إلى الجهاز من داخل النطاق باستخدام الشبكة، ويمكنك أن تستخدم البطاقات الشبكيّة المتوفِّرة في الجهاز للاتصال إليه عبر «طرفيّة وهميّة» (virtual terminal) مثل عملاء Telnet أو تنزيل الملفات عبر TFTP، وغيرها من البروتوكولات مثل بروتوكول FTP وبروتوكول «النقل الآمن» (secure copy) لضبط ومراقبة وإدارة الجهاز عبر خادوم إدارة مركزية عبر الشبكة، أو أداة إدارة شبكيّة مثل SNMP، أو «Cisco Works» في حالة أنظمة سيسكو. يتضمّن نظام IOS صَدَفة (shell) ضبط معروفة باسم «واجهة سطر الأوامر»؛ التي يمكن استعمالها لإدخال أو لصق الأوامر لضبط الجهاز، وتوجد عدِّة أنواع (أو نكهات [flavors]) من نظام IOS اعتمادًا على نوع الجهاز، بما في ذلك الجدر الناريّة، ونقاط الوصول اللاسلكية، والمبدِّلات، والموجِّهات ...إلخ. ستصبح الأوامر متوفرةً في عدِّة أنمطٍ تتبع النهج الهرمي؛ على سبيل المثال، إذا ذهبت إلى نمط الضبط العام (global) لضبط أشياءٍ متعلقة بالموجِّه كجهاز، يمكنك بعدها الذهاب إلى وضع ضبط المنافذ الشبكيّة... لكل نمط شكل مِحَث (prompt) مختلف لتسهيل التعرّف عليه بصريًّا. يمكنك الضغط على زر Enter عندما بعد أن تكتب الأوامر لتفسيرها وتنفيذها مباشرةً؛ ستذهب تلك الأوامر إلى ذاكرة RAM إلى شيءٍ يُعرَف بالضبط التشغيلي (running configuration). ويجب حفظها إلى شيءٍ يُعرَف بالضبط الإقلاعي (startup configuration) لكي تتاح بعد إعادة إقلاع الجهاز؛ مثالٌ عن أحد أنواع الضبط هو نمط EXEC، الذي يسمح للمستخدمين بفتح صدفة (shell) في الجهاز وبدء عملية ضبطه؛ هنالك نمطان للوصول إلى أجهزة سيسكو: نمط المستخدم العادي (user mode)، ونمط المستخدم ذو الامتيازات (privilege mode)؛ يمكن للمدير في نمط المستخدم العادي أن يراقب ويتحقق من الضبط أدوات التشخيص لمرا ئقبة الشبكة والجهاز نفسه، أما في نمط المستخدم ذو الامتيازات، سيكون لديك المزيد من الامتيازات الإدارية على صيانة برمجيات ومكوِّنات الجهاز بالإضافة إلى قدرتك على ضبطه. نمط EXEC في نظام تشغيل IOS (نمط المستخدم العادي) نمط المستخدم هو أوّل ما ستصادفه عندما تتصل إلى الجهاز؛ سيكون لديك إمكانية مراقبة الجهاز لكن دون القدرة على ضبطه؛ يمكنك التعرّف على نمط المستخدم العادي بالنظر إلى مِحَث الأوامر؛ حيث سيحتوي على اسم الجهاز متبوعًا بإشارة «أكبر-من»؛ تستطيع في هذا النمط تشغيل المساعدة على الإنترنت في واجهة سطر أوامر IOS؛ وذلك بكتابة علامة استفهام مما يتيح لك وصولًا إلى معلوماتٍ عن الأوامر المتوفرة في هذا النمط. DSTR2 con0 is now available Press RETURN to get started. User Access Verification Username: admin Password: DSTR2>? Exec commands: access-enable Create a temporary Access-List entry access-profile Apply user-profile to interface clear Reset functions connect Open a terminal connection … نمط EXEC في نظام تشغيل IOS (نمط المستخدم ذو الامتيازات) النمط الثاني هو نمط المستخدم ذو الامتيازات، الذي سيمح لك بالمراقبة والتشخيص بالإضافة إلى إمكانيات الصيانة والضبط؛ وهذا النمط هو أساس بقية أنماط الضبط، ويمكنك التعرّف على نمط المستخدم ذو الامتيازات إذا رأيت اسم الجهاز متبوعًا بإشارة المربّع. ولكي تنتقل من نمط المستخدم العادي إلى نمط المستخدم ذو الامتيازات، فعليك إدخال الأمر enable وستُسأل عن كلمة اسم المستخدم وكلمة المرور. DSTR2> DSTR2>enable Password: DSTR2# DSTR2#? Exec commands: access-enable Create a temporary Access-List entry access-profile Apply user-profile to interface access-template Create a temporary Access-List entry … وسائل المساعدة في سطر أوامر المبدلات المساعدة في سطر أوامر أجهزة سيسكو مفصّلة بشكل كبير؛ فتتوفر لك مساعدةٌ حساسةٌ للسياق، التي تسمح لك بسرد الأوامر المتوفرة في كل نمط ضبط ومساعدتك ببناء الشكل العام للأوامر بكتابة علامة استفهام في كل خطوة أو في كل وسيط في الأمر نفسه. ولديك إمكانية التنقل إلى الأعلى والأسفل في حافظة تأريخ الأوامر (command history)، مما يمكّنك من استدعاء الأوامر الطويلة والمعقّدة دون الحاجة إلى إعادة كتابتها؛ وستساعدك رسائل الخطأ من التعرّف على المشاكل في أي أمر يمكن أن يكون قد أُدخِل بصيغة غير صحيحة، حيث سترى رسائل الأخطاء في البنية (syntax errors)، أو رسائل الأوامر غير المكتملة، أو الرسائل التي تشير إلى أنَّ الأمر غير موجود. تتضمن ميزات التعديل المُحسَّن أوامر تسمح لك بالتحرك بسلاسة في سطر الأوامر لإجراء تصحيحات أو تعديلات؛ حيث سيتحرّك المؤشر إلى بداية السطر عند الضغط على Ctrl-A، أو إلى نهاية السطر بالضغط على Crtl-E، ويمكنك التنقل إلى الإمام وإلى الخلف حروفًا وكلماتٍ، وحذف حرفٍ وحيدٍ أو مسح كل السطر بالضغط على Ctrl-U؛ وأحد أكثر المفاتيح فائدةً هو المفتاح Tab، الذي سيُكمِل الأوامر بعد أن تُدخِل أول عدِّة أحرف منها. يمكنك التحرك إلى الأمام والخلف عبر تأريخ الأوامر مستخدمًا Ctrl-P و Ctrl-N أو عبر أزرار الأسهم (إلى الأعلى، وإلى الأسفل)؛ إذا أردت رؤية جميع التأريخ المتوفر، فيمكنك تنفيذ الأمر show history، الذي تكتبه في نمط EXEC، ويمكنك زيادة حجم التأريخ عبر زيادة عدد أسطره. تُخزَّن ملفات الضبط تخزينًا حيًّا في ذاكرة RAM، وهذا ما يُسمى بالضبط التشغيلي (running configuration) الذي هو الضبط النشط الذي يحكم آلية عمل الجهاز في تلك اللحظة؛ وهناك ما يُسمى بالضبط الإقلاعي (startup configuration)، الذي يكون مخزنًا في ذاكرة تُسمى NVRAM (اختصار للعبارة nonvolatile RAM)؛ يتضمن الضبط الإقلاعي جميع الأوامر التي يجب أن تكون متوفرةً عند إقلاع الجهاز مرةً أخرى. يمكنك مشاهدة النسخة الحالية من الضبط عبر الأمر show running-config، والأمر show startup-config لعرض الضبط الإقلاعي. قد تكون النسختان مختلفتين عن بعضها لأن عملية حفظ الضبط التشغيلي إلى ضبط إقلاعي هي عمليةٌ يدويةٌ. فإذا لم تحفظه، فسيكون ملفا الضبط مختلفين وقد تخسر تغييراتك التي أجريتها عندما تعيد الإقلاع. يعرض الأمر show running-config الضبط التشغيلي الموجود في ذاكرة RAM، مما يسمح لك بمراقبة وإدارة هذا النوع من الضبط. DSTR2#show running-config Building configuration... Current configuration : 1481 bytes ! version 15.0 سيُظهِر الأمر show startup-config محتويات ملف الضبط في NVRAM، لاحظ أن الأمر show running-config يبني الضبط من ذاكرة RAM ولهذا ستحصل على تلك الرسالة التي تشير إلى ذلك، بينما الأمر show startup-config يعرض محتويات ملفٍ موجودٍ في NVRAM؛ بالإضافة إلى عرضه لعدد البايتات التي يستهلكها ملف الضبط، والكميّة الإجمالية المتاحة من ذاكرة NVRAM. أُخِذ ناتج الأوامر الموجودة في هذه المقالة من مبدِّل DSTR2 في «مخبر التبديل» (switching lab). ترجمة -وبتصرّف- للمقال Supporting a Layer 2-to-Layer 3 Boundary Design.
  15. نحن نعلم أنَّ الطبقة الأولى تتعامل مع الوسائط (media) الفيزيائيّة؛ وهي تتعلق بالبتات والإشارات (signals) والواصلات (connectors) والأكبال وغيرها من المكّونات الفيزيائيّة. أمثلة هي: الاتصالات التسلسلية (serial connections) لشبكات WAN، والمُكرِّرات (repeaters) للشبكات الضوئية (optical networks)، والبروتوكولات الأخرى والمواصفات الفيزيائية للبطاقات الشبكيّة، التي قد تكون مثلًا «إيثرنت» (Ethernet). أجهزة الطبقة الثانية نتعامل في الطبقة الثانية مع الوصول إلى الوسائط (media)، لذلك نقوم بتقسيم المعلومات إلى إطارات (framing of information) لتوفيرها إلى الطبقة الفيزيائية؛ ونقوم أيضًا في الطبقة الثانية بإسناد العناوين، وإنشاء الجسور، والتبديل (switching) لتجاوز محدودية الوسائط الفيزيائيّة ولتجميع اتصالاتٍ متعددة من عدِّة نهايات؛ وبهذا تملك البطاقة الشبكيّة وصولًا «ذكيًّا» إلى الوسائط؛ وتتمكن المبدِّلات من وصل عدِّة أجهزة؛ وتُستخدَم الجسور تقليديًّا (مع غيرها من الأجهزة) لزيادة المسافة العظمى لبعض الوسائط الفيزيائية. إسناد العناوين (addressing) في الطبقة الثانية مهمٌ جدًا، لأننا نتكلم عن اتصالات «النّد-للنّد» (peer-to-peer)؛ ومثالٌ عن ذلك هو عنوان MAC ‏(media access control address) في شبكات إيثرنت؛ فجميع النهايات الشبكيّة تملك عنوان MAC، وحتى في بعض الأحيان يكون للمبدِّلات (switches) عناوين MAC. أجهزة الطبقة الثالثة يمكن أن تُفصَل الشبكات عن بعضا اعتمادًا على المسافة أو المكان الجغرافي، أو ربما تريد تقسيم شبكتك إلى عدِّة أجزاء؛ ففي هذه المرحلة، ستحتاج إلى جهازٍ في الطبقة الثالثة للقيام بدور التوجيه واختيار أفضل طريق؛ وستتمكن النهايات الشبكيّة من اتخاذ قراراتٍ عن مكان إرسال الرزم عبر طبقة الشبكة؛ فلو كانت الوجهة في قسمٍ أو شبكةٍ مختلفة، فإن الموجهات ستعرف الطريق إلى الشبكة الهدف، وستعطيه لتلك الرزم. إن عناوين الطبقة الثالثة مهمة ليس اتباعًا لنموذج اتصالات الند للند، وإنما أيضًا لإضافة هيكليّة إلى تسمية الأجهزة والتعرّف إليها؛ فكل نظام تشغيل خاص بالشبكة له صيغة عناوين خاصة به... فمثلًا، يستخدم بروتوكول TCP/IP عناوين IP. نماذج OSI الشاملة تَستخدم عناوين NSAP؛ لكن حصول كل جهاز على عنوان IP فريد خاص به، بالإضافة إلى الهيكليّة الموجودة في عناوين IP ستخدم هدف السماح للأجهزة والنهايات الشبكية والموجهات بمعرفة أين يجب أن تكون العقدة التوجيهية (next-hop) التالية لكي نصل إلى الوجهة المطلوبة. شرح عملية ARP نحن نعلم مدى أهميّة التفاعل بين الطبقات في النموذج الطبقي؛ في الحقيقة، نعلم أن الاتصالات العمودية بين الطبقات مهمة في نموذج اتصالات الند للند؛ حيث ستفدينا عناوين IP في سدّ الفجوة بين الطبقتين الثالثة والثانية؛ وعندما تُجمَّع الرزم الشبكيّة وتُنشَأ الاتصالات، فستحتاج الأجهزة إلى الوصول إلى الوسائط الفيزيائية، أي أن علينا الانتقال إلى الطبقة الثانية، ولهذا سنحتاج عنوان MAC إن كنّا نستخدم بروتوكول إيثرنت؛ إذ أنَّ المعلومات القادمة من الطبقات الأعلى هي عنوان IP، ويستطيع ARP التحويل بينهما. في هذا المثال، سيكون لدينا الجهاز A الذي سيحاول إرسال رزم شبكيّة إلى 172.16.3.2، ولكي يستبين ويتعرَّف على عنوان MAC لذاك IP، فإننا نستخدمARP لإذاعة السؤال الآتي: «من هو 172.16.3.2؟» وسيستلم كل جهازٍ على الشبكة هذا السؤال، لكن سيرد الجهاز صاحب عنوان IP الموافق فقط، ويعطي عنوان MAC الخاص به. وبالتالي سيحصل المُرسِل على معلومات عنوان MAC ويستطيع إنشاء الاتصال في الطبقة الثانية. من المهم أن تُخزَّن (cached) معلومات ARP في كل جهاز على الشبكة، لأن الإذاعة «مكلفة» بتعابير الشبكة، ويجب أن تبقى تلك المعلومات لفترةٍ محددة، ﻷنها من غير المحتمل أن تتغير خلال الاتصال؛ ولهذا، سيحتوي جدول ARP على معلومات الربط (mapping information) وهو ديناميكي لتعلم ARP، وإبقاء جدول الربط لفترة، ومن ثم التخلص منه بعد انقضاء فترة صلاحيته للاستجابة إلى أيّة تغيرات قد حصلت في الربط؛ وتكون المهلة عادةً هي 300 ثانية، لكن هذا يعتمد أيضًا على نظام التشغيل؛ يمكن مثلًا الحصول على جدول ARP على نظام ويندوز باستخدام الأمر arp -a. C:\Users\Administrator>arp -a Interface: 192.168.0.7 --- 0xe Internet Address Physical Address Type 192.168.0.1 a0-f3-c1-05-a4-96 dynamic 192.168.0.6 e4-ce-8f-9c-19-b3 dynamic 192.168.0.12 00-26-96-00-18-5e dynamic 192.168.0.255 ff-ff-ff-ff-ff-ff static أدوات المضيف طريقة جيّدة للتحقق من قابلية الاتصال دون الحاجة إلى وجود تطبيق لإرسال البيانات هي استخدام الأدوات المختلفة الموجودة في طبقة الشبكة. أحد الأمثلة على تلك الأدوات هو ping، الذي يُرسِل طلبات ICMP echo إلى عنوان IP معيّن أو اسم مضيف كما في هذا المثال؛ وبالطبع، سيتحوَّل اسم المضيف إلى عنوان IP، ثم ستستخدمه الأداة ping. فإذا وصلت رسالة الاختبار (probe) إلى الوجهة، وكانت الوجهة قادرةً على الرد على ICMP echo، فسيعلم المُرسِل أنَّ المستقبِل يعمل ويمكن الوصول إليه؛ لكن الأمر سيكون عديم الفائدة إن لم نحسب الزمن اللازم للوصول إلى الوجهة؛ حيث تحسب الأداة ping الزمن اللازم لإتمام الرحلة إلى الهدف؛ ويعطيك ناتج الأمر الزمن الأدنى والأقصى والمتوسط للرحلات؛ ونسبة مئوية للرزم المفقودة؛ ويوجد لهذا الأمر خياراتٌ لتحديد حجم الرزمة، وعدد الطلبيات التي ستُرسَل، والمهلة التي يجب انتظارها لكل عملية رد. أداةٌ أخرى مفيدةٌ جدًا هي trace، واسم الأمر في حالة نظام ويندوز هو tracert؛ حيث سيُظهِر هذه الأمر جميع الموجِّهات بين المُرسِل والمُستقبِل؛ لذا فإنه يعرض الطريق إلى الوجهة، مُظهِرًا جميع العقد التوجيهيّة (hops) والموجِّهات؛ ويعرض أيضًا معلومات الرحلة إلى كل بوابة، ويُظهِر آخر سطرٍ معلومات الرحلة الإجمالية إلى الوجهة. تعمل هذه الأداة عملًا مختلفًا وفقًا لنظام التشغيل، بعضها يستخدم رزم UDP، وبعضها يستخدم ICMP؛ ويكون لديها خياراتٌ كغيرها من الأوامر، يمكنك على سبيل المثال أن تُحدِّد العدد الأقصى من العقد التوجيهية لتضمِّنها في الناتج، أو أن تُحدِّد قائمةً بالبوابات التي تريد العبور خلالها للوصول إلى الوجهة. ترجمة -وبتصرّف- للمقال Exploring the Packet Delivery Process.
  16. شاهدنا عبر مسيرة تطور الشبكات المحلية كيف أنَّ كفاءة الشبكة واستغلال التراسل الشبكي أصبحا ميزتين محوريتين ومهمتين في كلٍّ شبكةٍ محليةٍ؛ وأصبحت الحواسيب والخواديم في أيامنا هذه قادرةً على معالجة آلاف ملايين العمليات في الثانية الواحدة، وهذا يعني أنها تملك المزيد من القدرة على توليد البيانات بدرجةٍ أكبر وإرسال المزيد من المعلومات عبر الشبكة. ازدحام الشبكة – الموزعات في مواجهة الجسور بصفةٍ عامة، ازدادت كميات البيانات التي تُنقَل عبر الشبكة المحلية (LAN) وذات النطاق الواسع (WAN) أضعافًا كثيرة، وتفرض البرمجيات الشرهة للتراسل الشبكي -مثل الفيديو، والوسائط المتعددة، والتعلم الإلكتروني ...إلخ.- متطلباتٍ صارمةً لشبكاتنا. نحن نعلم أنَّ الموزَّعات (hubs) لا يمكن أن تُستخدَم بفعاليّة في شبكاتنا الحالية لأنها تمثِّل مجالًا وحيدًا للتصادمات ومجالًا وحيدًا للإذاعة في كل موزِّعٍ، ولا يمكنها التعامل مع كمّياتٍ ضخمةٍ من البيانات الشبكيّة التي تمر في شبكاتنا العصرية؛ تمثِّل الجسور (bridges) تحسينًا كبيرًا، بينما ما تزال تعمل في الطبقة الثانية من نموذج OSI، لكنها تملك ذكاءً لتمرير الإطارات (frames) بناءً على معرفتها للمصدر والوجهة على شكل عنوان MAC؛ وعلى الرغم من أنَّها تملك منافذ أقل وهي أبطء، لكنها أفضل من الموزَّعات؛ وفي الواقع، يمكنها إنشاء مجالات تصادمات متعددة مثلها مثل المبدِّلات. المبدلات على الرغم من أنَّ آلية العمل الأساسية للمبدِّلات مشابهةٌ للجسور، لكن المبدِّلات تعمل بسرعات أعلى بكثير وفيها وظائف أكثر مقارنةً مع الجسور؛ وفيها عدد منافذ أكثر، فتتضمن مبدِّلات طبقةِ الوصولِ (access layer LAN switches) الاعتيادية من 28 إلى 48 منفذًا (port)، ويمكن أن تدعم مبدِّلات طبقة التوزيع (distribution layer switches) مئات المنافذ؛ وهذا يجعلها داعمةً للتوسع بشكلٍ كبير، ولها قدرة على تخزين الإطارات الكبيرة والمزيد من المعلومات مؤقتًا، مما يقلل من احتمال تجاهل بعض الإطارات الشبكيّة عندما تتم معالجتها؛ ومن المُرجَّح أن تدعم مزيجًا من سرعات المنافذ تتراوح بين 10 إلى ‎100 Mb/s إلى ‎1 Gb و ‎10 Gb/s وخصوصًا في «الخطوط الصاعدة» (uplinks) إلى الشبكات الأكبر. تتضمن المبدِّلات عدِّة مجالات للتصادمات أو مجالًا واحدًا لكل منفذ للسماح بإجراء اتصالاتٍ متعددة في نفس الوقت وزيادة سلاسة مرور البيانات العابرة في المبدِّل بآنٍ واحد. ويمكن أيضًا ضبطها لدعم عدِّة أنماط من «التبديل» (switching)؛ فنمط «التخزين-والتمرير» (store-and-forward) هو النمط التقليدي الذي تُخزَّن فيه الرزم كاملةً مؤقتًا قبل إرسالها لكي تتم معالجتها وتحديد المنفذ الصادر. وهنالك آليةٌ أخرى أكثر كفاءة هي نمط «المرور» (cut-through)، الذي يتم فيه تمرير الرزم في أسرع وقت ممكن بعد أن يتمكن المبدِّل من تحديد عنوان الوجهة؛ وهذا يحدث حتى لو لم يستلم المبدِّل الرزمة كاملةً؛ خيارٌ آخر هو نمط التبديل «الخالي من القطع» (fragment-free) الذي يتغلب على مشاكلٍ متعلقةً بالأخطاء المحتملة في نمط «المرور» (cut-through). تتشابه الجسور والمبدِّلات في أنها تصل بين مختلف قطع (segments) الشبكة المحليّة، وتتعلم عناوين MAC لترشيح البيانات وإرسالها إلى المنفذ الملائم حيث تتواجد الوجهة؛ لكن توجد ميزات في المبدِّلات تجعلها أكثر كفاءةً في تخفيف الازدحام والاستفادة بصورة أفضل من التراسل الشبكي. هذه قائمةٌ بتلك الميزات: أولها هو التواصل المخصص بين الأجهزة المعروف باسم «التجزئة الصغيرة» (micro segmentation)، وهذه الميزة تجعل الأجهزة لا تتنافس مع بعضها لإرسال البيانات، إذ يمثِّل كل منفذٍ في المبدِّل مجال تصادماتٍ مختلف؛ أي أنَّه لا توجد تنافسية بين الأجهزة ولا يحصل -نظريًّا- أيّة تصادمات. قد تظن أنَّه ما يزال هنالك تنافسيةٌ في الشبكة بسبب احتمال محاولة طرفَيّ الوصلة إرسال البيانات في نفس الوقت، لكن ذلك غير موجود والفضل يعود إلى الاتصالات ثنائية الاتجاه (full-duplex)، مما يسمح لجهازَين بالإرسال معًا في آنٍ واحد، مما يزيد من مقدار نقل البيانات، فمثلًا يمكن لوصلة بسرعة ‎100 Mb/s أن تنقل البيانات بسرعة 200‎ Mb/s. ميزةٌ أخرى مهمة هي أنَّ المبدِّلات تسمح باتصالاتٍ متعددة في آن واحد؛ وهذا بسبب ما يسمى «switching fabric» في المبدِّل، الذي هو مجرد حافظات داخلية تسمح لأزواجٍ متعددة من المنافذ بإرسال الإطارات في آنٍ واحد. هنالك بعض أنواع المبدِّلات التي تسمح لجميع المنافذ بإرسال جميع الإطارات في جميع المحادثات معًا، التي تسمى «wire-speed nonblocking servers»، ويكون بالطبع ثمنها أغلى. هنالك ميزةٌ أخرى تسمح للمبدِّلات بالتعامل مع سرعاتٍ متفاوتة على منافذ مختلفة مما يجعل المبدِّل يعمل كوسيط لنقل الرزم بين تلك المنافذ؛ وهذا يسمح باستخدام المبدِّل لوصل عدِّة أجهزة بسرعاتٍ قليلة أو بتراسل شبكي صغير، ويمكن لها في نفس الوقت التعامل مع الاتصالات ذوات السرعات العالية مع بقية الشبكة. ولهذه الأسباب، تتفوق المبدِّلات على الجسور؛ مما يجعلها الاختيار الأنسب للشبكات المحلية في هذه الأيام، فلم يعد من المعقول استخدام الموزَّعات والجسور في الشبكات العصرية؛ وبغض النظر أنَّ المبدِّلات تعمل في الطبقة الثانية مثلها مثل الجسور، لكنها تملك منافذ أكثر بسرعاتٍ أكبر، وكما ذكرنا سابقًا، لديها ذكاءٌ لتمرير، أو ترشيح، أو «إغراق» الشبكة بالإطارات الشبكيّة؛ فعندما تستلم المبدِّلات إطارًا، فإنها تبحث عن عنوان MAC للوجهة في جدول عناوين MAC الخاص بها، فإذا وجدت مطابقةً فإنها ستُمرِّر الإطار إلى المنفذ حيث تتواجد الوجهة، وإلا فسترسِل الإطار إلى جميع المنافذ عدا المنفذ الذي أتى منه الإطار. تبديل الإطارات (Switching Frames) هذا شرحٌ مرئيٌ للعملية؛ ففي الخطوة 1، يُرسِل الحاسوب A إطارًا إلى المبدِّل، ثم سيقارن المبدِّل عنوان MAC للوجهة مع جدول عناوين MAC الخاص به، فلا يجده؛ وقبل إرسال الإطار إلى جميع المنافذ، فسيربط المبدِّل عنوان MAC للحاسوب A إلى المنفذ بتضمين العنوان في جدول عناوين MAC؛ تتم إذاعة الإطار في الخطوة 3 على كل المنافذ، ثم -في الخطوة 4- ستستقبل الوجهة الإطار وترسِل إشعارًا مع عنوان MAC الخاص بها؛ ثم سيستمع المبدِّل إلى الرد في الخطوة 5 ويضيف عنوان MAC للحاسوب B إلى جدوله؛ ويكون المبدِّل جاهزًا لتمرير الإطارات في الخطوة 6. بكلامٍ آخر، سيمرر المبدِّل الإطار إلى المنفذ 1 فقط، وهو المنفذ الذي يقبع فيه الحاسوب A استنادًا إلى جدول MAC. نحن نعلم أنَّه يمكن لجميع الأجهزة المتصلة إلى مبدِّل أن ترى بعضها بعضًا في قطعة شبكيّة (network segment)؛ ومن احتياجات الاتصال في شبكاتنا المحلية الحالية هي التوسع إلى عدِّة مجموعات عمل، والتوجه الحالي في الشبكات ينزع إلى المركزية وأن تكون مجموعات العمل متصلةً فيما بينها وتملك وصولًا إلى الموارد المركزية (مجموعة خواديم) وإلى الإنترنت. ولهذا نُنشِئ شبكاتٍ كبيرةً مصنوعةً من سلسلةٍ من المبدِّلات الموصولة فيما بينها بخطوط ربطٍ سريعة؛ مما يُمكِّن آلاف المستخدمين من الاتصال إلى شبكةٍ فيها مجال إذاعة وحيد. لا تنسَ أن المبدِّلات تمثَّل مجال إذاعةٍ وحيدًا؛ فإذا وصلت عدِّة مبدِّلات فيما بينها، فسيكون لديك مجال إذاعةٍ وحيد؛ وهذا يعني أنَّ رسالة الإذاعة المُرسَلة من أحد المستخدمين على مجموعة عمل ما ستُشاهَد من كل الشبكة، وهذا سيُنقِص من الأداء وله تأثير على استهلاك التراسل الشبكي. لمحة عن VLAN تستعمل VLANs كطريقة لإنشاء عدِّة مجالات للإذاعة في نفس المبدِّل أو في سلسلة هيكليّة من المبدِّلات. VLAN هي شبكة LAN وهمية (Virtual LAN) تُحسِّن من الأداء عبر إنشاء مجالات إذاعة، وتسمى هذه العملية بالتقطيع (segmentation)؛ فرسائل الإذاعة المولَّدة من جهازٍ على شبكة VLAN معيّنة ستُرى من بقيّة الأجهزة على شبكة VLAN نفسها؛ ولن تنتقل إلى شبكات VLAN الأخرى؛ يُعتَبر كل مجال إذاعة أو شبكة VLAN هو شبكة IP فرعية (IP subnet)، وهذا يعني أنَّه للتواصل بين مختلف شبكات VLAN فستحتاج إلى استخدام وظائف في الطبقة الثالثة من نموذج OSI، أي بكلامٍ آخر، ستحتاج إلى موجِّه؛ مما يجعل شبكات VLAN أداةً أمنيةً لأن بيانات التراسل الشبكي المُرسَلة عبر شبكات VLAN يجب أن تمر على الموجِّه، وبهذا تستطيع ضبط التحكم بالوصول في الموجِّه الخاص بك. إحدى طرق استخدام شبكات VLAN هي إسناد منافذ المبدِّل إلى شبكات VLAN معيّنة، مما يفصل بين الموقع الفيزيائي للجهاز وشبكة LAN الوهمية التي ينتمي إليها؛ أي بكلامٍ آخر، يمكن أن يكون لديك جهازٌ في الطابق الثالث ينتمي إلى شبكة VLAN معيّنة، ويمكن أن يكون جهازٌ في الطابق الأول جزءًا من تلك الشبكة الوهمية أيضًا، وهما في الواقع متصلان بمبدِّلَين مختلفَين، لكن جميع المبدِّلات في الشبكة المحلية تَعرِف تعريف الشبكات الوهمية الذي ضَبَطَتَهُ؛ مما يُنشِئ بيئاتٍ مرنة، فلم يعد المكان الفيزيائي مهمًا، وستكون الإضافات والتغيرات في الشبكة أسهل في التنفيذ؛ فلو أردت أن يصبح جهازٌ ما جزءًا من مجموعة عمل معيّنة، فكل ما عليك فعله هو تغيير الشبكة الوهمية (VLAN) لمنفذ المبدِّل الذي يتصل فيه ذاك الجهاز. ترجمة -وبتصرّف- للمقال Developing an Optimum Design for Layer 2.
  17. يساعدنا هذا الدرس في فهم التحديات التي تواجه التقنيات التشاركيّة (shared technologies) مثل إيثرنت؛ ستتعرَّف على بعض الأمور المتعلقة بمحدودية المسافة وأجهزة الاتصال؛ تتضمن هذه الأجهزة الموزِّعات (hubs)، لكننا سنركِّز على المبدِّلات (switches)، وكيف تتعامل مع التصادمات (collisions) بتحديد مجالات التصادمات (collision domains). محدوديات قطع الشبكة المحلية رأينا أنواعًا مختلفة من إيثرنت اعتمادًا على نوع الوسيط (media)، إذ لدينا أطوال قطعٍ (segment) مختلفة، وستضعف قوة الإشارة تبعًا للمسافة؛ ستؤثر هذه المحدوديات على طريقة تصميمك لشبكة إيثرنت، ونوع الأجهزة التي عليك استعمالها لزيادة محدودية المسافة. على سبيل المثال، ستضعف قوة الإشارة في الأكبال المجدولة بعد 100 متر، بينما ستضعف الإشارة المنقولة في أكبال الألياف الزجاجية بعد عدِّة كيلومترات. جزءٌ من عمل بعض العناصر الشبكيّة ليس فقط وصل الأجهزة المختلفة، وإنما أيضًا زيادة حدود المسافة القصوى بتكرير (repeating) وبتضخيم (amplifying) الإشارة. الموزِّع هو الجهاز الذي كان يُستعمَل في شبكات إيثرنت المحليّة في أيامها الأولى، ولم يكن «ذكيًّا» لإدارة تراسل البيانات وعدِّة اتصالات تحدث في آنٍ واحدٍ بكفاءة. فعندما يستلم الموزِّع إشارةً، فسوف يكررها إلى جميع المنافذ الشبكيّة المتاحة؛ وهنالك مشكلتان في ذلك: أولهما هو أنه لا يعلم المصدر والوجهة، فسترى جميع الأجهزة البيانات المُرسَلة من أي جهازٍ على الشبكة، وهذا غير عملي، وسيخفِّض أداء الأجهزة جميعًا؛ أما المشكلة الثانية فهي أن الأجهزة تتشارك في تراسل البيانات (bandwidth) نفسه، فعلى الرغم من أنَّ لكل جهازٍ متصلٍ إلى الموزَّع كابلٌ خاصٌ به، لكن ستُحاسب جميع الأجهزة على تراسل البيانات ذاته. مجالات التصادمات يمثِّل كلُ موزِّعٍ مجال تصادمٍ وحيدًا؛ يُعرَّف مجال التصادم بعدد الأجهزة المتصلة التي يمكن أن تتأثر بإشارات التشويش الناتجة عن التصادمات؛ فإذا كنت تذكر آلية عمل تحسس الناقل للتصادمات في إيثرنت، فستعلم أنَّه عندما يحاول جهازان «التحدث» في نفس الوقت، فسيتحسسان الناقل، ويلاحظان التصادم، ثم سيرسلان إشارة تشويش (jam signal) ليعلم الجميع أنَّ عليهم عدم الإرسال في هذا الوقت؛ وفي حالة الموزَّع، فسترى جميع الأجهزة المتصلة إشارة التشويش وستتوقف عن الإرسال؛ وسيخفِّض هذا النوع من البيئات الشبكية من الأداء، وسيبطِّئ من عمل الشبكة؛ وهذا شبيهٌ بمحاولة عدِّة أشخاصٍ التحدث في نفس الوقت في مؤتمرٍ هاتفي، إذ تلاحظ أنهم سيقاطعون بعضهم بعضًا وسيحاولون التوقف عن الكلام لتجنب «التصادم». حلٌ آخر لهذه المشكلة هو إضافة المبدِّلات؛ فيمثِّل كل منفذٍ (port) في المبدِّل مجالًا للتصادمات، فهذا يعني أن التصادمات ستؤثر على الجهاز المتصل بهذا المنفذ فقط؛ وفي الواقع يمكننا القول أنَّه لا توجد تصادمات في بيئة شبكيّة تعتمد كليًّا على المبدِّلات. أمرٌ آخرٌ هو أنَّ المبدِّلات فيها «ذكاء» لتمرير البيانات مع علمها بالمصدر والوجهة؛ أي بكلامٍ آخر، على الرغم من أنَّ المبدِّل «يُغرِق» الشبكة ببيانات التراسل في المرّة الأولى التي يرى فيها مصدرًا أو وجهةً، لكنها سيتعلم أماكن تلك المصادر والوجهات ويصلها أو يربطها مع المنافذ التي تتصل تلك الأجهزة عليها؛ ويمكن للمبدِّل بعد تعلم أماكن المصادر والوجهات أن يُمرِّر الرزم إلى الوجهة المحددة دون إرسالها إلى جميع الأجهزة كما في الموزَّع. مجالات الإذاعة مفهومٌ مهمٌ آخر هو «مجالات الإذاعة» (broadcast domains). يُعرَّف مجال الإذاعة بعدد الأجهزة التي تتأثر بالإذاعة، أي بكلامٍ آخر، عدد الأجهزة التي يمكنها رؤية ومعالجة الرسائل المُرسَلة إلى الإذاعة؛ ويمثِّل موزِّعٌ واحدٌ مجال إذاعةٍ وحيدًا، وكذلك الأمر للمبدِّلات (بضبطها الافتراضي)؛ فعلى الرغم من أنَّ المبدِّلات تحل مشكلة التصادمات، لكنها ما تزال توزِّع الإذاعات مما يخفِّض من الأداء. أحد الحلول هو تقسيم الشبكة إلى عدِّة مجالات إذاعية عبر الشبكات المحليّة الوهمية (Virtual LANs) التي يُشار إليها بالاصطلاح VLANs. ترجمة -وبتصرّف- للمقال Understanding the Challenges of Shared Local Area Networks.
  18. cisco icnd1

    تربط البطاقة الشبكيّة بين الحاسوب والشبكة المحليّة، وتتواصل مع الشبكة عبر اتصالٍ تسلسلي (serial connection) ومع الحاسوب عبر اتصالٍ بخطوطٍ متوازية (parallel connection)؛ وعندما تتواصل مع الحاسوب، فإنها تتطلب خط طلب المقاطعة (interrupt request line) اختصارًا IRQ، وعنوان دخل وخرج (I/O) ومجالًا للذاكرة ضمن نظام التشغيل، وتَستخدِم التعريفات (drivers) لتوفير «ذكاء» للعتاد حيث تحكم التعريفات طريقة عمل البطاقة الشبكيّة، ويكون عنوان MAC مدمجًا مع البطاقة الشبكيّة من قِبل المُصنِّع. مقارنة مواصفات وسائط إيثرنت النوع 10 BASE-T 100 BASE-TX 100 BASE-FX 1000 BASE-CX 1000 BASE-T 1000 BASE-SX 1000 BASE-LX الوسيط (media) EIA/TIA Category 3, 4, 5 UTP 2 pair EIA/TIA Category 5 UTP 2 pair 62.5/125 micron multimode fiber STP EIA/TIA Category 5 UTP 4 pair 62.5/50 micron multimide fiber 9 micron single-mode fiber الطول الأقصى للقطعة الواحدة 100 متر 100 متر 400 متر 25 متر 100 متر 275 متر (62.5 micron) 550 متر (50 micron) 3 – 10 كيلو متر الواصل (connector) ISO 8877 (RJ-45) ISO 8877 (RJ-45) Duplex media interface connector (MIC) ST ISO 8877 RJ-45 ISO 8877 (RJ-45) - - مواصفات أكبال وواصلات إيثرنت مستمدةٌ من هيئة TIA ‏(telecommunications industry) التي هي جزءٌ من هيئة (Electronic Industries Alliance اختصارًا EIA). أَنشَأت تلك الهيئات المعيارية مواصفة واصل RJ-45، الذي يُستخدَم في غالبية أنواع اتصالات إيثرنت في الوقت الراهن؛ إحدى جوانب مقارنة هذه المصفوفة من مختلف تقنيات إيثرنت هي الاصطلاحات المستخدمة لتعريفها، حيث تُستخدَم ثلاثة مكونات، أول مكوِّن هو رقم يُعرَّف مقدار التراسل الشبكيّ المتاح؛ فعلى سبيل المثال، 10BASE-T هو بسرعة ‎10 Mb/s، أما المكوِّن الثاني هو إن كان التصميم basement أو broadband؛ جميع ما سبق يستخدم baseband أو base؛ أمّا المكوِّن الثالث فيُعرِّف مواصفة الوسيط (media) المُستخدَم؛ على سبيل المثال، تَرمُز T في 10BASE-T إلى الأكبال المجدولة (twisted pair cabling). تُشير الاختصارات FX، و SX، وLX إلى تقنية أكبال الألياف الضوئية، حيث تمثِّل SX أكبال الألياف الضوئية متعددة الأنماط (multimode) لكنها قصيرة المدى؛ أما LX فهي الأكبال الضوئية أحادية النمط (single mode) لكن بطول أكبر قد يصل مداها من 3 إلى 10 كيلو متر. RJ-45 إن RJ-45 هو أحد أشهر واصلات إيثرنت (Ethernet connector)؛ يُشير RJ إلى «المقبس المُسجَّل» (Registered Jack) ذو الرقم 45 الذي يُشير إلى موديل معيّن من الواصلات الفيزيائية فيها ثمانية ناقلات (conductors). ويمكنك شراء الجهاز ثم زيادة وظائفه عبر إضافة مكونات معيّنة أو ترقيتها إلى سرعاتٍ أعلى، مثالٌ على ذلك هو GBIC أو Gigabit Interface Converter، الذي هو «hot-swappable I/Ops» بوضعها في منافذ Gigabyte Ethernet، مما يُمكِّنك من الترقية؛ وأن تضعها في واصل الأكبال الضوئية، وبهذا تستطيع الانتقال إلى تقنيات SX مثلًا دون تغيير الجهاز، وإنما بتغيير البطاقة الشبكيّة في الجهاز فقط. GBICs بتقنية الألياف الضوئية هنالك أنواعٌ مختلفة من GBIC لتقنية الألياف الضوئية، فهنالك طول الموجة القصير للمسافات التي تصل إلى 500 متر، وطول الموجة الطويل LX للمسافات حوالي 5 كيلومتر، و «long haul» للمسافات حوالي 10 كيلومتر؛ و ZX لمسافاتٍ أكبر من 70 كيلومتر؛ تحوِّل هذه المحوِّلات الإشارات الإلكترونية إلى ضوئية وبالعكس. UTP إن الأكبال المجدولة غير المعزولة (Unshielded twisted-pair) المعروفة باسم UTP؛ هي أسلاكٌ رباعية الأزواج فيها ثمانية أسلاك نحاسية مغطاةٌ بمادةٍ عازلة، وتُحاط كلها بغلافٍ خارجي الذي يوفِّر المزيد من الحماية. تكون الأسلاك مجدولةً حول بعضها في ثنائيات، وهذا يقلل من التشويش على الإشارات الذي يُسبِّبه تداخل الموجات الإلكترونية وموجات الراديو. يُستخدم كابل UTP في مختلف أنواع الشبكات؛ يجعل حجمه وواصله الصغير وسماكته منه خيارًا مرنًا أثناء عملية تثبيت الشبكة أو تغييرها، وهو أرخص من غيره من الأكبال، ويستطيع في الوقت نفسه تمرير بيانات بسرعات تصل إلى ‎1 Gb/s، وما زال يزداد شهرةً وأصبح مدعومًا ومستخدمًا في أغلبية الشبكات المحليّة. تُنشِئ سماكة الأشرطة ونوع العزل (بالإضافة لأمورٍ أخرى) تصنيفاتٍ مختلفة، وتُحدِّد أيضًا نوع الاستخدام لأكبال UTP، فمثلًا، يُستعمَل التصنيف 1 عادةً في بيئات الهواتف الأرضية، بينما CAT 6، أو التصنيف 6، يُستعمَل لنقل البيانات بسرعات ‎1 Gb/s. واصل RJ-45 ملائم لإنهاء الأكبال المجدولة غير المعزولة. يجب أن ينتهي كل سلك في مكانٍ خاص اسمه «pin location»، الذي يمكن رؤيته بالنظر إلى الواصل من الأمام؛ أماكن الوصل مرقمة من 1 إلى 8 بدءًا من اليمين؛ ويُعتبَر في كل زوج أول سلك T والثاني R، وهي اختصاراتٌ للكلمتين top و ring؛ وهي اصطلاحاتٌ تنحدر أصولها من الأيام الأولى للهواتف الأرضية. مقبس RJ-45 هو الجزء الأنثوي (female component) من الاتصال، بينما واصل RJ-45 هو الجزء الذكري (male component). الذي يرتبط مع جهاز موجود في الجدار، أو لوحة خاصة اسمها patch panel، وفيه أيضًا أماكن لوصل الأسلاك وهي مرقمة من الواحد حتى الثمانية بدءًا من اليسار. الأكبال المباشرة (Straight-Through cables) سيجعلك ترتيب الأسلاك في واصل RJ-45 تحصل إلى أكبال مباشرة أو متشابكة (crossover)؛ تستعمل الأكبال المباشرة عادةً لوصل الأجهزة إلى الموجهات وعناصر الشبكة، أما الأكبال المتشابكة (crossover) فتستعمل عادةً للوصل بين العناصر الشبكيّة مثل المبدِّلات؛ يكون ترتيب الأسلاك في الأكبال المباشرة في نهايتي الكابل نفسه، فلو وُضِع واصلَيّ RJ-45 بجوار بعضهما في نفس الاتجاه، فستلاحظ نفس تسلسل ألون الأسلاك؛ أما من ناحية وظيفة كل سلك، فإن أزواجًا مختلفةً تُستعمَل للإرسال، والأخرى للاستقبال؛ فعقد TX للإرسال أما RX للاستقبال؛ ويُرسِل كل زوج من الأسلاك إشاراتٍ موجبة وأخرى سالبة لمقاومة التشويش. الأكبال المتشابكة ستجد أن واصلات RJ-45 في نهايتَيّ الكبل تُظهِر أنَّ بعض الأسلاك في الطرف الأول متشابكة وترتبط في مكانٍ مختلف في النهاية الأخرى؛ وتحديدًا، السلك الأول في النهاية الأولى يجب أن يرتبط بالمكان الثالث في النهاية الأخرى؛ والسلك الثاني في المكان السادس؛ أماكن وصل الأسلاك في كلتي النهايتين معروفةٌ بالمعيار EIA/TIA T568A و EIA/TIA T568B؛ راجع الصورة الآتية للتوضيح. وهذا أمرٌ مثيرٌ للاهتمام، لكن الاستخدام العملي لهذا التعريف يكون في وصل مختلف أنواعٍ مختلفةً من الأجهزة، أي أنك تستعمل عادةً كابلًا مباشرًا (straight-through) لربط حاسوب أو خادوم إلى المبدِّلات، وأيضًا بين مبدِّلٍ وموجِّه. يمكنك استخدام الأكبال المتشابكة لوصل العناصر الشبكيّة من نفس النوع، أي بين المبدِّلات، والموجِّهات، وحتى بين الحواسيب والخواديم؛ هنالك حالةٌ خاصةٌ هي وصل حاسوب أو خادوم إلى الموجِّه مباشرةً، حيث يمكنك في هذه الحالة استخدام الأكبال التشابكيّة. ترجمة -وبتصرّف- للمقال Connecting to an Ethernet LAN.
  19. cisco icnd1

    إيثرنت (Ethernet) هو البروتوكول المُختار في الشبكات المحليّة؛ والشبكة المحليّة هي مجموعةٌ من الأجهزة المتصلة داخليًا والمتواجدة في أماكن قريبة من بعضها في منطقة محدودة. هنالك ثلاثة عوامل لتعريف شبكة LAN عن الشبكات واسعة النطاق (WAN)، أولها هو المكان الفيزيائي القريب للأجهزة، وثانيها هو السرعة العالية لنقل البيانات، فهي تتراوح بين 100‎ Mb/s إلى ‎1 Gb/s‎ و ‎10 Gb/s التي نراها في الشبكات المعاصرة؛ وثالثها وأهمها هو أننا لا نحتاج إلى استئجار خط أو الاشتراك عند مزود الخدمة لوصل الأجهزة مع بعضها بعضًا. ويمكن أن تكون شبكة LAN صغيرةً كشبكةٍ في مكتبٍ صغير، أو أن تكون شبكةً في حرمٍ جامعيٍ كبير بعدِّة مبانٍ باتصالاتٍ عبر الألياف الزجاجية بينها. مكونات الشبكة المحلية المكونات (components) الاعتيادية هي: النهايات الشبكيّة مثل الحواسيب الشخصية، والخواديم، والطرفيات ...إلخ. والأجهزة الشبكية التي توفِّر قابلية الاتصال في الشبكة مثل المبدِّلات (switches)، والموجِّهات (routers) لوصل مختلف الشبكات داخليًّا في نفس الشبكة المحليّة، وفي بعض الأحيان قد نجد الموزِّعات (hubs) لمشاركة البيانات. وتُشكِّل البطاقات الشبكيّة والأكبال جزءًا من الشبكة المحليّة. وبخصوص البروتوكولات، فإن بروتوكول إيثرنت هو البروتوكول الحاكم في الطبقة الثانية، و IP في الطبقة الثالثة، وضمن IP تجد بروتوكول ARP وبرتوكولاتٍ أخرى مثل DHCP لأتمتة عملية حجز وإسناد عناوين IP. الشبكة المحليّة هي البيئة التقليدية لكي يتشارك المُستخدمون المواردَ على شكل بيانات، وتطبيقات، ووظائفٍ أخرى؛ أجهزة الدخل والخرج مثل الكاميرات والطابعات موجودةٌ أيضًا؛ وأحد أهم الوظائف للشبكة المحليّة المعاصرة هي توفير قدرة الاتصال إلى الشبكات الأخرى، وذلك عبر البوابات الافتراضية (default gateways) وخلال الموجِّهات وأجهزة WAN الطرفية (WAN edge devices). حجم الشبكة المحلية كما ذكرنا سابقًا، يتراوح حجم الشبكة المحليّة بين المكاتب الصغيرة التي فيها عدِّة أجهزة متصلة بالإنترنت، وحرمٌ كبيرٌ فيها عدِّة مبانٍ بآلاف المستخدمين؛ ويمكن في أيامنا هذه اعتبار أن العاملين عن بُعد جزء من الشبكات المحلية عبر استخدام تقنية VPN ‏(اختصار للعبارة virtual private network)، فالهدف الرئيسي من تقنية VPN هو الوصول إلى شبكةٍ محليةٍ ما؛ وعندها ستكون طريقةُ تعامل المستخدم البعيد مع الشبكة المحلية كما لو أنه كان متصلًا محليًا بها. تطور بروتوكول إيثرنت أُنشِئ بروتوكول الشبكة المحلية «إيثرنت» في السبعينيات من قِبل DEC و Intel و Xerox؛ في الواقع، كان اسمه «DIX Ethernet»، ثم تحول اسمه إلى «thick Ethernet» بسبب استخدام الأكبال المحورية؛ وفي منتصف الثمانينيات، تمت ترقيته لدعم المزيد من الإمكانيات والسرعات، وسُمِّي وقتها «Ethernet 2»، وفي نفس الوقت تقريبًا، كانت منظمة IEEE تُنشِئ معايير لشبكاتٍ شبيهةٍ بإيثرنت، التي كان يُطلَق عليها اسم «802.3». وشاهدنا عبر السنوات، كيف أن بروتوكول إيثرنت تطوَّر إلى ‎10 Mb/s و ‎100 Mb/s ومن ثم إلى ‎1 Gb/s وحاليًا ‎10 Gb/s على شكل معيار IEEE ذي الاسم «802.3AE». معايير LAN القياسية: معيار IEEE 802.3 إذا نظرنا إلى إيثرنت من وجهة نظر نموذج OSI، فسنرى أنه يرتبط بطبقة وصل البيانات (data link layer) لكنه يحتوي بعض المواصفات (specifications) في الطبقة الفيزيائية؛ إذا نظرة إلى البروتوكولات الأخرى، مثل IEEE 802.3U، الذي هو «Fast Ethernet»، أو ‎.3Z الذي هو «‎1 Gb Ethernet»، و 3AB الذي هو «‎10 Gb Ethernet»، فسنلاحظ أنَّ المواصفات في الطبقة الفيزيائية موجودةٌ فيه، وهنالك إشارات إلى تقنيات الألياف الضوئية وواصلاتها لتوفير سرعات عالية. هذا البروتوكول مُقسَّم إلى طبقتين فرعيتين، طبقة التحكم بوصول الوسائط (media access control sublayer) التي تتعامل مع الوصول إلى الوسائط وتعريف عناوين MAC كطريقة لتمييز كل الأجهزة في شبكة إيثرنت؛ وطبقة التحكم بالوصل المنطقي (logical link control sublayer) التي تتعامل مع التواصل مع الطبقات العليا؛ حيث ستُشير -على سبيل المثال- إلى عنوان IP في الطبقات العليا باستخدام الحقول في «ترويسة الإطار» (frame header). CSNA/CD أصبحنا نعلم أنَّ إيثرنت هو بروتوكولٌ في الطبقة الثانية، الذي يوفر عنونة MAC بالإضافة إلى طريقة وصول (access method)؛ تُسمى طريقة الوصول بالاسم CSNA/CD (اختصار للعبارة carrier sense multiple access collision detection) وهي آلية تسمح بإرسال الإشارات في نفس الوقت دون إعطاء أولوية لأي إشارة، حيث يملك الجميع وصولًا متساويًا إلى «قناة» (channel)، وهذه هو قسم الوصول المتعدد في هذا البروتوكول. هنالك احتمالٌ كبيرٌ أن جهازين سيحاولان نقل البيانات في نفس الوقت، مما يؤدي إلى حدوث تصادم (collision)؛ لكن في تقنية إيثرنت، يمكن لجميع الأجهزة «تحسس» (sense) القناة وتحديد فيما إذا كانت هنالك إشارات من مُرسِلين آخرين، وهذا هو قسم «تحسس الناقل» (carrier sense) من البروتوكول؛ ويُسمَح للأجهزة بتحسس القناة وكشف التصادمات، وهذا هو قسم «كشف التصادمات» (collision detection) من البروتوكول. حسنًا، كيف يعمل إذًا؟ عندما يحدث تصادم بين الإطارات، فإنها «ترتدد» وتُجدّوَل إعادة إرسالها بناءً على مؤقِّت عشوائي، الذي سيكون مختلفًا في كل جهاز؛ وهذا يزيد من احتمال محاولة الأجهزة إعادة الإرسال في نفس الوقت مرةً أخرى... لكن يجب أن تكون لدينا بيئةٌ بأداءٍ جيد على المدى الطويل. قد تتجه بعض الأمور نحو الأسوأ، ويحصل ذلك عادةً إن كان تصميم الشبكة سيئًا، فعلى سبيل المثال، يكون مجالُ التصادمات كبيرًا مع عددٍ كبيرٍ من الأجهزة التي تتشارك نفس القناة، مما يزيد من احتمالية إرسال الأجهزة في نفس الوقت، مما يزيد من التصادمات، الذي بدوره يقلل من أداء الشبكة؛ وهنالك مشاكلٌ أخرى متعلقةٌ بأعطال العتاد، التي تسبب إرسال إطارات تحتوي على أخطاء أو إطارات غير مفهومة إلى الشبكة، مما يسبب تضاربًا مع بقية الأجهزة ويسبب أخطاءً في الشبكة. بنية إطارات إيثرنت وظيفةٌ مهمةٌ أخرى من وظائف أي بروتوكول في الطبقة الثانية هي «تأطير» البيانات (framing). الإطار هو الحاوية التي ستحمل البتات التي يجب نقلها عبر الشبكة، ويتضمّن حقولًا ستجعل تلك البتات ذاتُ معنى؛ يبيّن الرسم التوضيحي الآتي صيغة الإطار في «Ethernet 2» وفي معيار «IEEE 802.3»؛ حيث يحتوي كلاهما سلسلة بتات تسمى «permeable» التي تستعمل لمزامنة جهازين متصلين؛ وسلسلة التحقق من الإطار، للتأكد من سلامة البيانات التي فيه؛ وعناوين الوجهة والمصدر، التي هي عناوين MAC. الفرق بينهما واضح، يبدأ إطار 802.3 بمُحدِّد الإطار (frame delimiter) الذي يُعلِم الجهاز المُستقبِل أنَّه سيبدأ نقل الإطار الفعلي؛ وانظر أيضًا إلى حقل «النوع» (type) في Ethernet 2، الذي يُشير إلى بروتوكولات الطبقة العليا، وستُستخدم نفس البتات كحقل الطول (length field) في 802.3 الذي يُمثِّل طول حقل البيانات. يحتوي حقل البيانات على ترويسة802.2 الذي هو تطبيقٌ لطبقة التحكم بالوصل المنطقي؛ يمكنك العثور على معلومات بروتوكول الطبقة العليا في هذه الترويسة. التواصل ضمن الشبكة المحلية مفهوم آخر مهم في اتصالات إيثرنت و LAN هو مجال الإرسال (scope of transmission). تكون هنالك وجهةٌ واحدةٌ في نقل unicast، أي سيكون هنالك عنوان وجهة يُمثِّل جهازًا واحدًا. هذه هي طريقة آلية العمل في الشبكات المحلية، ويكون عنوان MAC هو المُعرِّف الفريد الذي يُستخدَم لإرسال إطارات unicast. ستحتاج بعض البروتوكولات والتطبيقات إلى إرسال الإطارات إلى جميع الأجهزة في الشبكة المحليّة، وهذا هو سبب استخدام «الإذاعة» (broadcast)، حيث تمثِّل الإذاعة وجهةً تُعالَج من جميع الأجهزة؛ وهذه ملائم لبعض البروتوكولات مثل ARP، الذي يطلب ترجمة عنوان IP إلى عنوان MAC دون معرفة مالك عنوان IP، حيث يُذاع الطلب إلى كل الأجهزة، وسيُجيب الجهاز المطلوب. أخيرًا وليس آخرًا، multicast هو حلٌ وسطٌ بين unicast و broadcast؛ حيث لا يمثِّل وجهةً واحدةً ولا جميع الأجهزة؛ بل يُمثِّل مجموعةً من الأجهزة، ثم ستُعدّ رزمةٌ لإرسالها إلى تلك المجموعة؛ ويمكن للأجهزة أن تنضم أو تخرج من المجموعات ديناميكيًا؛ مثالٌ عن تطبيقات تستخدم multicast: المؤتمرات المرئية، والتعلم الإلكتروني، وأشكالٌ أخرى من الوسائط المتعدِّدة. مكونات عناوين MAC وظيفةٌ أخرى من وظائف أي بروتوكول في الطبقة الثانية هي «العنونة» (addressing)، وليس بروتوكول إيثرنت استثناءً، وعنوان «media access control» هو مُعرِّفٌ فريدٌ يُستخدَم من كل الأجهزة على شبكة إيثرنت. ترتبط عناوين MAC عادةً بمصنِّع العتاد؛ في الحقيقة، هنالك مجالات مُعرَّفة من قِبل IEEE لمختلف المصنِّعين لضمان أنَّ العناوين فريدةٌ؛ يَسمح بعض المصنِّعين بتعديل عناوين MAC لأغراضٍ معيّنة. يتألف عنوان MAC من مكوِّنَين رئيسيَين هما: 24-بت مُعرِّف تنظيمي فريد (Organizational Unique Identifier أو اختصارًا OUI)، الذي يُحدِّد مُصنِّع العتاد (الذي يمكن أن يكون بطاقةً شبكيّةً، أو منافذ موجِّه [router ports] ...إلخ.) وضمن تلك 24-بت هنالك 2 بت لهما معنىً خاص، «بت الإذاعة» (broadcast bit) الذي يُستخدَم عادةً للإشارة أنَّ هذا العنوان هو عنوان broadcast أو multicast؛ وبت «عنوانٌ محليُّ الإدارةِ» (locally administered address) الذي يُستعمَل عادةً عندما يُغيَّر عنوان MAC. القسم الثاني من عنوان MAC بطول 24-بت، وهو مُسنَد من الشركة المصنِّعة، ويجب أن يكون فريدًا. ترجمة -وبتصرّف- للمقال Understanding Ethernet.
  20. cisco icnd1

    الوظيفة الرئيسية لطبقة النقل هي إخفاء تعقيدات الشبكة عن الطبقات العليا (التطبيق والعرض والجلسة)، مُتيحةً لمُطورِيّ التطبيقات تطويرَ البرمجيات دون التفكير في طريقة التعامل مع الشبكة. مما يوفِّر استقلاليّةً في نشر (deployment) وتطوير المكونات (components) في تجميعة بروتوكول IP. يتوفَّر بروتوكولان في طبقة النقل هما: UDP ‏(User Datagram Protocol)، و TCP ‏(Transmission Control Protocol). يقوم كلاهما بالإرسال المتعدد للجلسة (session multiplexing)، الذي هو أحد الوظائف الرئيسية لطبقة النقل، الذي يعني أنه يتمّكن جهازٌ ما يستعمل عدِّة جلسات أو عدِّة اتصالات من استخدام عنوان IP ذاته للتواصل مع الشبكة. مثال: تتمكن الخواديم التي توفِّر خدمات الويب وFTP من استخدام نفس عنوان IP. ميزةٌ أخرى هي«التقطيع» (segmentation) التي تُحضِّر وحدات المعلومات (units of information) من طبقة التطبيقات وتُقسِّمها إلى قطع لتغليفها في رزم لإرسالها عبر الشبكة. وقد تتأكد طبقة النقل -اختياريًّا- أن تلك الرزم قد وصلت إلى الوجهة عبر آليات التحكم في الجريان (flow control). ما سبق اختيارٌ لأنَّ بروتوكول TCP هو من يوفِّر تلك الخدمة فقط، لأنه بروتوكولٌ يعتمد على الاتصالات (connection-oriented)؛ على عكس UDP الذي هو بروتوكول عديم الاتصال (connectionless)، ويُستخدَم عندما تكون السرعةُ عاملًا مهمًّا، حيث يؤدي التحكم في الجريان والوثوقية (reliability) إلى إبطاء سرعة الاتصال. فإذا أردنا أن نقارن بروتوكولَي طبقة النقل، فسيكون بروتوكول TCP معتمدًا على الاتصالات، وهو بروتوكولٌ ذو وثوقيةٍ عالية، ويوفِّر آلياتٍ مثل ترقيم الرزم وإعادة تجميعها في الوجهة بنفس الترتيب، وآليةٌ كاملةٌ لتحديد التوقيت لضمان تسليم الرزم... أما UDP فهو بروتوكولٌ عديم الاتصال، ولا يوفِّر أي ترتيبٍ للرزم ولا أي نوعٍ من ضمانة توصيلها. هذا يشبه إلى حدٍ كبير المكالمات الهاتفيّة، حيث عليك أن تطلب الرقم وتُنشِئ اتصالًا قبل أن تبدأ بالتكلّم، وهذا مثل TCP؛ أو توصيل البريد العادي، حيث لا تضمن أن رسائلك ستصل إلى وجهتها، فإنِّك تُرسِل الرزم الشبكيّة آملًا أن تصل إلى هناك، وهذا مثل UDP. لكن قد تتعامل الطبقات العليا مع بروتوكول UDP بطريقةٍ مختلفة، وتزيد من وثوقية توصيله للرزم. أمثلة على استخدام كلي البروتوكولَين: تَستخدم خدمات البريد الإلكتروني ونقل الملفات والتنزيل بروتوكول TCP ذا الوثوقيّة العالية؛ أما اتصالات الصوت والفيديو فستستفيد من التخلص من عبء التحقق من الوصول والوثوقية مما يؤدي إلى تسريع تسليم الرزم، حيث تستطيع تلك التطبيقات التعامل مع فقدان بعض الرزم الشبكيّة. الوثوقية أفضل جهد (Best-Effort) البروتوكول TCP UDP نوع الاتصال ذو اتصال عديم الاتصال ترتيب الرزم نعم لا الاستخدامات البريد الإلكتروني مشاركة الملفات تنزيل الملفات تدفق الصوت تدفق الفيديو الخدمات التي تعمل بالوقت الحقيقي خصائص بروتوكول UDP هو بروتوكولٌ عديم الاتصال، حيث يوفِّر تحققًا محدودًا من الأخطاء، فلا توجد ميزات لاستعادة البيانات عند فقدان بعض الرزم، ولهذا لا يوفِّر ميزة إعادة إرسال الرزم، إذ تستفيد التطبيقات التي تستخدم UDP من قلة الإجراءات المُتّبَعة عند استخدام هذا البروتوكول، لأنه لا توجد آليات للتحقق من وثوقية وصول البيانات؛ نقصد بالتحقق المحدود من الأخطاء أنَّ هنالك بعض التحقق من الأخطاء على شكل مجموعات اختبارية (checksums) للتحقق من سلامة البيانات الموجودة في هذه الرزم؛ وهنالك أيضًا ترويسة صغيرة تتضمن المنافذ في المصدر والوجهة، فلو لم تكن هنالك خدمةٌ تعمل على جهاز الوجهة، فسيُعيد بروتوكول UDP رسالة خطأ تقول أنَّ الخدمة غير متوفرة. تحتوي ترويسة UDP على المنافذ في المصدر والوجهة، التي تُحدِّد التطبيقات التي تتصل عبر UDP، ويوجد أيضًا طول الحمولة (payload) وطول الترويسة والمجموع الاختباري للتحقق من سلامة البيانات. خصائص بروتوكول TCP يُوفِّرُ بروتوكولٌ يعتمد على الاتصالات، مثل TCP، وثوقيةً واكتشافًا للأخطاء وتصحيحًا لها، ويَضمن أيضًا توصيل الرزم؛ ولهذه الأسباب، سيكون أكثر تعقيدًا من UDP؛ إذ يُوفِّر تحققًا من الأخطاء على شكل مجموعات اختباريّة (checksums) بالإضافة إلى ترقيم كل رزمة لكي تتأكد الوجهة من الترتيب وتبحث عن الأجزاء أو الرزم الناقصة؛ يشبه اتصال TCP محادثةً تتم عبر الجهاز اللاسلكي (walkie-talkie)؛ حيث تتضمن إشعاراتٍ (acknowledgments) من كل طرف أنَّ الطرفَ الآخر قد استلم البيانات، وسيتم إكمال إرسال البيانات بعد استلام تأكيد بأنَّ الرزم السابقة قد وصلت. ولدى هذا البروتوكول آليةٌ لكي يعيد إرسال البيانات؛ فإن فُقِدَت رزمةٌ ما أثناء النقل، فيمكن إعادة إرسالها بمعرفة رقمها التسلسلي. لن تؤدي العملية السابقة إلى المزيد من الإجراءات والبروتوكولات -مثل حساب الأرقام التسلسلية وآلية «sliding windows»- فحسب، بل وستؤدي أيضًا إلى وجود المزيد من المعلومات التي يجب تضمينها في الترويسة؛ ففي بروتوكول TCP، لن نشاهد منافذ المصدر والوجهة في الترويسة فقط، وإنما سنشاهد أيضًا الأرقام التسلسلية، وأرقام إشعارات الاستلام. يُحدَّد حجم النافذة (window size) لتسهيل عملية تأكيد وصول عدِّة رزم في مرة واحدة؛ وسيضمن المجموع الاختباري سلامة البيانات المنقولة. وهنالك أنماطٌ مختلفةٌ من التوصيل عبر استعمال «مؤشِّر الرزم المُستعجَلة» (urgent pointer)، والخيارات، والرايات (flags). لمحة عن طبقة التطبيقات في TCP/IP مهمة طبقة النقل هي إخفاء تعقيد الشبكة عن التطبيقات في الطبقة العليا؛ يمكن بناء تلك التطبيقات باستخدام TCP أو UDP اعتمادًا على حاجاتها، فيما إذا كانت تريد اتصالًا ذو وثوقيةٍ عالية، أو كانت تفضِّل سرعة النقل؛ مثالٌ عن التطبيقات هو تطبيقات FTP، و TFTP، وNFS لنقل الملفات؛ وSTMP، و POS3 للبريد الإلكتروني؛ ومختلف تطبيقات الوصول عن بُعد؛ و SNMP لإدارة الشبكة؛ وخدمة DNS لتحويل أسماء المضيفين إلى عناوين IP. أحد أهم المفاهيم الأساسية لأي نموذج متعدد الطبقات هو التفاعل بين الطبقات؛ والطبقتان 3 و 4 من نموذج OSI ليستا استثناءً؛ فمثلًا، لو استقبل جهازٌ معيّن رزمًا من الشبكة وعالجها عبر بروتوكول IP في الطبقة الثالثة، فسيحتاج إلى مزيدٍ من المعلومات لتحديد البروتوكول الملائم لمعالجة تلك الرزمة، هل هو TCP أم UDP؛ بكلامٍ آخر، ما هو بروتوكول طبقة النقل الذي يجب أن يتوَّلى أمر الرزمة من هنا؟ يَستخدم IP حقل «البروتوكول» لتحديد بروتوكول طبقة النقل المُستخدَم؛ فمثلًا، الرقم «6» في حقل البروتوكول يعني أن TCP هو بروتوكول طبقة النقل الذي يجب أن يُعالِج تلك الرزمة، بينما «17» يعني أنَّ UDP هو البروتوكول الذي عليه معالجة الرزمة. وبشكلٍ مشابه، سيحتاج بروتوكولَيّ TCP و UDP إلى المزيد من المعلومات ليعلما أيُّ تطبيقٍ في الطبقات العليا سيستلم الرزم الموجَّهة إليه؛ وذلك عبر أرقام المنافذ التي ستُذكَر في ترويسة طبقة النقل؛ على سبيل المثال، يُمثِّل المنفذ 21 خدمة FTP، و23 خدمة Telnet، بينما 80 يُمثِّل خدمة الويب على شكل بروتوكول HTTP؛ أما 53 فلخدمة DNS، و69 لخدمة TFTP، و 161 لخدمة SNMP؛ يجب أن تكون تلك الأرقام فريدةً، وهي مُسندةٌ من هيئة IANA؛ تكون أرقام المنافذ الشهيرة تحت 1023، لكن هنالك مجالاتٌ أخرى للمنافذ المُسجَّلة لكنّها تتبع للتطبيقات الاحتكاريّة؛ وحتى هنالك مجالاتٌ متوفرة للمنافذ التي تُحدَّد ديناميكيًا. إنشاء اتصال بروتوكول TCP مسؤولٌ عن إنشاء الاتصالات قبل إرسال الرزم؛ سيُستعمَل هذا الاتصال من كلي الطرفين لإنشاء جلسة معيّنة وإخفاء تعقيد الشبكة عنهما؛ بكلامٍ آخر، سيرى المُضيفان مُعرِّف الاتصال (connection identifier) وليس الشبكة المعقدة التي تقع «تحت» ذاك الاتصال؛ ومن واجبات بروتوكول TCP أيضًا إنشاء، وإدارة، وإنهاء الاتصالات بعد الانتهاء منها. عملية «إنشاء الاتصال ثلاثية الاتجاه» (three-way handshake) هي عملية لمزامنة (synchronizing) جهازَين ليعلما أنهما متصلان عبر TCP؛ تَستخدِم هذه العملية رزمًا خاصةً التي تستعمل حقول التحكم (control fields) وترويسة TCP؛ حقول التحكم تلك مُعرَّفةٌ بالكلمة المفتاحية CTL في المخطط البياني التالي. ويبدأ الأمر بأكمله بإرسال رزمةٍ لها رقمٌ تسلسليٌ معيّن؛ وبكل تأكيد، سيكون «بت» التحكم هو SYN؛ ستُرسَل الرزمة وتعالجها النهاية المُستقبِلة وتُرسِل ما يُعرَف بإشعار SYN، التي (أي رزمة ذاك الإشعار) تكون فيها راية SYN ‏(SYN flag) وراية الإشعار. وتُستخدَم أيضًا الأرقام التسلسلية لإشعار استلام السلسلة التالية من البتات؛ يُنشَأ الاتصال بشكل كامل عندما يُرسَل الإشعار النهائي من المستلم؛ بت التحكم المُستخدم في الإشعار النهائي هو راية الإشعار فقط. وهذا يُشبِه محادثة الهاتف حيث نبدأ المحادثة بقول «مرحبًا» ويُرَدُّ علينا بالجملة «أهلًا، أنا هنا» ثم سيقول المُرسِل «حسنًا، لقد أنشَأنا الاتصال، لنبدأ التحدث». التحكم في الجريان (Flow Control) تؤدي آلية التحكم في الجريان في طبقة النقل والبروتوكولات مثل TCP إلى وظيفتين مستقلتين لكن توجد علاقةٌ تربط بينهما؛ أولاهما هي إشعارات استلام الرزم؛ والإشعارات ما هي إلا رزمٌ خاصةٌ تمثِّل تأكيدًا أن البيانات قد وصلت إلى وجهتها؛ ولن يُكمِل المُرسِل إرسال بياناتٍ إضافيةٍ ما لم يحصل على إشعارٍ باستلام البيانات المُرسَلة سابقًا. الآلية الثانية هي «النوافذ» (windows)، التي تخدم هدف إرسال إشعار باستلام قطع من البيانات؛ بكلامٍ آخر، بدلًا من إرسال إشعار باستلام كل رزمة؛ فسنطلب من المُرسِل أن يُرسِل سلسلةً من الرزم دفعةً واحدة، بدلًا من إرسالها مُتفرِّقةً. وتُساهِم هذه الآلية بزيادة التحكم بكمية البيانات المُرسَلة، فعندما يُرسِل المُستقبِل حجم نافذة مساوٍ للقيمة 0، فإنه يقول للمُرسِل: «حافظتي ممتلئة، لا أستطيع معالجة أيّة بياناتٍ إضافيةً، أتمنى أن تنتظر حتى إشعارٍ آخر»، وعندما تصبح حافظة المستقبِل فارغةً ويصبح بمقدوره استلام المزيد من الرزم، فسيُستأنَف نقل البيانات عبر إرسال حجم نافذة مختلف؛ وفي هذه النقطة، سيُعيد المُرسِل تهيئة عملية النقل مجددًا. حجم النافذة ما هو إلا مقدار المعلومات التي لم يُرسَل إشعارٌ باستلامها التي يمكن أن تكون قيد الإرسال؛ فعندما يُرسِل المُرسِل قطعة (chunk) البيانات رقم 1 (وتُعرَّف تلك القطعة بعدد البايتات أو الكيلوبايتات التي ستُرسَل)، فسيعمله المُستقبِل بذلك عبر تحديد القطعة التالية التي يتوقع وصولها؛ بكلامٍ آخر، لن يقول المُستقبِل: «أنا أعلمك أنني استلمت القطعة رقم 1 من البيانات»، بل سيقول: «أرسِل لي قطعة البيانات رقم 2 الآن»؛ يكون حجم النافذة في المثال السابق هو «1»، أي أننا نُرسِل إشعارًا باستلام كل قطعة، وهذا سيصبح أمرًا معقّدًا ويسبب بطئًا في الشبكة؛ حيث يلزم المزيد من الإشعارات للتحكم في التدفق ولإكمال الإرسال. فمن المهم أن نفهم أنَّ ما نسميّه «قطعًا» (chunks) يكون على شكل «segments» في طبقة النقل، وتكون تلك القطعة بوحدة بايت أو كيلوبايت. لا يُسبِّب إشعارٌ واحدٌ لكل وحدة بيانات حِملًا ثقيلًا على الشبكة فحسب، بل يُبطِئ أيضًا من سرعة الاتصال؛ وهذا يشبه كثيرًا قول كلمة «حوِّل» (في مثالنا عن «اتصال الراديو» السابق) بعد كل كلمة يقولها المُرسِل: «أهلًا حوِّل»، «بِك حوِّل» ...إلخ. يتضمّن بروتوكول TCP آليةً للنوافذ، التي تسمح بزيادة عدد القطع المُرسَلة قبل إشعار استلامها؛ وبهذا، تستطيع أن تقول «أهلًا بِك» ثم تقول كلمة «حوِّل» في نهاية الجملة. يُمثِّل حجم النافذة عدد البايتات أو الكيلوبايتات التي يمكن أن تُرسَل دفعةً واحدة؛ ففي المخطط الآتي، ستُرسَل ثلاث قطع، ثم سيُرسِل المُستقبِل إشعارًا بالاستلام بقوله: «أرسل لي الرقم 4». وبهذا نكون قد أرسلنا إشعارًا باستلام أول ثلاث قطع دفعةً واحدة. يكون حجم النافذة في الحياة العملية بوحدة الكيلوبايت، أي ستكون طريقة زيادة حجم النافذة كالآتي: «كنت أُرسِل 64 كليوبايت، وأنا الآن أُرسِل 128 كيلوبايت، ويمكنك إرسال إشعار باستلام 128 كيلوبايت بدلًا من 64». لا يُفضَّل استخدام نافذةٌ ذات حجمٍ ثابت للمُستقبِل والمُرسِل لملائمة ازدحام الشبكة (network congestion) والتأقلم تبعًا له؛ يسمح لك حجم نافذة محجوزٌ ديناميكيًا (ويُعرَف أيضًا بالمصطلح «sliding window») بالتأقلم دون التسبب بازدحامٍ في الشبكة ويعمل أيضًا كآلية للتحكم بالجريان (flow control mechanism). تكتمل آلية التحكم عبر استخدام أرقام تسلسلية وأرقام إشعارات الاستلام؛ لاحظ أنه في هذا الرسم التوضيحي تكون الأرقام التسلسلية أكثر واقعيةً حيث تَظهِر كميّة البيانات بوحدة البايت التي ستُرسَل في كل قطعة؛ أي أنَّ الرقم التسلسلي «10» يعني أنَّه قد أُرسِل 10 بايتات من البيانات؛ ورقم إشعار الاستلام 11 يعني أن أول 10 بايتات قد اُستُلِمَت ويتوقع المُستقبِل إرسال القطعة التي تلي تلك البايتات؛ التبادل التالي ذو الرقم 260 يعني أن 250 بايتًا من البيانات قد أُرسِل، أي أن الرقم التسلسلي يمثِّل إزاحةً لها علاقة بالقطعة التي أُرسِلت في البداية. لاحظ أن المُرسِل والمُستقبِل يعلمان عن هذه المحادثة ويمكن أن يعتبرانها اتصالًا واحدًا بناءً على المنافذ المُستخدَمة في المصدر والوجهة. يُولَّد منفذ المصدر عشوائيًا وقت الاتصال، لكن يجب معرفة منفذ الوجهة مسبقًا، الذي يُعرِّف تطبيقًا معيّنًا، وهو Telnet في هذا الرسم التوضيحي: ترجمة -وبتصرّف- للمقال Understanding The TCP/IP Transport Layer.
  21. cisco icnd1

    لفهم دور طبقة الإنترنت في تجميعة بروتوكول TCP/IP، فعلينا أن نفهم وظائف بروتوكول TCP/IP أولًا؛ باختصار، إن IP مسؤولٌ عن تمرير الرزم من المصدر إلى الوجهة في الشبكة؛ تكون الرزم هي وحدة البيانات (data unit) لطبقة الإنترنت في TCP/IP؛ وهي وحدات تتضمِّن البيانات التي ستُرسَل بالإضافة إلى معلوماتٍ كافية لكل رزمة لكي تُعامَل بشكلٍ مستقل وتُوجَّه في الشبكة. تتضمن آلية التوجيه اختيار أفضل طريق للوصول من المصدر إلى الوجهة؛ ويجب الآن تعريف الوجهات والمصدر كأجهزة ضمن الشبكة، ولهذا فإن الوظيفة الثانية لبروتوكول الإنترنت هي توفير عناوين لتلك الأجهزة، وتلك العناوين يجب أن تكون هيكليّة، لأننا سنناقش إرسال البيانات من الجهاز 1 في الشبكة 1 إلى الجهاز 1 في الشبكة 2؛ وبالطبع ما سبق هو مجرد مثال عن آلية تعريف الأجهزة بشكلٍ هيكلي. الأمر الثالث هو أنَّ بروتوكول الإنترنت ذو طبيعة عديمة الاتصال (connectionless)؛ أي أنه لا يتطلب إنشاء اتصال، فمثالٌ عن إنشاء اتصال هو رفع سماعة الهاتف وطلب الرقم قبل أن نتمكن من التحدّث؛ أما الطريقة التي يعمل بها IP تُشابِه إرسال الأحرف عبر البريد العادي، حيث ستُرسَل كلماتنا ونتمنى أنها ستصل إلى وجهتها، أي أنَّ البروتوكول نفسه لن يوفِّر آلياتٍ لاسترداد البيانات أو لضمان وصولها؛ فمن واجبات بقية الطبقات توفيرُ الوثوقية (reliability)؛ وهذا يعتمد على نوعية التطبيق؛ فمثلًا، تتطلب عملية نقل ملفٍ وثوقيةً وتأكيدًا أن البيانات ستصل إلى الوجهة كما أُرسِلَت، أما نقل الصوت في الوقت الحقيقي (real-time) فسيستفيد من السرعة أكثر من الوثوقية. إحدى وظائف IP كبروتوكول هي تعريف العناوين والتعرّف على الأجهزة ضمن هيكلية الشبكات. لنلقِ الآن نظرةً إلى بنية عناوين IP؛ إن عناوين IP هي مُعرِّفاتٌ بطول 32 بت التي تميّز كل جهاز على شبكة IP، أي أن على الجهاز أن يملك عنوان IP فريد إذا أراد التواصل مع بقية الأجهزة على الشبكة. أي لو أردنا الاتصال من الجهاز 1 في الشبكة 1 إلى الجهاز 2 في الشبكة 2، فيجب أن تملك تلك الأجهزة عناوين IP؛ وفي الواقع، تتألف عناوين IP من مكوِّنَين هما مُعرِّف المضيف (host ID) الذي يُسنَد للأجهزة المتصلة بالشبكة، ومُعرِّف الشبكة (network identifier) الذي يُحدِّد القسم أو الشبكة التي تنتمي تلك الأجهزة إليها. وهذا شبيهٌ بطريقة تنظيم الشوارع والمباني هيكليًّا، حيث لديك أرقامٌ للمنازل والمباني، لكنها تنتمي إلى نفس الشارع. ترويسة IP يجب أن تحتوي الرزم على مصدرها ووجهتها عند محاولة إرسالها من جهازٍ إلى آخر، وهذه هي كيفية توجيه الرزم في شبكةٍ من الأجهزة؛ حيث تنظر تلك الأجهزة إلى عنوان الوجهة وتحسب أفضل طريق للوصول إلى هناك. تُضاف هذه البيانات على شكل ترويسة في وحدة نقل البيانات (data unit) لبروتوكول طبقة الإنترنت؛ ولأن البروتوكول المستخدم هنا هو بروتوكول IP؛ فإن وحدة نقل البيانات المستعملة هي الرزم (packets)، ولأن الهيكلية مُضمَّنة في العناوين، فتتمكن الأجهزة مثل الموجَّهات من فهم تلك الهيكلية وتوجيه الرزم توجيهًا صحيحًا. وذلك مثل مبدِّلات الهاتف الأرضي (telephone switch)، على سبيل المثال، ستتمكّن من تحديد رمز المنطقة بالنظر إلى أول ثلاثة أرقام من رقم الهاتف؛ وبطريقةٍ مشابهة، ستنظر الموجَّهات إلى الشبكة الهدف وستتمكن من توجيه الرزم الشبكية توجيهًا صحيحًا إلى تلك الوجهة حتى دون الحاجة إلى قراءة عنوان الوجهة بأكمله. تحتوي بعض مكونات ترويسة IP أيضًا على نوع الخدمة لتحديد «جودة الخدمة» (QoS) وزمن بقاء الرزمة «على قيد الحياة» لكي لا تبقى تَتَنَقَّل في الشبكة إلى ما لا نهاية... يمثِّل هذا الرقم «تاريخًا للصلاحية» لتلك الرزمة. صيغة عناوين IP أما ما يتعلق ببنية عناوين IP؛ فيتألّف العنوان من سلسلةٍ من 32 بتًا تتكون من الرقمين 0 و1؛ ويُشكِّل جزءٌ من هذا العنوان «مُعرِّف المضيف» (host ID)، وجزءٌ آخرٌ سيُشكِّل «مُعرِّف الشبكة» (network ID). وتكون الصيغة الثنائية (binary) مثاليةً للموجهات، لكنها ليست ملائمةً للبشر، لذلك سنحتاج إلى شيءٍ أبسط وقابل للتذكر بسهولة، ولهذا السبب ستُقسَّم السلسلة ذات 32 بتًا إلى أربع ثمانيّات (octet) أو بايتات؛ حيث يتكوّن كل بايت من 8 بت، ثم ستحوَّل الصيغة الثنائية إلى أرقامٍ عشرية، وستُشرَح عملية التحويل تلك لاحقًا في هذه الدورة التدريبية وسنُفصِّلها فيما بعد. لذا، ستُتحوَّل السلسلة ذات 32 بتًا إلى 4 بايت، التي ستصبح بدورها أرقامًا عشرية؛ ثم ستُفصَل تلك الأرقامُ بنقطٍ، مما سيُنتِج الصيغة العشرية المفصولة بنقط (dotted decimal notation) التي نسميها «عناوين IP». السؤال الآن هو: كيف نُميّز جزءَ الشبكة في العنوان من جزء المضيف؟ في بدايات استخدام الإنترنت، خرجت هيئة IANA (اختصار للعبارة Internet Assigned Numbers Authority) بمخططٍ لتقسيم العناوين إلى فئات، حيث تُحدِّد الفئة عددَ البتات المخصصة لمعرِّف الشبكة وعدد البتات المخصصة للمضيفين؛ تُعرَّف فئات العناوين وتُميَّز بسلسلة بتات تبدأ من أول ثمانيّة، ولهذا تستطيع تحديد فئة الشبكة بالنظر إلى أول ثمانيّة؛ فجميع العناوين التي تبدأ بصفر ستكون من فئة العناوين A ‏(Class A). حيث تحجز فئة العناوين A أول ثمانيّة لتمثِّل معرِّف الشبكة، وتُترَك الثمانيّة الثانية والثالثة والرابعة لتمثِّل معرِّف المضيف؛ وهذا منطقيٌ في بدايات الإنترنت، لأنه كان لديهم عددٌ قليلٌ جدًا من الشبكات، وفي كلِّ شبكةٍ عددٌ كبيرٌ من المضيفين؛ وتلك الشبكات تكون عادةً تابعةً للجامعات أو للحكومات أو للمواقع العسكرية. تُعرَف عناوين الفئة B بوجود واحد وصفر في أول بتَّين (first 2 bits) من أول ثمانيّة، ويُحجَز أول بايتين للشبكة وآخر بايتين للمضيفين؛ وبشكلٍ مشابه، تبدأ الفئة C بالسلسلة 110 ويُحجَز أول ثلاث ثمانيّات للشبكة، وثمانيّة واحد فقط للمضيفين. في النهاية، بناء عنوان IP يعني إسناد معرِّفات فريدة للأجهزة ضمن الشبكة، ثم إعطاؤها نفس معرِّف الشبكة كي تصبح جزءًا من شبكةٍ واحد، وهذا يشبه كثيرًا أرقام المنازل المختلفة في شارعٍ ما، لكن اسم الشارع هو نفسه. مجالات عناوين IP هنالك نتيجتان حصلنا عليهما من استراتيجية التنظيم وفق فئات: أولاها أنَّه يصعب علينا نحن البشر التعرّف على سلسلة البتات في أول ثمانيّة، لذلك حوّلناها إلى أرقامٍ عشريةٍ لتعطينا مجالًا من الأرقام سيُسهِّل علينا التعرف على كل فئةٍ من الفئات. لذا، لو كانت أول ثمانيّة تقع بين 1 إلى 126، فإننا نتحدَّث عن الفئة A ‏(Class A)، وإذا نظرنا إلى أوّل ثمانيّة ووجدناها تقع بين 128 و 191، فإننا نتحدث عن الفئة B؛ أما لو كان المجال بين 192 و 223، فإن الفئة هي C. لاحظ أن بعض الأرقام ناقصة مثل 127، الذي هو رقمٌ مجوزٌ لا يمكن إسناده للشبكات، ويُستخدَم في اختبار الاتصال إلى المضيف المحلّي عبر بطاقة loopback. النتيجة الثانية هي أننا ما زلنا نتعامل مع عددٍ محدودٍ من البتات، أي كلما أسندنا المزيد من الثمانيّات إلى مُعرِّف الشبكة، كان عدد البتات المتبقية لاستخدامها للمضيفين أقل، والعكس صحيح. لو حجزت الفئة A أول بايت للشبكة وثلاثة بايتات للمضيفين، فسيكون عدد المضيفين كبيرًا لكن عدد الشبكات قليل. تُوفِّر الفئة C مكانًا للمضيفين بعدد 254 كحدٍ أقصى؛ قد تُفاجَئ من ذلك ﻷن الفئة C تحجز ثمانيّة تحتوي 8 بتات للمضيفين، لكن 2 للقوة 8 (استنادًا إلى العمليات على الأعداد الثنائية) يعطي 256؛ لذا قد تظن أنك قادرٌ على الحصول على 256 عنوانًا صالحًا للاستخدام كعناوين للمضيفين في الشبكات ذات الفئة C، لكن هنالك بعض العناوين المحجوزة التي لا تستطيع إسنادها للأجهزة. فئة عناوين IP قيمة أول ثمانيّة بالنظام العشري قيمة أول ثمانيّة بالنظام الثنائي الحد الأقصى لعدد للمضيفين الفئة A ‎1 - 126 ‎00000001 إلى 01111110 16‎ 777 214 الفئة B ‎128 – 191 ‎10000000 إلى 10111111 ‎65 534 الفئة C ‎192 - 223 ‎11000000 إلى ‎11011111 254 تُمثِّل جميع الأصفار في قسم المضيف من عنوان IP الشبكةَ نفسها؛ على سبيل المثال، إذا كان لدي العنوان 10.0.0.0، فلا يمكن إسناد هذا العنوان إلى جهازٍ على الشبكة، حيث يُمثِّل الشبكة«10» نفسها؛ وبشكلٍ مشابهٍ، فإن الرقم 1 في قسم المضيف من العنوان هو عنوانٌ محجوزٌ أيضًا، حيث يمثِّل عنوان الإذاعة (broadcast) في تلك الشبكة. تُستخدم الإذاعة لإرسال معلومات إلى كل الأجهزة في الشبكة. ويمثِّل الرقم 1 في الثمانيّات عند تحويلها إلى النظام العشري الرقم 255؛ أي أنه على سبيل المثال، يمثِّل العنوانُ 200.1.1.255 عنوانَ الإذاعة في الشبكة «200.1.1». يُعتَبر هذا النوع من الإذاعة «إذاعةٌ موجَّهة» (directed broadcast) في تلك الشبكة؛ لكن أكبر عناوين الإذاعة هو عندما يملأ الرقم 1 جميع البتات؛ وهذا ما يُسمى «إذاعة محليّة»، ولا يمكن إعادة توجيه الإذاعات المحلية. عناوين IP العامة الإنترنت هي شبكة من الشبكات، وهي شبكة عامة شاملة تصل الأجهزة عالميًا ببعضها. وباتباع قواعد IP الأساسية، يجب أن تملك تلك الأجهزة عناوين IP فريدة عالميًا؛ قد يُسبِّب تكرار العناوين عدم استقرار الإنترنت؛ لأنه قد تصل البيانات إلى الوجهة الخطأ عندما يكون هنالك عناوين مكررة؛ أو قد يُسبِّب تكرار عنوان IP المصدر إلى حدوث اضطرابات في الوجهة. أنشَأت هيئة IANA مجالاتٍ لعناوين IP العامّة لكل فئة، وبهذا سنضمن عدم حدوث تكرار، وأنَّ كلَّ شيءٍ تحت السيطرة من هيئة مركزية لإسناد عناوين IP. فإذا أردت الحصول على عنوان IP عام على شبكة الإنترنت، فعليك التواصل مع IANA والتقدّم بطلبٍ رسمي؛ وحاليًا، يمكنك حجز العناوين عبر الهيئة المركزية وعبر هيئات موزَّعة في مناطق جغرافية مختلفة؛ فهيئة APNIC توزِّع عناوين IP لآسيا، و ARIN للأمريكيتَين، و RIPE لأوروبا. عناوين IP الخاصة بسبب وجود عدد هائل من الأجهزة في الشبكة العامة، فأصبح جليًّا أن 32 بتًا في عناوين IPv4 لن تكون كافيةً. IPv4 هو النسخة الحالية من IP والمتوفرة تجاريًا والتي تُستخدَم في الإنترنت؛ بدأت النسخة السادسة IPv6 بالانتشار في الآونة الأخيرة، وستُصبِح قريبًا النسخة المعيارية في الشبكات؛ ولكن ظهرت إلى ذاك الحين حلولٌ بديلةٌ للسماح للمزيد من الأجهزة بالحصول على عناوين IP دون الحاجة إلى أن تكون عامّة (public)؛ يُمكن أن تُستخدَم مجالات العناوين الخاصة المذكورة هنا للشبكات من فئات A وB و C؛ وستكون هذه العناوين مستقلّة عن الإنترنت ومن ثم يمكن تحويلها (translated) إلى عنوانٍ عام عندما تحتاج الرزم إلى الوصول إلى شبكة عامّة؛ ويمكن للأجهزة ذات العناوين الخاصة أن تصل إلى الشبكات العامة بالحصول على عنوان IP عام؛ وعملية التحويل هذه تُسمى NAT ‏(network address translation)؛ ليس لمجالات العناوين الخاصة أي معنى في شبكة الإنترنت وليست قابلة للتوجيه في تلك الشبكة، وهذا يعني أن رزم IP المرتبطة بهذه العناوين كوجهة أو مصدر سيتم تجاهلها في موجهات الإنترنت؛ وقد عُرِّفَت هذه العناوين الخاصة في RFC 1918. الفئة مجال العناوين الخاص A من 10.0.0.0 إلى 10.255.255.255 B من 172.16.0.0 إلى 172.31.255.255 C من 192.168.0.0 إلى 192.168.255.255 DHCP بعد أن تعلمت تصميم عناوين IP، يمكنك الآن حجز وإسناد وضبط عناوين IP على الأجهزة، ربما تتبع القواعد الأساسية، لنقل على سبيل المثال، سيكون لجميع الأجهزة في الشبكة 1 نفس معرِّف الشبكة، لكن مُعرِّفات المضيفين ستكون فريدةً؛ أصبحت عملية ضبط عناوين IP على جميع الأجهزة أمرًا مرهقًا وصعب الإدارة، وذلك اعتمادًا على عدد الأجهزة المتصلة بالشبكة؛ وهذه هو السبب الرئيسي وراء بروتوكولات مثل DHCP (بروتوكول ضبط المضيف الديناميكي [Dynamic Host Configuration Protocol])؛ يُستخدَم هذا البروتوكول لإسناد عناوين IP تلقائيًا دون تدخل بشري؛ إذ يَستخدِم خادمًا مركزيًا ليدير مجالاتٍ من عناوين IP لأجهزةٍ مختلفة؛ تؤجَّر (lease) عناوين IP إلى الأجهزة ويكون لها تاريخ صلاحية محدد يجب على الجهاز تجديده إن أراد الاحتفاظ بعنوان IP. تبدأ هذه الأجهزة اتصالها بالشبكة دون عنوان IP، ثم تطلب واحدًا من الخادوم؛ ويتم ذلك بسلسلةٍ من الرسائل المتبادلة بين العملاء والخواديم لحجز وإسناد عنوان IP. DNS بروتوكول آخر هو بروتوكول DNS ‏(Domain Name System)؛ هذا تطبيقٌ مُحدَّدٌ في تجميعة TCP/IP؛ وهو موجود لأنه يساعدنا في تذكر عناوين الأجهزة بشكل أسهل؛ فعند الاتصال إلى جهازٍ معيّن، فإننا نتذكر اسم المضيف وليس علينا تذكر عنوان IP؛ فدور خدمة DNS هي تحويل أسماء المضيفين إلى عناوين IP؛ فعندما تكتب عنوان URL في متصفحك، مثل academy.hsoub.com، فإن جهازك سيبحث عن خادوم DNS في الشبكة، ويطلب منه تحويل الاسم إلى عنوان IP، ويستلم المعلومات، ثم يستخدم العنوان الذي حصل عليه للاتصال بالجهاز. ipconfig يمكننا استخدام الأمر ipconfig في واجهة سطر الأوامر في أنظمة ويندوز لكي نراقِب ونتأكد من الضبط الشبكي؛ حيث يستطيع استئجار عنوان IP مع قناع الشبكة الفرعية (subnet mask)، والبوابة الافتراضية (default gateway)، وخواديم DHCP، وخواديم DNS، ومعلوماتٍ حول مدة صلاحية عناوين IP. يمكن إظهار جميع الضبط بالكلمة المفتاحية ‎/all لأمر ipconfig؛ الكلمات المفتاحية الأخرى مثل ‎/release لإطلاق عنوان IP من خادم DHCP، و ‎/renew لتجديد مدة صلاحية عنوان IP، أو ‎/?‎ للحصول على مساعدة. ترجمة -وبتصرّف- للمقال Understanding the TCP/IP Internet Layer. Internal IP Addressing.
  22. قطعنا شوطًا طويلًا في تطوير الاتصالات الشبكيّة؛ ما بدأ كنموذج (model) احتكاري (proprietary) تُعرِّف فيه الشركاتُ تقنياتها والعتاد والبرمجيات التي تعمل فقط على منتجاتها، أصبح نموذجًا مفتوحًا للاتصال والدمج بين الأنظمة، بناءً على معاييرٍ تسمح لعدِّة مصنِّعين بالاستفادة من الشبكة، وبناء تطبيقاتٍ تعمل على بيئات شبكيّة من عدِّة مصنِّعين؛ وحتى الإدارة أصبحت مفتوحة، يمكنك التفكير في برامج الإدارة التي تجري عملية صيانة إدارية وتوفِّر وظائف لعناصر الشبكة التي تأتي من عدِّة شركات مُصنِّعة؛ سنحتاج في هذه الظروف إلى تقسيم عناصر ومكونات الشبكة إلى طبقات؛ وربما كانت أول طبقتين تفصلان التطبيقات عن بنية الشبكة؛ لكن الآن نجد طبقاتٍ متعدِّدة ضمن الشبكة لتحديد وظائف العناصر الشبكيّة. نموذج الشبكة الطبقي (OSI Model) أدت طريقة التفكير السابقة إلى إنشاء معايير قياسيّة مثل نموذج OSI، الذي هو اختصار للعبارة «open systems interconnection»؛ يُقسِّم هذا النموذج (الذي أنشَأته المنظمة العالمية للمعايير القياسية في عام 1994) مهمة التواصل الشبكي إلى عدِّة طبقات (layers)؛ وبينما كان الهدف الأوليّ للنموذج هو توفير مجموعة من المعايير للشركات كي تطوِّر تقنياتها الخاصة، والتفكير في شبكة مفتوحة تحقِّق قدرًا كبيرًا من التوافقية (compatibility)، فإن النتيجة النهائية وفَّرت عدِّة فوائد. يتم تخفيف التعقيد بتقسيم الوظائف المختلفة إلى طبقات مستقلة، وكل ما بقي فعله هو توفير واجهة موحّدة للتواصل بين الطبقات؛ وهذا ما تم إنجازه عبر نموذج OSI، سامحًا للمصنعين ببناء مكوناتٍ خاصةٍ بهم ثم استخدام واجهات معياريّة للتواصل مع بقيّة مكونات الشبكة. هذا النموذج مُقسمٌ إلى وحدات؛ مما يضمن التوافقية عند الالتزام بها؛ وهو أداةٌ رائعةٌ للتدريس وللتعلم عن الشبكات وعن مختلف مكوِّنات الشبكات وكيف تتفاعل مع بعضها بعضًا؛ من المهم أن نقول أن هذا النوع من النماذج يمثِّل «ماذا» يمكن فعله في الشبكة، لكن ليس «كيف» يتم ذلك؛ تتحكم الشركات التي تُصنِّع التقنيات المبنية على هذا المعيار بالطريقة التي تعمل بها أجهزتها، لكن المعايير تعرِّف ماذا يجب أن يُفعَل؛ وقد تَتَّبع الشركات هذا المعيار أو لا تَتَّبِعُه؛ لكن كلما أتبعت الشركاتُ المعاييرَ، فستزداد التوافقية بين مختلف مكونات الشبكة. نموذج OSI 7 التطبيق (Application) 6 العرض (Presentation) 5 الجلسة (Session) 4 النقل (Transport) 3 الشبكة (Network) 2 وصل البيانات (Data Link) 1 الفيزيائية (Physical) بعد أن تتصل الأجهزة داخليًّا في نفس طبقة وصل البيانات، فإن الخطوة التالية هي التعامل مع الشبكات العامة وطرق الاتصال مع شبكة الإنترنت؛ وهذه هي مهمة «طبقة الشبكة»: توجيه (route) رزم البيانات عبر الشبكات إلى عدِّة وجهات بعيدة (remote destinations). ومن بين مسؤوليات هذه الطبقة هو تعريف العناوين المنطقية (logical addressing) أو تعريف الأجهزة بهيكليّة من الشبكات، وتحدِّد أيضًا كيفية التعامل مع طرق متوازية لاختيار أفضل طريق لتوصيل البيانات. يقدِّم نموذج OSI سبع طبقات لتقسيم مهمة التواصل؛ يستخدم بعض الأشخاص طرقًا غريبة لفهم وتذكر تلك الطبقات؛ لديك طبقة فيزيائية للاتصال الشبكي، وجلسة النقل، والعرض، والتطبيق؛ تلك الطبقات مرقمةٌ أيضًا. والطبقة الأولى هي الطبقة الفيزيائية التي تتعلق بنقل البيانات والمرتبطة بالمواصفات الكهربائية والميكانيكية والإجرائية (procedural) لتفعيل (activating) الوصلة الفيزيائية والحفاظ عليها (maintaining) وتعطيلها (deactivating)؛ وربما تجد أنواعًا مختلفة من وسائط (media) النقل مثل تقنيات الألياف الضوئية (fiber)، والأكبال المحورية (coaxial)، وحتى عبر التقنيات اللاسلكية (wireless)؛ وحتى ستجد فيها الواصلات (connectors) والمكوِّنات المطلوبة لوصل الأجهزة إلى الوسائط الفيزيائية. الطبقة الثانية هي طبقة وصل البيانات، التي تعرِّف طرقًا للوصول إلى الوسائط، وقد خُطِّطَ لها لكي تكون آلية الوصول إلى الوسائط مستقلةً تمامًا عن الوسائط التي تستخدمها؛ بروتوكول إيثرنت (Ethernet) هو مثال على بروتوكول في طبقة وصل البيانات؛ حيث تستطيع استخدامه على أكبال الألياف الزجاجية أو الأكبال المحورية أو الأكبال المجدولة. تُعرِّف هذه الطبقة ما الذي يجب فعله عند محاولة عدِّة أجهزة الوصول إلى نفس الوسيط (media)، وهي مسؤولةٌ أيضًا عن تعريف تلك الأجهزة في هذه الطبقة أو هذه المرحلة. عنوان MAC في بيئات إيثرنت هو مثالٌ عن طريقة تعريف الأجهزة في شبكة إيثرنت؛ لأنَّ هذه الطبقة تتفاعل مع عمليات النقل بين الأجهزة في نفس الوسيط (media)، وبالتالي يجب أن توفِّر درجةً ما من إمكانية اكتشاف الأخطاء ومحاولة تصحيحها. أما الطبقة الرابعة ( طبقة النقل) فهي آخر طبقةٍ تتعامل مع النقل الفعلي للبيانات من مضيفٍ إلى آخر، حيث تتعامل الطبقات العليا (التي هي طبقة التطبيقات والعرض والجلسة) مع التطبيقات المُستخدَمة في الشبكة، أما طبقة النقل فتمثِّل حدًا فاصلًا بين تلك التطبيقات والشبكة نفسها؛ بكلماتٍ أخرى، إحدى مهامها هي إخفاء تعقيدات الشبكة من الطبقات العليا ومن التطبيقات، وفي هذا السّياق، سيتم التّعامل مع طرقٍ متعدّدة والتي تتعامل بدورها مع طبقة الشبكة وذلك بإنشاء الاتصالات والحفاظ عليها، من أجل ضمان وثوقيّة نقل البيانات؛ وأيضًا إعادة تجميع المحادثات التي يمكن أن تُرسَل على شكل عدّة رزم من البيانات عبر الشّبكة، وبشكل عام، فإنّ القرار بإعطاء الوثوقيّة أو عدمها متروكٌ للطبقات العليا (Upper layer).‎ الطبقات العليا التي هي الطبقة الخامسة والسادسة والسابعة، هي أقرب للمستخدمين والتطبيقات، أي بكلامٍ آخر، تتعامل طبقة «الجلسة» (session) مع إنشاء وإدارة وإنهاء الجلسات، لكن هذا مختلفٌ عن طريقة إنشاء وإدارة وإنهاء طبقة النقل (transport) للاتصالات؛ تتعلق هذه الجلسات بجلسات المستخدم، التي يمكن أن تكون مقسمةً إلى عدِّة اتصالاتٍ في طبقة النقل؛ فعلى سبيل المثال، ربما يتصل أكثر من مستخدم إلى خادم الويب، لذا ستكون مهمة طبقة الجلسة التمييز بين جلسات هؤلاء المستخدمين، وأن توفِّر لهم وصولًا إلى التطبيق؛ وفي نفس الوقت التعامل مع عدِّة اتصالات شبكيّة أنشأها كل مستخدم إلى خادم الويب. تتعامل طبقة العرض مع تنسيق المعلومات، ستجد شبهًا بينها وبين اللغات المحكية، حيث يمكن ترجمة المعلومات إلى الإنكليزية أو الإسبانية على سبيل المثال، أو يمكنك الحصول على صيغٍ (formats) مختلفةٍ بناءً على الفوائد الوظيفية (functional benefits) لكل صيغة؛ على سبيل المثال، البيانات المكتوبة والبيانات المحكية. تتعلق الصيغ أيضًا بطبيعة المعلومات، فمثلًا، يمكن أن تختلف صيغة الفيديو باستخدام مواصفات مختلفة، ويمكن تنسيق النصوص باستخدام مواصفات مختلفة أيضًا، مثل ASCI؛ وكذلك الأمر للصور، فيمكن تنسيقها على هيئة bitmaps، أو JPEG، أو غيرها من الصيغ. في النهاية، تكون طبقة التطبيقات هي أقرب الطبقات إلى المستخدم، حيث تُعرِّف تجربة المستخدم عبر الخدمات التي تقدِّمها، ووظيفة تلك الخدمات، وعبر أشياء مثل استيثاق المستخدم (user authentication)، والتفاعل مع الخدمات نفسها؛ بعض الأمثلة هي: البريد الإلكتروني، ونقل الملفات، ومحاكاة الطرفية (terminal emulation)، وحتى تطبيقات نقل الصوت أو الاتصال الهاتفي، وتستطيع تصنفيها إلى فئات مثل فئة التسلية، أو الأعمال، أو الإنتاجية ...إلخ. المعلومات التي تُنقَل عبر الشبكة يجب أن تكون على شكل «رزم» (packets)، الرزمة هي الوحدة الأساسية (basic unit) للمعلومات المعروفة للشبكات والأجهزة، وهي مثل الكلمات في اللغة الإنكليزية؛ وتسمى عملية «تحزيم» تلك المعلومات بالمصطلح «التغليف» (encapsulation)، تضيف هذه العملية معلومات التحكم اللازمة والبروتوكول الملائم إلى البيانات كي تُفهَم فهمًا سليمًا في الجهاز المُستقبِل. أثناء مرور البيانات رأسيًا (vertically) خلال طبقات OSI، فستضيف كل طبقة ترويسةً (header) تحتوي على المعلومات التي تتطلبها تلك الطبقة. حتى ولو كانت عملية تغليف الرزمة رأسيةً، لكن تُستخدَم معلومات الترويسة أفقيًا (horizontally)؛ لذا يمكن للمُستقبِل أن يقرأ ويُفسِّر كل ترويسة؛ أمثلة عن المعلومات المُغلَّفة هي: الصيغة (format) في طبقة العرض، وصيغة البيانات المُرسَلة (فيديو، أو نصوص ...إلخ.)، أو ربما يُضاف في طبقة الشبكة عنوان IP الفريد الذي يُعرِّف المُرسِل والمستقبل؛ تشبه هذه العمليةُ آليةَ إرسال الطرود والحروف عبر خدمة البريد العادي. في بيئة الأعمال، يمكن أن يكتب أحدهم رسالةً في ظرف الرسالة (envelope) معنونةً بالترويسة «إلى خالد في قسم المحاسبة»، وإذا كان قسم المحاسبة موجودٌ في مكانٍ مختلف، فسيضع أحد الأشخاص في الشركة المغلفَ الصغير في مغلفٍ أكبر ويرسله إلى العنوان الحقيقي لقسم المحاسبة عبر خدمة البريد. تُنشِئ عملية التغليف رزمةً فيها البيانات الأصلية والترويسات المُضافَة من كل طبقة، وفي الواقع تُضيف بعض الطبقات تذييلًا (trailer)، مثل سلسلة التحقق من الإطارات (frame check sequence) المُضافة من طبقة وصل البيانات. تبدأ عملية إزالة التغليف (decapsulation) في المُستقبِل من قِبل كل طبقة، التي تقرأ الترويسة الملائمة لها وتستخدم المعلومات الموجودة فيها لاتخاذ قرارات متناغمة؛ مثالٌ عن ذلك سيكون عن أرقام المنافذ في طبقة النقل؛ إذا كان يشغِّل المُستقبِل -على سبيل المثال- عدِّة تطبيقات مثل خدمات FTP والويب، فسيكون رقم المنفذ في طبقة النقل هو مُعرِّف فريد لكل تطبيق ويمكن أن يُستخدَم من برمجيات طبقة النقل لإرسال بقية الرزمة إلى التطبيق الملائم؛ أي أن العملية الأفقية هي فهم المُستقبِل للمُرسِل عبر إضافة معلومات التحكم إلى الترويسة، لكن عملية التغليف وإزالة التغليف هي عمليةٌ رأسية؛ وبهذا تكتمل عملية التواصل. أي أن عملية التغليف وإزالة التغليف تُعرِّف التفاعل الأفقي المنطقي والاتصال بين الطبقات، وفي الوقت نفسه تستثمر ميزة التفاعل الرأسي بين الطبقات؛ المعلومات المُضافة المطلوبة من أجل التفاعل الرأسي ستُضاف إلى الرزم. الرزم هي مصطلح عام يُستخدم عادةً لتعريف وحدات المعلومات (information units) التي تنتقل عبر الشبكة؛ لكن إذا نظرت بعمق إلى كل طبقة، فهنالك مُعرِّفات (identifiers) ومصطلحات تُستخدم لتعريف وحدات المعلومات التي تتعلق بطبقة معيّنة؛ تذكر أننا نتكلم عن اتصالات الند-للند (peer-to-peer)، ولطالما بقيت طبقتَي النقل في المُرسِل والمستقبل تتفاعلان مع بعضهما بعضًا، فلن تكون لديهم معلومات عن الطبقات الأخرى؛ فمثلًا، المصطلح المُستخدم في طبقة النقل هو «القطع» (segments)؛ وفي طبقة الشبكة، فإن مكونَيّ الشبكة سيتعاملان مع الرزم الفعلية، لذا فإن «الرزمة» هو مصطلحٌ تابع لطبقة الشبكة، لكنه مصطلحٌ عامٌ أيضًا؛ تَستخدم طبقة وصل البيانات المصطلح «إطارات» (frames)، وهذه هي الطريقة التي تتفاهم بها مكونات وصل البيانات بين الخادم والمُستقبِل. تَستخدم الطبقة الفيزيائية البتات (bits) كوحدة للمعلومات. المصطلح العام لتعريف وحدات المعلومات في كل طبقة هو PDU أو «وحدة بيانات البروتوكول» (Protocol Date Unit). تجميعة البروتوكول (protocol stack) هي دمجٌ للمكونات التي تتبع لنموذج طبقي (layered model)، البروتوكول هو طريقة تطبيق وظيفة صُمِّمَت طبقةٌ معينة لفعلها. صُمِّمت وطوِّرت تجميعة البروتوكول TCP/IP في نفس فترة تطوير نموذج OSI، لكن بوضع بروتوكول IP بعين الاعتبار؛ وحتى لو كان اسم التجميعة هو «TCP/IP» الذي يشير فقط إلى بروتوكولين يشكِّلان التجميعة، لكن يُطلق في بعض الأحيان على تلك التجميعة اسم «تجميعة بروتوكول IP»‏ (IP protocol stack) فقط؛ لكن توجد عدِّة بروتوكولات مشاركة في التجميعة، وتعرَف بالطبقات الأربع، ووظيفتها مشابهة لنموذج OSI، لكن TCP/IP أصبح المعيار القياسي للوصل بالإنترنت وللاتصالات عمومًا؛ طبقة «الوصول للشبكة» (network access) تتعامل مع الوصول الفيزيائي إلى الوسائط بالإضافة إلى طريقة الوصول إلى تلك الوسائط؛ أما طبقة الإنترنت فإنها تتعامل مع التوجيه واختيار الطريق، وعلى الرغم من أن طبقة النقل شبيهة بطبقة النقل في نموذج OSI في أنها توفِّر اتصالاتٍ شبكيّة ذات وثوقية للتطبيقات في الطبقات العليا؛ فإن طبقة التطبيقات في هذا النموذج تدمج الطبقات من 5 إلى 7 في نموذج OSI في طبقةٍ واحد. ترجمة -وبتصرّف- للمقال Understanding the Host-to-Host Communications Model.
  23. cisco icnd1

    عندما نتحدث عن الحماية، يجب علينا أن نعي حقيقة أننا لم نعد «نعيش» في بيئة شبكيّة مغلقة؛ وليست الحماية هي السبب، وإنما السبب هو التكلفة والمرونة، ورغبتنا وحاجتنا إلى التواصل مع بقيّة العالم. التقنيات في الشبكات المغلقة، مثل «Frame Relay» و «PSTN» التقليدية، مصممةٌ لغرضٍ معيّن، وليس من الضروري أن تحمل بيانات الوسائط المتعددة (multimedia) وتسمح بالتبادلات الشبكيّة الكثيرة التي نتطلب حدوثها في الوقت الراهن. وصُمِّمَت وبُنَيَت بوضع خصائص معيّنة بعين الاعتبار، ولم يكن ضروريًّا أن تُدمَج مع بقية التقنيات؛ وتكون الحماية أكثر قابليةً للتحكم في الشبكات المغلقة، ﻷننا لن نكون عرضةً للهجمات الخارجية لأننا واثقون أننا نعمل في بيئة شبكتنا الهادئة؛ وسيكون من السهل احتواء الحوادث الداخلية، لأنها ستبقى ضمن شبكتنا دون أن تُتاح لها إمكانية الاتصال مع العالم الخارجي. الشبكات المفتوحة ليس هذا هو الحال مع الشبكات العصرية، حيث تشكِّل الإنترنت أكبر مثال عن الشبكات العامة؛ ويوجد لدينا متطلبات للمحمولية (mobility) والمرونة؛ هذا عصر الأنظمة المدمجة وعالم المعايير المدمجة (integrated standards)؛ لكن ذلك يفتح الباب للمخاطر الأمنية؛ حيث سيُسبِّب استخدام شبكةٍ عامةٍ يستعملها أي شخص بعض المخاوف والقلق على سريّة المعلومات والخصوصية. فكلما عرضنا خدماتنا إلى بقية العالم، فسنجد عقولًا تفكِّر تفكيرًا خبيثًا تحاول الوصول إلى تلك الخدمات والعمل على مفاجأتنا بطرقٍ جديدةٍ لاستغلال مواردنا. فئات الهجمات لا نتحدث عن «مستخدمي السكربتات الجاهلين» (script kiddies) الذين يملكون وقتًا فارغًا طويلًا عندما نتحدث عن المهاجمين؛ وإنما نتحدث عن المنافسين كمهاجمين محتملين، والمجرمين، والجريمة المنظّمة، والإرهابيين، والدول؛ قد تختلف دوافعهم، لكن أحد أشهر الدوافع هو المال، حيث يدخل المال على الخط في كل مرة، فستلعب أمورٌ مثل الجّشع وحب كنز الأموال دورًا في الهجمات، ونحن نعلم قوة ذاك الدافع؛ سيكون الموظفون المستاؤون غاضبين ويضعون الانتقام في بالهم. يُسبِّب كل ما سبق فئاتٍ مختلفةً من الهجمات: فهنالك هجمات هدفها إخراجُ الموقعِ عن العمل أو للبحث بنشاطٍ عن معلوماتٍ عن الاتصالات والأملاك؛ أحد أكثر الهجمات تأثيرًا هو هجومٌ للتلصص على البيانات، الذي هدفه هو سرقة بيانات الشركة أو بيانات شخصية خاصة؛ قد لا تُعتبَر بعض الحوادث هجماتٍ، حيث تتم من قِبل موظفين أو أفراد الأسرة الذين يرتكبون أخطاءً تؤدي إلى كشفِ شبكةٍ ذاتُ حمايةٍ ضعيفة. التهديدات المحتملة نشاهد بتكرار تقنياتٍ وطرقًا جديدةً لإيجاد ثغراتٍ في الشبكات؛ يجب تصنيف التهديدات إلى فئات كي ندرسها، لنكون قادرين على تأمين شبكاتنا ضدها وتصميم بنية تحتية قوية أمنيًّا؛ لكن لاحظ أن تلك التقنيات تتغير بوتيرةٍ عالية. إن البنية العامة لهجمةٍ اعتياديةٍ تتضمن استعمال أدوات للاستطلاع لتعلّم المزيد من المعلومات حول الشبكات، وكشف مخطط الشبكة والخدمات الموجودة فيها؛ واستخدام المعلومات المتاحة على الإنترنت عن الخواديم والخدمات والشركات؛ وهذا ما يُتبَع عادةً بهجومٍ بعد أن يعرف المهاجم كيف تبدو الشبكة، ثم سيحاول الحصول على بيانات منها، ويحصل على امتيازات المدير في الخواديم والحواسيب، ثم يزيد من امتيازاته ويبحث بعمق في الشبكة للحصول على المزيد من المعلومات القيّمة؛ يمكن أن تُعتَبَر هجمات كلمات المرور مجموعةً فرعيةً من الهجمات التي تهدف إلى الحصول على وصولٍ للشبكة، ومن ثم الحصول على البيانات باستخدام كلمات مرور صالحة للدخول إلى الشبكة. إذا أضفنا كل ذلك إلى التهديدات الفيزيائية، مثل الكوارث الطبيعية، وانقطاع التّيار الكهربائي، وحتى الأعطال التي تتطلب الصيانة؛ فإن ذلك سيكون «نحسًا» بكل تأكيد. تخفيف خطر هجمات كلمات المرور إذا ألقينا نظرةً عن قرب إلى واحدةٍ من المجموعات المنضوية تحت طرق الهجوم للحصول على وصول (access attack)، على سبيل المثال تهديدات كلمات المرور، فسندرك بأنّ هذه الطّرق تُستعمَل من قِبل الأشخاص السّيئين، وهي طرائق غاية في التّعقيد؛ حيث سيحاولون استغلال قاعدة البيانات والنّظر بداخلها للحصول على كلمات المرور وفك تشفيرها. من الممكن استعمال مُسجِّل المفاتيح (key logger) من أجل مراقبة جميع المفاتيح التي سيُضغَط عليها، وبالتالي الحصول على جميع كلمات المرور التي ستُكتَب؛ أو من الممكن أن يستعملوا «الهندسة الاجتماعية»، أي ببساطة سيتصلون بك ويدّعون أنّهم مسؤولو إدارة الشّبكة ويطلبون منك كلمة المرور. وهناك البعض منهم سيغوص في النفايات الخاصّة بك بحثًا عن بيانات البطاقة الائتمانية الخاصّة بك. أصبح ضروريًا استعمال تقنيّاتٍ وطرائق ذكيّة تضمن تخفيف خطر هجمات كلمات المرور، كاستعمال كلمات مرور بأحرفٍ كبيرة وصغيرة وأرقامٍ ورموزٍ خاصّة. لدينا سياسات معيّنة لطول كلمات المرور، بحيث أنّه لو تمّ الهجوم باستعمال كلمات مرورٍ لا تُطابِق هذه السّياسات، فسيتم اتّخاذ إجراءات معيّنة، مثلًا تعطيل الحسابات، وسيُعطَّل الحساب أيضًا بعد عددٍ معينٍ من محاولات تسجيل الدخول غير الناجحة؛ وأيضًا لدينا سياسات تجاه استعمال عاملَين للاستيثاق (two-factor authentication) والتّحقّق القوي (Strong authentication)، البطاقات الرمزيّة (token)، والبطاقات الذكيّة، وأيضًا التواقيع الرقميّة وذلك لإعطاء المستخدمين إذن وصول إلى الشبكة. ‎ترجمة -وبتصرّف- للمقال Securing the Network.
  24. cisco icnd1

    سنناقش في هذا الدرس أساسيات شبكات الحواسيب، وسنشرح قائمة المكونات الشائعة للشبكات الصغيرة الاعتيادية ونرى كيف نضعها في «مخططات شبكيّة» (network diagrams)؛ ستتضمّن هذه المخططات مختلف أنواع الشبكات وسنقارنها بمختلف طرق التوصيل الفيزيائية والمنطقيّة مثل طريقة التوصيل الحلقية والنجميّة. كل ما يهم في الشبكة هو نقل التطبيقات، لذا سنشرح مختلف الطرق للاتصال بالإنترنت لكي نصبح موزِّعين لهذه التطبيقات. ما هي الشبكة؟ أساسيات الشبكة أول سؤالٍ فلسفي اليوم هو: ما هي الشبكة؟ حسنًا، الشبكة ما هي إلا مجموعة من الأجهزة المتصلة وفي نهاياتها عقدٌ وأنظمةٌ هدفها هو تبادل ومشاركة المعلومات. تتألف الشبكة في الوقت الراهن من مجموعة من الأجهزة والنهايات الشبكيّة التي يمكن أن تكون أيّ شيء تقريبًا، ليس فقط الحواسيب والخواديم، لكن أيضًا الهواتف والهواتف المحمولة وأجهزة الأتمتة الصناعية التي تشترك الآن في تبادل المعلومات؛ هذا يعني أننا لا نتبادل فقط البيانات التقليدية على شكل ملفات، لكن نشارك أيضًا الصوت والفيديو والوسائط المتعددة. جزءٌ مهمٌ آخر هو مجال الشبكة، إذا تأمّلت في شبكة الإنترنت، فستجد أنَّ هنالك شبكات في كل مكان؛ يمكنك التفكير في مستخدم للهاتف المحمول يعمل من المنزل، حيث يستطيع الاتصال والدخول إلى الشبكة؛ تُكمَل الهيكلية مع الموظفين عن بعد، و المكاتب المنزلية، و المكاتب الفرعية، والمركز الرئيسي. أي أنَّ الإنترنت هي شبكة عامّة تصلنا جميعًا مع بعض. المكونات الفيزيائية الشائعة للشبكة تَتَّبِع شبكات اليوم هيكليةً تحاكي هيكلية تنظيم البشر؛ أي أنَّ لديك أناسًا يعيشون في منازل تشكِّل شوارعًا، التي بدورها تألِّف مدنًا، ثم تكوِّن دولًا ...إلخ. لديك أيضًا حواسيب تتصل داخليًا عبر مبدِّلات، التي بدورها تتصل داخليًا عبر موجِّهات؛ يمكنك النظر إلى الاتصال الفيزيائي بين تلك الأجهزة في الهيكلية، وستشاهد المكونات الرئيسية؛ صحيحٌ أنَّ الحواسيب نهاياتٌ شبكيةٌ؛ لكن لا تنسَ أنَّ الهواتف أيضًا هي نهاياتٌ شبكية، وكذلك أجهزة الأتمتة، وقريبًا ستكون آلة صنع القهوة نهايةً شبكيّةً؛ ستتصل تلك العقد الشبكية عبر مبدِّلات، التي توفِّر الوصل بالشبكة بالإضافة إلى التبديل «الذكي» للمعلومات؛ ستشاهد كبلات أو وسائط (media) سلكية أو لا سلكية لتجعل الأجهزة تتصل إلى المبدِّل؛ وستشاهد أيضًا مكونات لوصل مكونات مثل البطاقة الشبكية توفِّر الشبكة إلى النظام، وأيضًا «واصلات» (connecters) لوصل الوسائط بالبطاقات الشبكية؛ ستكون الموجهات موجودةً لوصل شبكة من المبدلات وتوفير أفضل طريق من شبكةٍ إلى أخرى. فهم مخططات الشبكة نستخدم مخططات الشبكة (network diagrams) عند تصميم وفهم واستكشاف أخطاء وتوثيق شبكاتنا؛ تحتوي هذه المخططات عادةً على أكبر قدرٍ من المعلومات دون جعلها فوضوية وعديمة الفائدة؛ يكون لديك عادةً أنواعٌ مختلفة من المخططات: المخططات الفيزيائية (physical topologies) التي تحتوي على سبيل المثال على طرق الاتصال الفيزيائي بين الأجهزة والمعلومات في الطبقة الفيزيائية. وستجد أيضًا مخططات منطقية تحتوي على أشياء مثل معلومات TCP/IP. لكن يمكنك أيضًا الحصول على مخططات شبكيّة تتضمن طرق انتقال البيانات، ومعلومات الإدارة لأغراض استكشاف الأخطاء ...إلخ. ربما تود استخدام أيقونات وتسميات متناسقة لبناء مخططاتك؛ على سبيل المثال، سنمثِّل المبدِّلات بأيقونة ذاتُ أربعة أسهم؛ وتكون الموجهات عمومًا في هذا النوع من المخططات دائريةً وفيها أيضًا أربعة أسهم؛ يمكنك استخدام خط مستقيم للدلالة على اتصالات إيثرنت (Ethernet) وخطٌ منكسرٌ للاتصالات التسلسلية (serial connections)؛ ربما الأيقونة نفسها غير مهمة، لكن المهم هو استخدام أيقونات متشابهة للدلالة على وظائف متشابهة، واستخدام الأيقونة نفسها دومًا لهذا النوع من الأجهزة؛ فمثلًا «السحابة» في هذا المخطط لا تمثل يومًا ماطرًا أبدًا، بل هي مجرَّد شبكة خارج نطاق إدارتنا، وفيها سلسلة من الأجهزة لكها لا تهمنا مباشرةً؛ كل ما نريد تمثيله هو شبكة عملاقة؛ الحظ أيضًا استخدام النصوص لتعريف عناوين IP، والبطاقات الشبكيّة، وبروتوكولات الإدارة. آلية عمل مشاركة الموارد وفوائدها الشبكات موجودةٌ للسماح لنا بمشاركة المعلومات والموارد بكفاءة وبفعالية، ولزيادة إنتاجيتنا؛ ونعني بضمير الجمع «نا» في الجملة السابقة كلًا من الأفراد والمنظمات والبلدان وهلمّ جرًا؛ إذا أردنا مشاركة البيانات والتطبيقات -ونعني بالتطبيقات الطرق التقليدية لمشاركة الملفات أو الطباعة، بالإضافة إلى الوسائط المتعددة مثل الصوت والفيديو ...إلخ.- ونريد أيضًا أن نجعل الموارد مركزيّة لذا سنحتاج إلى أن يكون المورد متاحًا في مكانٍ واحد، دون الحاجة إلى إنشاء نسخ لعدِّة مستخدمين؛ وبهذا يمكننا أن نصل الكاميرات إلى الشبكة كأجهزة دخل ونشاركها بين عدِّة مستخدمين؛ وحتى أجهزة الإخراج مثل الطابعات أو التخزين الشبكي، أو حتى أجهزة النسخ الاحتياطي كي لا نحتاج إلى إنشاء نسخ احتياطية محلية على كل حاسوب، إذ نستطيع أخذ نسخٍ احتياطية عبر الشبكة ثم نشارك ذاك المورد بين مستخدمين عددين؛ يجب أن يجعلنا النظام الاقتصادي للتوسع أكثر إنتاجيةً ويسمح لنا أيضًا بتقليل التكاليف؛ ويجب أيضًا أن يسمح لنا بالتفكير بوضوح في خدمات الشبكة. لم يعد المكان الفيزيائي مهمًا، ويجب أن نقدر على الاتصال بالتخزين الشبكي إن كان مكانه الفيزيائي بجوارنا أو كان في الصين لكنه متاحٌ للاتصال عبر الشبكات العامة مثل الإنترنت. أصبح عددٌ كبيرٌ من التطبيقات متوفرًا لنا، وبعضها شائع الاستخدام أيضًا، مثل البريد على شكل «Outlook»، أو حتى البريد «العام» مثل Yahoo!‎ أو Google. تسمح متصفحات الويب لنا بفتح نافذة على العالم والوصول إلى عدد هائل من التطبيقات عبر عميل عالمي (متصفح الويب). تأثير تطبيقات المستخدم يمكننا أيضًا تصنيف التطبيقات بناءً على تأثيرها على الشبكة؛ في كلماتٍ أخرى، ما هي كمية البيانات التي ترسلها إلى الشبكة وهل تُسبِّب «ازدحامًا» في الشبكة؛ لكن وعلى نفس المنهج، يجب أن نصنفها وفق تأثير الشبكة عليها؛ فعلى سبيل المثال، تطبيقات نقل الملفات مثل FTP وTFP تضيف بعض المعلومات إلى الشبكة وترسل ما يسمونها «رزمًا» إلى الشبكة بكميات كبيرة؛ لكنها لا تتأثر بازدحام (congestion) الشبكة إلى حدٍ كبير؛ إذا وصل الملف إلى وجهته خلال بضع ثوانٍ، فلا يهم ذلك أو لا يكون له تأثيرٌ على تجربة المستخدم؛ لكن على الكفّة الأخرى، لدينا تطبيقات تعمل في الوقت الحقيقي (real-time) التي ترسِل رزمًا أقل إلى الشبكة، لكنها قد تتأثر بازدحام الشبكة إلى حدٍ كبير؛ فزمن التأخير بين نهايتين شبكيتين سيؤثر مثلًا على نقل الصوت ويجعله أقل جودةً. وفي الوسط، هنالك تطبيقات تفاعلية تؤثر على تجربة المستخدم اعتمادًا على نوع التطبيق. من المهم فهم أن جميع أنواع التطبيقات الثلاثة ستتواجد في الشبكة، ولهذا ستكون إدارة موازنة الأولويات جزءًا من آلية تسمى «جودة الخدمة» (quality of service) أو QoS؛ حيث لدينا موارد شبكيّة محدودة، ولكن ما يزال علينا السماح لأنواع التطبيقات الثلاثة في الشبكة بدرجاتٍ مختلفةٍ من المرونة والتأقلم مع شروط الشبكة والمتطلبات المختلفة. صفات الشبكة يجب أن نتمكن من تصميم شبكاتنا باستخدام إرشادات عامة بناءً على معطيات محددة، بعض تلك المعطيات مذكورٌ هنا: السرعة والتراسل الشبكي (bandwidth) مهمان جدًا، خصوصًا بعد معرفة أننا سنحتاج إلى استخدام تطبيقات شرهة للتراسل الشبكي مثل مشاركة الفيديو والوسائط المتعددة في شبكاتنا. لن نستفيد شيئًا بالحصول على اتصال بسرعة عالية إذا كان الاتصال ينقطع طوال الوقت، لذا فإن الوثوقية (reliability) هي شيءٌ يجب علينا تأصيله في شبكاتنا؛ بعض المخططات الشبكيّة الفيزيائية يمكن أن تكون أكثر وثوقية من غيرها؛ فقد يكون لبعض عناصر الشبكة تاريخٌ طويل بمشاكل في الاستقرار لكن غيرها لا يملك تلك المشاكل. وهذا يؤدي إلى الحديث عن التوفر (availability)، بعض الخدمات تتطلب توفرًا بنسبة 100%، 24×7 في 365 يوم؛ بعضها لا يتطلب كل هذا القدر من التوفر. عمومًا، تُقاس الوثوقية بالنسبة المئوية لزمن التشغيل (uptime) خلال السنة، وبهذا، قد تتطلب بعض الخدمات المهمة زمن تشغيل 99.999%؛ وهذا من الصعب الوصول إليه، ويحتاج إلى متطلبات خاصة لكيفية تصميمك للشبكة، الحماية هي عامل مهم أيضًا مثل الوثوقية والتوفر، لأن الخدمات التي تحتوي على معلومات الزبائن الخاصة ومعلومات مهمة ومحورية للشركات، ستكون حمايتها هدفًا مهمًا؛ جميع تلك الأشياء موجودةٌ في في مخطط الشبكة، لكن أحد أهم العوامل -خصوصًا في الحقل التجاري- هو التكلفة؛ وربما لن نكون قادرين على توفير كل تلك المعطيات بنسبة 100%، لأن ذلك سيكون مقيّدًا بميزانيتنا وبتكاليف التقنية. تصنيف مخططات الشبكة الفيزيائية: أنواع الشبكات هنالك نوعان من المخططات في الشبكات: المخططات الفيزيائية والمخططات المنطقية. تعرِّف المخططات الفيزيائية التوصيل الشبكي ونوع الاتصال الفيزيائي، وخصائص تلك الاتصالات الفيزيائية؛ بينما يعرِّف المخطط المنطقي كيف تُنقل البيانات في المخطط الفيزيائي، حيث تحتوي على الطرق المنطقية، والتي ليست بالضرورة طرقًا فيزيائية. هذه أمثلة عن المخططات الفيزيائية، وكيف أنها ارتبطت تاريخيًا إلى نوع الأكبال التي سنستخدمها لبناء المخطط الفيزيائي. على سبيل المثال: الكبل المجدول (twisted pair) أو الكبل المحوري (coaxial) أو أكبال الألياف الزجاجية (fiber)؛ في المخططات التسلسلية (bus topologies) القديمة؛ كانت الأجهزة تتصل مع بعضها في خط باستخدام كبل محوري، مما يُنتِج بيئةً مشتركةً في التراسل الشبكي؛ لكن في المخطط الحلقي (ring topology)، فإن الأجهزة تتصل عبر الكبلات إلى بعضها، حيث سيكمل أول جهاز وآخر جهاز الحلقة؛ وستؤثر وصلةٌ لا تعمل على الحلقة بأكملها، وستجعل وقت نقل البيانات أكبر، ولهذا السبب هنالك بعض الأشخاص الذين يصممون الحلقات المزدوجة لتصل وصلًا مزدوجًا بين الأجهزة. أما في المخطط النجمي، فإن جهازًا مركزيًا سيتصل إلى بقية الأجهزة وسيوفر اتصالًا بينها، مما يحل بعضًا من مشاكل الوثوقية الموجودة في المخططات الحلقية؛ تستعمل المخططات النجمية عادةً الكبلات المجدولة. المخططات المنطقية مرةً أخرى، المخططات المنطقية هي تعريف كيف تسافر الإشارات والمعلومات من نقطة إلى أخرى ضمن الشبكة؛ ربما تشاهد مخططًا منطقيًا مختلفًا عن المخطط الفيزيائي، على الرغم أنهم قد يكونوا متماثلَين؛ على سبيل المثال، في مخططٍ تسلسليٍ فيزيائي، تستخدم الإشارات طريقًا مستقيمًا للانتقال من نقطة إلى أخرى؛ لكن ربما يكون لديك مخطط نجمي فيزيائي، لكن الأجهزة تتصل داخليًا مع بعضها كأنها موصولة بنفس الكبل، وبهذا يكون المخطط المنطقي هو مخطط تسلسلي. هذه هي حالة إيثرنت (Ethernet) التي هي أكثر المعماريات والمخططات الفيزيائية المنطقية الموجودة في شبكات LAN المحلية في أيامنا هذه. المخطط التسلسلي في المخطط التسلسلي الفيزيائي، توصل الأجهزة إلى كبل وحيد، وعمومًا هو كبل محوري؛ الإنهاء في نهاية الكبل هو أمرٌ مهم لمنع الإشارات من العودة إلى الكبل والتسبب في أخطاء شبكيّة؛ كانت تَستخدم الشبكات المحلية القديمة هذا المخطط، لكنه يُستخدَم كثيرًا حاليًا من شركات «الكيبل» (cable) التي توفِّر وصولًا إلى الإنترنت؛ إذا تخيلت أن الأجهزة قادرة على التحدث في نفس الوقت، فستحتاج إلى بروتوكولٍ آخر أو طريقةٍ أخرى للوصول إلى الكبل لمنع التصادمات (collisions) ولمنع حدوث أخطاء شبكية. المخطط النجمي يَستخدم المخطط النجمي الفيزيائي جهازًا مركزيًا لوصل جميع الأجهزة؛ في الشبكات المحلية الاعتيادية، هذا الجهاز يكون موزِّعًا (hub) أو مبدِّلًا (switch)، وستمر كل البيانات المنقولة عبر تلك النقطة المركزية؛ وهذا سيُحسِّن من وثوقية الشبكة لأن حدوث مشكلة في أحد الوصلات سيؤثر على الجهاز الموصول بتلك الوصلة فقط، ولا علاقة لبقية الشبكة بهذا الخلل؛ لكن يسبب حدوث خلل في المبدل تأثيرًا على كل الشبكة؛ وهذا هو السبب لماذا يجب تصميم طريقة تعويضية (redundancy) في هذا المخطط. المخطط النجمي الموسَّع يمكن إنجاز عدِّة مراحل من redundancy باتباع بعض الاستراتيجيات؛ على سبيل المثال، إذا أنشَأت المزيد من الفروع في المخطط؛ في هذا المثال، حدوث خلل في مبدل سيؤثر فقط على ثلاثة أجهزة ولن يؤثر على بقية الشبكة؛ عليك أن تضع بعين الاعتبار أن تستخدم مبدِّلَين مركزيَين وتصل الأجهزة اتصالات مزدوجًا مع المبدلين؛ فلو حدث خللٌ في إحدى المبدلات الرئيسية، فستتولى الأخرى الاتصالات ولن تتأثر الشبكة. المخطط الحلقي في المخطط الحلقي، جميع الأجهزة متصلة إلى بعضها بعضًا على شكل حلقة؛ لكن هذا مختلفٌ عن المخطط التسلسلي، على الرغم من أنه قد يبدو أنه يشبهه؛ لأنها ليست متصلة إلى كبل واحد، لكنها متصلة إلى بعضها بعضًا، وهذه أكبال مختلفة هنا؛ تنتقل الإشارات عبر الحلقة، وفي بعض الأحيان في اتجاهٍ واحد؛ حدوث خلل في أحد تلك الأجهزة سيؤثر على كامل الحلقة، مما يمثِّل نقطة ضعف، ربما تريد نقل بيانات باتجاهين أو استخدام المخطط الحلقي المزدوج لزيادة التوفر. المخططات الحلقية يمكن أن تكون على شكل مخطط فيزيائي، أو على شكل مخططات منطقية؛ على سبيل المثال، «token ring» هي نجمة فيزيائية، لكن عمومًا، عند استخدام «token» فإن الأجهزة ستشكّل حلقات منطقية لنقل البيانات. المخطط الحلقي المزدوج سيؤثر حدوث خلل في اتصال أو جهاز في مخطط حلقي فردي على كل الحلقة؛ ولهذا يجب أن نستخدم حلقة تعويضية (redundancy)؛ وبالتالي ستسمح للبيانات بالمرور بطريقٍ واحد في أول حلقة، ونقل البيانات في اتجاهٍ آخر في الحلقة الثانية. وهذا أفضل للتوفر والوثوقية، لكن هذا على حساب المزيد من المصاريف للوصلات والكبلات. مخطط ترابطي تام (Full-Mesh) أشمل طريقة للوصل هي المخطط الترابطي التام؛ جميع الأجهزة متصلةٌ مع بعضها بعضًا في هذا المخطط، مما يؤدي إلى مستويات عالية من تدارك الأخطاء؛ لكن هذا المخطط يكلف تكلفةً كبيرةً، ويُلاحظ استخدامه في بيئات WAN للوصل بين المكاتب الفرعية والمركز الرئيسي؛ لا توجد نقطة ضعف تؤدي إلى تعطل الشبكة، لكن قد يكون غالي الثمن في بعض الأحيان، لهذا تكون هنالك خياراتٌ أخرى تتضمن مخططًا ترابطيًا جزئيًا. المخطط الترابطي الجزئي (Partial-Mesh) إن المخطط الترابطي الجزئي هو حلٌ وسطٌ بين ضمان عدم انقطاع الاتصالات وبين التكلفة؛ ربما تختار أهم الفروع الشبكية أو أهم الأجهزة، ثم تبني المزيد من الوصلات بينها، وتترك المستوى الاعتيادي من redundancy للعقد الأقل أهميةً. العامل المؤثر في غالبية الأوقات هو الميزانية. الاتصال إلى الإنترنت تتطلب الاتصالات إلى الإنترنت اهتمامًا خاصًا، لأن هذه شبكةٌ عامةٌ تسمح لنا بالاتصال بسعرٍ رخيص. توجد ثلاثة خيارات مذكورة هنا: DSL الذي يستخدم البنية التحتية للهواتف الأرضية للسماح بنقل البيانات؛ وشبكات «الكيبل» التي توفر عروضًا تتضمن اتصالًا بالإنترنت وتمرير بيانات IP؛ وأخيرًا، الاتصالات التسلسلية التقليدية، المرتبطة بشبكات TDM-type ‏(time division multiplexing-type) باستخدام CSU/DSUs للاتصال إلى موفر خدمة الإنترنت. ترجمة -وبتصرف- للمقال Network Topologies and Functions.
  25. cisco icnd1

    تُحسِّن الشهادات من سيرتك الذاتية عبر إضافة مجموعة من المهارات إليها؛ هنالك المئات من الشهادات المتعلقة بالتقنية متوفرةٌ الآن، لكن شهادة Cisco CCNA هي من أكثر الشهادات المعترف فيها دوليًا؛ أنشَأت سيسكو الشهادة لإعطاء المدراء مجموعةً من المهارات لتسليح الموظفين المحتملين بطريقة لقياس مهاراتهم أو لمطابقة معيار معيّن؛ يمكن أن تكون خطوة الحصول على شهادة من سيسكو خطوةً محوريةً لبدء رحلة ناجحة إلى مهنة ذات كسبٍ وفير؛ على سبيل المثال، أُنشِئ برنامج شهادة CCNA لتوفير مقدمة صلبة ليس إلى نظام تشغيل سيسكو للشبكات الداخلية (Cisco Internetwork Operation System [اختصارًا IOS]) والعتاد الذي توفِّره سيسكو فحسب، لكن إلى الشبكات الداخلية عمومًا، مما يجعل تلك الشهادة مفيدةً حتى في المجالات التي ليست متعلقة بسيسكو بشكلٍ خاص. الصناعات الناشئة في تقنيات المعلومات والاتصالات في حاجةٍ مستمرة إلى المحترفين؛ تؤكد شهادة CCNA أنَّ حامل الشهادة مدرَّب للعمل مع غالبية نواحي الشبكة، حيث تتلخص بدورة تدريبية شاملة مع خبرة تقنية جيدة بالإضافة إلى مهارات عملية وبرمجية أساسية. مهام العمل لحاملي شهادة CCNA تتضمن تثبيت وإدارة ودعم شبكات IP وأنظمة الحواسيب؛ وهم مسؤولون أيضًا عن تركيب القطع الفيزيائية للشبكة وضبط برمجياتها بالإضافة إلى استكشاف أخطاء الشبكة وإصلاحها، وضمان حماية وأمن الشبكة، والتوفر (availability). يوجد حاليًا عشرة مسارات مختلفة في «مرحلة المساعد» (Associate level) بناءً على مختلف التقنيات؛ لكن شهادة «CCNA Routing and Switching» هي أكثرها قيمةً وهي شرطٌ إذا أردت التخصص في الصوت، أو الفيديو، أو الحماية، أو أي شيءٍ آخر متوفر كشهادات في «مرحلة المساعد». يُقسَّم مسار «CCNA Routing and Switching» إلى خطوتين: ICND1 و ICND2، اللذان هما امتحانان صغيران؛ لكن النتيجة مساوية للحصول على شهادة CCNA الشهيرة التي ستأخذها بعد أن تتجاوز امتحان 120-200. برامج CCxP هي الخطوة المنطقية التالية في مهنتك؛ ستهيؤك لفهم وتَتَبُّع مشاكل الشبكات الدخلية؛ ستمر بمرحلة تغيرات جذرية، وتزيد معرفتك ومهاراتك كثيرًا خلال عملية الحصول على تلك الشهادات، قبل أن تقرر المجال الذي تريد الاختصاص فيه، بعض تلك المواضيع هي «التوجيه والتبديل» (Routing and Switching)، والحماية والتعاون (Security and Collaboration) (بالصوت والفيديو). هذا هو السبب لم عليك التدرب في «Cisco Collaboration Devices‏» (CICD) ثم تحاول اجتياز امتحان CICD ‏(210-060) الذي سيحدِّد مهاراتك ومعرفتك بمنتجات «Cisco Unified Communications»؛ أو إذا كنت مرتابًا، فيمكنك اختيار الالتحاق بدورة «Cisco IOS Network Security‏ [IINS]» ثم اجتياز امتحان IINS ‏(640-554). آخر خطوة هي الحصول على شهادة «Cisco Certified Internetwork Expert‏ [CCIE]»، تنصح سيسكو بخبرة عمل من ثلاث إلى خمس سنوات من خبرة العمل قبل السعي وراء نيل شهادة CCIE؛ بعد اجتياز تلك العقبة، عليك النجاح في امتحان CCIE الكتابي قبل الدخول إلى المخبر. ما زال الطريق أمامك طويلًا، لكن تذكر أن كل رحلة تبدأ بخطوة، التي هي في حالتك شهادة CCNA. دور حامل شهادة CCNA مهمٌ لتحسين الأنظمة الحالية باستراتيجية غير مكلفة لزيادة الإنتاجية؛ ولمّا كانت تقنية المعلومات حقلًا متجددًا، فإن شهادة CCNA مصنفة من أعلى الشهادات التي تطوِّر الشركات والمنظمات لتحقيق موارد مالية كبيرة. شهادة ICND1 يجدر بنا بناء أساساتٍ قوية قبل أن نبحر في غمار تفاصيل دورة ICND1/CCENT التدريبية؛ تخيّل عملية بناء مبنىً: ما الذي علينا فعله بادئ الأمر؟ سنبدأ أولًا بالأساسات، حيث علينا أن نصب الخرسانة لدعم بقية المبنى الذي نُنشِئه، وسنفعل بنفس الأمر هنا. سنتعرّف على كل تلك المكونات المختلفة وكيف تتصل مع بعضها بعضًا؛ والأمر الأكثر أهميةً، سنتعلم كيف تتدفق الاتصالات بين نقطتَين على الشبكة. خذ لحظةً لتفكِّر في جميع القطع الإلكترونية التي يُمكنك الوصول إليها، مثل هاتفك المحمول أو تلفازك أو حاسوبك، ما الشيء المشترك بينها؟ تشارك العديد من المكونات في عملية تشغيلها، لكن لا تساوي تلك المكونات شيئًا دون بعضها بعضًا، وهنالك شيءٌ مهمٌ جدًا هو نظام التشغيل؛ لنفكِّر قليلًا عن المبدِّلات (switches) والموجِّهات (routers) في عالم سيسكو، كل ما لدينا هو مجموعة من المكوِّنات داخل صندوق، لكن ما يجعل ذاك «الصندوق» يعمل هو نظام التشغيل، لذا سنركِّز على نظام «Cisco IOS». يكون لكل جهاز إلكتروني نشتريه بعض الإعدادات الأوّليّة فيه؛ لكن هل نستخدم هذه الإعدادات الأوّليّة في الحياة العملية؟ لا، نجري دومًا تغييرات لكي يلائم الجهاز احتياجاتنا؛ وهذا ما نريد فعله هنا مع مبدِّلاتنا، علينا أن نستطيع إدارتها عن بعد، وليس علينا دومًا الاتصال إلى كبل طرفية «console cord» لذا علينا تحديد عنوان IP للإدارة لكي نتصل منه؛ نود أيضًا أن نكون قادرين على التحقق من أنّ عملية الإقلاع قد تمّت دون أخطاء، وأنّ كل شيءٍ في مبدِّلاتنا يعمل عملًا سليمًا. هل تتذكر أيّة طبقة من طبقات OSI أو مجموعة TCP/IP نجد المبدِّلات؟ أتمنى أنك قلت «الطبقة الثانية»؛ لكن كيف نصل كل تلك المبدلات مع بعضها؟ ما الذي سنستخدمه في الطبقة الفيزيائية من طبقات OSI؟ نحتاج إلى كوابل؛ هنالك أنواعٌ مختلفةٌ من الكوابل التي يمكننا استعمالها؛ من المهم أن نختار الكوابل الصحيحة لتلائم استعمالنا؛ لذلك سنقضي بعض الوقت في الطبقتين الأولى والثانية من طبقات OSI مركزين على طرائق التغليف (encapsulation) التي يمكننا استعمالها لنتأكد من أن لدينا اتصالًا بين جهازين على شبكاتنا المحليّة. متى سينقضي عهد النسخة الرابعة من بروتوكول الإنترنت، أو IPv4؟ لا أحد يعلم؛ لكن النسخة السادسة من بروتوكول الإنترنت (IPv6) هي البديل بكل تأكيد؛ لكن متى يحدث ذلك؟ لا يوجد تاريخ محدد، لا يوجد زر معين يمكن الضغط عليه ليقول: «يا أيها الناس، انتقلوا إلى IPv6»؛ وحتى لو كانت النسخة السادسة من بروتوكول الإنترنت (IPv6) تلوح بالأفق، لكن ما زال علينا احتراف التعامل مع IPv4 (من ناحية العناوين والشبكات الفرعية)؛ سنأخذ مجال عناوين كبير ونسنده إلى جزءٍ من شبكتنا وستبدع وستتعامل بكفاءة مع عناوين IPv4 ذلك لأنها نادرة وعليك أن تَفصِلَها إلى شبكات منطقية مختلفة، وذلك بتقسيمها عبر الشبكات الفرعية (subnetting)، إذا لم يكن ذلك مألوفًا لديك، فسنعلِّمك ذلك لاحقًا في هذه الدورة التدريبية؛ سنشرح كيف يمكن أن نأخذ شبكة ذات الفئة (class) ‎/8، أو ‎/16، أو ‎/24، وعمل شبكات فرعية منها؛ لنقل مثلًا أنّه لدينا شبكة بفئة ‎/24 وقسّمناها إلى شبكة فرعية بفئة ‎/28، هل هذا كل ما يمكننا فعله؟ ألم نعد نستطيع تقسيمها أكثر من ذلك؟ بلى نستطيع، وهذا ما نسميه «variable-length subnet masking» أو اختصارًا VLSM‎، لكن ما هذا؟ إنها مجرد طريقة لتقسيم الشبكة الفرعية إلى شبكة فرعية أخرى. بعد أن ركّزنا على أول ثلاث طبقات من OSI، فلنكمل طريقنا إلى الأعلى؛ لنركّز على الطبقة الرابعة من OSI، المعروفة بطبقة النقل (transport layer)، وإذا طابقناها مع مجموعة TCP/IP، فتلك الطبقة تشير أيضًا إلى طبقة النقل؛ سنركِّز خصوصًا على بروتوكولَين هنا، هما TCP و UDP، حيث سنقارنها مع بعضهما بعضًا وسنتعلم أين ولماذا سنستخدم أيًّا منهما لنقل البيانات. ثم سنغوص في شيءٍ كنا ننتظره جميعًا، طريقة عمل الموجِّه؛ سنلقي نظرةً إلى مكونات الموجهات، وطريقة إعدادها وضبطها لإجراء العمليات الأساسية. سنشرح أحد أهم المفاهيم هنا؛ سنشرح كيفية تمرير الرزم (packet forwarding)، كيف نرسِل تلك الرزمة من محطة ما في الشبكة إلى محطة أخرى في شبكة مختلفة تمامًا؟ سنبدأ هنا بالتعمق في الموجهات، وسنركِّز على الذي يحصل عندما تصل الرزمة إلى الموجِّه، وماذا يفعل لكي تُكمِلَ الرزمةُ طريقها إلى وجهتها. سنتحدث عن شيءٍ آخر أيضًا هو مفهوم التوجيه (routing) وكيف «نُدرِّب» موجهاتنا؛ أي أننا هنا سنعرِّفك على نمط التوجيه الثابت (static routing) وكيف يمكننا يدويًا تدريب موجهاتنا لكي نتأكد أنها تعلم ماذا عليها أن تفعل عندما تصل إليها الرزمة الشبكيّة. لاحقًا، سنشرح قائمة التحكم بالوصول (access control list) في عدّة مواطن في دورة ICND1 التدريبية؛ لكن لماذا سنفعل ذلك؟ حسنًا، هنالك سببان يدفعاننا لاستعمال المتحكمات في الوصول، حيث يمكننا استعمالها للتصنيف (classification) أو للترشيح (filtering)؛ وسنركِّز على تقنيات التصنيف، أي سنناقش طريقة «ترجمة عنوان الشبكة» (Network Address Translation) أو اختصارًا NAT؛ وسنتعلم كيف نستخدم قائمة التحكم في الوصول للتعرف على البيانات الشبكية التي يجب أن «تترجم» (translated) باستخدام NAT. حسنًا، لقد استقبلت موجهًا ومبدِّلًا جديدًا، ففتحت الصندوق وأخرجتهما، ثم ضبطتها. هل تظن أنَّ هنالك أي نوع من أنواع الحماية مضبوطٌ افتراضيًا على الموجهات أو المبدلات؟ الجواب هو «لا»، لا توجد أيّة حماية؛ علينا أن نقضي وقتًا في ضبط هذه الأجهزة وتدعيمها كي تكون محميةً من المهاجمين، سواءً من المستخدمين داخل شبكتنا أو من خارجها، صُمِّمَت الموجِّهات والمبدِّلات لتمرير البيانات الشبكيّة، لذلك علينا أن نتأكد أن البيانات المُمرّرة لا تتعرض للإعاقة بسبب أيّ نوع أو شكل من أشكال الاختراقات الأمنية. تحتوي شبكاتنا على العديد من المبدلات المختلفة، ويمكن أن تحتوي أيضًا على مختلف الموجهات؛ لكن ماذا يعني هذا لنا؟ هذا يعني أنه سيكون عندنا شبكاتٌ فرعيةٌ مختلفة، وأننا سنحتاج إلى أن تتمدد الشبكة، لا نريد من شبكتنا أن تبقى صغيرةً؛ لأنه إذا بقيت شبكتنا صغيرةً فهذا يعني أننا لا نتوسع أو نتطور؛ علينا أن نكون مجتهدين وأن نصمِّم شبكتنا تصميمًا جيدًا للتأكد أننا نتحكم في تدفق البيانات؛ إذا لم تمر البيانات مرورًا صحيحًا، فستحدث أزمة «ازدحام» في شبكتنا، ولهذا السبب علينا أن نستوعب مفهوم «الشبكات المحلية الوهمية» (Virtual Local Area Networks) أو اختصارًا VLAN. تمنحنا الشبكات المحلية الوهمية القدرة على عزل شبكة الطبقة الثانية من OSI وتمنحنا القدرة على التأكد أننا نسمح للبيانات بالمرور بطريقةٍ أكثر كفاءةً، لكن عندما تكبر شبكتنا، فهل سنستمر في إسناد عناوين IP يدويًا؟ لا، لن نحتاج لذلك؛ حيث يعني التوسع أن الشبكة أكبر، مما يعني أن هنالك المزيد من العمل لننجزه؛ لذلك علينا الاعتماد على بروتوكول ضبط المضيف الديناميكي (Dynamic Host Configuration Protocol) أو اختصارًا DHCP؛ ويمكننا إن أردنا أن نضبط موجهات سيسكو لتعمل كخوادم DHCP. وعندما نستمر في التوسع، فإننا في مرحلةٍ ما سننتقل خارج منطقتنا الجغرافية. ماذا يعني هذا؟ هذا يعني أنَّه سيكون لدينا مواقع بعيدة، وسيعمل عندنا موظفون عن بعد؛ ربما سنحتاج إلى إرسال بعض الموظفين للسفر وسيبيتون بفنادق؛ لكن كيف سيتصلون إلى شبكتنا المحلية حيث تقبع جميع الموارد التي يحتاجون لها؟ لذا سنناقش الشبكات بعيدة المدى (Wide Area Networks) وكيف نسمح للمستخدمين المتواجدين في مكانٍ بعيد عن الموارد التي يحتاجون لها بالاتصال إليها. وسنحتاج عند التوسّع إلى الاعتماد على نوع مختلف من البروتوكولات للتأكد أن موجهاتنا تعلم عن الشبكات الوجهة (destination networks)، وهنا سنعتمد على بروتوكولات التوجيه الديناميكي (dynamic routing protocols)، وسنركِّز خصوصًا على «Open Shortest Path First» أو اختصارًا OSPF. غالبيتنا يتجنبون النسخة السادسة من IP لسنوات، حيث نعلم عنها، ونعلم أنها في الطريق لتنتشر، لكننا نقول: سأتعلمها لاحقًا، حسنًا يا قوم، الوقت الآن مناسبٌ لتعلمها، لن ننتظر أكثر من ذلك، ولن نتجنب IPv6 بعد الآن؛ فسنتحدث عن ميزات IPv6 مما يسمح لك ببناء أساسٍ قويٍ يمكّنك من فهم لماذا نحتاج IPv6 وكيف سنستخدمها؛ حيث سنتحدث عن الضبط وعن آلية عمل IPv6؛ لكن الشبكات التي تتوسع ستحتاج إلى العديد من الموجهات، ولهذا سنحتاج إلى بروتوكولات التوجيه، فهل هنالك بروتوكولات توجيه لنسخة IPv6؟ نعم، سنعرِّفك عليها لكننا سنناقشها بالتفصيل في دورة ICND2 التدريبية. ترجمة -وبتصرف- للمقال ICND1/CCENT 100-101 Course & Exam.