تحياتي الأعزاء!
في مرحلة ما من حياتهم ، يتوقف كل صندوق عنيد عنيد عن فعله في تفويت سيارة Kantian Arduino على أنها "أشياء في حد ذاتها"
لا يستطيعون! : إن وميض مؤشر LED ، ونقل البيانات من المستشعرات ونقلها عبر السلك إلى الكمبيوتر الشخصي أمر ممتع بالتأكيد ، لكن الكأس المقدسة في حالة تنقل ، متحررة من "الروابط النحاسية" ، في حرية حقيقية بين موجات الأثير العالمي.
هذا هو المكان الذي يفتح أمامنا الواقع القاسي المتمثل في قنوات الاتصال غير المستقرة ، وأخطاء الإرسال ، والرسائل غير المسلمة.
لا سمح الله أن يدعي الأصالة في هذا المجال: طالما استخدمت البشرية مجموعة كاملة من البروتوكولات لجميع المناسبات.
لكن هدفنا هو التعلم ، وبما أنني مؤيد متحمس للاستطلاع في القتال ، فسوف ندرس من خلال ابتكار بروتوكولنا الخاص "بالدراجة".
أقترح اليوم تطوير بروتوكول يضمن تسليم الرسائل وتكاملها وتسلسلها المضمونين بين مشتركين (من نقطة إلى نقطة ، من نقطة إلى نقطة) ، ويعرف كيف يطبق خوارزمية
Nagle وخطوط
الأنابيب للبروتوكولات ، ويعني ذلك. في الوقت نفسه ، ينبغي أن يكون لها الحد الأدنى من
النفقات العامة والضغط حتى في Arduino UNO الضيقة.

أطلب من كل المهتمين على متن الطائرة ، أن نغلق البوابات ونفتح أحجار الملء ونملأ خزانات الصابورة. لدينا رحلة في الماضي ، الوجهة: عام 1974!
لفارغ الصبر (أنا نفسي كذلك!)فيما يلي مستودع جيثب حيث توجد التطبيقات:
وفقًا للتقاليد القديمة الجيدة ، يشارك على الأقل خبيران معترف بهما في هذا المجال في وصف خوارزميات وبروتوكولات التشفير ، إذا كان أي شخص آخر لا يعرفها ، تعرف:
و
أولاً نصف مهمة بسيطة
تجلس أليس وبوب في الخنادق المجاورة ولا يمكنهم رفع رؤوسهم لرؤية بعضهم البعض. لا يمكنهم التحدث إلا بصوت ، بجانب صفارات الرصاص وانفجار القذائف ، مما يغرق صراخهم ، وبالإضافة إلى ذلك ، عندما يتحدث أحدهم ، يجب أن تصرخ حتى لا تسمع أي شيء على الإطلاق.
الموقف معقد بسبب حقيقة أن الأعداء يسمعونهم - وعليك استخدام لغة الكود ، لسبب ما يتكون من سلاسل طويلة من الأرقام.
نظرًا لأن كلا من Alice و Bob هما شخصان ، فيتعين عليهما الخروج لتناول الطعام أو الذهاب إلى المرحاض بشكل دوري ، كما أنهما غير صبورين إلى الحد الذي يجعلهما غير صبورين في أكثر اللحظات غير المناسبة!
كيف ولماذا لتأسيس اتصال؟
كيف يمكننا ترتيب نقل موثوق للبيانات في مثل هذا الموقف المحبط ، عندما يبدو أن كل شيء محكوم عليه بالفشل؟
الحل الأول الذي قد يتبادر إلى الذهن هو استخدام عبارات رمز
إيقاف الكلمات لبدء النقل وإنهائه.
حسنًا ، دعنا نقول ما إذا كانت أليس تريد إرسال رسالة ، فعليها أن تصرخ "ابدأ الإرسال!" وانتظر حتى يجيب بوب عن "بدء الاستقبال!".
إذا لم تنتظر أليس استجابة بوب ، فهي ببساطة تكرر طلبها لبدء النقل. بطبيعة الحال ، يجب ألا تفعل هذا كثيرًا ، وإلا ، كما نعلم ، لا تسمع إجابة بوب.
غرامة. ولكن ماذا يحدث إذا سمعت أليس في استجابة من الخندق التالي ، "بدء الإرسال!"
اتضح أن بوب قرر أيضًا نقل بعض المعلومات المهمة الآن. أليس لها شخصية لطيفة ، وقد فكرت: "حسنًا ، سأنتظر ، رسالتي هي ، من حيث المبدأ ، ليست عاجلة ، اترك بوب ينقلها أولاً". التفكير في هذا ، أجابت ، "ابدأ الاستقبال!".
نظرًا لأن
قيمة الجيب في زمن الحرب يمكن أن تصل إلى أربعة ، فإن سرعة الصوت محدودة ، ويستغرق الأمر بعض الوقت لفهم ما سمعته أليس وبوب ، وحتى بوب ، كرجل نبيل ، يمكنه أن يستسلم للسيدة ، يتجاهل ويصرخ ، "أنا أبدأ الاستقبال!" ...
لتوضيح الغضب ، سوف نستخدم مخططات الوقت. الوقت يذهب اليهم.
القضية عندما لم يتفق أليس وبوب في الوقت المحدد:

الحالة التي فقدت فيها الرسالة:

هذا هو الفشل الذريع. يصبح كل شيء مشوشًا جدًا ويتفاقم بسبب حقيقة أن المرسل إليه يمكنه إما سماع أو عدم سماع أي من العبارات ، وفي كل حالة لا يعرف المحاور ما إذا كان المرسل إليه قد سمع رسالته.
الآن كل من أليس وبوب يتوقعون الترحيب. سيكون من المنطقي أن ندرك أن هناك تعارضًا قد حدث وأن هناك من يحتاج إلى استئناف الإرسال. ولكن ماذا لو حدث كل شيء مرة أخرى بطريقة جديدة؟ ونحن هنا مرة أخرى حيث بدأنا.
إذا كنت تعتقد أن الموقف نادر للغاية ، فتذكر آخر مرة تحدثت فيها إلى شخص ما عبر الصوت ، عندما يكون لدى المشترك أو أنت (أو كليهما) اتصال إنترنت بطيء. "مرحباً مرحباً ، أنت تختفي". "لا يمكنك سماع مرحبا مرحبا."
وفي الوقت نفسه ، في الخنادق ، فإن الوضع يتصاعد ، ويطالب القادة بإرسال التقارير.
حان الوقت
للانتقال إلى المصادر الأساسية: لدراسة ماركس ، ستعود
إنجلز قبل أكثر من 40 عامًا لترى كيف تم حل هذه المشكلات بواسطة مهندسي
DEC عند تصميم بروتوكول
DDCMP .
وفقًا لمطوري DDCMP ، تحتاج أليس وبوب إلى رفض العواطف وتصبح مثل
آلات الحالة المحدودة .
هذا يعني أنه من الآن فصاعدًا ، لن يكون لدى Alice و Bob سوى عدد قليل من الحالات الثابتة ، يمكن أن تحدث عمليات الانتقال بين هذه الحالات وفقًا لقواعد معينة عند حدوث أحداث معينة.
أولاً ، نذكر الدول ببساطة:
- -توقف
- البداية الأولية
- البدء المعترف به
- دوران
كما ترون ، هناك أربعة منهم فقط. والآن ، بغض النظر عن ما يحدث ، يعرف كل مشترك على الأقل بالتأكيد أن نظيره في واحدة من هذه الحالات فقط. في الواقع ، وبالنظر إلى المستقبل قليلاً ، سأقول أنه دائمًا ما يعرف أحد المشتركين الحالة التي
يدخل فيها المشترك الثاني ،
لكن هذا ليس دقيقًا .
دعونا نفكر في الولايات بشكل منفصل ، بالتفصيل
HALTED هي أبسط حالة ، لا أحد يذهب إلى أي مكان ، يبقى الجميع في أماكنهم ، لا يتم بث أي شيء ولا يتم استلامه ، يتم تجاهل أي منبهات خارجية. جميع ما عدا واحدة - إرادة السلطات العليا. في بروتوكول DDCMP الأصلي ، يمكن أن يكون الانتقال من حالة
HALTED في حالة
البدء الأولي بناءً على طلب المستخدم - تتلقى Alice أو Bob طلبًا لإنشاء اتصال.
ماذا يحدث عندما تتلقى أليس أو بوب مثل هذا الطلب؟
يلاحظون على الفور أن الدولة قد تغيرت من
HALTED إلى
START الأولية ، وهذا التحول ، مثل أي تحول آخر ، ينطوي على سلسلة محددة بدقة من الإجراءات. في هذه الحالة ، تحتاج إلى الصراخ "افعلها!" وضبط الساعة على مدار الساعة. هذا كل شيء.
لذلك ، صرخت أليس ما هو مطلوب منها ، وضغطت على زر على ساعة توقيت. الآن ، لفهم ما يمكن توقعه من بوب ، سنعرف ما الذي يمكن أن يحدث لأليس عندما تكون في حالة
البدء الأولي .
- منذ اللحظة التي لاحظت أليس مرور الوقت ، دعنا نقول 10 ثوانٍ ولم تسمع أي رد فعل من بوب (لاحظ ، أنا لا أقول إن بوب لم يصرخ لها شيئًا رداً على ذلك - هذا غير معروف ، لكن فقط أن أليس لا تعرف شيئًا سمعت خلال هذا الوقت ، أليس امرأة حكيمة وعقلانية وتعتمد فقط على الحقائق). نسمي هذا الحدث مهلة - تم تجاوز فترة الانتظار. في هذه الحالة ، يخبرنا البروتوكول أن نكرر: الصراخ "افعلها مرة واحدة!" والوقت مرة أخرى. ليس بعد سميكة.
- إذا سمعت أليس أن بوب صاح بنفس الشيء - "افعل مرة واحدة!" ، فانتقلت Alice بشكل
غير انتقائي إلى حالة
ACKNOWLEDGED START ، التي ينبغي لها أن تصرخ فورًا "DO TWO!" وضبط الساعة مرة أخرى.
- مرة أخرى ، إذا سمعت أليس من بوب "DO TWO!" ، فذهبت على الفور إلى حالة
RUNNING (!) ، صرخت "قبلت NOOOOOL!". إذا كانت ساعة توقيتها قد بدأت ، فتغلقها من مقدمة الحذر.
من المهم جدًا عدم القيام بأي حركات غير ضرورية لا توفرها الحالة الحالية. بغض النظر عن صرخات بوب ، بغض النظر عن مدى الشتم أو التسول ، تتفاعل أليس فقط كما هو متفق عليه.
يتم عرض مثل هذه الأشياء بشكل مريح في الجدول. لذلك ، دعنا نبدأ
بدولتي HALTED و
INITIAL START الموصوفتين بالفعل ، ثم سنقوم بتجديد الجدول أكثر.
لقد حذفت بوعي بعض النقاط من الوصف الأصلي لـ DDCMP - نحن لسنا بحاجة إليها ، لا نريد فقط تكرار DDCMP ، ولكن بناء على أساسها
هو نفسه ، فقط بروتوكول جديد
آخر .
ولكن العودة إلى وصف الدول والتحولات. الدولة التالية هي بداية
البدء .
في هذه الحالة ، كل ما يمكن أن يقلق أليس أو بوب هو:
- كما كان من قبل ، انتهاء وقت الانتظار ، في هذه الحالة ، تحتاج إلى البقاء في نفس الحالة ، تصرخ "DO TWO!" وابدأ المؤقت مرة أخرى
- المترجم "DO TWO!" يترجم إلى حالة التشغيل ، بينما يصرخ "يقبل NOOOOL!" ويوقف الموقت ؛
- يسمع "افعلها!" في نفس الحالة ، يجب أن تصرخ "افعلها!" وابدأ المؤقت ؛
- سمعت "قبول NOOOL!" - الانتقال إلى حالة التشغيل ، وإيقاف الموقت.
نضع كل ما سبق في جدول.
باستخدام المصافحة ، يصبح كل شيء جاهزًا تقريبًا - يبقى النظر في حالة
RUNNING واحدة فقط ، لأن أحد المشتركين يمكنه الدخول بالفعل ، والثاني - يركض بشكل عاجل إلى المرحاض ، وعندما يعود ، ينسى كل شيء ويحاول إنشاء اتصال جديد.
من وجهة نظر إجراء المصافحة (لم نتعامل بعد مع نقل البيانات ، الذي بدأ كل شيء - هذه قصة منفصلة) في حالة التشغيل ، نحن مهتمون بحدثين:
- إذا صرخوا لنا "افعلوها مرة واحدة!" - كل شيء سيء للغاية ، إنه مخطط كامل ، كل شيء يجب أن يبدأ من جديد. يرشدك البروتوكول الأصلي إلى الدخول ببساطة إلى حالة
HALTED . لكن هذا لن يساعدنا بأي شكل من الأشكال - إذا حدث هذا لسبب ما على اردوينو المتمتعة بالحكم الذاتي ، والذي ينقل بعض البيانات من بعض أجهزة الاستشعار ، فهذا بالنسبة لنا هو الفشل التام. كما نعلم ، من
HALTED ، يمكنك الذهاب إلى
البداية فقط بأمر من السلطات.
لذلك ، نحن نقوم بتعديل البروتوكول هنا: يجب أن يعمل الاستقبال في حالة
HALTED من القيادة "DO ONCE!" مثل أمر من السلطات - أي
قم بالتبديل إلى حالة
البدء المبدئي ، وأصرخ "افعلها مرة واحدة!" ، وابدأ الموقت. علاوة على ذلك ، في بعض الحالات يكون من المريح إصدار أمر بتأسيس الاتصال فور توفير الطاقة للذات.
وبالتالي ، الآن ، في الحالة الأكثر غير مريحة ، سيكون لدينا ببساطة إعادة تعيين الاتصال.
- الحدث الثاني الذي يجب الرد عليه في حالة
RUNNING - إذا سمعنا "DO TWO!" من خندق مجاور. هذا بالفعل أكثر إثارة للاهتمام. في هذه الحالة ، تحتاج إلى الصراخ "ACCEPTED ER!" حيث تشير ER إلى عدد الرسائل التي تم تلقيها بنجاح في جلسة الاتصال الحالية. هذا مفهوم جديد. فيما يلي سننظر في كل شيء بمزيد من التفصيل ، ولكن في الوقت الحالي ، سنقوم بإدخال كل شيء تعلمناه حتى اللحظة الحالية في جدول:
الآن ، إذا اتبعت Alice و Bob البروتوكول بشكل صارم ، فلن يكون لديهم أي خيارات
للدخول في شيء
غير مفهوم ، باستثناء كيفية إنشاء اتصال ، والتحول المشترك إلى حالة
RUNNING ، أو في حالة سيئة ، محاولة تأسيسه قبل
النقر على النصر.
يمكن للقارئ العدواني محاولة فرز جميع الخيارات والتوصل إلى استنتاج مفاده أن سلسلة الحالات والانتقالات تبين أنها مغلقة ومصممة بدقة. نحن (بمساعدة عقول مهندسي DEC) قمنا الآن بربط أليس وبوب بمجموعة من القواعد التي ببساطة عن طريق اتباعها ستؤسس اتصالًا ، إذا كان هذا ممكنًا بشكل عام في الظروف الحالية.
كيفية نقل البيانات الآن؟
حسنا ، كان ذلك تمرين لطيف. فترة باقة الحلوى في العلاقة بين العقدتين الشبكة. تذكر أننا بدأنا نشاطًا تجاريًا: نحتاج إلى نقل البيانات مع التسليم المضمون والأولوية! مع التعافي من الكوارث. إلى الحد الذي تسمح به موارد الأجهزة بهذا (بعد كل شيء ، قد يثبت كل من Alice و Bob أنهما ضعيفان في وحدات التحكم 8 بت مع 2 كيلو بايت من ذاكرة الوصول العشوائي!).
يعلمنا مهندسو DEC أن الرسائل التي نحتاج إلى ترقيمها ، نحتاج إلى حساب كمية الرسائل التي أرسلناها ، وعدد الرسائل التي تلقيناها وعدد الرسائل التي أرسلناها وصلت إلى المرسل إليه.
لقد حان الوقت لاستئصال!اعترف بذلك. عندما رأيت أسماء المتغيرات في وصف بروتوكول DDCMP ، قررت أنه لم يكن مصادفة: الأمريكيون مغرمون جدًا بجذب الاختصارات الجميلة من آذانهم.
لراحتنا ، هناك العديد من الموارد حيث يمكن للمهتمين بلمسة جميلة.
المفضل لدي هو هذا -
موقع مختصرات فلكية غبية أو مفرطة القسري (أو DOOFAAS)ما هي هذه الافتراءات يستحق!
هنا مثال:
WASP - مقياس تناظري واسع النطاق (ولكن ليس على الإطلاق ما فكرت به!)
ساورو - وحدة
المساحة الطيفية للأبحاث حول السدم البصري
CISCO - جهاز تصوير طيف بالأشعة تحت الحمراء مبرد وكاميرا لـ OHS (هذا ما يعنيه!)
وهنا ، فقط النار:
SQUIRT (أوه نعم ، المادة 18+!) - Satettile QUick Research Testbed
SHIT (لا أكثر ولا أقل!) - تلسكوب سوبر هيفي Interferometric ، مع نقش "ابحث عن نفسك" ، الذي يرتبط به الرابط إلى الملخص بالمادة التي تحمل الاسم نفسه.
لذلك ، يشار إلى المتغيرات التي تشير إلى عدد الحزم المستلمة والمرسلة والمسلمة على العقدة في الوصف الأصلي للبروتوكول باسم
RNA .
آه ، لماذا لم يذكروا البروتوكول بهذه الطريقة - RNA! وهناك نوع من شبكة الحمض النووي الريبي. كان لبروتوكولات DECnet كل فرصة في أن تصبح بروتوكولات إنترنت إذا كانت القصة قد خرجت بشكل مختلف.
لكن العودة إلى خنادقنا
يعرّف معيار البروتوكول الأصلي أن جميع العدادات هي 8 بت ومعيار الزيادة 256. وهذا يعني أنه يمكن أن يكون هناك حد أقصى قدره 256 من الرسائل المرسلة التي لم يتم استلام تأكيد لها بعد.
وإذا لم يتم استلام التأكيد ، فقد يحتاج الأمر إلى إعادة إرساله ، وإذا لزم الأمر ، فيجب تخزينه حتى التأكيد. بعد كل شيء ، لدينا ضمان التسليم!
المعلمات المادية لدينا أليس وبوب تملي علينا ظروف مختلفة. في Arduino ذي 8 بت ، لا يمكن تخزين هذه الكمية من البيانات ببساطة وعلينا التنازل عنها. وأنا لا أتحدث عن حقيقة أن طول الحزم (الرسائل) بالبايت في المعيار يقتصر على عدد 16 بت ، أي 64 كيلو بايت هو ترف غير مقبول!
لذلك ، تم تأسيس الاتصال. ما التالي؟
في اللحظة التي
تدخل فيها Alice أو Bob
إلى حالة
RUNNING ، تتم إعادة تعيين العدادات.
كما ذكرت من قبل ، فإن البروتوكول الأصلي يتضمن ترقيم الرسائل modulo 256 ، لكن يتعين علينا تقليل هذا العدد ليناسب مقدار الذاكرة الصغير في الأشياء المشابهة لـ Arduino.
حتى نتمكن من تحديد جميع الزيادات في العدادات فورًا ، سنقدم UMCP_PACKETS_NUMBER ثابتًا معينًا ، وستحدث الآن جميع الزيادات في هذه الوحدة.
إذا كنت تأخذ UMCP_PACKETS_NUMBER = 8 ، وكان الحد الأقصى لحجم الحزمة هو UMCP_PACKET_DATA_SIZE - تقتصر أجزاء البيانات التي يتم إرسالها في وقت ما على 64 بايت ، فسيتم احتواء كل شيء في Arduino UNO وسيظل قليلاً لاحتياجات المستخدم.
من المهم أن نتذكر أن كلا من هذه المعلمات يجب أن تكون هي نفسها لكلا الطرفين.
من الواضح ، الآن ، إذا نجحت Alice و Bob في إنشاء اتصال ، وكان أحدهما يحتاج إلى نقل البيانات ، فيجب أولاً تقسيم البيانات إلى أجزاء لا يتجاوز حجمها 64 بايت ، وثانياً ، يجب أن تحتوي كل حزمة أيضًا على حالة عدادان للمرسل: عدد الرسائل المستلمة والمرسلة (R و N).
انظر كم هو سهل الآن تنظيم ما يسمى ب خطوط الأنابيب ومدى سهولة التعامل مع حالات الخطأ!
إذا أرسلت Alice 3 حزم على التوالي مباشرة بعد إنشاء الاتصال ، فسيتم تعيين العداد R على 0 (لم تتلق بعد أي حزم) ، وستزيد العداد N بواحدة مع كل حزمة جديدة.
إذا قبل بوب جميعها بنجاح ، ثم لتأكيد استلام الحزم الثلاث جميعها ، فسيكون كافيًا أن يرسل تأكيدًا للحزمة الأخيرة فقط ، في الواقع ، إذا أرسل ببساطة حالة عداداته R = 3 و N = 0 ، فسوف تدرك Alice على الفور أن جميع الرسائل المرسلة وصلت رسائلها إلى المرسل إليه.
كانت حالة مثالية عندما لم تحدث أي قوة قاهرة. دعنا الآن ننظر إلى ما يمكن أن يحدث خطأ وكيفية التعامل معها.
إذا تخطى بوب الرزمة الأولى لسبب ما وقَبِل إحدى الرزم التالية ، عندها يلفت الانتباه على الفور إلى أن العداد N الموجود فيها (عدد الرزم التي ترسلها أليس) يتجاوز العداد R على جانب Bob ويدرك بوب بسهولة أنه فاته الحزمة الأولى . في هذه الحالة ، يحتاج فقط إلى لعب الكابتن Evidence الأكثر سطحية وإخبار Alice عن حالة عداد الحزم المستلمة (R = 0). تدرك أليس في نفس الوقت أنها N = 3 ، وأن Bob لديه R = 0 ، أي أنه من الضروري نقل الحزم بطريقة جديدة ، بدءًا من الأولى.
إذا نظرت إلى هذا المخطط بعناية ، يمكنك أن ترى أن أي نقل لحالة عداداته من قبل أي مشترك يخطره فورًا بنتيجة إرسال حزم البيانات ، والفرق بين العداد الذي تم إرساله من جانب وتلقيه من جهة أخرى يشير إلى عدد الحزم المفقودة و كم رقم بدأ من.
وهذا هو ، في أسوأ الحالات ، وجود إعادة إرسال كاملة للإرسال ، وفي المتوسط ، تزداد العداد A على جانب المرسل إلى قيمة العداد R على جانب الاستقبال ، و "إرسال" الرزم المفقودة.من السهل أن نفهم أنه بهذه الطريقة يتم الحفاظ على استمرارية زيادة العدادات ، مما يعني أن نقل الرسائل (الحزم) مضمون.بالإضافة إلى متغيرات RNA ، كل مشترك لديه علامتان SACK و SPEP. إذا تم تثبيت الأول ، فأنت بحاجة إلى إرسال تأكيد (إرسال إقرار) ، إذا كان الثاني - فأنت بحاجة إلى إرسال طلب تأكيد (إرسال الرد على رسالة).بالمناسبة ، تم تضمين إشارة أخرى في DDCMP الأصلي - SNAK (إرسال إقرار سلبي). يتضمن التثبيت الخاص به إرسال رسالة خطأ مع نوع من التعليمات البرمجية. ولكن في إصدارنا من البروتوكول ، سنحل جميع الأخطاء بشكل حصري باستخدام آلية المهلة ، لأنه يمكن استخدام البروتوكول ، على سبيل المثال ، في الاتصالات السونارية أو اللاسلكية في نطاق تردد شائع - ليس من المنطقي أن تسد البيئة المشتركة برموز الأخطاء.إذا تم استلام الرسالة مع وجود خطأ في تكاملها ، فبالتأكيد ستكون رسالة غير مقبولة.في هذه المرحلة ، يجب أن يكون للقارئ المتآكل شعور بأن هناك شيئًا مفقودًا. هناك خطأ ما في هذا المخطط النحيف. وهذا صحيح.
المزيد عن هذا في وقت لاحق.في غضون ذلك ، أقترح ، باتباع مثال عملية إعداد الاتصال ، جمع كل الأفكار المجزأة حول نقل البيانات إلى جدول.نظرًا لأن لدينا الآن حالة واحدة فقط ، فسيحتوي الجدول على عمودين فقط - الحدث والإجراءات الواجب اتخاذها. لتجنب الخلط بين أولئك الذين تنتمي إليهم المتغيرات ، نقوم بتمييز المتغيرات المحلية بفهرس L والمتغيرات المحذوفة (المتضمنة في الرسالة المستلمة مع فهرس R).الآن نلقي نظرة فاحصة ، انتقل من خلال الدائرة بأكملها في الرأس. نحن ندرك ما هو مفقود هنا.في الوصف الأصلي لـ DDCMP ، الذي غادرنا منه بشدة ، يُسمى هذا العلم SELECT - قد تكون "العقدة" (Alice أو Bob) "قد تم اختيارها".ما أربكنا هو أنه لم يتم السماح لأي آلية بالسماح بالنقل أو حظره.حسنًا ، ها هو: هذا هو العلم SELECT. يتم تطبيقه بكل بساطة: إذا تم تعيين العلم ، فإنه يمكن إرساله ، إن لم يكن ، فإنه لا يمكن.ACK REP . . «» , «», . , , , . ( ?).
, , — . — SELECT.
.
.
, !
Message Framing — .
, .
1. , R N . Arduino 8 . , , 4-.
:
= (RL & 0x0F) | (NL << 4);
وسوف نقرأ حالة العدادات مثل هذا:
NR = (c >> 4) & 0x0F; RR = c & 0x0F;
ج - بايت المقابلة من الرسالة
2. نتذكر أيضًا أن كل رسالة يجب أن تحتوي على حالة علامة SELECT. وأنواع الرسائل المختلفة نفسها ستكون:
هذا هو ، فقط 6 أنواع مختلفة من الرسائل. جميع الرسائل باستثناء DTA "تصدر" علامة SELECT - فهي تحتاج إلى استجابة فورية من المشترك عن بُعد ، وبدون علم لن يتمكن من إرسالها. لا تُرجع رسالة DTA إشارة لجعل خطوط الأنابيب ممكنة.
بشكل عام ، لدينا ما يكفي من 3 بتات لنوع الرسالة ، ولكن حتى لا نعالجها ، نخصص بايتًا بالكامل للنوع - في حالة المراجعة ، سنحصل على بعض حرية التصرف.
إذا كانت الرسالة تحتوي على بيانات ، فإننا نحتاج إلى نقل كميتها واختبارها. نظرًا لأن الحد الأقصى لحجم الحزمة هو 64 بايت ، فسوف نأخذ أيضًا بايت للاختباري وللطول - فجأة سيتعين عليك زيادة حجم الحزمة.
3. نحتاج أيضًا إلى بعض توقيع بداية الرسالة ومجموع اختباري منفصل للرأس.
مع وضع كل هذا في الاعتبار ، يبدو الرأس (ويعرف أيضًا باسم رسائل التحكم) كما يلي:
وكتلة البيانات مثل هذا:
هذا كل شيء. هذا وصف كامل للبروتوكول الذي حصلنا عليه من DDCMP.
الآن يمكنك الذهاب من خلال التنفيذ.
كيف يتم ترتيبها وكيفية استخدامها؟
أولا ، قليلا عن هيكل المستودع.
كما ذكرت في البداية ، يكمن رمز المشروع على github:
uMCPInoلمعرفة كيفية عمل كل شيء ، يمكنك تشغيل
تطبيق اختبار على جهاز كمبيوتر.
في الأرشيف ، قم بتشغيل uMCPIno_Test.exe ، حدد منفذ COM المطلوب وحاول كيفية عمله.
يمكنك التحقق من زوج من منافذ COM الافتراضية (عادة ما أفعل ذلك).
لماذا يمكنك تشغيل نسختين من التطبيق. لا تنس تشغيل "تم اختياره بواسطة DEFAULT" في نسخة واحدة - سيكون هذا Master ، وفي الآخر - قم بإيقاف تشغيله. بالمناسبة ، إذا كنت مهتمًا ، يمكنك معرفة ما يحدث إذا لم تلتزم بهذه القاعدة =)
يتيح لك خيار EXTRAS رؤية جميع حركات الأفكار داخل الدماغ للبروتوكول. سيتم عرض جميع التغييرات في حالة علامات SELECT ، والأحداث من أجهزة ضبط الوقت ، والتغيرات في حالة العقدة ، وكذلك قيم المتغيرات R و N في الرسائل المرسلة والمستلمة.
أقوم بتوصيل Arduino UNO بجهاز الكمبيوتر المحمول الخاص بي عبر محول UART <-> USB. تسمح لك موصلات الدبوس بمحاكاة فاصل الأسطر في أي وقت:

إذا قمت الآن بتشغيل التطبيق على الكمبيوتر المحمول ، ثم بعد الضغط على زر "الاتصال" ، ستقوم اردوينا بإنشاء اتصال:

وهذه هي الطريقة التي يتفاعل بها النظام مع محاولة الإرسال عبر خط "ممزق":

لتضمين uMCPIno في تطبيقك للكمبيوتر الشخصي:
- يحتوي المستودع على مكتبة uMCPIno. قم بتوصيله بمراجع مشروعك
- أنه يحتوي على فئة uMCPInoPort. نعلن مثاله:
uMCPInoPort port; port = new uMCPInoPort("COM1", UCNLDrivers.BaudRate.baudRate9600, true, 8100, 2000, 64, 8);
المعلمات بالترتيب: اسم المنفذ ، ثم سرعة المنفذ ، وحالة SELECT الافتراضية ، والفاصل الزمني لـ SELECT ، والفاصل الزمني للمهلة ، وحجم الحزمة ، والحد الأقصى لعدد الرسائل غير المعترف بها.
- اشترك في الأحداث:
عند تغيير علامة SELECT - port.Select:
OnSelectChangedEventHandler
عندما تتغير الحالة - port.State:
OnStateChangedEventHandler
يؤكد المضيف البعيد استلام الرمز:
OnDataBlockAcknowledgedEventHandler
متى تصل حزمة البيانات:
OnDataBlockReceivedEventHandler
- قبل العمل ، افتح المنفذ
port.Open();
- لإرسال البيانات ، نسميها الطريقة:
port.Send(byte[] data);
- عند الانتهاء ، أغلق المنفذ:
port.Close();
فقط أرسل وحدتي بايت!
الآن دعنا ننتقل إلى تنفيذ Arduino. يوجد مثالان في المجلد
github.com/AlekUnderwater/uMCPIno/tree/master/Arduinoالأول هو مجرد محول من وإلى uMCP. يخدم المسلسل الأول التواصل مع المضيف و Serial1 (إذا كان على لوحتك) أو SoftwareSerial على السنين 2 و 3 - للتواصل مع عقدة uMCPIno أخرى. يمكنك توصيل Bluetooth أو وحدة راديو هنا.
والثاني هو قالب مشروع مع دعم لبروتوكول uMCPIno
يحتوي كلا المشروعين على إعدادات حيث يمكنك ويجب عليك الصعود. ها هم:
الحالة الافتراضية للعلامة SELECT. إذا تم التعيين على (صواب) ، فحتى إذا لم تُرجع العقدة البعيدة العلامة ، فسيتم ضبطها على صواب بواسطة المؤقت.
#define CFG_SELECT_DEFAULT_STATE (false)
لتعيين فترة هذا المؤقت ، يوجد الإعداد التالي: الفاصل الزمني لإرجاع علامة SELECT بالمللي ثانية
#define CFG_SELECT_DEFAULT_INTERVAL_MS (4000)
الفاصل الزمني لانتظار استجابة بالمللي ثانية ، من الأفضل تركه أقل قليلاً من الفاصل الزمني لإرجاع علامة SELECT.
#define CFG_TIMEOUT_INTERVAL_MS (3000)
معدل باود الفعلي للخط. هذه المعلمة مطلوبة لتحديد وقت انتهاء النقل.
#define CFG_LINE_BAUDRATE_BPS (9600)
فاصل تراكم البيانات لخوارزمية Nagle. تأخذ بوقاحة ما يعادل 100 ميلي ثانية. خلال هذا الوقت ، ننتظر مجموعة من الحزم ، إذا لم تتم كتابتها ، فإننا نرسلها كما هي. تتمثل مهمة خوارزمية Nagle في تخليص شبكة كومة من الحزم الصغيرة من حجم واحد إلى عدة بايت.
#define CFG_NAGLE_DELAY_MS (100)
تقوم هذه الإعدادات بتعيين سرعات المنفذ للتواصل مع نظام التحكم (المضيف) والخط. لا تخلط بين سرعة المنفذ وخط معدل نقل فعلي.
#define CFG_HOST_CONNECTION_BAUDRATE_BPS (9600)
إذا تم تمكين هذا الإعداد ، فعندما يتم تزويد الطاقة بوحدة التحكم ، فإن البروتوكول نفسه سيأمر نفسه بالبدء في تأسيس اتصال.
#define CFG_IS_AUTOSTART_ON_POWERON (true)
هذا هو الحجم بالبايت من المخزن المؤقت لحزم البيانات الواردة.
#define CFG_IL_RING_SIZE (255)
بعد ذلك ، لنرى كيف تبدو حلقة المخطط الرئيسية:
void loop() { uMCP_ITimers_Process(); DC_Input_Process(); DC_Output_Process();
الآن دعونا نرى كيف يعمل البروتوكول. يوجد المنطق الرئيسي في الدالة uMCP_Protocol_Perform () ؛ هنا كودها:
void uMCP_Protocol_Perform() { if (state == uMCP_STATE_RUNNING) {
محلل حزمة الذي يعيش في وظيفة
On_NewByte_From_Line
مرتبة حسب مبدأ آلة الحالة المحدودة وتعمل "بايتة بايت". يتم ذلك من أجل حفظ الذاكرة.
بقية التنفيذ ليست ذات أهمية خاصة. من الأفضل تحليل كيفية تفاعل المستخدم مع البروتوكول. في هذا المثال ، هناك أربعة "نقاط اتصال".
الأول هو وظيفة إرسال البيانات على سطر uMCPIno:
bool uMCPIno_SendData(byte* dataToSend, byte dataSize);
كل شيء بسيط هنا - لديك dataToSend عازلة بايت ، وحجمها هو dataSize. تُرجع الدالة true إذا كان الإرسال ممكنًا (توجد مساحة لإضافة البيانات) ، وغير صحيحة.
من أجل عدم القيادة دون جدوى ، يمكنك على الفور التحقق من توفر مساحة كافية باستخدام الوظيفة:
bool uMCP_IsCanSend(byte dataSize);
لتحليل حزم البيانات الواردة ، تحتاج إلى إضافة التعليمات البرمجية الخاصة بك إلى نص الوظيفة
void USER_uMCPIno_DataPacketReceived();
تتم كتابة البيانات الواردة إلى المخزن المؤقت الدائري il_ring. يمكن أن تنظم القراءة منه بايت مثل هذا:
while (il_Cnt > 0) { c = il_ring[il_rPos]; il_rPos = (il_rPos + 1) % CFG_IL_RING_SIZE; il_Cnt--;
للمتعة المتطورة هناك وظيفة
void USER_uMCP_OnTxBufferEmptry();
وهو ما يسمى عندما يتم إرسال جميع البيانات بنجاح. من الممكن أيضًا وضروريًا وضع رمز ما فيه.
لماذا هذا كل شيء وأين؟
تعاملت بشكل رئيسي مع فقط للمتعة. بالإضافة إلى ذلك ، كنت بحاجة إلى بروتوكول بسيط ، والأهم من ذلك ، "خفيف الوزن" لإرسال البيانات من خلال أجهزة المودم سونار
uWAVE الخاصة بنا. نظرًا لأنهم ينقلون البيانات عبر المياه بسرعة 80 بت في الثانية فقط ، وبمدى اتصال أقصى يبلغ 1000 متر وسرعة الصوت في الماء حوالي 1500 م / ث ، فإن النقل يرتبط بتأخيرات ملحوظة ، وهناك قناة سونار واحدة فقط (إن لم تكن الأكثر !) من صاخبة ، أبطأ وغير مستقر.
بسبب هذا إلى حد كبير ، اضطررت إلى التخلي عن آلية الاعتراف السلبي (NAK) - إذا كان من الممكن عدم النقل - في الماء فمن الأفضل عدم نقل 100 ٪.
في الواقع ، أصبح البروتوكول مفيدًا عند نقل البيانات عبر قناة راديو باستخدام وحدات
DORJI و
NS-012 المعروفة باسم arduinoes.
ما التالي؟
إذا كان هناك وقت ، فأنا أخطط لإضافة إمكانية معالجة (والتي ، بالمناسبة ، كانت في DDCMP). نظرًا لأن المهمة الرئيسية لهذا البروتوكول الآن هي توفير الراحة لجميع أنواع اختبارات أجهزة المودم سونار وشبكات Sensors الأخرى ، فهناك مطبات (حرفيًا) هناك. لا يمكنني إلا أن أقول إن المشكلة لا يمكن حلها عن طريق إضافة حقلي "المرسل" و "الهدف".
ربما يتعلق الأمر بالتوجيه
الجغرافي وكل موسيقى الجاز هذه.
PS
تقليديًا ، سأكون ممتنًا جدًا للنقد البناء والرغبات والاقتراحات. من المهم دائمًا أن تفهم ما إذا كنت تفعل شيئًا مفيدًا للناس أو تضيع الوقت.
ربما ، في محاولة لتجنب انتقال هذا longread إلى رواية "الحرب والسلام" ، فاتني بعض التفاصيل - لا تتردد في طرحها.
PPS
شكرا جزيلا للعار على أمي ، مشيرا إلى الأخطاء (النحوية والمنطقية):
كان المشروع في الأصل مفتوح المصدر ، ولكن الآن المقال مفتوح المصدر أيضًا.