الإنجليزيةالفرنسيةالإسبانية

OnWorks فافيكون

ns-3-manual - عبر الإنترنت في السحابة

قم بتشغيل دليل ns-3-manual في مزود استضافة OnWorks المجاني عبر Ubuntu Online أو Fedora Online أو محاكي Windows عبر الإنترنت أو محاكي MAC OS عبر الإنترنت

هذا هو الأمر ns-3-manual الذي يمكن تشغيله في مزود الاستضافة المجانية OnWorks باستخدام إحدى محطات العمل المجانية المتعددة على الإنترنت مثل Ubuntu Online أو Fedora Online أو محاكي Windows عبر الإنترنت أو محاكي MAC OS عبر الإنترنت

برنامج:

اسم


دليل ns-3 - دليل ns-3

هذا هو NS-3 مانيوال. الوثائق الأولية لمشروع ns-3 متاحة في خمسة
نماذج:

· NS-3 Doxygen: توثيق واجهات برمجة التطبيقات العامة لجهاز المحاكاة

· تعليمي ، دليل (هذه وثيقة)، والمكتبة النموذجية لـ آخر الافراج عن
تطوير شجرة

· NS-3 ويكي

المحتويات


منظمة
يصف هذا الفصل بشكل عام NS-3 تنظيم البرمجيات وما يقابلها
تنظيم هذا الدليل.

NS-3 هو عبارة عن محاكي شبكة حدث منفصل يكون فيه جوهر المحاكاة والنماذج
تم تنفيذه في C ++. NS-3 تم بناؤه كمكتبة قد تكون ثابتة أو ديناميكية
مرتبط ببرنامج رئيسي C ++ الذي يحدد طوبولوجيا المحاكاة ويبدأ في
جهاز محاكاة. NS-3 تقوم أيضًا بتصدير جميع واجهات برمجة التطبيقات الخاصة بها تقريبًا إلى Python ، مما يسمح لبرامج Python بالعمل
استيراد وحدة "ns3" بنفس طريقة استيراد ملف NS-3 المكتبة مرتبطة بالملفات التنفيذية
في C ++.
[صورة] تنظيم برمجيات NS-3.إلغاء المسافة البادئة

الكود المصدري لـ NS-3 يتم تنظيمه في الغالب في SRC الدليل ويمكن وصفه
من خلال الرسم التخطيطي في تطبيقات الكمبيوتر منظمة of NS-3. سنعمل طريقنا من القاع
أعلى؛ بشكل عام ، تحتوي الوحدات النمطية فقط على تبعيات على الوحدات الموجودة تحتها في الشكل.

نصف أولاً جوهر جهاز المحاكاة ؛ تلك المكونات المشتركة بين الجميع
البروتوكول والأجهزة والنماذج البيئية. يتم تنفيذ جوهر المحاكاة في
src / الأساسية. الحزم هي كائنات أساسية في محاكي الشبكة ويتم تنفيذها في
src / الشبكة. تم تصميم وحدتي المحاكاة في حد ذاتهما لتشكيل a
نواة محاكاة عامة يمكن استخدامها بواسطة أنواع مختلفة من الشبكات ، وليس فقط
الشبكات القائمة على الإنترنت. الوحدات المذكورة أعلاه من NS-3 مستقلة عن شبكة معينة
وطرازات الأجهزة ، التي تم تناولها في الأجزاء اللاحقة من هذا الدليل.

بالإضافة إلى ما سبق NS-3 الأساسية ، نقدمها أيضًا في الجزء الأول من
يدوي ، وحدتان أخريان تكملان واجهة برمجة التطبيقات الأساسية القائمة على C ++. NS-3 يجوز للبرامج
الوصول إلى كل واجهة برمجة التطبيقات مباشرة أو قد تستخدم ما يسمى ب المساعد API الذي يوفر
أغلفة مريحة أو تغليف لمكالمات API ذات المستوى المنخفض. حقيقة ان NS-3 برامج
يمكن كتابتها إلى اثنين من واجهات برمجة التطبيقات (أو مزيج منها) هو جانب أساسي من
محاكاة. نصف أيضًا كيف يتم دعم بايثون في NS-3 قبل الانتقال إلى ما هو محدد
نماذج ذات صلة بمحاكاة الشبكة.

يركز باقي الدليل على توثيق النماذج ودعمها
قدرات. يركز الجزء التالي على شيئين أساسيين في NS-3: ال العقدة
NetDevice. تم تصميم نوعين خاصين من NetDevice لدعم استخدام محاكاة الشبكة
الحالات ، والمضاهاة موصوفة بعد ذلك. الفصل التالي مكرس ل
النماذج المتعلقة بالإنترنت ، بما في ذلك مآخذ التوصيل API التي تستخدمها تطبيقات الإنترنت. ال
يغطي الفصل التالي التطبيقات ، ويصف الفصل التالي الدعم الإضافي
للمحاكاة ، مثل الرسوم المتحركة والإحصاءات.

يحتفظ المشروع بدليل منفصل مخصص للاختبار والتحقق من صحة NS-3 الكود
(انظر NS-3 الاختبار التحقق كتيب).

عشوائية المتغيرات
NS-3 يحتوي على مولد رقم عشوائي زائف مدمج (PRNG). من المهم ل
المستخدمين الجادين للمحاكي لفهم الوظائف والتكوين والاستخدام
من PRNG هذا ، ولتحديد ما إذا كان كافياً لاستخدامه البحثي.

سريع نظرة عامة
NS-3 يتم توفير أرقام عشوائية عبر حالات ns3 :: RandomVariableStream.

· بشكل افتراضي، NS-3 تستخدم المحاكاة بذرة ثابتة ؛ إذا كان هناك أي عشوائية في
المحاكاة ، فإن كل تشغيل من البرنامج سيؤدي إلى نتائج متطابقة ما لم تكن البذور و / أو
تم تغيير رقم التشغيل.

· في NS-3.3 وقبل ذلك ، NS-3 استخدمت عمليات المحاكاة بذرة عشوائية بشكل افتراضي ؛ هذا يمثل أ
تغيير في السياسة بدءًا من NS-3.4.

· في NS-3.14 وقبل ذلك ، NS-3 استخدمت عمليات المحاكاة فئة غلاف مختلفة تسمى
NS3 :: RandomVariable. اعتبارا من NS-3.15، تم استبدال هذا الفصل بـ
ns3 :: RandomVariableStream؛ لم يقم مولد الرقم العشوائي الزائف الأساسي
تغيرت.

· للحصول على العشوائية عبر عمليات محاكاة متعددة ، يجب عليك إما تعيين البذور
بشكل مختلف أو قم بتعيين رقم التشغيل بشكل مختلف. لتعيين بذرة ، اتصل
ns3 :: RngSeedManager :: SetSeed () في بداية البرنامج ؛ لتعيين رقم التشغيل مع
نفس البذرة ، اتصل ns3 :: RngSeedManager :: SetRun () في بداية البرنامج ؛ يرى
خلق عشوائية المتغيرات.

كل RandomVariableStream المستخدمة في NS-3 لديه مولد رقم عشوائي افتراضي مرتبط
معها تستخدم جميع المتغيرات العشوائية إما بذرة ثابتة أو عشوائية بناءً على استخدام
البذور العالمية (النقطة السابقة) ؛

· إذا كنت تنوي تنفيذ عدة عمليات تشغيل لنفس السيناريو ، ولكن بشكل عشوائي مختلف
الأرقام ، يرجى التأكد من قراءة القسم الخاص بكيفية إجراء النسخ المستقلة:
خلق عشوائية المتغيرات.

اقرأ المزيد لمزيد من الشرح حول خاصية الأرقام العشوائية لـ NS-3.

خلفيّة
تستخدم المحاكاة الكثير من الأرقام العشوائية ؛ وجدت إحدى الدراسات أن معظم عمليات محاكاة الشبكة
تنفق ما يصل إلى 50٪ من وحدة المعالجة المركزية في توليد أرقام عشوائية. يحتاج مستخدمو المحاكاة إلى أن يكونوا كذلك
تهتم بجودة الأرقام العشوائية (الزائفة) والاستقلال بينها
تيارات مختلفة من الأرقام العشوائية.

يحتاج المستخدمون إلى الاهتمام ببعض المشكلات ، مثل:

· بذر مولد الأعداد العشوائية وما إذا كانت نتيجة المحاكاة كذلك
حتمية أم لا ،

· كيفية الحصول على تيارات مختلفة من الأرقام العشوائية المستقلة عن واحد
آخر و

· كم من الوقت تستغرق تيارات دورة

سنقدم هنا بعض المصطلحات: يوفر RNG سلسلة طويلة من العشوائية (الزائفة)
أعداد. طول هذا التسلسل يسمى دورة الطول or فترة، وبعد ذلك
سيعيد RNG نفسه. يمكن تقسيم هذا التسلسل إلى مفككة تيارات. A
تيار RNG هو مجموعة فرعية أو فدرة متجاورة من تتابع RNG. على سبيل المثال ، إذا كان
يبلغ طول فترة RNG N ، ويتم توفير دفقين من RNG هذا ، ثم الأول
قد يستخدم الدفق قيم N / 2 الأولى وقد ينتج التيار الثاني N / 2 الثانية
قيم. خاصية مهمة هنا هي أن الدفقين غير مرتبطين. على نفس المنوال،
يمكن تقسيم كل دفق بشكل منفصل إلى عدد غير مرتبط دريمات فرعية.
من المأمول أن ينتج RNG الأساسي تسلسلًا شبه عشوائي من الأرقام بطول طويل جدًا
طول الدورة ، ويقسم هذا إلى تيارات وتيارات فرعية بطريقة فعالة.

NS-3 يستخدم نفس مولد الأرقام العشوائي الأساسي كما يفعل NS-2: MRG32k3a
مولد من بيير ليكوييه. يمكن العثور على وصف مفصل في
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf. مولد MRG32k3a
يوفر 1.8 × 10 ^ {19} تدفقات مستقلة من الأرقام العشوائية ، يتكون كل منها من
2.3x10 ^ {15} دريمات فرعية. كل تيار فرعي له فترة (أي، وهو عدد الأرقام العشوائية
قبل التداخل) 7.6x10 ^ {22}. فترة المولد بالكامل هي 3.1 × 10 ^ {57}.

مبوبة ns3 :: RandomVariableStream هي الواجهة العامة لهذا الرقم العشوائي الأساسي
مولد كهرباء. عندما ينشئ المستخدمون متغيرات عشوائية جديدة (مثل ns3 :: UniformRandomVariable,
ns3 :: ExponentialRandomVariable، وما إلى ذلك) ، يقومون بإنشاء كائن يستخدم أحد
تيارات متميزة ومستقلة لمولد الأرقام العشوائية. لذلك ، كل كائن من
نوع ns3 :: RandomVariableStream لديها ، من الناحية المفاهيمية ، RNG "الافتراضية" الخاصة بها. بالإضافة إلى،
كل ns3 :: RandomVariableStream يمكن تهيئتها لاستخدام إحدى مجموعات الدارات الفرعية المرسومة
من التيار الرئيسي.

سيكون التنفيذ البديل هو السماح لكل RandomVariable بأن يكون له خاصته
(مصنفة بشكل مختلف) RNG. ومع ذلك ، لا يمكننا أن نضمن بقوة أن الاختلاف
التسلسلات ستكون غير مرتبطة في مثل هذه الحالة ؛ ومن ثم ، فإننا نفضل استخدام RNG واحد و
تيارات وتيارات فرعية منه.

خلق عشوائية المتغيرات
NS-3 يدعم عددًا من الكائنات المتغيرة العشوائية من الفئة الأساسية
بث عشوائي متغير. هذه الأشياء مستمدة من ns3 :: الكائن ويتم التعامل معها من قبل شركة ذكية
مؤشرات.

الطريقة الصحيحة لإنشاء هذه الكائنات هي استخدام القوالب CreateObject <> الأسلوب،
مثل:

Ptr س = CreateObject () ؛

ثم يمكنك الوصول إلى القيم عن طريق استدعاء طرق على الكائن مثل:

myRandomNo = x-> GetInteger () ،

إذا حاولت بدلاً من ذلك القيام بشيء مثل هذا:

myRandomNo = UniformRandomVariable (). GetInteger () ،

سيواجه برنامجك خطأ تجزئة ، لأن التنفيذ يعتمد عليه
بعض بناء السمة التي تحدث فقط عندما CREATEOBJECT يسمى.

يناقش الكثير من الجزء المتبقي من هذا الفصل الآن خصائص تيار
الأرقام العشوائية الزائفة المتولدة من مثل هذه الأشياء ، وكيفية التحكم في نثرها
شاء.

زراعة مستقل التكرارات
NS-3 يمكن تكوين عمليات المحاكاة لإنتاج نتائج حتمية أو عشوائية. إذا كان
NS-3 تم تكوين المحاكاة لاستخدام بذرة ثابتة وحتمية مع نفس رقم التشغيل ،
يجب أن يعطي نفس الإخراج في كل مرة يتم تشغيله.

افتراضيا، NS-3 تستخدم عمليات المحاكاة رقمًا أوليًا وتشغيلًا ثابتًا. يتم تخزين هذه القيم في
اثنان ns3 :: GlobalValue الأمثلة: g_rng البذور g_rng تشغيل.

حالة الاستخدام النموذجية هي تشغيل محاكاة كسلسلة من التجارب المستقلة ، وذلك من أجل
إحصائيات على عدد كبير من عمليات التشغيل المستقلة. يمكن للمستخدم إما تغيير ملف
البذور العالمية وإعادة تشغيل المحاكاة ، أو يمكن أن تقدم حالة التيار الفرعي لـ RNG ، والتي
يشار إلى زيادة رقم التشغيل.

صف ns3 :: RngSeedManager يوفر API للتحكم في عدد البذر والتشغيل
سلوك. يجب استدعاء إعداد حالة البذر والدفق الفرعي هذا قبل أي إعداد عشوائي
يتم إنشاء المتغيرات ؛ على سبيل المثال:

RngSeedManager :: SetSeed (3) ، // يغير البذور من 1 إلى 3
RngSeedManager :: SetRun (7) ، // تغيير رقم التشغيل من الافتراضي من 1 إلى 7
// الآن ، أنشئ متغيرات عشوائية
Ptr س = CreateObject () ؛
Ptr y = CreateObject () ؛


أيهما أفضل ، وضع بذرة جديدة أم دفع حالة التيار الفرعي؟ لا يوجد
تضمن عدم تداخل التيارات التي تنتجها بذرتان عشوائيتان. الطريقة الوحيدة
ضمان عدم تداخل دفقين هو استخدام قدرة التيار الفرعي التي يوفرها
تنفيذ RNG. ولذلك، تستخدم هيه تيار فرعي قدرة إلى إنتاج متعدد
مستقل يدير of هيه نفسه محاكاة. بعبارة أخرى ، كانت أكثر صرامة من الناحية الإحصائية
طريقة تكوين عدة نسخ مستقلة هي استخدام أصل ثابت والمضي قدمًا
رقم التشغيل. يسمح هذا التنفيذ بحد أقصى 2.3 × 10 ^ {15} بشكل مستقل
مكررات باستخدام التدفقات الفرعية.

لسهولة الاستخدام ، ليس من الضروري التحكم في عدد البذور والتشغيل من داخل
برنامج؛ يمكن للمستخدم ضبط NS_GLOBAL_VALUE متغير البيئة كالتالي:

$ NS_GLOBAL_VALUE = "RngRun = 3". / waf - اسم برنامج التشغيل

هناك طريقة أخرى للتحكم في هذا من خلال تمرير حجة سطر الأوامر ؛ لأن هذا هو ملف NS-3
مثيل GlobalValue ، يتم إجراؤه بشكل مكافئ على النحو التالي:

$ ./waf --command-template = "٪ s --RngRun = 3" - اسم برنامج التشغيل

أو إذا كنت تقوم بتشغيل برامج خارج واف مباشرة:

$ ./build/optimized/scratch/program-name --RngRun = 3

تسهل متغيرات سطر الأوامر المذكورة أعلاه تشغيل الكثير من عمليات التشغيل المختلفة من shell
البرنامج النصي عن طريق تمرير مؤشر RngRun مختلف.

مبوبة بث عشوائي متغير
يجب اشتقاق جميع المتغيرات العشوائية من الصنف عشوائي متغير. توفر هذه الفئة الأساسية ملف
طرق قليلة لتكوين سلوك مولد الأرقام العشوائية عالميًا. مشتق
توفر الفئات API لرسم متغيرات عشوائية من التوزيع المعين
أيد.

يتم إعطاء كل بث عشوائي تم إنشاؤه في المحاكاة مولدًا جديدًا
تدفق RNG من PRNG الأساسي. بهذه الطريقة ، يتم تطبيق L'Ecuyer
يسمح بحد أقصى 1.8 × 10 ^ 19 متغير عشوائي. كل متغير عشوائي في واحد
يمكن أن ينتج عن النسخ المتماثل ما يصل إلى 7.6 × 10 ^ 22 رقمًا عشوائيًا قبل التداخل.

الفئة الأساسية فئة جمهور API
فيما يلي مقتطفات من بعض الطرق العامة للفصل الدراسي بث عشوائي متغير التي تصل إلى
القيمة التالية في التدفق الفرعي.

/ **
* \ brief إرجاع مضاعف عشوائي من التوزيع الأساسي
* \ إرجاع قيمة عشوائية للفاصلة العائمة
*/
مضاعفة GetValue (void) const ؛

/ **
* \ brief إرجاع عدد صحيح عشوائي من التوزيع الأساسي
* \ Return caster cast of :: GetValue ()
*/
uint32_t GetInteger (باطل) const ؛

لقد وصفنا بالفعل تكوين البذر أعلاه. متغير عشوائي مختلف
قد تحتوي الفئات الفرعية على واجهة برمجة تطبيقات إضافية.

الأنواع of المتغيرات العشوائية
يتم توفير الأنواع التالية من المتغيرات العشوائية ، وهي موثقة في ملف NS-3
Doxygen أو عن طريق القراءة src / core / model / random-variable-stream.h. يمكن للمستخدمين أيضًا إنشاء ملفات
المتغيرات العشوائية المخصصة الخاصة بهم من خلال الاشتقاق من الفئة بث عشوائي متغير.

· فصل منتظم عشوائي متغير

· فصل ثابت عشوائي متغير

· فصل متسلسل عشوائي متغير

· فصل أسي عشوائي متغير

· فصل ParetoRandomVariable

· فصل متغير عشوائي

· فصل عادي عشوائي متغير

· فصل تسجيل عادي عشوائي متغير

· فصل غاما عشوائي متغير

· فصل إرلانج عشوائي متغير

· فصل مثلث عشوائي متغير

· فصل Zipf عشوائي متغير

· فصل ZetaRandomVariable

· فصل متغير عشوائي

· فصل المتغير العشوائي التجريبي

دلالات of بث عشوائي متغير الأجسام
يتم اشتقاق كائنات RandomVariableStream من ns3 :: الكائن ويتم التعامل معها بواسطة مؤشرات ذكية.

يمكن أيضًا استخدام مثيلات RandomVariableStream في ملفات NS-3 الصفات ، مما يعني ذلك
يمكن تعيين القيم لهم من خلال NS-3 نظام السمة. مثال في
نماذج الانتشار لجهاز WifiNet:

النوع
RandomPropagationDelayModel :: GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("ns3 :: RandomPropagationDelayModel")
.SetParent ()
.AddConstructor ()
.AddAttribute ("متغير"،
"المتغير العشوائي الذي يولد تأخيرات (تأخيرات) عشوائية" ،
StringValue ("ns3 :: UniformRandomVariable") ،
MakePointerAccessor (& RandomPropagationDelayModel :: m_variable) ،
MakePointerChecker ())
;
عودة المد
}

هنا، و NS-3 يمكن للمستخدم تغيير المتغير العشوائي الافتراضي لنموذج التأخير هذا (وهو
a UniformRandomVariable يتراوح من 0 إلى 1) من خلال نظام السمة.

باستخدام آخر برنج
لا يوجد حاليًا أي دعم لاستبدال رقم عشوائي أساسي مختلف
مولد (على سبيل المثال ، مكتبة GNU العلمية أو حزمة Akaroa). البقع هي موضع ترحيب.

الضبط هيه مجرى عدد
يوفر مولد MRG32k3a الأساسي 2 ^ 64 تدفقات مستقلة. في ns-3 ، هذه هي
يتم تعيينها بالتتابع بدءًا من التدفق الأول كمثيلات RandomVariableStream جديدة
إجراء مكالمتهم الأولى إلى GetValue ().

كنتيجة لكيفية تعيين كائنات RandomVariableStream هذه إلى التدفقات الأساسية ،
التخصيص حساس لاضطرابات تكوين المحاكاة. ال
والنتيجة هي أنه إذا تم تغيير أي جانب من جوانب تكوين المحاكاة ، فإن التعيين
من RandomVariables إلى التدفقات قد (أو لا تتغير).

كمثال ملموس ، قد يقوم المستخدم بإجراء دراسة مقارنة بين بروتوكولات التوجيه
تجد أن إجراء تغيير بروتوكول توجيه لآخر سيلاحظ أن
تغير نمط التنقل الأساسي أيضًا.

بدءًا من ns-3.15 ، تم توفير بعض التحكم للمستخدمين للسماح للمستخدمين بذلك
حدد اختياريا تعيين كائنات RandomVariableStream المحددة إلى الأساسي
تيارات. هذا ال شريط الاحداث السمة ، وهي جزء من الفئة الأساسية RandomVariableStream.

بتقسيم التسلسل الحالي للتيارات من قبل:

<------------------------------------------------- ------------------------->
تيار 0 تيار (2 ^ 64 - 1)

إلى مجموعتين متساويتين الحجم:

<------------------------------------------------- ------------------------->
^ ^ ^ ^
| || |
تيار 0 تيار (2 ^ 63-1) تيار 2 ^ 63 تيار (2 ^ 64 - 1)
<- تم تعيينه تلقائيًا -----------> <- تم تعيينه بواسطة المستخدم ----------------->

يستمر تعيين أول 2 ^ 63 تدفقات تلقائيًا ، بينما يتم تعيين آخر 2 ^ 63 تدفقات
مؤشرات تيار معينة تبدأ بصفر حتى 2 ^ 63-1.

إن تخصيص التدفقات إلى رقم تيار ثابت اختياري ؛ حالات
سيتم تعيين RandomVariableStream الذي لم يتم تعيين قيمة دفق له على التالي
واحد من مجموعة التدفقات التلقائية.

لإصلاح RandomVariableStream لتيار أساسي معين ، قم بتعيين شريط الاحداث
السمة إلى عدد صحيح غير سالب (القيمة الافتراضية -1 تعني أن القيمة ستكون
تم تخصيصه تلقائيًا).

نشر لك النتائج
عندما تنشر نتائج المحاكاة ، فهي جزء أساسي من معلومات التكوين
يجب أن تذكر دائمًا كيفية استخدامك لمولد الأرقام العشوائية.

· ما البذور التي استخدمتها ،

· ما هو RNG الذي استخدمته إن لم يكن الافتراضي ،

· كيف تم إجراء عمليات التشغيل المستقلة ،

· بالنسبة لعمليات المحاكاة الكبيرة ، كيف تأكدت من عدم قيامك بالدوران.

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

الملخص
دعنا نراجع الأشياء التي يجب عليك فعلها عند إنشاء محاكاة.

· قرر ما إذا كنت تعمل ببذرة ثابتة أم بذرة عشوائية. البذرة الثابتة هي
إفتراضي،

· قرر كيف ستدير عمليات التكرار المستقلة ، إن أمكن ،

· أقنع نفسك أنك لا ترسم قيمًا عشوائية أكثر من طول الدورة ، إذا
تقوم بتشغيل محاكاة طويلة جدًا ، و

· عند النشر ، اتبع الإرشادات أعلاه حول توثيق استخدامك للعشوائية
مولد الرقم.

مزيج وظائف
NS-3 يوفر واجهة عامة لوظائف التجزئة للأغراض العامة. في أبسط
الاستخدام ، تقوم دالة التجزئة بإرجاع التجزئة 32 بت أو 64 بت لمخزن البيانات أو السلسلة.
وظيفة التجزئة الأساسية الافتراضية هي همهمة 3، تم اختياره لأنه يحتوي على وظيفة تجزئة جيدة
الخصائص ويقدم إصدار 64 بت. الموقر FNV1a التجزئة متاحة أيضًا.

هناك آلية مباشرة لإضافة (أو توفير في وقت التشغيل) تجزئة بديلة
تطبيقات الوظيفة.

Basic الأستعمال
إن أبسط طريقة للحصول على قيمة تجزئة لمخزن بيانات أو سلسلة هي فقط:

# تضمين "ns3 / hash.h"

باستخدام مساحة الاسم ns3 ؛

شار * عازلة = ...
size_t buffer_size = ...

uint32_t buffer_hash = Hash32 (المخزن المؤقت ، حجم المخزن المؤقت) ؛

الأمراض المنقولة جنسيا :: سلسلة s ؛
uint32_t string_hash = Hash32 (s) ،

يتم تحديد الوظائف المكافئة لقيم تجزئة 64 بت.

تزايدي تجزئة
في بعض الحالات ، من المفيد حساب تجزئة العديد من المخازن المؤقتة ، كما لو كانت كذلك
تم ضمهم معًا. (على سبيل المثال ، قد ترغب في تجزئة تدفق الحزمة ، ولكن لا تريد ذلك
تريد تجميع مخزن مؤقت واحد مع المحتويات المدمجة لجميع الحزم.)

يعد هذا أمرًا مباشرًا تقريبًا مثل المثال الأول:

# تضمين "ns3 / hash.h"

باستخدام مساحة الاسم ns3 ؛

شار * عازلة
حجم_حجم_المخزن المؤقت ؛

حشر حشر // استخدم وظيفة التجزئة الافتراضية

ل ( )
{
المخزن المؤقت = get_next_buffer () ،
التجزئة (المخزن المؤقت ، حجم_المخزن) ؛
}
uint32_t Combined_hash = hasher.GetHash32 () ،

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

hasher.clear () .GetHash32 (المخزن المؤقت ، حجم المخزن المؤقت) ؛

يؤدي هذا إلى إعادة تهيئة الحالة الداخلية قبل تجزئة المخزن المؤقت.

باستخدام an البديل مزيج الوظيفة
وظيفة التجزئة الافتراضية هي همهمة 3. FNV1a متاح أيضا. لتحديد التجزئة
تعمل بشكل صريح ، استخدم هذا المُنشئ:

Hasher hasher = Hasher (Create ()) ؛

إضافة جديد مزيج الوظيفة تطبيقات
لإضافة وظيفة التجزئة فواتبع تجزئة نفخة 3.h/. سم مكعب نمط:

· إنشاء إعلان فئة (.h) وتعريف (. سم مكعب) يرث من
الهاش :: التنفيذ.

· تتضمن الإعلان في هاش (عند النقطة حيث تجزئة نفخة 3.h متضمن.

في التعليمات البرمجية الخاصة بك ، قم بإنشاء مثيل لـ حشر كائن عبر المنشئ حشر
(Ptr ())

إذا كانت وظيفة التجزئة الخاصة بك هي وظيفة واحدة ، على سبيل المثال التجزئة، فلن تحتاج حتى إلى إنشاء ملف
فئة جديدة مشتقة من الهاش.

حشر hasher =
حشر (إنشاء (& hashf)) ؛

لتجميع هذا ، ملفك التجزئة يجب أن يتطابق مع أحد توقيعات مؤشر الوظيفة:

typedef uint32_t (* Hash32Function_ptr) (const char *، const size_t) ؛
typedef uint64_t (* Hash64Function_ptr) (const char *، const size_t) ؛

مصادر لـ مزيج وظائف
تتضمن مصادر تطبيقات دالة التجزئة الأخرى ما يلي:

· بيتر كانكوفسكي: http://www.strchr.com

أراش بارتو: http://www.partow.net/programming/hashfunctions/index.html

· إس إم هاشر: http://code.google.com/p/smhasher/

· سنمايسه: http://www.sanmayce.com/Fastest_Hash/index.html

فعاليات محاكاة
NS-3 هو جهاز محاكاة شبكة الأحداث المنفصلة. من الناحية المفاهيمية ، يتتبع جهاز المحاكاة ملف
عدد الأحداث المجدولة للتنفيذ في وقت محاكاة محدد. وظيفة
المحاكي هو تنفيذ الأحداث بترتيب زمني متسلسل. بمجرد الانتهاء من
حدث ما ، سينتقل المحاكي إلى الحدث التالي (أو سيخرج إذا لم يكن هناك
المزيد من الأحداث في قائمة انتظار الحدث). إذا ، على سبيل المثال ، حدث مجدول لوقت المحاكاة
يتم تنفيذ "100 ثانية" ، ولم تتم جدولة الحدث التالي حتى "200 ثانية" ، فإن
سينتقل المحاكي فورًا من 100 ثانية إلى 200 ثانية (من وقت المحاكاة) إلى
تنفيذ الحدث التالي. هذا هو المقصود بمحاكاة "الحدث المنفصل".

لتحقيق كل هذا ، يحتاج المحاكي إلى بعض الأشياء:

1. كائن محاكاة يمكنه الوصول إلى قائمة انتظار الأحداث حيث يتم تخزين الأحداث ويمكن ذلك
إدارة تنفيذ الأحداث

2. جدولة مسؤولة عن إدراج وإزالة الأحداث من قائمة الانتظار

3. طريقة لتمثيل زمن المحاكاة

4. الأحداث نفسها

يصف هذا الفصل من الدليل هذه الكائنات الأساسية (المحاكي ، المجدول ،
الوقت والحدث) وكيف يتم استخدامها.

الحدث/الفعالية
إلى be منجز

محاكاة
فئة المحاكاة هي نقطة الدخول العامة للوصول إلى مرافق جدولة الأحداث. مرة واحدة
تم جدولة حدثين لبدء المحاكاة ، يمكن للمستخدم البدء في
قم بتنفيذها عن طريق الدخول في الحلقة الرئيسية للمحاكي (call محاكي :: تشغيل). مرة واحدة في الحلقة الرئيسية
يبدأ التشغيل ، وسوف ينفذ بالتسلسل جميع الأحداث المجدولة بالترتيب من الأقدم إلى
الأحدث حتى عدم وجود أحداث أخرى متبقية في قائمة انتظار الحدث أو
محاكي :: تم استدعاء Stop.

لجدولة الأحداث للتنفيذ بواسطة الحلقة الرئيسية للمحاكي ، توفر فئة Simulator
المحاكي :: الجدول الزمني * عائلة الوظائف.

1. التعامل مع معالجات الأحداث بتوقيعات مختلفة

يتم الإعلان عن هذه الوظائف وتنفيذها كقوالب C ++ للتعامل تلقائيًا مع ملف
مجموعة متنوعة من تواقيع معالج الأحداث C ++ المستخدمة في البرية. على سبيل المثال ، لجدولة ملف
لتنفيذ 10 ثوانٍ في المستقبل ، واستدعاء طريقة أو وظيفة C ++ مع
حجج محددة ، يمكنك كتابة هذا:

معالج باطل (int arg0، int arg1)
{
استدعاء معالج std :: cout << "مع وسيطة arg0 =" << arg0 << "و
arg1 = "<< arg1 << std :: endl؛
}

محاكي :: جدول (ثانية(10) ، معالج ، 10 ، 5) ؛

الذي سينتج:

تم استدعاء المعالج باستخدام الوسيطة arg0 = 10 و arg1 = 5

بالطبع ، يمكن لقوالب C ++ هذه أيضًا التعامل بشفافية مع أساليب الأعضاء على C ++
شاء:

إلى be مكتمل: عضو طريقة مثال

الملاحظات:

· لا تتعرف طرق الجدولة ns-3 على الوظائف والطرق تلقائيًا إلا إذا كانت كذلك
تأخذ أقل من 5 حجج. إذا كنت بحاجة إليها لدعم المزيد من الحجج ، من فضلك ، قم بتقديم ملف
تقرير الشوائب.

· القراء المألوفون بمصطلح "المنفذون المرتبطون بالكامل" سوف يتعرفون على
Simulator :: جدولة الطرق كطريقة لإنشاء مثل هذه الكائنات تلقائيًا.

2. عمليات الجدولة المشتركة

تم تصميم Simulator API لتسهيل جدولة معظم الأحداث. هو - هي
يوفر ثلاثة متغيرات للقيام بذلك (مرتبة من الأكثر استخدامًا إلى الأقل استخدامًا):

· طرق الجدول التي تسمح لك بجدولة حدث في المستقبل من خلال توفير
التأخير بين وقت المحاكاة الحالي وتاريخ انتهاء صلاحية الحدث المستهدف.

· طرق ScheduleNow التي تسمح لك بجدولة حدث للمحاكاة الحالية
الوقت: سيقومون بتنفيذ _after_ انتهاء الحدث الحالي من التنفيذ ولكن _ قبل_
تم تغيير وقت المحاكاة للحدث التالي.

· طرق ScheduleDestroy التي تسمح لك لربط عملية إيقاف تشغيل جهاز المحاكاة
لتنظيف موارد المحاكاة: يتم تنفيذ كل حدث "إتلاف" عندما يتصل المستخدم
طريقة المحاكاة :: تدمير.

3. الحفاظ على سياق المحاكاة

هناك طريقتان أساسيتان لجدولة الأحداث ، مع وبدون سياق الكلام. ماذا يفعل هذا
تعني؟

المحاكاة :: الجدول الزمني (الوقت الثابت والوقت ، MEM mem_ptr ، OBJ obj) ؛

مقابل

المحاكي :: ScheduleWithContext (سياق uint32_t ، الوقت الثابت والوقت ، MEM mem_ptr ، OBJ obj) ؛

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

في الواقع ، يتم تعقب معرف العقدة لعقدة الشبكة المنفذة حاليًا بواسطة المحاكي
فصل. يمكن الوصول إليه باستخدام أسلوب Simulator :: GetContext الذي يقوم بإرجاع ملف
يرتبط "السياق" (عدد صحيح 32 بت) ويتم تخزينه في الحدث الجاري تنفيذه حاليًا. في
في بعض الحالات النادرة ، عندما لا يكون حدث ما مرتبطًا بعقدة شبكة معينة ، فإن
تم تعيين "السياق" على 0xffffffff.

لربط سياق بكل حدث ، فإن طريقتين ScheduleNow و ScheduleNow تلقائيًا
إعادة استخدام سياق الحدث الجاري تنفيذه كسياق للحدث المجدول
للتنفيذ لاحقًا.

في بعض الحالات ، وعلى الأخص عند محاكاة إرسال حزمة من عقدة إلى
آخر ، هذا السلوك غير مرغوب فيه لأن السياق المتوقع لحدث الاستقبال هو
أن العقدة المستقبلة ، وليس عقدة الإرسال. لتجنب هذه المشكلة ، فإن برنامج Simulator
يوفر class طريقة جدول محددة: ScheduleWithContext والتي تسمح لأحد بتوفيرها
بشكل صريح معرف العقدة للعقدة المستقبلة المرتبطة بحدث الاستلام.

الثلاثون: الكود مثال

في بعض الحالات النادرة جدًا ، قد يحتاج المطورون إلى تعديل أو فهم كيفية السياق
(معرف العقدة) للحدث الأول مضبوط على العقدة المرتبطة به. هذا إنجاز
بواسطة فئة NodeList: كلما تم إنشاء عقدة جديدة ، تستخدم فئة NodeList
ScheduleWithContext لجدولة حدث "تهيئة" لهذه العقدة. حدث "التهيئة"
وبالتالي يتم تنفيذه مع سياق معين إلى سياق معرف العقدة ويمكن استخدام النوع العادي من
طرق الجدولة. تستدعي طريقة Node :: Initialize التي تنشر "التهيئة"
الحدث عن طريق استدعاء أسلوب DoInitialize لكل كائن مرتبط بالعقدة. ال
تم تجاوز أسلوب DoInitialize في بعض هذه الكائنات (وعلى الأخص في التطبيق
الفئة الأساسية) ستقوم بجدولة بعض الأحداث (أبرزها Application :: StartApplication) والتي
ستقوم بدورها بجدولة أحداث توليد حركة المرور والتي بدورها ستعمل على الجدول الزمني
أحداث على مستوى الشبكة.

الملاحظات:

يحتاج المستخدمون إلى توخي الحذر لنشر أساليب DoInitialize عبر الكائنات عن طريق الاستدعاء
التهيئة بشكل صريح على الكائنات الأعضاء الخاصة بهم

معرّف السياق المرتبط بكل طريقة ScheduleWithContext له استخدامات أخرى بعد ذلك
التسجيل: يتم استخدامه بواسطة فرع تجريبي لـ ns-3 لإجراء محاكاة متوازية على
أنظمة متعددة النواة باستخدام multithreading.

لا تعرف وظائف Simulator :: * ما هو السياق: فهي فقط تتأكد من ذلك
أيا كان السياق الذي تحدده مع ScheduleWithContext يكون متاحًا عندما يكون المقابل
يتم تنفيذ الحدث باستخدام :: GetContext.

الأمر متروك للنماذج المطبقة أعلى Simulator :: * لتفسير قيمة السياق.
في ns-3 ، تفسر نماذج الشبكة السياق على أنه معرف العقدة للعقدة التي
ولدت حدثا. هذا هو السبب في أنه من المهم استدعاء ScheduleWithContext في
ns3 :: Channel subclasses لأننا نولد حدثًا من العقدة i إلى العقدة j ونحن
تريد التأكد من أن الحدث الذي سيتم تشغيله على العقدة j لديه السياق الصحيح.

الوقت:
إلى be منجز

جدولة
إلى be منجز

الاسترجاعات
بعض المستخدمين الجدد NS-3 ليسوا على دراية بلغة البرمجة المستخدمة على نطاق واسع
في جميع أنحاء الكود: NS-3 رد. يقدم هذا الفصل بعض الدوافع على
رد الاتصال ، وإرشادات حول كيفية استخدامها ، وتفاصيل عن تنفيذها.

الاسترجاعات التحفيز
ضع في اعتبارك أن لديك نموذجين للمحاكاة A و B ، وترغب في اجتيازهما
المعلومات بينهما أثناء المحاكاة. إحدى الطرق التي يمكنك من خلالها فعل ذلك هي أنك أنت
يمكن أن تجعل كل من A و B على دراية صريحة بالآخر ، حتى يتمكنوا من الاحتجاج
طرق على بعضها البعض:

فئة أ {
الجمهور:
ReceiveInput باطلة (// المعلمات) ؛

}

(في ملف مصدر آخر :)

الصف ب {
الجمهور:
باطل DoSomething (باطل) ؛


خاص:
A * a_instance. // المؤشر إلى أ
}

باطل
ب :: DoSomething ()
{
// أخبر a_instance بحدوث شيء ما
a_instance-> ReceiveInput (// المعلمات) ؛

}

هذا بالتأكيد يعمل ، لكن له عيبًا أنه يقدم الاعتماد على A و B
لمعرفة الآخر في وقت الترجمة (وهذا يجعل من الصعب الحصول على مستقل
وحدات التجميع في المحاكاة) وليست معممة ؛ إذا كان في سيناريو استخدام لاحق ،
يحتاج B إلى التحدث إلى كائن C مختلف تمامًا ، ويجب أن يكون رمز المصدر لـ B
تغيرت لإضافة أ c_instance وهكذا دواليك. من السهل أن نرى أن هذه قوة غاشمة
آلية الاتصال التي يمكن أن تؤدي إلى عملية البرمجة في النماذج.

هذا لا يعني أن الأشياء لا ينبغي أن تعرف عن بعضها البعض إذا كان هناك صعوبة
التبعية بينهما ، ولكن في كثير من الأحيان يمكن جعل النموذج أكثر مرونة إذا كان
تكون التفاعلات أقل تقييدًا في وقت الترجمة.

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

------------ -----------
| برنامج التعاون الفني | | برنامج التعاون الفني |
------------ -----------
| يصبح -> |
----------- -----------
| الملكية الفكرية | | إيبسيك |
----------- -----------
|
-----------
| الملكية الفكرية |
-----------

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

الاسترجاعات خلفيّة
NOTE:
يمكن للقراء المطلعين على عمليات إعادة الاتصال البرمجية تخطي قسم البرنامج التعليمي هذا.

تُعرف الآلية الأساسية التي تسمح للشخص بمعالجة المشكلة أعلاه باسم رد.
الهدف النهائي هو السماح لقطعة واحدة من التعليمات البرمجية باستدعاء وظيفة (أو طريقة في C ++)
بدون أي تبعية محددة بين الوحدات.

هذا يعني في النهاية أنك بحاجة إلى نوع من المراوغة - أنت تتعامل مع عنوان
تسمى وظيفة كمتغير. يسمى هذا المتغير متغير المؤشر إلى الوظيفة.
العلاقة بين الوظيفة ومؤشر المؤشر إلى الوظيفة لا تختلف حقًا
ذلك من كائن ومؤشر إلى كائن.

في لغة C ، يكون المثال الأساسي لمؤشر إلى وظيفة هو أ
مؤشر إلى وظيفة إرجاع عدد صحيح (PFI). بالنسبة لـ PFI الذي يأخذ معلمة int واحدة ، هذا
يمكن التصريح عنه مثل:

int (* pfi) (int arg) = 0 ؛

ما تحصل عليه من هذا هو متغير يسمى ببساطة الرابطة تمت تهيئته إلى القيمة 0.
إذا كنت تريد تهيئة هذا المؤشر إلى شيء ذي معنى ، فيجب أن يكون لديك ملف
وظيفة مع توقيع مطابق. في هذه الحالة:

int MyFunction (int arg) {}

إذا كان لديك هذا الهدف ، فيمكنك تهيئة المتغير للإشارة إلى وظيفتك مثل:

pfi = وظيفتي ؛

يمكنك بعد ذلك الاتصال بـ MyFunction بشكل غير مباشر باستخدام الشكل الأكثر إيحاءًا للمكالمة:

نتيجة int = (* pfi) (1234) ؛

هذا موحي لأنه يبدو أنك تقوم بإلغاء الإشارة إلى مؤشر الوظيفة فقط
كما لو كنت ترغب في عدم الإشارة إلى أي مؤشر. ومع ذلك ، عادةً ما يستفيد الأشخاص من
حقيقة أن المترجم يعرف ما يجري وسيستخدم صيغة أقصر:

نتيجة int = pfi (1234) ؛

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

في C ++ لديك التعقيد الإضافي للكائنات. التشابه مع PFI أعلاه يعني أنك
يكون لديك مؤشر إلى وظيفة عضو بإرجاع int (PMI) بدلاً من المؤشر إلى
وظيفة إرجاع int (PFI).

يبدو إعلان المتغير الذي يوفر المراوغة مختلفًا قليلاً فقط:

int (MyClass :: * pmi) (int arg) = 0 ؛

هذا يصرح عن متغير اسمه مؤشر مديري المشتريات تمامًا كما أعلن المثال السابق عن متغير اسمه
الرابطة. نظرًا لأن الأمر سيكون لاستدعاء طريقة لمثيل لفئة معينة ، يجب على المرء
أعلن عن هذه الطريقة في الفصل:

فئة MyClass {
الجمهور:
int MyMethod (int arg) ؛
};

بالنظر إلى إعلان الفئة هذا ، يمكن للمرء بعد ذلك تهيئة هذا المتغير مثل هذا:

pmi = & MyClass :: MyMethod؛

هذا يعين عنوان الكود الذي ينفذ الطريقة إلى المتغير ، الإكمال
المراوغة. من أجل استدعاء طريقة ، يجب أن يكون الرمز المؤشر. وهذا بدوره
يعني أنه يجب أن يكون هناك كائن من MyClass للإشارة إليه. مثال مبسط على هذا هو عادل
استدعاء طريقة بشكل غير مباشر (فكر في وظيفة افتراضية):

int (MyClass :: * pmi) (int arg) = 0 ؛ // أعلن عن PMI
pmi = & MyClass :: MyMethod؛ // أشر إلى كود التنفيذ

MyClass myClass ؛ // تحتاج إلى مثيل للفئة
(myClass. * pmi) (1234) ، // استدعاء الأسلوب مع كائن ptr

تمامًا كما في مثال C ، يمكنك استخدام هذا في استدعاء غير متزامن لوحدة نمطية أخرى
والتي سوف دعوة الى الخلف باستخدام طريقة ومؤشر كائن. الامتداد المباشر
قد يفكر المرء في تمرير مؤشر إلى الكائن ومتغير PMI. الوحدة
سيفعل فقط:

(* objectPtr. * pmi) (1234) ؛

لتنفيذ رد الاتصال على الكائن المطلوب.

قد يسأل المرء في هذا الوقت ، ما هى هيه نقطة؟ يجب أن تفهم الوحدة التي تم استدعاؤها
النوع الملموس لكائن الاستدعاء من أجل إجراء رد النداء بشكل صحيح. ولم لا
فقط اقبل هذا ، مرر مؤشر الكائن المكتوب بشكل صحيح وافعل الكائن>خدمة التوصيل(1234) in
الكود بدلاً من رد الاتصال؟ هذه هي بالضبط المشكلة الموضحة أعلاه. ما هو
مطلوب طريقة لفصل وظيفة الاستدعاء عن الفئة التي تم استدعاؤها تمامًا. هذا
أدى الشرط إلى تطوير المنفّذ.

الممتع هو ثمرة شيء تم اختراعه في الستينيات يسمى الإغلاق. إنها
في الأساس مجرد استدعاء دالة مجمعة ، ربما مع بعض الحالات.

يتكون المنع من جزأين ، جزء محدد وجزء عام ، مرتبطان بالوراثة.
كود الاستدعاء (الكود الذي ينفذ رد الاتصال) سوف ينفذ التحميل الزائد العام
عامل () من المنفذ العام للتسبب في استدعاء رد الاتصال. الكود المسمى (ملف
الكود الذي يريد أن يتم استدعاؤه مرة أخرى) يجب أن يوفر تنفيذًا متخصصًا لـ
هيه عامل () الذي يؤدي العمل الخاص بالفئة والذي تسبب في الاقتران الوثيق
المشكلة أعلاه.

مع المميزات المحددة وحملتها الزائدة عامل () تم إنشاؤه ، رمز يسمى بعد ذلك
يعطي الكود المتخصص للوحدة التي ستقوم بتنفيذ رد الاتصال (الاستدعاء
الشفرة).

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

المعلومات التي يحتاجها المرء لإنشاء أداة تحويل معينة هي مؤشر الكائن و
عنوان المؤشر إلى الأسلوب.

جوهر ما يجب أن يحدث هو أن يعلن النظام جزءًا عامًا من
المنعز:

نموذج
فئة المنبه
{
الجمهور:
عامل التشغيل الظاهري () (T arg) = 0 ؛
};

يحدد المتصل جزءًا معينًا من المنفذ موجود بالفعل للتنفيذ
المحدد المشغل أو العامل() الأسلوب:

نموذج
فئة محددة
{
الجمهور:
SpecificFunctor (T * p، int (T :: * _ pmi) (ARG arg))
{
m_p = p ؛
m_pmi = _pmi ؛
}

عامل التشغيل الظاهري () (ARG arg)
{
(* m_p. * m_pmi) (arg) ؛
}
خاص:
int (T :: * m_pmi) (ARG arg) ؛
T * m_p ؛
};

فيما يلي مثال على الاستخدام:

فئة أ
{
الجمهور:
أ (int a0): أ (a0) {}
مرحبا int (int b0)
{
std :: cout << "مرحبًا من A، a =" << a << "b0 =" << b0 << std :: endl؛
}
كثافة العمليات
};

إنت مين ()
{
A a(10)
محدد sf (& a ، & A :: Hello) ؛
sf(5)
}

NOTE:
الكود السابق ليس كود ns-3 حقيقي. إنه رمز مثال مبسط يستخدم فقط لـ
وضح المفاهيم المتضمنة ولمساعدتك على فهم النظام بشكل أكبر. لا
توقع العثور على هذا الرمز في أي مكان في شجرة ns-3.

لاحظ أن هناك متغيرين محددين في الفئة أعلاه. المتغير m_p هو
مؤشر الكائن و m_pmi هو المتغير الذي يحتوي على عنوان الوظيفة إلى
نفذ - اعدم.

لاحظ ذلك متى المشغل أو العامل() يتم استدعاؤه ، وهو بدوره يستدعي الطريقة المتوفرة مع
مؤشر الكائن باستخدام بناء جملة C ++ PMI.

لاستخدام هذا ، يمكن للمرء بعد ذلك الإعلان عن بعض التعليمات البرمجية النموذجية التي تأخذ عامل تحويل عام كملف
المعلمة:

مكتبة باطلة (Functor functor) ؛

الكود الذي سيتحدث إلى النموذج سيبني ممولًا معينًا ويمرره إليه
وظيفة المكتبة:

MyClass myClass ؛
محدد functor (& myclass، MyClass :: MyMethod) ؛

متى وظيفة المكتبة تم ، يتم تنفيذ رد الاتصال باستخدام المشغل أو العامل() على العام
تم تمريره ، وفي هذه الحالة بالذات ، يوفر الوسيطة الصحيحة:

باطل
LibraryFunction (المنفّذ)
{
// تنفيذ وظيفة المكتبة
ممول(1234)
}

لاحظ أن وظيفة المكتبة منفصل تمامًا عن النوع المحدد للعميل.
يتم الاتصال من خلال تعدد الأشكال Functor.

واجهة برمجة تطبيقات Callback بتنسيق NS-3 تنفذ عمليات الاسترجاعات الموجهة للكائنات باستخدام آلية functor.
واجهة برمجة تطبيقات رد الاتصال هذه ، التي تستند إلى قوالب C ++ ، هي نوع آمن ؛ أي أنه يؤدي ساكنة
تدقيق النوع لفرض توافق التوقيع الصحيح بين المتصلين وكالي. إنها
لذلك أكثر أمانًا من النوع للاستخدام من مؤشرات الوظائف التقليدية ، ولكن قد يكون بناء الجملة
تبدو مهيبة في البداية. تم تصميم هذا القسم لإرشادك عبر نظام رد الاتصال
حتى تكون مرتاحًا في استخدامه NS-3.

باستخدام هيه أن نتواصل معك API
يعد Callback API ضئيلًا إلى حد ما ، حيث يوفر خدمتين فقط:

1. إعلان نوع رد الاتصال: طريقة للإعلان عن نوع من رد النداء بتوقيع معين ،
و،

2. إنشاء مثيل لرد الاتصال: طريقة لإنشاء مثيل لرد إعادة توجيه تم إنشاؤه بواسطة قالب
والتي يمكنها إعادة توجيه أي مكالمات إلى طريقة عضو أخرى في فئة C ++ أو وظيفة C ++.

من الأفضل ملاحظة ذلك من خلال السير في مثال ، بناءً على عينات / main-callback.cc.

باستخدام هيه أن نتواصل معك API مع ساكن وظائف
ضع في اعتبارك وظيفة:

مزدوج ثابت
CbOne (مزدوج أ ، مزدوج ب)
{
std :: cout << "استدعاء cbOne a =" << a << "، b =" << b << std :: endl؛
العودة أ ؛
}

ضع في اعتبارك أيضًا مقتطف البرنامج الرئيسي التالي:

int main (int argc، char * argv [])
{
// نوع الإرجاع: double
// نوع الوسيط الأول: مزدوج
// نوع الوسيط الثاني: double
أتصل مرة أخرى واحد؛
}

هذا مثال على رد نداء على النمط C - والذي لا يتضمن أو يحتاج إلى
المؤشر. قالب الوظيفة أن نتواصل معك هو في الأساس إعلان عن المتغير
تحتوي على المؤشر إلى الوظيفة. في المثال أعلاه ، أظهرنا بوضوح مؤشرًا
إلى دالة أعادت عددًا صحيحًا وأخذت عددًا صحيحًا واحدًا كمعامل ، The
أن نتواصل معك الدالة template هي نسخة عامة من ذلك - تُستخدم للإعلان عن النوع
من رد الاتصال.

NOTE:
يمكن للقراء الذين ليسوا على دراية بقوالب C ++ الرجوع إليها
http://www.cplusplus.com/doc/tutorial/templates/.

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

لذلك في المثال أعلاه ، لدينا رد اتصال مُعلن باسم "واحد" والذي سيؤدي في النهاية
عقد مؤشر الوظيفة. يجب أن يعود توقيع الوظيفة التي ستحتفظ بها
مزدوج ويجب أن يدعم حجتين مزدوجتين. إذا حاول المرء تمرير وظيفة
التوقيع لا يتطابق مع رد النداء المعلن ، سيحدث خطأ في الترجمة. أيضا إذا
يحاول المرء أن يعين لرد اتصال غير متوافق ، سينجح التجميع ولكن أ
سيتم رفع NS_FATAL_ERROR وقت التشغيل. برنامج العينة
src / core / أمثلة / main-callback.cc يوضح كل من حالات الخطأ هذه في نهاية
هيه الأساسية() برنامج.

الآن ، نحتاج إلى ربط مثيل رد الاتصال هذا مع وظيفة الهدف الفعلية
(CbOne). لاحظ أعلاه أن CbOne له نفس أنواع توقيعات الوظيفة مثل رد الاتصال--
هذا مهم. يمكننا تمرير أي وظيفة مكتوبة بشكل صحيح إلى رد الاتصال هذا.
لنلقِ نظرة عن كثب على هذا:

ثابت مزدوج CbOne (مزدوج أ ، مزدوج ب) {}
^ ^ ^
| | |
| | |
أتصل مرة أخرى واحد؛

يمكنك فقط ربط دالة باستدعاء إذا كان لديهم التوقيع المطابق. الأول
وسيطة القالب هي نوع الإرجاع ، ووسيطات القالب الإضافية هي الأنواع
من حجج توقيع الوظيفة.

الآن ، دعنا نربط رد النداء "واحد" بالوظيفة التي تطابق توقيعها:

// بناء مثيل رد الاتصال الذي يشير إلى وظيفة cbOne
one = MakeCallback (& ​​CbOne) ؛

هذه الدعوة ل إجعل الإتصال هو ، في جوهره ، إنشاء واحد من الممثلين المتخصصين
المذكور أعلاه. أعلن المتغير باستخدام أن نتواصل معك ستذهب وظيفة القالب إلى
أن تلعب دور الممتلئ العام. الاحالة صورة واحدة؟ = إجعل الإتصال (& CbOne) is
الممثلين الذي يحول الممثّل المتخصص المعروف لدى المستدعي إلى ممتلئ عام
معروف للمتصل.

ثم لاحقًا في البرنامج ، إذا كانت هناك حاجة إلى رد الاتصال ، فيمكن استخدامه على النحو التالي:

NS_ASSERT (! one.IsNull ()) ،

// استدعاء دالة cbOne من خلال مثيل رد الاتصال
إعادة مزدوجة
retOne = واحد (10.0 ، 20.0) ؛

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

باستخدام هيه أن نتواصل معك API مع عضو وظائف
بشكل عام ، لن تقوم باستدعاء وظائف ثابتة ولكن بدلاً من ذلك تقوم باستدعاء وظائف الأعضاء العامة
شيء. في هذه الحالة ، هناك حاجة إلى وسيطة إضافية للدالة MakeCallback ، إلى
أخبر النظام عن الكائن الذي يجب استدعاء الوظيفة عليه. ضع في اعتبارك هذا المثال ،
أيضًا من main-callback.cc:

فئة MyCb {
الجمهور:
int CbTwo (مزدوج أ) {
استدعاء std :: cout << "cbTwo a =" << a << std :: endl؛
عودة -5 ؛
}
};

انت مين ()
{

// نوع الإرجاع: int
// نوع الوسيط الأول: مزدوج
أتصل مرة أخرى اثنين؛
MyCb cb ؛
// build مثيل رد الاتصال الذي يشير إلى MyCb :: cbTwo
two = MakeCallback (& ​​MyCb :: CbTwo، & cb) ؛

}

هنا ، نقوم بتمرير مؤشر كائن إضافي إلى MakeCallback <> وظيفة. أذكر من
قسم الخلفية أعلاه المشغل أو العامل() سيستخدم المؤشر إلى بناء الجملة عندما يكون
ينفذ على كائن:

عامل التشغيل الظاهري () (ARG arg)
{
(* m_p. * m_pmi) (arg) ؛
}

ولذا ، فقد احتجنا إلى توفير المتغيرين (م_ص m_pmi) عندما قمنا بالتحديد
المنع. الخط:

two = MakeCallback (& ​​MyCb :: CbTwo، & cb) ؛

يفعل ذلك بالضبط. في هذه الحالة ، متى اثنان () تم استدعاؤه:

نتيجة int = اثنان (1.0) ؛

سوف يؤدي إلى مكالمة إلى CbTwo وظيفة العضو (الطريقة) على الكائن المشار إليه
& ج ب.

ابني فارغة الاسترجاعات
من الممكن أن تكون عمليات الاسترجاعات خالية ؛ ومن ثم قد يكون من الحكمة التحقق منها قبل استخدامها.
هناك بناء خاص لرد نداء فارغ ، وهو أفضل من مجرد التمرير
"0" كوسيطة ؛ انها MakeNullCallback <> بناء:

اثنان = MakeNullCallback () ؛
NS_ASSERT (two.IsNull ()) ،

استدعاء رد نداء فارغ يشبه تمامًا استدعاء مؤشر دالة فارغ: سيتعطل عند
مدة العرض.

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

ماذا لو كان مطلوبًا للسماح بوظيفة العميل (التي توفر رد الاتصال)
تقديم بعض المعلمات؟ الكسندرسكو يستدعي عملية السماح للعميل بـ
حدد أحد المعلمات "ربط". أحد معالم المشغل أو العامل() وكان
ملزمة (ثابتة) من قبل العميل.

تقدم بعض رموز تتبع pcap الخاصة بنا مثالًا رائعًا على ذلك. هناك وظيفة
يحتاج إلى استدعاء كلما تم تلقي حزمة. تستدعي هذه الوظيفة كائنًا
يكتب في الواقع الحزمة إلى القرص بتنسيق ملف pcap. توقيع واحد من هؤلاء
ستكون الوظائف:

ستاتيك باطل DefaultSink (Ptr ملف ، Ptr ع) ؛

تعني الكلمة الأساسية الثابتة أن هذه وظيفة ثابتة لا تحتاج إلى ملف المؤشر ، لذلك
سيتم استخدام عمليات الاسترجاعات على النمط C. لا نريد أن نعرف رمز الاتصال
أي شيء ما عدا الحزمة. ما نريده في كود الاتصال هو مجرد مكالمة تشبه:

m_promiscSnifferTrace (m_currentPkt) ،

ما نريد القيام به هو ربط هيه Ptr ملف إلى رد الاتصال المحدد
التنفيذ عند إنشائه والترتيب لـ المشغل أو العامل() من رد الاتصال إلى
توفر هذه المعلمة مجانًا.

نحن نقدم MakeBoundCallback نموذج وظيفة لهذا الغرض. يأخذ نفس الشيء
المعلمات مثل إجعل الإتصال وظيفة القالب ولكن أيضًا تأخذ المعلمات لتكون
مرتبط ب. في حالة المثال أعلاه:

MakeBoundCallback (& ​​DefaultSink ، ملف) ؛

سيُنشئ تنفيذ رد نداء محدد يعرف أنه سيضيف الحد الإضافي
الحجج. من الناحية المفاهيمية ، فإنه يمتد إلى المميزات المحددة الموصوفة أعلاه بواحد أو أكثر
الحجج منضم:

نموذج
فئة محددة
{
الجمهور:
SpecificFunctor (T * p، int (T :: * _ pmi) (ARG arg)، BOUND_ARG boundArg)
{
m_p = p ؛
m_pmi = pmi ؛
m_boundArg = قيمة ملزمة ؛
}

عامل التشغيل الظاهري () (ARG arg)
{
(* m_p. * m_pmi) (m_boundArg ، arg) ؛
}
خاص:
باطل (T :: * m_pmi) (ARG arg) ؛
T * m_p ؛
BOUND_ARG m_boundArg ؛
};

يمكنك أن ترى أنه عند إنشاء الممول المحدد ، يتم حفظ الوسيطة المرتبطة في ملف
functor / callback object نفسه. عندما المشغل أو العامل() يتم استدعاؤه مع واحد
المعلمة ، كما في:

m_promiscSnifferTrace (m_currentPkt) ،

تنفيذ المشغل أو العامل() يضيف المعامل المربوط إلى استدعاء الوظيفة الفعلي:

(* m_p. * m_pmi) (m_boundArg ، arg) ؛

من الممكن أيضًا ربط حجتين أو ثلاث حجج. لنفترض أن لدينا وظيفة مع
التوقيع:

NotifyEvent باطل ثابت (Ptr a ، Ptr b ، MyEventType e) ؛

يمكن للمرء إنشاء ربط رد الاتصال المرتبط بالوسيطتين الأوليين مثل:

MakeBoundCallback (& ​​NotifyEvent، a1، b1) ؛

على افتراض a1 b1 هي كائنات من النوع A B على التوالى. بالمثل لثلاثة
الحجج التي قد يكون لها وظيفة مع التوقيع:

NotifyEvent باطل ثابت (Ptr a ، Ptr b ، MyEventType e) ؛

ثلاث حجج ملزمة في القيام به مع:

MakeBoundCallback (& ​​NotifyEvent، a1، b1، c1) ؛

مرة أخرى على افتراض a1, b1 c1 هي كائنات من النوع A, B C على التوالي.

يمكن استخدام هذا النوع من الربط لتبادل المعلومات بين الكائنات في المحاكاة ؛
على وجه التحديد ، يمكن استخدام عمليات الاسترجاعات المقيدة باعتبارها عمليات نداء متتبعة ، والتي سيتم وصفها في
القسم التالي.

تتبعت الاسترجاعات
نائب القسم الفرعي

أن نتواصل معك المواقع in NS-3
أين تُستخدم عمليات الاسترجاعات بشكل متكرر NS-3؟ فيما يلي بعض من أكثرها وضوحًا
المستخدمون العاديون:

· مقبس API

· طبقة 2 / طبقة 3 API

· تتبع النظام الفرعي

· API بين IP وأنظمة التوجيه الفرعية

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

تمت كتابة الكود في الأصل بناءً على التقنيات الموضحة في
http://www.codeproject.com/cpp/TTLFunction.asp. تمت إعادة كتابته لاحقًا للمتابعة
الهندسة المبينة في تقدم C + + التصميم، عام برمجة وتطوير تصميم أنماط
مُطبَّق، الكسندرسكو ، الفصل 5, المعممة المنفذين.

يستخدم هذا الرمز:

معلمات القالب الافتراضية لإنقاذ المستخدمين من الاضطرار إلى تحديد المعلمات الفارغة عندما
عدد المعلمات أصغر من الحد الأقصى للرقم المدعوم

· مصطلح pimpl: يتم تمرير فئة Callback بالقيمة وتفويض جوهر
العمل لمؤشر pimpl الخاص به.

يمكن استخدام اثنين من تطبيقات pimpl المستمدة من CallbackImpl FunctorCallbackImpl
مع أي نوع functor بينما يمكن استخدام MemPtrCallbackImpl مع مؤشرات للعضو
الوظائف.

· تطبيق قائمة مرجعية لتنفيذ دلالات قيمة رد الاتصال.

يخرج هذا الرمز بشكل ملحوظ عن تطبيق Alexandrescu لأنه لا يفعل ذلك
استخدام قوائم النوع لتحديد أنواع وسيطات رد الاتصال وتمريرها. بالطبع،
كما أنه لا يستخدم دلالات إتلاف النسخ ويعتمد على قائمة مرجعية بدلاً من
autoPtr لعقد المؤشر.

هدف نموذج
NS-3 هو في الأساس نظام كائن C ++. يمكن الإعلان عن الكائنات وإنشاء مثيل لها كـ
المعتاد ، وفقًا لقواعد C ++. NS-3 يضيف أيضًا بعض الميزات إلى كائنات C ++ التقليدية ، مثل
الموضحة أدناه ، لتوفير وظائف وميزات أكبر. هذا الفصل من الدليل هو
تهدف إلى تعريف القارئ على NS-3 نموذج الكائن.

يصف هذا القسم تصميم فئة C ++ لـ NS-3 أشياء. باختصار ، عدة تصميم
تتضمن الأنماط المستخدمة التصميم الكلاسيكي الموجه للكائنات (واجهات متعددة الأشكال و
التطبيقات) ، وفصل الواجهة والتنفيذ ، والجمهور غير الافتراضي
نمط تصميم الواجهة ، ومرفق تجميع الكائنات ، وحساب المرجع
إدارة الذاكرة. أولئك الذين هم على دراية بنماذج المكونات مثل COM أو Bonobo سوف
التعرف على عناصر التصميم في NS-3 نموذج تجميع الكائن ، على الرغم من أن NS-3
التصميم لا يتوافق تمامًا مع أي منهما.

وجوه المنحى سلوك
توفر كائنات C ++ ، بشكل عام ، إمكانات مشتركة موجهة للكائنات (التجريد ،
التغليف والوراثة وتعدد الأشكال) التي تعد جزءًا من العناصر الكلاسيكية الموجهة
التصميم. NS-3 الكائنات تستفيد من هذه الخصائص ؛ على سبيل المثال:

عنوان الفصل
{
الجمهور:
عنوان ()؛
العنوان (uint8_t type، const uint8_t * buffer، uint8_t len) ؛
العنوان (العنوان والعنوان) ؛
العنوان & عامل = (عنوان & العنوان) ؛

خاص:
uint8_t m_type ؛
uint8_t m_len ؛

};

هدف قاعدة فصول
هناك ثلاث فئات أساسية خاصة مستخدمة في NS-3. الفئات التي ترث من هذه القاعدة
يمكن للفئات إنشاء كائنات ذات خصائص خاصة. هذه الفئات الأساسية هي:

· فصل هدف

· فصل ObjectBase

· فصل SimpleRefCount

لا يشترط ذلك NS-3 الكائنات ترث من هذه الفئة ، لكن تلك التي تحصل عليها
خصائص خاصة. فئات مشتقة من الطبقة هدف احصل على الخصائص التالية.

· ال NS-3 النوع ونظام السمات (انظر السمات)

· نظام تجميع الكائنات

· نظام عد مرجعي ذو مؤشر ذكي (فئة Ptr)

الفئات المشتقة من الطبقة ObjectBase احصل على أول خاصيتين أعلاه ، لكن لا تفعل ذلك
الحصول على مؤشرات ذكية. الفئات المشتقة من الطبقة SimpleRefCount: احصل فقط على
نظام عد مرجعي مؤشر ذكي.

في الممارسة ، الطبقة هدف هو متغير الثلاثة أعلاه NS-3 المطور سوف
الأكثر شيوعًا.

ذاكرة إدارة فئة بي تي آر
تعد إدارة الذاكرة في برنامج C ++ عملية معقدة ، وغالبًا ما تتم بشكل غير صحيح أو
بشكل غير متسق. لقد استقرنا على تصميم حساب مرجعي موصوف على النحو التالي.

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

· عندما يحصل رمز العميل على مؤشر من الكائن نفسه من خلال إنشاء الكائن ،
أو عبر GetObject ، ليس من الضروري زيادة عدد المرجع.

عندما يحصل رمز العميل على مؤشر من مصدر آخر (على سبيل المثال ، نسخ مؤشر) يجب أن يكون
دعوة المرجع () لزيادة عدد المرجع.

يجب على جميع مستخدمي مؤشر الكائن الاتصال Unref () لإطلاق المرجع.

عبء الاتصال Unref () إلى حد ما عن طريق استخدام العد المرجعي
فئة المؤشر الذكية الموضحة أدناه.

المستخدمون الذين يستخدمون واجهة برمجة تطبيقات ذات مستوى منخفض يرغبون في تخصيص كائنات غير محسوبة بمرجع صريح
على الكومة ، باستخدام عامل التشغيل الجديد ، تكون مسؤولة عن حذف هذه الكائنات.

الرقم المرجعي عد سمارت مؤشر (بتر)
دعوة المرجع () Unref () كل الوقت سيكون مرهقا ، لذلك NS-3 يوفر ذكاء
فئة المؤشر بي تي آر على غرار دفعة :: intrusive_ptr. تفترض فئة المؤشر الذكي هذا
النوع الأساسي يوفر زوجًا من المرجع أونريف الأساليب التي من المتوقع أن
زيادة وإنقاص refcount الداخلي لمثيل الكائن.

يسمح لك هذا التطبيق بمعالجة المؤشر الذكي كما لو كان عاديًا
المؤشر: يمكنك مقارنته بصفر ، ومقارنته بمؤشرات أخرى ، وإسناد صفر إلى
ذلك ، إلخ.

من الممكن استخراج المؤشر الخام من هذا المؤشر الذكي بامتداد GetPointer ()
نظرة خاطفة () الأساليب.

إذا كنت تريد تخزين كائن جديد في مؤشر ذكي ، فننصحك باستخدام
وظائف قالب CreateObject لإنشاء الكائن وتخزينه في مؤشر ذكي إلى
تجنب تسرب الذاكرة. هذه الوظائف هي في الحقيقة وظائف راحة صغيرة وهدفها
هو فقط لتوفير القليل من الكتابة.

CREATEOBJECT إنشاء
قد يتم إنشاء الكائنات في C ++ بشكل ثابت أو ديناميكي أو تلقائيًا. هذا صحيح
لـ NS-3 أيضًا ، ولكن بعض الكائنات في النظام لديها بعض الأطر الإضافية المتاحة.
على وجه التحديد ، عادةً ما يتم تخصيص الكائنات المحسوبة المرجعية باستخدام نموذج إنشاء أو
طريقة CreateObject ، على النحو التالي.

للأشياء المشتقة من الطبقة هدف:

Ptr الجهاز = CreateObject () ؛

يرجى عدم إنشاء مثل هذه الكائنات باستخدام عامل جديد؛ إنشائها باستخدام إنشاء كائن()
بدلا من ذلك.

للأشياء المشتقة من الطبقة SimpleRefCount، أو الكائنات الأخرى التي تدعم استخدام
فئة المؤشر الذكي ، وظيفة المساعد النموذجية متاحة ويوصى باستخدامها:

Ptr ب = إنشاء () ؛

هذا مجرد غلاف حول المشغل الجديد الذي يعالج العد المرجعي بشكل صحيح
نظام.

باختصار ، استخدم يخلق إذا لم يكن B كائنًا ولكنه يستخدم فقط حساب المرجع (على سبيل المثال
رزمة) والاستخدام إنشاء كائن إذا كان B مشتق من ns3 :: الكائن.

تجميع
إنّ NS-3 يتم تحفيز نظام تجميع الكائنات في جزء قوي من خلال الاعتراف بأن أ
حالة الاستخدام الشائعة لـ NS-2 تم استخدام الوراثة وتعدد الأشكال لتوسيع
نماذج البروتوكول. على سبيل المثال ، تشتق الإصدارات المتخصصة من TCP مثل RenoTcpAgent
من (وإلغاء الوظائف من) فئة TcpAgent.

ومع ذلك ، فقد نشأت مشكلتان في NS-2 النموذج منحدرات و "قاعدة ضعيفة
class. "Downcasting يشير إلى إجراء استخدام مؤشر فئة أساسي لكائن و
الاستعلام عنها في وقت التشغيل لاكتشاف معلومات النوع ، وتستخدم لتوجيه المؤشر بشكل صريح
إلى مؤشر فئة فرعية بحيث يمكن استخدام الفئة الفرعية API. تشير الفئة الأساسية الضعيفة إلى
المشاكل التي تنشأ عندما لا يمكن إعادة استخدام فئة بشكل فعال (مشتق منها) لأنها
يفتقر إلى الوظائف الضرورية ، مما يدفع المطور إلى تعديل الفئة الأساسية و
تسبب في تكاثر استدعاءات API للفئة الأساسية ، وبعضها قد لا يكون معنويًا
صحيح لجميع الفئات الفرعية.

NS-3 يستخدم إصدارًا من نمط تصميم واجهة الاستعلام لتجنب هذه المشاكل.
يعتمد هذا التصميم على عناصر مكون هدف الموديل GNOME البونوبو رغم أن
التوافق الكامل على المستوى الثنائي للمكونات القابلة للاستبدال غير مدعوم ولدينا
حاول تبسيط بناء الجملة والتأثير على مطوري النماذج.

أمثلة
تجميع مثال
العقدة هو مثال جيد على استخدام التجميع في NS-3. لاحظ أنه لا يوجد مشتق
فئات العقد في NS-3 مثل الفصل عقدة الإنترنت. بدلا من ذلك ، المكونات (البروتوكولات) هي
مجمعة في عقدة. لنلقِ نظرة على كيفية إضافة بعض بروتوكولات Ipv4 إلى العقدة:

الفراغ ثابت
AddIpv4Stack (Ptr العقدة)
{
Ptr ipv4 = CreateObject () ؛
ipv4-> SetNode (عقدة) ؛
عقدة-> AggregateObject (ipv4) ؛
Ptr ipv4Impl = CreateObject () ؛
ipv4Impl-> SetIpv4 (ipv4) ؛
عقدة-> AggregateObject (ipv4Impl) ؛
}

لاحظ أنه يتم إنشاء بروتوكولات Ipv4 باستخدام إنشاء كائن(). ثم يتم تجميعها
إلى العقدة. بهذه الطريقة ، لا يلزم تحرير فئة Node الأساسية للسماح للمستخدمين
باستخدام مؤشر عقدة من الفئة الأساسية للوصول إلى واجهة Ipv4 ؛ قد يطلب المستخدمون من العقدة ملف
مؤشر لواجهة IPv4 الخاصة به في وقت التشغيل. كيف يسأل المستخدم العقدة موصوفة في ملف
القسم الفرعي التالي.

لاحظ أن تجميع أكثر من كائن من نفس النوع إليه يعد خطأ برمجيًا
an ns3 :: الكائن. لذلك ، على سبيل المثال ، التجميع ليس خيارًا لتخزين كل ملفات
مآخذ نشطة من العقدة.

GETOBJECT مثال
GetObject هي طريقة آمنة من النوع لتحقيق خفض آمن والسماح للواجهات بأن تكون
وجدت على كائن.

ضع في اعتبارك مؤشر العقدة m_node يشير إلى كائن عقدة له تطبيق
تم تجميع IPv4 مسبقًا له. يرغب رمز العميل في تكوين مسار افتراضي. ل
للقيام بذلك ، يجب أن يصل إلى كائن داخل العقدة التي لها واجهة لإعادة توجيه IP
إعدادات. يقوم بما يلي:

Ptr ipv4 = m_node-> GetObject () ؛

إذا كانت العقدة في الواقع لا تحتوي على كائن Ipv4 مجمع عليها ، فستكون الطريقة
العودة فارغة. لذلك ، من الجيد التحقق من قيمة الإرجاع من هذه الوظيفة
يتصل. في حالة النجاح ، يمكن للمستخدم الآن استخدام Ptr لكائن Ipv4 الذي كان سابقًا
مجمعة للعقدة.

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

نأمل أن يتطلب وضع البرمجة هذا حاجة أقل بكثير للمطورين للتعديل
الفئات الأساسية.

هدف المصانع
حالة الاستخدام الشائعة هي إنشاء الكثير من الكائنات ذات التكوين المتشابه. يمكن للمرء مرارا وتكرارا
دعوة إنشاء كائن() ولكن هناك أيضًا نمط تصميم مصنع قيد الاستخدام في NS-3 نظام.
يستخدم بكثرة في API "المساعد".

مبوبة ObjectFactory يمكن استخدامها لإنشاء كائنات وتكوين السمات على
تلك الأشياء:

SetTypeId باطلة (TypeId tid) ؛
مجموعة باطلة (std :: string name، const AttributeValue & value) ؛
Ptr إنشاء (باطل) const ؛

الطريقة الأولى تسمح للمرء باستخدام NS-3 نظام TypeId لتحديد نوع الكائنات
مخلوق. والثاني يسمح للمرء بتعيين سمات على الكائنات المراد إنشاؤها ، و
الثالث يسمح للشخص بإنشاء الأشياء بأنفسهم.

فمثلا:

مصنع ObjectFactory
// اجعل هذا المصنع ينشئ كائنات من النوع FriisPropagationLossModel
factory.SetTypeId ("ns3 :: FriisPropagationLossModel")
// اجعل كائن المصنع هذا يغير القيمة الافتراضية للسمة ، لـ
// تم إنشاؤه لاحقًا
factory.Set ("SystemLoss"، DoubleValue (2.0)) ؛
// إنشاء كائن واحد من هذا القبيل
Ptr الكائن = factory.Create () ؛
factory.Set ("SystemLoss"، DoubleValue (3.0)) ؛
// إنشاء كائن آخر باستخدام SystemLoss مختلف
Ptr الكائن = factory.Create () ؛

الكآبة
السؤال الذي نشأ عدة مرات هو ، "إذا كان لدي مؤشر فئة أساسية (Ptr) إلى ملف
الكائن وأريد مؤشر الفئة المشتق ، هل يجب أن أخفض (عبر C ++ dynamic cast) إلى
الحصول على المؤشر المشتق ، أو يجب علي استخدام نظام تجميع الكائنات ل GetObject <> ()
للعثور على Ptr للواجهة الخاصة بالفئة الفرعية API؟ "

الجواب على ذلك هو أنه في العديد من المواقف ، ستنجح كلتا الطريقتين. NS-3 ويوفر
دالة على شكل قالب لجعل بناء جملة الكائن الديناميكي يلقي مستخدمًا أكثر بكثير
ودود:

نموذج
Ptr
DynamicCast (Ptr const & p)
{
عودة Ptr (بث ديناميكي (PeekPointer (ع))) ؛
}

يعمل DynamicCast عندما يكون لدى المبرمج مؤشر نوع أساسي ويتم اختباره مقابل ملف
مؤشر فئة فرعية. يعمل GetObject عند البحث عن كائنات مختلفة مجمعة ، ولكن أيضًا
يعمل مع الفئات الفرعية ، بنفس طريقة DynamicCast. إذا لم تكن متأكدًا ، يجب على المبرمج
استخدم GetObject ، لأنه يعمل في جميع الحالات. إذا كان المبرمج يعرف التسلسل الهرمي للفئة
الكائن قيد النظر ، فمن الأفضل استخدام DynamicCast فقط.

الاعداد السمات
In NS-3 المحاكاة ، هناك جانبان رئيسيان للتكوين:

طوبولوجيا المحاكاة وكيف ترتبط الأشياء.

· القيم المستخدمة بواسطة النماذج التي تم إنشاء مثيل لها في الهيكل.

يركز هذا الفصل على العنصر الثاني أعلاه: كيف يتم استخدام العديد من القيم في NS-3 .
منظمة وموثقة وقابلة للتعديل بواسطة NS-3 المستخدمين. ال NS-3 نظام السمة هو أيضا
تعزيز كيفية جمع الآثار والإحصاءات في جهاز المحاكاة.

في سياق هذا الفصل سنناقش الطرق المختلفة لتعيين القيم أو تعديلها
استعمل من قبل NS-3 كائنات نموذجية. بترتيب الخصوصية المتزايد ، هذه هي:

┌─────────────────────────────────┬─────────────── ───────────────────┐
│ الطريقة │ النطاق │
├─────────────────────────────────┼─────────────── ───────────────────┤
│تعيين قيم السمات الافتراضية │ تؤثر على جميع مثيلات │
│عند تحديد السمات في │ class. │
GetTypeId (). │ │
└─────────────────────────────────┴─────────────── ───────────────────┘

سطر الأوامر │ تؤثر على جميع الحالات المستقبلية. │
التكوين :: SetDefault () │ │
متجر التكوين │ │
├─────────────────────────────────┼─────────────── ───────────────────┤
ObjectFactory │ يؤثر على جميع الحالات التي تم إنشاؤها │
│ │ مع المصنع. │
├─────────────────────────────────┼─────────────── ───────────────────┤
XHelperSetAttribute () │ يؤثر على جميع الحالات التي تم إنشاؤها بواسطة │
│ │ المساعد. │
├─────────────────────────────────┼─────────────── ───────────────────┤
MyClass :: SetX () │ يغير هذه الحالة بالذات. │
الكائن :: SetAttribute () │ بشكل عام هذا هو الشكل الوحيد │
التكوين :: مجموعة () │ والتي يمكن جدولتها لتعديل │
│ │ مثيل مرة واحدة المحاكاة │
│ │ قيد التشغيل. │
└─────────────────────────────────┴─────────────── ───────────────────┘

نعني بكلمة "الخصوصية" أن الطرق الموجودة في الصفوف اللاحقة في الجدول تتجاوز مجموعة القيم
من خلال ، وعادة ما تؤثر على عدد أقل من الحالات من الطرق السابقة.

قبل الخوض في تفاصيل نظام قيمة السمة ، من المفيد مراجعة بعضها
الخصائص الأساسية للفئة هدف.

هدف نظرة عامة
NS-3 هو في الأساس نظام قائم على كائن C ++. بهذا نعني أن فئات C ++ الجديدة
يمكن التصريح عن (الأنواع) وتعريفها وتصنيفها الفرعي كالمعتاد.

كثير NS-3 ترث الكائنات من هدف الفئة الأساسية. هذه الأشياء لديها بعض إضافية
الخصائص التي نستغلها لتنظيم النظام وتحسين إدارة الذاكرة
من كائناتنا:

· نظام "البيانات الوصفية" الذي يربط اسم الفئة بالكثير من المعلومات الوصفية حول
كائن ، بما في ذلك:

· الفئة الأساسية للفئة الفرعية ،

· مجموعة المنشئات التي يمكن الوصول إليها في الفئة الفرعية ،

· مجموعة "سمات" الفئة الفرعية ،

· ما إذا كان يمكن تعيين كل سمة أم للقراءة فقط ،

· نطاق القيم المسموح به لكل سمة.

· تطبيق عد مؤشر العد الذكي لإدارة الذاكرة.

NS-3 الكائنات التي تستخدم نظام السمات مشتق من أي منهما هدف or ObjectBase. معظم
NS-3 الأشياء التي سنناقشها مشتقة من هدف، ولكن القليل من خارج الأذكياء
مؤشر إطار إدارة الذاكرة مشتق من ObjectBase.

دعنا نراجع اثنين من خصائص هذه الكائنات.

لوحة تحكم ذكية Pointers
كما تم تقديمه في NS-3 الدورة التعليمية، NS-3 الكائنات هي الذاكرة التي تديرها أ مرجع
عد سمارت مؤشر التنفيذ، صف دراسي بي تي آر.

تُستخدم المؤشرات الذكية على نطاق واسع في ملف NS-3 واجهات برمجة التطبيقات ، لتجنب تمرير الإشارات إلى
كائنات مخصصة كومة قد تتسبب في حدوث تسرب للذاكرة. لمعظم الاستخدامات الأساسية (بناء الجملة) ، تعامل
مؤشر ذكي مثل المؤشر العادي:

Ptr الثانية = ...
nd-> CallSomeFunction () ؛
// إلخ.

إذن كيف تحصل على مؤشر ذكي لكائن ، كما في السطر الأول من هذا المثال؟

CREATEOBJECT
كما ناقشنا أعلاه في Memory-management-and-class-Ptr ، في كائنات API ذات المستوى الأدنى
من النوع هدف لا يتم إنشاء مثيل لها باستخدام عامل جديد كالمعتاد ولكن بدلاً من ذلك بواسطة قالب
وظيفة تسمى CREATEOBJECT ().

الطريقة النموذجية لإنشاء مثل هذا الكائن هي كما يلي:

Ptr nd = CreateObject () ؛

يمكنك التفكير في هذا على أنه مكافئ وظيفيًا لـ:

WifiNetDevice * nd = WifiNetDevice جديد () ؛

الأشياء التي تشتق من هدف يجب تخصيصها على الكومة باستخدام CREATEOBJECT (). أولئك
مشتقة من ObjectBase، مثل NS-3 وظائف المساعد ورؤوس الحزم والمقطورات ،
يمكن تخصيصها على المكدس.

في بعض البرامج النصية ، قد لا ترى الكثير من ملفات CREATEOBJECT () المكالمات في الكود ؛ هذا هو
لأن هناك بعض الكائنات المساعدة سارية المفعول تقوم بتنفيذ CREATEOBJECT () المكالمات
بالنسبة لك.

النوع
NS-3 الفئات التي تنبثق من الطبقة هدف يمكن أن تتضمن فئة بيانات وصفية تسمى النوع أن
يسجل المعلومات الوصفية حول الفئة ، لاستخدامها في تجميع العناصر والمكونات
أنظمة المدير:

· سلسلة فريدة تحدد الفئة.

· الصنف الأساسي للفئة الفرعية ضمن نظام البيانات الوصفية.

· مجموعة المنشئات التي يمكن الوصول إليها في الفئة الفرعية.

· قائمة بالخصائص المتاحة للجمهور ("السمات") الخاصة بالفئة.

هدف الملخص
بتجميع كل هذه المفاهيم معًا ، دعنا نلقي نظرة على مثال محدد: فئة العقدة.

ملف الرأس العام عقدة يحتوي على تصريح يتضمن ثابتًا GetTypeId ()
استدعاء الوظيفة:

فئة العقدة: الكائن العام
{
الجمهور:
TypeId ثابت GetTypeId (باطل) ؛


يتم تعريف هذا في العقدة.cc ملف على النحو التالي:

النوع
العقدة :: GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("ns3 :: Node")
.SetParent ()
.AddConstructor ()
.AddAttribute ("DeviceList"،
"قائمة الأجهزة المرتبطة بهذه العقدة."،
ObjectVectorValue () ،
MakeObjectVectorAccessor (& Node :: m_devices) ،
MakeObjectVectorChecker ())
.AddAttribute ("ApplicationList"،
"قائمة التطبيقات المرتبطة بهذه العقدة." ،
ObjectVectorValue () ،
MakeObjectVectorAccessor (& Node :: m_applications) ،
MakeObjectVectorChecker ())
.AddAttribute ("Id"،
"المعرف (عدد صحيح فريد) لهذه العقدة." ،
TypeId :: ATTR_GET، // السماح بالحصول عليه فقط.
UintegerValue (0) ،
MakeUintegerAccessor (& Node :: m_id) ،
MakeUintegerChecker ())
;
عودة المد
}

النظر في النوع ل NS-3 هدف فئة كشكل ممتد من نوع وقت التشغيل
المعلومات (RTTI). تتضمن لغة C ++ نوعًا بسيطًا من RTTI من أجل دعمها
dynamic_cast typeid العاملين.

إنّ SetParent () يتم استخدام المكالمة في التعريف أعلاه جنبًا إلى جنب مع
آليات تجميع الكائنات للسماح بصب آمن لأعلى ولأسفل في أشجار الوراثة
أثناء GETOBJECT (). كما أنه يمكّن الفئات الفرعية من وراثة سمات الوالدين
فئة.

إنّ AddConstructor () يتم استخدام المكالمة جنبًا إلى جنب مع مصنع الكائنات المجردة
آليات للسماح لنا ببناء كائنات C ++ دون إجبار المستخدم على معرفة
فئة ملموسة للكائن الذي تقوم ببنائه.

المكالمات الثلاثة ل اضف ميزة () إقران سلسلة معينة بقيمة مكتوبة بقوة في
الفصل. لاحظ أنه يجب عليك تقديم سلسلة تعليمات يمكن عرضها ، على سبيل المثال ،
بواسطة معالجات سطر الأوامر. كل السمة يرتبط بآليات الوصول
متغير العضو الأساسي في الكائن (على سبيل المثال ، MakeUintegerAccessor () يروي
العام السمة كود كيفية الحصول على معرّف العقدة أعلاه). هناك أيضا "Checker"
الطرق المستخدمة للتحقق من صحة القيم مقابل حدود النطاق ، مثل الحد الأقصى و
القيم الدنيا المسموح بها.

عندما يرغب المستخدمون في إنشاء العقد ، فعادةً ما يستدعيون شكلاً من أشكال CREATEOBJECT (),:

Ptr ن = CreateObject () ؛

أو بشكل أكثر تجريدًا ، باستخدام مصنع الكائن ، يمكنك إنشاء ملف العقدة كائن بدون حتى
معرفة نوع الخرسانة C ++:

مصنع ObjectFactory
const std :: string typeId = "ns3 :: Node ''؛
factory.SetTypeId (typeId) ؛
Ptr عقدة = مصنع () ؛

تؤدي كلتا الطريقتين إلى إتاحة سمات تمت تهيئتها بالكامل في ملف
مما أدى هدف الحالات.

نناقش بعد ذلك كيفية السمات (القيم المرتبطة بمتغيرات الأعضاء أو وظائف
الصف) في ما سبق النوع.

السمات
الهدف من نظام السمات هو تنظيم وصول كائنات الأعضاء الداخلية في ملف
محاكاة. ينشأ هذا الهدف لأنه ، عادةً في المحاكاة ، سيقطع المستخدمون و
لصق / تعديل نصوص المحاكاة الحالية ، أو ستستخدم بنيات محاكاة عالية المستوى ،
ولكن غالبًا ما يكون مهتمًا بدراسة أو تتبع متغيرات داخلية معينة. ل
على سبيل المثال ، استخدم حالات مثل:

· "I تريد إلى تتبع هيه الحزم on هيه لاسلكي الواجهة فقط on هيه أول الوصول هدف."

· "I تريد إلى تتبع هيه قيمنا of هيه TCP احتقان نافذة (كل الوقت it التغييرات) on a
خاص TCP قابس كهرباء."

· "I تريد a تفريغ of الكل القيم أن كان مستعمل in my محاكاة."

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

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

إذا نظرنا إلى إعلان DropTailQueueنرى ما يلي:

class DropTailQueue: قائمة الانتظار العامة {
الجمهور:
TypeId ثابت GetTypeId (باطل) ؛


خاص:
الأمراض المنقولة جنسيا :: قائمة الانتظار > m_packets ؛
uint32_t m_maxPackets ؛
};

لنفكر في الأشياء التي قد يرغب المستخدم في القيام بها بقيمة الحزم:

· تعيين قيمة افتراضية للنظام ، بحيث كلما كان جديدًا DropTailQueue أنشئ،
تمت تهيئة هذا العضو إلى هذا الإعداد الافتراضي.

تعيين أو الحصول على القيمة على قائمة انتظار تم إنشاء مثيل لها بالفعل.

عادة ما تتطلب الأشياء المذكورة أعلاه توفير بكج () تواصل () وظائف ، وبعض أنواع ملفات
القيمة الافتراضية العالمية.

في مجلة NS-3 نظام السمات ، وتعريفات القيمة هذه وتسجيلات وظيفة الموصل
يتم نقلها إلى النوع صف دراسي؛ على سبيل المثال.:

NS_OBJECT_ENSURE_REGISTERED (DropTailQueue) ،

النوع
DropTailQueue :: GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("ns3 :: DropTailQueue")
.SetParent ()
.AddConstructor ()
.AddAttribute ("MaxPackets"،
"الحد الأقصى لعدد الحزم المقبولة بواسطة DropTailQueue هذا." ،
UintegerValue (100) ،
MakeUintegerAccessor (& DropTailQueue :: m_maxPackets) ،
MakeUintegerChecker ())
;

عودة المد
}

إنّ اضف ميزة () الطريقة هي تنفيذ عدد من الأشياء لـ الحزم القيمة:

· ربط متغير العضو (الخاص عادة) الحزم لسلسلة عامة
"MaxPackets".

· توفير قيمة افتراضية (100 حزمة).

· تقديم بعض نصوص المساعدة لتعريف معنى القيمة.

· توفير "فاحص" (غير مستخدم في هذا المثال) يمكن استخدامه لتعيين الحدود على
نطاق القيم المسموح به.

النقطة الأساسية هي أنه يمكن الآن الوصول إلى قيمة هذا المتغير وقيمته الافتراضية
في مساحة اسم السمة ، والتي تستند إلى سلاسل مثل "MaxPackets" النوع الاسم
سلاسل. في القسم التالي ، سنقدم مثالًا على برنامج نصي يوضح كيف يمكن للمستخدمين ذلك
التلاعب بهذه القيم.

لاحظ أن تهيئة السمة تعتمد على الماكرو NS_OBJECT_ENSURE_REGISTERED
(دروبتيلكويو) يطلق عليها؛ إذا تركت هذا خارج تطبيق الفصل الجديد ، فسيكون لديك
السمات لن تتم تهيئتها بشكل صحيح.

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

توثيق مفصل للسمات الفعلية المعرفة لنوع ، وقائمة عالمية من
تتوفر جميع السمات المحددة في وثائق API. لبقية هذا
وثيقة سنقوم بتوضيح الطرق المختلفة للحصول على السمات وتعيينها
القيم.

الضبط الترتيب القيم
التكوين :: SetDefault سطر الأوامر
لنلقِ نظرة على كيفية وصول نص برمجي للمستخدم إلى قيمة سمة معينة. نحن سوف نذهب الئ
استخدم ال src / من نقطة إلى نقطة / أمثلة / main-attribute-value.cc النصي للتوضيح ، مع
تم تجريد بعض التفاصيل. ال رئيسي تبدأ الوظيفة:

// هذا مثال أساسي على كيفية استخدام نظام السمات
// تعيين والحصول على قيمة في النظام الأساسي ؛ وهي غير موقعة
// عدد صحيح من الحد الأقصى لعدد الحزم في قائمة الانتظار
//

مادبا
main (int argc، char * argv [])
{

// افتراضيًا ، تحتوي سمة MaxPackets على 100 حزمة
// (يمكن ملاحظة هذا الإعداد الافتراضي في وظيفة DropTailQueue :: GetTypeId)
//
// هنا ، قمنا بتعيينه على 80 حزمة. يمكننا استخدام نوع من نوعي القيم:
// قيمة مستندة إلى سلسلة أو قيمة Uinteger
Config :: SetDefault ("ns3 :: DropTailQueue :: MaxPackets"، StringValue ("80"))؛
// استدعاء الوظيفة أدناه زائد عن الحاجة
Config :: SetDefault ("ns3 :: DropTailQueue :: MaxPackets"، UintegerValue (80))؛

// السماح للمستخدم بتجاوز أي من الإعدادات الافتراضية وما سبق
// SetDefaults () في وقت التشغيل ، عبر وسيطات سطر الأوامر
// على سبيل المثال ، عبر "--ns3 :: DropTailQueue :: MaxPackets = 80"
CommandLine كمد ؛
// يوفر هذا طريقة أخرى لتعيين القيمة من سطر الأوامر:
cmd.AddValue ("maxPackets"، "ns3 :: DropTailQueue :: MaxPackets")؛
cmd ، Parse (argc ، argv) ؛

الشيء الرئيسي الذي يجب ملاحظته في ما سبق هما النداءان المكافئان لـ التكوين :: SetDefault
(). هذه هي الطريقة التي نعيّن بها القيمة الافتراضية لكل ما تم إنشاء مثيل له لاحقًا
DropTailQueueس. نوضح أن نوعين من القيم الطبقات ، أ قيمة السلسلة و
Uinteger القيمة class ، لتعيين قيمة للسمة المسماة بواسطة
"ns3 :: DropTailQueue :: MaxPackets".

من الممكن أيضًا معالجة السمات باستخدام امتداد سطر الأوامر؛ رأينا بعض الأمثلة
في وقت مبكر من البرنامج التعليمي. على وجه الخصوص ، من السهل إضافة حجة مختصرة
الاسم ، مثل - maxPackets، لسمة ذات صلة خاصة بنموذجك ،
في هذه الحالة "ns3 :: DropTailQueue :: MaxPackets". هذا لديه ميزة إضافية أن
ستتم طباعة سلسلة التعليمات الخاصة بالسمة كجزء من رسالة استخدام البرنامج النصي.
لمزيد من المعلومات راجع سطر الأوامر وثائق API.

الآن ، سننشئ بعض العناصر باستخدام واجهة برمجة التطبيقات ذات المستوى المنخفض. سوف قوائم الانتظار التي تم إنشاؤها حديثًا
لم يكن لديك الحزم مهيأ إلى 100 حزمة ، على النحو المحدد في
DropTailQueue :: GetTypeId () وظيفة ، ولكن إلى 80 حزمة ، بسبب ما فعلناه أعلاه
قيم افتراضية.:

Ptr n0 = CreateObject () ؛

Ptr net0 = CreateObject () ؛
n0-> AddDevice (net0) ؛

Ptr q = CreateObject () ؛
net0-> AddQueue (q) ؛

في هذه المرحلة ، أنشأنا واحدة العقدة (n0) وحيدة PointToPointNetDevice
(net0) ، وأضاف أ DropTailQueue (q) إلى net0.

المنشئون ، المساعدون ObjectFactory
مجموعات تعسفية من السمات يمكن تعيينها وجلبها من المساعد والمستوى المنخفض
واجهات برمجة التطبيقات. إما من الصانعين أنفسهم:

Ptr ع =
CreateObjectWithAttributes
("MinX"، DoubleValue (-100.0)،
"MinY"، DoubleValue (-100.0)،
"DeltaX" ، DoubleValue (5.0) ،
"DeltaY" ، DoubleValue (20.0) ،
"GridWidth" ، UintegerValue (20) ،
"LayoutType" ، StringValue ("RowFirst")) ؛

أو من واجهات برمجة التطبيقات المساعدة ذات المستوى الأعلى ، مثل:

التنقل
("ns3 :: GridPositionAllocator"،
"MinX" ، DoubleValue (-100.0) ،
"MinY"، DoubleValue (-100.0)،
"DeltaX" ، DoubleValue (5.0) ،
"DeltaY" ، DoubleValue (20.0) ،
"GridWidth" ، UintegerValue (20) ،
"LayoutType" ، StringValue ("RowFirst")) ؛

لا نوضح ذلك هنا ، ولكن يمكنك أيضًا تكوين ملف ObjectFactory بقيم جديدة
لسمات محددة. المثيلات التي تم إنشاؤها بواسطة ObjectFactory سوف يكون هؤلاء
تعيين السمات أثناء البناء. هذا مشابه جدًا لاستخدام أحد واجهات برمجة التطبيقات المساعدة
لاجل القسم.

للمراجعة ، هناك عدة طرق لتعيين قيم لسمات مثيلات الفئة إلى be
خلق in هيه المستقبل:

· التكوين :: SetDefault ()

· CommandLine :: AddValue ()

· CreateObjectWithAttributes <> ()

واجهات برمجة التطبيقات المساعدة المختلفة

ولكن ماذا لو قمت بالفعل بإنشاء مثيل ، وتريد تغيير قيمة
يصف؟ في هذا المثال ، كيف يمكننا التعامل مع الحزم قيمة بالفعل
مثيل DropTailQueue؟ فيما يلي طرق مختلفة للقيام بذلك.

متغير القيم
سمارت بوينتر
افترض أن المؤشر الذكي (بي تي آر) لجهاز الشبكة ذي الصلة في متناول اليد ؛ فى الحاضر
على سبيل المثال ، هو net0 المؤشر.

تتمثل إحدى طرق تغيير القيمة في الوصول إلى مؤشر إلى قائمة الانتظار الأساسية وتعديلها
السمة.

أولاً ، نلاحظ أنه يمكننا الحصول على مؤشر إلى (الفئة الأساسية) طابور بواسطة هيه
PointToPointNetDevice الصفات ، حيث يتم استدعاؤها "TxQueue":

المؤشر القيمة tmp ؛
net0-> GetAttribute ("TxQueue" ، tmp) ؛
Ptr txQueue = tmp.GetObject () ،

باستخدام GETOBJECT () وظيفة ، يمكننا إجراء عملية هبوط آمنة إلى ملف DropTailQueue، حيث
"MaxPackets" هي سمة:

Ptr dtq = txQueue-> GetObject () ؛
NS_ASSERT (dtq! = 0) ،

بعد ذلك ، يمكننا الحصول على قيمة سمة في قائمة الانتظار هذه. لقد قدمنا ​​المجمع
القيم فئات لأنواع البيانات الأساسية ، على غرار أغلفة Java حول هذه الأنواع ،
نظرًا لأن نظام السمات يخزن القيم المتسلسلة إلى سلاسل وليس أنواعًا متباينة.
هنا ، يتم تعيين قيمة السمة إلى Uinteger القيمة، و تواصل () طريقة على هذا
تنتج القيمة (غير مغلفة) uint32_t.:

حد القيمة ؛
dtq-> GetAttribute ("MaxPackets" ، الحد) ؛
NS_LOG_INFO ("1. حد dtq:" << limit.Get () << "حزم") ؛

لاحظ أن ما ورد أعلاه ليس مطلوبًا حقًا ؛ يمكن أن نحصل على السمة
قيمة مباشرة من com.txQueueوهو هدف:

txQueue-> GetAttribute ("MaxPackets" ، الحد) ؛
NS_LOG_INFO ("2. حد txQueue:" << limit.Get () << "الحزم")؛

الآن ، دعنا نضبطها على قيمة أخرى (60 حزمة):

txQueue-> SetAttribute ("MaxPackets" ، UintegerValue (60)) ؛
txQueue-> GetAttribute ("MaxPackets" ، الحد) ؛
NS_LOG_INFO ("3. تم تغيير حد txQueue:" << limit.Get () << "الحزم")؛

التكوين مساحة الاسم مسار
هناك طريقة بديلة للحصول على السمة وهي استخدام مساحة اسم التكوين. هنا،
هذه السمة موجودة على مسار معروف في مساحة الاسم هذه ؛ هذا النهج مفيد إذا كان أحد
ليس لديه حق الوصول إلى المؤشرات الأساسية ويرغب في تكوين ملف
ببيان واحد:

التكوين :: مجموعة ("/ NodeList / 0 / DeviceList / 0 / TxQueue / MaxPackets" ،
UintegerValue (25)) ؛
txQueue-> GetAttribute ("MaxPackets" ، الحد) ؛
NS_LOG_INFO ("4. تم تغيير حد txQueue من خلال مساحة الاسم:"
<< limit.Get () << "الحزم") ؛

غالبًا ما يتخذ مسار التكوين شكل "... /
الاسم> / /.../ / " للإشارة إلى مثيل معين بواسطة فهرس
كائن في الحاوية. في هذه الحالة ، تكون الحاوية الأولى هي قائمة الكل العقدةس؛ ال
الحاوية الثانية هي قائمة الكل NetDeviceق على المختار العقدة. وأخيرا، فإن
ينتهي مسار التكوين عادةً بتتابع سمات العضو ، وفي هذه الحالة يكون ملف
"MaxPackets" سمة من "TxQueue" من المختارين NetDevice.

كان بإمكاننا أيضًا استخدام أحرف البدل لتعيين هذه القيمة لجميع العقد وجميع أجهزة الشبكة
(والذي في هذا المثال البسيط له نفس التأثير السابق التكوين :: مجموعة ()):

التكوين :: Set ("/ NodeList / * / DeviceList / * / TxQueue / MaxPackets" ،
UintegerValue (15)) ؛
txQueue-> GetAttribute ("MaxPackets" ، الحد) ؛
NS_LOG_INFO ("5. تم تغيير حد txQueue من خلال مساحة الاسم ذات أحرف البدل:"
<< limit.Get () << "الحزم") ؛

هدف الاسم العطاء
هناك طريقة أخرى للحصول على السمة وهي استخدام مرفق خدمة اسم الكائن. ال
تسمح لنا خدمة اسم الكائن بإضافة عناصر إلى مساحة اسم التكوين أسفل
"/ أسماء /" مسار بسلسلة اسم معرفة من قبل المستخدم. هذا النهج مفيد إذا لم يكن المرء كذلك
الوصول إلى المؤشرات الأساسية ومن الصعب تحديد المطلوب
مسار مساحة التكوين الملموس.

الأسماء :: إضافة ("الخادم" ، n0) ؛
الأسماء :: Add ("server / eth0"، net0) ؛



Config :: Set ("/ Names / server / eth0 / TxQueue / MaxPackets" ، UintegerValue (25)) ؛

هنا أضفنا عناصر المسار "الخادم" "eth0" تحت "/ أسماء /" مساحة الاسم ، إذن
استخدم مسار التكوين الناتج لتعيين السمة.

انظر أسماء الكائنات للحصول على معالجة أكمل لـ NS-3 مساحة التكوين.

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

p-> Set ("cwnd"، StringValue ("100"))؛ // الواضع القائم على السلسلة
p-> Set ("cwnd"، IntegerValue (100))؛ // واضع على أساس عدد صحيح

يوفر النظام بعض وحدات الماكرو التي تساعد المستخدمين في إعلان وتعريف AttributeValue الجديد
الفئات الفرعية للأنواع الجديدة التي يريدون إدخالها في نظام السمات:

· ATTRIBUTE_HELPER_HEADER

· ATTRIBUTE_HELPER_CPP

راجع وثائق API لهذه التركيبات لمزيد من المعلومات.

التهيئة الطلب
يجب ألا تعتمد السمات في النظام على حالة أي سمة أخرى في هذا
نظام. هذا بسبب عدم تحديد طلب تهيئة السمة ، ولا
مفروض من قبل النظام. يمكن رؤية مثال محدد على ذلك في التكوين الآلي
برامج مثل متجر التكوين. على الرغم من أن نموذجًا معينًا قد يرتب ذلك بحيث السمات
تتم تهيئة بترتيب معين ، قد يقرر مُكوِّن تلقائي آخر
بشكل مستقل لتغيير السمات بترتيب أبجدي على سبيل المثال.

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

هذا قيد قوي للغاية وهناك حالات يجب فيها تعيين السمات
باستمرار للسماح بالتشغيل الصحيح. تحقيقًا لهذه الغاية ، نسمح بفحص الاتساق
متى هيه السمة is مستعمل (cf. NS_ASSERT_MSG or NS_ABORT_MSG).

بشكل عام ، رمز السمة لتعيين قيم لمتغيرات عضو الفئة الأساسية
يتم تنفيذه بعد إنشاء كائن. ولكن ماذا لو احتجت إلى تعيين القيم
قبل تنفيذ هيئة المنشئ ، لأنك تحتاجها في منطق
البناء؟ هناك طريقة للقيام بذلك ، تستخدم على سبيل المثال في الفصل متجر التكوين: يتصل
ObjectBase :: ConstructSelf () كما يلي:

ConfigStore :: ConfigStore ()
{
ObjectBase :: ConstructSelf (AttributeConstructionList ()) ؛
// تابع مع المنشئ.
}

احذر من أن الكائن وكل الأصناف المشتقة منه يجب أن يطبق أيضًا GetInstanceTypeId
() طريقة. وإلا فإن ObjectBase :: ConstructSelf () لن تكون قادرة على قراءة
الصفات.

إضافة السمات
إنّ NS-3 سيضع النظام عددًا من القيم الداخلية ضمن نظام السمات ، ولكن
مما لا شك فيه أن المستخدمين سيرغبون في تمديد هذا لالتقاط الملفات التي فاتتنا ، أو لإضافة ملفات
الفصول الخاصة بالنظام.

هناك ثلاث حالات استخدام نموذجية:

· جعل أحد أعضاء بيانات الفصل الحالي يمكن الوصول إليه كسمة ، عندما لا يكون موجودًا بالفعل.

· جعل فئة جديدة قادرة على كشف بعض أعضاء البيانات كسمات من خلال إعطائها TypeId.

· إنشاء ملف قيمة السمة فئة فرعية لفئة جديدة بحيث يمكن الوصول إليها كملف
يصف.

موجود فريقنا متغير
ضع في اعتبارك هذا المتغير في TcpSocket:

uint32_t m_cWnd ؛ // نافذة الازدحام

افترض أن شخصًا ما يعمل مع TCP أراد الحصول على قيمة هذا المتغير أو تعيينها
باستخدام نظام البيانات الوصفية. إذا لم يتم توفيرها بالفعل بواسطة NS-3، يمكن للمستخدم أن يعلن
الإضافة التالية في نظام البيانات الوصفية لوقت التشغيل (إلى ملف GetTypeId () تعريف ل
TcpSocket):

.AddAttribute ("نافذة الازدحام"،
"نافذة ازدحام Tcp (بايت)" ،
UintegerValue (1) ،
MakeUintegerAccessor (& TcpSocket :: m_cWnd) ،
MakeUintegerChecker ())

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

جديد مبوبة النوع
هنا ، نناقش التأثير على المستخدم الذي يريد إضافة فصل جديد إليه NS-3. ما
يجب القيام بأشياء إضافية لتمكينها من الاحتفاظ بصفات؟

لنفترض أن صفنا الجديد يسمى ns3 :: MyMobility، هو نوع من نماذج التنقل. أولاً،
يجب أن يرث الفصل من فئة الوالدين ، ns3 :: MobilityModel. في حركتي
الملف الاساسي:

مساحة الاسم ns3 {

فئة MyClass: public MobilityModel
{

هذا يتطلب أن نعلن GetTypeId () وظيفة. هذه وظيفة عامة من سطر واحد
تصريح:

الجمهور:
/ **
* سجل هذا النوع.
* \ إرجاع الكائن TypeId.
*/
TypeId ثابت GetTypeId (باطل) ؛

لقد قدمنا ​​بالفعل ما هو ملف النوع التعريف سيبدو في my-mobility.cc
ملف التنفيذ:

NS_OBJECT_ENSURE_REGISTERED (MyMobility) ،

النوع
MyMobility :: GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("ns3 :: MyMobility")
.SetParent ()
.SetGroupName ("التنقل")
.AddConstructor ()
.AddAttribute ("الحدود"،
"حدود المنطقة للرحلة."،
RectangleValue (مستطيل (0.0 ، 0.0 ، 100.0 ، 100.0)) ،
MakeRectangleAccessor (& MyMobility :: m_bounds) ،
MakeRectangleChecker ())
.AddAttribute ("الوقت"،
"تغيير الاتجاه الحالي والسرعة بعد التحرك لهذا التأخير." ،
TimeValue (ثواني (1.0)) ،
MakeTimeAccessor (و MyMobility :: m_modeTime) ،
ميك تايم تشيكر ())
// الخ (المزيد من المعلمات).
;
عودة المد
}

إذا لم نرغب في فصل فئة فرعية من فئة موجودة ، فإننا نرث فقط في ملف الرأس
تبدأ من ns3 :: الكائن، وفي ملف الكائن ، قمنا بتعيين الفئة الأصل إلى ns3 :: الكائن مع
.SetParent ().

تتضمن الأخطاء النموذجية هنا:

· عدم الاتصال NS_OBJECT_ENSURE_REGISTERED ()

· عدم استدعاء Setparent () الطريقة ، أو تسميتها بالنوع الخطأ.

· عدم استدعاء AddConstructor () الطريقة ، أو تسميتها بالنوع الخطأ.

· إدخال خطأ مطبعي باسم النوع في منشئها.

· عدم استخدام اسم نوع C ++ المؤهل بالكامل لفئة C ++ المرفقة كاسم للملف
النوع. لاحظ أن "ns3 ::" هو مطلوب.

لا يمكن اكتشاف أي من هذه الأخطاء بواسطة NS-3 codebase ، لذلك يُنصح المستخدمون بالتحقق
بعناية عدة مرات أنهم حصلوا عليها بشكل صحيح.

جديد قيمة السمة النوع
من وجهة نظر المستخدم الذي يكتب صنفًا جديدًا في النظام ويريده أن يكون
يمكن الوصول إليها كسمة ، هناك بشكل أساسي مسألة كتابة التحويلات من / إلى
السلاسل وقيم السمات. يمكن نسخ / لصق معظم هذا برمز مكروي. ل
على سبيل المثال ، ضع في اعتبارك إعلان فئة لـ مستطيل في ال src / التنقل / النموذج دليل:

رأس قم بتقديم
/ **
* \ مختصر مستطيل ثنائي الأبعاد
*/
فئة مستطيل
{


xMin مزدوج.
xMax مزدوج ؛
ضعف yMin ؛
مزدوج yMax
};

يجب إضافة مكالمة ماكرو واثنين من المشغلين أسفل إعلان الفئة من أجل
تحويل المستطيل إلى قيمة يمكن استخدامها بواسطة السمة النظام:

std :: ostream & عامل << (std :: ostream & os، const Rectangle & rectangle)؛
std :: istream & عامل >> (std :: istream & is، Rectangle & rectangle)؛

ATTRIBUTE_HELPER_HEADER (مستطيل) ،

تطبيق قم بتقديم
في تعريف الفصل (. سم مكعب ملف) ، يبدو الرمز كما يلي:

ATTRIBUTE_HELPER_CPP (مستطيل) ،

الأمراض المنقولة جنسيا :: ostream &
عامل التشغيل << (الأمراض المنقولة جنسيا :: ostream & os، const Rectangle & Rectangle)
{
نظام التشغيل << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|"
<< rectangle.yMax؛
عودة نظام التشغيل
}
الأمراض المنقولة جنسيا :: istream &
عامل >> (std :: istream & is، Rectangle & rectangle)
{
شار c1 ، c2 ، c3 ؛
هو >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3
>> مستطيل.
إذا (c1! = '|' ||
c2! = '|' ||
c3! = '|')
{
is.setstate (std :: ios_base :: failbit) ؛
}
العودة
}

عوامل التدفق هذه تتحول ببساطة من تمثيل سلسلة للمستطيل
("xMin | xMax | yMin | yMax") إلى المستطيل الأساسي. يجب على المصمم تحديد هذه
العوامل والتمثيل النحوي للسلسلة لمثيل من الفئة الجديدة.

متجر التكوين
قيم NS-3 يمكن تخزين السمات في ملف نصي ASCII أو XML وتحميلها في ملف
تشغيل المحاكاة في المستقبل. تُعرف هذه الميزة باسم NS-3 ConfigStore. ال متجر التكوين is
قاعدة بيانات متخصصة لقيم السمات والقيم الافتراضية.

على الرغم من أنها وحدة يتم الاحتفاظ بها بشكل منفصل في src / config-store / دليل ، نحن
قم بتوثيقها هنا بسبب اعتمادها الوحيد على NS-3 الوحدة الأساسية والسمات.

يمكننا استكشاف هذا النظام باستخدام مثال من
src / config-store / أمثلة / config-store-save.cc.

أولاً ، كل مستخدمي متجر التكوين يجب أن يتضمن البيان التالي:

#include "ns3 / config-store-module.h"

بعد ذلك ، يضيف هذا البرنامج كائنًا نموذجيًا تكوين مثال لتوضيح كيف يتم توسيع النظام:

فئة ConfigExample: الكائن العام
{
الجمهور:
ثابت TypeId GetTypeId (باطل) {
ثابت TypeId tid = TypeId ("ns3 :: A")
.SetParent ()
.AddAttribute ("TestInt16" ، "نص المساعدة" ،
عدد صحيح (-2) ،
MakeIntegerAccessor (& A :: m_int16) ،
MakeIntegerChecker ())
;
عودة المد
}
int16_t m_int16 ؛
};

NS_OBJECT_ENSURE_REGISTERED (ConfigExample) ،

بعد ذلك ، نستخدم نظام التهيئة الفرعي لتجاوز الإعدادات الافتراضية بطريقتين:

Config :: SetDefault ("ns3 :: ConfigExample :: TestInt16"، IntegerValue (-5))؛

Ptr a_obj = CreateObject () ؛
NS_ABORT_MSG_UNLESS (a_obj-> m_int16 == -5 ،
"لا يمكن تعيين سمة العدد الصحيح لـ ConfigExample عبر Config :: SetDefault") ؛

Ptr a2_obj = CreateObject () ؛
a2_obj-> SetAttribute ("TestInt16"، IntegerValue (-3)) ؛
عدد صحيح
a2_obj-> GetAttribute ("TestInt16"، iv) ؛
NS_ABORT_MSG_UNLESS (iv.Get () == -3 ،
"لا يمكن تعيين سمة العدد الصحيح لـ ConfigExample عبر SetAttribute") ؛

العبارة التالية ضرورية للتأكد من أن (أحد) الكائنات التي تم إنشاؤها متجذر
في مساحة اسم التكوين كمثيل كائن. هذا يحدث عادة عندما
تجميع الأشياء إلى أ ns3 :: عقدة or ns3 :: قناة على سبيل المثال ، ولكن هنا ، لأننا نعمل
على المستوى الأساسي ، نحتاج إلى إنشاء كائن مساحة اسم جذر جديد:

التكوين :: RegisterRootNamespaceObject (a2_obj) ،

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

هناك ثلاث سمات تحكم سلوك ConfigStore: "وضع",
"اسم الملف"و "تنسيق الملف". الوضع (الافتراضي "لا أحد") بتكوين ما إذا كان NS-3 ينبغي
تحميل التكوين من ملف محفوظ مسبقًا (حدد "الوضع = تحميل") أو احفظه في ملف
(حدد "الوضع = حفظ"). اسم الملف (الافتراضي "") هو المكان الذي يجب أن يقرأ فيه ConfigStore أو
اكتب بياناتها. تنسيق الملف (افتراضي "RawText") ما إذا كان تنسيق ConfigStore
نص عادي أو Xml ("FileFormat = Xml")

المثال يوضح:

Config :: SetDefault ("ns3 :: ConfigStore :: Filename"، StringValue ("output-attributes.xml")) ؛
Config :: SetDefault ("ns3 :: ConfigStore :: FileFormat"، StringValue ("Xml"))؛
Config :: SetDefault ("ns3 :: ConfigStore :: Mode" ، StringValue ("حفظ")) ؛
ConfigStore outputConfig ؛
outputConfig.ConfigureDefaults () ،
outputConfig.ConfigureAttributes () ،

// مخزن تكوين الإخراج إلى تنسيق txt
Config :: SetDefault ("ns3 :: ConfigStore :: Filename"، StringValue ("output-attributes.txt")) ؛
Config :: SetDefault ("ns3 :: ConfigStore :: FileFormat"، StringValue ("RawText"))؛
Config :: SetDefault ("ns3 :: ConfigStore :: Mode" ، StringValue ("حفظ")) ؛
ConfigStore outputConfig2 ؛
outputConfig2.ConfigureDefaults () ،
outputConfig2.ConfigureAttributes () ،

محاكي :: تشغيل () ؛

جهاز محاكاة :: تدمير () ؛

لاحظ موضع هذه البيانات قبل محاكي :: تشغيل () بيان.
يسجل هذا الإخراج جميع القيم في مكانها قبل بدء المحاكاة (أي.
بعد إجراء كل التكوين).

بعد الجري ، يمكنك فتح ملف سمات الإخراج. txt ملف وانظر:

الافتراضي ns3 :: RealtimeSimulatorImpl :: SynchronizationMode "BestEffort"
الافتراضي ns3 :: RealtimeSimulatorImpl :: HardLimit "+ 100000000.0ns"
الافتراضي ns3 :: PcapFileWrapper :: CaptureSize "65535"
الافتراضي ns3 :: PacketSocket :: RcvBufSize "131072"
الافتراضي ns3 :: ErrorModel :: IsEnabled "صحيح"
الافتراضي ns3 :: RateErrorModel :: ErrorUnit "EU_BYTE"
الافتراضي ns3 :: RateErrorModel :: ErrorRate "0"
الافتراضي ns3 :: RateErrorModel :: RanVar "Uniform: 0: 1"
الافتراضي ns3 :: DropTailQueue :: Mode "حزم"
الافتراضي ns3 :: DropTailQueue :: MaxPackets "100"
الافتراضي ns3 :: DropTailQueue :: MaxBytes "6553500"
الافتراضي ns3 :: Application :: StartTime "+ 0.0ns"
الافتراضي ns3 :: Application :: StopTime "+ 0.0ns"
ns3 الافتراضي :: ConfigStore :: Mode "حفظ"
الافتراضي ns3 :: ConfigStore :: Filename "output-attributes.txt"
ns3 الافتراضي :: ConfigStore :: FileFormat "RawText"
ns3 الافتراضي :: ConfigExample :: TestInt16 "-5"
RngSeed العالمية "1"
RngRun العالمية "1"
Global SimulatorImplementationType "ns3 :: DefaultSimulatorImpl"
Global SchedulerType "ns3 :: MapScheduler"
ChecksumEnabled العمومية "خطأ"
القيمة / $ ns3 :: ConfigExample / TestInt16 "-3"

في ما سبق ، يتم عرض جميع القيم الافتراضية لسمات الوحدة الأساسية.
ثم ، كل قيم NS-3 يتم تسجيل القيم العالمية. أخيرًا ، قيمة
حالة تكوين مثال التي تم تجذيرها في مساحة اسم التكوين. في
حقيقي NS-3 البرنامج ، سيتم عرض العديد من النماذج والسمات والافتراضيات.

يوجد إصدار XML أيضًا في سمات الإخراج.xml:




























يمكن أرشفة هذا الملف باستخدام برنامج المحاكاة النصي وبيانات الإخراج.

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

Config :: SetDefault ("ns3 :: ConfigStore :: Filename"، StringValue ("input-defaults.xml")) ؛
التكوين :: SetDefault ("ns3 :: ConfigStore :: Mode" ، StringValue ("تحميل")) ؛
Config :: SetDefault ("ns3 :: ConfigStore :: FileFormat"، StringValue ("Xml"))؛
ConfigStore inputConfig ؛
inputConfig.ConfigureDefaults () ،

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

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

عندما متجر التكوين الكائن هو مثيل ، سماته "اسم الملف", "وضع"و
"تنسيق الملف" يجب تعيين إما بواسطة سطر الأوامر أو بواسطة بيانات البرنامج.

القراءة / الكتابة مثال
كمثال أكثر تعقيدًا ، لنفترض أننا نريد أن نقرأ في تكوين
الافتراضات من ملف الإدخال المسمى المدخلات الافتراضية. xmlواكتب النتيجة
سمات إلى ملف منفصل يسمى سمات الإخراج.xml.:

#include "ns3 / config-store-module.h"

انت مين (...)
{

Config :: SetDefault ("ns3 :: ConfigStore :: Filename"، StringValue ("input-defaults.xml")) ؛
التكوين :: SetDefault ("ns3 :: ConfigStore :: Mode" ، StringValue ("تحميل")) ؛
Config :: SetDefault ("ns3 :: ConfigStore :: FileFormat"، StringValue ("Xml"))؛
ConfigStore inputConfig ؛
inputConfig.ConfigureDefaults () ،

//
// السماح للمستخدم بتجاوز أي من الإعدادات الافتراضية و Bind () أعلاه في
// وقت التشغيل ، وسيطات سطر الأوامر
//
CommandLine كمد ؛
cmd ، Parse (argc ، argv) ؛

// طوبولوجيا الإعداد


// استدعاء قبل الدخول إلى Simulator :: Run ()
Config :: SetDefault ("ns3 :: ConfigStore :: Filename"، StringValue ("output-attributes.xml")) ؛
Config :: SetDefault ("ns3 :: ConfigStore :: Mode" ، StringValue ("حفظ")) ؛
ConfigStore outputConfig ؛
outputConfig.ConfigureAttributes () ،
محاكي :: تشغيل () ؛
}

متجر التكوين GUI
هناك واجهة أمامية مستندة إلى GTK لـ ConfigStore. هذا يسمح للمستخدمين باستخدام واجهة المستخدم الرسومية ل
الوصول إلى المتغيرات وتغييرها. تتوفر لقطات شاشة لهذه الميزة في ملف | ns3 |
نظرة عامة عرض.

لاستخدام هذه الميزة ، يجب على المرء تثبيت libgtk libgtk- ديف؛ مثال على أوبونتو
أمر التثبيت هو:

sudo apt-get install libgtk2.0-0 libgtk2.0-dev

للتحقق مما إذا كان قد تم تكوينه أم لا ، تحقق من إخراج الخطوة:

تكوين $ ./waf - أمثلة قابلة للتمكين - اختبارات التمكين

---- ملخص لميزات NS-3 الاختيارية:
ربط بايثون: مُمكّن
دعم Python API Scanning: مُمكّن
NS-3 انقر فوق دمج: ممكّن
GtkConfigStore: غير ممكّن (المكتبة 'gtk + -2.0> = 2.12' غير موجودة)

في المثال أعلاه ، لم يتم تمكينه ، لذا لا يمكن استخدامه حتى يتم إصدار إصدار مناسب
مثبت و:

تكوين $ ./waf - أمثلة قابلة للتمكين - اختبارات التمكين
$ ./واف

يتم إعادة تشغيله.

الاستخدام مماثل للإصدار غير المستند إلى GTK تقريبًا ، لكن لا يوجد متجر التكوين
السمات المشاركة:

// استدعاء قبل الدخول إلى Simulator :: Run ()
تكوين GtkConfigStore ؛
config.ConfigureDefaults () ،
config.ConfigureAttributes () ،

الآن ، عند تشغيل البرنامج النصي ، يجب أن تظهر واجهة المستخدم الرسومية ، مما يسمح لك بفتح قوائم
سمات على عقد / كائنات مختلفة ، ثم قم بتشغيل تنفيذ المحاكاة عندما تقوم بذلك
منتهي.

Future العمل
هناك نوعان من التحسينات الممكنة:

حفظ رقم إصدار فريد مع التاريخ والوقت في بداية الملف.

حفظ rng البذور الأولية في مكان ما.

· اجعل كل RandomVariable تسلسلًا للبذور الأولية الخاصة به وأعد قراءتها لاحقًا.

هدف أسماء
نائب الفصل

تسجيل
إنّ NS-3 يمكن استخدام وسيلة التسجيل لمراقبة أو تصحيح تقدم المحاكاة
البرامج. يمكن تمكين إخراج التسجيل من خلال بيانات البرنامج في ملف الأساسية() برنامج أو
عن طريق استخدام NS_LOG متغيرات البيئة.

لا يتم تجميع بيانات التسجيل في بنيات محسّنة لـ NS-3. لاستخدام التسجيل ، واحد
يجب إنشاء بنية تصحيح الأخطاء (الافتراضية) لـ NS-3.

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

نظرة عامة
NS-3 تُستخدم عبارات التسجيل عادةً لتسجيل أحداث تنفيذ البرنامج المختلفة ، مثل
مثل حدوث أحداث المحاكاة أو استخدام وظيفة معينة.

على سبيل المثال ، مقتطف الشفرة هذا من IPv4L3Protocol :: IsDestinationAddress ():

إذا (العنوان == iaddr.GetBroadcast ())
{
NS_LOG_LOGIC ("بالنسبة لي (عنوان بث الواجهة)") ؛
عودة صحيح؛
}

إذا تم تمكين التسجيل لـ بروتوكول IPv4L3 المكون في شدة منطق or
أعلاه (انظر أدناه حول خطورة السجل) ، ستتم طباعة البيان ؛ وإلا فإنه
سيتم قمعها.

تمكين الناتج
هناك طريقتان يتحكم فيهما المستخدمون عادةً في إخراج السجل. الأول هو عن طريق تحديد
NS_LOG متغيرات البيئة؛ على سبيل المثال:

NS_LOG $ = "*" ./waf - تشغيل أولاً

سيدير ​​ال أول برنامج تعليمي مع كل مخرجات التسجيل. (تفاصيل ملف NS_LOG
الشكل أدناه.)

يمكن جعل هذا أكثر دقة عن طريق اختيار المكونات الفردية:

NS_LOG $ = "Ipv4L3Protocol" ./waf - تشغيل أولاً

يمكن تصميم الإخراج بشكل أكبر باستخدام خيارات البادئة.

الطريقة الثانية لتمكين التسجيل هي استخدام عبارات صريحة في برنامجك ، مثل في
هيه أول برنامج تعليمي:

مادبا
main (int argc، char * argv [])
{
LogComponentEnable ("UdpEchoClientApplication" ، LOG_LEVEL_INFO) ،
LogComponentEnable ("UdpEchoServerApplication" ، LOG_LEVEL_INFO) ،


(معنى LOG_LEVEL_INFOوالقيم المحتملة الأخرى أدناه.)

NS_LOG بناء الجملة
إنّ NS_LOG يحتوي متغير البيئة على قائمة بمكونات وخيارات السجل. سجل
المكونات مفصولة بأحرف ":":

NS_LOG دولار = " : ... "

يتم تقديم خيارات كل مكون من مكونات السجل كعلامات بعد كل مكون من مكونات السجل:

NS_LOG دولار = " = | ...: ... "

تتحكم الخيارات في خطورة ومستوى هذا المكون ، وما إذا كان اختياريًا
يجب تضمين المعلومات ، مثل وقت المحاكاة ، عقدة المحاكاة ، الوظيفة
الاسم والخطورة الرمزية.

سجل مكونات
بشكل عام ، يشير مكون السجل إلى شفرة مصدر واحدة . سم مكعب الملف ، ويشتمل على ملف
الملف بأكمله.

بعض المساعدين لديهم طرق خاصة لتمكين تسجيل جميع المكونات في الوحدة النمطية ،
تغطي وحدات ترجمة مختلفة ، ولكنها مجمعة منطقيًا معًا ، مثل NS-3
كود wifi:

WifiHelper wifi مساعد ؛
wifiHelper.EnableLogComponents () ،

إنّ NS_LOG حرف البدل لمكون السجل "*" سيمكن جميع المكونات.

لمعرفة مكونات السجل المحددة ، سيعمل أي من هذه المكونات:

NS_LOG $ = "قائمة الطباعة". / waf - تشغيل ...

$ NS_LOG = "foo" # a رمز مميز لا يتطابق مع أي مكون سجل

سيطبع النموذج الأول الاسم والعلامات الممكّنة لجميع مكونات السجل
مرتبطة في ؛ جربها مع محاكي الخدش. النموذج الثاني يطبع كل السجل المسجل
المكونات ، ثم الخروج مع وجود خطأ.

خطورة مستوى مزيد من الخيارات
تنتمي الرسائل الفردية إلى "فئة خطورة" واحدة ، يتم تعيينها بواسطة الماكرو الذي ينشئ ملف
رسالة. في المثال أعلاه ، NS_LOG_LOGIC (..) يقوم بإنشاء الرسالة بتنسيق LOG_LOGIC
فئة الشدة.

يتم تعريف فئات الخطورة التالية على أنها التعداد الثوابت:

┌───────────────┬───────────────────────────────── ─┐
"فئة الخطورة" المعنى "
├───────────────┼───────────────────────────────── ─┤
LOG_NONE │ الافتراضي ، لا تسجيل │
├───────────────┼───────────────────────────────── ─┤
سجل_خطأ │ رسائل خطأ جسيمة فقط │
├───────────────┼───────────────────────────────── ─┤
LOG_WARN │ رسائل التحذير │
├───────────────┼───────────────────────────────── ─┤
LOG_DEBUG │ للاستخدام في التصحيح │
├───────────────┼───────────────────────────────── ─┤
LOG_INFO إعلامي
├───────────────┼───────────────────────────────── ─┤
LOG_FUNCTION وظيفة التتبع │
├───────────────┼───────────────────────────────── ─┤
LOG_LOGIC التحكم في تتبع التدفق داخل │
│ │ وظائف │
└───────────────┴───────────────────────────────── ─┘

عادةً ما يرغب المرء في رؤية الرسائل في فئة خطورة معينة أعلى. يتم ذلك عن طريق
تحديد "مستويات" التسجيل الشامل:

┌───────────────────┬───────────────────────────── ─────┐
"المستوى" المعنى "
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_ERROR │ فقط سجل_خطأ فئة الخطورة │
│ │ الرسائل. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_WARNLOG_WARN و ما فوق. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_DEBUGLOG_DEBUG و ما فوق. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_INFOLOG_INFO و ما فوق. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_FUNCTIONLOG_FUNCTION و ما فوق. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_LOGICLOG_LOGIC و ما فوق. │
├───────────────────┼───────────────────────────── ─────┤
LOG_LEVEL_ALL │ جميع فئات الخطورة. │
├───────────────────┼───────────────────────────── ─────┤
تسجيل_الكل │ مرادف ل LOG_LEVEL_ALL
└───────────────────┴───────────────────────────── ─────┘

يمكن إعطاء خيارات الدرجة ومستوى الخطورة في ملف NS_LOG متغير البيئة
هذه الرموز المميزة:

┌────────────────────────┐
"فئة" مستوى "
├─────────┼──────────────┤
خطأمستوى_خطأ
├─────────┼──────────────┤
حذرمستوى_حذير
├─────────┼──────────────┤
تصحيحمستوى_تفسير
├─────────┼──────────────┤
infoمستوى_المعلومات
├─────────┼──────────────┤
وظيفةوظيفة_المستوى
├─────────┼──────────────┤
منطقمنطق_المستوى
├─────────┼──────────────┤
│ │ مستوى_جميع
│ │ الكل
│ │ *
└─────────┴──────────────┘

يؤدي استخدام رمز مميز لفئة الخطورة إلى تمكين رسائل السجل بهذه الدرجة من الخطورة فقط. على سبيل المثال،
NS_LOG = "* = تحذير" لن يخرج رسائل بخطورة خطأ. NS_LOG = "* = level_debug" سوف
رسائل الإخراج على مستويات الخطورة تصحيح و ما فوق.

يمكن دمج فئات ومستويات الخطورة مع "|" المشغل أو العامل:
NS_LOG = "* = level_warn | منطق" ستخرج الرسائل عند مستويات الخطورة خطأ, حذر منطق.

إنّ NS_LOG مستوى الخطورة wildcard "*" و الكل مرادفات ل مستوى_جميع.

لمكونات السجل المذكورة فقط في NS_LOG

NS_LOG دولار = " : ... "

الخطورة الافتراضية هي LOG_LEVEL_ALL.

بادئة مزيد من الخيارات
يمكن أن يساعد عدد من البادئات في تحديد مكان ووقت ظهور الرسالة ، ووقت حدوث ذلك
خطورة.

خيارات البادئة المتاحة (مثل التعداد الثوابت) هي

┌─────────────────┬─────────────────────────────── ───┐
│ رمز البادئة │ المعنى
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_FUNC بادئة اسم المتصل
│ │ وظيفة. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_TIME بادئة وقت المحاكاة. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_NODE │ بادئة معرف العقدة. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_LEVEL │ بادئة مستوى الخطورة. │
├─────────────────┼─────────────────────────────── ───┤
LOG_PREFIX_ALL │ قم بتمكين كل البادئات. │
└─────────────────┴─────────────────────────────── ───┘

تم وصف خيارات البادئة باختصار أدناه.

يمكن إعطاء الخيارات في NS_LOG متغير البيئة من خلال هذه الرموز المميزة:

┌───────────┬───────────┐
│ الكلام │ البديل │
├───────────┼───────────┤
prefix_funcظائفها
├───────────┼───────────┤
بادئة_وقتالوقت
└───────────┴───────────┘

رمز البادئةالعقدة
├───────────┼───────────┤
prefix_levelمستوى
├───────────┼───────────┤
بادئة_جميعالكل
│ │ *
└───────────┴───────────┘

لمكونات السجل المذكورة فقط في NS_LOG

NS_LOG دولار = " : ... "

خيارات البادئة الافتراضية هي LOG_PREFIX_ALL.

خطورة بادئة
يمكن تضمين فئة خطورة الرسالة مع الخيارات prefix_level or مستوى.
على سبيل المثال ، هذه القيمة NS_LOG يتيح التسجيل لجميع مكونات السجل ("*") وجميع
فئات الشدة (= الكل) ، وتبدأ الرسالة بفئة الخطورة (| prefix_level).

$ NS_LOG = "* = all | prefix_level" ./waf - تشغيل محاكاة الخدش
محاكي الصفر
[ERROR] رسالة خطأ
[تحذير] رسالة تحذير
[تصحيح] رسالة التصحيح
[INFO] رسالة معلومات
[وظيفة] رسالة وظيفة
[المنطق] رسالة المنطق

الوقت: بادئة
يمكن تضمين وقت المحاكاة مع الخيارات بادئة_وقت or الوقت . هذا يطبع ملف
وقت المحاكاة بالثواني.

العقدة بادئة
يمكن تضمين معرف عقدة المحاكاة مع الخيارات رمز البادئة or العقدة.

الوظيفة بادئة
يمكن تضمين اسم وظيفة الاستدعاء مع الخيارات prefix_func or ظائفها.

NS_LOG البدل
سيمكن حرف البدل لمكون السجل "*" جميع المكونات. لتمكين جميع المكونات في
استخدام مستوى الخطورة المحدد * =.

يعد حرف البدل لخيار مستوى الخطورة "*" مرادفًا لـ الكل. يجب أن يحدث هذا قبل أي
"|" خيارات فصل الأحرف. لتمكين جميع فئات الخطورة ، استخدم = *,
or = * |.

خيار حرف البدل "*" أو الرمز المميز الكل تمكن جميع خيارات البادئة ، ولكن يجب أن تحدث بعد a
"|" شخصية. لتمكين فئة أو مستوى خطورة معين وجميع البادئات ، استخدم
= | *.

خيار الجمع بين أحرف البدل ** تمكن جميع درجات الخطورة وجميع البادئات ؛ على سبيل المثال،
= **.

أوبر وايلد كارد *** يُمكّن كل درجات الخطورة وجميع البادئات لجميع مكونات السجل.
هذه كلها متكافئة:

$ NS_LOG = "***" ... $ NS_LOG = "* = الكل | *" ... $ NS_LOG = "* = * | الكل" ...
$ NS_LOG = "* = **" ... $ NS_LOG = "* = level_all | *" ... $ NS_LOG = "* = * | prefix_all" ...
NS_LOG $ = "* = * | *" ...

كن على علم: حتى التافه محاكي الخدش تنتج أكثر من 46 ألف خط إنتاج مع
NS_LOG = "***"!

كيفية إلى تضيف تسجيل إلى لك الكود
تعد إضافة التسجيل إلى التعليمات البرمجية الخاصة بك أمرًا بسيطًا للغاية:

1. استدعاء NS_LOG_COMPONENT_DEFINE (...) ؛ داخل الماكرو مساحة الاسم ns3.
قم بإنشاء معرف سلسلة فريد (يعتمد عادةً على اسم الملف و / أو الفئة
المحدد داخل الملف) وقم بتسجيله باستدعاء ماكرو مثل:

مساحة الاسم ns3 {

NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol") ؛


هذا يسجل بروتوكول IPv4L3 كعنصر سجل.

(تمت كتابة الماكرو بعناية للسماح بالتضمين إما داخل أو خارج
مساحة الاسم ns3، وسيختلف الاستخدام عبر مصدر الشفرة ، لكن القصد الأصلي كان
سجل هذا في الخارج من مساحة الاسم ns3 في النطاق العام للملف.)

2. إضافة بيانات التسجيل (استدعاءات الماكرو) إلى وظائفك والهيئات الوظيفية.

تسجيل وحدات الماكرو
وحدات ماكرو التسجيل ومستويات الخطورة المرتبطة هي

┌─────────────┬──────────────────── ─┐
فئة الخطورة │ ماكرو │
├─────────────┼──────────────────── ─┤
LOG_NONE │ (لا حاجة) │
├─────────────┼──────────────────── ─┤
سجل_خطأNS_LOG_ERROR (...) ؛
├─────────────┼──────────────────── ─┤
LOG_WARNNS_LOG_WARN (...) ؛
├─────────────┼──────────────────── ─┤
LOG_DEBUGNS_LOG_DEBUG (...) ؛
├─────────────┼──────────────────── ─┤
LOG_INFONS_LOG_INFO (...) ؛
├─────────────┼──────────────────── ─┤
LOG_FUNCTIONNS_LOG_FUNCTION (...) ؛
├─────────────┼──────────────────── ─┤
LOG_LOGICNS_LOG_LOGIC (...) ؛
└─────────────┴──────────────────── ─┘

تعمل وحدات الماكرو كإخراج متدفق ، لذا يمكنك إرسال أي شيء إليه الأمراض المنقولة جنسيا :: كوت، انضم
by << المشغلين ، مسموح لهم:

void MyClass :: Check (int value، char * item)
{
NS_LOG_FUNCTION (هذا << arg << عنصر) ؛
إذا (arg> 10)
{
NS_LOG_ERROR ("تمت مصادفة قيمة سيئة" << قيمة <
"أثناء تحديد" << name << "!") ؛
}

}

نلاحظ أن NS_LOG_FUNCTION يقوم تلقائيًا بإدراج ملف,'(مسافة فاصلة) بين
كل من حججه. هذا يبسط تسجيل وسيطات الدالة ؛ فقط تسلسل
لهم << كما في المثال أعلاه.

غير مشروط تسجيل
كوسيلة راحة ، فإن NS_LOG_UNCOND (...) ؛ سيسجل الماكرو دائمًا وسيطاته ، حتى لو
لم يتم تمكين مكون السجل المرتبط بأي درجة خطورة. لا يستخدم هذا الماكرو أي
من خيارات البادئة. لاحظ أن التسجيل ممكّن فقط في إصدارات التصحيح ؛ هذا الماكرو
لن تنتج مخرجات في بنيات محسّنة.

التوجيهات
· ابدأ كل فصل مع طريقة NS_LOG_FUNCTION (هذه << أرغس ...) ؛ هذا يجعل من السهل
وظيفة تتبع المكالمات.

باستثناء: لا تسجل المشغلين أو منشئي النسخ الصريحين ، لأن ذلك سيؤدي إلى حدوث ذلك
العودية اللانهائية وتجاوز المكدس.

· بالنسبة إلى الطرق التي لا تحتوي على وسيطات ، استخدم نفس النموذج: NS_LOG_FUNCTION (هذا)؛

· للوظائف الثابتة:

مع استخدام الحجج NS_LOG_FUNCTION (...) ؛ كالطبيعي.

· بدون استخدام الحجج NS_LOG_FUNCTION_NOARGS ()؛

· يستخدم NS_LOG_ERROR لحالات الخطأ الجسيم التي من المحتمل أن تبطل المحاكاة
تنفيذ.

· يستخدم NS_LOG_WARN للحالات غير العادية التي قد تكون قابلة للتصحيح. يرجى إعطاء بعض التلميحات
من حيث طبيعة المشكلة وكيف يمكن تصحيحها.

· NS_LOG_DEBUG عادة ما يستخدم في ملف ad خاص طريقة لفهم تنفيذ النموذج.

· يستخدم NS_LOG_INFO للحصول على معلومات إضافية حول التنفيذ ، مثل حجم ملف
هيكل البيانات عند الإضافة / الإزالة منه.

· يستخدم NS_LOG_LOGIC لتتبع الفروع المنطقية المهمة داخل دالة.

· اختبار أن تغييرات التسجيل الخاصة بك لا تكسر الكود. قم بتشغيل بعض أمثلة البرامج باستخدام
تم تشغيل كافة مكونات السجل (على سبيل المثال NS_LOG = "***").

البحث عن المفقودين
يعد نظام التتبع الفرعي أحد أهم الآليات التي يجب فهمها NS-3. في
أغلب الحالات، NS-3 سيكون لدى المستخدمين فكرة رائعة لبعض الشبكات الجديدة والمحسّنة
ميزة. من أجل التحقق من نجاح هذه الفكرة ، سيقوم الباحث بإجراء تغييرات على ملف
النظام الحالي ثم قم بإجراء التجارب لمعرفة كيف تتصرف الميزة الجديدة من خلال التجميع
الإحصاءات التي تلتقط سلوك الميزة.

وبعبارة أخرى ، فإن الهدف الكامل من تشغيل المحاكاة هو توليد المزيد من المخرجات
يذاكر. في NS-3، النظام الفرعي الذي يمكّن الباحث من القيام بذلك هو التتبع
النظام الفرعي.

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

#يشمل

انت مين ()
{

std :: cout << "قيمة x هي" << x << std :: endl؛

}

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

شيء آخر يجب مراعاته هو أنه في كل مرة تكون هناك حاجة إلى معلومة جديدة ، جوهر البرنامج
يجب تحريره وإدخال نسخة أخرى. لا توجد طريقة موحدة للتحكم في كل شيء
من هذا الناتج ، وبالتالي فإن مقدار الإنتاج يميل إلى النمو بدون حدود. في النهاية ،
يبدأ النطاق الترددي المطلوب لإخراج هذه المعلومات ببساطة في الحد من وقت التشغيل
من المحاكاة. تنمو ملفات الإخراج إلى أحجام هائلة ويصبح تحليلها ملف
المشكلة.

NS-3 يوفر آلية بسيطة للتسجيل وتوفير بعض التحكم في الإخراج عبر
سجل مكونات، لكن مستوى التحكم ليس دقيقًا جدًا على الإطلاق. التسجيل
الوحدة هي أداة حادة نسبيًا.

من المستحسن أن يكون لديك مرفق يسمح للمرء بالوصول إلى النظام الأساسي وفقط
الحصول على المعلومات المطلوبة دون الحاجة إلى تغيير وإعادة تجميع النظام الأساسي. حتى
من الأفضل أن يكون النظام الذي يخطر المستخدم عند تغيير عنصر الاهتمام أو
حدث مثير للاهتمام.

إنّ NS-3 تم تصميم نظام التتبع للعمل على طول هذه الخطوط ومتكامل بشكل جيد مع
تسمح السمة والتهيئة الفرعية لسيناريوهات الاستخدام البسيطة نسبيًا.

نظرة عامة
يعتمد نظام التتبع الفرعي بشكل كبير على NS-3 آليات رد الاتصال والسمة. أنت
يجب قراءة وفهم الأقسام المقابلة من الدليل قبل محاولة ذلك
فهم نظام التعقب.

إنّ NS-3 نظام التتبع مبني على مفاهيم مصادر التتبع المستقلة و
تتبع الأحواض إلى جانب آلية موحدة لربط المصادر بالأحواض.

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

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

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

يمكن أن يكون هناك صفر أو أكثر من المستهلكين لأحداث التتبع التي تم إنشاؤها بواسطة مصدر التتبع. يمكن للمرء
فكر في مصدر التتبع كنوع من ارتباط المعلومات من نقطة إلى عدة نقاط.

"بروتوكول النقل" لهذا الارتباط المفاهيمي من نقطة إلى عدة نقاط هو NS-3 أن نتواصل معك .

أذكر من قسم رد الاتصال أن ميزة رد الاتصال هي طريقة للسماح بوحدتين في
يقوم النظام بالاتصال عبر مكالمات الوظائف مع فصل الاتصال في نفس الوقت
تعمل من الفئة المسماة تمامًا. هذا هو نفس الشرط على النحو المبين أعلاه
لنظام البحث عن المفقودين.

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

إنّ أبسط مثال
سيكون من المفيد أن تمشي مثالًا سريعًا فقط لتعزيز ما قلناه:

# تضمين "ns3 / object.h"
# تضمين "ns3 / uinteger.h"
# تضمين "ns3 / traced-value.h" "
# تضمين "ns3 / trace-source-accessor.h"

#يشمل

باستخدام مساحة الاسم ns3 ؛

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

بشكل عام ، تعني دلالات القيمة فقط أنه يمكنك تمرير الكائن ، وليس ملف
عنوان. من أجل استخدام دلالات القيمة على الإطلاق ، يجب أن يكون لديك كائن بامتداد
يتوفر مُنشئ النسخ المرتبط وعامل التخصيص. نحن نمد المتطلبات
للحديث عن مجموعة العوامل المحددة مسبقًا لأنواع البيانات القديمة البسيطة (POD).
عامل التشغيل = ، عامل التشغيل ++ ، عامل التشغيل - ، عامل التشغيل + ، عامل التشغيل == ، إلخ.

ما يعنيه هذا كله هو أنك ستكون قادرًا على تتبع التغييرات على كائن تم إنشاؤه باستخدام
هؤلاء المشغلين:

فئة MyObject: الكائن العام
{
الجمهور:
TypeId ثابت GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("MyObject")
.SetParent (Object :: GetTypeId ())
.AddConstructor ()
.AddTraceSource ("MyInteger"،
"قيمة عدد صحيح للتتبع." ،
MakeTraceSourceAccessor (& MyObject :: m_myInt))
;
عودة المد
}

كائني () {}
TracedValue m_myInt ؛
};

نظرًا لأن نظام التتبع يتكامل مع السمات ، وتعمل السمات مع الكائنات ،
يجب أن يكون هناك NS-3 هدف لمصدر التتبع للعيش فيه. الخطان المهمان لـ
كود هي .AddTraceSource و TracedValue إعلان.

إنّ .AddTraceSource يوفر "الخطافات" المستخدمة لتوصيل مصدر التتبع بـ
العالم الخارجي. ال TracedValue الإعلان يوفر البنية التحتية التي تفرط في تحميل
المشغلين المذكورين أعلاه ويقودون عملية رد الاتصال:

باطل
IntTrace (Int oldValue، Int newValue)
{
std :: cout << "Traced" << oldValue << "إلى" << newValue << std :: endl؛
}

هذا هو تعريف أثر بالوعة. يتوافق مباشرة مع وظيفة رد الاتصال.
سيتم استدعاء هذه الوظيفة كلما كان أحد مشغلي TracedValue is
أعدم.:

مادبا
main (int argc، char * argv [])
{
Ptr myObject = CreateObject () ؛

myObject-> TraceConnectWithoutContext ("MyInteger" ، MakeCallback (& ​​IntTrace)) ؛

myObject-> m_myInt = 1234 ؛
}

في هذا المقتطف ، أول شيء يجب القيام به هو إنشاء الكائن الذي
يعيش مصدر التتبع.

الخطوة التالية هي TraceConnectWithoutContext، يشكل الاتصال بين التتبع
المصدر والمغسلة الأثر. لاحظ ال إجعل الإتصال وظيفة القالب. أذكر من
قسم رد الاتصال الذي يؤدي إلى إنشاء الممول المتخصص المسؤول عن توفير
زائد المشغل أو العامل() تستخدم "إطلاق" رد الاتصال. عوامل التشغيل المثقلة بالأعباء (++ ، - ، إلخ.)
سوف تستخدم هذا المشغل أو العامل() لاستدعاء رد الاتصال بالفعل. ال TraceConnectWithoutContext,
تأخذ معلمة سلسلة توفر اسم السمة المعينة للتتبع
مصدر. دعنا نتجاهل الجزء المتعلق بالسياق في الوقت الحالي لأنه ليس مهمًا بعد.

أخيرًا ، السطر:

myObject-> m_myInt = 1234 ؛

يجب تفسيره على أنه استدعاء لـ عامل التشغيل = على متغير العضو m_myInt مع
تم تمرير العدد الصحيح 1234 كمعامل. اتضح أن هذا العامل معرف (بواسطة
TracedValue) لتنفيذ رد نداء يُرجع فارغًا ويأخذ قيمتين صحيحتين كـ
المعلمات - قيمة قديمة وقيمة جديدة للعدد الصحيح المعني. هذا هو بالضبط
توقيع الوظيفة لوظيفة رد الاتصال التي قدمناها - انتتريس.

للتلخيص ، مصدر التتبع هو ، في جوهره ، متغير يحتوي على قائمة من عمليات الاسترجاعات. أ
مصدر التتبع هو دالة تستخدم كهدف لرد الاتصال. نوع السمة والكائن
تُستخدم أنظمة المعلومات لتوفير طريقة لتوصيل مصادر التتبع لتتبع الأحواض. ال
فعل "الاصطدام" بمصدر التتبع هو تنفيذ عامل تشغيل على مصدر التتبع الذي يطلق
عمليات الاسترجاعات. ينتج عن هذا رد نداءات مصدر التتبع تسجيل الاهتمام بالمصدر
يتم استدعاؤها بالمعلمات التي يوفرها المصدر.

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

على سبيل المثال ، قد يجد المرء شيئًا يشبه ما يلي في النظام (مأخوذ
تبدأ من أمثلة / tcp-large-transfer.cc):

CwndTracer باطل (uint32_t oldval، uint32_t newval) {}



التكوين :: ConnectWithoutContext (
"/ NodeList / 0 / $ ns3 :: TcpL4Protocol / SocketList / 0 / CongestionWindow" ،
MakeCallback (& ​​CwndTracer)) ؛

يجب أن يبدو هذا مألوفًا جدًا. إنه نفس الشيء مثل المثال السابق ، ما عدا ذلك
وظيفة عضو ثابتة للفئة التكوين يتم استدعاؤه بدلاً من طريقة على هدف;
وبدلا من السمة الاسم ، يتم توفير مسار.

أول شيء يجب فعله هو قراءة المسار إلى الوراء. يجب أن يكون الجزء الأخير من المسار
an السمة ل هدف. في الواقع ، إذا كان لديك مؤشر إلى ملف هدف التي لديها
"CongestionWindow" السمة مفيد (يطلق عليه الكائن) ، يمكنك كتابة هذا تمامًا مثل
المثال السابق:

CwndTracer باطل (uint32_t oldval، uint32_t newval) {}



theObject-> TraceConnectWithoutContext ("CongestionWindow" ، MakeCallback (& ​​CwndTracer)) ؛

اتضح أن رمز التكوين :: ConnectWithoutContext يفعل ذلك بالضبط. هذا
تأخذ الوظيفة مسارًا يمثل سلسلة من هدف المؤشرات ويتبعها حتى
يصل إلى نهاية المسار ويفسر المقطع الأخير على أنه ملف السمة في النهاية
هدف. دعنا نتعرف على ما يحدث.

يشير الحرف "/" البادئة في المسار إلى ما يسمى مساحة الاسم. واحد من
مساحات الأسماء المحددة مسبقًا في نظام التكوين هي "NodeList" وهي قائمة تضم جميع ملفات
العقد في المحاكاة. تتم الإشارة إلى العناصر الموجودة في القائمة بواسطة مؤشرات في القائمة ، لذلك
يشير "/ NodeList / 0" إلى العقدة الصفرية في قائمة العقد التي تم إنشاؤها بواسطة المحاكاة.
هذه العقدة هي في الواقع ملف Ptr وكذلك فئة فرعية من ns3 :: الكائن.

كما هو موضح في قسم نموذج الكائن ، NS-3 يدعم نموذج تجميع الكائن. ال
يبدأ مقطع المسار التالي بالحرف "$" الذي يشير إلى a GETOBJECT يجب أن تكون المكالمة
جعل البحث عن النوع الذي يليه. عندما تتم تهيئة العقدة بواسطة ملف
InternetStackHelper يتم تجميع عدد من الواجهات في العقدة. واحد من هؤلاء هو
بروتوكول TCP المستوى الرابع. نوع وقت تشغيل كائن البروتوكول هذا هو ns3 :: TcpL4Protocol ''.
متى هيه "GetObject يتم تنفيذه ، فإنه يعيد مؤشر إلى كائن من هذا النوع.

إنّ بروتوكول TcpL4 تحدد فئة سمة تسمى "SocketList" وهي قائمة
مآخذ. كل مقبس هو في الواقع ns3 :: الكائن مع الخاصة بها السمات. العناصر الموجودة في
تتم الإشارة إلى قائمة المقابس بواسطة الفهرس تمامًا كما هو الحال في NodeList ، لذا فإن "SocketList / 0"
يشير إلى المقبس الصفري في قائمة المقابس الموجودة على العقدة الصفرية في NodeList -
العقدة الأولى التي تم إنشاؤها في المحاكاة.

هذا المقبس ، الذي يتضح أن نوعه هو ns3 :: TcpSocketImpl يحدد سمة
يسمى "CongestionWindow" وهو ملف TracedValue.
التكوين :: ConnectWithoutContext يفعل الآن:

object-> TraceConnectWithoutContext ("CongestionWindow" ، MakeCallback (& ​​CwndTracer)) ؛

باستخدام مؤشر الكائن من "SocketList / 0" الذي يجعل الاتصال بين التتبع
المصدر المحدد في المقبس لرد الاتصال - CwndTracer.

الآن ، كلما تم إجراء تغيير على TracedValue تمثل الازدحام
نافذة في مقبس TCP ، سيتم تنفيذ رد الاتصال المسجل والوظيفة
CwndTracer سيتم استدعاء طباعة القيم القديمة والجديدة لازدحام TCP
نافذة.

باستخدام هيه البحث عن المفقودين API
هناك ثلاثة مستويات من التفاعل مع نظام التتبع:

· يمكن للمستخدم المبتدئ التحكم بسهولة في الأشياء التي تشارك في التتبع ؛

يمكن للمستخدمين المتوسطين توسيع نظام التتبع لتعديل تنسيق الإخراج المتولد
أو استخدام مصادر التتبع الحالية بطرق مختلفة ، دون تعديل جوهر
محاكاة.

يمكن للمستخدمين المتقدمين تعديل جوهر المحاكاة لإضافة مصادر ومصارف تتبع جديدة.

باستخدام أثر المساعدون
إنّ NS-3 يوفر مساعدو التتبع بيئة غنية لتكوين واختيار مختلف
تتبع الأحداث وكتابتها إلى الملفات. في الأقسام السابقة ، في المقام الأول "المبنى
الطبولوجيا ، "لقد رأينا عدة أنواع من أساليب مساعد التتبع المصممة للاستخدام
داخل مساعدين (جهاز) آخرين.

ربما تتذكر رؤية بعض هذه الاختلافات:

pointToPoint.EnablePcapAll ("الثانية") ،
pointToPoint.EnablePcap ("second"، p2pNodes.Get (0) -> GetId ()، 0) ؛
csma.EnablePcap ("ثالث"، csmaDevices.Get (0)، true) ؛
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr")) ؛

ما قد لا يكون واضحًا ، مع ذلك ، هو أن هناك نموذجًا ثابتًا لجميع
الطرق ذات الصلة بالتتبع الموجودة في النظام. سنأخذ الآن بعض الوقت ونلقي نظرة
في "الصورة الكبيرة".

توجد حاليًا حالتا استخدام أساسيتان لمساعدي التتبع في NS-3: مساعدي الجهاز
ومساعدي البروتوكول. يبحث مساعدو الأجهزة في مشكلة تحديد الآثار التي يجب أن تكون
يتم تمكينها من خلال عقدة أو زوج من الأجهزة. على سبيل المثال ، قد ترغب في تحديد هذا الملف الشخصي
يجب تمكين التتبع على جهاز معين على عقدة معينة. هذا يتبع من
NS-3 النموذج المفاهيمي للجهاز ، وكذلك النماذج المفاهيمية للجهاز المتنوع
مساعدين. بعد ذلك بشكل طبيعي ، تتبع الملفات التي تم إنشاؤها ملف
- - اصطلاح التسمية.

ينظر مساعدو البروتوكول في مشكلة تحديد الآثار التي يجب تمكينها من خلالها
زوج من البروتوكول والواجهة. هذا يتبع من NS-3 نموذج مفاهيمي بروتوكول المكدس ،
وكذلك النماذج المفاهيمية لمساعدي مكدس الإنترنت. بطبيعة الحال ، ملفات التتبع
يجب أن تتبع أ - - اصطلاح التسمية.

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

┌──────────────┬───────────┐
│ │ pcap ascii │
├──────────────┼──────┼───────┤
│ مساعد الجهاز │ │ │
├──────────────┼──────┼───────┤
│مساعد البروتوكول │ │ │
└──────────────┴──────┴───────┘

نحن نستخدم نهجا يسمى أ mixin لإضافة وظائف التتبع لفئات المساعدة لدينا. أ
mixin هي فئة توفر وظائف لما ورثتها فئة فرعية.
لا يعتبر الميراث من mixin شكلاً من أشكال التخصص ولكنه في الحقيقة وسيلة لتحقيق ذلك
جمع الوظائف.

دعونا نلقي نظرة سريعة على كل هذه الحالات الأربع وكل منها مزيج.

بكاب البحث عن المفقودين الجهاز المساعدون
الهدف من هؤلاء المساعدين هو تسهيل إضافة وسيلة تتبع pcap متسقة إلى ملف
NS-3 جهاز. نريد أن تعمل جميع النكهات المختلفة لتتبع pcap بنفس الطريقة
جميع الأجهزة ، لذلك يتم توريث طرق هؤلاء المساعدين بواسطة مساعدي الجهاز. إلق نظرة
at src / network / helper / trace-helper.h إذا كنت تريد متابعة المناقشة أثناء النظر في
كود حقيقي.

الفصل PcapHelperForDevice هو mixin يوفر وظائف عالية المستوى لاستخدام
تتبع pcap في ملف NS-3 جهاز. يجب أن ينفذ كل جهاز طريقة افتراضية واحدة
موروث من هذه الفئة:

EnablePcapInternal الفراغ الظاهري (بادئة std :: string ، Ptr الثانية ، منطقية منحل) = 0 ؛

يعكس توقيع هذه الطريقة وجهة النظر المتمحورة حول الجهاز للوضع في هذا الصدد
مستوى. جميع الأساليب العامة الموروثة من الطبقة PcapUserHelperForDevice قلل الى
استدعاء طريقة التنفيذ المعتمدة على الجهاز الفردي. على سبيل المثال ، أدنى مستوى
طريقة pcap:

EnablePcap باطلة (بادئة std :: string ، Ptr الثانية ، منطقية مختلطة = خطأ ، منطقية صريحة = خطأ) ؛

سيستدعي تنفيذ الجهاز لـ تمكينPcapInternal مباشرة. جميع pcap العامة الأخرى
تعتمد أساليب التتبع على هذا التنفيذ لتوفير مستوى مستخدم إضافي
وظائف. ما يعنيه هذا للمستخدم هو أن جميع مساعدي الجهاز في النظام سيفعلون ذلك
لديك جميع طرق تتبع pcap المتاحة ؛ وستعمل جميع هذه الأساليب في نفس الوقت
عبر الأجهزة إذا كان الجهاز يطبق تمكينPcapInternal بشكل صحيح.

بكاب البحث عن المفقودين الجهاز المساعد طرق
EnablePcap باطلة (بادئة std :: string ، Ptr اختصار الثاني،
منطقية منحل = خطأ ، منطقية صريحة اسم الملف = خطأ) ؛
EnablePcap باطلة (بادئة std :: string ، std :: string ndName ،
منطقية منحل = خطأ ، منطقية صريحة اسم الملف = خطأ) ؛
EnablePcap باطل (بادئة std :: string ، NetDeviceContainer d ،
منطقية منحل = خطأ) ؛
EnablePcap باطل (std :: string بادئة ، NodeContainer n ،
منطقية منحل = خطأ) ؛
EnablePcap باطل (std :: string prefix، uint32_t nodeid، uint32_t deviceid،
منطقية منحل = خطأ) ؛
EnablePcapAll void (بادئة std :: string ، bool promiscuous = false) ؛

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

Ptr اختصار الثاني؛

helper.EnablePcap ("بادئة" ، nd ، صواب) ؛

سيمكن وضع اللقطات المختلطة على NetDevice المحدد من قبل nd.

تتضمن الطريقتان الأوليان أيضًا معلمة افتراضية تسمى صريح اسم الملف ذلك سوف
تناقش أدناه.

نشجعك على الاطلاع على Doxygen للفصل الدراسي PcapHelperForDevice للعثور على التفاصيل
من هذه الأساليب لكن لتلخيص ...

يمكنك تمكين تتبع pcap على زوج معين من العقدة / جهاز الشبكة من خلال توفير ملف
Ptr إلى تمكينPcap طريقة. ال Ptr ضمنيًا منذ الجهاز الصافي
يجب أن ينتمي إلى واحد بالضبط العقدة. على سبيل المثال،:

Ptr اختصار الثاني؛

helper.EnablePcap ("بادئة" ، بدون تاريخ) ؛

يمكنك تمكين تتبع pcap على زوج معين من العقدة / جهاز الشبكة من خلال توفير ملف
الأمراض المنقولة جنسيا :: سلسلة تمثل سلسلة خدمة اسم الكائن إلى ملف تمكينPcap طريقة. ال
Ptr تم البحث عنه من سلسلة الاسم. مرة أخرى ، فإن ضمنيًا منذ أن
يجب أن ينتمي جهاز net المسمى إلى جهاز واحد بالضبط العقدة. على سبيل المثال،:

الأسماء :: إضافة ("الخادم" ...) ؛
الأسماء :: إضافة ("server / eth0" ...) ؛

helper.EnablePcap ("بادئة"، "server / ath0") ؛

يمكنك تمكين تتبع pcap على مجموعة من أزواج العقدة / الجهاز الشبكي من خلال توفير ملف
NetDeviceContainer. لكل واحد NetDevice في الحاوية يتم فحص النوع. لكل
جهاز من النوع المناسب (نفس النوع الذي يديره مساعد الجهاز) ، التتبع هو
ممكن. مرة أخرى ، فإن ضمنيًا نظرًا لأن جهاز الشبكة الذي تم العثور عليه يجب أن ينتمي بالضبط
صورة واحدة؟ العقدة. على سبيل المثال،:

NetDeviceContainer d = ... ؛

helper.EnablePcap ("بادئة"، d) ؛

يمكنك تمكين تتبع pcap على مجموعة من أزواج العقدة / الجهاز الشبكي من خلال توفير ملف
NodeContainer. لكل واحد العقدة في ال NodeContainer مرفق به NetDevices تتكرر.
لكل NetDevice المرفقة بكل عقدة في الحاوية ، نوع هذا الجهاز
التحقق. لكل جهاز من النوع المناسب (نفس النوع الذي يديره الجهاز
المساعد) ، تم تمكين التتبع .:

NodeContainer n ؛

helper.EnablePcap ("بادئة"، n) ؛

يمكنك تمكين تتبع pcap على أساس معرف العقدة ومعرف الجهاز وكذلك مع صريح
بي تي آر. كل العقدة في النظام يحتوي على معرف عقدة عدد صحيح وكل جهاز متصل بالعقدة
له معرّف جهاز صحيح:

helper.EnablePcap ("بادئة"، 21، 1) ؛

أخيرًا ، يمكنك تمكين تتبع pcap لجميع الأجهزة في النظام ، بنفس نوع
التي يديرها مساعد الجهاز:

helper.EnablePcapAll ("بادئة") ،

بكاب البحث عن المفقودين الجهاز المساعد اسم الملف اختيار
ضمنيًا في أوصاف الطريقة أعلاه هو إنشاء اسم ملف كامل بواسطة
طريقة التنفيذ. وفقًا للاتفاقية ، يتتبع pcap في ملف NS-3 النظام من الشكل
- معرف> - معرف> .pcap

كما ذكرنا سابقًا ، سيكون لكل عقدة في النظام معرف عقدة مخصص للنظام ؛ و
سيحتوي كل جهاز على فهرس واجهة (يسمى أيضًا معرف الجهاز) بالنسبة للعقدة الخاصة به.
بشكل افتراضي ، إذن ، ملف تتبع pcap تم إنشاؤه كنتيجة لتمكين التتبع في الأول
جهاز العقدة 21 باستخدام البادئة "البادئة" سيكون البادئة -21-1.

يمكنك دائمًا استخدام ملف NS-3 خدمة اسم الكائن لجعل هذا أكثر وضوحًا. على سبيل المثال ، إذا
كنت تستخدم خدمة اسم الكائن لتعيين اسم "الخادم" للعقدة 21 ، pcap الناتج
سيصبح اسم ملف التتبع تلقائيًا ، بادئة خادم 1.pcap وإذا قمت أيضًا بتعيين
اسم "eth0" على الجهاز ، سيقوم اسم ملف pcap تلقائيًا باختيار هذا ويكون
تسمى بادئة خادم eth0.pcap.

أخيرًا ، طريقتان من الطرق الموضحة أعلاه:

EnablePcap باطلة (بادئة std :: string ، Ptr الثانية ، منطقية مختلطة = خطأ ، منطقية صريحة = خطأ) ؛
EnablePcap باطل (std :: string بادئة ، std :: string ، ndName ، bool مختلط = false ، bool صريح صريح = خطأ) ؛

لها معلمة افتراضية تسمى صريح اسم الملف. عند التعيين على صحيح ، هذه المعلمة
يعطل آلية إكمال اسم الملف التلقائي ويسمح لك بإنشاء ملف
اسم الملف. هذا الخيار متاح فقط في الطرق التي تتيح تتبع pcap على ملف
جهاز واحد.

على سبيل المثال ، من أجل ترتيب مساعد الجهاز لإنشاء pcap واحد مختلط
التقاط ملف باسم معين (my-pcap-file.pcap) على جهاز معين ، يمكن للمرء:

Ptr اختصار الثاني؛

helper.EnablePcap ("my-pcap-file.pcap" ، nd ، true ، true) ؛

أول صحيح تمكن المعلمة من تتبعات الوضع المختلط والثانية تخبر المساعد
لتفسير بادئة المعلمة كاسم ملف كامل.

أسكي البحث عن المفقودين الجهاز المساعدون
سلوك المساعد تتبع أسكي mixin يشبه إلى حد كبير إصدار pcap.
الق نظرة على src / network / helper / trace-helper.h إذا كنت تريد متابعة المناقشة
أثناء النظر إلى الكود الحقيقي.

الفصل AsciiTraceHelperForDevice يضيف وظائف عالية المستوى لاستخدام ASCII
تتبع فئة مساعد الجهاز. كما هو الحال في حالة pcap ، يجب أن يقوم كل جهاز بتنفيذ ملف
طريقة افتراضية واحدة موروثة من تتبع أسكي mixin.:

الفراغ الظاهري EnableAsciiInternal (Ptr تيار ، الأمراض المنقولة جنسيا :: بادئة سلسلة ، Ptr الثانية) = 0 ؛

يعكس توقيع هذه الطريقة وجهة النظر المتمحورة حول الجهاز للوضع في هذا الصدد
مستوى؛ وكذلك حقيقة أن المساعد قد يكتب إلى تدفق إخراج مشترك. كل
الطرق ذات الصلة بتتبع أسكي العامة الموروثة من الفصل AsciiTraceHelperForDevice
تقليل استدعاء طريقة التنفيذ المعتمدة على جهاز واحد. على سبيل المثال ، ملف
طرق تتبع أسكي الأدنى مستوى:

void EnableAscii (std :: string prefix، Ptr اختصار الثاني)؛
باطل EnableAscii (Ptr تيار ، Ptr اختصار الثاني)؛

سيستدعي تنفيذ الجهاز لـ تمكين AsciiInternal بشكل مباشر ، مع توفير إما أ
بادئة أو دفق صالح. ستبني جميع طرق تتبع أسكي العامة الأخرى على هذه
وظائف منخفضة المستوى لتوفير وظائف إضافية على مستوى المستخدم. ماذا يعني هذا لـ
المستخدم هو أن جميع مساعدي الأجهزة في النظام سيكون لديهم جميع طرق تتبع ascii
متاح؛ وستعمل جميع هذه الطرق بنفس الطريقة عبر الأجهزة إذا كانت الأجهزة
تنفيذ EnablAscii الداخلية بشكل صحيح.

أسكي البحث عن المفقودين الجهاز المساعد طرق
void EnableAscii (std :: string prefix، Ptr اختصار الثاني)؛
باطل EnableAscii (Ptr تيار ، Ptr اختصار الثاني)؛

EnableAscii باطلة (بادئة std :: string ، std :: string ndName) ؛
باطل EnableAscii (Ptr تيار ، الأمراض المنقولة جنسيا :: سلسلة ndName) ؛

EnableAscii باطلة (بادئة std :: string ، NetDeviceContainer d) ؛
باطل EnableAscii (Ptr تيار ، NetDeviceContainer د) ؛

EnableAscii باطلة (بادئة std :: string ، NodeContainer n) ؛
باطل EnableAscii (Ptr تيار ، NodeContainer n) ؛

void EnableAscii (std :: string prefix، uint32_t nodeid، uint32_t deviceid) ؛
باطل EnableAscii (Ptr تيار ، uint32_t nodeid ، uint32_t deviceid) ؛

باطل EnableAsciiAll (الأمراض المنقولة جنسيا :: بادئة سلسلة) ؛
باطل EnableAsciiAll (Ptr تدفق)؛

نشجعك على الاطلاع على Doxygen للفصل الدراسي TraceHelperForDevice لتجد ال
تفاصيل هذه الأساليب ؛ لكن لتلخيص ...

هناك ضعف عدد الطرق المتاحة لتتبع أسكي مقارنة ببرنامج pcap
اقتفاء أثر. هذا بسبب ، بالإضافة إلى نموذج pcap-style حيث توجد آثار من كل منها
تتم كتابة زوج العقدة / الجهاز الفريد في ملف فريد ، ونحن ندعم النموذج الذي تتبع فيه
تتم كتابة المعلومات الخاصة بالعديد من أزواج العقد / الأجهزة في ملف مشترك. هذا يعني أن ملف
- - يتم استبدال آلية إنشاء اسم الملف بآلية
الرجوع إلى ملف مشترك ؛ ويتضاعف عدد طرق API للسماح للجميع
مجموعات.

تمامًا كما هو الحال في تتبع pcap ، يمكنك تمكين تتبع ascii على زوج معين من العقدة / جهاز الشبكة
من خلال توفير أ Ptr إلى تمكين طريقة. ال Ptr ضمنيًا منذ ذلك الحين
يجب أن ينتمي جهاز الشبكة إلى واحد بالضبط العقدة. على سبيل المثال،:

Ptr اختصار الثاني؛

helper.EnableAscii ("البادئة" ، الثانية) ؛

في هذه الحالة ، لا تتم كتابة أي سياقات تتبع في ملف تتبع ascii لأنها ستكون كذلك
متكرر. سيختار النظام اسم الملف الذي سيتم إنشاؤه باستخدام نفس القواعد مثل
الموصوفة في قسم pcap ، باستثناء أن الملف سيكون له اللاحقة ".tr" بدلاً من
".pcap".

إذا كنت ترغب في تمكين تتبع ascii على أكثر من جهاز شبكة وإرسال جميع عمليات التتبع
لملف واحد ، يمكنك القيام بذلك أيضًا باستخدام كائن للإشارة إلى ملف واحد:

Ptr و 1 ؛
Ptr و 2 ؛

Ptr تيار = asciiTraceHelper.CreateFileStream ("trace-file-name.tr") ؛

المساعد EnableAscii (تيار ، nd1) ؛
المساعد EnableAscii (تيار ، nd2) ؛

في هذه الحالة ، تتم كتابة سياقات التتبع في ملف تتبع ascii نظرًا لأنها مطلوبة
لإزالة الغموض عن الآثار من الجهازين. لاحظ أنه منذ المستخدم تماما
عند تحديد اسم الملف ، يجب أن تتضمن السلسلة ".tr" من أجل التناسق.

يمكنك تمكين تتبع ascii على زوج معين من العقدة / جهاز الشبكة من خلال توفير ملف
الأمراض المنقولة جنسيا :: سلسلة تمثل سلسلة خدمة اسم الكائن إلى ملف تمكينPcap طريقة. ال
Ptr تم البحث عنه من سلسلة الاسم. مرة أخرى ، فإن ضمنيًا منذ أن
يجب أن ينتمي جهاز net المسمى إلى جهاز واحد بالضبط العقدة. على سبيل المثال،:

الأسماء :: إضافة ("العميل" ...) ؛
الأسماء :: إضافة ("client / eth0" ...) ؛
الأسماء :: إضافة ("الخادم" ...) ؛
الأسماء :: إضافة ("server / eth0" ...) ؛

helper.EnableAscii ("بادئة"، "client / eth0") ؛
helper.EnableAscii ("بادئة"، "server / eth0") ؛

قد ينتج عن هذا ملفين مسميين بادئة- العميل-eth0.tr بادئة- server-eth0.tr مع
تتبع لكل جهاز في ملف التتبع المعني. منذ كل من EnableAscii
الوظائف محملة بشكل زائد لأخذ غلاف دفق ، يمكنك استخدام هذا النموذج أيضًا:

الأسماء :: إضافة ("العميل" ...) ؛
الأسماء :: إضافة ("client / eth0" ...) ؛
الأسماء :: إضافة ("الخادم" ...) ؛
الأسماء :: إضافة ("server / eth0" ...) ؛

Ptr تيار = asciiTraceHelper.CreateFileStream ("trace-file-name.tr") ؛

helper.EnableAscii (تيار ، "العميل / eth0") ؛
helper.EnableAscii (تيار ، "الخادم / eth0") ؛

قد ينتج عن هذا ملف تتبع واحد يسمى تتبع اسم الملف.tr الذي يحتوي على كل
أحداث التتبع لكلا الجهازين. سيتم توضيح الأحداث من خلال سياق التتبع
سلاسل.

يمكنك تمكين تتبع ascii على مجموعة من أزواج العقدة / الجهاز الشبكي من خلال توفير ملف
NetDeviceContainer. لكل واحد NetDevice في الحاوية يتم فحص النوع. لكل
جهاز من النوع المناسب (نفس النوع الذي يديره مساعد الجهاز) ، التتبع هو
ممكن. مرة أخرى ، فإن ضمنيًا نظرًا لأن جهاز الشبكة الذي تم العثور عليه يجب أن ينتمي بالضبط
صورة واحدة؟ العقدة. على سبيل المثال،:

NetDeviceContainer d = ... ؛

helper.EnableAscii ("البادئة" ، d) ؛

سيؤدي هذا إلى إنشاء عدد من ملفات تتبع ascii ، كل منها يتبع
ال - - .tr اتفاقية. يتم دمج كل الآثار في ملف
ملف واحد يتم إنجازه بشكل مشابه للأمثلة أعلاه:

NetDeviceContainer d = ... ؛

Ptr تيار = asciiTraceHelper.CreateFileStream ("trace-file-name.tr") ؛

المساعد EnableAscii (تيار ، د) ؛

يمكنك تمكين تتبع ascii على مجموعة من أزواج العقدة / الجهاز الشبكي من خلال توفير ملف
NodeContainer. لكل واحد العقدة في ال NodeContainer مرفق به NetDevices تتكرر.
لكل NetDevice المرفقة بكل عقدة في الحاوية ، نوع هذا الجهاز
التحقق. لكل جهاز من النوع المناسب (نفس النوع الذي يديره الجهاز
المساعد) ، تم تمكين التتبع .:

NodeContainer n ؛

helper.EnableAscii ("بادئة"، n) ؛

سيؤدي هذا إلى إنشاء عدد من ملفات تتبع ascii ، كل منها يتبع
ال - - .tr اتفاقية. يتم دمج كل الآثار في ملف
ملف واحد يتم إنجازه بشكل مشابه للأمثلة أعلاه:

يمكنك تمكين تتبع pcap على أساس معرف العقدة ومعرف الجهاز وكذلك مع صريح
بي تي آر. كل العقدة في النظام يحتوي على معرف عقدة عدد صحيح وكل جهاز متصل بالعقدة
له معرّف جهاز صحيح:

helper.EnableAscii ("بادئة" ، 21 ، 1) ؛

بالطبع ، يمكن دمج الآثار في ملف واحد كما هو موضح أعلاه.

أخيرًا ، يمكنك تمكين تتبع pcap لجميع الأجهزة في النظام ، بنفس نوع
التي يديرها مساعد الجهاز:

helper.EnableAsciiAll ("بادئة") ؛

سيؤدي هذا إلى إنشاء عدد من ملفات تتبع ascii ، واحد لكل جهاز في
نظام من النوع الذي يديره المساعد. ستتبع كل هذه الملفات ملف
- - .tr اتفاقية. دمج كل الآثار في واحد
ملف تم إنجازه بشكل مشابه للأمثلة أعلاه.

أسكي البحث عن المفقودين الجهاز المساعد اسم الملف اختيار
ضمنيًا في أوصاف أسلوب البادئة أعلاه هو بناء الكامل
أسماء الملفات من خلال طريقة التنفيذ. من خلال الاتفاقية ، تتبع أسكي في NS-3 النظام
النموذج - معرف> - معرف>. tr.

كما ذكرنا سابقًا ، سيكون لكل عقدة في النظام معرف عقدة مخصص للنظام ؛ و
سيحتوي كل جهاز على فهرس واجهة (يسمى أيضًا معرف الجهاز) بالنسبة للعقدة الخاصة به.
بشكل افتراضي ، إذن ، يتم إنشاء ملف تتبع ascii كنتيجة لتمكين التتبع في الأول
جهاز العقدة 21 ، باستخدام البادئة "البادئة" ، سيكون البادئة 21-1.tr.

يمكنك دائمًا استخدام ملف NS-3 خدمة اسم الكائن لجعل هذا أكثر وضوحًا. على سبيل المثال ، إذا
كنت تستخدم خدمة اسم الكائن لتعيين اسم "الخادم" للعقدة 21 ، الناتج
سيصبح اسم ملف تتبع ascii تلقائيًا ، بادئة- server-1.tr وإذا قمت أيضًا بتعيين
اسم "eth0" للجهاز ، سيقوم اسم ملف تتبع أسكي الخاص بك باختيار هذا تلقائيًا
ويتم استدعاؤهم بادئة- server-eth0.tr.

بكاب البحث عن المفقودين بروتوكول المساعدون
الهدف من هؤلاء مزيج هو تسهيل إضافة أداة تتبع pcap متسقة إلى
البروتوكولات. نريد أن تعمل جميع النكهات المختلفة لتتبع pcap بنفس الطريقة في الكل
البروتوكولات ، لذلك يتم توريث أساليب هؤلاء المساعدين بواسطة مساعدي المكدس. ألق نظرة على
src / network / helper / trace-helper.h إذا كنت تريد متابعة المناقشة أثناء النظر في
كود حقيقي.

سنقوم في هذا القسم بتوضيح الأساليب المطبقة على البروتوكول IPv4. إلى
تحديد التتبع في بروتوكولات مماثلة ، فقط استبدل النوع المناسب. على سبيل المثال،
إستخدم Ptr بدلا من Ptr و اتصل تمكينPcapIpv6 بدلا من تمكينPcapIpv4.

الفصل PcapHelperForIpv4 يوفر وظائف عالية المستوى لاستخدام تتبع pcap
في ال IPv4 بروتوكول. يجب أن يقوم كل مساعد بروتوكول يتيح هذه الأساليب بتنفيذ ملف
الطريقة الافتراضية الموروثة من هذه الفئة. سيكون هناك تنفيذ منفصل لـ
IPv6، على سبيل المثال ، ولكن الاختلاف الوحيد سيكون في أسماء الطرق والتوقيعات.
مطلوب أسماء طرق مختلفة لإزالة الغموض عن الفصل IPv4 تبدأ من IPv6 كلاهما
مشتق من الطبقة هدف، والطرق التي تشترك في نفس التوقيع:

الفراغ الظاهري EnablePcapIpv4Internal (std :: string prefix، Ptr ipv4 ، واجهة uint4_t) = 32 ؛

يعكس توقيع هذه الطريقة البروتوكول وعرض مركز الواجهة لـ
الوضع على هذا المستوى. جميع الأساليب العامة الموروثة من الطبقة PcapHelperForIpv4
تقليل إلى استدعاء طريقة التنفيذ المعتمدة على جهاز واحد. على سبيل المثال ، ملف
طريقة pcap الأدنى مستوى:

باطل EnablePcapIpv4 (الأمراض المنقولة جنسياً: بادئة السلسلة ، Ptr ipv4 ، واجهة uint4_t) ؛

سيستدعي تنفيذ الجهاز لـ تمكينPcapIpv4Internal مباشرة. كل الجمهور الآخر
تعتمد أساليب تتبع pcap على هذا التطبيق لتوفير مستوى مستخدم إضافي
وظائف. ما يعنيه هذا للمستخدم هو أن جميع مساعدي البروتوكول في النظام سيفعلون ذلك
لديك جميع طرق تتبع pcap المتاحة ؛ وستعمل جميع هذه الأساليب في نفس الوقت
عبر البروتوكولات إذا نفذ المساعد تمكينPcapIpv4Internal بشكل صحيح.

بكاب البحث عن المفقودين بروتوكول المساعد طرق
تم تصميم هذه الطرق لتكون في مراسلات فردية مع العقدة- و
NetDevice- إصدارات مركزية من إصدارات الجهاز. بدلاً من العقدة NetDevice زوج
القيود ، نستخدم قيود البروتوكول والواجهة.

لاحظ أنه تمامًا كما هو الحال في إصدار الجهاز ، هناك ست طرق:

باطل EnablePcapIpv4 (الأمراض المنقولة جنسياً: بادئة السلسلة ، Ptr ipv4 ، واجهة uint4_t) ؛
EnablePcapIpv4 باطلة (بادئة std :: string ، std :: string ipv4Name ، واجهة uint32_t) ؛
باطل EnablePcapIpv4 (std :: string بادئة ، Ipv4InterfaceContainer c) ؛
EnablePcapIpv4 باطلة (بادئة std :: string ، NodeContainer n) ؛
باطل EnablePcapIpv4 (الأمراض المنقولة جنسياً: بادئة السلسلة ، uint32_t nodeid ، واجهة uint32_t) ؛
باطل EnablePcapIpv4All (std :: string بادئة) ؛

نشجعك على الاطلاع على Doxygen للفصل الدراسي PcapHelperForIpv4 للعثور على التفاصيل
من هذه الأساليب لكن لتلخيص ...

يمكنك تمكين تتبع pcap على زوج بروتوكول / واجهة معين من خلال توفير ملف
Ptr الواجهة إلى تمكينPcap طريقة. على سبيل المثال،:

Ptr ipv4 = عقدة-> GetObject () ؛

helper.EnablePcapIpv4 ("بادئة"، ipv4، 0) ؛

يمكنك تمكين تتبع pcap على زوج معين من العقدة / جهاز الشبكة من خلال توفير ملف
الأمراض المنقولة جنسيا :: سلسلة تمثل سلسلة خدمة اسم الكائن إلى ملف تمكينPcap طريقة. ال
Ptr تم البحث عنه من سلسلة الاسم. على سبيل المثال،:

الأسماء :: إضافة ("serverIPv4" ...) ؛

helper.EnablePcapIpv4 ("بادئة"، "serverIpv4"، 1) ؛

يمكنك تمكين تتبع pcap على مجموعة من أزواج البروتوكول / الواجهة من خلال توفير ملف
IPv4InterfaceContainer. لكل واحد IPv4 / زوج الواجهة في الحاوية نوع البروتوكول
مفحوص. لكل بروتوكول من النوع المناسب (نفس النوع الذي تتم إدارته بواسطة
الجهاز المساعد) ، يتم تمكين التتبع للواجهة المقابلة. على سبيل المثال،:

عقد NodeContainer

أجهزة NetDeviceContainer = deviceHelper.Install (العقد) ؛

IPv4AddressHelper ipv4 ؛
ipv4.SetBase ("10.1.1.0"، "255.255.255.0") ؛
واجهات Ipv4InterfaceContainer = ipv4.Assign (الأجهزة) ؛

helper.EnablePcapIpv4 ("بادئة" ، واجهات) ؛

يمكنك تمكين تتبع pcap على مجموعة من أزواج البروتوكول / الواجهة من خلال توفير ملف
NodeContainer. لكل واحد العقدة في ال NodeContainer تم العثور على البروتوكول المناسب. ل
كل بروتوكول ، يتم تعداد واجهاته ويتم تمكين التتبع على الناتج
أزواج. على سبيل المثال،:

NodeContainer n ؛

helper.EnablePcapIpv4 ("بادئة"، n) ؛

يمكنك تمكين تتبع pcap على أساس معرف العقدة والواجهة أيضًا. في هذه الحالة،
يتم ترجمة معرف العقدة إلى Ptr ويتم البحث عن البروتوكول المناسب في
العقدة. يتم استخدام البروتوكول والواجهة الناتجة لتحديد التتبع الناتج
مصدر.:

helper.EnablePcapIpv4 ("بادئة"، 21، 1) ؛

أخيرًا ، يمكنك تمكين تتبع pcap لجميع الواجهات في النظام ، مع ملفات
البروتوكول هو نفس نوع البروتوكول الذي يديره مساعد الجهاز:

helper.EnablePcapIpv4All ("بادئة") ؛

بكاب البحث عن المفقودين بروتوكول المساعد اسم الملف اختيار
ضمنيًا في جميع توصيفات الطريقة أعلاه هو بناء الكامل
أسماء الملفات من خلال طريقة التنفيذ. وفقًا للاتفاقية ، تم التقاط آثار pcap للأجهزة في
هيه NS-3 النظام من الشكل - معرف> - معرف> .pcap. في حالة
بروتوكول تتبع ، هناك مراسلات واحد لواحد بين البروتوكولات و العقد. وهذا هو
لأن البروتوكول الأجسام يتم تجميعها إلى العقدة الأجسام. لأنه لا يوجد بروتوكول عالمي
id في النظام ، نستخدم معرف العقدة المقابل في تسمية الملف. لذلك هناك ملف
إمكانية تضارب اسم الملف في أسماء ملفات التتبع المختارة تلقائيًا. لهذا
السبب ، يتم تغيير اصطلاح اسم الملف لتتبعات البروتوكول.

كما ذكرنا سابقًا ، سيكون لكل عقدة في النظام معرف عقدة مخصص للنظام.
نظرًا لوجود تطابق واحد لواحد بين مثيلات البروتوكول ومثيلات العقدة
نستخدم معرف العقدة. كل واجهة لها معرف واجهة بالنسبة إلى البروتوكول الخاص بها. نحن نستخدم
الاتفاقية " -ن -أنا .pcap "لتسمية ملف التتبع بتنسيق
مساعدي البروتوكول.

لذلك ، بشكل افتراضي ، يتم إنشاء ملف تتبع pcap كنتيجة لتمكين التتبع
ستكون الواجهة 1 من بروتوكول Ipv4 للعقدة 21 باستخدام البادئة "البادئة"
"البادئة-n21-i1.pcap".

يمكنك دائمًا استخدام ملف NS-3 خدمة اسم الكائن لجعل هذا أكثر وضوحًا. على سبيل المثال ، إذا
يمكنك استخدام خدمة اسم الكائن لتعيين اسم "serverIpv4" إلى Ptr على العقدة
21 ، سيصبح اسم ملف تتبع pcap الناتج تلقائيًا ،
"بادئة nserverIpv4-i1.pcap".

أسكي البحث عن المفقودين بروتوكول المساعدون
يشبه سلوك مساعدي تتبع ascii إلى حد كبير حالة pcap. خذ
النظر في src / network / helper / trace-helper.h إذا كنت تريد متابعة المناقشة أثناء
بالنظر إلى الكود الحقيقي.

سنقوم في هذا القسم بتوضيح الأساليب المطبقة على البروتوكول IPv4. إلى
تحديد التتبع في بروتوكولات مماثلة ، فقط استبدل النوع المناسب. على سبيل المثال،
إستخدم Ptr بدلا من Ptr و اتصل تمكينAsciiIpv6 بدلا من
تمكينAsciiIpv4.

الفصل AsciiTraceHelperForIpv4 يضيف وظائف عالية المستوى لاستخدام ASCII
تتبع إلى مساعد بروتوكول. يجب على كل بروتوكول يمكّن هذه الأساليب تنفيذ أ
طريقة افتراضية واحدة موروثة من هذه الفئة:

الفراغ الظاهري EnableAsciiIpv4Internal (Ptr تيار ، الأمراض المنقولة جنسيا :: بادئة سلسلة ،
Ptr ipv4 ، واجهة uint4_t) = 32 ؛

يعكس توقيع هذه الطريقة طريقة عرض البروتوكول والواجهة المركزية لـ
الوضع على هذا المستوى. وكذلك حقيقة أن المساعد ربما يكتب إلى ملف مشترك
تيار الإخراج. جميع الأساليب العامة الموروثة من الطبقة
PcapAndAsciiTraceHelperForIpv4 تقليل إلى استدعاء هذا الجهاز الفردي المعتمد
طريقة التنفيذ. على سبيل المثال ، طرق تتبع ascii ذات المستوى الأدنى:

باطل EnableAsciiIpv4 (الأمراض المنقولة جنسياً: بادئة السلسلة ، Ptr ipv4 ، واجهة uint4_t) ؛
باطل EnableAsciiIpv4 (Ptr تيار ، Ptr ipv4 ، واجهة uint4_t) ؛

سيستدعي تنفيذ الجهاز لـ تمكينAsciiIpv4Internal بشكل مباشر ، مع توفير إما
البادئة أو الدفق. ستبني جميع طرق تتبع أسكي العامة الأخرى على هذه
وظائف منخفضة المستوى لتوفير وظائف إضافية على مستوى المستخدم. ماذا يعني هذا لـ
المستخدم هو أن جميع مساعدي الأجهزة في النظام سيكون لديهم جميع طرق تتبع ascii
متاح؛ وستعمل جميع هذه الطرق بنفس الطريقة عبر البروتوكولات إذا كان
تنفيذ البروتوكولات EnablAsciiIpv4 داخلي بشكل صحيح.

أسكي البحث عن المفقودين الجهاز المساعد طرق
باطل EnableAsciiIpv4 (الأمراض المنقولة جنسياً: بادئة السلسلة ، Ptr ipv4 ، واجهة uint4_t) ؛
باطل EnableAsciiIpv4 (Ptr تيار ، Ptr ipv4 ، واجهة uint4_t) ؛

EnableAsciiIpv4 باطلة (بادئة std :: string ، std :: string ipv4Name ، واجهة uint32_t) ؛
باطل EnableAsciiIpv4 (Ptr تيار ، الأمراض المنقولة جنسيا :: سلسلة ipv4Name ، واجهة uint32_t) ؛

باطل EnableAsciiIpv4 (std :: string بادئة ، Ipv4InterfaceContainer c) ؛
باطل EnableAsciiIpv4 (Ptr تيار ، Ipv4InterfaceContainer ج) ؛

باطل EnableAsciiIpv4 (std :: string بادئة ، NodeContainer n) ؛
باطل EnableAsciiIpv4 (Ptr تيار ، NodeContainer n) ؛

void EnableAsciiIpv4 (std :: string prefix، uint32_t nodeid، uint32_t deviceid) ؛
باطل EnableAsciiIpv4 (Ptr تيار ، uint32_t nodeid ، واجهة uint32_t) ؛

باطل EnableAsciiIpv4All (std :: string prefix) ؛
باطل EnableAsciiIpv4All (Ptr تدفق)؛

نشجعك على الاطلاع على Doxygen للفصل الدراسي PcapAndAsciiHelperForIpv4 لتجد ال
تفاصيل هذه الأساليب ؛ لكن لتلخيص ...

هناك ضعف عدد الطرق المتاحة لتتبع أسكي مقارنة ببرنامج pcap
اقتفاء أثر. هذا بسبب ، بالإضافة إلى نموذج pcap-style حيث توجد آثار من كل منها
تتم كتابة زوج بروتوكول / واجهة فريد في ملف فريد ، ونحن ندعم نموذجًا فيه
تتم كتابة معلومات التتبع للعديد من أزواج البروتوكول / الواجهة في ملف مشترك. هذا
يعني أن -ن - يتم استبدال آلية إنشاء اسم الملف
بواسطة آلية للإشارة إلى ملف مشترك ؛ ويتضاعف عدد طرق API إلى
السماح لجميع المجموعات.

تمامًا كما هو الحال في تتبع pcap ، يمكنك تمكين تتبع ascii على بروتوكول / واجهة معينة
الزوج من خلال توفير ملف Ptr و الواجهة إلى تمكين طريقة. على سبيل المثال،:

Ptr ipv4 ؛

helper.EnableAsciiIpv4 ("بادئة" ، ipv4 ، 1) ؛

في هذه الحالة ، لا تتم كتابة أي سياقات تتبع في ملف تتبع ascii لأنها ستكون كذلك
متكرر. سيختار النظام اسم الملف الذي سيتم إنشاؤه باستخدام نفس القواعد مثل
الموصوفة في قسم pcap ، باستثناء أن الملف سيكون له اللاحقة ".tr" بدلاً من
".pcap".

إذا كنت ترغب في تمكين تتبع ascii على أكثر من واجهة وإرسال جميع عمليات التتبع إليها
ملف واحد ، يمكنك القيام بذلك أيضًا باستخدام كائن للإشارة إلى ملف واحد. نحن
لديك بالفعل شيء مشابه لهذا في مثال "cwnd" أعلاه:

Ptr Protocol4 = node1-> GetObject () ؛
Ptr Protocol4 = node2-> GetObject () ؛

Ptr تيار = asciiTraceHelper.CreateFileStream ("trace-file-name.tr") ؛

helper.EnableAsciiIpv4 (تيار ، بروتوكول 1 ، 1) ؛
helper.EnableAsciiIpv4 (تيار ، بروتوكول 2 ، 1) ؛

في هذه الحالة ، تتم كتابة سياقات التتبع في ملف تتبع ascii نظرًا لأنها مطلوبة
لإزالة الغموض عن الآثار من الواجهتين. لاحظ أنه منذ المستخدم تماما
عند تحديد اسم الملف ، يجب أن تتضمن السلسلة ".tr" من أجل التناسق.

يمكنك تمكين تتبع ascii على بروتوكول معين من خلال توفير ملف الأمراض المنقولة جنسيا :: سلسلة
تمثل سلسلة خدمة اسم الكائن إلى ملف تمكينPcap طريقة. ال Ptr is
بحثت عن سلسلة الاسم. ال في أسماء الملفات الناتجة ضمنيًا منذ ذلك الحين
هناك مراسلات فردية بين مثيلات البروتوكول والعقد ، على سبيل المثال:

الأسماء :: إضافة ("node1Ipv4" ...) ؛
الأسماء :: إضافة ("node2Ipv4" ...) ؛

helper.EnableAsciiIpv4 ("بادئة"، "node1Ipv4"، 1) ؛
helper.EnableAsciiIpv4 ("بادئة"، "node2Ipv4"، 1) ؛

قد ينتج عن هذا ملفين باسم "بادئة-nnode1Ipv4-i1.tr" و
"بادئة-nnode2Ipv4-i1.tr" مع تتبعات لكل واجهة في ملف التتبع المعني.
نظرًا لأن جميع وظائف EnableAscii محملة فوق طاقتها لأخذ غلاف دفق ، يمكنك ذلك
استخدم هذا النموذج أيضًا:

الأسماء :: إضافة ("node1Ipv4" ...) ؛
الأسماء :: إضافة ("node2Ipv4" ...) ؛

Ptr تيار = asciiTraceHelper.CreateFileStream ("trace-file-name.tr") ؛

helper.EnableAsciiIpv4 (تيار، "node1Ipv4"، 1) ؛
helper.EnableAsciiIpv4 (تيار، "node2Ipv4"، 1) ؛

قد ينتج عن هذا ملف تتبع واحد يسمى "trace-file-name.tr" الذي يحتوي على كافة
أحداث التتبع لكلا الواجهتين. سيتم توضيح الأحداث من خلال سياق التتبع
سلاسل.

يمكنك تمكين تتبع ascii على مجموعة من أزواج البروتوكول / الواجهة من خلال توفير ملف
IPv4InterfaceContainer. لكل بروتوكول من النوع المناسب (نفس النوع الذي تتم إدارته
بواسطة مساعد الجهاز) ، يتم تمكين التتبع للواجهة المقابلة. مرة أخرى ، فإن
ضمنيًا نظرًا لوجود تطابق واحد لواحد بين كل بروتوكول و
عقدة. على سبيل المثال،:

عقد NodeContainer

أجهزة NetDeviceContainer = deviceHelper.Install (العقد) ؛

IPv4AddressHelper ipv4 ؛
ipv4.SetBase ("10.1.1.0"، "255.255.255.0") ؛
واجهات Ipv4InterfaceContainer = ipv4.Assign (الأجهزة) ؛


helper.EnableAsciiIpv4 ("بادئة" ، واجهات) ؛

سيؤدي هذا إلى إنشاء عدد من ملفات تتبع ascii ، كل منها يتبع
ال -ن -أنا .tr اتفاقية. يتم دمج كل الآثار في ملف
ملف واحد يتم إنجازه بشكل مشابه للأمثلة أعلاه:

عقد NodeContainer

أجهزة NetDeviceContainer = deviceHelper.Install (العقد) ؛

IPv4AddressHelper ipv4 ؛
ipv4.SetBase ("10.1.1.0"، "255.255.255.0") ؛
واجهات Ipv4InterfaceContainer = ipv4.Assign (الأجهزة) ؛

Ptr تيار = asciiTraceHelper.CreateFileStream ("trace-file-name.tr") ؛

helper.EnableAsciiIpv4 (دفق ، واجهات) ؛

يمكنك تمكين تتبع ascii على مجموعة من أزواج البروتوكول / الواجهة من خلال توفير ملف
NodeContainer. لكل واحد العقدة في ال NodeContainer تم العثور على البروتوكول المناسب. ل
كل بروتوكول ، يتم تعداد واجهاته ويتم تمكين التتبع على الناتج
أزواج. على سبيل المثال،:

NodeContainer n ؛

helper.EnableAsciiIpv4 ("بادئة"، n) ؛

سيؤدي هذا إلى إنشاء عدد من ملفات تتبع ascii ، كل منها يتبع
ال - - .tr اتفاقية. يتم دمج كل الآثار في ملف
ملف واحد يتم إنجازه بشكل مشابه للأمثلة أعلاه:

يمكنك تمكين تتبع pcap على أساس معرف العقدة ومعرف الجهاز أيضًا. في هذه الحالة،
يتم ترجمة معرف العقدة إلى Ptr ويتم البحث عن البروتوكول المناسب في
العقدة. يتم استخدام البروتوكول والواجهة الناتجة لتحديد التتبع الناتج
مصدر.:

helper.EnableAsciiIpv4 ("بادئة"، 21، 1) ؛

بالطبع ، يمكن دمج الآثار في ملف واحد كما هو موضح أعلاه.

أخيرًا ، يمكنك تمكين تتبع ascii لجميع الواجهات في النظام ، مع ملفات
البروتوكول هو نفس نوع البروتوكول الذي يديره مساعد الجهاز:

helper.EnableAsciiIpv4All ("بادئة") ؛

سيؤدي هذا إلى إنشاء عدد من ملفات تتبع ascii ، واحدة لكل واجهة
في النظام المتعلق ببروتوكول من النوع الذي يديره المساعد. كل هذه الملفات
سيتبع -ن -أنا
في ملف واحد يتم إنجازه بشكل مشابه للأمثلة أعلاه.

أسكي البحث عن المفقودين الجهاز المساعد اسم الملف اختيار
ضمنيًا في أوصاف أسلوب البادئة أعلاه هو بناء الكامل
أسماء الملفات من خلال طريقة التنفيذ. من خلال الاتفاقية ، تتبع أسكي في NS-3 النظام
النموذج " - - .tr. "

كما ذكرنا سابقًا ، سيكون لكل عقدة في النظام معرف عقدة مخصص للنظام.
نظرًا لوجود مراسلات فردية بين البروتوكولات والعقد التي نستخدمها لمعرف العقدة
لتحديد هوية البروتوكول. سيكون لكل واجهة على بروتوكول معين
فهرس الواجهة (يسمى أيضًا ببساطة واجهة) بالنسبة إلى بروتوكولها. بشكل افتراضي،
بعد ذلك ، تم إنشاء ملف تتبع أسكي كنتيجة لتمكين التتبع على الجهاز الأول من
العقدة 21 ، باستخدام البادئة "البادئة" ، ستكون "البادئة-n21-i1.tr". استخدم البادئة لـ
توضيح عدة بروتوكولات لكل عقدة.

يمكنك دائمًا استخدام ملف NS-3 خدمة اسم الكائن لجعل هذا أكثر وضوحًا. على سبيل المثال ، إذا
يمكنك استخدام خدمة اسم الكائن لتعيين الاسم "serverIpv4" إلى البروتوكول الموجود على العقدة
21 ، وأيضًا تحديد الواجهة الأولى ، فسيتم تلقائيًا اسم ملف تتبع ascii الناتج
تصبح ، "بادئة-nserverIpv4-1.tr".

البحث عن المفقودين التنفيذ تفاصيل
البيانات المجموعات
يصف هذا الفصل ns-3 Data Collection Framework (DCF) ، والذي يوفر
القدرة على الحصول على البيانات التي تم إنشاؤها بواسطة النماذج في جهاز المحاكاة ، لأداء عبر الإنترنت
الاختزال ومعالجة البيانات ، وتنظيم البيانات الخام أو المحولة إلى مخرجات مختلفة
الأشكال.

يدعم إطار العمل حاليًا عمليات تشغيل ns-3 المستقلة التي لا تعتمد على أي خارجي
مراقبة تنفيذ البرنامج. قد يتم ربط الكائنات التي يوفرها DCF NS-3 تتبع
مصادر لتمكين معالجة البيانات.

الكود المصدري للفئات موجود في الدليل src / احصائيات.

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

تصميم
يتكون DCF من ثلاث فئات أساسية:

· مسبار هي آلية للأداة والتحكم في إخراج بيانات المحاكاة
تستخدم لرصد الأحداث الشيقة. ينتج مخرجات في شكل واحد أو أكثر NS-3
مصادر التتبع. يتم توصيل كائنات المجس بتتبع واحد أو أكثر المصارف (مسمي
جامعي) ، التي تعالج العينات عبر الإنترنت وتجهزها للإخراج.

· جامع يستهلك البيانات التي تم إنشاؤها بواسطة كائن مسبار واحد أو أكثر. ينفذ
التحولات على البيانات ، مثل التطبيع والتخفيض وحساب
إحصائيات أساسية. لا تنتج كائنات المُجمع البيانات التي يتم إخراجها مباشرةً بواسطة
ns-3 المدى بدلاً من ذلك ، يقومون بإخراج البيانات في اتجاه المصب إلى نوع آخر من الكائنات يسمى
مجمع، الذي يؤدي هذه الوظيفة. عادةً ما يُخرج المُجمعون بياناتهم بتنسيق
شكل مصادر التتبع أيضًا ، مما يسمح بتقييد الجامعين في سلسلة.

· مجمع هي نقطة نهاية البيانات التي تم جمعها بواسطة شبكة من المجسات والمجمعات.
المسؤولية الرئيسية للمُجمِّع هي تنظيم البيانات وما يقابلها
البيانات الوصفية إلى تنسيقات إخراج مختلفة مثل ملفات النص العادي أو ملفات جداول البيانات أو
قواعد بيانات.

توفر كل هذه الفئات الثلاثة القدرة على تشغيل نفسها أو إيقاف تشغيلها ديناميكيًا
في جميع أنحاء المحاكاة.

أي قائمة بذاتها NS-3 عادةً ما يُنشئ تشغيل المحاكاة الذي يستخدم DCF واحدًا على الأقل
مثيل لكل من الفئات الثلاثة أعلاه.
[صورة] نظرة عامة على إطار عمل جمع البيانات

تم توضيح التدفق الإجمالي لمعالجة البيانات بتنسيق البيانات المجموعات الإطار نظرة عامة.
على الجانب الأيسر ، ركض NS-3 تم تصوير المحاكاة. في سياق تشغيل
المحاكاة ، يتم توفير البيانات بواسطة النماذج من خلال مصادر التتبع ، أو عبر وسائل أخرى.
يوضح الرسم التخطيطي إمكانية توصيل المجسات بمصادر التتبع هذه لتلقي البيانات
بشكل غير متزامن ، أو تستطيع المجسات الاستقصاء عن البيانات. ثم يتم تمرير البيانات إلى كائن المجمع
الذي يحول البيانات. أخيرًا ، يمكن توصيل مُجمِّع بمخرجات ملف
جامع ، لإنشاء المؤامرات أو الملفات أو قواعد البيانات.
[صورة] تجميع إطار عمل جمع البيانات

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

البيانات المجموعات المساعدون
يتم توفير المرونة الكاملة لإطار جمع البيانات من خلال الترابط
من المجسات والمجمعات والمجمعات. يؤدي إجراء كل هذه الترابطات إلى
العديد من بيانات التكوين في برامج المستخدم. لسهولة الاستخدام ، فإن بعضًا من أكثرها شيوعًا
يمكن دمج العمليات وتغليفها في وظائف المساعدة. بالإضافة إلى بعض
البيانات التي تنطوي على NS-3 لا تحتوي مصادر التتبع على روابط Python ، بسبب القيود في
الارتباطات.

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

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

حتى الآن ، تم تنفيذ اثنين من مساعدي جمع البيانات:

· غنوبلوتهيلبر

FileHelper

مساعد Gnuplot
GnuplotHelper هي فئة مساعدة لإنتاج ملفات الإخراج المستخدمة لإنشاء gnuplots. ال
الهدف العام هو توفير القدرة للمستخدمين على إنشاء قطع بسرعة من البيانات المصدرة
in NS-3 مصادر التتبع. بشكل افتراضي ، يتم تنفيذ الحد الأدنى من تحويل البيانات ؛
الهدف هو إنشاء مخططات مع عدد قليل من عبارات التكوين (الافتراضية) مثل
ممكن.

مساعد Gnuplot نظرة عامة
سينشئ GnuplotHelper 3 ملفات مختلفة في نهاية المحاكاة:

مساحة منفصلة ملف البيانات gnuplot

ملف التحكم gnuplot

نص قذيفة لتوليد gnuplot

هناك نوعان من عبارات التكوين اللازمة لإنتاج المؤامرات. الأول
بيان تكوين المؤامرة (اسم الملف ، العنوان ، وسائل الإيضاح ، ونوع الإخراج ، حيث الإخراج
النوع الافتراضي هو PNG إذا لم يتم تحديده):

ConfigurePlot باطل (const std :: string & outputFileNameWithoutExtension ،
const std :: string & title،
const std :: string & xLegend ،
const std :: string & yLegend ،
const std :: string & terminalType = ".png") ؛

العبارة الثانية تربط مصدر الاهتمام:

PlotProbe باطل (const std :: string & typeId ،
const std :: string & path،
const std :: string & probeTraceSource ،
const std :: string & title) ؛

الحجج هي كما يلي:

typeId: ملف NS-3 TypeId للمسبار

· المسار: المسار في NS-3 التكوين لمصدر تتبع واحد أو أكثر

· probeTraceSource: ما هو ناتج المسبار (مصدر التتبع نفسه) الذي يجب رسمه

· العنوان: العنوان المطلوب ربطه بمجموعة (مجموعات) البيانات (في وسيلة إيضاح gnuplot)

أحد المتغيرات في PlotProbe أعلاه هو تحديد وسيطة اختيارية خامسة تتحكم
حيث يتم وضع المفتاح (وسيلة الإيضاح) في المؤامرة.

مثال يعمل بشكل كامل (من السابع) موضح أدناه:

// أنشئ مساعد gnuplot.
مخطط GnuplotHelper

// تكوين المؤامرة.
// تكوين المؤامرة. الوسيطة الأولى هي بادئة اسم الملف
// لملفات الإخراج التي تم إنشاؤها. الثاني والثالث والرابع
// الوسيطات هي ، على التوالي ، عناوين الرسم ، والمحور السيني ، والمحور الصادي
plotHelper.ConfigurePlot ("عدد الحزمة السابعة بايت" ،
"عدد بايتات الحزم مقابل الوقت" ،
"الوقت (بالثواني)" ،
"عدد بايت الحزم" ،
"بي إن جي")؛

// حدد نوع الفحص ومسار مصدر التتبع (في مساحة اسم التكوين) و
// فحص مصدر تتبع الإخراج ("OutputBytes") للتخطيط. الحجة الرابعة
// يحدد اسم تسمية سلسلة البيانات على قطعة الأرض. الاخير
// الوسيطة تنسق الحبكة عن طريق تحديد المكان الذي يجب أن يوضع فيه المفتاح.
plotHelper.PlotProbe (نوع المسبار ،
tracePath ،
"OutputBytes"،
"عدد بايت الحزم" ،
GnuplotAggregator :: KEY_BELOW) ؛

في هذا المثال ، نوع المسبار com.tracePath هي كما يلي (لـ IPv4):

probeType = "ns3 :: Ipv4PacketProbe" ؛
tracePath = "/ NodeList / * / $ ns3 :: Ipv4L3Protocol / Tx" ؛

يعتبر probeType معلمة أساسية لعمل هذا المساعد. يجب تسجيل معرّف TypeId هذا
في النظام ، ويجب أن يتطابق التوقيع الموجود على مصدر التتبع الخاص بالمسبار مع توقيع التتبع
المصدر الذي يتم ربطه به. أنواع المجسات محددة مسبقًا لعدد من أنواع البيانات
الموافق NS-3 القيم المتتبعة ، ولعدد قليل من تواقيع مصدر التتبع الأخرى مثل
مصدر تتبع "Tx" لـ ns3 :: Ipv4L3Protocol فئة.

لاحظ أن مسار مصدر التتبع المحدد قد يحتوي على أحرف بدل. في هذه الحالة ، متعددة
يتم رسم مجموعات البيانات على قطعة أرض واحدة ؛ واحد لكل مسار مطابق.

الناتج الرئيسي سيكون ثلاثة ملفات:

الحزمة السابعة بايت عدد. dat
العدد السابع للحزمة البايت
الحزمة السابعة بايت- العد. sh

في هذه المرحلة ، يمكن للمستخدمين إما تحرير ملف .plt لمزيد من التخصيصات ، أو
فقط قم بتشغيله من خلال gnuplot. جري sh الحزمة السابعة بايت- العد. sh يدير المؤامرة ببساطة
من خلال gnuplot ، كما هو موضح أدناه.
[صورة] 2-D Gnuplot تم إنشاؤه بواسطة مثال XNUMXth.cc..UNINDENT

يمكن ملاحظة أن العناصر الأساسية (وسيلة الإيضاح ، العنوان ، موضع وسيلة الإيضاح ، xlabel ، ylabel ،
ومسار البيانات) كلها موضوعة على قطعة الأرض. منذ أن كانت هناك مطابقتان ل
مسار التكوين المقدم ، يتم عرض سلسلتي البيانات:

· عدد بايتات الحزم 0 يتوافق مع / NodeList / 0 / $ ns3 :: Ipv4L3Protocol / Tx

· عدد بايتات الحزم 1 يتوافق مع / NodeList / 1 / $ ns3 :: Ipv4L3Protocol / Tx

مساعد Gnuplot تكوينالمؤامرة
GnuplotHelper's ConfigurePlot () يمكن استخدام الوظيفة لتكوين المؤامرات.

لديها النموذج الأولي التالي:

ConfigurePlot باطل (const std :: string & outputFileNameWithoutExtension ،
const std :: string & title،
const std :: string & xLegend ،
const std :: string & yLegend ،
const std :: string & terminalType = ".png") ؛

لها الحجج التالية:

┌───────────────────────────────┬───────────────── ─────────────────┐
│ الوسيطة │ الوصف │
├───────────────────────────────┼───────────────── ─────────────────┤
│outputFileNameWithoutExtension اسم ملفات gnuplot ذات الصلة بـ
│ │ الكتابة بدون تمديد. │
├───────────────────────────────┼───────────────── ─────────────────┤
│ العنوان │ سلسلة عنوان المؤامرة لاستخدامها في │
│ │ هذه المؤامرة. │
├───────────────────────────────┼───────────────── ─────────────────┤
│xLegend أسطورة x أفقي │
│ │ المحور. │
├───────────────────────────────┼───────────────── ─────────────────┤
“أسطورة” “أسطورة” عمودي “ص”
│ │ المحور. │
└───────────────────────────────┴───────────────── ─────────────────┘

│terminalType │ سلسلة ضبط نوع المحطة الطرفية لـ │
│ │ الإخراج. المحطة الافتراضية │
│ │ النوع هو "png". │
└───────────────────────────────┴───────────────── ─────────────────┘

GnuplotHelper's ConfigurePlot () تكوّن الوظيفة المعلمات ذات الصلة بالمؤامرة لهذا الغرض
gnuplot helper بحيث يقوم بإنشاء ملف بيانات gnuplot مفصول بمسافة باسم
outputFileNameWithoutExtension + ".dat" ، ملف تحكم gnuplot اسمه
outputFileNameWithoutExtension + ".plt" ، وبرنامج نصي شل لإنشاء gnuplot المسمى
outputFileNameWithoutExtension + ".sh".

يمكن رؤية مثال على كيفية استخدام هذه الوظيفة في ملف السابع الكود الموصوف أعلاه
حيث تم استخدامه على النحو التالي:

plotHelper.ConfigurePlot ("عدد الحزمة السابعة بايت" ،
"عدد بايتات الحزم مقابل الوقت" ،
"الوقت (بالثواني)" ،
"عدد بايت الحزم" ،
"بي إن جي")؛

مساعد Gnuplot مؤامرة
GnuplotHelper's PlotProbe () يمكن استخدام الوظيفة لرسم القيم التي تم إنشاؤها بواسطة المجسات.

لديها النموذج الأولي التالي:

PlotProbe باطل (const std :: string & typeId ،
const std :: string & path،
const std :: string & probeTraceSource ،
const std :: string & title،
تعداد GnuplotAggregator :: KeyLocation keyLocation = GnuplotAggregator :: KEY_INSIDE) ؛

لها الحجج التالية:

┌─────────────────┬─────────────────────────────── ───┐
│ الوسيطة │ الوصف │
├─────────────────┼─────────────────────────────── ───┤
│typeId معرف النوع للمسبار │
│ │ تم إنشاؤها بواسطة هذا المساعد. │
├─────────────────┼─────────────────────────────── ───┤
│ المسار │ تكوين المسار للوصول إلى التتبع │
│ │ المصدر. │
├─────────────────┼─────────────────────────────── ───┤
│probeTraceSource مصدر تتبع المجس إلى │
│ │ الوصول. │
├─────────────────┼─────────────────────────────── ───┤
│ العنوان │ العنوان المراد ربطه بـ │
│ │ مجموعة البيانات هذه │
├─────────────────┼─────────────────────────────── ───┤
│keyLocation موقع المفتاح في │
│ │ مؤامرة. الموقع الافتراضي هو │
│ │ بالداخل. │
└─────────────────┴─────────────────────────────── ───┘

GnuplotHelper's PlotProbe () ترسم الدالة مجموعة بيانات تم إنشاؤها عن طريق ربط ملف NS-3
مصدر التتبع باستخدام مسبار تم إنشاؤه بواسطة المساعد ، ثم رسم القيم من
فحص المصدر. سيكون لمجموعة البيانات العنوان المقدم ، وسوف تتكون من
"newValue" في كل طابع زمني.

إذا كان مسار التكوين يحتوي على أكثر من تطابق في النظام بسبب وجود حرف بدل ، إذن
سيتم رسم مجموعة بيانات واحدة لكل مباراة. سيتم إلحاق عناوين مجموعة البيانات بـ
الأحرف المتطابقة لكل من أحرف البدل في مسار التكوين ، مفصولة بمسافات. ل
على سبيل المثال ، إذا كان عنوان مجموعة البيانات المقترحة هو السلسلة "بايت" ، وكان هناك حرفان بدل
في المسار ، فإن عناوين مجموعة البيانات مثل "bytes-0 0" أو "bytes-12 9" ستكون ممكنة
تسميات لمجموعات البيانات المرسومة.

يمكن رؤية مثال على كيفية استخدام هذه الوظيفة في ملف السابع الكود الموصوف أعلاه
حيث تم استخدامه (مع استبدال متغير) على النحو التالي:

plotHelper.PlotProbe ("ns3 :: Ipv4PacketProbe"،
"/ NodeList / * / $ ns3 :: Ipv4L3Protocol / Tx" ،
"OutputBytes"،
"عدد بايت الحزم" ،
GnuplotAggregator :: KEY_BELOW) ؛

أخرى أمثلة
غنوبلوت المساعد مثال
مثال أبسط قليلاً من السابع يمكن العثور على المثال في
src / stats / أمثلة / gnuplot-helper-example.cc. تم إنشاء gnuplot ثنائي الأبعاد التالي باستخدام
المثال.
[صورة] 2-D Gnuplot تم إنشاؤه بواسطة gnuplot-helper-example.cc مثال .. UNINDENT

في هذا المثال ، يوجد كائن Emitter يزيد من عداده وفقًا لـ
عملية Poisson ثم تنبعث قيمة العداد كمصدر تتبع.

Ptr باعث = CreateObject () ؛
الأسماء :: إضافة ("/ أسماء / باعث" ، باعث) ؛

لاحظ أنه نظرًا لعدم وجود أحرف بدل في المسار المستخدم أدناه ، كان هناك داتاستريم واحد فقط
مرسومة في المؤامرة. تم تسمية مجموعة البيانات المنفردة هذه في المؤامرة ببساطة باسم "عدد الباعث" ،
مع عدم وجود لاحقات إضافية مثل ما يمكن للمرء أن يرى ما إذا كان هناك أحرف البدل في المسار.

// أنشئ مساعد gnuplot.
مخطط GnuplotHelper

// تكوين المؤامرة.
plotHelper.ConfigurePlot ("gnuplot-helper-example"،
"الباعث يحسب مقابل الوقت" ،
"الوقت (بالثواني)" ،
"عدد الباعث"،
"بي إن جي")؛

// ارسم القيم التي تم إنشاؤها بواسطة المسبار. الطريق الذي نقدمه
// يساعد على إزالة الغموض عن مصدر التتبع.
plotHelper.PlotProbe ("ns3 :: Uinteger32Probe" ،
"/ Names / Emitter / Counter" ،
"انتاج"،
"عدد الباعث"،
GnuplotAggregator :: KEY_INSIDE) ؛

FileHelper
FileHelper عبارة عن فئة مساعدة تُستخدم لوضع قيم البيانات في ملف. الهدف العام هو
لتزويد المستخدمين بالقدرة على إنشاء ملفات نصية منسقة بسرعة من البيانات المصدرة
in NS-3 مصادر التتبع. بشكل افتراضي ، يتم تنفيذ الحد الأدنى من تحويل البيانات ؛
الهدف هو إنشاء ملفات مع عدد قليل من عبارات التكوين (الافتراضية) مثل
ممكن.

FileHelper نظرة عامة
سيقوم FileHelper بإنشاء ملف نصي واحد أو أكثر في نهاية المحاكاة.

يمكن لـ FileHelper إنشاء 4 أنواع مختلفة من الملفات النصية:

· منسق

مسافة مفصولة (الافتراضي)

· مفصولة بفواصل

· الجدولة مفصولة

تستخدم الملفات المنسقة سلاسل تنسيق نمط C ووظيفة sprintf () لطباعة ملفات
القيم الموجودة في الملف الذي تتم كتابته.

الملف النصي التالي مع عمودين من القيم المنسقة المسماة
الحزمة السابعة بايت عدد 0.txt تم إنشاؤه باستخدام المزيد من التعليمات البرمجية الجديدة التي تمت إضافتها إلى ملف
أصلي NS-3 رمز المثال التعليمي. يتم عرض أول 10 سطور فقط من هذا الملف
هنا للإيجاز.

الوقت (بالثواني) = 1.000e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.004e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.004e + 00 عدد بايت الحزمة = 576
الوقت (بالثواني) = 1.009e + 00 عدد بايت الحزمة = 576
الوقت (بالثواني) = 1.009e + 00 عدد بايت الحزمة = 576
الوقت (بالثواني) = 1.015e + 00 عدد بايت الحزمة = 512
الوقت (بالثواني) = 1.017e + 00 عدد بايت الحزمة = 576
الوقت (بالثواني) = 1.017e + 00 عدد بايت الحزمة = 544
الوقت (بالثواني) = 1.025e + 00 عدد بايت الحزمة = 576
الوقت (بالثواني) = 1.025e + 00 عدد بايت الحزمة = 544



الملف النصي المختلف التالي مع عمودين من القيم المنسقة المسماة
الحزمة السابعة بايت عدد 1.txt تم إنشاؤه أيضًا باستخدام نفس الرمز الجديد الذي تمت إضافته إلى
الأصلي NS-3 رمز المثال التعليمي. يتم عرض أول 10 سطور فقط من هذا الملف
هنا للإيجاز.

الوقت (بالثواني) = 1.002e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.007e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.013e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.020e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.028e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.036e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.045e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.053e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.061e + 00 عدد بايت الحزمة = 40
الوقت (بالثواني) = 1.069e + 00 عدد بايت الحزمة = 40



الكود الجديد الذي تمت إضافته لإنتاج الملفين النصيين أدناه. مزيد من التفاصيل حول
سيتم تغطية واجهة برمجة التطبيقات هذه في قسم لاحق.

لاحظ أنه نظرًا لوجود 2 تطابق لحرف البدل في المسار ، هناك ملفان نصيان منفصلان
خلقوا. الملف النصي الأول ، والذي يحمل الاسم "0th-packet-byte-count-XNUMX.txt" ،
يتوافق مع تطابق حرف البدل مع استبدال "*" بـ "0". الملف النصي الثاني ،
والتي تسمى "الحزمة السابعة بايت عدد 1.txt" ، يتوافق مع تطابق حرف البدل مع
تم استبدال "*" بـ "1". لاحظ أيضًا أن استدعاء الوظيفة لـ كتابة مسبار () سيعطي
رسالة خطأ إذا لم تكن هناك مطابقات لمسار يحتوي على أحرف البدل.

// إنشاء الملف المساعد.
FileHelper fileHelper ؛

// تكوين الملف المراد كتابته.
fileHelper.ConfigureFile ("عدد الحزم السابعة بايت" ،
FileAggregator :: FORMATTED) ؛

// تعيين التسميات لملف الإخراج المنسق هذا.
fileHelper.Set2dFormat ("الوقت (ثوان) =٪ .3e \ t عدد وحدات البايت =٪ .0f")؛

// اكتب القيم التي تم إنشاؤها بواسطة المسبار.
fileHelper.WriteProbe ("ns3 :: Ipv4PacketProbe"،
"/ NodeList / * / $ ns3 :: Ipv4L3Protocol / Tx" ،
"OutputBytes") ؛

FileHelper تكوين الملف
FileHelper's تكوين ملف () يمكن استخدام الوظيفة لتكوين ملفات نصية.

لديها النموذج الأولي التالي:

ConfigureFile باطل (const std :: string & outputFileNameWithoutExtension ،
تعداد FileAggregator :: FileType fileType = FileAggregator :: SPACE_SEPARATED) ؛

لها الحجج التالية:

┌───────────────────────────────┬───────────────── ─────────────────┐
│ الوسيطة │ الوصف │
├───────────────────────────────┼───────────────── ─────────────────┤
│outputFileNameWithoutExtension اسم ملف الإخراج المراد كتابته
│ │ بدون تمديد. │
├───────────────────────────────┼───────────────── ─────────────────┤
│ نوع الملف │ نوع الملف المراد كتابته. │
│ النوع الافتراضي للملف هو space
│ │ مفصول. │
└───────────────────────────────┴───────────────── ─────────────────┘

FileHelper's تكوين ملف () تعمل الوظيفة على تكوين المعلمات ذات الصلة بالملف النصي لـ
file helper بحيث يقوم بإنشاء ملف يسمى outputFileNameWithoutExtension plus
معلومات إضافية محتملة من مطابقات أحرف البدل بالإضافة إلى ".txt" بقيم مطبوعة بتنسيق
محدد بواسطة نوع الملف. نوع الملف الافتراضي هو مفصول بمسافات.

يمكن رؤية مثال على كيفية استخدام هذه الوظيفة في ملف السابع الكود الموصوف أعلاه
حيث تم استخدامه على النحو التالي:

fileHelper.ConfigureFile ("عدد الحزم السابعة بايت" ،
FileAggregator :: FORMATTED) ؛

FileHelper اكتب مسبار
FileHelper's كتابة مسبار () يمكن استخدام الوظيفة لكتابة القيم التي تم إنشاؤها بواسطة المسابير إلى
ملفات نصية.

لديها النموذج الأولي التالي:

WriteProbe باطل (const std :: string & typeId ،
const std :: string & path،
const std :: string & probeTraceSource) ؛

لها الحجج التالية:

┌─────────────────┬─────────────────────────────── ───┐
│ الوسيطة │ الوصف │
├─────────────────┼─────────────────────────────── ───┤
│typeId معرف النوع للمسبار ليكون │
│ │ تم إنشاؤه. │
├─────────────────┼─────────────────────────────── ───┤
│ المسار │ تكوين المسار للوصول إلى التتبع │
│ │ المصدر. │
├─────────────────┼─────────────────────────────── ───┤
│probeTraceSource مصدر تتبع المجس إلى │
│ │ الوصول. │
└─────────────────┴─────────────────────────────── ───┘

FileHelper's كتابة مسبار () تقوم الوظيفة بإنشاء ملفات نصية ناتجة تم إنشاؤها عن طريق ربط ملف
مصدر التتبع ns-3 بمسبار تم إنشاؤه بواسطة المساعد ، ثم كتابة القيم من
فحص المصدر. ستحتوي أسماء ملفات الإخراج على النص المخزن في متغير العضو
m_outputFileNameWithoutExtension بالإضافة إلى ".txt" ، ويتكون من "newValue" في كل
الطابع الزمني.

إذا كان مسار التكوين يحتوي على أكثر من تطابق في النظام بسبب وجود حرف بدل ، إذن
سيتم إنشاء ملف إخراج واحد لكل مباراة. ستحتوي أسماء ملفات الإخراج على الامتداد
النص في m_outputFileNameWithoutExtension بالإضافة إلى الأحرف المتطابقة لكل ملف
أحرف البدل في مسار التكوين ، مفصولة بشرطة ، بالإضافة إلى ".txt". على سبيل المثال ، إذا كانت القيمة
في m_outputFileNameWithoutExtension هي السلسلة "packet-byte-count" ، وهناك نوعان
أحرف البدل في المسار ، ثم إخراج أسماء الملفات مثل "packet-byte-count-0-0.txt" أو
سيكون "packet-byte-count-12-9.txt" ممكنًا كأسماء للملفات التي سيتم إنشاؤها.

يمكن رؤية مثال على كيفية استخدام هذه الوظيفة في ملف السابع الكود الموصوف أعلاه
حيث تم استخدامه على النحو التالي:

fileHelper.WriteProbe ("ns3 :: Ipv4PacketProbe"،
"/ NodeList / * / $ ns3 :: Ipv4L3Protocol / Tx" ،
"OutputBytes") ؛

أخرى أمثلة
قم بتقديم المساعد مثال
مثال أبسط قليلاً من السابع يمكن العثور على المثال في
src / stats / أمثلة / file-helper-example.cc. يستخدم هذا المثال ملف FileHelper فقط.

الملف النصي التالي مع عمودين من القيم المنسقة المسماة ملف مساعد- example.txt
تم إنشاؤه باستخدام المثال. يتم عرض أول 10 سطور فقط من هذا الملف هنا لـ
الإيجاز.

الوقت (بالثواني) = 0.203 عد = 1
الوقت (بالثواني) = 0.702 عد = 2
الوقت (بالثواني) = 1.404 عد = 3
الوقت (بالثواني) = 2.368 عد = 4
الوقت (بالثواني) = 3.364 عد = 5
الوقت (بالثواني) = 3.579 عد = 6
الوقت (بالثواني) = 5.873 عد = 7
الوقت (بالثواني) = 6.410 عد = 8
الوقت (بالثواني) = 6.472 عد = 9


في هذا المثال ، يوجد كائن Emitter يزيد من عداده وفقًا لـ
عملية Poisson ثم تنبعث قيمة العداد كمصدر تتبع.

Ptr باعث = CreateObject () ؛
الأسماء :: إضافة ("/ أسماء / باعث" ، باعث) ؛

لاحظ أنه نظرًا لعدم وجود أحرف بدل في المسار المستخدم أدناه ، كان هناك ملف نصي واحد فقط
مخلوق. يسمى هذا الملف النصي الفردي ببساطة "file-helper-example.txt" ، بدون أي إضافات
اللواحق كما لو كانت هناك أحرف بدل في المسار.

// إنشاء الملف المساعد.
FileHelper fileHelper ؛

// تكوين الملف المراد كتابته.
fileHelper.ConfigureFile ("ملف مساعد-مثال" ،
FileAggregator :: FORMATTED) ؛

// تعيين التسميات لملف الإخراج المنسق هذا.
fileHelper.Set2dFormat ("الوقت (ثوان) =٪ .3e \ tCount =٪ .0f") ؛

// اكتب القيم التي تم إنشاؤها بواسطة المسبار. الطريق الذي نحن
// تقديم يساعد على إزالة الغموض عن مصدر التتبع.
fileHelper.WriteProbe ("ns3 :: Uinteger32Probe" ،
"/ Names / Emitter / Counter" ،
"انتاج")؛

مجال القيود
حاليًا ، تم تنفيذ هذه المجسات فقط وتوصيلها بـ GnuplotHelper و
إلى FileHelper:

· مسبار بوليان

· DoubleProbe

· التحقيق Uinteger8

· التحقيق Uinteger16

· التحقيق Uinteger32

· تايم بروب

· مسبار الحزم

· ApplicationPacketProbe

· IPv4PacketProbe

وبالتالي ، فإن هذه المجسات هي النوع الوحيد المتاح للاستخدام فيه PlotProbe ()
كتابة مسبار ().

في الأقسام القليلة التالية ، نغطي كل نوع من أنواع الكائنات الأساسية (Probe ، Collector ،
و Aggregator) بمزيد من التفصيل ، وإظهار كيف يمكن توصيلهما معًا باستخدام
المستوى الأدنى API.

تحقيقات
يوضح هذا القسم تفاصيل الوظائف التي توفرها فئة Probe إلى ملف NS-3
محاكاة ، ويعطي أمثلة على كيفية ترميزها في أحد البرامج. هذا القسم مخصص لـ
المستخدمون المهتمون بتطوير عمليات المحاكاة باستخدام NS-3 الأدوات واستخدام البيانات
Collection Framework ، التي تعد فئة Probe جزءًا منها ، لإنشاء إخراج البيانات باستخدام
نتائج المحاكاة الخاصة بهم.

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

عادةً ما يكون المسبار متصلًا بملف NS-3 مصدر التتبع. بهذه الطريقة ، كلما
يقوم مصدر التتبع بتصدير قيمة جديدة ، ويستهلك المسبار القيمة (ويصدرها في اتجاه مجرى النهر
إلى كائن آخر عبر مصدر التتبع الخاص به).

يمكن اعتبار المسبار كنوع من مرشح على مصادر التتبع. الأسباب الرئيسية ل
من المحتمل أن يتم ربط المسبار بدلاً من مصدر التتبع مباشرة كما يلي:

· قد يتم تشغيل وإيقاف المجسات ديناميكيًا أثناء المحاكاة مع المكالمات إلى يُمكَِن()
إبطال(). على سبيل المثال ، قد يتم إيقاف إخراج البيانات أثناء
مرحلة إحماء المحاكاة.

· قد تقوم المجسات بإجراء عمليات على البيانات لاستخراج القيم من أكثر تعقيدًا
الهياكل؛ على سبيل المثال ، إخراج قيمة حجم الحزمة من حزمة مستلمة ns3 :: Packet.

· تقوم المجسات بتسجيل اسم في ns3 :: Config مساحة الاسم (باستخدام الأسماء :: إضافة ()) حتى أن الآخرين
قد تشير الأشياء إليهم.

· توفر المجسات طريقة ثابتة تسمح للشخص بمعالجة المسبار بالاسم ، مثل
ما الذي يتم في مقياس ns2measure [Cic06]

Stat :: put ("my_metric" ، معرف ، عينة) ؛

المكافئ ns-3 لرمز القياس ns2 أعلاه ، على سبيل المثال

DoubleProbe :: SetValueByPath ("/ path / to / probe" ، عينة) ؛

خلق
لاحظ أنه لا يمكن إنشاء كائن فئة أساسية Probe لأنه قاعدة مجردة
class ، أي أنها تحتوي على وظائف افتراضية خالصة لم يتم تنفيذها. كائن من
سيتم إنشاء نوع DoubleProbe ، وهو فئة فرعية من فئة Probe ، هنا للعرض
ما يجب القيام به.

يقوم أحدهم بتعريف DoubleProbe في الذاكرة الديناميكية باستخدام فئة المؤشر الذكي (Ptr ). ل
إنشاء DoubleProbe في ذاكرة ديناميكية باستخدام مؤشرات ذكية ، يحتاج المرء فقط إلى استدعاء
NS-3 طريقة إنشاء كائن():

Ptr myprobe = CreateObject () ؛

يُنشئ الإعلان أعلاه DoubleProbes باستخدام القيم الافتراضية لسماته.
هناك أربع سمات في فئة DoubleProbe؛ اثنان في كائن الفئة الأساسية
DataCollectionObject ، واثنان في فئة Probe الأساسية:

· "الاسم" (DataCollectionObject) ، قيمة StringValue

"ممكّن" (DataCollectionObject) ، قيمة منطقية

· "ابدأ" (دقق) ، قيمة زمنية

· "توقف" (دقق) ، قيمة زمنية

يمكن للمرء تعيين هذه السمات عند إنشاء الكائن باستخدام الطريقة التالية:

Ptr myprobe = CreateObjectWithAttributes (
"الاسم" ، StringValue ("myprobe") ،
"ممكّن" ، قيمة منطقية (خطأ) ،
"Start" ، TimeValue (ثواني (100.0)) ،
"Stop"، TimeValue (Seconds (1000.0))) ؛

البداية والإيقاف هي متغيرات الوقت التي تحدد الفاصل الزمني لعمل المسبار. ال
سيقوم المسبار بإخراج البيانات فقط إذا كان الوقت الحالي للمحاكاة داخل ذلك
فاصلة. ستعمل قيمة الوقت الخاصة البالغة 0 ثانية للإيقاف على تعطيل هذه السمة (على سبيل المثال
استمر في تشغيل المسبار للمحاكاة بأكملها). Enabled هي علامة تقوم بتشغيل Probe أو
متوقف ، ويجب ضبطه على "صواب" لكي يقوم المسبار بتصدير البيانات. الاسم هو اسم الكائن
في إطار DCF.

استيراد تصدير البيانات
NS-3 يتم كتابة مصادر التتبع بقوة ، وبالتالي فإن آليات ربط المجسات بالتتبع
المصدر وتصدير البيانات تنتمي إلى الفئات الفرعية. على سبيل المثال ، الافتراضي
توزيع لل NS-3 يوفر فئة DoubleProbe المصممة لربط التتبع
مصدر تصدير قيمة مزدوجة. سنقوم بعد ذلك بتفصيل عملية DoubleProbe و
ثم ناقش كيف يمكن للمستخدم تعريف فئات المسبار الأخرى.

دبلبروب نظرة عامة
يتصل DoubleProbe بملف NS-3 مصدر التتبع ، ويصدر نفسه أ
مختلفة مزدوجة القيمة NS-3 مصدر التتبع.

الكود التالي مأخوذ من src / stats / أمثلة / double-probe-example.cc، يظهر الأساسيات
عمليات سباكة DoubleProbe في محاكاة ، حيث يتم فحص عداد
تم تصديره بواسطة كائن باعث (class Emitter).

Ptr باعث = CreateObject () ؛
الأسماء :: إضافة ("/ أسماء / باعث" ، باعث) ؛


Ptr probe1 = CreateObject () ؛

// قم بتوصيل المجس بعداد المرسل
bool متصل = probe1-> ConnectByObject ("Counter" ، باعث) ؛

تقوم التعليمة البرمجية التالية بفحص نفس العداد الذي تم تصديره بواسطة نفس كائن المرسل. هذا
ومع ذلك ، يستخدم DoubleProbe مسارًا في مساحة اسم التكوين لإنشاء ملف
اتصال. لاحظ أن المرسل سجل نفسه في مساحة اسم التكوين بعد ذلك
تم إنشاؤه؛ خلاف ذلك ، لن يعمل ConnectByPath.

Ptr probe2 = CreateObject () ؛

// ملاحظة ، لا يتم فحص أي قيمة مرتجعة هنا
probe2-> ConnectByPath ("/ Names / Emitter / Counter") ؛

سيتم تعيين قيمته في DoubleProbe الموضح أدناه باستخدام مساره في
مساحة التكوين. لاحظ أنه هذه المرة سجل DoubleProbe نفسه في ملف
التكوين بعد إنشائه.

Ptr probe3 = CreateObject () ؛
probe3-> SetName ("StaticallyAccessedProbe") ؛

// يجب أن نضيفه إلى قاعدة بيانات التكوين
الأسماء :: إضافة ("/ Names / Probes"، probe3-> GetName ()، probe3)؛

أصبحت وظيفة الباعث Count () قادرة الآن على تعيين قيمة DoubleProbe كـ
يتبع:

باطل
باعث :: العد (باطل)
{

m_counter + = 1.0 ؛
DoubleProbe :: SetValueByPath ("/ Names / StaticallyAccessedProbe"، m_counter) ؛

}

يوضح المثال أعلاه كيف أن الكود الذي يستدعي المسبار لا يجب أن يكون صريحًا
مرجع إلى المسبار ، ولكن يمكنه توجيه إعداد القيمة من خلال مساحة اسم التكوين.
هذا مشابه في وظائف ستات :: وضع الطريقة التي أدخلتها ns2measure paper
[Cic06] ، ويسمح للمستخدمين بإدراج عبارات Probe مؤقتًا مثل printf البيانات
ضمن القائمة NS-3 عارضات ازياء. لاحظ أنه من أجل أن تكون قادرًا على استخدام DoubleProbe في هذا
مثال كهذا ، شيئان ضروريان:

1. تم تضمين ملف رأس وحدة الإحصائيات في مثال ملف .cc

2. تم جعل المثال يعتمد على وحدة الإحصائيات في ملف wscript الخاص بها.

يجب القيام بأشياء مماثلة من أجل إضافة مجسات أخرى في أماكن أخرى في NS-3
قاعدة التعليمات البرمجية.

يمكن أيضًا تعيين قيم DoubleProbe باستخدام الوظيفة DoubleProbe :: SetValue () ،
بينما يمكن الحصول على قيم DoubleProbe باستخدام الوظيفة
DoubleProbe :: GetValue ().

يقوم DoubleProbe بتصدير قيم مزدوجة في مصدر تتبع "الإخراج" الخاص به؛ كائن المصب
يمكن ربط حوض التتبع (NotifyViaProbe) بهذا على النحو التالي:

متصل = probe1-> TraceConnect ("Output"، probe1-> GetName ()، MakeCallback (& ​​NotifyViaProbe)) ؛

أخرى المجسات
بالإضافة إلى DoubleProbe ، تتوفر أيضًا المجسات التالية:

· Uinteger8Probe يتصل بملف NS-3 مصدر تتبع يقوم بتصدير uint8_t.

· Uinteger16Probe يتصل بملف NS-3 مصدر تتبع يقوم بتصدير uint16_t.

· Uinteger32Probe يتصل بملف NS-3 مصدر تتبع يقوم بتصدير uint32_t.

PacketProbe يربط إلى ملف NS-3 مصدر تتبع تصدير حزمة.

ApplicationPacketProbe يتصل بملف NS-3 مصدر تتبع تصدير حزمة ومقبس
عنوان.

· Ipv4PacketProbe يتصل بملف NS-3 مصدر التتبع الذي يصدر حزمة ، كائن IPv4 ، و
واجهة.

خلق جديد مسبار أنواع
لإنشاء نوع مسبار جديد ، عليك القيام بالخطوات التالية:

· تأكد من اشتقاق فئة Probe الجديدة من فئة Probe الأساسية.

تأكد من أن الوظائف الافتراضية البحتة التي ترثها فئة Probe الجديدة من
تم تنفيذ فئة قاعدة المسبار.

· ابحث عن فئة Probe الحالية التي تستخدم مصدر تتبع هو الأقرب في النوع إلى
نوع مصدر التتبع الذي سيستخدمه مسبارك.

· انسخ ملف رأس فئة Probe الموجود (.h) وملف التنفيذ (.cc) إلى ملفين
ملفات جديدة بأسماء تطابق مسبارك الجديد.

· استبدال الأنواع والحجج والمتغيرات في الملفات المنسوخة بالمناسبة
اكتب للمسبار الخاص بك.

· قم بإجراء التعديلات اللازمة لجعل الشفرة ترجمة ولجعلها تتصرف كما تريد
أحب.

أمثلة
سيتم مناقشة مثالين بالتفصيل هنا:

مثال مسبار مزدوج

مثال على حزمة IPv4

مزدوج مسبار مثال
تمت مناقشة مثال المسبار المزدوج سابقًا. يمكن العثور على مثال البرنامج
in src / stats / أمثلة / double-probe-example.cc. لتلخيص ما يحدث في هذا البرنامج ،
هناك باعث يصدر عدادًا يتزايد وفقًا لعملية بواسون.
على وجه الخصوص ، يتم عرض طريقتين لإصدار البيانات:

1. من خلال متغير تتبع مرتبط بمسبار واحد:

TracedValue m_counter ؛ // عادةً ما يكون هذا نوعًا صحيحًا

2. من خلال عداد تم ترحيل قيمته إلى مسبار ثان ، يشار إليه باسمه في
نظام التكوين:

باطل
باعث :: العد (باطل)
{
NS_LOG_FUNCTION (هذا) ،
NS_LOG_DEBUG ("العد عند" << Simulator :: Now () .GetSeconds ()) ؛
m_counter + = 1.0 ؛
DoubleProbe :: SetValueByPath ("/ Names / StaticallyAccessedProbe"، m_counter) ؛
المحاكاة :: الجدول (الثواني (m_var-> GetValue ()) ، والباعث :: Count ، هذا) ؛
}

دعونا ننظر إلى المسبار بعناية أكبر. يمكن أن تتلقى المجسات قيمها في صورة مضاعفة
طرق:

1. بواسطة المجس للوصول إلى مصدر التتبع مباشرة وربط حوض التتبع به

2. بواسطة المسبار للوصول إلى مصدر التتبع من خلال مساحة اسم التكوين وتوصيل أ
تتبع الغرق إليه

3. بواسطة كود الاستدعاء صراحة استدعاء المسبار SetValue () طريقة

4. بواسطة كود الاستدعاء صراحة SetValueByPath
("/ path / through / Config / namespace"، ...)

من المتوقع أن تكون أول طريقتين هي الأكثر شيوعًا. أيضًا في المثال ، ملف
يتم عرض ربط وظيفة رد الاتصال العادية ، كما هو الحال عادةً في NS-3. هذا
وظيفة رد الاتصال غير مرتبطة بكائن مسبار. سنسمي هذه الحالة 0) أدناه.

// هذه وظيفة لاختبار ربط دالة خام بمصدر التتبع
باطل
NotifyViaTraceSource (سياق std :: string ، double oldVal ، double newVal)
{
NS_LOG_DEBUG ("السياق:" << سياق << "قديم" << oldVal << "new" << newVal) ؛
}

أولاً ، يحتاج الباعث إلى الإعداد:

Ptr باعث = CreateObject () ؛
الأسماء :: إضافة ("/ أسماء / باعث" ، باعث) ؛

// لا يرتبط الكائن Emitter بعقدة ns-3 ، لذلك
// لن تبدأ تلقائيًا ، لذلك نحن بحاجة إلى القيام بذلك بأنفسنا
المحاكاة :: الجدول (الثواني (0.0) ، والباعث :: البداية ، الباعث) ؛

تتفاعل DoubleProbes المختلفة مع الباعث في المثال كما هو موضح أدناه.

الحالة 0):

// يظهر أدناه وظائف نموذجية بدون مسبار
// (قم بتوصيل وظيفة الحوض بمصدر التتبع)
//
متصل = باعث-> TraceConnect ("عداد" ، "سياق عينة" ، MakeCallback (& ​​NotifyViaTraceSource)) ؛
NS_ASSERT_MSG (متصل ، "مصدر التتبع غير متصل") ؛

حالة 1):

//
// سيتم ربط Probe1 مباشرة بكائن مصدر تتبع Emitter
//

// سيتم ربط المسبار 1 بمصدر تتبع Emitter
Ptr probe1 = CreateObject () ؛
// يمكن أن يكون اسم المسبار بمثابة سياقه في التتبع
probe1-> SetName ("ObjectProbe") ؛

// قم بتوصيل المجس بعداد المرسل
متصل = probe1-> ConnectByObject ("عداد" ، باعث) ؛
NS_ASSERT_MSG (متصل ، "مصدر التتبع غير متصل بـ probe1") ؛

حالة 2):

//
// سيتم ربط Probe2 بكائن مصدر تتبع Emitter بواسطة
// الوصول إليه عن طريق اسم المسار في قاعدة بيانات التكوين
//

// إنشاء مسبار آخر مماثل ؛ سيؤدي ذلك إلى التوصيل عبر مسار التكوين
Ptr probe2 = CreateObject () ؛
probe2-> SetName ("PathProbe") ؛

// ملاحظة ، لا يتم فحص أي قيمة مرتجعة هنا
probe2-> ConnectByPath ("/ Names / Emitter / Counter") ؛

الحالة 4) (الحالة 3 غير معروضة في هذا المثال):

//
// سيتم استدعاء Probe3 بواسطة الباعث مباشرة من خلال ملف
// الطريقة الثابتة SetValueByPath ().
//
Ptr probe3 = CreateObject () ؛
probe3-> SetName ("StaticallyAccessedProbe") ؛
// يجب أن نضيفه إلى قاعدة بيانات التكوين
الأسماء :: إضافة ("/ Names / Probes"، probe3-> GetName ()، probe3)؛

وأخيرًا ، يوضح المثال كيف يمكن ربط المجسات لتوليد الإخراج:

// يجب أن يولد المسبار نفسه ناتجًا. السياق الذي نقدمه
// لهذا التحقيق (في هذه الحالة ، اسم التحقيق) سيساعد في توضيح
// مصدر التتبع
متصل = probe3-> TraceConnect ("الإخراج" ،
"/ Names / Probes / StaticallyAccessedProbe / Output" ،
MakeCallback (& ​​NotifyViaProbe)) ؛
NS_ASSERT_MSG (متصل ، "مصدر التتبع غير .. متصل بإخراج probe3") ؛

تم ربط رد الاتصال التالي بالمسبار في هذا المثال لأغراض توضيحية ؛
عادة ، سيتم ربط المسبار بكائن جامع.

// هذه وظيفة لاختبار ربطه بمخرج المجس
باطل
NotifyViaProbe (std :: string Context، double oldVal، double newVal)
{
NS_LOG_DEBUG ("السياق:" << سياق << "قديم" << oldVal << "new" << newVal) ؛
}

IPv4 رزمة قطعة مثال
يعتمد مثال مخطط حزمة IPv4 على المثال الخامس من ملف NS-3 درس تعليمي. هو - هي
يمكن العثور عليها في src / stats / أمثلة / ipv4-packet-plot-example.cc.

العقدة 0 العقدة 1
+ ---------------- + + ---------------- +
| NS-3 TCP | | NS-3 TCP |
+ ---------------- + + ---------------- +
| 10.1.1.1 | | 10.1.1.2 |
+ ---------------- + + ---------------- +
| من نقطة إلى نقطة | | من نقطة إلى نقطة |
+ ---------------- + + ---------------- +
| |
+ --------------------- +

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

هناك جوانب أخرى لهذا المثال سيتم شرحها لاحقًا في التوثيق.
نوعا البيانات التي يتم تصديرها هما الحزمة نفسها (الناتج) وعدد من
عدد البايت في الحزمة (بايتات الإخراج).

النوع
Ipv4PacketProbe :: GetTypeId ()
{
ثابت TypeId tid = TypeId ("ns3 :: Ipv4PacketProbe")
.SetParent ()
.AddConstructor ()
.AddTraceSource ("الإخراج"،
"الحزمة بالإضافة إلى كائن IPv4 الخاص بها والواجهة التي تعمل كإخراج لهذا التحقيق" ،
MakeTraceSourceAccessor (& Ipv4PacketProbe :: m_output))
.AddTraceSource ("OutputBytes"،
"عدد البايت في الحزمة" ،
MakeTraceSourceAccessor (& Ipv4PacketProbe :: m_outputBytes))
;
عودة المد
}

عندما يحصل مصدر تتبع المسبار على حزمة ، إذا تم تمكين Probe ، فسيخرج
الحزمة الموجودة عليها الناتج مصدر التتبع ، ولكنه سينتج أيضًا عدد البايتات في ملف
بايتات الإخراج مصدر التتبع.

باطل
Ipv4PacketProbe :: TraceSink (Ptr حزمة ، Ptr ipv4 ، واجهة uint4_t)
{
NS_LOG_FUNCTION (هذه << الحزمة << ipv4 << الواجهة) ؛
إذا (IsEnabled ())
{
m_packet = حزمة ؛
m_ipv4 = ipv4 ؛
m_interface = الواجهة ؛
m_output (حزمة ، ipv4 ، واجهة) ؛

uint32_t packetSizeNew = packet-> GetSize () ؛
m_outputBytes (m_packetSizeOld ، packetSizeNew) ؛
m_packetSizeOld = packetSizeNew ؛
}
}

مراجع حسابات
[Cic06]
كلاوديو سيكونيتي ، إنزو مينجوزي ، جيوفاني ستيا ، "إطار متكامل لـ
تمكين جمع البيانات والتحليل الإحصائي الفعال مع ns2 ، ورشة عمل حول
ns-2 (WNS2) ، بيزا ، إيطاليا ، أكتوبر 2006.

جامعي
هذا القسم هو عنصر نائب لتفاصيل الوظائف التي يوفرها المُجمع
فئة ل NS-3 محاكاة ، ويعطي أمثلة على كيفية ترميزها في أحد البرامج.

ملحوظة: اعتبارًا من ns-3.18 ، لا يزال المقتنيات قيد التطوير ولم يتم توفيرها كجزء
من الإطار.

تجميع
يوضح هذا القسم تفاصيل الوظائف التي توفرها فئة المُجمِّع إلى ملف NS-3
محاكاة. هذا القسم مخصص للمستخدمين المهتمين بتطوير عمليات المحاكاة باستخدام
NS-3 الأدوات واستخدام إطار عمل جمع البيانات ، والذي تعتبر فئة المُجمِّع منه
الجزء ، لتوليد إخراج البيانات مع نتائج المحاكاة الخاصة بهم.

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

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

لاحظ ما يلي حول المُجمِّعين:

المُجمِّع قد يتم تشغيله وإيقاف تشغيله ديناميكيًا أثناء المحاكاة مع المكالمات إلى
يُمكَِن() إبطال(). على سبيل المثال ، قد يتم إيقاف تجميع البيانات أثناء
مرحلة إحماء المحاكاة ، مما يعني أن هذه القيم لن يتم تضمينها في المرحلة النهائية
وسط الإخراج.

المُجمِّعون يتلقون البيانات من المُجمِّعين عبر عمليات الاسترداد. عندما يرتبط المُجمع
إلى مجمع ، يتم إجراء استدعاء لـ TraceConnect لتأسيس تتبع العارض
طريقة الحوض كإعادة اتصال.

حتى الآن ، تم تنفيذ اثنين من المُجمِّعين:

· مجمع GnuplotAggregator

مجمع الملفات

مجمّع Gnuplot
ينتج GnuplotAggregator ملفات الإخراج المستخدمة لإنشاء gnuplots.

سيقوم GnuplotAggregator بإنشاء 3 ملفات مختلفة في نهاية المحاكاة:

مساحة منفصلة ملف البيانات gnuplot

ملف التحكم gnuplot

نص قذيفة لتوليد gnuplot

خلق
سيتم إنشاء كائن من النوع GnuplotAggregator هنا لإظهار ما يجب القيام به.

يقوم أحدهم بتعريف GnuplotAggregator في ذاكرة ديناميكية باستخدام فئة المؤشر الذكي
(Ptr ). لإنشاء مجمّع GnuplotAggregator في ذاكرة ديناميكية باستخدام مؤشرات ذكية ، واحد فقط
يحتاج إلى استدعاء NS-3 طريقة إنشاء كائن(). الكود التالي من
src / stats / أمثلة / gnuplot-aggregator-example.cc يوضح كيفية القيام بذلك:

سلسلة fileNameWithoutExtension = "gnuplot-aggregator" ؛

// إنشاء مجمع.
Ptr المجمّع =
إنشاء كائن (fileNameWithoutExtension) ؛

الوسيطة الأولى للمُنشئ ، fileNameWithoutExtension ، هي اسم ملف
gnuplot ذات الصلة بالكتابة بدون امتداد. سيقوم GnuplotAggregator هذا بإنشاء ملف
ملف بيانات gnuplot مفصول بمسافة باسم "gnuplot-aggregator.dat" ، ملف تحكم gnuplot
باسم "gnuplot-aggregator.plt" ، ونص برمجي شل لإنشاء gnuplot المسمى +
"gnuplot-aggregator.sh".

يمكن أن يكون لـ gnuplot الذي تم إنشاؤه مفتاحه في 4 مواقع مختلفة:

· لا مفتاح

· المفتاح داخل الحبكة (الافتراضي)

· المفتاح فوق المؤامرة

· المفتاح أدناه المؤامرة

يُسمح لقيم تعداد موقع مفتاح gnuplot التالية بتحديد موضع المفتاح:

تعداد KeyLocation {
لا مفتاح،
KEY_INSIDE ،
KEY_ABOVE ،
المفتاح_أدناه
};

إذا كان مطلوبًا أن يكون لديك المفتاح أدناه بدلاً من الموضع الافتراضي للداخل ، إذن
يمكنك القيام بما يلي.

المجمع-> SetKeyLocation (GnuplotAggregator :: KEY_BELOW) ؛

أمثلة
سيتم مناقشة أحد الأمثلة بالتفصيل هنا:

مثال مجمع Gnuplot

غنوبلوت مجمع مثال
يمكن العثور على مثال يقوم بتمارين GnuplotAggregator في
src / stats / أمثلة / gnuplot-aggregator-example.cc.

تم إنشاء gnuplot ثنائي الأبعاد التالي باستخدام المثال.
[صورة] 2-D Gnuplot تم إنشاؤه بواسطة gnuplot-aggregator-example.cc مثال .. UNINDENT

يوضح هذا الرمز من المثال كيفية إنشاء GnuplotAggregator كما تمت مناقشته
في الاعلى.

Create2dPlot () باطلة
{
باستخدام مساحة الاسم الأمراض المنقولة جنسيا.

سلسلة fileNameWithoutExtension = "gnuplot-aggregator" ؛
string plotTitle = "Gnuplot Aggregator Plot"؛
سلسلة plotXAxisHeading = "الوقت (بالثواني)" ؛
سلسلة plotYAxisHeading = "قيم مزدوجة" ؛
سلسلة plotDatasetLabel = "قيم البيانات" ؛
سلسلة datasetContext = "مجموعة البيانات / السياق / السلسلة"؛

// إنشاء مجمع.
Ptr المجمّع =
إنشاء كائن (fileNameWithoutExtension) ؛

يتم تعيين سمات GnuplotAggregator المختلفة بما في ذلك مجموعة البيانات ثنائية الأبعاد التي ستكون
مؤامرة.

// تعيين خصائص المجمّع.
المجمع-> SetTerminal ("png") ؛
المجمع-> SetTitle (plotTitle) ؛
المجمع-> SetLegend (plotXAxisHeading ، plotYAxisHeading) ؛

// أضف مجموعة بيانات إلى المُجمع.
المجمع-> Add2dDataset (datasetContext ، plotDatasetLabel) ؛

// يجب أن يكون المجمّع قيد التشغيل
المجمع-> تمكين () ؛

بعد ذلك ، يتم حساب القيم ثنائية الأبعاد ، ويتم كتابة كل واحدة على حدة إلى
GnuplotAggregator باستخدام امتداد Write2d () وظيفة.

وقت مضاعف؛
قيمة مزدوجة

// أنشئ مجموعة بيانات ثنائية الأبعاد.
لـ (الوقت = -5.0 ؛ الوقت <= +5.0 ؛ الوقت + = 1.0)
{
// احسب منحنى 2-D
//
/ / 2
// القيمة = الوقت.
//
القيمة = الوقت * الوقت ؛

// أضف هذه النقطة إلى المؤامرة.
المجمع-> Write2d (datasetContext ، الوقت ، القيمة) ؛
}

// تعطيل تسجيل البيانات للمجمع.
المجمع-> تعطيل () ؛
}

مجمع الملفات
يرسل FileAggregator القيم التي يتلقاها إلى ملف.

يمكن لـ FileAggregator إنشاء 4 أنواع مختلفة من الملفات:

· منسق

مسافة مفصولة (الافتراضي)

· مفصولة بفواصل

· الجدولة مفصولة

تستخدم الملفات المنسقة سلاسل تنسيق نمط C ووظيفة sprintf () لطباعة ملفات
القيم الموجودة في الملف الذي تتم كتابته.

خلق
سيتم هنا إنشاء كائن من النوع FileAggregator لإظهار ما يجب القيام به.

يقوم أحدهم بتعريف FileAggregator في الذاكرة الديناميكية باستخدام فئة المؤشر الذكي (Ptr ).
لإنشاء مجمّع ملفات في ذاكرة ديناميكية باستخدام مؤشرات ذكية ، يحتاج المرء فقط إلى الاتصال
هيه NS-3 طريقة CreateObject. الكود التالي من
src / stats / أمثلة / file-aggregator-example.cc يوضح كيفية القيام بذلك:

string fileName = "file-aggregator-formatted-values.txt" ؛

// إنشاء مجمع يحتوي على قيم منسقة.
Ptr المجمّع =
إنشاء كائن (اسم الملف ، FileAggregator :: FORMATTED) ؛

الوسيطة الأولى للمُنشئ ، اسم الملف ، هي اسم الملف المراد كتابته ؛ ال
الوسيطة الثانية ، نوع الملف ، هي نوع الملف المراد كتابته. سيقوم FileAggregator هذا بإنشاء ملف
ملف يسمى "file-aggregator-formatted-values.txt" مع طباعة قيمه كما هو محدد بواسطة
نوع الملف ، أي تنسيقه في هذه الحالة.

يُسمح بقيم تعداد أنواع الملفات التالية:

تعداد نوع الملف {
منسق ،
SPACE_SEPARATED ،
مفصولة بفواصل،
TAB_SEPARATED
};

أمثلة
سيتم مناقشة أحد الأمثلة بالتفصيل هنا:

مثال مجمع الملف

قم بتقديم مجمع مثال
يمكن العثور على مثال يقوم بتمارين FileAggregator في
src / stats / أمثلة / file-aggregator-example.cc.

تم إنشاء الملف النصي التالي مع عمودين من القيم مفصولة بفاصلات باستخدام
مثال.

-5,25
-4,16
-3,9
-2,4
-1,1
0,0
1,1
2,4
3,9
4,16
5,25

يوضح هذا الرمز من المثال كيفية إنشاء FileAggregator كما تمت مناقشته
في الاعلى.

CreateCommaSeparatedFile () باطلة
{
باستخدام مساحة الاسم الأمراض المنقولة جنسيا.

سلسلة fileName = "ملف-مجمّع-فاصلة-مفصول. txt" ؛
سلسلة datasetContext = "مجموعة البيانات / السياق / السلسلة"؛

// إنشاء مجمع.
Ptr المجمّع =
إنشاء كائن (اسم الملف ، FileAggregator :: COMMA_SEPARATED) ؛

يتم تعيين سمات FileAggregator.

// يجب أن يكون المجمّع قيد التشغيل
المجمع-> تمكين () ؛

بعد ذلك ، يتم حساب القيم ثنائية الأبعاد ، ويتم كتابة كل واحدة على حدة إلى
FileAggregator باستخدام امتداد الملف Write2d () وظيفة.

وقت مضاعف؛
قيمة مزدوجة

// أنشئ مجموعة بيانات ثنائية الأبعاد.
لـ (الوقت = -5.0 ؛ الوقت <= +5.0 ؛ الوقت + = 1.0)
{
// احسب منحنى 2-D
//
/ / 2
// القيمة = الوقت.
//
القيمة = الوقت * الوقت ؛

// أضف هذه النقطة إلى المؤامرة.
المجمع-> Write2d (datasetContext ، الوقت ، القيمة) ؛
}

// تعطيل تسجيل البيانات للمجمع.
المجمع-> تعطيل () ؛
}

تم أيضًا إنشاء الملف النصي التالي مع عمودين من القيم المنسقة باستخدام امتداد
مثال.

الوقت = -5.000e + 00 القيمة = 25
الوقت = -4.000e + 00 القيمة = 16
الوقت = -3.000e + 00 القيمة = 9
الوقت = -2.000e + 00 القيمة = 4
الوقت = -1.000e + 00 القيمة = 1
الوقت = 0.000e + 00 القيمة = 0
الوقت = 1.000e + 00 القيمة = 1
الوقت = 2.000e + 00 القيمة = 4
الوقت = 3.000e + 00 القيمة = 9
الوقت = 4.000e + 00 القيمة = 16
الوقت = 5.000e + 00 القيمة = 25

يوضح هذا الرمز من المثال كيفية إنشاء FileAggregator كما تمت مناقشته
في الاعلى.

CreateFormattedFile () باطلة
{
باستخدام مساحة الاسم الأمراض المنقولة جنسيا.

string fileName = "file-aggregator-formatted-values.txt" ؛
سلسلة datasetContext = "مجموعة البيانات / السياق / السلسلة"؛

// إنشاء مجمع يحتوي على قيم منسقة.
Ptr المجمّع =
إنشاء كائن (اسم الملف ، FileAggregator :: FORMATTED) ؛

يتم تعيين سمات FileAggregator ، بما في ذلك سلسلة تنسيق النمط C لاستخدامها.

// تعيين تنسيق القيم.
المجمع-> Set2dFormat ("الوقت =٪ .3e \ tValue =٪ .0f") ؛

// يجب أن يكون المجمّع قيد التشغيل
المجمع-> تمكين () ؛

بعد ذلك ، يتم حساب القيم ثنائية الأبعاد ، ويتم كتابة كل واحدة على حدة إلى
FileAggregator باستخدام امتداد الملف Write2d () وظيفة.

وقت مضاعف؛
قيمة مزدوجة

// أنشئ مجموعة بيانات ثنائية الأبعاد.
لـ (الوقت = -5.0 ؛ الوقت <= +5.0 ؛ الوقت + = 1.0)
{
// احسب منحنى 2-D
//
/ / 2
// القيمة = الوقت.
//
القيمة = الوقت * الوقت ؛

// أضف هذه النقطة إلى المؤامرة.
المجمع-> Write2d (datasetContext ، الوقت ، القيمة) ؛
}

// تعطيل تسجيل البيانات للمجمع.
المجمع-> تعطيل () ؛
}

محولات
يوضح هذا القسم تفاصيل الوظائف التي توفرها فئة المحول إلى ملف NS-3
محاكاة. هذا القسم مخصص للمستخدمين المهتمين بتطوير عمليات المحاكاة باستخدام
NS-3 الأدوات واستخدام إطار عمل جمع البيانات ، الذي تعتبر فئة المحول جزءًا منه ،
لتوليد إخراج البيانات مع نتائج المحاكاة الخاصة بهم.

ملاحظة: المصطلح "محول" يمكن أن يكون مكتوبًا أيضًا "محول" ؛ اخترنا محاذاة التدقيق الإملائي
مع معيار C ++.

محول نظرة عامة
يتم استخدام المحول لإجراء اتصالات بين أنواع مختلفة من كائنات DCF.

حتى الآن ، تم تنفيذ مهايئ واحد:

TimeSeriesAdaptor

الوقت: مسلسلات محول
يتيح TimeSeriesAdaptor للمسابقات الاتصال مباشرة بالمجمِّعين دون الحاجة إلى أي منها
جامع بينهما.

يستخدم كل من مساعدي DCF المنفذين TimeSeriesAdaptors من أجل إجراء اختبار
قيم من أنواع مختلفة وإخراج الوقت الحالي بالإضافة إلى القيمة مع كلاهما المحول
إلى الزوجي.

دور فئة TimeSeriesAdaptor هو دور المحول ، الذي يأخذ قيمة أولية
فحص البيانات من أنواع مختلفة وإخراج مجموعة من قيمتين مزدوجتين. الأول هو
الطابع الزمني ، والذي قد يتم تعيينه على درجات دقة مختلفة (على سبيل المثال ، ثوانٍ ، ميلي ثانية ، إلخ) في
المستقبل ولكنه حاليًا غير مقيد إلى ثوانٍ. والثاني هو تحويل أ
قيمة غير مزدوجة إلى قيمة مزدوجة (ربما مع فقدان الدقة).

النطاق / القيود
يناقش هذا القسم نطاق وحدود إطار عمل جمع البيانات.

حاليًا ، تم تنفيذ هذه المجسات فقط في DCF:

· مسبار بوليان

· DoubleProbe

· التحقيق Uinteger8

· التحقيق Uinteger16

· التحقيق Uinteger32

· تايم بروب

· مسبار الحزم

· ApplicationPacketProbe

· IPv4PacketProbe

حاليًا ، لا يتوفر مُجمع في DCF ، على الرغم من أن BasicStatsCollector أقل من
التنمية.

حاليًا ، تم تنفيذ المجمعين فقط في DCF:

· مجمع GnuplotAggregator

مجمع الملفات

حاليًا ، تم تنفيذ هذا المحول فقط في DCF:

محول سلسلة الوقت.

Future للعمل
يناقش هذا القسم العمل المستقبلي الذي يتعين القيام به في إطار عمل جمع البيانات.

فيما يلي بعض الأشياء التي لا يزال يتعين القيام بها:

ربط المزيد من مصادر التتبع في NS-3 كود للحصول على المزيد من القيم من المحاكاة.

· تنفيذ أنواع أكثر من المجسات الموجودة حاليًا.

· تنفيذ أكثر من مجرد جامع ثنائي الأبعاد ، BasicStatsCollector.

· تنفيذ المزيد من المُجمِّعين.

· تنفيذ أكثر من مجرد محولات.

إحصائي الإطار
يلخص هذا الفصل العمل على محاكاة جمع البيانات والإطار الإحصائي ل
NS-3.

الكود المصدري للإطار الإحصائي موجود في الدليل src / احصائيات.

الأهداف
الأهداف الأساسية لهذا الجهد هي ما يلي:

· توفير وظائف لتسجيل البيانات والإحصاءات وحسابها وتقديمها لتحليلها
من محاكاة الشبكة.

· تعزيز أداء المحاكاة عن طريق تقليل الحاجة إلى إنشاء سجلات تتبع واسعة النطاق
من أجل جمع البيانات.

· تمكين التحكم في المحاكاة عبر الإحصائيات عبر الإنترنت ، على سبيل المثال إنهاء عمليات المحاكاة أو
تكرار المحاكمات.

تشمل الأهداف الفرعية المشتقة والميزات المستهدفة الأخرى ما يلي:

· التكامل مع نظام التتبع ns-3 الحالي كإطار عمل أساسي للأجهزة
لمحرك المحاكاة الداخلي ، على سبيل المثال مكدسات الشبكة وأجهزة الشبكة والقنوات.

· تمكين المستخدمين من استخدام الإطار الإحصائي دون الحاجة إلى استخدام التتبع
نظام.

· مساعدة المستخدمين على إنشاء وتجميع وتحليل البيانات عبر تجارب متعددة.

· تقديم الدعم للأجهزة التي تم إنشاؤها بواسطة المستخدم ، مثل الأحداث الخاصة بالتطبيق و
الإجراءات.

انخفاض الذاكرة ونفقات وحدة المعالجة المركزية عند عدم استخدام الحزمة.

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

· الدعم النهائي لتوزيع التكرارات المستقلة مهم ولكنه غير مدرج
في الجولة الأولى من الميزات.

نظرة عامة
يتضمن إطار الإحصاء الميزات التالية:

· الإطار الأساسي واثنان من جامعي البيانات الأساسيين: عداد ، و min / max / avg / total
المراقبون.

· امتدادات تلك للعمل بسهولة مع الأوقات والحزم.

إخراج نص عادي منسق ل OMNet ++.

· إخراج قاعدة البيانات باستخدام سكليتي، محرك SQL مستقل وخفيف الوزن وعالي الأداء.

· البيانات الوصفية الإلزامية والمفتوحة للوصف والعمل مع عمليات التشغيل.

· مثال على أساس التجربة النظرية لفحص خصائص NS-3
أداء WiFi المخصص الافتراضي. يتضمن ما يلي:

· يُنشئ شبكة WiFi ذات عقدتين مخصصتين ، مع مسافة معلمات للعقد
بعيدا، بمعزل، على حد.

· مصدر حركة مرور UDP وتطبيقات المصارف مع سلوك مختلف قليلاً و
خطاطيف القياس من فئات الأسهم.

· جمع البيانات من NS-3 الأساسية عبر إشارات التتبع الموجودة ، ولا سيما بيانات حول
إطارات ترسلها وتستقبلها كائنات WiFi MAC.

· أدوات التطبيقات المخصصة عن طريق توصيل إشارات التتبع الجديدة إلى القانون الأساسي
وكذلك عبر التحديثات المباشرة. يتم تسجيل المعلومات حول الحزم الإجمالية
المرسلة والمستلمة ، البايت المرسلة ، والتأخير من طرف إلى طرف.

مثال على استخدام علامات الحزمة لتتبع التأخير من طرف إلى طرف.

نص تحكم بسيط يقوم بتشغيل عدد من التجارب بتفاوتات
المسافات والاستعلام عن قاعدة البيانات الناتجة لإنتاج رسم بياني باستخدام GNUPlot.

لكى يفعل
تشمل العناصر ذات الأولوية العالية ما يلي:

· إدراج رمز إحصائي على الإنترنت ، على سبيل المثال لفترات الثقة بكفاءة الذاكرة.

· أحكام في جامعي البيانات لإنهاء عمليات التشغيل ، أي عند الحد الأدنى أو
يتم استيفاء الثقة.

جامعي البيانات لتسجيل العينات بمرور الوقت ، وإخراجها إلى التنسيقات المختلفة.

· شرح كتابة الغراء الدوري البسيط للأحداث لاستقصاء بعض القيمة بانتظام.

يجب أن يثبت كل من هؤلاء أنه من السهل تضمينه في الإطار الحالي.

الرسالة
يعتمد إطار العمل على المبادئ الأساسية التالية:

· يتم إجراء تجربة واحدة من خلال مثيل واحد لبرنامج محاكاة ، سواء في
متوازي أو متسلسل.

· سيناريو التحكم ينفذ حالات من المحاكاة ، مع تغيير المعلمات حسب الضرورة.

· يتم جمع البيانات وتخزينها للتخطيط والتحليل باستخدام برامج نصية خارجية و
الأدوات الموجودة.

· يتم اتخاذ التدابير داخل النواة ns-3 من خلال ربط إطار عمل النظام الأساسي بالقائمة
تتبع الإشارات.

· يمكن استخدام إشارات التتبع أو التلاعب المباشر بالإطار لأداة مخصصة
كود المحاكاة.

هذه المكونات الأساسية لإطار العمل وتفاعلاتها موضحة في
الشكل التالي. [صورة]

مثال
يمر هذا القسم بعملية إنشاء تجربة في إطار العمل و
إنتاج البيانات للتحليل (الرسوم البيانية) منه ، وإظهار البنية وواجهة برمجة التطبيقات على طول
الطريقة.

سؤال
'' ما هو الأداء (المحاكى) لأجهزة WiFi NetDevices الخاصة بـ ns-3 (باستخدام الإعداد الافتراضي
إعدادات)؟ إلى أي مدى يمكن أن تكون العقد اللاسلكية متباعدة في محاكاة قبل أن لا تستطيع ذلك
التواصل بشكل موثوق؟ "

· الفرضية: بناءً على معرفة أداء الحياة الواقعية ، يجب أن تتواصل العقد
جيد بشكل معقول إلى مسافة 100 متر على الأقل. لا ينبغي أن تكون الاتصالات التي تتجاوز 200 متر
قابليه.

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

محاكاة البرنامج
أول شيء يجب القيام به في تنفيذ هذه التجربة هو تطوير المحاكاة
برنامج. يمكن العثور على رمز هذا المثال في أمثلة / إحصائيات / wifi-example-sim.cc.
يقوم بالخطوات الرئيسية التالية.

· إعلان المعلمات وتحليل سطر الأوامر باستخدام ns3 :: CommandLine.

مسافة مزدوجة = 50.0 ؛
تنسيق السلسلة ("OMNet ++") ؛
تجربة السلسلة ("wifi-Distance-test") ؛
استراتيجية السلسلة ("wifi-default") ؛
سلسلة runID ؛

CommandLine كمد ؛
cmd.AddValue ("المسافة" ، "المسافة المتباعدة لوضع العقد (بالأمتار)." ، المسافة) ؛
cmd.AddValue ("تنسيق" ، "تنسيق لاستخدامه لإخراج البيانات." ، تنسيق) ؛
cmd.AddValue ("تجربة" ، "معرف للتجربة" ، تجربة) ؛
cmd.AddValue ("استراتيجية" ، "معرف للاستراتيجية" ، استراتيجية) ؛
cmd.AddValue ("تشغيل" ، "معرف للتشغيل." ، runID) ؛
cmd ، Parse (argc ، argv) ؛

· إنشاء العقد وشبكات الأكوام باستخدام ns3 :: NodeContainer, ns3 :: WiFiHelperو
ns3 :: InternetStackHelper.

عقد NodeContainer
العقد(2)

WifiHelper wifi ؛
wifi.SetMac ("ns3 :: AdhocWifiMac") ؛
wifi.SetPhy ("ns3 :: WifiPhy") ؛
NetDeviceContainer nodeDevices = wifi.Install (العقد) ؛

إنترنت InternetStackHelper ؛
internet.Install (العقد) ؛
IPv4AddressHelper ipAddrs ؛
ipAddrs.SetBase ("192.168.0.0"، "255.255.255.0") ؛
ipAddrs.Assign (nodeDevices) ؛

· تحديد المواقع باستخدام العقد ns3 :: MobilityHelper. بشكل افتراضي ، تكون العقد ثابتة
التنقل ولن يتحرك ، ولكن يجب وضعه على مسافة معينة. هناك
عدة طرق للقيام بذلك ؛ يتم ذلك باستخدام ns3 :: ListPositionAllocatorالذي يرسم
مواقف من قائمة معينة.

التنقل
Ptr positionAlloc =
إنشاء كائن () ؛
positionAlloc-> Add (Vector (0.0، 0.0، 0.0)) ؛
positionAlloc-> Add (Vector (0.0، مسافة، 0.0)) ؛
mobility.SetPositionAllocator (positionAlloc) ؛
Mobility.Install (العقد) ؛

· تركيب مولد مرور وحوض مرور. المخزون التطبيقات يمكن أن يكون
مستخدم ، لكن المثال يتضمن كائنات مخصصة بتنسيق تطبيقات src / test / test02 (cc | h). هؤلاء
لها سلوك بسيط ، وتوليد عدد معين من الحزم متباعدة في فترة زمنية معينة.
نظرًا لوجود واحد فقط من كل منهم يتم تثبيته يدويًا ؛ لمجموعة أكبر
ns3 :: ApplicationHelper يمكن استخدام الطبقة. علق خارج التكوين :: مجموعة يتغير الخط
وجهة الحزم ، مضبوطة على البث افتراضيًا في هذا المثال. لاحظ أن
بشكل عام ، قد يكون لشبكة WiFi أداء مختلف للبث والإطارات الأحادية بسبب
سياسات مختلفة للتحكم في الأسعار وإعادة إرسال MAC.

Ptr appSource = NodeList ::GetNode(0)
Ptr المرسل = CreateObject () ؛
appSource-> AddApplication (المرسل) ؛
المرسل-> ابدأ (ثانية(1)) ؛

Ptr appSink = NodeList ::GetNode(1)
Ptr المتلقي = CreateObject () ؛
appSink-> AddApplication (المتلقي) ؛
المتلقي-> ابدأ (ثانية(0)) ؛

// Config :: Set ("/ NodeList / * / ApplicationList / * / $ Sender / Destination" ،
// Ipv4AddressValue ("192.168.0.2")) ؛

· تكوين البيانات والإحصاءات التي سيتم جمعها. النموذج الأساسي هو أن
ns3 :: DataCollector يتم إنشاء كائن للاحتفاظ بمعلومات حول هذا التشغيل المعين ، إلى
التي يتم إرفاق المراقبون والآلات الحاسبة لتوليد البيانات فعليًا. الأهم ،
تتضمن معلومات التشغيل تسميات "التجربة" و "الإستراتيجية" و "الإدخال" و
''يجري''. تُستخدم هذه لتحديد البيانات في وقت لاحق وتجميعها بسهولة من تجارب متعددة.

· التجربة هي الدراسة التي تنتمي إليها هذه التجربة. ها هو على شبكة WiFi
الأداء والمسافة.

· الإستراتيجية هي الكود أو المعلمات التي يتم فحصها في هذه التجربة. في هذا المثال
تم إصلاحه ، لكن الامتداد الواضح سيكون التحقيق في بت WiFi مختلف
معدلات ، كل منها سيكون استراتيجية مختلفة.

· المدخلات هي المشكلة الخاصة التي أعطيت لهذه التجربة. هنا هو ببساطة ملف
المسافة بين العقدتين.

إن معرّف runID هو معرّف فريد لهذه التجربة التي تُوسم معلوماتها
لتحديدها في التحليل اللاحق. إذا لم يتم إعطاء معرف التشغيل ، فإن المثال يجعل البرنامج
معرف تشغيل (ضعيف) باستخدام الوقت الحالي.

هذه الأجزاء الأربعة من البيانات الوصفية مطلوبة ، ولكن قد يكون مطلوبًا المزيد. يمكن إضافتها
إلى السجل باستخدام ns3 :: DataCollector :: AddMetadata () الأسلوب.

بيانات جامع البيانات ؛
data.DescribeRun (تجربة ، استراتيجية ، إدخال ، runID) ؛
data.AddMetadata ("المؤلف" ، "tjkopena") ؛

المراقبة الفعلية والحساب يتم بواسطة ns3 :: DataCalculator الأشياء ، منها
توجد عدة أنواع مختلفة. يتم إنشاؤها بواسطة برنامج المحاكاة ، المرفق
الإبلاغ أو رمز أخذ العينات ، ومن ثم التسجيل في ns3 :: DataCollector لذلك سيفعلون
يتم الاستفسار عنها لاحقًا عن ناتجها. إحدى آليات المراقبة السهلة هي استخدام الموجودة
تتبع المصادر ، على سبيل المثال إلى كائنات الأجهزة في النواة ns-3 دون تغيير
شفرة. هنا يتم توصيل العداد مباشرة بإشارة تتبع في طبقة WiFi MAC
العقدة الهدف.

Ptr totalRx = CreateObject () ؛
totalRx-> SetKey ("wifi-rx-Frames") ؛
التكوين :: الاتصال ("/ NodeList / 1 / DeviceList / * / $ ns3 :: WifiNetDevice / Rx" ،
MakeCallback (& ​​PacketCounterCalculator :: FrameUpdate ، totalRx)) ؛
data.AddDataCalculator (totalRx) ،

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

Ptr > appRx = CreateObject > () ؛
appRx-> SetKey ("Receiver-rx-packets") ؛
المتلقي-> SetCounter (appRx) ؛
data.AddDataCalculator (appRx) ،

لزيادة العدد ، يستدعي كود معالجة الحزمة الخاص بالوعة أحد
طرق تحديث الآلة الحاسبة.

m_calc-> تحديث () ؛

يتضمن البرنامج العديد من الأمثلة الأخرى أيضًا ، باستخدام كلٍّ من البدائيين
الآلات الحاسبة مثل ns3 :: CounterCalculator وتلك التي تم تكييفها لمراقبة الحزم و
مرات. في تطبيقات src / test / test02 (cc | h) كما أنه ينشئ علامة مخصصة بسيطة تستخدمها
لتتبع التأخير من طرف إلى طرف للحزم التي تم إنشاؤها ، وإبلاغ النتائج إلى ملف
ns3 :: TimeMinMaxAvgTotalCalculator حاسبة البيانات.

· تشغيل المحاكاة ، والتي تكون مباشرة جدًا بمجرد إنشائها.

محاكي :: تشغيل () ؛

· توليد إما OMNet ++ or سكليتي الإخراج ، اعتمادًا على وسيطات سطر الأوامر. ل
افعل هذا أ ns3 :: DataOutputInterface يتم إنشاء الكائن وتكوينه. النوع المحدد
من هذا سيحدد تنسيق الإخراج. ثم يتم إعطاء هذا الكائن
ns3 :: DataCollector الشيء الذي يستجوبه لإنتاج الإخراج.

Ptr انتاج؛
إذا (التنسيق == "OMNet ++") {
NS_LOG_INFO ("إنشاء إخراج بيانات منسق OMNet ++.") ؛
الإخراج = CreateObject () ؛
{} آخر
# ifdef STAT_USE_DB
NS_LOG_INFO ("إنشاء إخراج بيانات منسق SQLite.") ؛
الإخراج = CreateObject () ؛
# إنهاء إذا
}

الإخراج-> الإخراج (البيانات) ؛

· تحرير الذاكرة التي تستخدمها المحاكاة. يجب أن يأتي هذا في نهاية الرئيسي
وظيفة على سبيل المثال.

جهاز محاكاة :: تدمير () ؛

تسجيل
لمعرفة ما يفعله المثال البرنامج والتطبيقات وإطار العمل الأساسي بالتفصيل ، قم بتعيين
هيه NS_LOG متغير بشكل مناسب. سيوفر ما يلي مخرجات وفيرة من الجميع
ثلاثة.

تصدير $ NS_LOG = تجربة WiFiDistance: WiFiDistanceApps

لاحظ أن هذا يبطئ المحاكاة بشكل غير عادي.

عينة الناتج
سيتم إلحاق تجميع برنامج الاختبار وتشغيله ببساطة OMNet ++ إخراج منسق مثل
ما يلي data.sca.

تشغيل run-1212239121

تجربة Attr "wifi-Distance-test"
استراتيجية Attr "wifi-default"
إدخال attr "50"
وصف Attr ""

attr "مؤلف" "tjkopena"

عدد إطارات wifi-tx عدد 30
عدد إطارات wifi-rx عدد 30
عدد حزم مرسل tx عددي 30
عدد حزم المستقبل- rx- عدد 30
العدد الحجمي لـ tx-pkt-size 30
إجمالي حجم tx-pkt الحجمي 1920
متوسط ​​حجم tx-pkt العددي 64
عددية tx-pkt-size بحد أقصى 64
العددية tx-pkt-size min 64
عدد التأخير العددي 30
مجموع التأخير القياسي 5884980ns
متوسط ​​التأخير القياسي 196166ns
تأخير عددي بحد أقصى 196166ns
تأخير عددي دقيقة 196166ns

مراقبة سيناريو
من أجل أتمتة جمع البيانات في مجموعة متنوعة من المدخلات (المسافات) ، بسيطة Bash
يستخدم البرنامج النصي لتنفيذ سلسلة من عمليات المحاكاة. يمكن العثور عليها في
أمثلة / إحصائيات / wifi-example-db.sh. من المفترض أن يتم تشغيل البرنامج النصي من ملف أمثلة / احصائيات /
الدليل.

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

#!/ بن / ش

المسافات = "25 50 75"
المحاكمات = "1 2 3 4 5"

مثال على تجربة صدى WiFi

إذا [-e data.db]
then
صدى قتل data.db؟
قراءة ANS
إذا ["$ ANS" = "نعم" -o "$ ANS" = "y"]
then
صدى حذف قاعدة البيانات
rm data.db
fi
fi

للمحاكمة في $ TRIALS
do
للمسافة في $ DISTANCES
do
echo Trial $ trial، مسافة $ مسافة
./bin/test02 - الشكل = ديسيبل - المسافة = المسافة بالدولار - المدى = المدى- المسافة بالدولار- التجربة بالدولار
فعل
فعل

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

CMD = "حدد exp.input ، متوسط ​​(100 - ((rx.value * 100) /tx.value)) \
من Singletons rx و Singletons tx و Experiments exp \
حيث rx.run = tx.run AND \
rx.run = exp.run و \
rx.name = 'Receiver-rx-packets' AND \
tx.name = 'sender-tx-packets' \
تجميع حسب exp.input \
ترتيب حسب القيمة المطلقة (exp.input) ASC ؛ "

sqlite3 -noheader data.db "$ CMD"> wifi-default.data
sed -i "s / | / /" wifi-default.data
gnuplot wifi-example.gnuplot

تم العثور على نص GNUPlot في أمثلة / إحصائيات / wifi-example.gnuplot يحدد ببساطة الإخراج
وبعض التنسيقات الأساسية للرسم البياني.

تعيين صورة تذييل المحطة الطرفية lw 2 "Helvetica" 14

ضبط الحجم 1.0 ، 0.66

# ------------------------------------------------- ------
حدد "wifi-default.eps"
#set title "فقد الحزمة على المسافة"
تعيين xlabel "مسافة (م) --- متوسط ​​5 تجارب لكل نقطة"
ضبط xrange [0: 200]
تعيين ylabel "٪ فقدان الحزمة"
تعيين yrange [0: 110]

رسم "wifi-default.data" بعنوان السطور "WiFi Defaults"

النهاية نتيجة
لا يقدم الرسم البياني الناتج أي دليل على أداء نموذج WiFi الافتراضي
غير معقول بالضرورة ويضفي بعض الثقة على إخلاص رمزي على الأقل لـ
الواقع. الأهم من ذلك ، أن هذا التحقيق البسيط قد تم تنفيذه على طول الطريق
باستخدام الإطار الإحصائي. نجاح! [صورة]

في الوقت الحالى
NS-3 تم تصميمه للاندماج في بيئات الاختبار والآلات الافتراضية. ل
تتكامل مع حزم الشبكة الحقيقية وتنبعث / تستهلك الحزم ، وهو برنامج جدولة في الوقت الفعلي
هناك حاجة لمحاولة قفل ساعة المحاكاة بساعة الجهاز. نصف هنا أ
مكون من هذا: جدولة RealTime.

الغرض من جدولة الوقت الحقيقي هو التسبب في تقدم ساعة المحاكاة
تحدث بشكل متزامن فيما يتعلق ببعض القواعد الزمنية الخارجية. بدون حضور
قاعدة زمنية خارجية (ساعة حائط) ، يقفز وقت المحاكاة على الفور من ساعة مقلدة
من الوقت إلى اليوم التالي.

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

عند الانتهاء من تنفيذ حدث ما ، وينتقل المجدول إلى الحدث التالي ، فإن ملف
يقارن المجدول وقت تنفيذ الحدث التالي بساعة الجهاز. إذا كان التالي
تم جدولة الحدث في وقت لاحق ، ينام المحاكي حتى يتم الوصول إلى ذلك الوقت الحقيقي
ثم ينفذ الحدث التالي.

قد يحدث أنه بسبب المعالجة المتأصلة في تنفيذ أحداث المحاكاة ،
أن جهاز المحاكاة لا يمكنه مواكبة الوقت الفعلي. في مثل هذه الحالة ، الأمر متروك للمستخدم
التكوين ما يجب القيام به. هناك اثنان NS-3 الصفات التي تحكم السلوك. ال
الاول هو ns3 :: RealTimeSimulatorImpl :: SynchronizationMode. المدخلان ممكنان ل
هذه السمة أفضل مجهود (الافتراضي) أو هارد ليميت. في وضع "BestEffort" ، فإن ملف
سيحاول المحاكي فقط اللحاق بالوقت الفعلي من خلال تنفيذ الأحداث حتى يصل إلى مستوى
نقطة حيث يكون الحدث التالي في المستقبل (الحقيقي) ، وإلا تنتهي المحاكاة. في
وضع BestEffort ، إذن ، من الممكن أن تستهلك المحاكاة وقتًا أطول من
وقت ساعة الحائط. الخيار الآخر "HardLimit" سيؤدي إلى إحباط المحاكاة إذا كان ملف
تم تجاوز عتبة التسامح. هذه السمة ns3 :: RealTimeSimulatorImpl :: HardLimit
والافتراضي 0.1 ثانية.

طريقة مختلفة للعملية هي التي يكون فيها وقت المحاكاة ليس مجمدة خلال حدث
تنفيذ. تم تنفيذ وضع المحاكاة في الوقت الفعلي هذا ولكن تمت إزالته من ملف NS-3 شجرة
بسبب الأسئلة حول ما إذا كان سيكون مفيدًا. إذا كان المستخدمون مهتمين بالوقت الحقيقي
المحاكي الذي لا يتجمد فيه وقت المحاكاة أثناء تنفيذ الحدث (على سبيل المثال ، كل
دعوة ل محاكي :: الآن () يعرض وقت ساعة الحائط الحالي ، وليس الوقت الذي يتم فيه
بدأ تنفيذ الحدث) ، يرجى الاتصال بالقائمة البريدية لمطوري ns.

الأستعمال
يعد استخدام جهاز محاكاة الوقت الفعلي أمرًا سهلاً من منظور البرمجة النصية.
يحتاج المستخدمون فقط إلى تعيين السمة نوع تنفيذ المحاكاة في الوقت الحقيقي
جهاز محاكاة ، مثل ما يلي:

GlobalValue :: Bind ("SimulatorImplementationType"،
StringValue ("ns3 :: RealtimeSimulatorImpl"))؛

هناك نص في أمثلة / الوقت الحقيقي / realtime-udp-echo.cc هذا مثال على كيفية
تكوين السلوك في الوقت الفعلي. يحاول:

$ ./waf - تشغيل الصدى في الوقت الفعلي

ما إذا كان المحاكي سيعمل بأفضل جهد أو يتم التحكم بطريقة سياسة الحد الصعب
بالسمات الموضحة في القسم السابق.

تطبيق
التنفيذ وارد في الملفات التالية:

· src / core / model / realtime-simulator-impl. {cc، h}

· src / core / model / wall-clock-synizer. {cc، h}

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

المساعدون
قدمت لك الفصول أعلاه العديد من الأشياء NS-3 مفاهيم البرمجة مثل الذكية
مؤشرات لإدارة الذاكرة ، السمات ، مساحات الأسماء ، عمليات الاسترجاعات ، الخ.
يمكن للمستخدمين الذين يعملون في واجهة برمجة التطبيقات منخفضة المستوى الاتصال ببعضهم البعض NS-3 الأشياء ذات الحبيبات الدقيقة.
ومع ذلك ، فإن برنامج المحاكاة المكتوب بالكامل باستخدام واجهة برمجة التطبيقات منخفضة المستوى سيكون طويلًا جدًا
ومملة للتعليمات البرمجية. لهذا السبب ، تمت إضافة ما يسمى بـ "واجهة برمجة التطبيقات المساعدة" المنفصلة
في الصميم NS-3 API. إذا كنت قد قرأت NS-3 البرنامج التعليمي ، ستكون مألوفًا بالفعل
باستخدام المساعد API ، نظرًا لأنها واجهة برمجة التطبيقات التي يتم تقديم المستخدمين الجدد إليها أولاً.
في هذا الفصل ، نقدم فلسفة تصميم واجهة برمجة التطبيقات المساعدة ونقابلها
واجهة برمجة التطبيقات ذات المستوى المنخفض. إذا أصبحت مستخدمًا كثيفًا لـ NS-3، من المحتمل أن تتحرك ذهابًا وإيابًا
بين واجهات برمجة التطبيقات هذه حتى في نفس البرنامج.

تحتوي واجهة برمجة التطبيقات المساعدة على بعض الأهداف:

1. بقية SRC / ليس له أي تبعيات على المساعد API ؛ أي شيء يمكن القيام به
يمكن تشفير API المساعد أيضًا في واجهة برمجة التطبيقات منخفضة المستوى

2. حاويات: غالبًا ما تحتاج عمليات المحاكاة إلى القيام بعدد من الإجراءات المتطابقة للمجموعات
من الأشياء. يستخدم المساعد API بشكل مكثف حاويات الأشياء المماثلة التي
يمكن إجراء عمليات مماثلة أو متطابقة.

3. API المساعد ليس عامًا ؛ لا تسعى جاهدة لتعظيم إعادة استخدام التعليمات البرمجية. لذا،
بنيات البرمجة مثل تعدد الأشكال والقوالب التي تحقق إعادة استخدام الكود هي
ليس سائدًا. على سبيل المثال ، هناك مساعدين منفصلين لـ CsmaNetDevice و
مساعدي PointToPointNetDevice لكنهم لا ينحدرون من قاعدة NetDevice مشتركة
فئة.

4. تعمل واجهة برمجة التطبيقات المساعدة عادةً مع الكائنات المخصصة للمكدس (مقابل كومة مخصصة). ل
بعض البرامج ، NS-3 قد لا يحتاج المستخدمون إلى القلق بشأن أي مستوى منخفض من إنشاء أو إنشاء كائن
التعامل مع Ptr يمكنهم التعامل مع حاويات الأشياء والمساعدين المخصصين للمكدس
التي تعمل عليها.

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

القيام ب المؤامرات استخدام هيه غنوبلوت مبوبة
هناك طريقتان شائعتان لعمل قطعة أرض باستخدام NS-3 و gnuplot (-
http://www.gnuplot.info):

1. قم بإنشاء ملف تحكم gnuplot باستخدام NS-3فئة Gnuplot.

2. قم بإنشاء ملف بيانات gnuplot باستخدام القيم التي تم إنشاؤها بواسطة NS-3.

يدور هذا القسم حول الطريقة الأولى ، أي أنه يدور حول كيفية عمل قطعة أرض باستخدام NS-3Gnuplot
فصل. إذا كنت مهتمًا بالطريقة الثانية ، فراجع القسم الفرعي "مثال حقيقي" ضمن
قسم "البحث عن المفقودين" في NS-3 البرنامج التعليمي.

خلق المؤامرات باستخدام هيه غنوبلوت مبوبة
يجب اتخاذ الخطوات التالية من أجل إنشاء قطعة أرض باستخدام NS-3فئة Gnuplot:

1. قم بتعديل الكود الخاص بك بحيث يستخدم فئة Gnuplot ووظائفها.

2. قم بتشغيل التعليمات البرمجية الخاصة بك بحيث تنشئ ملف تحكم gnuplot.

3. استدعاء gnuplot باسم ملف التحكم gnuplot.

4. اعرض ملف الرسومات الذي تم إنتاجه في عارض الرسومات المفضل لديك.

راجع الكود من أمثلة المخططات التي تمت مناقشتها أدناه للحصول على تفاصيل حول الخطوة 1.

An مثال البرنامج أن استخدام هيه غنوبلوت مبوبة
مثال على برنامج يستخدم NS-3يمكن العثور على فئة Gnuplot الخاصة بـ Gnuplot هنا:

src / stats / أمثلة / gnuplot-example.cc

لتشغيل هذا المثال ، قم بما يلي:

$ ./waf شل
$ cd build / debug / src / stats / أمثلة
$ ./gnuplot-example

يجب أن ينتج عن هذا ملفات التحكم gnuplot التالية في الدليل حيث يكون المثال
يقع:

مؤامرة 2d.plt
مؤامرة 2d مع أشرطة الخطأ .plt
مؤامرة 3d.plt

من أجل معالجة ملفات تحكم gnuplot هذه ، قم بما يلي:

$ gnuplot مؤامرة 2d.plt
$ gnuplot plot-2d-with-error-Bars.plt
$ gnuplot مؤامرة 3d.plt

يجب أن ينتج هذا ملفات الرسومات التالية في الدليل حيث يوجد المثال
تقع:

مؤامرة 2d.png
مؤامرة-2d-مع-خطأ-bars.png
مؤامرة 3d.png

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

$ الأعرج مؤامرة-2d.png
$ gimpplot-2d-with-error-bars.png
$ الأعرج مؤامرة-3d.png

An مثال 2 الأبعاد قطعة
المؤامرة ثنائية الأبعاد التالية
[صورة]

تم إنشاؤه باستخدام الكود التالي من gnuplot-example.cc:

باستخدام مساحة الاسم الأمراض المنقولة جنسيا.

سلسلة fileNameWithNoExtension = "plot-2d" ؛
string graphicsFileName = fileNameWithNoExtension + ".png" ؛
سلسلة plotFileName = fileNameWithNoExtension + ".plt" ؛
سلسلة plotTitle = "مؤامرة ثنائية الأبعاد" ؛
سلسلة dataTitle = "بيانات ثنائية الأبعاد" ؛

// إنشاء المؤامرة وتعيين عنوانها.
مؤامرة Gnuplot (graphicsFileName) ؛
مؤامرة. SetTitle (plotTitle) ؛

// اصنع ملف الرسومات ، الذي سينشئه ملف الرسم عندما يكون
// يستخدم مع Gnuplot ، يكون ملف PNG.
plot.SetTerminal ("png") ؛

// تعيين التسميات لكل محور.
plot.SetLegend ("X Values"، "Y Values")؛

// اضبط النطاق للمحور x.
plot.AppendExtra ("set xrange [-6: +6]")؛

// قم بإنشاء مجموعة البيانات ، وحدد عنوانها ، واجعل النقاط كما هي
// تآمر مع خطوط التوصيل.
مجموعة بيانات Gnuplot2d
مجموعة البيانات. SetTitle (dataTitle) ؛
dataset.SetStyle (Gnuplot2dDataset :: LINES_POINTS) ،

مزدوج x ؛
ص مزدوج

// أنشئ مجموعة بيانات ثنائية الأبعاد.
لـ (س = -5.0 ؛ س <= +5.0 ؛ س + = 1.0)
{
// احسب منحنى 2-D
//
/ / 2
// y = x.
//
ص = س * س ؛

// أضف هذه النقطة.
إضافة (س ، ص) ؛
}

// أضف مجموعة البيانات إلى المؤامرة.
مؤامرة. AddDataset (مجموعة البيانات) ؛

// افتح ملف الرسم.
ofstream plotFile (plotFileName.c_str ()) ،

// اكتب ملف الرسم.
مؤامرة. GenerateOutput (plotFile) ؛

// أغلق ملف الرسم.
plotFile.close () ،

An مثال 2 الأبعاد قطعة مع خطأ الاعمدة
الرسم ثنائي الأبعاد التالي مع أشرطة الخطأ في الاتجاهين x و y
[صورة]

تم إنشاؤه باستخدام الكود التالي من gnuplot-example.cc:

باستخدام مساحة الاسم الأمراض المنقولة جنسيا.

string fileNameWithNoExtension = "plot-2d-with-error-bars"؛
string graphicsFileName = fileNameWithNoExtension + ".png" ؛
سلسلة plotFileName = fileNameWithNoExtension + ".plt" ؛
سلسلة plotTitle = "مؤامرة ثنائية الأبعاد بأشرطة خطأ"؛
string dataTitle = "بيانات ثنائية الأبعاد بأشرطة خطأ"؛

// إنشاء المؤامرة وتعيين عنوانها.
مؤامرة Gnuplot (graphicsFileName) ؛
مؤامرة. SetTitle (plotTitle) ؛

// اصنع ملف الرسومات ، الذي سينشئه ملف الرسم عندما يكون
// يستخدم مع Gnuplot ، يكون ملف PNG.
plot.SetTerminal ("png") ؛

// تعيين التسميات لكل محور.
plot.SetLegend ("X Values"، "Y Values")؛

// اضبط النطاق للمحور x.
plot.AppendExtra ("set xrange [-6: +6]")؛

// قم بإنشاء مجموعة البيانات ، وحدد عنوانها ، واجعل النقاط كما هي
// مؤامرة بدون خطوط متصلة.
مجموعة بيانات Gnuplot2d
مجموعة البيانات. SetTitle (dataTitle) ؛
dataset.SetStyle (Gnuplot2dDataset :: POINTS) ؛

// اجعل مجموعة البيانات بها أشرطة خطأ في كلا الاتجاهين x و y.
dataset.SetErrorBars (Gnuplot2dDataset :: XY) ،

مزدوج x ؛
xErrorDelta مزدوج ؛
ص مزدوج
ضعف yErrorDelta ؛

// أنشئ مجموعة بيانات ثنائية الأبعاد.
لـ (س = -5.0 ؛ س <= +5.0 ؛ س + = 1.0)
{
// احسب منحنى 2-D
//
/ / 2
// y = x.
//
ص = س * س ؛

// اجعل عدم اليقين في اتجاه x ثابتًا وصنعه
// يكون عدم اليقين في الاتجاه y جزءًا ثابتًا من
// قيمة y.
xErrorDelta = 0.25 ؛
yErrorDelta = 0.1 * ص ؛

// أضف هذه النقطة مع عدم اليقين في كل من x و y
// اتجاه.
dataset.Add (x، y، xErrorDelta، yErrorDelta) ؛
}

// أضف مجموعة البيانات إلى المؤامرة.
مؤامرة. AddDataset (مجموعة البيانات) ؛

// افتح ملف الرسم.
ofstream plotFile (plotFileName.c_str ()) ،

// اكتب ملف الرسم.
مؤامرة. GenerateOutput (plotFile) ؛

// أغلق ملف الرسم.
plotFile.close () ،

An مثال 3 الأبعاد قطعة
المؤامرة ثنائية الأبعاد التالية
[صورة]

تم إنشاؤه باستخدام الكود التالي من gnuplot-example.cc:

باستخدام مساحة الاسم الأمراض المنقولة جنسيا.

سلسلة fileNameWithNoExtension = "plot-3d" ؛
string graphicsFileName = fileNameWithNoExtension + ".png" ؛
سلسلة plotFileName = fileNameWithNoExtension + ".plt" ؛
سلسلة plotTitle = "مؤامرة ثنائية الأبعاد" ؛
سلسلة dataTitle = "بيانات ثنائية الأبعاد" ؛

// إنشاء المؤامرة وتعيين عنوانها.
مؤامرة Gnuplot (graphicsFileName) ؛
مؤامرة. SetTitle (plotTitle) ؛

// اصنع ملف الرسومات ، الذي سينشئه ملف الرسم عندما يكون
// يستخدم مع Gnuplot ، يكون ملف PNG.
plot.SetTerminal ("png") ؛

// قم بتدوير المؤامرة 30 درجة حول المحور x ثم قم بتدوير
// ارسم 120 درجة حول المحور z الجديد.
plot.AppendExtra ("ضبط العرض 30 ، 120 ، 1.0 ، 1.0") ؛

// اجعل الصفر للمحور z في مستوى المحور x والمحور y.
plot.AppendExtra ("تعيين ticslevel 0") ؛

// تعيين التسميات لكل محور.
plot.AppendExtra ("تعيين xlabel 'X Values'")؛
plot.AppendExtra ("تعيين ylabel 'Y Values'")؛
plot.AppendExtra ("تعيين قيم zlabel 'Z'")؛

// اضبط نطاقات المحورين x و y.
plot.AppendExtra ("set xrange [-5: +5]")؛
plot.AppendExtra ("تعيين yrange [-5: +5]")؛

// قم بإنشاء مجموعة البيانات ، وحدد عنوانها ، واجعل النقاط كما هي
// متصل بخطوط.
مجموعة بيانات Gnuplot3d
مجموعة البيانات. SetTitle (dataTitle) ؛
dataset.SetStyle ("مع خطوط") ؛

مزدوج x ؛
ص مزدوج
ض مزدوج

// أنشئ مجموعة بيانات ثنائية الأبعاد.
لـ (س = -5.0 ؛ س <= +5.0 ؛ س + = 1.0)
{
لـ (ص = -5.0 ؛ ص <= +5.0 ؛ ص + = 1.0)
{
// احسب السطح ثلاثي الأبعاد
//
// 2 2
// z = x * y.
//
ض = س * س * ص * ص ؛

// أضف هذه النقطة.
إضافة (س ، ص ، ض) ؛
}

// السطر الفارغ ضروري في نهاية كل بيانات قيمة x
// نقاط للشبكة السطحية ثلاثية الأبعاد للعمل.
dataset.AddEmptyLine () ،
}

// أضف مجموعة البيانات إلى المؤامرة.
مؤامرة. AddDataset (مجموعة البيانات) ؛

// افتح ملف الرسم.
ofstream plotFile (plotFileName.c_str ()) ،

// اكتب ملف الرسم.
مؤامرة. GenerateOutput (plotFile) ؛

// أغلق ملف الرسم.
plotFile.close () ،

باستخدام Python إلى يجري NS-3
تسمح روابط Python باستخدام كود C ++ بتنسيق NS-3 ليتم استدعاؤها من Python.

يوضح لك هذا الفصل كيفية إنشاء برنامج نصي بايثون يمكن تشغيله NS-3 وأيضا
عملية إنشاء روابط Python لـ C ++ NS-3 وحدة.

المُقدّمة
الهدف من ارتباطات Python لـ NS-3 شقان:

1. اسمح للمبرمج بكتابة نصوص محاكاة كاملة بلغة Python (-
http://www.python.org);

2. نماذج أولية جديدة (مثل بروتوكولات التوجيه).

في الوقت الحالي ، يكون التركيز الأساسي للارتباطات هو الهدف الأول ، ولكن الهدف الثاني
الهدف سيتم دعمه في النهاية أيضًا. ارتباطات Python لـ NS-3 يجري تطويرها
باستخدام أداة جديدة تسمى PyBindGen (http://code.google.com/p/pybindgen).

An مثال Python سيناريو أن أشواط NS-3
إليك بعض الأمثلة على التعليمات البرمجية المكتوبة بلغة Python والتي تعمل NS-3الذي هو مكتوب
في C ++. يمكن العثور على مثال Python هذا في أمثلة / تعليمي / first.py:

استيراد تطبيقات ns.
استيراد ns.core
استيراد ns.internet
استيراد ns.network
استيراد ns.point_to_point

ns.core.LogComponentEnable ("UdpEchoClientApplication" ، ns.core.LOG_LEVEL_INFO)
ns.core.LogComponentEnable ("UdpEchoServerApplication"، ns.core.LOG_LEVEL_INFO)

العقد = ns.network.NodeContainer ()
العقد(2)

pointToPoint = ns.point_to_point.PointToPointHelper ()
pointToPoint.SetDeviceAttribute ("DataRate"، ns.core.StringValue ("5Mbps"))
pointToPoint.SetChannelAttribute ("تأخير"، ns.core.StringValue ("2 مللي ثانية"))

الأجهزة = pointToPoint.Install (العقد)

المكدس = ns.internet.InternetStackHelper ()
المكدس. تثبيت (العقد)

العنوان = ns.internet.Ipv4AddressHelper ()
address.SetBase (ns.network.Ipv4Address ("10.1.1.0")، ns.network.Ipv4Mask ("255.255.255.0"))

واجهات = address.Assign (أجهزة) ؛

خادم الصدى = ns.applications.UdpEchoServerHelper(9)

serverApps = echoServer.Install (العقد(1))
serverApps.Start (ns.core.Seconds (1.0))
serverApps.Stop (ns.core.Seconds (10.0))

echoClient = ns.applications.UdpEchoClientHelper (واجهات(1) ، 9)
echoClient.SetAttribute ("MaxPackets"، ns.core.U صحيحة القيمة(1))
echoClient.SetAttribute ("Interval"، ns.core.TimeValue (ns.core.Seconds (1.0)))
echoClient.SetAttribute ("PacketSize"، ns.core.U صحيحة القيمة(1024))

clientApps = echoClient.Install (العقد(0))
clientApps.Start (ns.seconds (2.0))
clientApps.Stop (ns.core.Seconds (10.0))

ns.core.Simulator.Run ()
ns.core.Simulator.Destroy ()

الركض Python مخطوطات
يحتوي waf على بعض الخيارات التي تقوم تلقائيًا بتحديث مسار python للعثور على ns3
وحدة. لتشغيل برامج الأمثلة ، هناك طريقتان لاستخدام waf للعناية بهذا الأمر. واحد
هو تشغيل قذيفة واف. على سبيل المثال:

$ ./waf - قشرة
أمثلة على بيثون / لاسلكي / لاسلكي مختلط

والآخر هو استخدام الخيار --pyrun إلى waf:

$ ./waf - أمثلة بايرون / لاسلكي / لاسلكي مختلط

لتشغيل نص بيثون تحت مصحح الأخطاء سي:

$ ./waf - قشرة
$ gdb - أمثلة على أمثلة بيثون / لاسلكي / لاسلكي مختلط

لتشغيل نص Python الخاص بك الذي يستدعي NS-3 وهذا هو الطريق ،
/path/to/your/example/my-script.py، قم بما يلي:

$ ./waf - قشرة
$ python /path/to/your/example/my-script.py

المحاذير
ارتباطات Python لـ NS-3 هي عمل قيد التنفيذ ، وبعض القيود التي تعرفها
المطورين. بعض هذه القيود (وليس كلها) مذكورة هنا.

غير كامل تغطية
بادئ ذي بدء ، ضع في اعتبارك أنه لا يتم دعم 100٪ من واجهة برمجة التطبيقات في Python. قليلا من ال
الأسباب هي:

1. تتضمن بعض واجهات برمجة التطبيقات مؤشرات تتطلب معرفة نوع الذاكرة
تمرير دلالات (من يملك أي ذاكرة). هذه المعرفة ليست جزءًا من الوظيفة
التوقيعات ، وإما موثقة أو غير موثقة في بعض الأحيان. التعليقات التوضيحية
هناك حاجة لربط هذه الوظائف ؛

2. في بعض الأحيان يتم استخدام نوع بيانات أساسي غير معتاد أو بناء C ++ لم يتم استخدامه بعد
بدعم من PyBindGen ؛

3. لا يقوم GCC-XML بالإبلاغ عن الفئات المستندة إلى القوالب ما لم يتم إنشاء مثيل لها.

يمكن تغليف معظم واجهات برمجة التطبيقات المفقودة ، مع إعطاء الوقت الكافي ، والصبر ، والخبرة ، و
من المحتمل أن يتم تغليفها إذا تم تقديم تقارير الأخطاء. ومع ذلك ، لا تقدم تقريرًا بالخطأ
قائلا "الارتباطات غير كاملة" ، لأننا لا نملك القوى العاملة لإكمال 100٪ من
الارتباطات.

تحويل الصانعين
تحويل الصانعين لم يتم دعمها بالكامل من قبل PyBindGen ، وهي تعمل دائمًا باسم
صريح عند ترجمة API إلى Python. على سبيل المثال ، في C ++ يمكنك القيام بذلك
هذه:

IPv4AddressHelper ipAddrs ؛
ipAddrs.SetBase ("192.168.0.0"، "255.255.255.0") ؛
ipAddrs.Assign (الأجهزة الأساسية) ؛

في بايثون ، في الوقت الحالي عليك القيام بما يلي:

ipAddrs = ns3.Ipv4AddressHelper ()
ipAddrs.SetBase(ns3.Ipv4Address("192.168.0.0"), ns3.Ipv4Mask("255.255.255.0"))
ipAddrs.Assign (الأجهزة الأساسية)

سطر الأوامر
CommandLine :: AddValue () يعمل بشكل مختلف في Python عما يعمل في NS-3. في Python ، فإن ملف
المعلمة الأولى هي سلسلة تمثل اسم خيار سطر الأوامر. عندما يكون الخيار
تم تعيينه ، يتم تعيين سمة تحمل نفس اسم اسم الخيار على سطر الأوامر()
هدف. مثال:

NUM_NODES_SIDE_DEFAULT = 3

cmd = ns3.CommandLine ()

cmd.NumNodesSide = لا شيء
cmd.AddValue ("NumNodesSide" ، "رقم جانب الشبكة للعقد (إجمالي عدد العقد سيكون هذا العدد مربعًا)")

cmd ، Parse (ARGV)

[...]

إذا كان cmd.NumNodesSide لا شيء:
num_nodes_side = NUM_NODES_SIDE_DEFAULT
آخر:
num_nodes_side = int (cmd.NumNodesSide)

البحث عن المفقودين
لم يتم دعم التتبع المستند إلى رد الاتصال بشكل صحيح لبايثون ، كجديد NS-3 يحتاج API إلى
يتم توفيرها لدعم هذا.

يتم دعم كتابة ملف Pcap عبر واجهة برمجة التطبيقات العادية.

تتبع Ascii مدعوم منذ ذلك الحين NS-3.4 عبر واجهة برمجة تطبيقات C ++ العادية المترجمة إلى Python.
ومع ذلك ، يتطلب تتبع ascii إنشاء كائن ostream لتمريره إلى ascii
طرق التعقب. في Python ، تم تغليف C ++ std :: ofstream بأدنى حد للسماح به
هذا. على سبيل المثال:

ascii = ns3.ofstream ("wifi-ap.tr") # إنشاء الملف
ns3.YansWifiPhyHelper.EnableAsciiAll (ASCII)
ns3.Simulator.Run ()
ns3.Simulator.Destroy ()
ascii.close () # أغلق الملف

هناك تحذير واحد: يجب ألا تسمح بجمع كائن الملف بالقمامة أثناء NS-3
لا يزال يستخدمه. هذا يعني أنه لا يجب السماح للمتغير "ascii" بالانتقال
خارج النطاق وإلا سيتعطل البرنامج.

سيغوين تحديد
لا تعمل روابط Python على Cygwin. هذا بسبب خطأ في gccxml.

قد تفلت من العقاب عن طريق إعادة فحص تعريفات API من داخل cygwin
البيئة (./waf - مسح بايثون). ومع ذلك ، فإن الحل الأكثر احتمالا قد يكون مضطرًا إلى ذلك
سواء قمنا بتعطيل روابط python في CygWin.

إذا كنت مهتمًا حقًا بروابط Python على Windows ، فحاول البناء باستخدام mingw والأصلي
بدلا من ذلك. وإلا ، للبناء بدون روابط python ، قم بتعطيل روابط python في ملف
مرحلة التكوين:

$ ./waf تكوين - تعطيل بيثون

العمل مع Python الارتباطات
يوجد حاليًا نوعان من روابط Python بتنسيق NS-3:

1. تحتوي الروابط المتجانسة على تعريفات API لجميع الوحدات ويمكن العثور عليها في
دليل واحد ، الارتباطات / بيثون.

2. تحتوي الروابط المعيارية على تعريفات API لوحدة واحدة ويمكن العثور عليها في كل منها
الوحدة الارتباطات الدليل.

Python الارتباطات سير العمل
العملية التي يتم من خلالها معالجة ارتباطات Python هي كما يلي:

1. يستخدم المطور بشكل دوري XML-XML (http://www.gccxml.org) API على أساس مسح ضوئي
البرنامج النصي ، والذي يحفظ تعريف API الممسوح ضوئيًا كملف الارتباطات / python / ns3_module _ *. py ملفات
أو كملفات Python في كل وحدة " الارتباطات الدليل. يتم الاحتفاظ بهذه الملفات تحت
التحكم في الإصدار الرئيسي NS-3 مخزن؛

2. يقوم المطورون الآخرون باستنساخ المستودع واستخدام تعريفات API الممسوحة ضوئيًا بالفعل ؛

3. عند التكوين NS-3، سيتم تنزيل pybindgen تلقائيًا إن لم يكن بالفعل
المثبتة. مطلق سراحه NS-3 سوف تقوم كرات القطران بشحن نسخة من بيبيندجن.

إذا حدث خطأ ما في تجميع روابط Python وتريد فقط تجاهلها
والمضي قدمًا في استخدام C ++ ، يمكنك تعطيل Python باستخدام:

$ ./waf - تعطيل بيثون

تعليمات لـ معالجة جديد ملفات or تغير في API
لذلك كنت قد تغيرت القائمة NS-3 لم تعد روابط API و Python تتراكم؟ يفعل
لا تيأس ، يمكنك إعادة فحص الروابط لإنشاء روابط جديدة تعكس التغييرات
إلى NS-3 API.

اعتمادًا على ما إذا كنت تستخدم روابط متجانسة أو معيارية ، راجع المناقشات أدناه لـ
تعلم كيفية إعادة فحص روابط Python الخاصة بك.

متكشف عن وحدة متراصة Python الارتباطات
مسح هيه متكشف عن وحدة متراصة Python الارتباطات
لمسح روابط Python المتجانسة ، قم بما يلي:

$ ./waf - مسح بايثون

منظمة of هيه متكشف عن وحدة متراصة Python الارتباطات
يتم تنظيم تعريفات Python API المتجانسة على النحو التالي. لكل NS-3 وحدة
، الملف الارتباطات / بيثون / ns3_module_ .السنة التحضيرية يصف API الخاص به. كل من هؤلاء
تحتوي الملفات على 3 وظائف المستوى الأعلى:

1. صفر أنواع التسجيل(وحدة)(): هذه الوظيفة تهتم بتسجيل أنواع جديدة (على سبيل المثال
فئات C ++ ، التعدادات) التي تم تعريفها في الوحدة النمطية ؛

2. صفر أساليب_التسجيل(وحدة)(): هذه الوظيفة تستدعي ، لكل فئة ، آخر
وظيفة register_methods_Ns3 (وحدة). هذه الوظائف الأخيرة تضيف طريقة
تعريفات لكل فئة ؛

3. صفر وظائف التسجيل(وحدة)(): هذه الوظيفة تسجل NS-3 الوظائف التي تنتمي إليها
تلك الوحدة.

وحدات Python الارتباطات
نظرة عامة
منذ ns 3.11 ، تتم إضافة الارتباطات المعيارية ، بالتوازي مع المتجانسة القديمة
الارتباطات.

يتم إنشاء روابط python الجديدة في مساحة اسم 'ns' ، بدلاً من 'ns3' للقديم
الارتباطات. مثال:

من عقدة استيراد ns.network
n1 = عقدة ()

مع روابط بايثون المعيارية:

1. توجد وحدة تمديد Python منفصلة لكل منها NS-3 وحدة؛

2. مسح تعريفات API (apidefs) يتم على أساس ns- وحدة.

3. يتم تخزين ملفات apidefs الخاصة بكل وحدة في دليل فرعي "روابط" للوحدة
دليل.

مسح هيه وحدات Python الارتباطات
لمسح روابط Python المعيارية للوحدة الأساسية ، على سبيل المثال ، قم بما يلي:

$ ./waf --apiscan = core

لفحص روابط Python المعيارية لجميع الوحدات النمطية ، قم بما يلي:

$ ./waf --apiscan = الكل

خلق a جديد وحدة
إذا كنت تضيف وحدة نمطية جديدة ، فستستمر روابط Python في التجميع ولكنها لن تفعل ذلك
تغطية الوحدة الجديدة.

لتغطية وحدة جديدة ، يجب عليك إنشاء ملف الارتباطات / بيثون / ns3_module_ .السنة التحضيرية ملف،
على غرار ما ورد في الأقسام السابقة ، وتسجيله في المتغير
LOCAL_MODULES () in الارتباطات / python / ns3modulegen.py

إضافة وحدات الارتباطات إلى A موجود وحدة
لإضافة دعم الارتباطات المعيارية إلى ملف NS-3 وحدة ، ما عليك سوى إضافة ما يلي
سطر لوظيفة wscript build ():

bld.ns3_python_bindings ()

منظمة of هيه وحدات Python الارتباطات
إنّ src / / الارتباطات قد يحتوي الدليل على الملفات التالية ، بعضها
اختياري:

· callbacks_list.py: هذا ملف ممسوح ضوئيًا ، لا تلمسه. يحتوي على قائمة
رد الاتصال <...> تم العثور على مثيلات القالب في الرؤوس الممسوحة ضوئيًا ؛

· Modulegen__gcc_LP64.py: هذا ملف ممسوح ضوئيًا ، لا تلمسه. تعريفات API الممسوحة ضوئيًا
لعمارة دول مجلس التعاون الخليجي ، LP64 (64 بت)

· Modulegen__gcc_ILP32.py: هذا ملف ممسوح ضوئيًا ، لا تلمسه. تعريفات API الممسوحة ضوئيًا
لعمارة دول مجلس التعاون الخليجي ، ILP32 (32 بت)

· Modulegen_customizations.py: يمكنك إضافة هذا الملف اختياريًا لتخصيص ملف
توليد كود بيبيندجن

· مسح رأس. h: يمكنك إضافة هذا الملف اختياريًا لتخصيص ملف الرأس الذي يتم فحصه
للوحدة. يتم فحص هذا الملف بشكل أساسي بدلاً من ns3 / -الوحدة.
عادةً ما تكون العبارة الأولى هي #include "ns3 / -module.h "، بالإضافة إلى بعض العناصر الأخرى
أشياء لفرض إنشاء قالب ؛

· Module_helpers.cc: يمكنك إضافة ملفات إضافية ، مثل هذه ، لربطها ببيثون
وحدة الامتداد ، ولكن يجب تسجيلها في ملف wscript. ينظر الى
src / core / wscript للحصول على مثال على كيفية القيام بذلك ؛

· .السنة التحضيرية: إذا كان هذا الملف موجودًا ، فإنه يصبح وحدة python "الواجهة الأمامية" لـ ns3
وحدة ، ووحدة الامتداد (ملف .so) تصبح _ . لذا بدلاً من .لذا.
ال يجب أن يقوم ملف .py باستيراد جميع الرموز من الوحدة النمطية _ (هذا أكثر
صعب مما يبدو ، راجع src / core / bindings / core.py للحصول على مثال) ، ثم يمكنك إضافة
بعض التعريفات الإضافية لـ Pure-python.

المزيد معلومات لـ المطورون
إذا كنت مطورًا وتحتاج إلى مزيد من المعلومات حول NS-3روابط Python ، يرجى الاطلاع على
Python الارتباطات ويكي صفحة.

اختبارات
نظرة عامة
تختص هذه الوثيقة باختبار والتحقق من صحة NS-3 البرنامج.

توفر هذه الوثيقة

· خلفية عن المصطلحات واختبار البرمجيات (الفصل 2)؛

· وصف لإطار الاختبار ns-3 (الفصل 3) ؛

· دليل لمطوري النماذج أو المساهمين في النموذج الجديد لكيفية كتابة الاختبارات (فصل
4)؛

باختصار ، يجب قراءة الفصول الثلاثة الأولى من قبل مطوري ns والمساهمين الذين
بحاجة إلى فهم كيفية المساهمة في كود الاختبار والبرامج المصادق عليها ، والباقي
من المستند يوفر مساحة للأشخاص للإبلاغ عن جوانب النماذج المختارة
تم التحقق من صحتها.

خلفيّة
هذه الفصل قد be تخطي by القراء مألوف مع هيه مبادئ of نظام البرمجيات الاختبار.

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

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

على سبيل المثال ، يمكن للمرء تقسيم العملية إلى فئات وظيفية واسعة مثل
"اختبار الصحة" "" اختبار الأداء "" "اختبار المتانة" و "الأمان
الاختبار. "هناك طريقة أخرى للنظر إلى المشكلة وهي دورة الحياة:" اختبار المتطلبات "
"اختبار التصميم" و "اختبار القبول" و "اختبار الصيانة". وجهة نظر أخرى
من خلال نطاق النظام الذي تم اختباره. في هذه الحالة يمكن الحديث عن "اختبار الوحدة"
"اختبار المكونات" و "اختبار التكامل" و "اختبار النظام". هذه المصطلحات هي
أيضًا لم يتم توحيدها بأي شكل من الأشكال ، وبالتالي فإن "اختبار الصيانة" و "الانحدار"
اختبار '' يمكن سماعه بالتبادل. بالإضافة إلى ذلك ، غالبًا ما يتم إساءة استخدام هذه المصطلحات.

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

إنّ NS-3 المشروع ليس في مجال الدفاع عن أي من هذه العمليات ، ولكن
يحتوي المشروع ككل على متطلبات تساعد في إبلاغ عملية الاختبار.

مثل جميع منتجات البرامج الرئيسية ، NS-3 لديه عدد من الصفات التي يجب أن تكون موجودة من أجل
المنتج لتحقيق النجاح. من منظور الاختبار ، يجب أن تكون بعض هذه الصفات
معالجة هي أن NS-3 يجب أن تكون "" صحيحة و "" قوية و "" فعالة "و
"يمكن صيانته." من الناحية المثالية ، يجب أن تكون هناك مقاييس لكل من هذه الأبعاد
تم التحقق من خلال الاختبارات لتحديد متى يفشل المنتج في تلبية توقعاته /
المتطلبات.

صحة
الغرض الأساسي من الاختبار هو تحديد سلوك جزء من البرنامج
"بشكل صحيح." NS-3 هذا يعني أنه إذا قمنا بمحاكاة شيء ما ، فيجب على المحاكاة
تمثل بأمانة بعض الكيانات المادية أو العمليات بدقة محددة و
الدقة.

اتضح أن هناك منظورين يمكن من خلالهما رؤية الصواب.
التحقق من أن نموذجًا معينًا يتم تنفيذه وفقًا لمواصفاته هو
بشكل عام التحقق. عملية تحديد أن النموذج هو الصحيح
يتم استدعاء الاستخدام المقصود بشكل عام التحقق من صحة.

التحقق التحقق
نموذج الكمبيوتر هو تمثيل رياضي أو منطقي لشيء ما. يمكن
تمثل مركبة ، فيل (انظر ديفيد هاريل حديث عن الصابون تصميم an فيل at
أدوات SIMUT 2009، أو بطاقة الشبكة. يمكن أن تمثل النماذج أيضًا عمليات مثل العالمية
الاحترار أو تدفق حركة المرور على الطرق السريعة أو مواصفات بروتوكول الشبكات. يمكن أن تكون النماذج
تمثيلات مخلصة تمامًا لمواصفات عملية منطقية ، لكنها
بالضرورة لا يمكن أبدًا محاكاة كائن مادي أو عملية بشكل كامل. في معظم الحالات ، أ
تم إجراء عدد من عمليات التبسيط على النموذج لإجراء المحاكاة حسابيًا
لين العريكة.

كل نموذج له الهدف نظام أنها تحاول محاكاة. الخطوة الأولى في
إنشاء نموذج محاكاة هو تحديد هذا النظام المستهدف ومستوى التفاصيل و
الدقة التي ترغب المحاكاة في إعادة إنتاجها. في حالة وجود عملية منطقية ،
يمكن تعريف النظام الهدف على أنه "TCP كما هو محدد بواسطة RFC 793." في هذه الحالة ، فإنه
سيكون من المرغوب فيه على الأرجح إنشاء نموذج يعيد إنتاج RFC بشكل كامل وصادق
793- لن يكون ذلك ممكناً في حالة وجود عملية فيزيائية. إذا ، على سبيل المثال ، أنت
ترغب في محاكاة بطاقة شبكة لاسلكية ، يمكنك تحديد ما تحتاج إليه
تنفيذ دقيق على مستوى MAC لمواصفات 802.11 و [...] ليس بطيئًا جدًا
نموذج مستوى PHY لمواصفات 802.11a. ''

بمجرد القيام بذلك ، يمكن للمرء أن يطور نموذجًا مجردًا للنظام الهدف. هذا هو
عادة ما يكون تمرينًا في إدارة المفاضلات بين التعقيد ومتطلبات الموارد
والدقة. تم استدعاء عملية تطوير نموذج مجرد نموذج
المؤهل العلمي في الأدب. في حالة بروتوكول TCP ، ينتج عن هذه العملية أ
تصميم لمجموعة من الأشياء والتفاعلات والسلوكيات التي سيتم تنفيذها بالكامل
RFC 793 بوصة NS-3. في حالة البطاقة اللاسلكية ، ينتج عن هذه العملية عدد من
المقايضات للسماح بمحاكاة الطبقة المادية وتصميم جهاز الشبكة
وقناة لـ ns-3 ، جنبًا إلى جنب مع الكائنات والتفاعلات والسلوكيات المرغوبة.

ثم تم تطوير هذا النموذج المجرد إلى ملف NS-3 النموذج الذي ينفذ الملخص
نموذج كبرنامج كمبيوتر. عملية الحصول على موافقة التنفيذ مع
النموذج المجرد يسمى نموذج التحقق في الأدب.

العملية حتى الآن هي حلقة مفتوحة. ما تبقى هو تحديد أن ns-3 معين
النموذج له بعض الارتباط ببعض الواقع - أن النموذج يمثل تمثيلًا دقيقًا لـ
نظام حقيقي ، سواء كان عملية منطقية أو كيان مادي.

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

إنّ NS-3 توفر بيئة الاختبار أدوات للسماح بالتحقق من صحة النموذج و
الاختبار ، والتشجيع على نشر نتائج التحقق.

متانة
المتانة هي نوعية القدرة على تحمل الضغوط أو التغيرات في البيئات ،
المدخلات أو الحسابات ، إلخ. يكون النظام أو التصميم "قويًا" إذا كان بإمكانه التعامل مع مثل هذا
التغييرات مع الحد الأدنى من فقدان الوظائف.

عادة ما يتم إجراء هذا النوع من الاختبارات بتركيز خاص. على سبيل المثال ، النظام باسم
يمكن تشغيل الكل على العديد من تكوينات النظام المختلفة لإثبات إمكانية ذلك
تعمل بشكل صحيح في عدد كبير من البيئات.

يمكن أيضًا التأكيد على النظام من خلال التشغيل بالقرب من السعة أو تجاوزها عن طريق التوليد
أو محاكاة استنفاد الموارد بمختلف أنواعها. يسمى هذا النوع من الاختبار
"اختبار التحمل."

قد يتعرض النظام ومكوناته لما يسمى "الاختبارات النظيفة" التي توضح ذلك
نتيجة إيجابية - وهذا هو أن النظام يعمل بشكل صحيح في استجابة كبيرة
تباين التكوينات المتوقعة.

قد يتعرض النظام ومكوناته أيضًا "لاختبارات قذرة" توفر مدخلات
خارج النطاق المتوقع. على سبيل المثال ، إذا كانت الوحدة النمطية تتوقع سلسلة صفرية منتهية
تمثيل عدد صحيح ، قد يوفر الاختبار القذر سلسلة غير منتهية من العشوائية
أحرف للتحقق من عدم تعطل النظام نتيجة لهذا الإدخال غير المتوقع.
لسوء الحظ ، فإن اكتشاف مثل هذه المدخلات "القذرة" واتخاذ التدابير الوقائية لضمان
النظام لا يفشل بشكل كارثي يمكن أن يتطلب قدرًا هائلاً من النفقات العامة للتنمية.
من أجل تقليل وقت التطوير ، تم اتخاذ قرار مبكرًا في المشروع بـ
تقليل مقدار التحقق من صحة المعلمة ومعالجة الأخطاء في NS-3 قاعدة البيانات. ل
لهذا السبب ، لا نقضي الكثير من الوقت في الاختبار القذر - بل سيكشف فقط عن
نتائج قرار التصميم الذي نعلم أننا اتخذناه.

نريد أن نثبت ذلك NS-3 البرنامج يعمل عبر مجموعة من الشروط. نحن
استعير بعض التعريفات لتضييق هذا قليلاً. ال نطاق of القابلية للتطبيق is
مجموعة من الشروط المحددة التي تم اختبار النموذج من أجلها ، مقارنةً بها
الواقع إلى أقصى حد ممكن ، ويعتبر مناسبًا للاستخدام. ال نطاق of دقة هو
الاتفاق بين النموذج المحوسب والواقع ضمن مجال التطبيق.

إنّ NS-3 توفر بيئة الاختبار أدوات للسماح بإعداد الاختبار وتشغيله
بيئات عبر أنظمة متعددة (buildbot) ويوفر فئات لتشجيع النظافة
اختبارات للتحقق من تشغيل النظام عبر "مجال التطبيق" المتوقع
و "مدى الدقة."

قوي
حسنًا ، كلمة "Performant" ليست كلمة إنجليزية حقيقية. ومع ذلك ، فهو حديث موجز للغاية
يتم استخدامه غالبًا لوصف ما نريد NS-3 أن تكون: قوية وسريعة بما يكفي
إنجاز المهمة.

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

في مجلة NS-3 إطار الاختبار ، نحن نقدم الدعم لتوقيت أنواع مختلفة من الاختبارات.

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

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

A محلي تراجع هو التغيير الذي يؤثر فيه التغيير على المكون الذي تم تغييره بشكل مباشر. ل
على سبيل المثال ، إذا تم تعديل أحد المكونات لتخصيص الذاكرة وتحريرها ولكن المؤشرات التي لا معنى لها تكون كذلك
مستخدم ، فشل المكون نفسه.

A عن بعد تراجع هو أحد العناصر التي يؤدي فيها التغيير إلى مكون واحد إلى تعطيل الوظيفة
مكون آخر. هذا يعكس انتهاكًا ضمنيًا ولكن ربما غير معترف به
عقد بين المكونات.

An غير المقنعة تراجع هي التي تخلق حالة بها خطأ موجود سابقًا
التي لم يكن لها تأثير يتم كشفها فجأة في النظام. قد يكون هذا بسيطًا مثل ممارسة الرياضة
مسار رمز لأول مرة.

A أداء تراجع هو الذي يتسبب في متطلبات أداء النظام
أن تنتهك. على سبيل المثال ، القيام ببعض الأعمال في وظيفة منخفضة المستوى يمكن تكرارها
قد يؤدي عدد كبير من المرات إلى جعل النظام فجأة غير قابل للاستخدام من وجهات نظر معينة.

إنّ NS-3 يوفر إطار الاختبار أدوات لأتمتة العملية المستخدمة للتحقق من صحة و
تحقق من الكود في مجموعات الاختبار الليلية للمساعدة في التعرف بسرعة على الانحدارات المحتملة.

الاختبار الإطار
يتكون ns-3 من محرك محاكاة أساسي ومجموعة من النماذج وبرامج أمثلة واختبارات.
بمرور الوقت ، يساهم المساهمون الجدد في النماذج والاختبارات والأمثلة. برنامج اختبار بايثون
test.py يعمل كمدير تنفيذ الاختبار ؛ test.py يمكن تشغيل كود الاختبار والأمثلة ل
البحث عن الانحدارات ، ويمكن إخراج النتائج في عدد من النماذج ، ويمكن إدارة التعليمات البرمجية
أدوات تحليل التغطية. علاوة على ذلك ، نحن طبقة بناء الروبوتات التي هي بناء آلي
الروبوتات التي تقوم باختبار القوة من خلال تشغيل إطار الاختبار على أنظمة مختلفة
وخيارات تكوين مختلفة.

BuildBots
في أعلى مستوى من اختبار ns-3 توجد الروبوتات البنائية (بناء الروبوتات). إذا كنت كذلك
غير مألوف مع نظرة هذا النظام http://djmitche.github.com/buildbot/docs/0.7.11/.
هذا هو نظام آلي مفتوح المصدر يسمح NS-3 ليتم إعادة بنائها واختبارها
الوقت تغير شيء ما. من خلال تشغيل buildbots على عدد من الأنظمة المختلفة ، فإننا
يمكن أن تضمن ذلك NS-3 يبني وينفذ بشكل صحيح على جميع أنظمته المدعومة.

لن يتفاعل المستخدمون (والمطورون) عادةً مع نظام buildbot بخلاف to
قراءة رسائلها المتعلقة بنتائج الاختبار. إذا تم الكشف عن فشل في أحد ملفات
وظائف البناء والاختبار المؤتمتة ، سيرسل buildbot بريدًا إلكترونيًا إلى NS- المطورين
القائمة البريدية. سيبدو هذا البريد الإلكتروني مثل

في عنوان URL الكامل للتفاصيل الموضحة في البريد الإلكتروني ، يمكن للمرء البحث عن الكلمة الأساسية فشل
حدد stdio رابط للخطوة المقابلة لمعرفة سبب الفشل.

سيقوم buildbot بعمله بهدوء إذا لم تكن هناك أخطاء ، وسيخضع النظام
بناء واختبار الدورات كل يوم للتحقق من أن كل شيء على ما يرام.

Test.py
تستخدم الروبوتات البنائية برنامج Python ، test.py، هذا هو المسؤول عن تشغيل كل
الاختبارات وجمع التقارير الناتجة في نموذج يمكن قراءته من قبل الإنسان. هذا البرنامج
متاح أيضًا للاستخدام من قبل المستخدمين والمطورين أيضًا.

test.py مرن للغاية في السماح للمستخدم بتحديد عدد ونوع الاختبارات
يجري؛ وكذلك كمية ونوع المخرجات المراد توليدها.

قبل الجري test.py، تأكد من أن الأمثلة والاختبارات الخاصة بـ ns3 قد تم إنشاؤها عن طريق العمل
ما يلي

تكوين $ ./waf - أمثلة قابلة للتمكين - اختبارات التمكين
$ ./واف

افتراضيا، test.py سيتم تشغيل جميع الاختبارات المتاحة والإبلاغ عن الحالة مرة أخرى بشكل موجز للغاية
استمارة. تشغيل الأمر

$ ./test.py

سيؤدي إلى عدد من مرر, يفشلون, تحطم or تخطى المؤشرات التي يتبعها نوع
الاختبار الذي تم تشغيله واسم العرض الخاص به.

Waf: إدخال الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
Waf: مغادرة الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
انتهى "البناء" بنجاح (0.939 ثانية)
فشل: TestSuite ns3-wifi-propagation-loss-loss
PASS: خدمة اسم الكائن TestSuite
تمرير: كائن ملف TestSuite pcap
اجتياز: TestSuite ns3-tcp-cwnd

تمرير: قابلية التشغيل المتداخل TestSuite ns3-tcp
PASS: مثال على بث csma
PASS: مثال csma-multicast

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

هناك عدد من الخيارات المتاحة للتحكم في سلوك test.py. اذا ركضت
test.py --مساعدة يجب أن ترى ملخصًا للأوامر مثل:

الاستخدام: test.py [options]

خيارات:
-h ، - ساعد في إظهار رسالة المساعدة هذه والخروج
-b BUILDPATH ، --buildpath = BUILDPATH
حدد المسار حيث تم بناء ns-3 (الإعدادات الافتراضية لملف
بناء دليل للمتغير الحالي)
-c KIND، --constrain = KIND
تقييد عداء الاختبار بنوع الاختبار
-E EXAMPLE، --example = EXAMPLE
تحديد مثال واحد لتشغيله (لا يوجد مسار نسبي
بحاجة)
-g، --grind قم بتشغيل مجموعات الاختبار والأمثلة باستخدام valgrind
-ك ، - أنواع طباعة أنواع الاختبارات المتاحة
-l، - قائمة طباعة قائمة الاختبارات المعروفة
-m ، - الإبلاغ عن عدة إخفاقات متعددة من مجموعات الاختبار والاختبار
الحالات
-n، --nowaf لا تقم بتشغيل الواف قبل بدء الاختبار
-p PYEXAMPLE ، --pyexample = PYEXAMPLE
تحديد مثال بيثون واحد لتشغيله (مع نسبي
المسار)
-r ، - الاحتفاظ بكافة الملفات المؤقتة (والتي عادة ما تكون
تم الحذف)
-s TEST-SUITE ، - Suite = TEST-SUITE
تحديد مجموعة اختبار واحدة للتشغيل
-t TEXT-FILE ، --text = TEXT-FILE
اكتب نتائج الاختبار التفصيلية في TEXT-FILE.txt
-v ، - تقدم الطباعة والإفراط في الطباعة والرسائل الإعلامية
-w HTML-FILE، --web = HTML-FILE، --html = HTML-FILE
كتابة نتائج اختبار مفصلة في HTML-FILE.html
-x XML-FILE ، --xml = XML-FILE
كتابة نتائج اختبار مفصلة في ملف XML-FILE.xml

إذا حدد أحد نمط الإخراج الاختياري ، فيمكنه إنشاء أوصاف تفصيلية لملف
الاختبارات والحالة. الأنماط المتوفرة نص HTML. ستحدد روبوتات البناء HTML
خيار إنشاء تقارير اختبار HTML للإصدارات الليلية باستخدام

$ ./test.py --html = nightly.html

في هذه الحالة ، سيتم إنشاء ملف HTML باسم nightly.html بملخص رائع
تم إجراء الاختبار. يتوفر تنسيق "قابل للقراءة البشرية" للمستخدمين المهتمين بـ
تفاصيل.

$ ./test.py --text = results.txt

في المثال أعلاه ، تقوم مجموعة الاختبار بفحص ملف NS-3 فقدان انتشار الجهاز اللاسلكي
النماذج فشلت. بشكل افتراضي لا يتم توفير مزيد من المعلومات.

لمزيد من استكشاف الفشل ، test.py يسمح بتحديد مجموعة اختبار واحدة.
تشغيل الأمر

$ ./test.py --suite = ns3-wifi-propagation-loss-Models

أو مكافئ

$ ./test.py -s ns3-wifi-propagation-loss-Models

يؤدي إلى تشغيل مجموعة الاختبار الفردية هذه.

فشل: TestSuite ns3-wifi-propagation-loss-loss

للعثور على معلومات مفصلة بشأن الفشل ، يجب على المرء تحديد نوع الإخراج
مرغوب. على سبيل المثال ، من المحتمل أن يهتم معظم الأشخاص بملف نصي:

$ ./test.py --suite = ns3-wifi-propagation-loss-Models --text = results.txt

سيؤدي ذلك إلى تشغيل مجموعة الاختبار الفردية هذه مع كتابة حالة الاختبار إلى
ملف 'results.txt' '.

يجب أن تجد شيئًا مشابهًا لما يلي في هذا الملف

فشل: مجموعة الاختبار "ns3-wifi-propagation-loss-Models" (0.02 مستخدم حقيقي 0.01 نظام 0.00)
PASS: Test Case "Check ... Friis ... model ..." (0.01 مستخدم حقيقي 0.00 نظام 0.00)
فشل: حالة الاختبار "تحقق ... مسافة السجل ... نموذج" (0.01 مستخدم حقيقي 0.01 نظام 0.00)
التفاصيل:
الرسالة: حصلت على قيمة SNR غير متوقعة
الحالة: [وصف مطول لما فشل بالفعل]
الفعلي: 176.395،XNUMX،XNUMX
الحد: 176.407 + - 0.0005
الملف: ../src/test/ns3wifi/propagation-loss-models-test-suite.cc
السطر: 360

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

إذا كنت ترغب في ذلك ، يمكنك بسهولة كتابة ملف HTML باستخدام امتداد --لغة البرمجة خيار
كما هو موضح أعلاه.

عادةً ما يقوم المستخدم بإجراء جميع الاختبارات مرة واحدة على الأقل بعد التنزيل NS-3 لتتآكد من ذلك
تم بناء بيئته أو بيئتها بشكل صحيح وتنتج النتائج الصحيحة
وفقًا لأجنحة الاختبار. سيقوم المطورون عادةً بتشغيل مجموعات الاختبار قبل و
بعد إجراء تغيير للتأكد من عدم حدوث تراجع مع
التغييرات. في هذه الحالة ، قد لا يرغب المطورون في إجراء جميع الاختبارات ، ولكن فقط مجموعة فرعية. ل
على سبيل المثال ، قد يرغب المطور فقط في تشغيل اختبارات الوحدة بشكل دوري أثناء إجراء
التغييرات في المستودع. في هذه الحالة، test.py يمكن أن يقال لتقييد أنواع
الاختبارات التي يتم إجراؤها على فئة معينة من الاختبارات. الأمر التالي سينتج عنه فقط
اختبارات الوحدة قيد التشغيل:

$ ./test.py --constrain = unit

وبالمثل ، سينتج عن الأمر التالي فقط مثال اختبارات الدخان قيد التشغيل:

$ ./test.py --constrain = unit

للاطلاع على قائمة سريعة بالأنواع القانونية للقيود ، يمكنك طلب إدراجها في القائمة.
الأمر التالي

$ ./test.py - أنواع

سيؤدي إلى عرض القائمة التالية:

Waf: إدخال الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
Waf: مغادرة الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
انتهى 'build' بنجاح (0.939 ثانية) Waf: إدخال الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
bvt: إنشاء اختبارات التحقق (لمعرفة ما إذا كان البناء قد اكتمل بنجاح)
core: قم بتشغيل جميع الاختبارات المستندة إلى TestSuite (استبعاد الأمثلة)
مثال: أمثلة (لمعرفة ما إذا تم تشغيل أمثلة البرامج بنجاح)
الأداء: اختبارات الأداء (تحقق لمعرفة ما إذا كان النظام سريعًا كما هو متوقع)
النظام: اختبارات النظام (تمتد للوحدات النمطية للتحقق من تكامل الوحدات)
الوحدة: اختبارات الوحدة (داخل الوحدات النمطية للتحقق من الوظائف الأساسية)

يمكن تقديم أي من هذه الأنواع من الاختبارات كقيد باستخدام --قيد الخيار.

للاطلاع على قائمة سريعة بجميع مجموعات الاختبار المتاحة ، يمكنك أن تطلب منهم ذلك
المدرجة. الأمر التالي ،

$ ./test.py - قائمة

سيؤدي إلى عرض قائمة بمجموعة الاختبار ، على غرار

Waf: إدخال الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
Waf: مغادرة الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
انتهى "البناء" بنجاح (0.939 ثانية)
الرسم البياني
ns3- تدخل واي فاي
ns3-tcp-cwnd
إمكانية التشغيل البيني ns3-tcp
عينة
أجهزة شبكة اللهب
أجهزة- شبكة- dot11s
أجهزة شبكة

خدمة اسم الكائن
رد
سمات
التكوين
قيمة عالمية
سطر الأوامر
رقم عشوائي أساسي
موضوع

يمكن تحديد أي من هذه المجموعات المدرجة ليتم تشغيلها بنفسها باستخدام --جناح الخيار كـ
هو مبين أعلاه.

على غرار مجموعات الاختبار ، يمكن للمرء تشغيل برنامج مثال C ++ واحد باستخدام --مثال
خيار. لاحظ أن المسار النسبي للمثال لا يحتاج إلى تضمينه وذاك
لا تحتوي الملفات التنفيذية المُصممة لأمثلة C ++ على ملحقات. الدخول

$ ./test.py --example = udp-echo

يؤدي إلى تشغيل هذا المثال الوحيد.

PASS: أمثلة أمثلة / udp / udp-echo

يمكنك تحديد الدليل حيث تم إنشاء ns-3 باستخدام امتداد --مسار بناء الخيار كـ
يتبع.

$ ./test.py --buildpath = / home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build / debug --example = wifi-simple-adhoc

يمكن للمرء تشغيل برنامج مثال Python واحد باستخدام - مثال اختيار. نلاحظ أن
يجب تضمين المسار النسبي للمثال وأن أمثلة Python تحتاج إلى
ملحقات. الدخول

$ ./test.py --pyexample = أمثلة / tutorial / first.py

يؤدي إلى تشغيل هذا المثال الوحيد.

PASS: أمثلة أمثلة / tutorial / first.py

نظرًا لأن أمثلة Python غير مبنية ، فلن تحتاج إلى تحديد الدليل حيث ns-3
تم بناؤه لتشغيلها.

عادة عندما يتم تنفيذ البرامج النموذجية ، فإنها تكتب كمية كبيرة من بيانات ملف التتبع.
يتم حفظ هذا عادةً في الدليل الأساسي للتوزيع (على سبيل المثال ،
/ home / user / ns-3-dev). متى test.py يدير مثالًا ، فهو حقًا غير مهتم تمامًا
مع ملفات التتبع. إنه يريد فقط تحديد ما إذا كان يمكن بناء المثال وتشغيله
بدون أخطاء. نظرًا لأن هذه هي الحالة ، تتم كتابة ملفات التتبع في ملف
/ tmp / آثار غير محددة الدليل. إذا قمت بتشغيل المثال أعلاه ، فيجب أن تكون قادرًا على العثور عليه
ويرتبط udp-echo.tr udp- صدى- n-1.pcap الملفات هناك.

يتم تحديد قائمة الأمثلة المتاحة من خلال محتويات دليل "أمثلة" في
التوزيع. إذا قمت بتحديد مثال للتنفيذ باستخدام --مثال اختيار،
test.py لن يقوم بأي محاولة لتحديد ما إذا كان المثال قد تم تكوينه أم لا ،
سيحاول فقط تشغيله والإبلاغ عن نتيجة المحاولة.

متى test.py يعمل ، بشكل افتراضي ، سيضمن أولاً أن النظام قد تم بالكامل
مبني. يمكن هزيمة هذا عن طريق اختيار - نواف الخيار.

$ ./test.py - قائمة --nowaf

سيؤدي إلى عرض قائمة بمجموعات الاختبار المبنية حاليًا ، على غرار:

نماذج فقدان الانتشار ns3-wifi
ns3-tcp-cwnd
إمكانية التشغيل البيني ns3-tcp
كائن ملف pcap
خدمة اسم الكائن
مولدات الأرقام العشوائية

لاحظ عدم وجود ملف WAF بناء الرسائل.

test.py يدعم أيضًا تشغيل مجموعات الاختبار والأمثلة تحت valgrind. Valgrind هو ملف
برنامج مرن لتصحيح الأخطاء وتنميط الملفات التنفيذية لينكس. بشكل افتراضي ، يتم تشغيل valgrind
أداة تسمى memcheck ، والتي تؤدي مجموعة من وظائف فحص الذاكرة ، بما في ذلك
الكشف عن الوصول إلى الذاكرة غير المهيأة ، إساءة استخدام الذاكرة المخصصة (عمليات التحرير المزدوجة ،
بعد الوصول المجاني ، وما إلى ذلك) واكتشاف تسرب الذاكرة. يمكن تحديد ذلك باستخدام ملف
--طَحن الخيار.

$ ./test.py --grind

أثناء سيرها ، test.py والبرامج التي يتم تشغيلها بشكل غير مباشر ، تولد أعدادًا كبيرة من
ملفات مؤقتة. عادةً ما يكون محتوى هذه الملفات غير مثير للاهتمام ، ولكن في البعض
يمكن أن يكون من المفيد (لأغراض التصحيح) عرض هذه الملفات. test.py ويوفر
--يحتفظ الخيار الذي سيؤدي إلى الاحتفاظ بهذه الملفات المؤقتة بعد التشغيل
مكتمل. يتم حفظ الملفات في دليل باسم testpy الإخراج تحت دليل فرعي
تم تسميته وفقًا للتوقيت العالمي المنسق الحالي (المعروف أيضًا باسم Greenwich Mean
زمن).

$ ./test.py - الاحتفاظ

وفي الختام test.py ويوفر - الإسراف الخيار الذي سيطبع كميات كبيرة من المعلومات
عن تقدمه. ليس من المتوقع أن يكون هذا مفيدًا للغاية ما لم يكن هناك
خطا. في هذه الحالة ، يمكنك الوصول إلى الإخراج القياسي والخطأ القياسي
تم الإبلاغ عنها من خلال تشغيل مجموعات وأمثلة الاختبار. حدد مطولًا بالطريقة التالية:

$ ./test.py - الإفراط في الكلام

يمكن خلط كل هذه الخيارات ومطابقتها. على سبيل المثال ، لتشغيل كل نواة ns-3
مجموعات الاختبار تحت valgrind ، في الوضع المطول ، أثناء إنشاء ملف إخراج HTML ، واحد
ستفعل:

$ ./test.py --verbose --grind --constrain = core --html = results.html

TestTaxonomy
كما ذكر أعلاه ، يتم تجميع الاختبارات في عدد من التصنيفات المحددة على نطاق واسع
تسمح للمستخدمين بإجراء الاختبارات بشكل انتقائي لمعالجة الأنواع المختلفة للاختبارات التي تحتاج إليها
أن يتم.

· بناء اختبارات التحقق

· اختبارات الوحدة

· اختبارات النظام

· أمثلة

· اختبارات الأداء

بناء اختبارات التحقق
هذه اختبارات بسيطة نسبيًا يتم إنشاؤها جنبًا إلى جنب مع التوزيع ويتم استخدامها
للتأكد من أن التصميم يعمل إلى حد كبير. اختبارات الوحدة الحالية لدينا تعيش في
ملفات المصدر للشفرة التي يختبرونها وتكون مدمجة في وحدات ns-3 ؛ وهكذا تناسب
وصف BVTs. تعيش ملفات BVT في نفس شفرة المصدر المضمنة في كود ns-3.
اختباراتنا الحالية هي أمثلة على هذا النوع من الاختبارات.

وحدة اختبارات
اختبارات الوحدة هي اختبارات أكثر تعقيدًا تدخل في التفاصيل للتأكد من وجود جزء من التعليمات البرمجية
يعمل كما هو معلن عنه في عزلة. لا يوجد سبب حقيقي لهذا النوع من الاختبارات
مدمج في وحدة ns-3. اتضح ، على سبيل المثال ، أن الوحدة تختبر الكائن
خدمة الاسم هي نفس حجم رمز خدمة اسم الكائن نفسه تقريبًا. اختبارات الوحدة
هي الاختبارات التي تتحقق من جزء واحد من الوظائف غير المضمنة في رمز ns-3 ،
لكن تعيش في نفس الدليل مثل الكود الذي يختبره. ومن الممكن أن تكون هذه الاختبارات
تحقق من تكامل ملفات التنفيذ المتعددة في الوحدة أيضًا. الملف
src / core / test / names-test-suite.cc مثال على هذا النوع من الاختبارات. الملف
src / network / test / pcap-file-test-suite.cc مثال آخر يستخدم pcap جيد معروف
ملف كملف متجه اختبار. يتم تخزين هذا الملف محليًا في دليل src / network.

اختبارات
اختبارات النظام هي تلك التي تتضمن أكثر من وحدة واحدة في النظام. لدينا الكثير من
هذا النوع من الاختبارات قيد التشغيل في إطار عمل الانحدار الحالي لدينا ، لكنها عادةً ما تكون كذلك
أمثلة مثقلة. نحن نوفر مكانًا جديدًا لهذا النوع من الاختبارات في الدليل
src / الاختبار. يعد الملف src / test / ns3tcp / ns3-interop-test-suite.cc مثالاً على هذا النوع
من الاختبار. يستخدم NSC TCP لاختبار تنفيذ ns-3 TCP. في كثير من الأحيان سيكون هناك اختبار
المتجهات المطلوبة لهذا النوع من الاختبار ، ويتم تخزينها في الدليل حيث
حياة الاختبار. على سبيل المثال ، ns3tcp-interop-response-vectors.pcap هو ملف يتكون من ملف
عدد رؤوس TCP المستخدمة كاستجابات متوقعة لـ ns-3 TCP قيد الاختبار
إلى حافز ناتج عن برنامج التعاون الفني في مجلس الأمن القومي والذي يستخدم باعتباره تنفيذ "جيد معروف".

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

الأداء اختبارات
اختبارات الأداء هي تلك التي تمارس جزءًا معينًا من النظام وتحدده
إذا تم تنفيذ الاختبارات حتى الانتهاء في وقت معقول.

الركض اختبارات
يتم إجراء الاختبارات عادةً باستخدام المستوى العالي test.py برنامج. للحصول على قائمة
خيارات سطر الأوامر المتاحة ، تشغيل test.py --مساعدة

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

باختصار ، لتشغيل جميع الاختبارات ، يجب أولاً تكوين الاختبارات أثناء مرحلة التكوين ، و
أيضًا (اختياريًا) أمثلة إذا كان سيتم التحقق من الأمثلة:

$ ./waf - تكوين - أمثلة - تمكين - اختبارات تمكين

ثم ، قم ببناء ns-3 ، وبعد أن يتم بناؤه ، ما عليك سوى تشغيل test.py. test.py -h سيظهر رقم
من خيارات التكوين التي تعدل سلوك test.py.

البرنامج test.py يستدعي ، بالنسبة لاختبارات وأمثلة C ++ ، برنامج C ++ منخفض المستوى يسمى
عداء اختبار لإجراء الاختبارات بالفعل. كما هو موضح أدناه ، هذا عداء اختبار يمكن أن يكون
طريقة مفيدة لتصحيح الأخطاء.

التصحيح اختبارات
من الأفضل إجراء تصحيح أخطاء برامج الاختبار عند تشغيل عداء الاختبار ذي المستوى المنخفض
برنامج. عداء الاختبار هو الجسر من كود Python العام إلى NS-3 شفرة. إنها
مكتوب بلغة C ++ ويستخدم عملية اكتشاف الاختبار التلقائي في NS-3 رمز للعثور و
تسمح بتنفيذ جميع الاختبارات المختلفة.

السبب الرئيسي test.py غير مناسب للتصحيح هو أنه غير مسموح به
التسجيل ليتم تشغيله باستخدام NS_LOG المتغير البيئي عند تشغيل test.py. هذا
لا ينطبق القيد على عداء الاختبار القابل للتنفيذ. وبالتالي ، إذا كنت تريد أن ترى التسجيل
الناتج من الاختبارات الخاصة بك ، يجب عليك تشغيلها باستخدام عداء الاختبار مباشرة.

من أجل تنفيذ عداء الاختبار ، يمكنك تشغيله مثل أي ns-3 قابل للتنفيذ - باستخدام
WAF. للحصول على قائمة بالخيارات المتاحة ، يمكنك كتابة:

$ ./waf - تشغيل "test-runner --help"

يجب أن ترى شيئًا مثل التالي

Waf: إدخال الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
Waf: مغادرة الدليل "/ home / craigdo / repos / ns-3-allinone-test / ns-3-dev / build"
انتهى "البناء" بنجاح (0.353 ثانية)
--assert: أخبر الاختبارات إلى segfault (مثل التأكيد) إذا تم اكتشاف خطأ
--basedir = dir: اضبط الدليل الأساسي (مكان العثور على src) على "dir"
--tempdir = dir: عيّن الدليل المؤقت (مكان العثور على ملفات البيانات) على "dir"
--constrain = test-type: تقييد الفحوصات لاختبار مجموعات من النوع `` test-type ''
--مساعدة: اطبع هذه الرسالة
--الأنواع: قائمة بجميع أنواع الاختبارات المتاحة
- قائمة: قائمة بجميع مجموعات الاختبار (مقيدة اختياريًا بنوع الاختبار)
--out = file-name: اضبط ملف إخراج حالة الاختبار على "اسم الملف"
--suite = suite-name: قم بتشغيل مجموعة الاختبار المسماة `` suite-name ''
- الإسهاب: قم بتشغيل الرسائل في مجموعات اختبار التشغيل

هناك عدد من الأشياء المتاحة لك والتي ستكون مألوفة لك إذا كان لديك
نظرت إلى test.py. يجب أن يكون هذا متوقعًا نظرًا لأن عارض الاختبار هو مجرد واجهة
ما بين test.py NS-3. قد تلاحظ أن الأوامر المتعلقة بالأمثلة مفقودة هنا.
هذا لأن الأمثلة ليست كذلك في الحقيقة NS-3 الاختبارات. test.py يديرهم كما لو كانوا
لتقديم بيئة اختبار موحدة ، لكنها في الحقيقة مختلفة تمامًا وليست كذلك
يمكن العثور عليها هنا.

الخيار الأول الجديد الذي يظهر هنا ، ولكن ليس في test.py هو --يجزم اختيار. هذه
الخيار مفيد عند تصحيح حالة اختبار عند التشغيل تحت مصحح أخطاء مثل جدب. عندما
محددًا ، يخبر هذا الخيار حالة الاختبار الأساسية بالتسبب في انتهاك التجزئة إذا
تم اكتشاف خطأ. هذا له تأثير جانبي لطيف وهو التسبب في توقف تنفيذ البرنامج
(اقتحام مصحح الأخطاء) عند اكتشاف خطأ. إذا كنت تستخدم gdb ، فيمكنك استخدام ملفات
هذا الخيار شيء مثل ،

$ ./waf شل
بناء / تصحيح / أدوات $ cd
عداء اختبار $ gdb
تشغيل $ - جناح = قيمة عالمية - تأكيد

إذا تم العثور على خطأ في مجموعة اختبار القيمة العالمية ، فسيتم إنشاء segfault
وسيتوقف مصحح الأخطاء (مستوى المصدر) عند NS_TEST_ASSERT_MSG التي اكتشفت
خطأ.

خيار جديد آخر يظهر هنا هو - باسادير خيار. اتضح أن بعض
قد تحتاج الاختبارات إلى الرجوع إلى دليل المصدر الخاص بـ NS-3 التوزيع للعثور على المحلية
البيانات ، لذلك يلزم دائمًا وجود دليل أساسي لإجراء اختبار.

إذا قمت بإجراء اختبار من test.py ، فسيقوم برنامج Python بتوفير الخيار الأساسي لـ
أنت. لإجراء أحد الاختبارات مباشرة من عداء الاختبار باستخدام WAF، ستحتاج إلى
حدد مجموعة الاختبار المراد تشغيلها مع الدليل الأساسي. لذلك يمكنك استخدام القشرة
و افعل:

$ ./waf --run "test-runner --basedir =` pwd` --suite = pcap-file-object "

لاحظ علامات الاقتباس "للخلف" الموجودة على ملف الأشخاص ذوي الإعاقة أمر.

إذا كنت تقوم بتشغيل مجموعة الاختبار من مصحح أخطاء ، فقد يكون من المؤلم للغاية تذكرها
واكتب باستمرار المسار المطلق لدليل قاعدة التوزيع. بسبب
هذا ، إذا حذفت أساسًا ، فسيحاول عداء الاختبار اكتشاف واحد لك. هو - هي
يبدأ في دليل العمل الحالي ويمشي في شجرة الدليل بحثًا عن ملف
ملف الدليل مع الملفات المسماة VERSION رخصة. إذا وجدت واحدة ، فإنها تفترض ذلك
يجب أن يكون أساسًا ويوفره لك.

اختبار الناتج
تحتاج العديد من مجموعات الاختبار إلى كتابة ملفات مؤقتة (مثل ملفات pcap) في عملية
إجراء الاختبارات. تحتاج الاختبارات بعد ذلك إلى دليل مؤقت للكتابة إليه. بايثون
ستوفر أداة الاختبار (test.py) ملفًا مؤقتًا تلقائيًا ، ولكن إذا تم تشغيله بشكل مستقل
يجب توفير هذا الدليل المؤقت. كما هو الحال في حالة الأساس ، يمكن أن يكون كذلك
مزعج أن تضطر باستمرار إلى توفير ملف --تمبدير، لذلك سيحدد عداء الاختبار واحدًا
من أجلك إذا لم تقدم واحدة. يبحث أولاً عن متغيرات البيئة المسماة TMP
مؤقت ويستخدم هؤلاء. إذا لم يكن كذلك TMP ولا مؤقت يتم تعريفها يختارها / تمة. الرمز
ثم يضغط على معرف يشير إلى ما أنشأ الدليل (ns-3) ثم الوقت
(hh.mm.ss) متبوعًا برقم عشوائي كبير. يقوم عداء الاختبار بإنشاء دليل لذلك
اسم لاستخدامه كدليل مؤقت. تنتقل الملفات المؤقتة بعد ذلك إلى الدليل الذي
سيتم تسميته بشيء مثل

/tmp/ns-3.10.25.37.61537845

يتم توفير الوقت كتلميح حتى تتمكن من إعادة بناء ما بسهولة نسبيًا
تم استخدام الدليل إذا كنت بحاجة إلى الرجوع وإلقاء نظرة على الملفات التي تم وضعها فيه
الدليل.

فئة أخرى من المخرجات هي اختبار الإخراج مثل تتبعات pcap التي يتم إنشاؤها للمقارنة
الإخراج المرجعي. سيقوم برنامج الاختبار عادةً بحذفها بعد كل مجموعات الاختبار
يجري. لتعطيل حذف إخراج الاختبار ، قم بتشغيل test.py مع خيار "الاحتفاظ":

$ ./test.py -r

ويمكن العثور على مخرجات الاختبار في ملف testpy الإخراج / الدليل.

التقارير of تجربه بالعربي الفشل
عند تشغيل مجموعة اختبار باستخدام عداء الاختبار ، سيتم تشغيل الاختبار بهدوء افتراضيًا.
المؤشر الوحيد على أنك ستحصل على اجتياز الاختبار هو غياب رسالة
تبدأ من WAF بالقول إن البرنامج أعاد شيئًا آخر غير رمز الخروج الصفري. تحصل
بعض مخرجات الاختبار ، تحتاج إلى تحديد ملف الإخراج الذي ستعمل عليه الاختبارات
كتابة حالة XML الخاصة بهم باستخدام --خارج خيار. عليك أن تكون حذرا في تفسير
النتائج لأن مجموعات الاختبار سوف ألحق النتائج على هذا الملف. يحاول،

$ ./waf --run "test-runner --basedir =` pwd` --suite = pcap-file-object --out = myfile.xml "

إذا نظرت إلى الملف myfile.xml يجب أن ترى شيئًا مثل ،


pcap-file-object

تحقق لترى أن PcapFile :: Open with mode 'w' يعمل
يمر
0.00 مستخدم حقيقي 0.00 نظام 0.00


تحقق لترى أن PcapFile :: Open with mode 'r' يعمل
يمر
0.00 مستخدم حقيقي 0.00 نظام 0.00


تحقق لترى أن PcapFile :: Open with mode '' a '' يعمل
يمر
0.00 مستخدم حقيقي 0.00 نظام 0.00


تحقق لمعرفة أن PcapFileHeader تتم إدارتها بشكل صحيح
يمر
0.00 مستخدم حقيقي 0.00 نظام 0.00


تحقق لمعرفة أن PcapRecordHeader تتم إدارتها بشكل صحيح
يمر
0.00 مستخدم حقيقي 0.00 نظام 0.00


تحقق من أن PcapFile يمكنه قراءة ملف pcap جيد معروف
يمر
0.00 مستخدم حقيقي 0.00 نظام 0.00

يمر
0.00 مستخدم حقيقي 0.00 نظام 0.00


إذا كنت معتادًا على XML ، فيجب أن يكون هذا واضحًا إلى حد ما. كما أنها ليست ملف
ملف XML كامل حيث تم تصميم مجموعات الاختبار بحيث يتم إلحاق مخرجاتها بسيد
ملف حالة XML كما هو موضح في ملف test.py والقسم الخاص به.

التصحيح تجربه بالعربي جناح الفشل
لتصحيح أعطال الاختبار ، مثل

تحطم: TestSuite ns3- تدخل واي فاي

يمكنك الوصول إلى برنامج عداء الاختبار الأساسي عبر gdb على النحو التالي ، ثم اجتياز
"--basedir =` pwd` "الوسيطة للتشغيل (يمكنك أيضًا تمرير وسيطات أخرى حسب الحاجة ، ولكن
Basedir هو الحد الأدنى المطلوب):

$ ./waf --command-template = "gdb٪ s" - تشغيل "test-runner"
Waf: إدخال الدليل "/ home / tomh / hg / sep09 / ns-3-allinone / ns-3-dev-678 / build"
Waf: دليل الخروج "/ home / tomh / hg / sep09 / ns-3-allinone / ns-3-dev-678 / build"
انتهى "البناء" بنجاح (0.380 ثانية)
جنو gdb 6.8 ديبيان
حقوق النشر (C) 2008 مؤسسة البرمجيات الحرة ، Inc.
L cense GPLv3 +: الإصدار 3 من GNU GPL أو أحدثhttp://gnu.org/licenses/gpl.html>
هذا برنامج مجاني: أنت حر في تغييره وإعادة توزيعه.
لا يوجد ضمان ، إلى الحد الذي يسمح به القانون. اكتب "إظهار النسخ"
و "إظهار الضمان" للحصول على التفاصيل.
تم تكوين GDB هذا كـ "x86_64-linux-gnu" ...
(gdb) r --basedir = `pwd`
بدء البرنامج: <..> / build / debug / utils / test-runner --basedir = `pwd`
[تم تمكين تصحيح الخيط باستخدام libthread_db]
فشل التأكيد. file = .. / src / core / model / type-id.cc ، line = 138 ، cond = "uid <= m_information.size () && uid! = 0"


فيما يلي مثال آخر على كيفية استخدام valgrind لتصحيح مشكلة في الذاكرة مثل:

VALGR: أجهزة TestSuite-mesh-dot11s-regression

$ ./waf --command-template = "valgrind٪ s --basedir =` pwd` --suite = الأجهزة- mesh-dot11s-regression "- عداء اختبار التشغيل

مبوبة تسترنر
تستخدم الملفات التنفيذية التي تشغل برامج اختبار مخصصة فئة TestRunner. هذه الفئة
يوفر التسجيل والإدراج التلقائي للاختبار ، بالإضافة إلى طريقة لتنفيذ
الاختبارات الفردية. تستخدم مجموعات الاختبار الفردية المُنشئين العالميين C ++ لإضافة أنفسهم إليها
مجموعة من مجموعات الاختبار التي يديرها عداء الاختبار. يتم استخدام عداء الاختبار في القائمة
جميع الاختبارات المتاحة واختيار اختبار ليتم تشغيله. هذا فصل بسيط للغاية
يوفر ثلاث طرق ثابتة لتوفير أو إضافة مجموعات الاختبار والحصول عليها إلى ملف
مجموعة من الاختبارات. انظر doxygen للفصل ns3 :: TestRunner للتفاصيل.

اختبار التالي
الكل NS-3 يتم تصنيف الاختبارات إلى مجموعات الاختبار وحالات الاختبار. مجموعة الاختبار هي أ
مجموعة من حالات الاختبار التي تمارس تمامًا نوعًا معينًا من الوظائف. مثل
الموصوفة أعلاه ، يمكن تصنيف مجموعات الاختبار على أنها ،

· بناء اختبارات التحقق

· اختبارات الوحدة

· اختبارات النظام

· أمثلة

· اختبارات الأداء

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

سيحدد الكود التالي فئة جديدة يمكن تشغيلها بواسطة test.py كاختبار "وحدة"
مع الاسم المعروض ، اسم جناح الاختبار الخاص بي.

فئة MySuite: TestSuite العامة
{
الجمهور:
MyTestSuite () ،
};

MyTestSuite :: MyTestSuite ()
: TestSuite ("my-test-suite-name"، UNIT)
{
AddTestCase (جديد MyTestCase) ،
}

MyTestSuite myTestSuite ؛

تهتم الفئة الأساسية بكل عمليات التسجيل والتقارير المطلوبة لتكون سلعة
مواطن في إطار الاختبار.

اختبار الإطار
يتم إنشاء الاختبارات الفردية باستخدام فئة TestCase. النماذج الشائعة لاستخدام الاختبار
تتضمن الحالة "حالة اختبار واحدة لكل ميزة" ، و "حالة اختبار واحدة لكل طريقة". مخاليط من
يمكن استخدام هذه النماذج.

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

فئة MyTestCase: TestCase العام
{
MyTestCase () ،
الفراغ الظاهري DoRun (باطل) ؛
};

MyTestCase :: MyTestCase ()
: TestCase ("تحقق من بعض الوظائف")
{
}

باطل
MyTestCase :: DoRun (باطل)
{
NS_TEST_ASSERT_MSG_EQ (صحيح ، صحيح ، "بعض رسائل الفشل") ؛
}

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

لم يتم توثيق هذه الأدوات المساعدة هنا ، ولكن على سبيل المثال ، يرجى الاطلاع على كيفية اختبار TCP
عثر عليه في src / test / ns3tcp / استخدام ملفات pcap والإخراج المرجعي.

كيفية إلى اكتب اختبارات
الهدف الأساسي لمشروع ns-3 هو مساعدة المستخدمين على تحسين الصلاحية و
مصداقية نتائجها. هناك العديد من العناصر للحصول على نماذج صالحة و
المحاكاة والاختبار مكون رئيسي. إذا كنت تساهم في نماذج أو أمثلة ل
ns-3 ، قد يُطلب منك المساهمة برمز الاختبار. سيتم استخدام النماذج التي تساهم بها
لسنوات عديدة بواسطة أشخاص آخرين ، ربما ليس لديهم فكرة للوهلة الأولى عما إذا كان
النموذج صحيح. سيساعد رمز الاختبار الذي تكتبه لنموذجك على تجنب المستقبل
الانحدار في المخرجات وسوف تساعد المستخدمين في المستقبل في فهم التحقق و
حدود قابلية تطبيق النماذج الخاصة بك.

توجد طرق عديدة للتحقق من صحة تنفيذ النموذج. في هذا
نتمنى تغطية بعض الحالات الشائعة التي يمكن استخدامها كدليل لكتابة جديد
الاختبارات.

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

· ماذا سيطلق على مجموعة الاختبار

· ما نوع الاختبار الذي سيكون (اختبار التحقق من الإنشاء أو اختبار الوحدة أو اختبار النظام أو
تجربة أداء)

· المكان الذي سيعيش فيه رمز الاختبار (إما في وحدة ns-3 الحالية أو بشكل منفصل في
src / test / directory). سيكون عليك تحرير ملف wscript في هذا الدليل إلى
قم بتجميع التعليمات البرمجية الجديدة ، إذا كانت ملفًا جديدًا.

برنامج يسمى src / create-module.py هي نقطة انطلاق جيدة. يمكن أن يكون هذا البرنامج
استدعى مثل create-module.py جهاز التوجيه لوحدة افتراضية جديدة تسمى جهاز التوجيه. ذات مرة
تفعل هذا ، سترى ملف جهاز التوجيه الدليل ، و اختبار / router-test-suite.cc حزمة اختبار.
يمكن أن يكون هذا الملف نقطة انطلاق للاختبار الأولي الخاص بك. هذه مجموعة اختبار عمل ،
على الرغم من أن الاختبارات الفعلية التي يتم إجراؤها تافهة. انسخه إلى اختبار الوحدة الخاصة بك
الدليل ، وقم بإجراء استبدال عام لـ "جهاز التوجيه" في هذا الملف لشيء متعلق
إلى النموذج الذي تريد اختباره. يمكنك أيضًا تعديل أشياء مثل المزيد من الوصف
اسم حالة الاختبار.

تحتاج أيضًا إلى إضافة كتلة إلى ملف wscript الخاص بك للحصول على هذا الاختبار لتجميع:

Module_test.source = [
"test / router-test-suite.cc" ،
]

قبل أن تبدأ فعلاً في القيام بأشياء مفيدة ، قد يكون من المفيد محاولة تشغيل ملف
هيكل عظمي. تأكد من أن ns-3 قد تم تكوينه باستخدام خيار "اختبارات التمكين".
لنفترض أن مجموعة الاختبار الجديدة الخاصة بك تسمى "جهاز التوجيه" مثل هنا:

RouterTestSuite :: RouterTestSuite ()
: TestSuite ("router"، UNIT)

جرب هذا الأمر:

جهاز التوجيه $ ./test.py -s

يجب إنتاج المخرجات على النحو التالي:

PASS: جهاز توجيه TestSuite
تم اجتياز 1 من 1 اختبار (1 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

راجع src / lte / test / test-lte-antenna.cc للحصول على مثال عملي.

اختبار وحدات الماكرو
هناك عدد من وحدات الماكرو المتاحة للتحقق من إخراج برنامج الاختبار مع المتوقع
انتاج. يتم تعريف وحدات الماكرو هذه في src / core / model / test.h.

تتضمن المجموعة الرئيسية لوحدات الماكرو المستخدمة ما يلي:

NS_TEST_ASSERT_MSG_EQ (فعلي ، حد ، رسالة)
NS_TEST_ASSERT_MSG_NE (فعلية ، حد ، رسالة)
NS_TEST_ASSERT_MSG_LT (فعلية ، حد ، رسالة)
NS_TEST_ASSERT_MSG_GT (فعلية ، حد ، رسالة)
NS_TEST_ASSERT_MSG_EQ_TOL (فعلي ، حد ، tol ، msg)

الحجة الأولى يقدم هي القيمة قيد الاختبار ، القيمة الثانية قصر هو المتوقع
القيمة (أو القيمة المراد اختبارها مقابل) ، والوسيطة الأخيرة MSG هي رسالة الخطأ إلى
اطبع إذا فشل الاختبار.

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

أخيرًا ، هناك متغيرات من أعلاه حيث الكلمة الرئيسية ASSERT لقد بدل بواسطة توقع.
تم تصميم هذه المتغيرات خصيصًا للاستخدام في عمليات الاسترجاع (خاصة عمليات الاسترجاعات)
فارغ. احتفظ باستخدامها لعمليات الاسترجاعات التي تستخدمها في برامج الاختبار الخاصة بك ؛ خلاف ذلك ، استخدم
هيه ASSERT المتغيرات.

كيفية إلى تضيف an مثال برنامج إلى هيه تجربه بالعربي جناح
يمكن للمرء أن "اختبار الدخان" الذي يجمع الأمثلة وتشغيلها بنجاح حتى الاكتمال (بدون
تسرب الذاكرة) باستخدام ملف أمثلة إلى run.py البرنامج النصي الموجود في دليل اختبار الوحدة الخاصة بك.
باختصار ، من خلال تضمين مثيل من هذا الملف في دليل الاختبار الخاص بك ، يمكنك أن تتسبب في ظهور ملف
عداء اختبار لتنفيذ الأمثلة المدرجة. من الأفضل عادة التأكد من ذلك
حدد الأمثلة التي لها أوقات تشغيل قصيرة بشكل معقول حتى لا تعيق الاختبارات. يرى
المثال في src / lte / test / الدليل.

الاختبار لـ منطقية النتائج
الاختبار النتائج متى العشوائية is المشاركة
الاختبار الناتج البيانات ضد a معروف توزيع
توفير غير تافه إدخال ناقلات of البيانات
تخزين الرجوع غير تافه الناتج البيانات
تقديم لك الناتج تجربه بالعربي البيانات
الدعم الفني
خلق a جديد NS-3 نموذج
يستعرض هذا الفصل عملية تصميم ملف NS-3 نموذج. في العديد من الحالات البحثية ،
لن يكون المستخدمون راضين عن مجرد تكييف النماذج الحالية ، ولكنهم قد يرغبون في توسيع نطاق
جوهر المحاكاة بطريقة جديدة. سنستخدم مثال إضافة ErrorModel إلى ملف
بسيط NS-3 الرابط كمثال محفز لكيفية التعامل مع هذه المشكلة و
المضي قدما من خلال التصميم والتنفيذ.

NOTE:
توثيق

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

تصميم الرسالة
فكر في الطريقة التي تريدها أن تعمل بها ؛ ماذا يجب ان تفعل. فكر في هذه الأشياء:

· وظائف: ما هي الوظائف التي يجب أن تتمتع بها؟ ما هي السمات أو التكوين
يتعرض للمستخدم؟

· إعادة الاستخدام: كم يجب أن يتمكن الآخرون من إعادة استخدام تصميمي؟ هل يمكنني إعادة استخدام الرمز من
NS-2 للبدء؟ كيف يقوم المستخدم بدمج النموذج مع باقي النموذج الآخر
محاكاة؟

· التبعيات: كيف يمكنني تقليل إدخال التبعيات الخارجية على الكود الجديد الخاص بي
قدر الإمكان (لجعلها أكثر نمطية)؟ على سبيل المثال ، هل يجب أن أتجنب أي منها
الاعتماد على IPv4 إذا كنت أرغب في استخدامه أيضًا بواسطة IPv6؟ هل يجب أن أتجنب أي تبعية
على IP على الإطلاق؟

لا تتردد في الاتصال بـ ns-3-المستخدمين or NS- المطورين قائمة إذا كان لديك أسئلة.
على وجه الخصوص ، من المهم التفكير في واجهة برمجة التطبيقات العامة لنموذجك الجديد وطلبها
تعليق. كما أنه يساعد في السماح للآخرين بمعرفة عملك في حال كنت مهتمًا به
المتعاونين.

على سبيل المثال: ErrorModel
يوجد نموذج خطأ في NS-2. يسمح بتمرير الحزم إلى كائن ذي حالة
يحدد ، بناءً على متغير عشوائي ، ما إذا كانت الحزمة تالفة. يمكن للمتصل
ثم قرر ما يجب فعله بالحزمة (قم بإسقاطها ، وما إلى ذلك).

واجهة برمجة التطبيقات (API) الرئيسية لنموذج الخطأ هي وظيفة لتمرير حزمة إلى ، وقيمة الإرجاع
هذه الوظيفة هي قيمة منطقية تخبر المتصل بحدوث أي فساد. ملحوظة
أنه وفقًا لنموذج الخطأ ، قد يكون المخزن المؤقت لحزمة البيانات تالفًا أو غير تالف.
دعنا نسمي هذه الوظيفة "IsCorrupt ()".

حتى الآن ، في تصميمنا ، لدينا:

فئة ErrorModel
{
الجمهور:
/ **
* \ ترجع صحيحًا إذا تم اعتبار الحزمة خاطئة / تالفة
* \ param pkt Packet لتطبيق نموذج الخطأ على
*/
منطقية IsCorrupt (Ptr pkt) ؛
};

لاحظ أننا لا نمرر مؤشر ثابت ، مما يسمح للوظيفة بتعديل
packet إذا عاد IsCorrupt () صحيحًا. لن تقوم جميع نماذج الأخطاء بتعديل الحزمة بالفعل ؛
يجب توثيق ما إذا كان المخزن المؤقت لحزمة البيانات تالفًا أم لا.

قد نحتاج أيضًا إلى إصدارات متخصصة من هذا ، مثل في NS-2، لذلك على الرغم من أنه ليس ملف
فقط اختيار التصميم لتعدد الأشكال ، نفترض أننا سنصنف فئة أساسية
ErrorModel للفئات المتخصصة ، مثل RateErrorModel ، ListErrorModel ، إلخ ، مثل
يتم في NS-2.

قد تفكر في هذه المرحلة ، "لماذا لا تجعل IsCorrupt () طريقة افتراضية؟". إنه
نهج واحد؛ والآخر هو جعل الوظيفة العامة غير الافتراضية غير مباشرة من خلال أ
الوظيفة الافتراضية الخاصة (تُعرف هذه في C ++ باسم لغة الواجهة غير الظاهرية وهي
المعتمد في NS-3 فئة ErrorModel).

بعد ذلك ، هل يجب أن يكون لهذا الجهاز أي تبعيات على IP أو بروتوكولات أخرى؟ نحن لا نريد
لإنشاء تبعيات على بروتوكولات الإنترنت (يجب أن يكون نموذج الخطأ قابلاً للتطبيق على
بخلاف بروتوكولات الإنترنت أيضًا) ، لذلك سنضع ذلك في الاعتبار لاحقًا.

اعتبار آخر هو كيف ستشمل الكائنات نموذج الخطأ هذا. نحن نتصور وضع
واضعًا صريحًا في بعض تطبيقات NetDevice ، على سبيل المثال:

/ **
* إرفاق تلقي ErrorModel إلى PointToPointNetDevice.
*
* قد يشتمل PointToPointNetDevice اختياريًا على ErrorModel بتنسيق
* سلسلة استلام الحزمة.
*
* انظر ErrorModel
*param em Ptr إلى ErrorModel.
*/
باطل PointToPointNetDevice :: SetReceiveErrorModel (Ptr م) ؛

مرة أخرى ، ليس هذا هو الخيار الوحيد الذي لدينا (يمكن تجميع نماذج الخطأ في الكثير من
كائنات أخرى) ، لكنها تلبي حالة الاستخدام الأساسية لدينا ، وهي السماح للمستخدم بالقوة
أخطاء في عمليات إرسال الحزم الناجحة ، على مستوى NetDevice.

بعد بعض التفكير والنظر في القائمة NS-2 رمز ، هنا نموذج API للقاعدة
الفئة والفئة الفرعية الأولى التي يمكن نشرها للمراجعة الأولية:

فئة ErrorModel
{
الجمهور:
ErrorModel () ،
افتراضي ~ ErrorModel () ؛
منطقية IsCorrupt (Ptr pkt) ؛
إعادة تعيين باطلة (باطلة) ؛
تمكين باطل (باطل) ؛
تعطيل باطل (باطل) ؛
منطقي IsEnabled (باطل) const ؛
خاص:
منطقية افتراضية DoCorrupt (Ptr pkt) = 0 ؛
DoReset الظاهري باطل (باطل) = 0 ؛
};

تعداد ErrorUnit
{
EU_BIT ،
EU_BYTE ،
EU_PKT
};

// تحديد الحزم التي بها خطأ والتي تتوافق مع أحد العناصر الأساسية
// التوزيع العشوائي المتغير ومعدل الخطأ ووحدة المعدل.
فئة RateErrorModel: العامة ErrorModel
{
الجمهور:
RateErrorModel () ،
افتراضي ~ RateErrorModel () ؛
تعداد ErrorUnit GetUnit (باطل) const ؛
SetUnit باطلة (تعداد ErrorUnit error_unit) ؛
مزدوج GetRate (باطل) const ؛
SetRate باطلة (معدل مزدوج) ؛
باطل SetRandomVariable (const RandomVariable & ranvar) ؛
خاص:
منطقية افتراضية DoCorrupt (Ptr pkt) ؛
DoReset الظاهري باطل (باطل) ؛
};

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

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

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

التقييم هيه NS-3 البرمجة الطراز وثيقة
في هذه المرحلة ، قد ترغب في التوقف وقراءة ملف NS-3 وثيقة أسلوب الترميز ، على وجه الخصوص
إذا كنت تفكر في المساهمة في إعادة الكود الخاص بك إلى المشروع. أسلوب الترميز
المستند مرتبط من صفحة المشروع الرئيسية: NS-3 Coding نمط.

يقرر في in هيه مصدر شجرة هيه الموديل وينبغي يقيم
كل من NS-3 نموذج التعليمات البرمجية المصدر في الدليل SRC /. سوف تحتاج إلى اختيار أي منها
دليل فرعي يتواجد فيه. إذا كان رمزًا نموذجيًا جديدًا من نوع ما ، فمن المنطقي وضعه
في SRC / الدليل في مكان ما ، خاصة لسهولة الدمج مع البنية
نظام.

في حالة نموذج الخطأ ، يرتبط ارتباطًا وثيقًا بفئة الحزمة ، لذا فمن المنطقي
لتنفيذ هذا في src / شبكة / الوحدة حيث NS-3 يتم تنفيذ الحزم.

WAF com.wscript
NS-3 يستخدم WAF نظام البناء. سوف ترغب في دمج ملف NS-3 يستخدم Waf
نظام البناء. سترغب في دمج ملفات المصدر الجديدة في هذا النظام. هذا
يتطلب أن تضيف ملفاتك إلى ملف com.wscript تم العثور على ملف في كل دليل.

لنبدأ بالملفات الفارغة error-model.h و error-model.cc ، ونضيف هذا إلى
src / شبكة / wscript. إنها في الحقيقة مجرد مسألة إضافة ملف .cc إلى باقي ملفات
الملفات المصدر وملف .h إلى قائمة ملفات الرأس.

الآن ، انبثق إلى دليل المستوى الأعلى واكتب "./test.py". لا يجب أن تنكسر
أي شيء بهذه العملية.

تضمن حراس
بعد ذلك ، دعنا نضيف البعض تتضمن حراس في ملف الرأس لدينا:

#ifndef ERROR_MODEL_H
#تعريف ERROR_MODEL_H

#endif

مساحة الاسم ns3
NS-3 يستخدم NS-3 مساحة الاسم لعزل رموزه عن مساحات الأسماء الأخرى. عادة ، أ
سيضع المستخدم بعد ذلك NS-3 كتلة مساحة الاسم في كل من ملف cc و h:

مساحة الاسم ns3 {

}

في هذه المرحلة ، لدينا بعض الملفات الهيكلية التي يمكننا من خلالها البدء في تحديد فئاتنا الجديدة.
ملف الرأس يبدو كالتالي:

#ifndef ERROR_MODEL_H
#تعريف ERROR_MODEL_H

مساحة الاسم ns3 {

} // مساحة الاسم ns3
#endif

في حين أن نموذج خطأ يبدو الملف ببساطة كالتالي:

# تضمين "error-model.h"

مساحة الاسم ns3 {

} // مساحة الاسم ns3

يجب تجميع هذه الملفات نظرًا لعدم احتوائها بالفعل على أي محتويات. نحن الآن جاهزون لذلك
ابدأ في إضافة الفصول.

في البداية تطبيق
في هذه المرحلة ، ما زلنا نعمل على بعض السقالات ، لكن يمكننا البدء في تحديد
فئات ، مع الوظيفة التي ستضاف لاحقًا.

يرث تبدأ من هيه هدف فصل؟
هذه خطوة تصميم مهمة ؛ سواء لاستخدام الطبقة هدف كفئة أساسية لجهازك الجديد
الطبقات.

كما هو موضح في الفصل الخاص بـ NS-3 نموذج الكائن ، الفئات التي ترث من الطبقة
هدف احصل على خصائص خاصة:

· ال NS-3 النوع ونظام السمات (انظر السمات)

· نظام تجميع الكائنات

· نظام عد مرجعي ذو مؤشر ذكي (فئة Ptr)

الفئات المشتقة من الطبقة ObjectBase} احصل على أول خاصيتين أعلاه ، لكن لا تفعل ذلك
الحصول على مؤشرات ذكية. الفئات المشتقة من الطبقة RefCountBase احصل فقط على المؤشر الذكي
نظام العد المرجعي.

في الممارسة ، الطبقة هدف هو متغير الثلاثة أعلاه NS-3 المطور سوف
الأكثر شيوعًا.

في حالتنا ، نريد الاستفادة من نظام السمات ، وسنمرر الأمثلة
من هذا الكائن عبر NS-3 API العامة ، لذلك من الدرجة هدف مناسب لنا.

في البداية فصول دراسية
تتمثل إحدى طرق المتابعة في البدء بتحديد الحد الأدنى من الوظائف ومعرفة ما إذا كانت ستفعل ذلك
تجميع. دعنا نراجع كل ما هو مطلوب لتنفيذه عندما نستمد من فئة Object:

#ifndef ERROR_MODEL_H
#تعريف ERROR_MODEL_H

# تضمين "ns3 / object.h"

مساحة الاسم ns3 {

فئة ErrorModel: public Object
{
الجمهور:
TypeId ثابت GetTypeId (باطل) ؛

ErrorModel () ،
افتراضي ~ ErrorModel () ؛
};

فئة RateErrorModel: العامة ErrorModel
{
الجمهور:
TypeId ثابت GetTypeId (باطل) ؛

RateErrorModel () ،
افتراضي ~ RateErrorModel () ؛
};
#endif

بعض الأشياء التي يجب ملاحظتها هنا. نحن بحاجة لتضمين وجوه. الاتفاقية في NS-3 هل هذا إذا
ملف الرأس موجود في نفس الدليل ، ويمكن تضمينه بدون أي مسار
بادئة. لذلك ، إذا كنا نطبق ErrorModel في src / core / model دليل ، نحن
كان من الممكن أن يقول "تتضمن # "object.h"". لكننا في src / الشبكة / النموذج، لذلك يجب علينا
أدرجها كـ "تتضمن # "ns3 / object.h"". لاحظ أيضًا أن هذا يذهب خارج نطاق الاسم
إعلان.

ثانيًا ، يجب على كل فئة تنفيذ وظيفة ثابتة للعضو العام تسمى GetTypeId (فارغ).

ثالثًا ، إنها فكرة جيدة أن تقوم بتنفيذ المنشئات والمدمرين بدلاً من السماح لـ
يقوم المترجم بتوليدها ، ولجعل أداة التدمير افتراضية. في C ++ ، لاحظ أيضًا تلك النسخة
يتم إنشاء عامل التعيين ومُنشئ النسخ تلقائيًا إذا لم يتم تعريفهما ، لذلك
إذا كنت لا تريد هؤلاء ، فيجب عليك تنفيذهم كأعضاء خاصين. هذا الجانب من
تمت مناقشة C ++ في كتاب Effective C ++ الخاص بـ Scott Meyers. البند 45.

دعنا الآن نلقي نظرة على بعض التعليمات البرمجية المطابقة لتطبيق الهيكل العظمي في ملف .cc:

# تضمين "error-model.h"

مساحة الاسم ns3 {

NS_OBJECT_ENSURE_REGISTERED (ErrorModel) ،

TypeId ErrorModel :: GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("ns3 :: ErrorModel")
.SetParent ()
;
عودة المد
}

ErrorModel :: ErrorModel ()
{
}

ErrorModel :: ~ ErrorModel ()
{
}

NS_OBJECT_ENSURE_REGISTERED (RateErrorModel) ،

TypeId RateErrorModel :: GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("ns3 :: RateErrorModel")
.SetParent ()
.AddConstructor ()
;
عودة المد
}

RateErrorModel :: RateErrorModel ()
{
}

RateErrorModel :: ~ RateErrorModel ()
{
}

ما هو GetTypeId (فارغ) وظيفة؟ هذه الوظيفة تقوم ببعض الأشياء. يسجل أ
سلسلة فريدة في نظام TypeId. يحدد التسلسل الهرمي للكائنات في
نظام السمة (عبر Setparent). ويعلن أيضًا أنه يمكن إنشاء كائنات معينة عبر
إطار عمل إنشاء الكائن (AddConstructor).

الماكرو NS_OBJECT_ENSURE_REGISTERED (اسم الفئة) هناك حاجة أيضًا مرة واحدة لكل فصل دراسي
يعرّف طريقة GetTypeId جديدة ، ويقوم بالتسجيل الفعلي للفئة في ملف
نظام. يناقش فصل نموذج الكائن هذا بمزيد من التفصيل.

بما فيه خارجي ملفات
تسجيل الدعم الفني
هنا، اكتب a بت عن الصابون مضيفا | ns3 | تسجيل وحدات الماكرو. ملاحظات أن LOG_COMPONENT_DEFINE is
فعل في الخارج هيه مساحة الاسم ns3

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

أضف Basic الدعم الفني in هيه مبوبة
/ * من نقطة إلى نقطة-net-device.h * /
فئة ErrorModel ؛

/ **
* نموذج خطأ لتلقي أحداث الحزمة
*/
Ptr m_receiveErrorModel ؛

أضف الموصل
باطل
PointToPointNetDevice :: SetReceiveErrorModel (Ptr م)
{
NS_LOG_FUNCTION (هذا << م) ؛
m_receiveErrorModel = م ؛
}

.AddAttribute ("ReceiveErrorModel"،
"نموذج خطأ جهاز الاستقبال المستخدم لمحاكاة فقد الحزمة" ،
PointerValue () ،
MakePointerAccessor (& PointToPointNetDevice :: m_receiveErrorModel) ،
MakePointerChecker ())

راسيا إلى هيه
باطل PointToPointNetDevice :: تلقي (Ptr رزمة)
{
NS_LOG_FUNCTION (هذه << الحزمة) ؛
بروتوكول uint16_t = 0 ؛

إذا (m_receiveErrorModel && m_receiveErrorModel-> IsCorrupt (packet))
{
//
// إذا كان لدينا نموذج خطأ ويشير إلى أن الوقت قد حان لفقد ملف
// حزمة تالفة ، لا تعيد توجيه هذه الحزمة ، دعها تذهب.
//
m_dropTrace (حزمة) ؛
}
آخر
{
//
// ضرب خطاف الاستلام ، قم بإزالة رأس بروتوكول نقطة إلى نقطة
// وإعادة توجيه هذه الحزمة إلى مكدس البروتوكول.
//
m_rxTrace (حزمة) ؛
رأس العملية (الحزمة ، البروتوكول) ؛
m_rxCallback (هذه الحزمة بروتوكول GetRemote ()) ؛
إذا (! m_promiscCallback.IsNull ())
{m_promiscCallback (هذه ، حزمة ، بروتوكول ، GetRemote () ،
GetAddress () ، NetDevice :: PACKET_HOST) ،
}
}
}

إنشاء فارغة الأداء الوظيفي سيناريو
/ * simple-error-model.cc * /

// نموذج الخطأ
// نريد إضافة نموذج خطأ إلى NetDevice الخاص بالعقدة 3
// يمكننا الحصول على مقبض لـ NetDevice عبر القناة والعقدة
// مؤشرات
Ptr nd3 = PointToPointTopology :: GetNetDevice
(ن 3 ، قناة 2) ؛
Ptr م = إنشاء () ؛
nd3-> SetReceiveErrorModel (em) ؛

منطقي
ErrorModel :: DoCorrupt (حزمة & p)
{
NS_LOG_FUNCTION ،
NS_LOG_UNCOND ("فاسد!") ؛
عودة كاذبة.
}

في هذه المرحلة ، يمكننا تشغيل البرنامج باستخدام ErrorModel التافه الخاص بنا في الاستلام
مسار PointToPointNetDevice. تطبع السلسلة "تالف!" لكل علبة
تلقى في العقدة n3. بعد ذلك ، نعود إلى نموذج الخطأ لإضافة فئة فرعية تعمل
نمذجة خطأ أكثر إثارة للاهتمام.

أضف a فئة فرعية
لا تقوم الفئة الأساسية التافهة ErrorModel بأي شيء مثير للاهتمام ، ولكنها توفر امتداد
واجهة فئة أساسية مفيدة (Corrupt () و Reset ()) ، يتم إعادة توجيهها إلى الوظائف الافتراضية التي
يمكن تصنيفها فرعيًا. لنفكر بعد ذلك في ما نسميه BasicErrorModel الذي يعتمد على
هيه NS-2 فئة ErrorModel (بتنسيق ns-2 / queue / errmodel. {cc، h}).

ما الخصائص التي نريدها من منظور واجهة المستخدم؟ نحن نريد أو نحب
ليتمكن المستخدم من تبديل نوع ErrorModel المستخدم في ملف
NetDevice. نود أيضًا القدرة على تعيين معلمات قابلة للتكوين.

فيما يلي بعض المتطلبات البسيطة التي سنأخذها في الاعتبار:

· القدرة على تحديد المتغير العشوائي الذي يحكم الخسائر (الافتراضي هو UniformVariable)

· القدرة على ضبط الوحدة (بت ، بايت ، رزمة ، وقت) من الدقة التي توجد بها الأخطاء
مطبقة.

· القدرة على تحديد معدل الأخطاء (على سبيل المثال 10 ^ -3) المقابلة للوحدة أعلاه
تقسيمات.

القدرة على التمكين / التعطيل (الافتراضي ممكّن)

كيفية إلى فئة فرعية
نعلن أن BasicErrorModel فئة فرعية من ErrorModel على النحو التالي:

فئة BasicErrorModel: العامة ErrorModel
{
الجمهور:
TypeId ثابت GetTypeId (باطل) ؛

خاص:
// تنفيذ وظائف افتراضية خالصة من الفئة الأساسية
منطقية افتراضية DoCorrupt (Ptr ع) ؛
منطقي افتراضي DoReset (باطل) ؛

}

وتكوين وظيفة GetTypeId للفئة الفرعية عن طريق تعيين سلسلة TypeId فريدة و
تعيين الأصل إلى ErrorModel:

TypeId RateErrorModel :: GetTypeId (باطل)
{
ثابت TypeId tid = TypeId ("ns3 :: RateErrorModel")
.SetParent ()
.AddConstructor ()


البناء جوهر وظائف وحدة اختبارات
أكد وحدات الماكرو
نادي الكتابة وحدة اختبارات
إضافة a جديد وحدة إلى NS-3
عندما تقوم بإنشاء مجموعة من الفئات والأمثلة والاختبارات ذات الصلة ، يمكن أن تكون كذلك
معًا في ملف NS-3 الوحدة النمطية بحيث يمكن استخدامها مع الموجودة NS-3 نماذج
وباحثين آخرين.

يرشدك هذا الفصل خلال الخطوات اللازمة لإضافة وحدة نمطية جديدة إليها NS-3.

خطوة 0 - وحدة تصميم
يمكن العثور على جميع الوحدات في ملف SRC الدليل. يمكن العثور على كل وحدة في دليل
التي لها نفس اسم الوحدة. على سبيل المثال ، ملف طيف يمكن العثور على الوحدة النمطية هنا:
src / الطيف. سنقتبس من طيف وحدة للتوضيح.

تحتوي الوحدة النمطية الأولية على بنية الدليل التالية والملفات المطلوبة:

SRC /
اسم وحدة/
الارتباطات /
وثيقة /
أمثلة/
com.wscript
المساعد/
نموذج/
اختبار/
أمثلة إلى run.py
com.wscript

لن تكون جميع الأدلة موجودة في كل وحدة.

خطوة 1 - إنشاء a وحدة هيكل عظمى
يتم توفير برنامج python في دليل المصدر الذي سيُنشئ هيكلًا عظميًا لملف
وحدة. لأغراض هذه المناقشة ، سنفترض أنه تم استدعاء الوحدة الجديدة الخاصة بك
وحدة جديدة. من SRC الدليل ، قم بما يلي لإنشاء الوحدة الجديدة:

$ ./create-module.py وحدة جديدة

المقبل، cd إلى وحدة جديدة؛ ستجد تخطيط الدليل هذا:

وحدة جديدة $ cd
ليرة سورية
أمثلة doc نموذج مساعد اختبار wscript

بمزيد من التفصيل ، فإن ملف create-module.py سينشئ البرنامج النصي الدلائل وكذلك الأولية
هيكل عظمي com.wscript, .h, . سم مكعب .أولا الملفات. الوحدة الكاملة مع ملفات الهيكل العظمي تبدو
مثله:

SRC /
وحدة جديدة /
وثيقة /
وحدة جديدة
أمثلة/
new-module-example.cc
com.wscript
المساعد/
new-module-helper.cc
مساعد وحدة جديدة
نموذج/
new-module.cc
وحدة جديدة
اختبار/
وحدة اختبار جديدة-suite.cc
com.wscript

(إذا لزم الأمر الارتباطات / الدليل مدرج في خطوة 0 سيتم إنشاؤه تلقائيًا أثناء
البناء.)

ننتقل بعد ذلك إلى كيفية تخصيص هذه الوحدة. إعلام WAF حول الملفات التي
تشكل الوحدة النمطية الخاصة بك عن طريق تحرير الاثنين com.wscript الملفات. سوف نسير من خلال
الخطوات الرئيسية في هذا الفصل.

الكل NS-3 وحدات تعتمد على النواة وحدة وعادة على وحدات أخرى. هذه التبعية
محدد في com.wscript ملف (في المستوى العلوي للوحدة ، وليس ملف com.wscript
ملف في أمثلة الدليل!). في الهيكل العظمي com.wscript المكالمة التي ستعلن
وحدة جديدة ل WAF سيبدو هكذا (قبل التحرير):

بناء def (bld):
module = bld.create_ns3_module ('new-module'، ['core'])

لنفترض ذلك وحدة جديدة يعتمد على الإنترنت, التنقلو com.aodv الوحدات. بعد
تحريره com.wscript يجب أن يبدو الملف بالشكل:

بناء def (bld):
module = bld.create_ns3_module ('new-module'، ['internet'، 'mobility'، 'aodv'])

لاحظ أنه يجب إدراج تبعيات وحدة المستوى الأول فقط ، ولهذا السبب قمنا بإزالتها
النواة؛ ال الإنترنت وحدة تعتمد بدوره على النواة.

من المرجح أن تحتوي الوحدة النمطية الخاصة بك على ملفات مصدر نموذجية. الهياكل العظمية الأولية (التي سوف
تجميع بنجاح) في نموذج / new-module.cc نموذج / وحدة جديدة.

إذا كانت الوحدة النمطية الخاصة بك ستحتوي على ملفات مصدر مساعدة ، فسوف ينتقلون إلى ملف المساعد/
الدليل؛ مرة أخرى ، يتم إنشاء الهياكل الأولية في هذا الدليل.

أخيرًا ، من الممارسات الجيدة كتابة الاختبارات والأمثلة. سيكون من شبه المؤكد أن هذه
مطلوبة للوحدات الجديدة ليتم قبولها في المسؤول NS-3 شجرة المصدر. هيكل عظمي
تم إنشاء مجموعة الاختبار وحالة الاختبار في اختبار/ الدليل. سوف جناح اختبار الهيكل العظمي
تحتوي على المُنشئ أدناه ، والذي يعلن عن اختبار وحدة جديد يسمى وحدة جديدة، مع
حالة اختبار واحدة تتكون من الفصل NewModuleTestCase1:

NewModuleTestSuite :: NewModuleTestSuite ()
: TestSuite ("new-module"، UNIT)
{
AddTestCase (جديد NewModuleTestCase1) ،
}

خطوة 3 - أعلن مصدر ملفات
يجب تحديد الرأس العام وملفات التعليمات البرمجية المصدر للوحدة النمطية الجديدة في ملف
com.wscript ملف عن طريق تعديله باستخدام محرر النصوص الخاص بك.

على سبيل المثال ، بعد إعلان طيف الوحدة النمطية src / الطيف / wscript يحدد
ملفات التعليمات البرمجية المصدر مع القائمة التالية:

بناء def (bld):

module = bld.create_ns3_module ("طيف" ، ["إنترنت" ، "انتشار" ، "هوائي" ، "تطبيقات"])

الوحدة النمطية المصدر = [
"model / range-model.cc" ،
"model / range-value.cc" ،
.
.
.
"model / wave-oven-spectrum-value-helper.cc" ،
"مساعد / طيف-helper.cc" ،
'helper / adhoc-aloha-noack-ideal-phy-helper.cc'،
"helper / waveform-generator-helper.cc"،
"المساعد / التحليل الطيفي-helper.cc" ،
]

سيتم تجميع الكائنات الناتجة عن تجميع هذه المصادر في مكتبة ارتباط ،
والتي سيتم ربطها بأي برامج تعتمد على هذه الوحدة.

ولكن كيف تتعلم مثل هذه البرامج واجهة برمجة التطبيقات العامة لوحدتنا الجديدة؟ واصل القراءة!

خطوة 4 - أعلن عام رأس ملفات
يجب أيضًا أن تكون ملفات الرأس التي تحدد واجهة برمجة التطبيقات العامة لنموذجك والمساعدات
المحدد في com.wscript ملف.

استمرار مع طيف النموذج التوضيحي ، يتم تحديد ملفات الرأس العامة
مع المقطع التالي. (لاحظ أن الحجة ل بناية تحكي الوظيفة WAF إلى
تثبيت رؤوس هذه الوحدة مع الآخر NS-3 رؤوس):

headers = bld (features = 'ns3header')

headers.module = "طيف"

الرؤوس المصدر = [
"نموذج / نموذج طيف. h" ،
"نموذج / قيمة الطيف. h"،
.
.
.
"النموذج / فرن الميكروويف الطيف قيمة المساعد. h" ،
"المساعد / مساعد الطيف. h"،
"helper / adhoc-aloha-noack-perfect-phy-helper.h ''،
"المساعد / الموجي-المولد-المساعد. h" ،
"المساعد / محلل الطيف المساعد. h" ،
]

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

# تضمين "ns3 / range-model.h"

لا يجب تضمين الرؤوس المستخدمة داخليًا بشكل صارم في التنفيذ هنا. هم
لا يزال في متناول التنفيذ الخاص بك من خلال تضمين عبارات مثل

# تضمين "my-module-Implementation.h"

خطوة 5 - أعلن اختبارات
إذا كانت الوحدة الجديدة الخاصة بك بها اختبارات ، فيجب تحديدها في ملف com.wscript ملف بواسطة
تعديله باستخدام محرر النصوص الخاص بك.

إنّ طيف اختبارات النموذج محددة بالمقطع التالي:

module_test = bld.create_ns3_module_test_library ("طيف")

Module_test.source = [
"test / range-interference-test.cc"،
"test / range-value-test.cc"،
]

يرى اختبارات لمزيد من المعلومات حول كيفية كتابة حالات الاختبار.

خطوة 6 - أعلن أمثلة
إذا كانت الوحدة الجديدة الخاصة بك تحتوي على أمثلة ، فيجب تحديدها في ملف أمثلة / wscript
ملف. (الهيكل العظمي من المستوى الأعلى com.wscript سوف تشمل بشكل متكرر أمثلة / wscript فقط اذا
تم تمكين الأمثلة في وقت التكوين.)

إنّ طيف النموذج يعرّف أنه المثال الأول في src / طيف / أمثلة / wscript مع

بناء def (bld):
obj = bld.create_ns3_program ('adhoc-aloha-perfect-phy'،
["طيف" ، "تنقل"])
obj.source = 'adhoc-aloha-ideal-phy.cc'

لاحظ أن الوسيطة الثانية للدالة create_ns3_program () هي قائمة الوحدات
أن البرنامج الذي يتم إنشاؤه يعتمد على ؛ مرة أخرى ، لا تنس أن تدرج وحدة جديدة in
القائمة. من أفضل الممارسات سرد تبعيات الوحدة المباشرة فقط ، والسماح لـ WAF
استنتج شجرة التبعية الكاملة.

من حين لآخر ، من أجل الوضوح ، قد ترغب في تقسيم التنفيذ على سبيل المثال الخاص بك بين
عدة ملفات المصدر. في هذه الحالة ، قم فقط بتضمين تلك الملفات كملفات صريحة إضافية
مصادر المثال:

obj = bld.create_ns3_program ('new-module-example'، [new-module])
obj.source = ['new-module-example.cc'، 'new-module-example-part.cc']

يتم تحديد أمثلة Python باستخدام استدعاء الوظيفة التالي. لاحظ أن الثانية
حجة للدالة register_ns3_script () هي قائمة الوحدات التي يستخدمها بايثون
المثال يعتمد على:

bld.register_ns3_script ('new-module-example.py'، ['new-module'])

خطوة 7 - أمثلة يجري as اختبارات
بالإضافة إلى تشغيل كود الاختبار الصريح ، يمكن أيضًا تصميم إطار الاختبار
قم بتشغيل برامج الأمثلة الكاملة لمحاولة اكتشاف الانحدارات في الأمثلة. ومع ذلك ، ليس كل شيء
أمثلة مناسبة لاختبارات الانحدار. الملف اختبار / أمثلة إلى run.py تسيطر على
استدعاء الأمثلة عند تشغيل إطار الاختبار.

إنّ طيف نماذج تشغيل بواسطة test.py محددة في
src / الطيف / الاختبار / أمثلة- to-run.py باستخدام القائمتين التاليتين من C ++ و Python
أمثلة:

# قائمة بأمثلة C ++ للتشغيل من أجل ضمان بقائها
# قابل للبناء وقابل للتشغيل بمرور الوقت. كل مجموعة في القائمة تحتوي على
#
# (example_name، do_run، do_valgrind_run).
#
# انظر test.py لمزيد من المعلومات.
cpp_examples = [
("adhoc-aloha-perfect-phy"، "True"، "True")،
("adhoc-aloha-perfect-phy-with-micro-oven"، "True"، "True")،
("adhoc-aloha-perfect-phy-matrix-propagation-loss-model"، "True"، "True") ،
]

# قائمة بأمثلة Python للتشغيل لضمان بقائها
# قابل للتشغيل بمرور الوقت. كل مجموعة في القائمة تحتوي على
#
# (example_name، do_run).
#
# انظر test.py لمزيد من المعلومات.
أمثلة بايثون = [
("sample-simulator.py"، "True") ،
]

كما هو موضح في التعليق ، يحتوي كل إدخال في قائمة أمثلة C ++ للتشغيل على ملحق
الصفوف (tuple) (اسم_المثال ، do_run ، do_valgrind_run)، حيث

· example_name هو الملف القابل للتنفيذ ليتم تشغيله ،

· do_run هو شرط لتشغيل المثال تحته ، و

· do_valgrind_run هو شرط لتشغيل المثال تحت valgrind. (هذا
هناك حاجة لأن NSC يتسبب في تعطل التعليمات غير القانونية مع بعض الاختبارات عند حدوث ذلك
يتم تشغيلها تحت valgrind.)

لاحظ أن الشرطين عبارة عن عبارات بايثون يمكن أن تعتمد عليها WAF ترتيب
المتغيرات. على سبيل المثال،

("tcp-nsc-lfn"، "NSC_ENABLED == True"، "NSC_ENABLED == False") ،

يحتوي كل إدخال في قائمة أمثلة Python المراد تشغيلها على tuple (اسم_المثال ،
افعل_تشغيل)، حيث ، بالنسبة لأمثلة C ++ ،

· example_name هو نص Python الذي سيتم تشغيله ، و

· do_run هو شرط لتشغيل المثال تحته.

مرة أخرى ، الشرط عبارة عن بيان بايثون يمكن أن يعتمد عليه WAF متغيرات التكوين.
على سبيل المثال،

("realtime-udp-echo.py"، "ENABLE_REAL_TIME == خطأ") ،

خطوة 8 - ضبط البناء
يمكنك الآن تكوين وبناء واختبار الوحدة النمطية الخاصة بك كالمعتاد. يجب إعادة تكوين ملف
المشروع كخطوة أولى بحيث WAF يخزن المعلومات الجديدة مؤقتًا في ملف com.wscript الملفات أو
وإلا فلن يتم تضمين الوحدة الجديدة الخاصة بك في البناء.

تكوين $ ./waf - أمثلة قابلة للتمكين - اختبارات التمكين
$ ./waf بناء
$ ./test.py

ابحث عن مجموعة اختبار الوحدة الجديدة الخاصة بك (وبرامج الأمثلة ، إذا كانت الوحدة الخاصة بك تحتوي على أي منها
ممكّن) في إخراج الاختبار.

خطوة 9 - Python الارتباطات
تعد إضافة روابط Python إلى الوحدة النمطية الخاصة بك أمرًا اختياريًا ، ويتم التعليق على الخطوة بواسطة
الافتراضي في create-module.py النصي.

# bld.ns3_python_bindings ()

إذا كنت تريد تضمين روابط Python (مطلوبة فقط إذا كنت تريد كتابة Python ns-3
بدلاً من برامج C ++ ns-3) ، يجب إلغاء التعليق أعلاه وتثبيت ملف
نظام فحص Python API (مغطى في مكان آخر في هذا الدليل) وقم بمسح الوحدة النمطية الخاصة بك إلى
إنشاء روابط جديدة.

خلق توثيق
NS-3 يوفر نوعين من التوثيق: فصول أسلوب العرض "دليل المستخدم" ، و
وثائق API التعليمات البرمجية المصدر.

تمت كتابة فصول "دليل المستخدم" يدويًا reStructuredText شكل (.أولا)، الذي
تمت معالجتها بواسطة نظام توثيق Python أبو الهول لإنشاء صفحات الويب وملفات pdf.
يتم إنشاء وثائق API من التعليمات البرمجية المصدر نفسها ، باستخدام Doxygen، لتوليد
صفحات الويب المتقاطعة. كلاهما مهم: فصول أبو الهول تشرح لماذا
ونظرة عامة على استخدام النموذج ؛ تشرح وثائق API كيف تفاصيل.

يقدم هذا الفصل نظرة عامة سريعة على هذه الأدوات ، مع التركيز على الاستخدام المفضل و
التخصيصات لـ NS-3.

لإنشاء جميع الوثائق القياسية:

مستندات $ ./waf

لمزيد من الخيارات المتخصصة ، تابع القراءة.

توثيق مع أبو الهول
نستخدم أبو الهول لإنشاء فصول عرضية تصف تصميم واستخدام كل منها
وحدة. الآن أنت تقرأ توثيق الفصل. ال عرض مصدر الارتباط في
سيظهر لك الشريط الجانبي مصدر reStructuredText لهذا الفصل.

إضافة جديد فصول
تتطلب إضافة فصل جديد ثلاث خطوات (موضحة بمزيد من التفصيل أدناه):

1. اختار أين؟ سيعيش ملف (ملفات) التوثيق.

2. الرابط من صفحة موجودة إلى الوثائق الجديدة.

3. أضف الملف الجديد إلى ملف ماكيفيلي.

أين؟
التوثيق لوحدة معينة ، فو، يجب أن تدخل بشكل طبيعي src / foo / doc /. فمثلا
src / foo / doc / foo.rst ستكون وثيقة المستوى الأعلى للوحدة. ال
src / create-module.py سيقوم البرنامج النصي بإنشاء هذا الملف من أجلك.

تتطلب بعض الطرز عدة .أولا الملفات والأرقام. كل هذه يجب أن تذهب في
src / foo / doc / الدليل. تم إنشاء المستندات بالفعل بواسطة Sphinx Makefile. على وجه الخصوص
الوثائق المتضمنة ، قد يكون من المفيد أن يكون لديك محلي ماكيفيلي في ال src / foo / doc /
دليل لتبسيط بناء التوثيق لهذه الوحدة (هوائي انه مثال).
إعداد هذا ليس بالأمر الصعب ، ولكنه خارج نطاق هذا الفصل.

في بعض الحالات ، يمتد التوثيق إلى نماذج متعددة ؛ ال شبكة الفصل هو مثال. في
هذه الحالات مضيفا .أولا الملفات مباشرة إلى وثيقة / نماذج / مصدر / قد يكون مناسبا.

الرابط
يجب أن يعرف أبو الهول أين يجب أن يظهر فصلك الجديد. في معظم الحالات ، نموذج جديد
يجب أن يظهر الفصل في الموديلات كتاب. لإضافة فصلك هناك ، قم بالتحرير
doc / نماذج / مصدر / index.rst

.. toctree ::
: maxdepth: 1

منظمة
الرسوم المتحركة
هوائي
com.aodv
التطبيقات


أضف اسم المستند الخاص بك (بدون ملف .أولا التمديد) لهذه القائمة. من فضلك احتفظ ب
نموذج الفصول بالترتيب الأبجدي لتسهيل المسح البصري لفصول محددة.

ماكيفيلي
يجب عليك أيضًا إضافة المستند إلى الملف المناسب ماكيفيلي، وبالتالي جعل يعرف التحقق من ذلك
للتحديثات. نماذج كتاب Makefile هو وثيقة / نماذج / Makefile، الكتاب اليدوي Makefile هو
وثيقة / دليل / Makefile.

# قائمة بجميع ملفات .rst الخاصة بمكتبة النماذج التي يجب نسخها إلى $ SOURCETEMP
المصادر = \
المصدر / conf.py \
المصدر / _static \
المصدر / index.rst \
المصدر / replace.txt \
المصدر / المنظمة. rst \

$ (SRC) /antenna/doc/source/antenna.rst \


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

ابني أبو الهول مستندات
بناء وثائق Sphinx بسيط للغاية. لبناء كل أبو الهول
توثيق:

$ ./waf أبو الهول

لإنشاء وثائق النماذج فقط:

$ make -C doc / Models

للاطلاع على الوثائق التي تم إنشاؤها ، قم بتوجيه المتصفح الخاص بك إلى doc / Models / build / html.

كما ترى ، يستخدم Sphinx Make لتوجيه العملية. الهدف الافتراضي يبني كل شيء
تمكين أشكال الإخراج ، والتي في NS-3 هي الصفحات المتعددة أتش تي أم أل، صفحة واحدة مفرد htmlو
بي دي إف (اللاتكس). لإنشاء لغة تأشير النص الفائق متعددة الصفحات فقط ، يمكنك إضافة الامتداد أتش تي أم أل استهداف:

$ make -C doc / Models html

يمكن أن يكون هذا مفيدًا لتقليل وقت الإنشاء (وحجم حديث الإنشاء) مثلك
يكتبون الفصل الخاص بك.

قبل الالتزام بوثائقك في الريبو ، يرجى التحقق من أنها تبني بدون
أخطاء أو تحذيرات. تولد عملية البناء الكثير من المخرجات (معظمها أحاديث عادية
من LaTeX) ، مما قد يجعل من الصعب معرفة ما إذا كانت هناك أي تحذيرات من Sphinx أو
أخطاء. للعثور على التحذيرات والأخطاء المهمة ، قم بإنشاء ملف أتش تي أم أل الإصدار ، ثم ابحث
سجل البناء ل تحذير or خطأ.

NS-3 تفاصيل
ابو الهول توثيق البرنامج التعليمي جيدة جدا. لن نكرر الأساسيات
هنا ، بدلاً من التركيز على الاستخدام المفضل لـ NS-3.

· ابدأ المستندات بهذين السطرين:

.. include :: replace.txt
.. تسليط الضوء :: cpp

يتيح السطر الأول بعض البدائل البسيطة. على سبيل المثال ، الكتابة | ns3 | يجعل مثل
NS-3. يقوم الثاني بتعيين كود المصدر الافتراضي الذي يبرز اللغة بشكل صريح لـ
ملف ، نظرًا لأن تخمين المحلل اللغوي ليس دقيقًا دائمًا. (من الممكن أيضًا ضبط ملف
اللغة بشكل صريح لكتلة تعليمات برمجية واحدة ، انظر أدناه.)

· الأقسام:

Sphinx متحررة جدًا فيما يتعلق بوضع علامات على عناوين الأقسام. بالاتفاقية ، نحن نفضل هذا
تَسَلسُل:

.. التسلسل الهرمي للعناوين:
------------- الفصل
************* قسم (#.#)
============= القسم الفرعي (#. #. #)
############## القسم الفرعي الفرعي

· تسليط الضوء على تركيب:

لاستخدام أداة تمييز بناء الجملة الافتراضية ، ما عليك سوى بدء كتلة رمز المصدر:

┌──────────────────────────────────────────────┬── ───────────────────────────────┐
│ مصدر سفنكس │ إخراج تم تقديمه │
├──────────────────────────────────────────────┼── ───────────────────────────────┤
│ │ ملف فروبنيتز يتم الوصول إليه عن طريق: │
│ يتم الوصول إلى `` Frobnitz '' بواسطة :: │ │
│ │ فو :: Frobnitz frob ؛ │
│ فو :: Frobnitz frob ؛ │ مجموعة frob.Set (...) ؛ │
│ مجموعة frob.Set (...) ؛ │ │
└──────────────────────────────────────────────┴── ───────────────────────────────┘

لاستخدام محدد بناء جملة معين ، على سبيل المثال ، سحق أوامر شل:

┌─────────────────────────────────┬─────────────── ───┐
│ مصدر سفنكس │ إخراج تم تقديمه │
├─────────────────────────────────┼─────────────── ───┤
│ │ │
│ .. sourcecode :: bash $ ls │
│ │ │
│ $ ليرة سورية │ │
└─────────────────────────────────┴─────────────── ───┘

· تدوينات مختصرة:

يتم تعريف هذه الاختصارات:

┌────────────────────────────────────────
│ مصدر سفنكس │ إخراج تم تقديمه │
├──────────────────────┼─────────────────
│ │ NS-3
│ | ns3 | │ │
├──────────────────────┼─────────────────
│ │ NS-2
│ | ns2 | │ │
├──────────────────────┼─────────────────
│ │ │
│ | تحقق | │ │
├──────────────────────┼─────────────────
│ │ RFC 6282
│: rfc: `6282` │ │
└──────────────────────┴─────────── ───┘

توثيق مع Doxygen
نستخدم Doxygen لتوليد قابل للتصفح وثائق API. يوفر Doxygen عددًا من
ميزات مفيدة:

· جدول ملخص لجميع أعضاء الفصل.

· الرسوم البيانية للميراث والتعاون لجميع الطبقات.

· روابط إلى الكود المصدري تكمل كل وظيفة.

· روابط لكل مكان يستخدم فيه العضو.

روابط لكل كائن يستخدم في تنفيذ وظيفة.

· تجميع الفئات ذات الصلة ، مثل جميع الفئات المتعلقة ببروتوكول معين.

بالإضافة إلى ذلك ، نستخدم ملف النوع نظام للإضافة إلى التوثيق لكل فصل

· ال التكوين المسارات التي يمكن من خلالها الوصول إلى هذه الأشياء.

· التوثيق لأي السمات، بما فيها السمات المعرفة في فصول الوالدين.

· التوثيق لأي أثر المصادر التي تحددها الفئة.

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

فضل الطراز
النمط المفضل لتعليقات Doxygen هو نمط JavaDoc:

/ **
* وصف موجز لهذه الفئة أو الطريقة.
* تصبح الأسطر المتجاورة فقرة واحدة.
*
* وصف أطول ، مع الكثير من التفاصيل.
*
* أسطر فارغة تفصل بين الفقرات.
*
* اشرح ما تفعله الفئة أو الطريقة ، باستخدام أي خوارزمية.
* شرح وحدات الوسيطات والقيم المعادة.
*
* \ ملاحظة لاحظ أي قيود أو مسدود.
*
* (للوظائف ذات الوسيطات أو إرجاع القيمة :)
* \ param foo عبارة اسمية مختصرة تصف هذه الوسيطة.
* \ بارام بار ملاحظة حالة الجملة وفترة الإنهاء.
* \ إرجاع عبارة اسمية مختصرة تصف القيمة.
*
* \داخلي
*
* يمكنك أيضًا مناقشة تفاصيل التنفيذ الداخلية.
* لا يجب أن يكون فهم هذه المواد ضروريًا للاستخدام
* الطبقة أو الطريقة.
*/
مثال فئة

في هذا النمط ، تبدأ كتلة تعليق Doxygen بحرفين "*": / **، ويسبق
العنصر الذي يتم توثيقه.

بالنسبة للعناصر التي تحتاج إلى وصف موجز فقط ، يكون أي من هذه النماذج القصيرة مناسبًا:

/ ** تنفيذ التدمير. * /
DoDispose () باطلة ؛

int m_count ؛ //! <عدد ...

لاحظ الشكل الخاص لنهاية تعليق السطر ، //!، مشيرا إلى أنه يشير إلى
السابقة البند.

بعض العناصر التي يجب ملاحظتها:

· استخدام حالة الجملة ، بما في ذلك الحرف الأول بأحرف كبيرة.

· استخدم علامات الترقيم ، خاصة في نهاية الجمل أو العبارات.

· ال \مختصر العلامة ليست هناك حاجة ؛ سيتم استخدام الجملة الأولى كموجز
وصف.

يجب على كل فئة وطريقة ومحرف ومتغير عضو ووسيطة دالة وقيمة إرجاع
يتم توثيقها في جميع ملفات التعليمات البرمجية المصدر التي تشكل واجهة برمجة التطبيقات الرسمية وتنفيذها
NS-3، مثل src / /نموذج/*, src / /المساعد/* src / / utils / *.
التوثيق للعناصر في src / /امتحان/* src / /أمثلة/* مفضل ،
لكن ليس مطلوبًا.

مفيد المميزات
· سيرث الأعضاء الموروثون المستندات تلقائيًا من الوالدين (ولكن يمكن استبدالهم
عن طريق الوثائق المحلية).

1. توثيق الفئة الأساسية.

2. في علامة الفئة الفرعية الوظائف الموروثة مع تعليق عادي:

// الطرق الموروثة
FooBar باطل افتراضي (باطل) ؛
الظاهري int BarFoo (مزدوج باز) ؛

لاحظ أن التوقيعات يجب أن تتطابق تمامًا ، لذا قم بتضمين الوسيطة الرسمية (فارغ)

هذا لا يعمل مع الوظائف الثابتة. يرى GetTypeIdأدناه على سبيل المثال.

ابني Doxygen مستندات
يعد إنشاء وثائق Doxygen أمرًا بسيطًا جدًا:

$ ./واف دوكسيجين

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

عند كتابة الوثائق ، غالبًا ما يكون من المفيد معرفة العناصر التي يتم إنشاؤها
تحذيرات ، عادةً حول المستندات المفقودة. للاطلاع على قائمة التحذيرات الكاملة ، استخدم ملف
doc / doxygen. warnings.report.sh النصي:

$ doc / doxygen.warnings.report.sh
Waf: إدخال الدليل "build"

Waf: ترك الدليل "build"
انتهى "البناء" بنجاح (3 م 24.094 ث)

إعادة بناء مستندات doxygen بأخطاء كاملة ... تم.

تقرير تحذيرات Doxygen
----------------------------------------

(كل التهم هي حدود أقل.)

تحذيرات حسب الوحدة / الدليل:

دليل العد
----- ----------------------------------
3844 src / lte / model
1718 src / wimax / model
1423 src / core / model
....
138 معلمة إضافية غير موثقة.
----------------------------------------
15765 إجمالي التحذيرات
126 دليلاً مع تحذيرات

تحذيرات حسب الملف (أبجديًا)

ملف العد
----- ----------------------------------
17 doc / introspected-doxygen.h
15 أمثلة / التوجيه / manet-routing-compare.cc
26 أمثلة / إحصائيات / wifi-example-apps.h
....
----------------------------------------
967 ملفًا مع تحذيرات

تحذيرات حسب الملف (عددية)

ملف العد
----- ----------------------------------
374 src / lte / model / lte-asn1-header.h
280 src / lte / model / lte-rrc-sap.h
262 src / lte / model / lte-rrc-header.h
....
----------------------------------------
967 ملفًا مع تحذيرات

ملخص تحذيرات الدوكسجين
----------------------------------------
126 أدلة
ملفات 967
15765 تحذيرات

يقوم البرنامج النصي بتعديل التكوين لإظهار كافة التحذيرات ولتقصير وقت التشغيل.
كما ترون ، لدينا في هذه الكتابة a الكثير من العناصر غير الموثقة. التقرير
يلخص التحذيرات حسب الوحدة src / * / *وبحسب الملف ، بالترتيب الأبجدي والعددي.

يحتوي البرنامج النصي على عدد قليل من الخيارات لتقليل الأشياء وجعلها أكثر قابلية للإدارة. للمساعدة،
استخدم ال -h خيار. بعد تشغيله مرة واحدة للقيام ببناء Doxygen وإنشاء ملف
سجل التحذيرات ، يمكنك إعادة معالجة ملف السجل مع "عوامل تصفية" مختلفة ، دون الحاجة إلى القيام بذلك
بناء Doxygen الكامل ، مرة أخرى باستخدام -s خيار. يمكنك استبعاد التحذيرات من
*/أمثلة/* ملفات (-e الخيار) و / أو */امتحان/* ملفات (-t).

ربما يكون الخيار الأكثر فائدة عند كتابة تعليقات التوثيق هو -m ، التي
سيقتصر التقرير على الملفات المطابقة فقط src / / *، واتبع التقرير مع
خطوط التحذير الفعلية. تتحد مع ويمكنك التركيز على التحذيرات
الأكثر إلحاحًا في وحدة واحدة:

doc / doxygen. warnings.report.sh -m mesh / helper

ملخص تحذيرات الدوكسجين
----------------------------------------
1 أدلة
ملفات 3
149 تحذيرات

التحذيرات المصفاة
========================================
src / mesh / helper / dot11s / dot11s-installer.h: 72: تحذير: العضو m_root (متغير) من الفئة ns3 :: Dot11sStack غير موثق.
src / mesh / helper / dot11s / dot11s-installer.h: 35: تحذير: نوع إرجاع العضو ns3 :: Dot11sStack :: GetTypeId غير موثق
src / mesh / helper / dot11s / dot11s-installer.h: 56: تحذير: نوع إرجاع العضو ns3 :: Dot11sStack :: InstallStack غير موثق
src / mesh / helper / flame / lfame-installer.h: 40: تحذير: العضو GetTypeId () (وظيفة) من الفئة ns3 :: FlameStack غير موثق.
src / mesh / helper / flame / flame-installer.h: 60: تحذير: نوع إرجاع العضو ns3 :: FlameStack :: InstallStack غير موثق
src / mesh / helper / mesh-helper.h: 213: تحذير: لم يتم توثيق واجهات m_nInterfaces للعضو (متغير) للفئة ns3 :: MeshHelper.
src / mesh / helper / mesh-helper.h: 214: تحذير: العضو m_spreadChannelPolicy (متغير) للفئة ns3 :: MeshHelper غير موثق.
src / mesh / helper / mesh-helper.h: 215: تحذير: العضو m_stack (متغير) من الفئة ns3 :: MeshHelper غير موثق.
src / mesh / helper / mesh-helper.h: 216: تحذير: العضو m_stackFactory (متغير) من الفئة ns3 :: MeshHelper غير موثق.
src / mesh / helper / mesh-helper.h: 209: تحذير: معلمات العضو ns3 :: MeshHelper :: CreateInterface ليست موثقة (كلها)
src / mesh / helper / mesh-helper.h: 119: تحذير: معلمات العضو ns3 :: MeshHelper :: SetStandard ليست موثقة (كلها)

الآن الأمر يتعلق فقط بفهم الكود وكتابة بعض المستندات!

NS-3 تفاصيل
أما أبو الهول ، فإن الدوكسجين مستندات مرجع جيدة جدا. لن نكرر ملف
الأساسيات هنا ، بدلاً من التركيز على الاستخدام المفضل لـ NS-3.

· استخدم Doxygen الأقسام لتجميع العناصر ذات الصلة.

في العنوان الرئيسي للوحدة النمطية ، قم بإنشاء مجموعة Doxgyen:

/ **
* \ defgroup بروتوكول foo Foo.
*/

ضع علامة على كل فئة مرتبطة على أنها تنتمي إلى المجموعة:

/ **
* \ جروب فو
*
* نوع حزمة فو.
*/
فئة فو

· هل كنت تعلم typedefs يمكن أن يكون لها حجج رسمية؟ هذا يتيح توثيق الوظيفة
توقيعات المؤشر:

/ **
* توقيع وظيفة شريط الاتصال.
*
* \ param ale هو حجم نصف لتر من البيرة بالأوقية الإمبراطورية.
*/
typedef void (* BarCallback) (const int ale) ؛

· انسخ ال السمة سلاسل المساعدة من GetTypeId طريقة لاستخدامها كموجز
أوصاف الأعضاء المرتبطين.

· \ bugid {298} سينشئ رابطًا إلى الخطأ 298 في Bugzilla.

· \ pname {foo} في شكل وصف فو ك \ بارام فو المعلمة ، مما يجعلها واضحة
أنك تشير إلى حجة حقيقية.

· \ RFC {301} سينشئ رابطًا إلى RFC 301.

· \داخلي يجب استخدامها فقط لبدء مناقشة تفاصيل التنفيذ ، وليس من أجل
علامة خاص وظائف (تم تمييزها بالفعل ، مثل خاص!)

· لا تقم بإنشاء فئات بأسماء تافهة ، مثل فئة A، حتى في أجنحة الاختبار. هؤلاء
يتسبب في عرض جميع مثيلات اسم الفئة الحرفي "أ" كروابط.

كما هو مذكور أعلاه ، لا ترث الوظائف الثابتة وثائق نفس الوظائف في
فئة الوالدين. NS-3 يستخدم بعض الوظائف الثابتة في كل مكان ؛ اقترح
كتلة التوثيق لهذه الحالات هي:

· المُنشئ / المدمر الافتراضي:

صفي ()؛ //! <المُنشئ الافتراضي
~ MyClass () ؛ //!

· التدمير الوهمي والتخلص منه:

/ ** التدمير الوهمي ، انظر DoDispose. * /
~ MyClass () ؛

/ ** تنفيذ التدمير * /
الفراغ الظاهري DoDispose () ؛

· معرف GetType:

/ **
* سجل هذا النوع.
* \ إرجاع الكائن TypeId.
*/
TypeId ثابت GetTypeId (باطل) ؛

تمكين مجموعات فرعية of NS-3 الأقسام
كما هو الحال مع معظم مشاريع البرامج ، NS-3 تتزايد باستمرار من حيث عدد الوحدات ،
أسطر من التعليمات البرمجية ، وبصمة الذاكرة. ومع ذلك ، لا يجوز للمستخدمين استخدام سوى عدد قليل من هذه الوحدات
في الوقت. لهذا السبب ، قد يرغب المستخدمون صراحةً في تمكين المجموعة الفرعية فقط من
ممكن NS-3 الوحدات التي يحتاجونها بالفعل لأبحاثهم.

يناقش هذا الفصل كيفية تمكين فقط NS-3 الوحدات التي أنت مهتم بها
استخدام.

كيفية إلى تمكين a فرعية of NS-3's نماذج
إذا تم إنشاء مكتبات مشتركة ، فسيؤدي تمكين وحدة نمطية إلى إنشاء واحدة على الأقل
المكتبة المزمع بناؤها:

3 - اسم الطراز

إذا كانت الوحدة تحتوي على مكتبة اختبار ويتم إنشاء مكتبات اختبار ، فحينئذٍ

libns3-modulename-test.so

سيتم بناؤه أيضًا. الوحدات النمطية الأخرى التي تعتمد عليها الوحدة ومكتباتها الاختبارية
سيتم بناؤها أيضا.

بشكل افتراضي ، يتم تضمين جميع الوحدات النمطية NS-3. هناك طريقتان لتمكين مجموعة فرعية من هذه
الوحدات:

1. استخدام خيار الوحدات القابلة للتمكين في waf

2. باستخدام NS-3 ملف التكوين

تفعيل نماذج استخدام واف - وحدات قابلة للتمكين خيار
لتمكين الوحدة الأساسية فقط مع الأمثلة والاختبارات ، على سبيل المثال ، جرب هذه الأوامر:

./waf نظيف
تكوين $ ./waf - أمثلة التمكين - اختبارات التمكين - الوحدات القابلة للتمكين = النواة
$ ./waf بناء
بناء / تصحيح $ cd /
ليرة سورية

والمكتبات التالية يجب أن تكون موجودة:

الروابط libns3-core.so ns3 أدوات الخدش
أمثلة libns3- اختبار النقاط. كذلك عينات src

لاحظ ال ./waff نظيف يتم تنفيذ الخطوة هنا فقط لجعل مكتبات الوحدات النمطية أكثر وضوحًا
بنيت. ليس عليك أن تفعل ./waff نظيف من أجل تمكين مجموعات فرعية من الوحدات.

سيؤدي تشغيل test.py إلى إجراء تلك الاختبارات التي تعتمد على الوحدة الأساسية فقط:

تم اجتياز 24 من 24 اختبار (24 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

كرر الخطوات المذكورة أعلاه لوحدة "الشبكة" بدلاً من الوحدة "الأساسية" ، و
سيتم بناء ما يلي ، نظرًا لأن الشبكة تعتمد على النواة:

الروابط libns3-core.so libns3-network.so أدوات خدش ns3
أمثلة libns3-core-test.so libns3-network-test.so عينات src

سيؤدي تشغيل test.py إلى إجراء تلك الاختبارات التي تعتمد على الوحدات النمطية الأساسية والشبكة فقط
كن مسرعا:

تم اجتياز 31 من 31 اختبار (31 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

تفعيل نماذج استخدام هيه NS-3 ترتيب ملف
تمت إضافة ملف تكوين ، .ns3rc ، إلى NS-3 الذي يسمح للمستخدمين بتحديد أي
الوحدات التي سيتم تضمينها في البناء.

عند تمكين مجموعة فرعية من NS-3 الوحدات النمطية ، تكون قواعد الأسبقية كما يلي:

1. تلغي سلسلة تكوين الوحدات النمطية القابلة للتمكين أي ملف .ns3rc

2. ملف .ns3rc في المستوى الأعلى NS-3 يتم استشارة الدليل بعد ذلك ، إن وجد

3. يبحث النظام عن ~ / .ns3rc إذا كان ما ورد أعلاه غير محدد

إذا لم يحد أي مما سبق من الوحدات النمطية التي سيتم بناؤها ، فإن جميع الوحدات التي تعرفها WAF هي الإرادة
سيتم بناؤها.

النسخة المحفوظة من ملف .ns3rc في ملف NS-3 يقع مستودع كود المصدر في
هيه تيلس الدليل. والسبب في ذلك هو أنه إذا كان في دليل المستوى الأعلى لملف
المستودع ، سيكون عرضة لعمليات التحقق غير المقصودة من المشرفين الذين يقومون بتمكين
الوحدات التي يريدون استخدامها. لذلك ، يحتاج المستخدمون إلى نسخ ملف .ns3rc يدويًا من ملف
تيلس الدليل إلى المكان المفضل لديهم (دليل المستوى الأعلى أو دليلهم الرئيسي) إلى
تمكين تكوين بناء معياري مستمر.

بافتراض أنك في المستوى الأعلى NS-3 الدليل ، يمكنك الحصول على نسخة من ملف .ns3rc
الملف الموجود في تيلس الدليل على النحو التالي:

$ cp utils / .ns3rc.

يجب أن يكون ملف .ns3rc الآن في المستوى الأعلى لديك NS-3 الدليل ، ويحتوي على ملف
التالية:

#! / البيرة / بن / إنف الثعبان

# قائمة بالوحدات التي سيتم تمكينها عند تشغيل ns-3.
# سيتم أيضًا تمكين الوحدات التي تعتمد على الوحدات المدرجة.
#
# يمكن تمكين جميع الوحدات عن طريق اختيار 'all_modules'.
modules_enabled = ['all_modules']

# اضبط هذا على صواب إذا كنت تريد تشغيل الأمثلة.
example_enabled = خطأ

# اضبط هذا على صواب إذا كنت تريد إجراء الاختبارات.
test_enabled = خطأ

استخدم المحرر المفضل لديك لتعديل ملف .ns3rc لتمكين الوحدة الأساسية فقط مع
أمثلة واختبارات مثل هذا:

#! / البيرة / بن / إنف الثعبان

# قائمة بالوحدات التي سيتم تمكينها عند تشغيل ns-3.
# سيتم أيضًا تمكين الوحدات التي تعتمد على الوحدات المدرجة.
#
# يمكن تمكين جميع الوحدات عن طريق اختيار 'all_modules'.
modules_enabled = ['core']

# اضبط هذا على صواب إذا كنت تريد تشغيل الأمثلة.
example_enabled = صحيح

# اضبط هذا على صواب إذا كنت تريد إجراء الاختبارات.
test_enabled = صحيح

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

./waf نظيف
$ ./waf تكوين
$ ./waf بناء
بناء / تصحيح $ cd /
ليرة سورية

والمكتبات التالية يجب أن تكون موجودة:

الروابط libns3-core.so ns3 أدوات الخدش
أمثلة libns3- اختبار النقاط. كذلك عينات src

لاحظ ال ./waff نظيف يتم تنفيذ الخطوة هنا فقط لجعل مكتبات الوحدات النمطية أكثر وضوحًا
بنيت. ليس عليك أن تفعل ./waff نظيف من أجل تمكين مجموعات فرعية من الوحدات.

سيؤدي تشغيل test.py إلى إجراء تلك الاختبارات التي تعتمد على الوحدة الأساسية فقط:

تم اجتياز 24 من 24 اختبار (24 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

كرر الخطوات المذكورة أعلاه لوحدة "الشبكة" بدلاً من الوحدة "الأساسية" ، و
سيتم بناء ما يلي ، نظرًا لأن الشبكة تعتمد على النواة:

الروابط libns3-core.so libns3-network.so أدوات خدش ns3
أمثلة libns3-core-test.so libns3-network-test.so عينات src

سيؤدي تشغيل test.py إلى إجراء تلك الاختبارات التي تعتمد على الوحدات النمطية الأساسية والشبكة فقط
كن مسرعا:

تم اجتياز 31 من 31 اختبار (31 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

التمكين / التعطيل NS-3 اختبارات أمثلة
إنّ NS-3 يتضمن التوزيع العديد من الأمثلة والاختبارات التي يتم استخدامها للتحقق من صحة NS-3
نظام. ومع ذلك ، قد لا يرغب المستخدمون دائمًا في تشغيل هذه الأمثلة والاختبارات لملفاتهم
تركيب NS-3.

يناقش هذا الفصل كيفية البناء NS-3 مع أو بدون الأمثلة والاختبارات.

كيفية إلى مفعل وغير مفعل أمثلة اختبارات in NS-3
هناك 3 طرق لتمكين / تعطيل الأمثلة والاختبارات في NS-3:

1. استخدام build.py عندما NS-3 تم بناءه لأول مرة

2. استخدام الواف مرة واحدة NS-3 تم بنائه

3. باستخدام NS-3 ملف التكوين مرة واحدة NS-3 تم بنائه

مفعل وغير مفعل أمثلة اختبارات استخدام build.py
يمكنك استخدام build.py لتمكين / تعطيل الأمثلة والاختبارات عندما NS-3 تم بناؤه لأول مرة
مرة.

بشكل افتراضي ، لا يتم تضمين الأمثلة والاختبارات NS-3.

من دليل ns-3-allinone ، يمكنك إنشاء ملفات NS-3 بدون أي أمثلة أو اختبارات ببساطة
عن طريق القيام:

$ ./build.py

تشغيل test.py في المستوى الأعلى NS-3 الدليل الآن لن يتسبب في وجود أمثلة أو اختبارات
يركض:

تم اجتياز 0 من 0 اختبار (0 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

إذا كنت ترغب في البناء NS-3 مع الأمثلة والاختبارات ، ثم قم بما يلي من
دليل ns-3-allinone:

$ ./build.py - أمثلة التمكين - اختبارات التمكين

تشغيل test.py في المستوى الأعلى NS-3 الدليل سيتسبب في جميع الأمثلة والاختبارات
ليتم تشغيلها:

تم اجتياز 170 من 170 اختبار (170 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

مفعل وغير مفعل أمثلة اختبارات استخدام WAF
يمكنك استخدام waf لتمكين / تعطيل الأمثلة والاختبارات مرة واحدة NS-3 تم بنائه.

بشكل افتراضي ، لا يتم تضمين الأمثلة والاختبارات NS-3.

من أعلى مستوى NS-3 الدليل ، يمكنك بناء NS-3 بدون أي أمثلة أو اختبارات ببساطة
عن طريق القيام:

$ ./waf تكوين
$ ./waf بناء

لن يؤدي تشغيل test.py الآن إلى تشغيل أمثلة أو اختبارات:

تم اجتياز 0 من 0 اختبار (0 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

إذا كنت ترغب في البناء NS-3 مع الأمثلة والاختبارات ، ثم قم بما يلي من الأعلى
مستوى NS-3 دليل:

تكوين $ ./waf - أمثلة قابلة للتمكين - اختبارات التمكين
$ ./waf بناء

سيؤدي تشغيل test.py إلى تشغيل جميع الأمثلة والاختبارات:

تم اجتياز 170 من 170 اختبار (170 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

مفعل وغير مفعل أمثلة اختبارات استخدام هيه NS-3 ترتيب ملف
تمت إضافة ملف تكوين ، .ns3rc ، إلى NS-3 الذي يسمح للمستخدمين بتحديد ما إذا كان
يجب بناء الأمثلة والاختبارات أم لا. يمكنك استخدام هذا الملف لتمكين / تعطيل
أمثلة واختبارات مرة واحدة NS-3 تم بنائه.

عند تمكين تعطيل الأمثلة والاختبارات ، تكون قواعد الأسبقية كما يلي:

1. تتخطى سلاسل التكوين - أمثلة / - تعطيل - أي ملف .ns3rc

2. - تمكين - الاختبارات / - تعطيل - اختبارات تكوين السلاسل تتجاوز أي ملف .ns3rc

3. ملف .ns3rc في المستوى الأعلى NS-3 يتم استشارة الدليل بعد ذلك ، إن وجد

4. يبحث النظام عن ~ / .ns3rc إذا لم يتم العثور على ملف .ns3rc في الخطوة السابقة

في حالة عدم وجود أي مما سبق ، فلن يتم إنشاء أمثلة واختبارات.

النسخة المحفوظة من ملف .ns3rc في ملف NS-3 يقع مستودع كود المصدر في
هيه تيلس الدليل. والسبب في ذلك هو أنه إذا كان في دليل المستوى الأعلى لملف
المستودع ، سيكون عرضة لعمليات التحقق غير المقصودة من المشرفين الذين يقومون بتمكين
الوحدات التي يريدون استخدامها. لذلك ، يحتاج المستخدمون إلى نسخ ملف .ns3rc يدويًا من ملف
تيلس الدليل إلى المكان المفضل لديهم (دليل المستوى الأعلى أو دليلهم الرئيسي) إلى
تمكين التمكين المستمر للأمثلة والاختبارات.

بافتراض أنك في المستوى الأعلى NS-3 الدليل ، يمكنك الحصول على نسخة من ملف .ns3rc
الملف الموجود في تيلس الدليل على النحو التالي:

$ cp utils / .ns3rc.

يجب أن يكون ملف .ns3rc الآن في المستوى الأعلى لديك NS-3 الدليل ، ويحتوي على ملف
التالية:

#! / البيرة / بن / إنف الثعبان

# قائمة بالوحدات التي سيتم تمكينها عند تشغيل ns-3.
# سيتم أيضًا تمكين الوحدات التي تعتمد على الوحدات المدرجة.
#
# يمكن تمكين جميع الوحدات عن طريق اختيار 'all_modules'.
modules_enabled = ['all_modules']

# اضبط هذا على صواب إذا كنت تريد تشغيل الأمثلة.
example_enabled = خطأ

# اضبط هذا على صواب إذا كنت تريد إجراء الاختبارات.
test_enabled = خطأ

من أعلى مستوى NS-3 الدليل ، يمكنك بناء NS-3 بدون أي أمثلة أو اختبارات ببساطة
عن طريق القيام:

$ ./waf تكوين
$ ./waf بناء

لن يؤدي تشغيل test.py الآن إلى تشغيل أمثلة أو اختبارات:

تم اجتياز 0 من 0 اختبار (0 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

إذا كنت ترغب في البناء NS-3 مع الأمثلة والاختبارات ، استخدم محررك المفضل للتغيير
القيم الموجودة في ملف .ns3rc للحصول على أمثلة_مُمكَّنة وملف الاختبارات_تمكينها لتكون صحيحة:

#! / البيرة / بن / إنف الثعبان

# قائمة بالوحدات التي سيتم تمكينها عند تشغيل ns-3.
# سيتم أيضًا تمكين الوحدات التي تعتمد على الوحدات المدرجة.
#
# يمكن تمكين جميع الوحدات عن طريق اختيار 'all_modules'.
modules_enabled = ['all_modules']

# اضبط هذا على صواب إذا كنت تريد تشغيل الأمثلة.
example_enabled = صحيح

# اضبط هذا على صواب إذا كنت تريد إجراء الاختبارات.
test_enabled = صحيح

من أعلى مستوى NS-3 الدليل ، يمكنك بناء NS-3 مع الأمثلة والاختبارات ببساطة عن طريق
عمل:

$ ./waf تكوين
$ ./waf بناء

سيؤدي تشغيل test.py إلى تشغيل جميع الأمثلة والاختبارات:

تم اجتياز 170 من 170 اختبار (170 ناجح ، 0 تم تخطيه ، 0 فشل ، 0 تعطل ، 0 أخطاء Valgrind)

استكشاف الأخطاء:
ينشر هذا الفصل بعض المعلومات حول الأخطاء الشائعة المحتملة في البناء أو التشغيل
NS-3 البرامج.

يرجى ملاحظة أن الويكي (http://www.nsnam.org/wiki/Troubleshooting) ربما ساهم
بنود

البناء أخطاء
وقت التشغيل أخطاء
في بعض الأحيان ، يمكن أن تحدث أخطاء في أحد البرامج بعد بناء ناجح. هذه هي وقت التشغيل
أخطاء ، ويمكن أن تحدث بشكل شائع عند تلف الذاكرة أو تكون قيم المؤشر بشكل غير متوقع
لا شيء.

فيما يلي مثال لما قد يحدث:

$ ./waf - تشغيل برنامج التعاون الفني من نقطة إلى نقطة
إدخال الدليل "/ home / tomh / ns-3-nsc / build"
انتهى التجميع بنجاح
تم إنهاء الأمر ['/ home / tomh / ns-3-nsc / build / debug /amples / tcp-point-to-point'] باستخدام الكود -11

تشير رسالة الخطأ إلى أن البرنامج تم إنهاؤه دون جدوى ، لكنها غير واضحة
من هذه المعلومات ما قد يكون خطأ. لفحصها عن كثب ، حاول تشغيلها
هيه جدب المصحح:

$ ./waf --run tcp-point-to-point - command-template = "gdb٪ s"
إدخال الدليل "/ home / tomh / ns-3-nsc / build"
انتهى التجميع بنجاح
جنو gdb ريد هات لينكس (6.3.0.0-1.134.fc5rh)
حقوق النشر 2004 مؤسسة البرمجيات الحرة ، Inc.
GDB هو برنامج مجاني ، مشمول برخصة GNU العامة ، وأنت كذلك
مرحبًا بك لتغييره و / أو توزيع نسخ منه في ظل ظروف معينة.
اكتب "إظهار النسخ" لمعرفة الشروط.
لا يوجد أي ضمان على الإطلاق لـ GDB. اكتب "عرض الضمان" للحصول على التفاصيل.
تم تكوين GDB هذا كـ "i386-redhat-linux-gnu" ... باستخدام المضيف libthread_db
مكتبة "/lib/libthread_db.so.1".

(gdb) تشغيل
برنامج البداية: / home / tomh / ns-3-nsc / build / debug /amples / tcp-point-to-point
قراءة الرموز من الكائن المشترك المقروءة من الذاكرة الهدف ... تم.
قدم النظام المحمّل DSO عند 0xf5c000

استقبل البرنامج إشارة SIGSEGV ، خطأ تجزئة.
0x0804aa12 في اللغة الرئيسية (argc = 1 ، argv = 0xbfdfefa4)
في ../examples/tcp-point-to-point.cc:136
136 نقطة localSocket = socketFactory-> CreateSocket () ؛
(gdb) ع localSocket
1 دولار = {m_ptr = 0x3c5d65}
(gdb) p socketFactory. مصنع
2 دولار = {m_ptr = 0x0}
(gdb) إنهاء
البرنامج قيد التشغيل. هل تريد الخروج على أي حال؟ (ص أو ن) ذ

لاحظ أولاً الطريقة التي تم بها استدعاء البرنامج - مرر الأمر للتشغيل كوسيط إلى ملف
قالب الأوامر "gdb٪ s".

يخبرنا هذا أنه كانت هناك محاولة لإلغاء مرجعية مصنع مقبس مؤشر فارغ.

لنلق نظرة حول السطر 136 من tcp-point-to-point كما يقترح gdb:

Ptr socketFactory = n2-> GetObject (Tcp :: iid) ؛
Ptr localSocket = socketFactory-> CreateSocket () ؛
localSocket-> ربط () ؛

الجاني هنا هو أن القيمة المعادة لـ GetObject لم يتم التحقق منها وقد يتم فحصها
لا شيء.

في بعض الأحيان قد تحتاج إلى استخدام ملف فالغريند ذاكرة فاحص لمزيد من الأخطاء الدقيقة. مرة أخرى،
تستدعي استخدام valgrind بالمثل:

$ ./waf --run tcp-point-to-point - command-template = "valgrind٪ s"

مصدر


هذه الوثيقة مكتوبة باللغة reStructuredText لـ أبو الهول ويتم الحفاظ عليه في
وثيقة / دليل دليل الكود المصدري ns-3.

استخدم دليل ns-3 عبر الإنترنت باستخدام خدمات onworks.net


خوادم ومحطات عمل مجانية

قم بتنزيل تطبيقات Windows و Linux

  • 1
    أوسو!
    أوسو!
    أوسو! هي لعبة إيقاع بسيطة مع بئر
    يعتقد منحنى التعلم للاعبين
    من جميع مستويات المهارة. واحد من العظماء
    جوانب Osu! هل هذا هو عليه
    المجتمع د ...
    تحميل Osu!
  • 2
    LIBPNG: مكتبة مرجعية PNG
    LIBPNG: مكتبة مرجعية PNG
    مكتبة مرجعية لدعم
    تنسيق رسومات الشبكة المحمولة (PNG).
    الجمهور: المطورين. برمجة
    اللغة: C. هذا هو أحد التطبيقات التي
    يمكن أيضا...
    تنزيل LIBPNG: مكتبة مرجعية PNG
  • 3
    كاشف المعادن على أساس RP2040
    كاشف المعادن على أساس RP2040
    بناءً على لوحة Raspberry Pi Pico ، هذا
    يتم تضمين جهاز الكشف عن المعادن في النبض
    فئة أجهزة الكشف عن المعادن التعريفي ، مع
    مزايا وعيوب معروفة.
    RP ...
    تنزيل جهاز الكشف عن المعادن على أساس RP2040
  • 4
    مدير PAC
    مدير PAC
    PAC هو بديل Perl / GTK لـ
    SecureCRT / المعجون / إلخ (لينكس
    ssh / telnet / ... gui) ... يوفر واجهة المستخدم الرسومية
    لتكوين الاتصالات: المستخدمين ،
    كلمات المرور ، توقع التنظيم ...
    تنزيل مدير PAC
  • 5
    GeoServer
    GeoServer
    GeoServer هو برنامج مفتوح المصدر
    خادم مكتوب بلغة Java يسمح للمستخدمين
    لمشاركة البيانات الجغرافية المكانية وتحريرها.
    مصممة للتشغيل البيني
    تنشر دا ...
    تنزيل GeoServer
  • 6
    اليراع الثالث
    اليراع الثالث
    تمويل شخصي مجاني ومفتوح المصدر
    إدارة. ميزات Firefly III أ
    نظام مسك الدفاتر مزدوج القيد. تستطيع
    أدخل بسرعة ونظم ملفات
    المعاملات ط ...
    تحميل فايرفلاي III
  • أكثر "

أوامر لينكس

Ad