این دستور ns-3-manual است که می تواند در ارائه دهنده هاست رایگان OnWorks با استفاده از یکی از چندین ایستگاه کاری آنلاین رایگان ما مانند Ubuntu Online، Fedora Online، شبیه ساز آنلاین ویندوز یا شبیه ساز آنلاین MAC OS اجرا شود.
برنامه:
نام
ns-3-manual - ns-3 manual
این است ns-3 دستی. اسناد اولیه برای پروژه ns-3 در پنج مورد موجود است
تشکیل می دهد:
· ns-3 اکسیژن: مستندسازی APIهای عمومی شبیه ساز
· آموزش، راهنما (این سند)و کتابخانه مدل برای آخرین آزاد و
توسعه درخت
· ns-3 ویکی
فهرست
سازمان
این فصل به طور کلی توضیح می دهد ns-3 سازمان نرم افزار و مربوطه
سازماندهی این راهنما
ns-3 یک شبیه ساز شبکه رویداد گسسته است که در آن هسته و مدل های شبیه سازی قرار دارند
در C++ پیاده سازی شده است. ns-3 به عنوان یک کتابخانه ساخته شده است که ممکن است به صورت ایستا یا پویا باشد
به یک برنامه اصلی C++ که توپولوژی شبیه سازی را تعریف می کند و شروع به کار می کند
شبیه ساز ns-3 همچنین تقریباً تمام API خود را به پایتون صادر می کند و به برنامه های پایتون اجازه می دهد
ماژول "ns3" را به همان روش وارد کنید ns-3 کتابخانه توسط فایل های اجرایی پیوند داده شده است
در C++
[تصویر] سازمان نرم افزار ns-3.UNINDENT
کد منبع برای ns-3 بیشتر در سازماندهی شده است " دایرکتوری و قابل توصیف است
توسط نمودار در نرم افزار کدام سازمان ها of ns-3. ما راه خود را از پایین کار خواهیم کرد
بالا به طور کلی، ماژول ها فقط به ماژول های زیر خود در شکل وابستگی دارند.
ابتدا هسته شبیه ساز را شرح می دهیم. اجزایی که در همه مشترک هستند
پروتکل، سخت افزار و مدل های محیطی هسته شبیه سازی در پیاده سازی شده است
src/core. بسته ها اشیاء اساسی در یک شبیه ساز شبکه هستند و در آن پیاده سازی می شوند
src/شبکه. این دو ماژول شبیه سازی به خودی خود در نظر گرفته شده است که شامل یک
هسته شبیه سازی عمومی که می تواند توسط انواع مختلف شبکه استفاده شود، نه فقط
شبکه های مبتنی بر اینترنت ماژول های فوق از ns-3 مستقل از شبکه خاصی هستند
و مدلهای دستگاه، که در بخشهای بعدی این راهنما توضیح داده شدهاند.
علاوه بر موارد فوق ns-3 هسته، ما معرفی می کنیم، همچنین در بخش اولیه از
کتابچه راهنمای کاربر، دو ماژول دیگر که مکمل API مبتنی بر C++ هستند. ns-3 برنامه ها ممکن است
به طور مستقیم به تمام API دسترسی داشته باشید یا ممکن است از یک به اصطلاح استفاده کنید یاور API فراهم می کند
بستهبندیهای مناسب یا کپسولهسازی تماسهای API سطح پایین. این حقیقت که ns-3 برنامه ها
را می توان در دو API نوشت (یا ترکیبی از آنها) یک جنبه اساسی از آن است
شبیه ساز همچنین نحوه پشتیبانی پایتون را توضیح می دهیم ns-3 قبل از حرکت به سمت خاص
مدل های مربوط به شبیه سازی شبکه
بقیه کتابچه راهنمای کاربر بر مستندسازی مدل ها و پشتیبانی متمرکز است
توانایی ها. بخش بعدی بر دو شیء اساسی تمرکز دارد ns-3از: گره و
NetDevice. دو نوع NetDevice ویژه برای پشتیبانی از شبیه سازی شبکه طراحی شده اند
موارد، و شبیه سازی در ادامه توضیح داده شده است. فصل زیر به این موضوع اختصاص دارد
مدلهای مرتبط با اینترنت، از جمله سوکتهای API که توسط برنامههای کاربردی اینترنتی استفاده میشوند. در
فصل بعدی برنامه ها را پوشش می دهد و فصل بعدی پشتیبانی اضافی را توضیح می دهد
برای شبیه سازی، مانند انیماتورها و آمار.
این پروژه یک کتابچه راهنمای جداگانه دارد که به آزمایش و اعتبار سنجی اختصاص داده شده است ns-3 رمز
(نگاه کنید به ns-3 تست و اعتبار کتابچه راهنمای).
تصادفی متغیر
ns-3 شامل یک تولید کننده اعداد شبه تصادفی (PRNG) داخلی است. برای آن مهم است
کاربران جدی شبیه ساز برای درک عملکرد، پیکربندی و استفاده
از این PRNG، و تصمیم گیری در مورد اینکه آیا برای استفاده تحقیقاتی او کافی است یا خیر.
سریع بررسی اجمالی
ns-3 اعداد تصادفی از طریق نمونه هایی از ارائه می شوند ns3::RandomVariableStream.
· به صورت پیش فرض، ns-3 شبیه سازی ها از یک دانه ثابت استفاده می کنند. در صورت وجود هر گونه تصادفی در
شبیه سازی، هر اجرای برنامه نتایج یکسانی را به همراه خواهد داشت مگر اینکه seed و/یا
شماره اجرا تغییر کرده است
· که در ns-3.3 و قبل از آن، ns-3 شبیه سازی به طور پیش فرض از یک دانه تصادفی استفاده می کند. این علامت a
تغییر در سیاست با شروع ns-3.4.
· که در ns-3.14 و قبل از آن، ns-3 شبیه سازی ها از کلاس wrapper متفاوتی به نام استفاده کردند
ns3::RandomVariable. همانطور که از ns-3.15، این کلاس جایگزین شده است
ns3::RandomVariableStream; مولد اعداد شبه تصادفی زیربنایی ندارد
تغییر کرد.
· برای به دست آوردن تصادفی بودن در اجرای چندین شبیه سازی، باید Seed را تنظیم کنید
متفاوت باشد یا عدد اجرا را متفاوت تنظیم کنید. برای تعیین دانه، تماس بگیرید
ns3::RngSeedManager::SetSeed() در ابتدای برنامه؛ برای تنظیم یک شماره اجرا با
همان دانه، تماس بگیرید ns3::RngSeedManager::SetRun() در ابتدای برنامه؛ دیدن
ایجاد تصادفی متغیرها.
· هر RandomVariableStream استفاده شده در ns-3 دارای یک مولد اعداد تصادفی مجازی مرتبط است
با آن؛ همه متغیرهای تصادفی از یک دانه ثابت یا تصادفی بر اساس استفاده استفاده می کنند
دانه جهانی (گلوله قبلی)؛
· اگر قصد دارید چندین اجرا از یک سناریو را با تصادفی متفاوت انجام دهید
اعداد، لطفا بخش نحوه انجام تکثیر مستقل را حتما بخوانید:
ایجاد تصادفی متغیرها.
برای توضیحات بیشتر در مورد امکانات اعداد تصادفی برای بیشتر بخوانید ns-3.
زمینه
شبیه سازی ها از تعداد زیادی اعداد تصادفی استفاده می کنند. یک مطالعه نشان داد که اکثر شبیه سازی های شبکه
50 درصد از CPU را صرف تولید اعداد تصادفی کنید. کاربران شبیه سازی باید باشند
مربوط به کیفیت اعداد تصادفی (شبه) و استقلال بین
جریان های مختلف اعداد تصادفی
کاربران باید با چند مشکل نگران باشند، مانند:
بذر مولد اعداد تصادفی و اینکه آیا یک نتیجه شبیه سازی است
قطعی یا نه،
· نحوه به دست آوردن جریان های مختلف اعداد تصادفی که مستقل از یک هستند
دیگری، و
چه مدت طول می کشد تا جریان ها چرخه شوند
ما در اینجا چند اصطلاح را معرفی می کنیم: یک RNG دنباله ای طولانی از (شبه) تصادفی را ارائه می دهد
شماره. طول این دنباله را می نامند چرخه طول or دوره، پس از آن
RNG خود را تکرار خواهد کرد. این دنباله را می توان به دو قسمت تقسیم کرد جریان.
جریان یک RNG یک زیرمجموعه یا بلوک پیوسته از دنباله RNG است. به عنوان مثال، اگر
دوره RNG به طول N است و دو جریان از این RNG ارائه می شود، سپس اولین
جریان ممکن است از مقادیر N/2 اول استفاده کند و جریان دوم ممکن است N/2 دوم را تولید کند
ارزش های. یک ویژگی مهم در اینجا این است که این دو جریان با هم مرتبط نیستند. به همین ترتیب،
هر جریان را می توان به طور مجزا به تعدادی ناهمبسته تقسیم کرد زیر جریان ها.
امیدواریم RNG زیربنایی یک دنباله شبه تصادفی از اعداد با طول بسیار طولانی تولید کند
طول چرخه، و آن را به شیوه ای کارآمد به جریان ها و زیرجریان ها تقسیم می کند.
ns-3 از همان مولد اعداد تصادفی زیربنایی استفاده می کند ns-2: MRG32k3a
ژنراتور از Pierre L'Ecuyer. شرح مفصل را می توان در یافت
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf. ژنراتور MRG32k3a
1.8x10^{19} جریان های مستقلی از اعداد تصادفی را ارائه می دهد که هر کدام از
جریانهای فرعی 2.3x10^{15}. هر زیر جریان یک دوره دارد (به عنوان مثال، تعداد اعداد تصادفی
قبل از همپوشانی) از 7.6x10^{22}. دوره کل ژنراتور 3.1x10^{57} است.
طبقه ns3::RandomVariableStream رابط عمومی برای این عدد تصادفی زیربنایی است
ژنراتور زمانی که کاربران متغیرهای تصادفی جدیدی ایجاد می کنند (مانند ns3::UniformRandomVariable,
ns3::تغییر تصادفی نماییو غیره)، آنها یک شی ایجاد می کنند که از یکی از موارد استفاده می کند
جریان های مجزا و مستقل از مولد اعداد تصادفی. بنابراین، هر شیء از
نوع ns3::RandomVariableStream از نظر مفهومی، RNG "مجازی" خود را دارد. علاوه بر این،
هر ns3::RandomVariableStream را می توان برای استفاده از یکی از مجموعه زیرجریان های ترسیم شده پیکربندی کرد
از جریان اصلی
یک پیاده سازی جایگزین این است که به هر RandomVariable اجازه داده شود تا خودش را داشته باشد
(با بذرهای متفاوت) RNG. با این حال، ما نمی توانیم به شدت تضمین کنیم که متفاوت است
توالی ها در چنین موردی با هم ارتباط ندارند. از این رو، ما ترجیح می دهیم از یک RNG و استفاده کنیم
جریان و فرعی از آن.
ایجاد تصادفی متغیرها
ns-3 تعدادی شیء متغیر تصادفی را از کلاس پایه پشتیبانی می کند
RandomVariableStream. این اشیاء از ns3:: شی و توسط هوشمند اداره می شوند
اشاره گرها
راه درست برای ایجاد این اشیاء استفاده از قالب است CreateObject<> روش،
مانند:
Ptr x = CreateObject ()
سپس می توانید با فراخوانی متدهایی روی شیء مانند:
myRandomNo = x->GetInteger ();
اگر سعی کنید به جای آن کاری شبیه به این انجام دهید:
myRandomNo = UniformRandomVariable().GetInteger ();
برنامه شما با خطای بخش بندی مواجه می شود، زیرا پیاده سازی به آن متکی است
برخی از ساختارهای صفت که فقط زمانی رخ می دهد که CreateObject نامیده میشود.
بسیاری از بقیه این فصل در حال حاضر ویژگی های جریان از را مورد بحث قرار می دهد
اعداد شبه تصادفی تولید شده از چنین اشیایی و نحوه کنترل بذر دادن آنها
اشیاء.
بذر و مستقل تکرارها
ns-3 شبیه سازی ها را می توان برای تولید نتایج قطعی یا تصادفی پیکربندی کرد. اگر
ns-3 شبیه سازی برای استفاده از یک دانه ثابت و قطعی با همان عدد اجرا پیکربندی شده است.
هر بار که اجرا می شود باید همان خروجی را بدهد.
به طور پیش فرض، ns-3 شبیه سازی ها از یک عدد seed و run ثابت استفاده می کنند. این مقادیر در
دو ns3::GlobalValue موارد: g_rngSeed و g_rng اجرا کنید.
یک مورد استفاده معمولی این است که شبیه سازی را به عنوان دنباله ای از آزمایشات مستقل اجرا کنیم تا بتوانیم
محاسبه آمار در تعداد زیادی از اجراهای مستقل. کاربر می تواند هر دو را تغییر دهد
جهانی بذر و شبیه سازی را مجددا اجرا کنید، یا می توانید حالت زیر جریان RNG را پیش ببرید، که
به عنوان افزایش عدد اجرا نامیده می شود.
یک کلاس ns3::RngSeedManager یک API برای کنترل تعداد دانهبندی و اجرا فراهم میکند
رفتار - اخلاق. این تنظیم حالت بذر و زیر جریان باید قبل از هر تصادفی فراخوانی شود
متغیرها ایجاد می شوند. به عنوان مثال:
RngSeedManager::SetSeed (3); // seed را از پیش فرض 1 به 3 تغییر می دهد
RngSeedManager::SetRun (7); // شماره اجرا را از پیش فرض 1 به 7 تغییر می دهد
// حالا متغیرهای تصادفی ایجاد کنید
Ptr x = CreateObject ()
Ptr y = CreateObject ()
...
کدام یک بهتر است، تنظیم یک دانه جدید یا پیشبرد وضعیت فرعی؟ وجود ندارد
تضمین می کند که جریان های تولید شده توسط دو دانه تصادفی با هم همپوشانی ندارند. تنها راه برای
تضمین عدم همپوشانی دو جریان برای استفاده از قابلیت زیرجریان ارائه شده توسط
پیاده سازی RNG از این رو، استفاده کنید la زیر جریان قابلیت به تولید کردن چندگانه
مستقل اجرا می شود of la همان شبیه سازی. به عبارت دیگر، از نظر آماری دقیق تر
راه برای پیکربندی چندین تکرار مستقل استفاده از یک دانه ثابت و پیشروی است
شماره اجرا این پیاده سازی حداکثر 2.3x10^{15} مستقل را امکان پذیر می کند
تکرار با استفاده از زیر جریان ها
برای سهولت استفاده، نیازی به کنترل عدد دانه و اجرا از داخل نیست
برنامه؛ کاربر می تواند تنظیم کند NS_GLOBAL_VALUE متغیر محیطی به شرح زیر است:
$ NS_GLOBAL_VALUE="RngRun=3" ./waf --run program-name
راه دیگر برای کنترل این، ارسال یک آرگومان خط فرمان است. از آنجایی که این یک ns-3
به عنوان مثال GlobalValue، به طور معادل به صورت زیر انجام می شود:
$ ./waf --command-template="%s --RngRun=3" --run program-name
یا اگر برنامه هایی را مستقیماً خارج از waf اجرا می کنید:
$ ./build/optimized/scratch/program-name --RngRun=3
انواع خط فرمان بالا اجرای بسیاری از اجراهای مختلف را از یک پوسته آسان می کند
اسکریپت فقط با ارسال یک شاخص RngRun متفاوت.
طبقه RandomVariableStream
همه متغیرهای تصادفی باید از کلاس مشتق شوند متغیر تصادفی. این کلاس پایه یک را ارائه می دهد
چند روش برای پیکربندی جهانی رفتار مولد اعداد تصادفی. نشات گرفته
کلاس ها API را برای ترسیم تغییرات تصادفی از توزیع خاص ارائه می کنند
پشتیبانی.
به هر RandomVariableStream ایجاد شده در شبیه سازی یک ژنراتور جدید داده می شود
RNG Stream از PRNG زیربنایی. در این روش، پیاده سازی L'Ecuyer استفاده می شود
حداکثر 1.8x10^19 متغیر تصادفی را امکان پذیر می کند. هر متغیر تصادفی در یک واحد
تکرار می تواند تا 7.6x10^22 اعداد تصادفی را قبل از همپوشانی ایجاد کند.
پایه کلاس عمومی API
در زیر چند روش عمومی کلاس گزیده شده است RandomVariableStream که دسترسی به
مقدار بعدی در زیر جریان
/ **
* \brief دو برابر تصادفی را از توزیع زیربنایی برمیگرداند
* \return یک مقدار تصادفی ممیز شناور
*/
دو برابر GetValue (باطل) const;
/ **
* \brief یک عدد صحیح تصادفی را از توزیع اصلی برمیگرداند
* \return بازیگران عدد صحیح ::GetValue()
*/
uint32_t GetInteger (void) const;
ما قبلاً پیکربندی کاشت را در بالا توضیح داده ایم. متغیر تصادفی متفاوت
زیر کلاس ها ممکن است API اضافی داشته باشند.
انواع of متغیرهای تصادفی
انواع زیر از متغیرهای تصادفی ارائه شده است و در آن مستند شده است ns-3
داکسیژن یا با خواندن src/core/model/random-variable-stream.h. کاربران همچنین می توانند ایجاد کنند
متغیرهای تصادفی سفارشی خود را با استخراج از کلاس RandomVariableStream.
· کلاس UniformRandomVariable
· کلاس ConstantRandomVariable
· کلاس متغیر تصادفی ترتیبی
· کلاس متغیر تصادفی نمایی
· کلاس ParetoRandomVariable
· کلاس WeibullRandomVariable
· کلاس NormalRandomVariable
· کلاس LogNormalRandomVariable
· کلاس GammaRandomVariable
· کلاس ErlangRandomVariable
· کلاس TriangularRandomVariable
· کلاس ZipfRandomVariable
· کلاس متغیر ZetaRandom
· کلاس DeterministicRandomVariable
· کلاس متغیر تصادفی تجربی
معناشناسی of RandomVariableStream اشیاء
اشیاء RandomVariableStream مشتق از ns3:: شی و توسط اشاره گرهای هوشمند مدیریت می شوند.
از نمونه های RandomVariableStream نیز می توان در آن استفاده کرد ns-3 صفات، که به این معنی است
مقادیر را می توان برای آنها از طریق تنظیم کرد ns-3 سیستم ویژگی یک مثال در
مدل های انتشار برای WifiNetDevice:
TypeId
RandomPropagationDelayModel::GetTypeId (باطل)
{
static TypeId tid = TypeId ("ns3::RandomPropagationDelayModel")
SetParent ()
.AddConstructor ()
.AddAttribute ("متغیر"،
"متغیر تصادفی که تاخیرهای تصادفی (های) را ایجاد می کند،"
StringValue ("ns3::UniformRandomVariable")،
MakePointerAccessor (&RandomPropagationDelayModel::m_variable)،
MakePointerChecker ())
;
برگرد
}
اینجا ns-3 کاربر می تواند متغیر تصادفی پیش فرض را برای این مدل تاخیر تغییر دهد (که این است
یک UniformRandomVariable از 0 تا 1) از طریق سیستم ویژگی.
با استفاده از دیگر PRNG
در حال حاضر هیچ پشتیبانی برای جایگزینی یک عدد تصادفی زیربنایی متفاوت وجود ندارد
مولد (به عنوان مثال، کتابخانه علمی گنو یا بسته Akaroa). پچ ها پذیرفته می شوند.
محیط la جریان عدد
ژنراتور زیرین MRG32k3a 2^64 جریان مستقل را ارائه می دهد. در ns-3، اینها هستند
به صورت متوالی از اولین جریان به عنوان نمونههای جدید RandomVariableStream اختصاص داده میشود
اولین تماس خود را با GetValue().
در نتیجه نحوه تخصیص این اشیاء RandomVariableStream به جریان های زیربنایی،
تخصیص به اختلالات پیکربندی شبیه سازی حساس است. در
نتیجه این است که اگر هر جنبه ای از پیکربندی شبیه سازی تغییر کند، نقشه برداری
متغیرهای تصادفی به جریان ها ممکن است (یا ممکن است) تغییر نکند.
به عنوان یک مثال عینی، کاربری که یک مطالعه مقایسه ای بین پروتکل های مسیریابی انجام می دهد ممکن است
متوجه شوید که عمل تغییر یک پروتکل مسیریابی به پروتکل دیگر متوجه خواهد شد که
الگوی تحرک اساسی نیز تغییر کرد.
با شروع با 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 که دارای مقدار جریان اختصاص داده نشده باشد، به بعدی اختصاص داده می شود
یکی از استخر جریان های خودکار.
برای رفع یک جریان تصادفی متغیر به یک جریان زیربنایی خاص، آن را اختصاص دهید جریان
نسبت به یک عدد صحیح غیر منفی (مقدار پیش فرض -1 به این معنی است که یک مقدار خواهد بود
به طور خودکار تخصیص داده می شود).
انتشار خود را نتایج
هنگامی که نتایج شبیه سازی را منتشر می کنید، یک قطعه کلیدی از اطلاعات پیکربندی است که شما
همیشه باید بیان کند که چگونه از مولد اعداد تصادفی استفاده کردید.
· از چه دانه هایی استفاده کردید،
· اگر پیشفرض نباشد، از چه RNG استفاده کردهاید،
· اجراهای مستقل چگونه انجام شد،
· برای شبیه سازی های بزرگ، چگونه بررسی کردید که دوچرخه سواری نکرده اید.
انتشار نتایج بر عهده محقق است که اطلاعات کافی را درج کند
به دیگران اجازه دهید نتایج او را بازتولید کنند. همچنین بر عهده محقق است
خود را متقاعد کنید که اعداد تصادفی استفاده شده از نظر آماری معتبر هستند و بیان کنید
مقاله چرا چنین اطمینانی در نظر گرفته شده است.
خلاصه
بیایید مرور کنیم که چه کارهایی باید هنگام ایجاد یک شبیه سازی انجام دهید.
· تصمیم بگیرید که آیا با یک دانه ثابت یا تصادفی در حال دویدن هستید. یک دانه ثابت است
پیش فرض،
· تصمیم بگیرید که چگونه می خواهید تکرارهای مستقل را مدیریت کنید، در صورت لزوم،
· خود را متقاعد کنید که مقادیر تصادفی بیشتری از طول چرخه ترسیم نمی کنید، اگر
شما در حال اجرای یک شبیه سازی بسیار طولانی هستید، و
· هنگام انتشار، دستورالعمل های بالا را در مورد مستندسازی استفاده خود از تصادفی دنبال کنید
مولد اعداد
مخلوط توابع
ns-3 یک رابط عمومی برای توابع هش با هدف عمومی فراهم می کند. در ساده ترین حالت
استفاده، تابع هش هش 32 بیتی یا 64 بیتی یک بافر یا رشته داده را برمی گرداند.
تابع هش پیش فرض زیربنایی است زمزمه 3، انتخاب شده است زیرا عملکرد هش خوبی دارد
خواص و نسخه 64 بیتی را ارائه می دهد. ارجمند FNV1a هش نیز موجود است.
مکانیزم مستقیمی برای افزودن (یا ارائه در زمان اجرا) هش جایگزین وجود دارد
پیاده سازی تابع
اساسی استفاده
ساده ترین راه برای بدست آوردن مقدار هش بافر یا رشته داده فقط این است:
#include "ns3/hash.h"
با استفاده از فضای نام ns3;
کاراکتر * بافر = ...
اندازه_t بافر_اندازه = ...
uint32_t buffer_hash = Hash32 ( buffer, buffer_size);
std::string s;
uint32_t string_hash = Hash32 (s);
توابع معادل برای مقادیر هش 64 بیتی تعریف شده است.
افزایشی هشی کردن
در برخی موقعیتها، محاسبه هش چند بافر مفید است، گویی که دارند
به هم پیوسته اند. (به عنوان مثال، شما ممکن است هش یک جریان بسته را بخواهید، اما نه
می خواهید یک بافر واحد با محتویات ترکیبی همه بسته ها جمع آوری کنید.)
این تقریباً به همان سادگی مثال اول است:
#include "ns3/hash.h"
با استفاده از فضای نام ns3;
کاراکتر * بافر;
size_t buffer_size;
هاشر هشر; // از تابع هش پیش فرض استفاده کنید
برای ( )
{
بافر = get_next_buffer ();
هشر (بافر، بافر_اندازه)؛
}
uint32_t ترکیبی_هش = hasher.GetHash32 ();
به صورت پیش فرض هشر حالت داخلی را برای فعال کردن هش افزایشی حفظ می کند. اگر شما می خواهید
استفاده مجدد a هشر شی (مثلاً چون با هش غیر پیشفرض پیکربندی شده است
تابع)، اما نمی خواهید به هش محاسبه شده قبلی اضافه کنید، باید این کار را انجام دهید روشن ()
اولین:
hasher.clear ().GetHash32 (بافر، بافر_اندازه);
این حالت داخلی را قبل از هش کردن بافر مجدداً آغاز می کند.
با استفاده از an دیگر مخلوط عملکرد
تابع هش پیش فرض است زمزمه 3. FNV1a نیز موجود است. برای مشخص کردن هش
به طور صریح عمل کنید، از این سازنده استفاده کنید:
Hasher hasher = هاشر ( ایجاد ())؛
اضافه کردن جدید مخلوط عملکرد پیاده سازی ها
برای اضافه کردن تابع هش فو، دنبال کن hash-murmur3.h/. رونوشت الگو:
· ایجاد یک اعلان کلاس (.h) و تعریف (. رونوشت) ارث بردن از
Hash:: پیاده سازی.
· شامل اعلامیه در hash.h (در نقطه ای که hash-murmur3.h گنجانده شده است.
· در کد خود، a را نمونه کنید هشر شی از طریق سازنده هشر
(Ptr ())
اگر تابع هش شما یک تابع است، به عنوان مثال هشف، حتی نیازی به ایجاد a نیست
کلاس جدید مشتق شده از HashImplementation:
هاشر هشر =
هاشر (ایجاد (&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
· SMHasher: http://code.google.com/p/smhasher/
· Sanmayce: http://www.sanmayce.com/Fastest_Hash/index.html
رویدادها و شبیه ساز
ns-3 یک شبیه ساز شبکه رویداد گسسته است. از نظر مفهومی، شبیه ساز a را پیگیری می کند
تعداد رویدادهایی که قرار است در یک زمان شبیه سازی مشخص اجرا شوند. کار از
شبیه ساز این است که رویدادها را به ترتیب زمانی اجرا کند. پس از اتمام
یک رویداد رخ می دهد، شبیه ساز به رویداد بعدی منتقل می شود (یا اگر وجود نداشته باشد، خارج می شود
رویدادهای بیشتر در صف رویداد). اگر مثلاً رویدادی برای زمان شبیه سازی برنامه ریزی شده باشد
"100 ثانیه" اجرا می شود و رویداد بعدی تا "200 ثانیه" برنامه ریزی نشده است.
شبیه ساز بلافاصله از 100 ثانیه به 200 ثانیه (از زمان شبیه سازی) به
رویداد بعدی را اجرا کنید این همان چیزی است که از شبیه ساز "رویداد گسسته" استفاده می شود.
برای اینکه همه این اتفاق بیفتد، شبیه ساز به چند چیز نیاز دارد:
1. یک شی شبیه ساز که می تواند به صف رویدادی که رویدادها در آن ذخیره می شوند و می تواند دسترسی داشته باشد
مدیریت اجرای رویدادها
2. زمانبندی مسئول درج و حذف رویدادها از صف
3. راهی برای نمایش زمان شبیه سازی
4. خود حوادث
این فصل از راهنما این اشیاء اساسی (شبیه ساز، زمانبندی،
زمان، رویداد) و نحوه استفاده از آنها.
واقعه
به be تکمیل شده
شبیه ساز
کلاس Simulator نقطه ورود عمومی برای دسترسی به امکانات برنامه ریزی رویداد است. یک بار
چند رویداد برای شروع شبیه سازی برنامه ریزی شده است، کاربر می تواند شروع کند
آنها را با وارد کردن حلقه اصلی شبیه ساز (تماس شبیه ساز::اجرا کنید). یک بار حلقه اصلی
شروع به اجرا می کند، تمام رویدادهای برنامه ریزی شده را به ترتیب از قدیمی ترین تا به ترتیب اجرا می کند
جدیدترین تا زمانی که یا هیچ رویداد دیگری در صف رویداد باقی نمانده باشد یا
Simulator::Stop فراخوانی شده است.
برای برنامه ریزی رویدادها برای اجرا توسط حلقه اصلی شبیه ساز، کلاس Simulator فراهم می کند
خانواده توابع Simulator::Schedule*.
1. مدیریت رویدادها با امضاهای مختلف
این توابع به عنوان قالب های ++C اعلام و پیاده سازی می شوند تا به طور خودکار مدیریت شوند
طیف گسترده ای از امضاهای کنترل کننده رویداد C++ که در طبیعت استفاده می شود. به عنوان مثال، برای برنامه ریزی یک
رویداد برای اجرای 10 ثانیه در آینده، و فراخوانی یک متد یا تابع C++ با آن
آرگومان های خاص، می توانید این را بنویسید:
کنترل کننده خالی (int arg0، int arg1)
{
std::cout << "هندلر با آرگومان arg0=" << arg0 << " و
arg1=" << arg1 << std::endl;
}
شبیه ساز::Schedule(ثانیه(10)، &handler، 10، 5);
که خروجی خواهد داشت:
کنترل کننده با آرگومان arg0=10 و arg1=5 فراخوانی می کند
البته، این قالبهای ++C میتوانند روشهای عضو شفاف در C++ را نیز مدیریت کنند
اشیاء:
به be تکمیل شد: عضو روش مثال
یادداشت:
· متدهای ns-3 Schedule به طور خودکار توابع و روش ها را فقط در صورتی تشخیص می دهند که آنها را انجام دهند
کمتر از 5 آرگومان بگیرید اگر به آنها برای پشتیبانی از آرگومان های بیشتر نیاز دارید، لطفاً a را بایگانی کنید
گزارش اشکال.
· خوانندگانی که با اصطلاح "عملکردهای کاملاً محدود" آشنا هستند، این را تشخیص خواهند داد
Simulator::زمان بندی روش ها به عنوان راهی برای ساخت خودکار چنین اشیایی.
2. عملیات برنامه ریزی مشترک
Simulator API طوری طراحی شده است که زمانبندی بیشتر رویدادها را بسیار ساده کند. آی تی
سه نوع را برای انجام این کار ارائه می دهد (به ترتیب از متداول ترین به کم استفاده تر):
· روشهایی را برنامهریزی کنید که به شما امکان میدهند یک رویداد را در آینده با ارائه آن برنامهریزی کنید
تاخیر بین زمان شبیه سازی فعلی و تاریخ انقضای رویداد هدف.
· روش های ScheduleNow که به شما امکان می دهد یک رویداد را برای شبیه سازی فعلی برنامه ریزی کنید
زمان: آنها _بعد_از_ اجرای رویداد فعلی اجرا خواهند کرد اما _قبل از_
زمان شبیه سازی برای رویداد بعدی تغییر می کند.
· روشهای ScheduleDestroy که به شما امکان میدهد در فرآیند خاموش کردن شبیهساز قلاب کنید
برای پاکسازی منابع شبیهسازی: هر رویداد «نابودی» با تماس کاربر اجرا میشود
روش Simulator::Destroy.
3. حفظ زمینه شبیه سازی
دو راه اساسی برای برنامه ریزی رویدادها وجود دارد، با و بدون زمینه. این چیست؟
معنی است؟
Simulator::Schedule (Time const &time, MEM mem_ptr, OBJ obj);
در مقابل
شبیه ساز::ScheduleWithContext (context uint32_t، زمان و زمان صرفه، MEM mem_ptr، OBJ obj)؛
خوانندگانی که زمان و تلاش خود را برای توسعه یا استفاده از یک مدل شبیه سازی غیر پیش پا افتاده صرف می کنند
ارزش چارچوب ثبت ns-3 را برای اشکال زدایی شبیه سازی های ساده و پیچیده می داند
یکسان یکی از ویژگی های مهمی که توسط این چارچوب ورود به سیستم ارائه می شود، این است
نمایش خودکار شناسه گره شبکه مرتبط با رویداد در حال اجرا "در حال حاضر".
شناسه گره گره شبکه در حال اجرا در واقع توسط شبیه ساز ردیابی می شود
کلاس با متد Simulator::GetContext می توان به آن دسترسی پیدا کرد
"context" (یک عدد صحیح 32 بیتی) مرتبط و در رویداد در حال اجرا ذخیره می شود. که در
برخی از موارد نادر، زمانی که یک رویداد با یک گره شبکه خاص مرتبط نیست، آن است
'context' روی 0xffffffff تنظیم شده است.
برای مرتبط کردن یک زمینه به هر رویداد، متدهای Schedule و ScheduleNow به طور خودکار
استفاده مجدد از زمینه رویداد در حال اجرا به عنوان زمینه رویداد برنامه ریزی شده
برای اعدام بعدا
در برخی موارد، به ویژه هنگام شبیه سازی انتقال یک بسته از یک گره به
دیگر، این رفتار نامطلوب است زیرا زمینه مورد انتظار رویداد پذیرایی است
گره دریافت کننده، نه گره فرستنده. برای جلوگیری از این مشکل، شبیه ساز
کلاس یک روش زمانبندی خاص ارائه می دهد: ScheduleWithContext که به فرد اجازه می دهد تا ارائه دهد
به صراحت شناسه گره گره دریافت کننده مرتبط با رویداد دریافت.
XXX: رمز مثال
در برخی موارد بسیار نادر، توسعه دهندگان ممکن است نیاز به تغییر یا درک چگونگی زمینه داشته باشند
(شناسه گره) رویداد اول روی گره مرتبط با آن تنظیم می شود. این امر محقق شده است
توسط کلاس NodeList: هر زمان که یک گره جدید ایجاد می شود، کلاس NodeList استفاده می کند
ScheduleWithContext برای برنامه ریزی یک رویداد 'initialize' برای این گره. رویداد "آغاز کردن".
بنابراین با یک متن تنظیم شده به شناسه گره اجرا می شود و می تواند از انواع معمولی استفاده کند
روش های برنامه ریزی متد Node::Initialize را فراخوانی می کند که "initialize" را منتشر می کند.
رویداد با فراخوانی متد DoInitialize برای هر شی مرتبط با گره. را
روش DoInitialize در برخی از این اشیا (به ویژه در برنامه کاربردی) لغو شده است
کلاس پایه) برخی رویدادها (به ویژه Application::StartApplication) را برنامه ریزی می کند
به نوبه خود رویدادهای تولید ترافیک را برنامه ریزی می کند که به نوبه خود برنامه ریزی می کند
رویدادهای سطح شبکه
یادداشت:
· کاربران باید مراقب باشند تا متدهای DoInitialize را با فراخوانی در سراسر اشیا منتشر کنند
به صراحت روی اشیاء عضو خود مقداردهی اولیه کنند
· شناسه زمینه مرتبط با هر روش ScheduleWithContext کاربردهای دیگری فراتر از آن دارد
logging: توسط یک شاخه تجربی از ns-3 برای انجام شبیه سازی موازی استفاده می شود
سیستم های چند هسته ای با استفاده از چند رشته ای
توابع Simulator::* نمی دانند که زمینه چیست: آنها فقط از آن اطمینان دارند
هر زمینه ای که با ScheduleWithContext مشخص می کنید در صورت متناظر در دسترس است
رویداد با ::GetContext اجرا می شود.
این به مدلهای پیادهسازی شده در بالای Simulator::* بستگی دارد تا مقدار متن را تفسیر کنند.
در ns-3، مدل های شبکه زمینه را به عنوان شناسه گره گره تفسیر می کنند
یک رویداد ایجاد کرد به همین دلیل مهم است که ScheduleWithContext را وارد کنید
ns3:: زیر کلاس های کانال زیرا ما در حال تولید یک رویداد از گره i به گره j هستیم و ما
می خواهید مطمئن شوید که رویدادی که روی گره j اجرا می شود زمینه مناسبی دارد.
زمان
به be تکمیل شده
زمان بند
به be تکمیل شده
پاسخگویی
برخی از کاربران جدید به ns-3 با یک اصطلاح برنامه نویسی که به طور گسترده استفاده می شود آشنا نیستند
در سراسر کد: the ns-3 فراخوان. این فصل انگیزه هایی در مورد
پاسخ به تماس، راهنمایی در مورد نحوه استفاده از آن، و جزئیات در مورد اجرای آن.
پاسخگویی انگیزه
در نظر بگیرید که شما دو مدل شبیه سازی A و B دارید و می خواهید آنها را پاس کنید
اطلاعات بین آنها در طول شبیه سازی. یکی از راه هایی که می توانید این کار را انجام دهید این است که شما
می توانند A و B را به طور صریح در مورد دیگری آگاه کنند تا بتوانند استناد کنند
روش ها بر روی یکدیگر:
کلاس A {
عمومی:
void ReceiveInput ( // پارامترها );
...
}
(در یک فایل منبع دیگر:)
کلاس B {
عمومی:
void DoSomething (باطل);
...
خصوصی:
A* a_instance; // اشاره گر به A
}
از درجه اعتبار ساقط
B::DoSomething()
{
// به یک مثال بگویید که اتفاقی افتاده است
a_instance->ReceiveInput (// پارامترها);
...
}
این مطمئناً کار می کند، اما این اشکال را دارد که وابستگی به A و B ایجاد می کند
دانستن در مورد دیگری در زمان کامپایل (این امر مستقل بودن را دشوارتر می کند
واحدهای کامپایل در شبیه ساز) و تعمیم داده نشده است. اگر در سناریوی استفاده بعدی،
B باید با یک شی کاملاً متفاوت C صحبت کند، کد منبع برای B باید باشد
تغییر برای اضافه کردن a ج_مثال و غیره به راحتی می توان فهمید که این یک نیروی بی رحم است
مکانیسم ارتباطی که می تواند منجر به برنامه ریزی در مدل ها شود.
این بدان معنا نیست که اجسام در صورت وجود سختی نباید از یکدیگر اطلاع داشته باشند
وابستگی بین آنها وجود دارد، اما اغلب مدل را میتوان انعطافپذیرتر کرد
تعاملات در زمان کامپایل کمتر محدود می شوند.
این یک مشکل انتزاعی برای تحقیقات شبیه سازی شبکه نیست، بلکه یک مشکل بوده است
منبع مشکلات در شبیه سازهای قبلی، زمانی که محققان می خواهند آن را گسترش یا اصلاح کنند
سیستمی برای انجام کارهای مختلف (همانطور که در تحقیقات مستعد انجام آنها هستند). برای مثال در نظر بگیرید
کاربری که می خواهد یک زیرلایه پروتکل امنیتی IPsec بین TCP و IP اضافه کند:
----------------------
| TCP | | TCP |
----------------------
| می شود -> |
----------- -----------
| IP | | IPsec |
----------- -----------
|
-----------
| IP |
-----------
اگر شبیهساز مفروضاتی را ایجاد کرده باشد و کد را به صورت سخت در کد قرار داده باشد، آن IP همیشه صحبت میکند
به پروتکل حمل و نقل بالا، کاربر ممکن است مجبور به هک کردن سیستم برای دریافت آن شود
اتصالات دلخواه واضح است که این یک راه بهینه برای طراحی یک ژنریک نیست
شبیه ساز
پاسخگویی زمینه
توجه:
خوانندگانی که با تماس های برنامه نویسی آشنا هستند ممکن است این بخش آموزشی را نادیده بگیرند.
مکانیسم اساسی که به شخص اجازه می دهد مشکل فوق را حل کند به عنوان a شناخته می شود فراخوان.
هدف نهایی اجازه دادن به یک قطعه کد برای فراخوانی یک تابع (یا متد در C++) است.
بدون هیچ گونه وابستگی بین ماژول خاصی.
این در نهایت به این معنی است که شما به نوعی غیرمستقیم نیاز دارید -- شما آدرس آن را درمان می کنید
تابع به عنوان یک متغیر نامیده می شود. این متغیر را متغیر اشاره گر به تابع می نامند.
رابطه بین تابع و اشاره گر به تابع واقعاً تفاوتی ندارد
که از شی و اشاره گر به شی.
در C مثال متعارف یک اشاره گر به تابع a است
اشاره گر به تابع-بازگشت-عدد صحیح (PFI). برای PFI که یک پارامتر int دریافت می کند، این است
می تواند به این صورت اعلام شود:
int (*pfi)(int arg) = 0;
چیزی که از این به دست می آورید یک متغیر به نام ساده است pfi که به مقدار 0 مقدار دهی اولیه می شود.
اگر میخواهید این اشارهگر را به چیزی معنادار مقداردهی کنید، باید a داشته باشید
عملکرد با امضای منطبق در این مورد:
int MyFunction (int arg) {}
اگر این هدف را دارید، می توانید متغیر را مقداردهی اولیه کنید تا به تابع شما اشاره کند مانند:
pfi = MyFunction;
سپس میتوانید با استفاده از فرم پیشنهادی تماس، بهطور غیرمستقیم با MyFunction تماس بگیرید:
int result = (*pfi) (1234);
این موضوع پیشنهادی است زیرا به نظر می رسد که شما فقط اشاره گر تابع را حذف می کنید
مثل اینکه شما هر اشاره گر را حذف می کنید. با این حال، به طور معمول، مردم از مزایای آن استفاده می کنند
این واقعیت که کامپایلر میداند چه اتفاقی میافتد و فقط از یک فرم کوتاهتر استفاده میکند:
int result = pfi (1234);
توجه داشته باشید که نشانگر تابع از معنایی ارزش تبعیت می کند، بنابراین می توانید آن را مانند هر مورد دیگری منتقل کنید
ارزش دیگر به طور معمول، هنگامی که از یک رابط ناهمزمان استفاده می کنید، مقداری موجودیت را ارسال می کنید
مانند این به تابعی که یک عمل و صدا به عقب تا به شما اطلاع بدهم
تکمیل شد. با دنبال کردن مسیر غیر مستقیم و اجرای تابع ارائه شده، دوباره فراخوانی می کند.
در C++ شما پیچیدگی اضافه ای از اشیاء را دارید. قیاس با PFI بالا به معنای شماست
یک اشاره گر به یک تابع عضو داشته باشید که یک int (PMI) را به جای اشاره گر به برمی گرداند
تابعی که یک int (PFI) را برمی گرداند.
اعلان متغیری که جهت غیرمستقیم را ارائه می کند فقط کمی متفاوت به نظر می رسد:
int (MyClass::*pmi) (int arg) = 0;
این یک متغیر به نام را اعلام می کند بعد از ظهر همانطور که مثال قبلی یک متغیر را با نام اعلام کرد
pfi. از آنجایی که اراده فراخوانی متدی از یک نمونه از یک کلاس خاص است، باید
آن متد را در یک کلاس اعلام کنید:
کلاس MyClass {
عمومی:
int MyMethod (int arg)؛
};
با توجه به این اعلان کلاس، می توان آن متغیر را به صورت زیر مقداردهی کرد:
pmi = &MyClass::MyMethod;
این آدرس کد پیادهسازی متد را به متغیر، تکمیل میکند
غیر جهت برای فراخوانی یک متد، کد به a نیاز دارد این اشاره گر این به نوبه خود،
به این معنی است که باید یک شی از MyClass وجود داشته باشد تا به آن رجوع شود. یک مثال ساده از این فقط است
فراخوانی یک متد به صورت غیر مستقیم (فکر کنید تابع مجازی):
int (MyClass::*pmi) (int arg) = 0; // یک PMI را اعلام کنید
pmi = &MyClass::MyMethod; // به کد پیاده سازی اشاره کنید
MyClass myClass; // نیاز به یک نمونه از کلاس
(myClass.*pmi) (1234); // متد را با یک شیء ptr فراخوانی کنید
درست مانند مثال C، می توانید از آن در تماس ناهمزمان با ماژول دیگری استفاده کنید
که خواهد شد صدا به عقب با استفاده از یک متد و یک اشاره گر شی پسوند ساده
می توان در نظر گرفت که یک اشاره گر به شی و متغیر PMI ارسال شود. ماژول
فقط انجام خواهد داد:
(*objectPtr.*pmi) (1234);
برای اجرای callback روی شی مورد نظر.
ممکن است در این زمان بپرسد، چه la نقطه? ماژول فراخوانی شده باید بفهمد
نوع عینی شیء فراخوان به منظور برقراری صحیح پاسخ تماس. چرا که نه
فقط این را بپذیرید، نشانگر شی که به درستی تایپ شده را ارسال کنید و انجام دهید شی ->روش(1234) in
کد به جای پاسخ به تماس؟ این دقیقاً همان مشکلی است که در بالا توضیح داده شد. چیست
مورد نیاز راهی برای جدا کردن کامل تابع فراخوانی از کلاس فراخوانی شده است. این
نیاز منجر به توسعه عامل.
فانککتور نتیجه چیزی است که در دهه 1960 اختراع شد به نام بسته شدن. این است
اساساً فقط یک فراخوانی تابع بسته بندی شده، احتمالاً با یک وضعیت.
یک تابع دارای دو بخش است، یک بخش خاص و یک بخش عمومی که از طریق وراثت مرتبط هستند.
کد فراخوانی (کدی که پاسخ تماس را اجرا می کند) یک سربارگذاری عمومی را اجرا می کند
اپراتور () یک تابع عمومی برای فراخوانی تماس برگشتی. کد فراخوانی شده (
کدی که میخواهد دوباره فراخوانی شود) باید یک پیادهسازی تخصصی از آن ارائه کند
la اپراتور () که کار خاص کلاس را که باعث جفت شدن نزدیک شد انجام می دهد
مشکل بالا
با تابع خاص و بارگذاری بیش از حد آن اپراتور () ایجاد شده، کد فراخوانی شده است
کد تخصصی را به ماژولی می دهد که پاسخ تماس را اجرا می کند (تماس
کد).
کد فراخوانی یک تابع عمومی را به عنوان پارامتر می گیرد، بنابراین یک ارسال ضمنی انجام می شود
در فراخوانی تابع برای تبدیل تابع خاص به یک تابع عمومی. این یعنی
که ماژول فراخوان فقط باید نوع تابع عمومی را درک کند. جدا شده است
از کد تماس به طور کامل.
اطلاعاتی که فرد برای ساختن یک تابع خاص نیاز دارد، اشاره گر شی و نشانگر است
آدرس اشاره گر به روش
ماهیت چیزی که باید اتفاق بیفتد این است که سیستم یک بخش عمومی از آن را اعلام کند
عامل:
قالب
کارکرد کلاس
{
عمومی:
virtual int operator() (T arg) = 0;
};
تماس گیرنده بخش خاصی از تابع را تعریف می کند که واقعاً برای پیاده سازی وجود دارد
خاص اپراتور() روش:
قالب
کلاس SpecificFunctor: عمومی Functor
{
عمومی:
SpecificFunctor(T* p، int (T::*_pmi)(ARG arg))
{
m_p = p;
m_pmi = _pmi;
}
virtual int operator() (ARG arg)
{
(*m_p.*m_pmi)(arg);
}
خصوصی:
int (T::*m_pmi)(ARG arg);
T* m_p;
};
در اینجا یک مثال از استفاده است:
کلاس A
{
عمومی:
A (int a0): a (a0) {}
int سلام (int b0)
{
std::cout << "سلام از A, a = " << a << " b0 = " << b0 << std::endl;
}
int a؛
};
int اصلی ()
{
A a(10)؛
SpecificFunctor sf(&a, &A::سلام);
sf(5)؛
}
توجه:
کد قبلی کد ns-3 واقعی نیست. این کد نمونه ساده ای است که فقط برای آن استفاده می شود
مفاهیم درگیر را نشان دهد و به شما در درک بیشتر سیستم کمک کند. انجام ندهید
انتظار می رود این کد را در هر جایی از درخت ns-3 پیدا کنید.
توجه داشته باشید که دو متغیر در کلاس بالا تعریف شده است. متغیر m_p است
اشاره گر شی و m_pmi متغیری است که حاوی آدرس تابع به است
اجرا کردن.
توجه داشته باشید که وقتی اپراتور() فراخوانی می شود، به نوبه خود متدی ارائه شده با the را فراخوانی می کند
اشاره گر شی با استفاده از سینتکس C++ PMI.
برای استفاده از این، میتوان کد مدلی را اعلام کرد که یک تابع عمومی را به عنوان یک میگیرد
پارامتر:
void LibraryFunction (عملکرد تابع).
کدی که با مدل صحبت می کند، یک تابع خاص می سازد و آن را به آن ارسال می کند
عملکرد کتابخانه:
MyClass myClass;
SpecificFunctor تابع (&myclass، MyClass::MyMethod);
چه زمانی عملکرد کتابخانه انجام می شود، پاسخ تماس را با استفاده از اپراتور() در مورد عمومی
تابع آن پاس داده شد، و در این مورد خاص، آرگومان عدد صحیح را ارائه می دهد:
از درجه اعتبار ساقط
LibraryFunction (عملکرد کارکرد)
{
// تابع کتابخانه را اجرا کنید
عامل(1234)؛
}
توجه کنید که عملکرد کتابخانه کاملاً از نوع خاص مشتری جدا شده است.
اتصال از طریق چندشکلی Functor انجام می شود.
Callback API در ns-3 فراخوانی شی گرا را با استفاده از مکانیسم تابع اجرا می کند.
این API برگشتی، که بر اساس الگوهای C++ است، از نظر نوع ایمن است. یعنی ایستا انجام می دهد
بررسی نوع برای اجرای سازگاری امضای مناسب بین تماس گیرندگان و تماس گیرندگان. این است
بنابراین استفاده از نوع ایمن تر از نشانگرهای تابع سنتی است، اما نحو ممکن است
در ابتدا تحمیل کننده به نظر برسید این بخش برای راهنمایی شما در سیستم Callback طراحی شده است
تا بتوانید در استفاده از آن راحت باشید ns-3.
با استفاده از la تماس لطفا API
Callback API تقریباً حداقل است و تنها دو سرویس ارائه می دهد:
1. اعلام نوع برگشت تماس: راهی برای اعلام یک نوع تماس با یک امضای معین،
و،
2. Callback Instantiation: راهی برای نمونهسازی پاسخ به تماس ارسالشده توسط الگو
که می تواند هر تماسی را به متد عضو کلاس C++ یا تابع C++ دیگر ارسال کند.
این به بهترین وجه از طریق قدم زدن در یک مثال، بر اساس مشاهده می شود نمونه ها / پاسخ به تماس اصلی.cc.
با استفاده از la تماس لطفا API با ایستا توابع
یک تابع را در نظر بگیرید:
استاتیک دوبل
CbOne (double a، double b)
{
std::cout << "invoke cbOne a=" << a << ", b=" << b << std::endl;
بازگشت یک؛
}
قطعه برنامه اصلی زیر را نیز در نظر بگیرید:
int main (int argc، char *argv[])
{
// نوع بازگشت: دو برابر
// اولین نوع arg: double
// نوع arg دوم: دوتایی
پاسخ به تماس یک
}
این نمونهای از یک تماس به سبک C است -- یکی که شامل یا نیازی به a ندارد این
اشاره گر قالب تابع تماس لطفا اساساً اعلان متغیر است
حاوی اشاره گر به تابع. در مثال بالا، ما به صراحت یک اشاره گر را نشان دادیم
به تابعی که یک عدد صحیح برمی گرداند و یک عدد صحیح را به عنوان پارامتر می گیرد، The
تماس لطفا تابع قالب یک نسخه عمومی از آن است -- برای اعلام نوع استفاده می شود
از پاسخ به تماس
توجه:
خوانندگانی که با الگوهای C++ آشنا نیستند ممکن است مشورت کنند
http://www.cplusplus.com/doc/tutorial/templates/.
La تماس لطفا الگو به یک آرگومان اجباری نیاز دارد (نوع برگرداندن تابع به
به این فراخوانی اختصاص داده شود) و حداکثر پنج آرگومان اختیاری که هر کدام مشخص می کنند
نوع آرگومان ها (اگر تابع فراخوانی خاص شما بیش از پنج آرگومان داشته باشد،
سپس این را می توان با گسترش اجرای callback مدیریت کرد).
بنابراین در مثال بالا، ما یک callback اعلام شده به نام "one" داریم که در نهایت انجام خواهد شد
یک نشانگر تابع را نگه دارید. امضای تابعی که نگه می دارد باید برگردد
double و باید از دو آرگومان دوگانه پشتیبانی کند. اگر کسی بخواهد تابعی را که
امضا با پاسخ تماس اعلام شده مطابقت ندارد، یک خطای کامپایل رخ خواهد داد. همچنین، اگر
یکی سعی می کند یک تماس ناسازگار را به یک callback اختصاص دهد، کامپایل موفق خواهد شد اما a
زمان اجرا NS_FATAL_ERROR افزایش می یابد. نمونه برنامه
src/core/examples/main-callback.cc هر دوی این موارد خطا را در پایان نشان می دهد
la اصلی () برنامه است.
اکنون، ما باید این نمونه تماس و تابع هدف واقعی را با هم گره بزنیم
(CbOne). در بالا توجه کنید که CbOne دارای همان نوع امضای تابعی است که تماس برگشتی دارد--
این مهم است. ما می توانیم هر تابعی که به درستی تایپ شده است را به این فراخوانی ارسال کنیم.
بیایید به این موضوع دقیق تر نگاه کنیم:
استاتیک دوبل CbOne (double a، double b) {}
^^^
| | |
| | |
پاسخ به تماس یک
تنها در صورتی میتوانید یک تابع را به یک فراخوان متصل کنید که دارای امضای منطبق باشد. اولین
آرگومان template نوع برگشتی است و آرگومان های قالب اضافی انواع هستند
از آرگومان های امضای تابع.
حالا بیایید callback "one" خود را به تابعی که با امضای آن مطابقت دارد متصل کنیم:
// ساخت نمونه تماس برگشتی که به تابع cbOne اشاره می کند
one = MakeCallback (&CbOne)؛
این تماس به MakeCallback در اصل ایجاد یکی از کارکردهای تخصصی است
در بالا ذکر شد. متغیر با استفاده از تماس لطفا تابع قالب در حال رفتن به
نقش عامل عمومی را بازی کنید. تکلیف یک = MakeCallback (&CbOne) is
بازیگری که فانککتور تخصصی شناخته شده برای تماس گیرنده را به یک عامل عمومی تبدیل می کند
برای تماس گیرنده شناخته شده است.
سپس در ادامه برنامه در صورت نیاز به callback می توان به صورت زیر از آن استفاده کرد:
NS_ASSERT (!one.IsNull ());
// تابع cbOne را از طریق نمونه تماس فراخوانی کنید
دو retOne;
retOne = یک (10.0، 20.0)؛
چک برای IsNull() تضمین می کند که تماس برگشتی تهی نیست -- که یک تابع وجود دارد
پشت این تماس تلفنی تماس بگیرید. سپس، یک () عمومی را اجرا می کند اپراتور() که واقعاً
با اجرای خاصی از اپراتور() و همان نتیجه را برمی گرداند که اگر
CbOne() مستقیما تماس گرفته شده بود
با استفاده از la تماس لطفا API با عضو توابع
به طور کلی، شما توابع استاتیک را فراخوانی نمی کنید، بلکه توابع اعضای عمومی را فراخوانی می کنید
یک شی در این مورد، یک آرگومان اضافی برای تابع MakeCallback، به مورد نیاز است
به سیستم بگویید که تابع در کدام شیء باید فراخوانی شود. این مثال را در نظر بگیرید،
همچنین از main-callback.cc:
کلاس MyCb {
عمومی:
int CbTwo (double a) {
std::cout << "invoke cbTwo a=" << a << std::endl;
بازگشت -5 ؛
}
};
intmain()
{
...
// نوع برگشتی: int
// اولین نوع arg: double
پاسخ به تماس دو
MyCb cb;
// ساخت نمونه تماس برگشتی که به MyCb::cbTwo اشاره می کند
دو = MakeCallback (&MyCb::CbTwo، &cb);
...
}
در اینجا، یک اشاره گر شی اضافی را به آن ارسال می کنیم MakeCallback<> عملکرد. یادآوری از
بخش پس زمینه بالای آن اپراتور() هنگامی که از اشاره گر به نحو عضو استفاده می کند
روی یک شی اجرا می کند:
virtual int operator() (ARG arg)
{
(*m_p.*m_pmi)(arg);
}
و بنابراین ما نیاز به ارائه دو متغیر داشتیم (m_p و m_pmi) زمانی که ما مشخص شد
عامل. خط:
دو = MakeCallback (&MyCb::CbTwo، &cb);
دقیقا همین کار را می کند در این مورد، زمانی که دو () فراخوانی می شود:
int result = دو (1.0);
منجر به تماس با شما خواهد شد CbTwo تابع عضو (روش) در شیئی که توسط آن اشاره شده است
&cb.
بنا تهی پاسخگویی
این امکان وجود دارد که کال بک ها تهی باشند. بنابراین ممکن است عاقلانه باشد که قبل از استفاده آنها را بررسی کنید.
یک ساختار ویژه برای یک کال بک تهی وجود دارد که به پاس دادن ساده ترجیح داده می شود
"0" به عنوان یک آرگومان؛ آن است MakeNullCallback<> ساختن:
دو = MakeNullCallback ()
NS_ASSERT (two.IsNull ());
فراخوانی یک فراخوان تهی درست مانند فراخوانی یک نشانگر تابع پوچ است: در آن خراب می شود
زمان اجرا
کران پاسخگویی
یک برنامه افزودنی بسیار مفید برای مفهوم تابع، یک پاسخ به تماس محدود است. قبلا آن را
ذکر شد که بسته شدن ها در اصل فراخوانی های تابعی بودند که برای بعد بسته بندی شده بودند
اجرا. توجه داشته باشید که در تمام توضیحات Callback بالا، راهی برای انجام این کار وجود ندارد
هر پارامتری را برای استفاده در آینده بسته بندی کنید -- زمانی که تماس لطفا از طریق فراخوانی می شود اپراتور().
تمام پارامترها توسط تابع فراخوانی ارائه می شوند.
اگر بخواهیم به تابع کلاینت (کسی که پاسخ تماس را ارائه می دهد) اجازه دهیم چه می شود
برخی از پارامترها را ارائه می دهد؟ الکساندرسکو فرآیند اجازه دادن به مشتری را فرا می خواند
یکی از پارامترها را مشخص کنید "الزام آور". یکی از پارامترهای اپراتور() بوده است
محدود شده (تثبیت شده) توسط مشتری.
برخی از کدهای ردیابی pcap ما مثال خوبی از این موضوع را ارائه می دهند. یک تابع وجود دارد که
هر زمان که بسته ای دریافت می شود باید فراخوانی شود. این تابع یک شی را فراخوانی می کند که
در واقع بسته را با فرمت فایل pcap روی دیسک می نویسد. امضای یکی از اینها
توابع خواهد بود:
فضای خالی استاتیک DefaultSink (Ptr فایل، Ptr پ)؛
کلمه کلیدی استاتیک به این معنی است که این یک تابع ثابت است که نیازی به a ندارد این اشاره گر، بنابراین
از تماسهای C-style استفاده خواهد کرد. ما نمی خواهیم که کد تماس در مورد آن بدانیم
هر چیزی جز بسته آنچه ما در کد تماس می خواهیم فقط یک تماس است که به نظر می رسد:
m_promiscSnifferTrace (m_currentPkt)؛
کاری که ما می خواهیم انجام دهیم این است که اتصال la Ptr پرونده به تماس خاص
پیاده سازی زمانی که ایجاد می شود و ترتیب آن اپراتور() از پاسخ به تماس به
آن پارامتر را به صورت رایگان ارائه دهید.
ما ارائه می دهیم MakeBoundCallback تابع قالب برای این منظور. همین را می گیرد
پارامترها به عنوان MakeCallback تابع قالب اما پارامترها را نیز می گیرد
مقید شده است. در مورد مثال بالا:
MakeBoundCallback (&DefaultSink، فایل)؛
یک پیادهسازی پاسخ به تماس خاص ایجاد میکند که میتواند کران اضافی را اضافه کند
استدلال ها از نظر مفهومی، تابع خاصی که در بالا توضیح داده شد را با یک یا چند گسترش می دهد
آرگومان های مقید:
قالب
کلاس SpecificFunctor: عمومی Functor
{
عمومی:
SpecificFunctor(T* p، int (T::*_pmi) (ARG arg)، BOUND_ARG boundArg)
{
m_p = p;
m_pmi = pmi;
m_boundArg = boundArg;
}
virtual int operator() (ARG arg)
{
(*m_p.*m_pmi)(m_boundArg, arg);
}
خصوصی:
void (T::*m_pmi)(ARG arg);
T* m_p;
BOUND_ARG m_boundArg;
};
می بینید که وقتی تابع خاص ایجاد می شود، آرگومان محدود در آن ذخیره می شود
خود شی تابع / callback. وقتی که اپراتور() با مجرد احضار می شود
پارامتر، مانند:
m_promiscSnifferTrace (m_currentPkt)؛
اجرای اپراتور() پارامتر Bound را به فراخوانی تابع واقعی اضافه می کند:
(*m_p.*m_pmi)(m_boundArg, arg);
می توان دو یا سه آرگومان را نیز باید کرد. بگو ما یک تابع با
امضا:
استاتیک void NotifyEvent (Ptr a، Ptr b، MyEventType e)؛
میتوان دو آرگومان اول را با اتصال برگشتی محدود ایجاد کرد، مانند:
MakeBoundCallback (&NotifyEvent, a1, b1)؛
با فرض اینکه a1 و b1 اشیاء از نوع هستند A و B به ترتیب. به طور مشابه برای سه
آرگومان هایی که می توان با یک امضا عمل کرد:
استاتیک void NotifyEvent (Ptr a، Ptr b، MyEventType e)؛
اتصال سه آرگومان در انجام شده با:
MakeBoundCallback (&NotifyEvent, a1, b1, c1)؛
دوباره با فرض a1, b1 و c1 اشیاء از نوع هستند A, B و C بود.
این نوع اتصال می تواند برای تبادل اطلاعات بین اشیاء در شبیه سازی استفاده شود.
به طور خاص، تماسهای باند را میتوان به عنوان تماسهای ردیابی شده مورد استفاده قرار داد که در ادامه توضیح داده خواهد شد
بخش بعدی
ترسیم پاسخگویی
حفره یا سوراخ زیر بخش
تماس لطفا مکان in ns-3
در کجا از تماس های برگشتی اغلب استفاده می شود ns-3? در اینجا برخی از موارد قابل مشاهده تر برای
کاربران معمولی:
· سوکت API
· Layer-2/Layer-3 API
· زیر سیستم ردیابی
· API بین IP و زیرسیستم های مسیریابی
پیاده سازی جزئیات
قطعات کد بالا ساده هستند و فقط برای نشان دادن مکانیسم طراحی شده اند
خود کد Callback واقعی کاملاً پیچیده است و بسیار قالبی است و a
درک عمیق کد مورد نیاز نیست. در صورت علاقه، کاربران متخصص ممکن است آن را پیدا کنند
دنبال مفید
این کد در ابتدا بر اساس تکنیک های شرح داده شده در نوشته شده است
http://www.codeproject.com/cpp/TTLFunction.asp. متعاقباً برای پیگیری بازنویسی شد
معماری مشخص شده در مدرن ++C طرح، عمومی برنامه نويسي و طرح الگوهای
کاربردی، الکساندرسکو، فصل 5, تعمیم یافته کارکردها.
این کد از:
· پارامترهای قالب پیش فرض برای صرفه جویی در کاربران از نیاز به تعیین پارامترهای خالی زمانی که
تعداد پارامترها از حداکثر تعداد پشتیبانی شده کوچکتر است
· اصطلاح pimpl: کلاس Callback توسط مقدار منتقل می شود و اصل آن را به آن تفویض می کند
کار به نشانگر جوش آن.
· دو پیاده سازی pimpl که از CallbackImpl FunctorCallbackImpl مشتق شده اند را می توان استفاده کرد
با هر نوع تابعی در حالی که MemPtrCallbackImpl را می توان با اشاره گر به عضو استفاده کرد
توابع.
· پیاده سازی لیست مرجع برای پیاده سازی معنایی ارزش Callback.
این کد به طور مشخص از پیادهسازی الکساندرسکو فاصله میگیرد زیرا اینطور نیست
از لیست های نوع برای تعیین و ارسال انواع آرگومان های برگشت به تماس استفاده کنید. البته،
همچنین از معناشناسی کپی تخریب استفاده نمی کند و به جای آن به فهرست مرجع تکیه می کند
autoPtr برای نگه داشتن نشانگر.
شیء مدل
ns-3 اساساً یک سیستم شیء ++C است. اشیاء را می توان به عنوان تعریف و نمونه سازی کرد
معمول، طبق قوانین C++. ns-3 همچنین برخی از ویژگی ها را به اشیاء C++ سنتی اضافه می کند
برای ارائه عملکرد و ویژگی های بیشتر در زیر توضیح داده شده است. این فصل راهنما است
قصد دارد خواننده را با ns-3 مدل شی
این بخش طراحی کلاس C++ را برای ns-3 اشیاء. به طور خلاصه، چندین طرح
الگوهای مورد استفاده شامل طراحی کلاسیک شی گرا (رابط چند شکلی و
پیاده سازی ها)، جداسازی رابط و پیاده سازی، عموم غیر مجازی
الگوی طراحی رابط، تسهیلات تجمع شی، و شمارش مرجع برای
مدیریت حافظه. کسانی که با مدل های کامپوننت مانند COM یا Bonobo آشنا هستند، این کار را خواهند کرد
شناسایی عناصر طراحی در ns-3 مدل تجمع شیء، اگرچه ns-3
طراحی کاملاً مطابق با هیچکدام نیست.
شی گرا رفتار
اشیاء C++، به طور کلی، قابلیت های مشترک شی گرا را ارائه می دهند (انتزاع،
کپسوله سازی، وراثت، و چندشکلی) که بخشی از شی گرا کلاسیک هستند
طرح. ns-3 اشیا از این ویژگی ها استفاده می کنند. برای مثال:
آدرس کلاس
{
عمومی:
نشانی ()؛
آدرس (نوع uint8_t، const uint8_t *بافر، uint8_t len)؛
آدرس (const آدرس و آدرس)؛
آدرس &اپراتور = (const Address & address);
...
خصوصی:
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() با استفاده از شمارش مرجع تا حدودی تسکین می یابد
کلاس اشاره گر هوشمند در زیر توضیح داده شده است.
کاربرانی که از یک API سطح پایین استفاده میکنند و میخواهند به صراحت اشیاء غیرمرجع شمارش شده را تخصیص دهند.
روی پشته، با استفاده از عملگر new، مسئول حذف چنین اشیایی هستند.
ارجاع با احتساب هوشمند اشارهگر (Ptr)
صدا زدن مرجع() و Unref() همه وقت دست و پا گیر خواهد بود، بنابراین ns-3 هوشمند را فراهم می کند
کلاس اشاره گر پترن مشابه تقویت::intrusive_ptr. این کلاس اشاره گر هوشمند این را فرض می کند
نوع زیرین یک جفت از کد عکس و Unref روش هایی که انتظار می رود
افزایش و کاهش تعداد مجدد داخلی نمونه شی.
این پیاده سازی به شما امکان می دهد تا نشانگر هوشمند را طوری دستکاری کنید که گویی یک حالت عادی است
اشاره گر: می توانید آن را با صفر مقایسه کنید، آن را با دیگر نشانگرها مقایسه کنید، صفر را به آن اختصاص دهید
آن و غیره
استخراج نشانگر خام از این اشاره گر هوشمند با GetPointer()
و PeekPointer() مواد و روشها.
اگر می خواهید یک شی جدید را در یک اشاره گر هوشمند ذخیره کنید، توصیه می کنیم از آن استفاده کنید
توابع قالب CreateObject برای ایجاد شی و ذخیره آن در یک اشاره گر هوشمند
جلوگیری از نشت حافظه این توابع واقعاً توابع راحتی کوچک و هدف آنها هستند
فقط برای صرفه جویی در مقدار کمی از تایپ کردن است.
CreateObject و ساختن
اشیاء در C++ ممکن است به صورت ایستا، پویا یا خودکار ایجاد شوند. این درست است
برای ns-3 همچنین، اما برخی از اشیاء در سیستم دارای چارچوب های اضافی در دسترس هستند.
به طور خاص، اشیاء شمارش مرجع معمولاً با استفاده از Create یا الگوی تخصیص داده می شوند
متد CreateObject به شرح زیر است.
برای اشیاء مشتق شده از کلاس شیء:
Ptr دستگاه = CreateObject ()
لطفا با استفاده از چنین اشیایی ایجاد نکنید اپراتور جدید; آنها را با استفاده از CreateObject()
به جای آن.
برای اشیاء مشتق شده از کلاس SimpleRefCount، یا سایر اشیایی که از استفاده پشتیبانی می کنند
کلاس اشاره گر هوشمند، یک تابع کمکی قالب موجود است و توصیه می شود از آن استفاده کنید:
Ptr b = ایجاد ();
این به سادگی یک بسته بندی در اطراف اپراتور جدید است که شمارش مرجع را به درستی مدیریت می کند
سیستم.
به طور خلاصه استفاده کنید ایجاد کردن اگر B یک شی نیست اما فقط از شمارش مرجع استفاده می کند (مثلا
بسته)، و استفاده کنید CreateObject اگر B از ns3:: شی.
تجمع
La ns-3 سیستم تجمیع اشیاء تا حد زیادی با شناختی که الف
مورد استفاده رایج برای ns-2 استفاده از وراثت و چندشکلی برای گسترش بوده است
مدل های پروتکل به عنوان مثال، نسخه های تخصصی TCP مانند RenoTcpAgent مشتق می شوند
از (و لغو توابع از) کلاس TcpAgent.
با این حال، دو مشکل که در آن بوجود آمده است ns-2 مدل های پایین و "پایه ضعیف
class." Downcasting به روش استفاده از اشاره گر کلاس پایه به یک شی اشاره دارد و
پرس و جو آن در زمان اجرا برای یافتن اطلاعات نوع، که برای فرستادن صریح اشاره گر استفاده می شود
به یک نشانگر زیر کلاس تا بتوان از API زیر کلاس استفاده کرد. کلاس پایه ضعیف به
مشکلاتی که زمانی بوجود می آیند که یک کلاس نمی تواند به طور موثر مورد استفاده مجدد قرار گیرد (از آن گرفته شده است) زیرا آن کلاس
فاقد عملکرد لازم است، که باعث می شود توسعه دهنده مجبور شود کلاس پایه را تغییر دهد و
باعث افزایش فراخوانی های API کلاس پایه می شود که ممکن است برخی از آنها از نظر معنایی نباشند
برای همه زیر کلاس ها درست است.
ns-3 از نسخه ای از الگوی طراحی رابط پرس و جو برای جلوگیری از این مشکلات استفاده می کند.
این طراحی بر اساس عناصری از جزء شیء مدل و گنوم بونوبو اگر چه
سازگاری کامل در سطح باینری اجزای قابل تعویض پشتیبانی نمی شود و ما داریم
سعی در ساده سازی نحو و تاثیر بر توسعه دهندگان مدل داشت.
مثال ها
تجمع مثال
گره نمونه خوبی از استفاده از تجمع در ns-3. توجه داشته باشید که مشتق نشده است
کلاس های گره در ns-3 مانند کلاس اینترنت نود. در عوض، اجزا (پروتکل ها) هستند
به یک گره تجمیع شده است. بیایید ببینیم که چگونه برخی از پروتکل های Ipv4 به یک گره اضافه می شوند.
باطل استاتیک
AddIpv4Stack(Ptr گره)
{
Ptr ipv4 = CreateObject ()
ipv4->SetNode (گره)؛
node->AggregateObject (ipv4);
Ptr ipv4Impl = CreateObject ()
ipv4Impl->SetIpv4 (ipv4);
node->AggregateObject (ipv4Impl);
}
توجه داشته باشید که پروتکل های Ipv4 با استفاده از آن ایجاد می شوند CreateObject(). سپس آنها جمع می شوند
به گره به این ترتیب، کلاس پایه Node برای اجازه دادن به کاربران نیازی به ویرایش ندارد
با اشاره گر Node کلاس پایه برای دسترسی به رابط Ipv4. کاربران ممکن است از گره درخواست کنند
اشاره گر به رابط Ipv4 آن در زمان اجرا. نحوه درخواست کاربر از گره در قسمت توضیح داده شده است
زیر بخش بعدی
توجه داشته باشید که تجمیع بیش از یک شی از همان نوع یک خطای برنامه نویسی است
an ns3:: شی. بنابراین، به عنوان مثال، تجمیع گزینه ای برای ذخیره همه موارد نیست
سوکت های فعال یک گره
GetObject مثال
GetObject یک روش ایمن برای دستیابی به یک downcasting ایمن و اجازه دادن به رابط ها است
روی یک شی پیدا شد
یک اشاره گر گره را در نظر بگیرید m_node که به یک شی Node اشاره می کند که دارای پیاده سازی است
IPv4 قبلاً به آن تجمیع شده است. کد مشتری می خواهد یک مسیر پیش فرض را پیکربندی کند. به
برای انجام این کار، باید به یک شی در گره دسترسی داشته باشد که دارای یک رابط برای ارسال IP است
پیکربندی موارد زیر را انجام می دهد:
Ptr ipv4 = m_node->GetObject ()
اگر گره در واقع یک شیء Ipv4 نداشته باشد، متد این کار را خواهد کرد
باطل برگرداند. بنابراین، بررسی مقدار بازگشتی از چنین تابعی تمرین خوبی است
زنگ زدن. در صورت موفقیت، کاربر اکنون می تواند از Ptr برای شی Ipv4 که قبلاً بود استفاده کند
به گره جمع می شود.
مثال دیگری از نحوه استفاده از تجمیع، افزودن مدل های اختیاری به اشیا است. برای
به عنوان مثال، یک شی Node موجود ممکن است یک شی "Energy Model" در آن جمع شده باشد
زمان اجرا (بدون تغییر و کامپایل مجدد کلاس گره). یک مدل موجود (مانند الف
دستگاه شبکه بی سیم) می تواند بعداً برای مدل انرژی "GetObject" را انجام دهد و به درستی عمل کند
اگر اینترفیس یا در شی Node زیرین ساخته شده باشد یا در آن جمع شده باشد
آن را در زمان اجرا با این حال، گره های دیگر نیازی به دانستن هیچ چیز در مورد مدل های انرژی ندارند.
ما امیدواریم که این حالت از برنامه نویسی نیاز بسیار کمتری به توسعه دهندگان برای اصلاح داشته باشد
کلاس های پایه
شیء کارخانه
یک مورد معمول استفاده، ایجاد تعداد زیادی از اشیاء با پیکربندی مشابه است. فرد می تواند بارها و بارها
صدا CreateObject() اما یک الگوی طراحی کارخانه نیز در استفاده از آن وجود دارد ns-3 سیستم.
این به شدت در API "helper" استفاده می شود.
طبقه ObjectFactory می توان برای نمونه سازی اشیاء و پیکربندی ویژگی ها استفاده کرد
آن اشیاء:
void SetTypeId (TypeId tid);
void Set (std::نام رشته، const AttributeValue &value);
Ptr ایجاد (باطل) const.
روش اول امکان استفاده از ns-3 سیستم TypeId برای تعیین نوع اشیاء
ایجاد شده. دومی به شخص اجازه میدهد تا ویژگیهایی را روی اشیایی که باید ایجاد شود، تنظیم کند
سوم این امکان را به فرد می دهد تا خود اشیاء را ایجاد کند.
مثلا:
کارخانه ObjectFactory;
// کاری کنید که این کارخانه اشیایی از نوع FriisPropagationLossModel ایجاد کند
factory.SetTypeId ("ns3::FriisPropagationLossModel")
// کاری کنید که این شی کارخانه مقدار پیشفرض یک ویژگی را برای تغییر دهد
// متعاقباً اشیاء ایجاد شد
factory.Set ("SystemLoss"، DoubleValue (2.0));
// یکی از این شی را ایجاد کنید
Ptr object = factory.Create ();
factory.Set ("SystemLoss"، DoubleValue (3.0));
// یک شی دیگر با SystemLoss متفاوت ایجاد کنید
Ptr object = factory.Create ();
پایین انداختن
سوالی که چندین بار مطرح شده این است، "اگر من یک اشاره گر کلاس پایه (Ptr) به an داشته باشم
شی و من اشاره گر کلاس مشتق شده را می خواهم، آیا باید (از طریق C++ dynamic cast) را پایین بیاورم
نشانگر مشتق شده را دریافت کنید، یا باید از سیستم تجمع شی استفاده کنم GetObject<> ()
برای پیدا کردن یک Ptr برای رابط به زیر کلاس API؟"
پاسخ این است که در بسیاری از موقعیت ها، هر دو تکنیک کار خواهند کرد. ns-3 فراهم می کند
تابع قالبی برای ساختن سینتکس Object casting پویا برای کاربر بسیار بیشتر
دوستانه:
قالب
Ptr
DynamicCast (Ptr const&p)
{
بازگشت Ptr (پویا_کست (PeekPointer (p)));
}
DynamicCast زمانی کار می کند که برنامه نویس یک اشاره گر نوع پایه داشته باشد و در حال آزمایش با a است
نشانگر زیر کلاس GetObject زمانی کار می کند که به دنبال اشیاء مختلف جمع آوری می شود، اما همچنین
مانند DynamicCast با زیر کلاس ها کار می کند. اگر مطمئن نیستید، برنامه نویس باید
از GetObject استفاده کنید، زیرا در همه موارد کار می کند. اگر برنامه نویس سلسله مراتب کلاس را بداند
شیء مورد بررسی، استفاده از DynamicCast مستقیم تر است.
پیکر بندی و خواص
In ns-3 شبیه سازی، دو جنبه اصلی برای پیکربندی وجود دارد:
· توپولوژی شبیه سازی و نحوه اتصال اشیا.
· مقادیر استفاده شده توسط مدل های نمونه سازی شده در توپولوژی.
این فصل بر دومین مورد بالا تمرکز میکند: چگونگی استفاده از مقادیر زیادی در آن ns-3 هستند
سازماندهی شده، مستند شده و قابل تغییر توسط ns-3 کاربران ns-3 سیستم ویژگی نیز است
زیربنای چگونگی جمع آوری ردپاها و آمار در شبیه ساز.
در طول این فصل، روشهای مختلف تنظیم یا تغییر مقادیر را مورد بحث قرار خواهیم داد
استفاده شده توسط ns-3 اشیاء مدل به ترتیب افزایش ویژگی، این موارد عبارتند از:
┌─────────────────────────────────┬─────────────── ────────────────────┐
│روش │ محدوده │
├─────────────────────────────────┼─────────────── ────────────────────┤
│مقادیر مشخصه پیش فرض تنظیم شده │ بر همه نمونه های │ تاثیر می گذارد
│زمانی که ویژگی ها در کلاس │ تعریف می شوند. │
│GetTypeId (). │ │
└─────────────────────────────────┴─────────────── ────────────────────┘
│خط فرمان │ همه موارد آینده را تحت تاثیر قرار دهید. │
│پیکربندی::SetDefault() │
│ConfigStore │
├─────────────────────────────────┼─────────────── ────────────────────┤
│ObjectFactory │ بر همه نمونه های ایجاد شده تاثیر می گذارد │
│ │ با کارخانه. │
├─────────────────────────────────┼─────────────── ────────────────────┤
│XHelperSetAttribute () │ بر همه موارد ایجاد شده توسط │ تأثیر می گذارد
│ │ یاور. │
├─────────────────────────────────┼─────────────── ────────────────────┤
│MyClass::SetX () │ این نمونه خاص را تغییر می دهد. │
│Object::SetAttribute () │ به طور کلی این تنها شکل │ است
│پیکربندی::Set() │ که می توان برای تغییر برنامه ریزی کرد │
│ │ یک نمونه یک بار شبیه سازی │
│ │ در حال اجرا است. │
└─────────────────────────────────┴─────────────── ────────────────────┘
منظور ما از «ویژگی» این است که روشهای ردیفهای بعدی جدول، مقادیر تنظیمشده را لغو میکنند
توسط، و معمولاً نمونه های کمتری را نسبت به روش های قبلی تحت تأثیر قرار می دهند.
قبل از پرداختن به جزئیات سیستم ارزش ویژگی، مرور برخی از آنها کمک خواهد کرد
ویژگی های اساسی کلاس شیء.
شیء بررسی اجمالی
ns-3 اساساً یک سیستم مبتنی بر شیء ++C است. منظور ما این است که کلاس های C++ جدید
(انواع) را می توان به طور معمول اعلام، تعریف و طبقه بندی کرد.
بسیاری ns-3 اشیاء از شیء کلاس پایه این اشیاء دارای مقداری اضافی هستند
ویژگی هایی که ما از آنها برای سازماندهی سیستم و بهبود مدیریت حافظه استفاده می کنیم
از اشیاء ما:
· سیستم "فراداده" که نام کلاس را به بسیاری از متا اطلاعات در مورد آن پیوند می دهد
شی، از جمله:
· کلاس پایه زیر کلاس،
· مجموعه سازنده های قابل دسترسی در زیر کلاس،
· مجموعه "ویژگی"های زیر کلاس،
· آیا هر ویژگی می تواند تنظیم شود یا فقط خواندنی است،
· محدوده مجاز مقادیر برای هر ویژگی.
· پیاده سازی اشاره گر هوشمند شمارش مرجع، برای مدیریت حافظه.
ns-3 اشیایی که از سیستم صفت استفاده می کنند از هر کدام مشتق می شوند شیء or ObjectBase. اکثر
ns-3 اشیایی که از آنها بحث خواهیم کرد شیء، اما تعدادی که خارج از هوشمند هستند
چارچوب مدیریت حافظه اشاره گر از ObjectBase.
بیایید چند ویژگی این اشیا را بررسی کنیم.
هوشمند اشاره گرها
همانطور که در معرفی شده است ns-3 آموزش ، ns-3 اشیاء توسط حافظه مدیریت می شوند مرجع
با احتساب هوشمند اشارهگر پیاده سازی، کلاس پترن.
اشاره گرهای هوشمند به طور گسترده در ns-3 API ها، برای جلوگیری از انتقال ارجاع به
اشیاء تخصیص داده شده به پشته که ممکن است باعث نشت حافظه شوند. برای بیشتر استفاده های اولیه (سینتکس)، درمان کنید
یک اشاره گر هوشمند مانند یک اشاره گر معمولی:
Ptr nd = ...;
nd->CallSomeFunction ();
// و غیره.
بنابراین، چگونه می توان یک اشاره گر هوشمند به یک شیء، مانند خط اول این مثال، دریافت کرد؟
CreateObject
همانطور که در بالا در Memory-management-and-class-Ptr، در API پایین ترین سطح، اشیاء بحث کردیم
از نوع شیء با استفاده از آن نمونه سازی نمی شوند اپراتور جدید طبق معمول اما در عوض توسط یک الگو
تابع فراخوانی شد CreateObject ().
یک راه معمولی برای ایجاد چنین شی به شرح زیر است:
Ptr nd = CreateObject ()
شما می توانید این را از نظر عملکردی معادل با:
WifiNetDevice* nd = WifiNetDevice جدید ();
اشیایی که از شیء باید بر روی پشته با استفاده تخصیص داده شود CreateObject (). آن
ناشی از ObjectBase، از جمله ns-3 توابع کمکی و هدرهای بسته و تریلرها،
می توان روی پشته تخصیص داد.
در برخی از اسکریپت ها، ممکن است تعداد زیادی از آنها را نبینید CreateObject () تماس در کد؛ این هست
زیرا برخی از اشیاء کمکی در عمل وجود دارند که این کار را انجام می دهند CreateObject () تماس
برای شما.
TypeId
ns-3 کلاس هایی که از کلاس نشات می گیرند شیء می تواند شامل یک کلاس ابرداده به نام باشد TypeId که
فرااطلاعات مربوط به کلاس را برای استفاده در انباشتگی شی و جزء ثبت می کند
سیستم های مدیریت:
· یک رشته منحصر به فرد شناسایی کلاس.
· کلاس پایه زیر کلاس، در سیستم ابرداده.
· مجموعه سازنده های قابل دسترسی در زیر کلاس.
· فهرستی از ویژگی های قابل دسترسی عمومی ("ویژگی ها") کلاس.
شیء خلاصه
با کنار هم قرار دادن همه این مفاهیم، اجازه دهید به یک مثال خاص نگاه کنیم: کلاس گره.
فایل هدر عمومی node.h دارای یک اعلان است که شامل یک استاتیک است GetTypeId ()
فراخوانی تابع:
کلاس Node: Public Object
{
عمومی:
استاتیک TypeId GetTypeId (باطل)؛
...
این در تعریف شده است node.cc به صورت زیر فایل کنید:
TypeId
Node::GetTypeId (باطل)
{
static TypeId tid = TypeId ("ns3::Node")
SetParent ()
.AddConstructor ()
.AddAttribute ("DeviceList"،
"فهرست دستگاه های مرتبط با این گره."،
ObjectVectorValue ()،
MakeObjectVectorAccessor (&Node::m_devices)،
MakeObjectVectorChecker ())
.AddAttribute ("ApplicationList"،
"فهرست برنامه های مرتبط با این گره."،
ObjectVectorValue ()،
MakeObjectVectorAccessor (&Node::m_applications)،
MakeObjectVectorChecker ())
.AddAttribute ("شناسه"،
"شناسه (عدد صحیح منحصر به فرد) این گره."،
TypeId::ATTR_GET، // فقط اجازه دریافت آن را می دهد.
مقدار واحد (0)،
MakeUintegerAccessor (&Node::m_id)،
MakeUintegerChecker ())
;
برگرد
}
در نظر بگیرید TypeId از ns-3 شیء کلاس به عنوان یک فرم توسعه یافته از نوع زمان اجرا
اطلاعات (RTTI). زبان C++ شامل یک نوع ساده RTTI به منظور پشتیبانی است
دینامیک_کست و نوع گونه اپراتورهای.
La SetParent () call در تعریف بالا در ارتباط با ما استفاده می شود
مکانیسم های تجمع اشیا برای امکان ریخته گری ایمن بالا و پایین در درختان ارثی
در طی GetObject (). همچنین زیر کلاس ها را قادر می سازد تا ویژگی های والد خود را به ارث ببرند
کلاس.
La AddConstructor () فراخوانی در ارتباط با کارخانه آبجکت انتزاعی ما استفاده می شود
مکانیزمهایی که به ما اجازه میدهند اشیاء C++ را بدون اجبار کاربر به دانستن آن بسازیم
کلاس بتنی شیئی که او می سازد.
سه تماس به AddAttribute () یک رشته داده شده را با یک مقدار قوی تایپ شده در مرتبط کنید
کلاس. توجه داشته باشید که باید یک رشته راهنما ارائه دهید که ممکن است نمایش داده شود، به عنوان مثال،
از طريق پردازنده های خط فرمان هر یک صفت با مکانیسم هایی برای دسترسی همراه است
متغیر عضو اصلی در شی (به عنوان مثال، MakeUintegerAccessor () می گوید
عمومی صفت نحوه رسیدن به شناسه گره بالا را کد کنید). همچنین "چکر" وجود دارد
روشهایی که برای اعتبارسنجی مقادیر در برابر محدودیتهای محدوده، مانند حداکثر و
حداقل مقادیر مجاز
هنگامی که کاربران می خواهند گره ایجاد کنند، معمولاً نوعی از آن را فراخوانی می کنند CreateObject (),:
Ptr n = CreateObject ()
یا به طور انتزاعی تر، با استفاده از یک کارخانه آبجکت، می توانید a ایجاد کنید گره شی بدون زوج
دانستن نوع بتن C++:
کارخانه ObjectFactory;
const std::string typeId = "ns3::Node'';
factory.SetTypeId (typeId);
Ptr گره = کارخانه. ایجاد ()
هر دوی این روشها باعث میشوند که ویژگیهای کاملاً اولیه در دسترس باشند
نتیجه شیء مصادیق
سپس در مورد چگونگی ویژگی ها (مقادیر مرتبط با متغیرهای عضو یا توابع) بحث می کنیم
کلاس) به موارد فوق تعلق دارند TypeId.
خواص
هدف سیستم ویژگی سازماندهی دسترسی به اشیاء عضو داخلی a است
شبیه سازی. این هدف به این دلیل به وجود می آید که، معمولاً در شبیه سازی، کاربران و را برش می دهند
اسکریپتهای شبیهسازی موجود را بچسبانید/تغییر دهید، یا از ساختارهای شبیهسازی سطح بالاتر استفاده کنید،
اما اغلب علاقه مند به مطالعه یا ردیابی متغیرهای داخلی خاص هستند. برای
به عنوان مثال، از مواردی مانند:
· "I می خواهم به رد la بسته on la بي سيم رابط فقط on la اول دسترسی نقطه."
· "I می خواهم به رد la ارزش of la TCP ازدحام پنجره (هر زمان it تغییرات) on a
ویژه TCP سوکت."
· "I می خواهم a موادی که موقتا برای استعمال انبار میشود of تمام ارزش که بود استفاده in my شبیه سازی."
به طور مشابه، کاربران ممکن است خواهان دسترسی دقیق به متغیرهای داخلی در شبیه سازی باشند، یا
ممکن است بخواهد مقدار اولیه مورد استفاده برای یک پارامتر خاص را به طور کلی تغییر دهد
پس از آن اشیاء ایجاد شده است. در نهایت، کاربران ممکن است بخواهند بدانند چه متغیرهایی قابل تنظیم هستند
و در یک پیکربندی شبیه سازی قابل بازیابی است. این فقط برای شبیه سازی مستقیم نیست
تعامل در خط فرمان؛ همچنین یک رابط کاربری گرافیکی (آینده) را در نظر بگیرید که
میخواهم قابلیتی را فراهم کند که به موجب آن کاربر بر روی یک گره کلیک راست کند
بوم را مشاهده کنید و یک لیست سلسله مراتبی و سازماندهی شده از پارامترهای قابل تنظیم روی را ببینید
گره و اشیاء عضو تشکیل دهنده آن، و متن راهنما و مقادیر پیش فرض برای هر کدام
پارامتر.
تعریف کردن خواص
ما راهی را برای کاربران فراهم میکنیم تا به مقادیر عمیق در سیستم دسترسی داشته باشند، بدون اینکه نیازی به آبگیری داشته باشند
لوازم جانبی (نشانگرها) از طریق سیستم و راه رفتن زنجیره های اشاره گر برای رسیدن به آنها. الف را در نظر بگیرید
کلاس DropTailQueue که دارای یک متغیر عضو است که یک عدد صحیح بدون علامت است m_maxPackets;
این متغیر عضو، عمق صف را کنترل می کند.
اگر به اعلامیه نگاه کنیم DropTailQueue، موارد زیر را مشاهده می کنیم:
کلاس DropTailQueue : صف عمومی {
عمومی:
استاتیک TypeId GetTypeId (باطل)؛
...
خصوصی:
std:: صف > m_packets;
uint32_t m_maxPackets;
};
بیایید چیزهایی را در نظر بگیریم که یک کاربر ممکن است بخواهد با ارزش آن انجام دهد m_maxPackets:
· یک مقدار پیش فرض برای سیستم تنظیم کنید، به طوری که هر زمان که یک مقدار جدید باشد DropTailQueue خلق شده است،
این عضو به آن پیش فرض مقداردهی اولیه می شود.
· مقدار را روی یک صف از قبل نمونه برداری شده تنظیم یا دریافت کنید.
موارد فوق معمولاً نیاز به ارائه دارند تنظیم () و گرفتن () توابع، و برخی از انواع
مقدار پیش فرض جهانی
در ns-3 سیستم ویژگی، این تعاریف ارزش و ثبت تابع دسترسی
به داخل منتقل می شوند TypeId کلاس؛ به عنوان مثال.:
NS_OBJECT_ENSURE_REGISTERED (DropTailQueue)؛
TypeId
DropTailQueue::GetTypeId (باطل)
{
static TypeId tid = TypeId ("ns3::DropTailQueue")
SetParent ()
.AddConstructor ()
.AddAttribute ("MaxPackets"،
"حداکثر تعداد بسته های پذیرفته شده توسط این DropTailQueue."،
مقدار واحد (100)،
MakeUintegerAccessor (&DropTailQueue::m_maxPackets)،
MakeUintegerChecker ())
;
برگرد
}
La AddAttribute () روش انجام تعدادی از کارها برای m_maxPackets مقدار:
· اتصال متغیر عضو (معمولا خصوصی). m_maxPackets به یک رشته عمومی
"MaxPackets".
· ارائه یک مقدار پیش فرض (100 بسته).
· ارائه چند متن راهنما که معنای مقدار را تعریف می کند.
ارائه یک "Checker" (که در این مثال استفاده نمی شود) که می تواند برای تعیین محدوده در
محدوده مجاز مقادیر
نکته کلیدی این است که اکنون مقدار این متغیر و مقدار پیش فرض آن قابل دسترسی است
در فضای نام ویژگی که بر اساس رشته هایی مانند "MaxPackets" و TypeId نام
رشته های. در بخش بعدی، ما یک نمونه اسکریپت ارائه خواهیم کرد که نشان می دهد کاربران چگونه ممکن است
این مقادیر را دستکاری کنید
توجه داشته باشید که مقداردهی اولیه مشخصه به ماکرو متکی است NS_OBJECT_ENSURE_REGISTERED
(DropTailQueue) فراخوانده شدن؛ اگر این را از اجرای کلاس جدید خود حذف کنید، شما
ویژگی ها به درستی مقداردهی اولیه نمی شوند.
در حالی که نحوه ایجاد ویژگی ها را توضیح داده ایم، هنوز نحوه دسترسی را توضیح نداده ایم
و این ارزش ها را مدیریت کنید. به عنوان مثال، وجود ندارد globals.h فایل هدر جایی که اینها هستند
ذخیره شده ویژگی ها با کلاس های خود ذخیره می شوند. سؤالاتی که به طور طبیعی مطرح می شود، چگونگی آن است
آیا کاربران به راحتی در مورد تمام ویژگی های مدل های خود و چگونه یک کاربر یاد می گیرند؟
به این ویژگی ها دسترسی داشته باشید یا مقادیر آنها را به عنوان بخشی از رکورد آنها مستند کنید
شبیه سازی؟
مستندات دقیق از ویژگی های واقعی تعریف شده برای یک نوع، و یک لیست جهانی از
تمام ویژگی های تعریف شده، در اسناد API موجود هستند. برای بقیه این
سند ما می خواهیم روش های مختلف دریافت و تنظیم ویژگی را نشان دهیم
ارزش ها.
محیط به طور پیش فرض ارزشها
پیکربندی::SetDefault و خط فرمان
بیایید ببینیم چگونه یک اسکریپت کاربر ممکن است به یک مقدار مشخصه خاص دسترسی پیدا کند. ما می رویم
با استفاده از src/point-to-point/examples/main-attribute-value.cc فیلمنامه برای تصویرسازی، با
برخی از جزئیات حذف شد در اصلی تابع شروع می شود:
// این یک مثال اساسی از نحوه استفاده از سیستم ویژگی است
// یک مقدار را در سیستم اصلی تنظیم کنید و دریافت کنید. یعنی یک علامت بدون امضا
// عدد صحیح حداکثر تعداد بسته ها در یک صف
//
INT
اصلی (int argc، char *argv[])
{
// به طور پیش فرض، ویژگی MaxPackets دارای 100 بسته است
// (این پیش فرض را می توان در تابع DropTailQueue::GetTypeId مشاهده کرد)
//
// در اینجا، آن را روی 80 بسته تنظیم می کنیم. میتوانیم از یکی از دو نوع مقدار استفاده کنیم:
// یک مقدار مبتنی بر رشته یا یک مقدار یک عدد
پیکربندی::SetDefault ("ns3::DropTailQueue::MaxPackets"، StringValue ("80"));
// فراخوانی تابع زیر اضافی است
پیکربندی::SetDefault ("ns3::DropTailQueue::MaxPackets"، UintegerValue (80));
// به کاربر اجازه می دهد هر یک از پیش فرض ها و موارد فوق را لغو کند
// SetDefaults () در زمان اجرا، از طریق آرگومان های خط فرمان
// برای مثال، از طریق "--ns3::DropTailQueue::MaxPackets=80"
CommandLine cmd;
// این روش دیگری را برای تنظیم مقدار از خط فرمان ارائه می دهد:
cmd.AddValue ("maxPackets"، "ns3::DropTailQueue::MaxPackets");
cmd.Parse (argc, argv);
نکته اصلی که در بالا باید به آن توجه کرد دو فراخوانی معادل هستند پیکربندی::SetDefault
(). به این صورت است که مقدار پیشفرض را برای همه نمونهسازیشدههای بعدی تنظیم میکنیم
DropTailQueueس ما این دو نوع را نشان می دهیم مقدار کلاس ها، الف مقدار رشته و یک
UintegerValue class، می تواند برای اختصاص مقدار به ویژگی نامگذاری شده توسط استفاده شود
"ns3::DropTailQueue::MaxPackets".
همچنین امکان دستکاری ویژگی ها با استفاده از خط فرمان; چند نمونه دیدیم
در اوایل آموزش به ویژه، اضافه کردن یک استدلال کوتاه ساده است
نام، مانند --maxPacketsبرای یک ویژگی که به مدل شما مرتبط است،
در این مورد "ns3::DropTailQueue::MaxPackets". این ویژگی اضافی دارد که
رشته کمکی برای ویژگی به عنوان بخشی از پیام استفاده برای اسکریپت چاپ می شود.
برای اطلاعات بیشتر نگاه کنید به خط فرمان مستندات API.
اکنون، چند شی با استفاده از API سطح پایین ایجاد می کنیم. صف های تازه ایجاد شده ما خواهد شد
نداشتن m_maxPackets به 100 بسته اولیه، همانطور که در تعریف شده است
DropTailQueue::GetTypeId () تابع، اما به 80 بسته، به دلیل آنچه در بالا با آن انجام دادیم
مقادیر پیش فرض.:
Ptr n0 = CreateObject ()
Ptr net0 = CreateObject ()
n0->AddDevice (net0)؛
Ptr q = CreateObject ()
net0->AddQueue(q);
در این مرحله، ما یک تک ایجاد کرده ایم گره (n0) و یک تک PointToPointNetDevice
(0) و a اضافه کرد DropTailQueue (q) به 0.
سازندگان، یاران و ObjectFactory
ترکیب های دلخواه از ویژگی ها را می توان تنظیم کرد و از کمک کننده و سطح پایین دریافت کرد
API ها یا از خود سازنده ها:
Ptr p =
CreateObjectWithAttributes
("MinX"، DoubleValue (-100.0)،
"MinY"، DoubleValue (-100.0)،
"DeltaX"، DoubleValue (5.0)،
"DeltaY"، DoubleValue (20.0)،
"GridWidth"، UintegerValue (20)،
"LayoutType"، StringValue ("RowFirst"))؛
یا از API های کمکی سطح بالاتر، مانند:
mobility.SetPositionAllocator
("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 آن ها را خواهد داشت
ویژگی های تنظیم شده در طول ساخت این بسیار شبیه به استفاده از یکی از API های کمکی است
برای کلاس
برای بررسی، چندین راه برای تنظیم مقادیر برای ویژگیها برای نمونههای کلاس وجود دارد به be
ایجاد شده in la آینده:
· پیکربندی::SetDefault ()
· CommandLine::AddValue ()
· CreateObjectWithAttributes<> ()
· API های کمکی مختلف
اما اگر قبلاً یک نمونه ایجاد کرده باشید و بخواهید مقدار آن را تغییر دهید، چه میشود
صفت؟ در این مثال، چگونه میتوانیم آن را دستکاری کنیم m_maxPackets ارزش از قبل
نمونه شد DropTailQueue? در اینجا روش های مختلفی برای انجام این کار وجود دارد.
تغییر دادن ارزشها
SmartPointer
فرض کنید یک اشاره گر هوشمند (پترن) به یک دستگاه شبکه مربوطه در دست است. در حال حاضر
به عنوان مثال، آن است 0 اشاره گر
یکی از راههای تغییر مقدار، دسترسی به یک اشارهگر به صف زیرین و تغییر آن است
ویژگی.
ابتدا مشاهده می کنیم که می توانیم یک اشاره گر به (کلاس پایه) دریافت کنیم. صف از طريق la
PointToPointNetDevice ویژگی ها، جایی که نامیده می شود "TxQueue":
PointerValue tmp;
net0->GetAttribute ("TxQueue"، tmp)؛
Ptr txQueue = tmp.GetObject ();
با استفاده از GetObject () عملکرد، ما می توانیم یک downcast امن به a انجام دهیم DropTailQueue، که در آن
"MaxPackets" یک صفت است:
Ptr dtq = txQueue->GetObject ()
NS_ASSERT (dtq != 0);
بعد، می توانیم مقدار یک ویژگی را در این صف دریافت کنیم. ما لفاف را معرفی کرده ایم
مقدار کلاسهایی برای انواع دادههای زیربنایی، مشابه بستهبندیهای جاوا در اطراف این انواع،
از آنجایی که سیستم ویژگی مقادیر سریال شده به رشته ها را ذخیره می کند، نه انواع متفاوت.
در اینجا، مقدار ویژگی به a اختصاص داده می شود UintegerValue، و گرفتن () روش در این مورد
ارزش (بدون بسته بندی) را تولید می کند uint32_t.:
UintegerValue محدودیت;
dtq->GetAttribute ("MaxPackets"، limit);
NS_LOG_INFO ("1. محدودیت dtq: " << محدودیت. دریافت () << " بسته ها");
توجه داشته باشید که downcast فوق واقعاً مورد نیاز نیست. ما می توانستیم ویژگی را دریافت کنیم
ارزش مستقیم از txQueue، که یک است شیء:
txQueue->GetAttribute ("MaxPackets"، limit);
NS_LOG_INFO ("2. محدودیت txQueue: " << محدودیت. دریافت () << " بستهها");
حالا بیایید آن را روی مقدار دیگری (60 بسته) تنظیم کنیم:
txQueue->SetAttribute("MaxPackets", UintegerValue (60));
txQueue->GetAttribute ("MaxPackets"، limit);
NS_LOG_INFO ("3. محدودیت txQueue تغییر کرد: " << محدودیت. دریافت () << " بستهها");
پیکربندی فضای نام راه
یک راه جایگزین برای رسیدن به ویژگی، استفاده از فضای نام پیکربندی است. اینجا،
این ویژگی در یک مسیر شناخته شده در این فضای نام قرار دارد. این رویکرد مفید است اگر یکی
به نشانگرهای زیرین دسترسی ندارد و می خواهد یک مورد خاص را پیکربندی کند
ویژگی با یک عبارت واحد.:
پیکربندی:: تنظیم ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets"،
UintegerValue (25));
txQueue->GetAttribute ("MaxPackets"، limit);
NS_LOG_INFO ("4. محدودیت txQueue از طریق فضای نام تغییر کرد: "
<< limit.Get () << " بسته ها");
مسیر پیکربندی اغلب دارای شکل است ".../
نام>/ /.../ / " برای ارجاع به یک نمونه خاص با شاخص یک
شی در ظرف در این مورد اولین ظرف فهرست همه است گرهs; را
ظرف دوم لیست همه است NetDeviceبر انتخاب شده است گره. سرانجام ،
مسیر پیکربندی معمولاً با صفات متوالی عضو، در این مورد، به پایان میرسد
"MaxPackets" ویژگی از "TxQueue" از برگزیده NetDevice.
همچنین میتوانستیم از علامتهای عام برای تنظیم این مقدار برای همه گرهها و همه دستگاههای شبکه استفاده کنیم
(که در این مثال ساده همان اثر قبلی را دارد پیکربندی:: تنظیم ()):
پیکربندی:: تنظیم ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets"،
UintegerValue (15));
txQueue->GetAttribute ("MaxPackets"، limit);
NS_LOG_INFO ("5. محدودیت txQueue از طریق فضای نام وحشی تغییر کرد: "
<< limit.Get () << " بسته ها");
شیء نام محصولات
راه دیگر برای دستیابی به ویژگی، استفاده از امکانات سرویس نام شی است. در
سرویس نام شی به ما امکان می دهد مواردی را به فضای نام پیکربندی در زیر اضافه کنیم
"/نام ها/" مسیر با یک رشته نام تعریف شده توسط کاربر. اگر کسی این کار را نکند، این رویکرد مفید است
به نشانگرهای زیربنایی دسترسی دارند و تعیین موارد مورد نیاز دشوار است
مسیر فضای نام پیکربندی بتن.
نام ها::افزودن ("سرور"، n0);
نام ها::افزودن ("server/eth0"، net0);
...
پیکربندی:: تنظیم ("/Names/server/eth0/TxQueue/MaxPackets"، UintegerValue (25));
در اینجا ما عناصر مسیر را اضافه کرده ایم "سرور" و "eth0" تحت "/نام ها/" پس فضای نام
از مسیر پیکربندی به دست آمده برای تنظیم ویژگی استفاده کرد.
برای درمان کاملتر به نام اشیاء مراجعه کنید ns-3 فضای نام پیکربندی
پیاده سازی جزئیات
مقدار کلاس
خوانندگان توجه داشته باشند TypeValue کلاس هایی که زیر کلاس های هستند AttributeValue پایه
کلاس اینها را می توان به عنوان کلاس های میانی در نظر گرفت که برای تبدیل از خام استفاده می شوند
انواع به AttributeValues که توسط سیستم ویژگی استفاده می شود. به یاد بیاورید که این
پایگاه داده دارای اشیاء از انواع مختلفی است که به رشته ها تبدیل شده اند. تبدیل به این نوع
می توان با استفاده از یک کلاس متوسط (مانند IntegerValue، یا DoubleValue برای
اعداد ممیز شناور) یا از طريق رشته های. تبدیل مستقیم ضمنی انواع به
AttributeValue واقعا کاربردی نیست بنابراین در بالا، کاربران حق انتخاب برای استفاده دارند
رشته ها یا مقادیر:
p->Set ("cwnd"، StringValue ("100")); // تنظیم کننده مبتنی بر رشته
p->Set ("cwnd"، IntegerValue (100)); // تنظیم کننده مبتنی بر اعداد صحیح
این سیستم ماکروهایی را ارائه می دهد که به کاربران کمک می کند تا AttributeValue جدید را اعلام و تعریف کنند
زیر کلاس ها برای انواع جدیدی که می خواهند به سیستم ویژگی معرفی کنند:
· ATTRIBUTE_HELPER_HEADER
· ATTRIBUTE_HELPER_CPP
برای اطلاعات بیشتر به مستندات API برای این ساختارها مراجعه کنید.
دهی اولیه سفارش
ویژگی های موجود در سیستم نباید به وضعیت هیچ ویژگی دیگری در این سیستم بستگی داشته باشد
سیستم. دلیلش این است که ترتیب اولیه سازی Attribute مشخص نشده است
توسط سیستم اجرا می شود. یک مثال خاص از این را می توان در پیکربندی خودکار مشاهده کرد
برنامه هایی مانند ConfigStore. اگرچه یک مدل داده شده ممکن است آن را به گونه ای ترتیب دهد که ویژگی ها
در یک ترتیب خاص مقداردهی اولیه می شوند، ممکن است پیکربندی خودکار دیگری تصمیم بگیرد
به طور مستقل برای تغییر ویژگی ها به عنوان مثال، به ترتیب حروف الفبا.
به دلیل این ترتیب غیر خاص، هیچ ویژگی در سیستم ممکن است وابستگی نداشته باشد
بر روی هر ویژگی دیگر به عنوان نتیجه، تنظیم کننده های ویژگی هرگز نباید به دلیل وضعیت شکست بخورند
از یک ویژگی دیگر هیچ تنظیم کننده مشخصه ای نمی تواند هر یک از مقادیر مشخصه دیگر را به عنوان a تغییر دهد (تنظیم کند).
نتیجه تغییر ارزش آن
این یک محدودیت بسیار قوی است و مواردی وجود دارد که ویژگی ها باید تنظیم شوند
به طور مداوم امکان عملکرد صحیح را فراهم کند. برای این منظور، ما امکان بررسی سازگاری را فراهم می کنیم
چه زمانی la صفت is استفاده (cf. NS_ASSERT_MSG or NS_ABORT_MSG).
به طور کلی، کد ویژگی برای تخصیص مقادیر به متغیرهای عضو کلاس اساسی است
پس از ساخت یک شی اجرا می شود. اما اگر به مقادیر تخصیص داده شده نیاز دارید چه می کنید
قبل از اجرای بدنه سازنده، زیرا شما در منطق به آنها نیاز دارید
سازنده؟ راهی برای انجام این کار وجود دارد که برای مثال در کلاس استفاده می شود ConfigStore: زنگ زدن
ObjectBase::ConstructSelf () به شرح زیر است:
ConfigStore::ConfigStore ()
{
ObjectBase::ConstructSelf (AttributeConstructionList ());
// با سازنده ادامه دهید.
}
مراقب باشید که شی و تمام کلاس های مشتق شده آن باید a را نیز پیاده سازی کنند GetInstanceTypeId
() روش. در غیر این صورت ObjectBase::ConstructSelf () قادر به خواندن نخواهد بود
ویژگی های.
اضافه کردن خواص
La ns-3 سیستم تعدادی از مقادیر داخلی را تحت سیستم ویژگی قرار می دهد، اما
بدون شک کاربران مایلند این را گسترش دهند تا مواردی را که از دست دادهایم انتخاب کنند یا آنها را اضافه کنند
کلاس های خود را به سیستم.
سه مورد استفاده معمولی وجود دارد:
· ایجاد یک عضو داده کلاس موجود به عنوان یک ویژگی، در حالی که قبلاً وجود نداشته باشد.
ایجاد یک کلاس جدید که بتواند برخی از اعضای داده را به عنوان ویژگی با دادن TypeId به آن نشان دهد.
· ایجاد یک AttributeValue زیر کلاس برای یک کلاس جدید تا بتوان به عنوان یک کلاس به آن دسترسی پیدا کرد
صفت.
موجود عضو متغیر
این متغیر را در نظر بگیرید TcpSocket:
uint32_t m_cWnd; // پنجره ازدحام
فرض کنید شخصی که با TCP کار می کند می خواهد مقدار آن متغیر را دریافت یا تنظیم کند
با استفاده از سیستم ابرداده اگر قبلاً توسط آن ارائه نشده بود ns-3، کاربر می تواند اعلام کند
اضافه شده زیر در سیستم ابرداده زمان اجرا (به GetTypeId() تعریف برای
TcpSocket):
.AddAttribute ("پنجره ازدحام"،
"پنجره تراکم Tcp (بایت)"،
مقدار واحد (1)،
MakeUintegerAccessor (&TcpSocket::m_cWnd)،
MakeUintegerChecker ())
در حال حاضر، کاربر با یک اشاره گر به a TcpSocket نمونه می تواند عملیاتی مانند
تنظیم و دریافت مقدار، بدون نیاز به افزودن صریح این توابع.
علاوه بر این، کنترل های دسترسی را می توان اعمال کرد، مانند اجازه دادن به پارامتر برای خواندن و
نوشته نشده است، یا می توان محدوده هایی را برای بررسی مقادیر مجاز اعمال کرد.
جدید طبقه TypeId
در اینجا، تأثیر آن بر کاربری که میخواهد کلاس جدیدی را به آن اضافه کند، مورد بحث قرار میدهیم ns-3. چی
کارهای اضافی باید انجام شود تا بتواند ویژگی ها را نگه دارد؟
بیایید کلاس جدیدمان را که نامیده می شود، فرض کنیم ns3::MyMobility، یک نوع مدل حرکتی است. اولین،
کلاس باید از کلاس والد خود ارث ببرد، ns3::MobilityModelاست. در my-mobility.h
فایل هدر:
فضای نام ns3 {
کلاس MyClass: عمومی MobilityModel
{
این مستلزم آن است که ما آن را اعلام کنیم GetTypeId () عملکرد. این یک تابع عمومی یک خطی است
اعلام:
عمومی:
/ **
* این نوع را ثبت کنید.
* \return شی TypeId.
*/
استاتیک TypeId GetTypeId (باطل)؛
ما قبلاً چه چیزی را معرفی کرده ایم TypeId تعریف مانند در خواهد بود my-mobility.cc
فایل پیاده سازی:
NS_OBJECT_ENSURE_REGISTERED (MyMobility)؛
TypeId
MyMobility::GetTypeId (باطل)
{
static TypeId tid = TypeId ("ns3::MyMobility")
SetParent ()
SetGroupName ("Mobility")
.AddConstructor ()
.AddAttribute ("محدوده ها"،
"محدوده منطقه برای سفر دریایی."،
RectangleValue (مستطیل (0.0، 0.0، 100.0، 100.0))،
MakeRectangleAccessor (&MyMobility::m_bounds)،
MakeRectangleChecker ())
.AddAttribute ("زمان"،
"جهت و سرعت فعلی را پس از حرکت برای این تاخیر تغییر دهید."،
مقدار زمانی (ثانیه (1.0))،
MakeTimeAccessor (&MyMobility::m_modeTime)،
MakeTimeChecker ())
// و غیره (پارامترهای بیشتر).
;
برگرد
}
اگر نمیخواهیم از یک کلاس موجود زیر کلاس بگیریم، در فایل هدر فقط به ارث میبریم
از جانب ns3:: شیو در فایل شی، کلاس والد را روی آن قرار می دهیم ns3:: شی با
SetParent ().
اشتباهات معمولی در اینجا عبارتند از:
· تماس نگرفتن NS_OBJECT_ENSURE_REGISTERED ()
· عدم تماس با SetParent () روش، یا فراخوانی آن با نوع اشتباه.
· عدم تماس با AddConstructor () روش، یا فراخوانی آن با نوع اشتباه.
· معرفی یک اشتباه تایپی در نام TypeId در سازنده آن
· عدم استفاده از نام نوع C++ کاملاً واجد شرایط کلاس C++ به عنوان نام
TypeId. توجه داشته باشید که "ns3::" مورد نیاز است.
هیچ یک از این اشتباهات را نمی توان تشخیص داد ns-3 پایگاه کد، بنابراین به کاربران توصیه می شود بررسی کنند
با دقت چندین بار که آنها این را درست دریافت کردند.
جدید AttributeValue نوع
از دیدگاه کاربری که کلاس جدیدی در سیستم می نویسد و می خواهد که باشد
به عنوان یک ویژگی قابل دسترسی است، عمدتاً موضوع نوشتن تبدیل به/از وجود دارد
رشته ها و مقادیر ویژگی بیشتر این موارد را می توان با کدهای ماکرو کپی/پیست کرد. برای
به عنوان مثال، یک اعلان کلاس برای در نظر بگیرید مستطیل در src/mobility/model دایرکتوری:
سربرگ پرونده
/ **
* یک مستطیل 2 بعدی را خلاصه کنید
*/
کلاس مستطیل
{
...
xMin دو برابر
xMax دو برابر؛
دو برابر yMin؛
دو برابر yMax؛
};
یک تماس ماکرو و دو اپراتور، باید در زیر اعلان کلاس اضافه شود تا بتواند
یک مستطیل را به یک مقدار قابل استفاده توسط صفت سیستم:
std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
std::istream &operator >> (std::istream &is, Rectangle &rectangle);
ATTRIBUTE_HELPER_HEADER (مستطیل)؛
پیاده سازی پرونده
در تعریف کلاس (. رونوشت فایل)، کد به صورت زیر است:
ATTRIBUTE_HELPER_CPP (مستطیل)؛
std::ostream &
عملگر << (std::ostream &os, const Rectangle & مستطیل)
{
os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|"
<< rectangle.yMax;
بازگشت سیستم عامل;
}
std::istream &
عملگر >> (std::istream &is، Rectangle &rectangle)
{
char c1, c2, c3;
است >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 است
>> rectangle.yMax;
اگر (c1 != '|' ||
c2 != '|' ||
c3 != '|')
{
is.setstate (std::ios_base::failbit);
}
بازگشت است؛
}
این عملگرهای جریان به سادگی از یک نمایش رشته ای مستطیل تبدیل می کنند
("xMin|xMax|yMin|yMax") به مستطیل زیرین. مدل ساز باید اینها را مشخص کند
عملگرها و نمایش نحوی رشته ای از یک نمونه از کلاس جدید.
ConfigStore
مقادیر برای ns-3 ویژگی ها را می توان در یک فایل متنی ASCII یا XML ذخیره کرد و در a بارگذاری کرد
اجرای شبیه سازی آینده این ویژگی به نام ns-3 ConfigStore. در ConfigStore is
یک پایگاه داده تخصصی برای مقادیر ویژگی و مقادیر پیش فرض.
اگرچه یک ماژول به طور جداگانه نگهداری می شود src/config-store/ دایرکتوری، ما
به دلیل وابستگی تنها به آن، آن را در اینجا مستند کنید ns-3 ماژول اصلی و ویژگی ها
ما می توانیم با استفاده از یک مثال از این سیستم را بررسی کنیم
src/config-store/examples/config-store-save.cc.
اول، همه کاربران از ConfigStore باید شامل عبارت زیر باشد:
#include "ns3/config-store-module.h"
بعد، این برنامه یک شی نمونه اضافه می کند ConfigExample برای نشان دادن نحوه گسترش سیستم:
class ConfigExample: Public Object
{
عمومی:
استاتیک TypeId GetTypeId (باطل) {
static 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));
IntegerValue iv;
a2_obj->GetAttribute ("TestInt16"، iv);
NS_ABORT_MSG_UNLESS (iv.Get () == -3،
"نمی توان ویژگی عدد صحیح ConfigExample را از طریق SetAttribute تنظیم کرد");
عبارت بعدی برای اطمینان از روت بودن (یکی از) اشیاء ایجاد شده ضروری است
در فضای نام پیکربندی به عنوان یک نمونه شی. این معمولا زمانی اتفاق می افتد که شما
جمع کردن اشیاء به a ns3:: گره or ns3:: کانال به عنوان مثال، اما اینجا، از آنجایی که ما در حال کار هستیم
در سطح هسته، باید یک شی فضای نام ریشه جدید ایجاد کنیم:
پیکربندی::RegisterRootNamespaceObject (a2_obj);
نوشته
در مرحله بعد، ما می خواهیم ذخیره تنظیمات را خروجی بگیریم. مثالها نشان میدهند که چگونه این کار را در دو صورت انجام دهیم
فرمت ها، XML و متن خام. در عمل باید این مرحله را درست قبل از تماس انجام داد
شبیه ساز::اجرا کنید () برای ذخیره پیکربندی نهایی درست قبل از اجرای شبیه سازی.
سه ویژگی وجود دارد که بر رفتار ConfigStore حاکم است: "حالت",
"نام فایل"و "فرمت فایل". حالت (پیشفرض "هیچ یک") پیکربندی می کند که آیا ns-3 باید
بارگیری پیکربندی از یک فایل ذخیره شده قبلی (مشخص کنید "حالت = بارگذاری") یا آن را در یک فایل ذخیره کنید
(مشخص كردن "Mode=Save"). نام فایل (پیشفرض "") جایی است که ConfigStore باید بخواند یا
داده های آن را بنویسید فرمت فایل (پیشفرض "RawText") تعیین می کند که آیا قالب ConfigStore
متن ساده یا Xml است ("FileFormat=Xml")
مثال نشان می دهد:
پیکربندی::SetDefault ("ns3::ConfigStore::نام فایل"، StringValue ("output-attributes.xml"));
پیکربندی::SetDefault ("ns3::ConfigStore::FileFormat"، StringValue ("Xml"));
Config::SetDefault ("ns3::ConfigStore::Mode"، StringValue ("ذخیره"));
ConfigStore outputConfig.
outputConfig.ConfigureDefaults ();
outputConfig.ConfigureAttributes ();
// خروجی ذخیره تنظیمات به فرمت txt
پیکربندی::SetDefault ("ns3::ConfigStore::نام فایل"، StringValue ("output-attributes.txt"));
Config::SetDefault ("ns3::ConfigStore::FileFormat"، StringValue ("RawText"));
Config::SetDefault ("ns3::ConfigStore::Mode"، StringValue ("ذخیره"));
ConfigStore outputConfig2;
outputConfig2.ConfigureDefaults ();
outputConfig2.ConfigureAttributes ();
شبیه ساز::Run ();
شبیه ساز::Destroy ();
به قرارگیری این عبارات درست قبل از شبیه ساز::اجرا کنید () بیانیه.
این خروجی تمام مقادیر را درست قبل از شروع شبیه سازی ثبت می کند (به عنوان مثال.
پس از انجام تمام تنظیمات).
پس از اجرا، می توانید باز کنید output-attributes.txt فایل کنید و ببینید:
پیشفرض ns3::RealtimeSimulatorImpl::SynchronizationMode "BestEffort"
پیشفرض ns3::RealtimeSimulatorImpl::HardLimit "+100000000.0ns"
پیش فرض ns3::PcapFileWrapper::CaptureSize "65535"
پیش فرض ns3::PacketSocket::RcvBufSize "131072"
پیش فرض ns3::ErrorModel::IsEnabled "true"
پیش فرض ns3::RateErrorModel::ErrorUnit "EU_BYTE"
پیش فرض ns3::RateErrorModel::ErrorRate "0"
پیش فرض ns3::RateErrorModel::RanVar "Uniform:0:1"
پیش فرض ns3::DropTailQueue::Mode "Packets"
پیش فرض ns3::DropTailQueue::MaxPackets "100"
پیش فرض ns3::DropTailQueue::MaxBytes "6553500"
پیش فرض ns3::Application::StartTime "+0.0ns"
پیش فرض ns3::Application::StopTime "+0.0ns"
پیش فرض ns3::ConfigStore::Mode "ذخیره"
پیش فرض ns3::ConfigStore::نام فایل "output-attributes.txt"
پیش فرض ns3::ConfigStore::FileFormat "RawText"
پیش فرض ns3::ConfigExample::TestInt16 "-5"
RngSeed جهانی "1"
RngRun جهانی "1"
جهانی SimulatorImplementationType "ns3::DefaultSimulatorImpl"
جهانی SchedulerType "ns3::MapScheduler"
جهانی ChecksumEnabled "false"
مقدار /$ns3::ConfigExample/TestInt16 "-3"
در بالا، تمام مقادیر پیش فرض برای ویژگی های ماژول هسته نشان داده شده است.
سپس، تمام مقادیر برای ns-3 مقادیر جهانی ثبت می شود. در نهایت، ارزش
به عنوان مثال از ConfigExample که در فضای نام پیکربندی ریشه داشت نشان داده شده است. در یک
واقعی ns-3 برنامه، مدلها، ویژگیها و پیشفرضهای بیشتری نشان داده میشوند.
یک نسخه XML نیز در آن وجود دارد output-attributes.xml:
این فایل را می توان با اسکریپت شبیه سازی و داده های خروجی بایگانی کرد.
مطالعه
بعد، ما در مورد پیکربندی شبیه سازی بحث می کنیم از طريق یک فایل پیکربندی ورودی ذخیره شده وجود دارد
چند تفاوت کلیدی در مقایسه با نوشتن پیکربندی شبیه سازی نهایی.
ابتدا باید عباراتی از این قبیل را در ابتدای برنامه، قبل از آن قرار دهیم
عبارات پیکربندی شبیه سازی نوشته شده است (بنابراین مقادیر قبل از ثبت ثبت می شوند
مورد استفاده در ساخت اشیا).
پیکربندی::SetDefault ("ns3::ConfigStore::نام فایل"، StringValue ("input-defaults.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode"، StringValue ("Load"));
پیکربندی::SetDefault ("ns3::ConfigStore::FileFormat"، StringValue ("Xml"));
ConfigStore inputConfig.
inputConfig.ConfigureDefaults ();
سپس، توجه داشته باشید که بارگیری دادههای پیکربندی ورودی به پیشفرض Attribute محدود میشود (به عنوان مثال.
نه نمونه) ارزش ها و ارزش های جهانی. مقادیر نمونه ویژگی پشتیبانی نمی شوند
زیرا در این مرحله از شبیه سازی، قبل از ساخت هیچ شیئی وجود ندارد
چنین مواردی در اطراف (توجه داشته باشید، پیشرفتهای آینده در فروشگاه پیکربندی ممکن است تغییر کند
این رفتار).
دوم، در حالی که خروجی از ConfigStore state همه چیز را در پایگاه داده لیست می کند
فایل ورودی فقط باید حاوی مقادیر خاصی باشد که باید لغو شوند. بنابراین، یک راه برای استفاده
این کلاس برای پیکربندی فایل ورودی برای ایجاد یک پیکربندی اولیه با استفاده از
خروجی ("صرفه جویی") "حالت" توضیح داده شده در بالا، فقط از آن فایل پیکربندی استخراج کنید
عناصری که مایل به تغییر هستند و این حداقل عناصر را به یک فایل پیکربندی جدید منتقل کنید
که سپس با خیال راحت می توان آن را ویرایش و در یک اجرای شبیه سازی بعدی بارگذاری کرد.
هنگامی که ConfigStore شیء نمونه سازی شده است، ویژگی های آن "نام فایل", "حالت"و
"فرمت فایل" یا باید تنظیم شود از طريق خط فرمان یا از طريق بیانیه های برنامه
خواندن نوشتن مثال
به عنوان یک مثال پیچیده تر، اجازه دهید فرض کنیم که می خواهیم در پیکربندی از بخوانیم
پیش فرض از یک فایل ورودی به نام input-defaults.xmlو نتیجه را بنویسید
ویژگی های یک فایل جداگانه به نام output-attributes.xml.:
#include "ns3/config-store-module.h"
...
int main (...)
{
پیکربندی::SetDefault ("ns3::ConfigStore::نام فایل"، StringValue ("input-defaults.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode"، StringValue ("Load"));
پیکربندی::SetDefault ("ns3::ConfigStore::FileFormat"، StringValue ("Xml"));
ConfigStore inputConfig.
inputConfig.ConfigureDefaults ();
//
// به کاربر اجازه میدهد تا هر یک از پیشفرضها و Bind () بالا را لغو کند
// زمان اجرا، آرگومان های خط فرمان
//
CommandLine cmd;
cmd.Parse (argc, argv);
// توپولوژی راه اندازی
...
// درست قبل از ورود به Simulator::Run () فراخوانی کنید
پیکربندی::SetDefault ("ns3::ConfigStore::نام فایل"، StringValue ("output-attributes.xml"));
Config::SetDefault ("ns3::ConfigStore::Mode"، StringValue ("ذخیره"));
ConfigStore outputConfig.
outputConfig.ConfigureAttributes ();
شبیه ساز::Run ();
}
ConfigStore GUI
یک قسمت جلویی مبتنی بر GTK برای ConfigStore وجود دارد. این به کاربران اجازه می دهد تا از رابط کاربری گرافیکی استفاده کنند
دسترسی و تغییر متغیرها اسکرین شات از این ویژگی در دسترس است |ns3|
بررسی اجمالی ارائه.
برای استفاده از این ویژگی باید نصب کنید libgtk و libgtk-dev; نمونه اوبونتو
دستور نصب این است:
$ sudo apt-get install libgtk2.0-0 libgtk2.0-dev
برای بررسی اینکه آیا پیکربندی شده است یا نه، خروجی مرحله را بررسی کنید:
$ ./waf پیکربندی --enable-examples --enable-tests
---- خلاصه ای از ویژگی های اختیاری NS-3:
Python Bindings: فعال است
پشتیبانی از اسکن Python API: فعال است
NS-3 روی یکپارچه سازی کلیک کنید: فعال است
GtkConfigStore: فعال نیست (کتابخانه 'gtk+-2.0 >= 2.12' یافت نشد)
در مثال بالا، آن فعال نبود، بنابراین تا زمانی که نسخه مناسبی وجود نداشته باشد، نمی توان از آن استفاده کرد
نصب شده و:
$ ./waf پیکربندی --enable-examples --enable-tests
$./waf
تکرار می شود.
استفاده تقریباً مشابه نسخه غیر مبتنی بر GTK است، اما وجود ندارد ConfigStore
ویژگی های دخیل:
// درست قبل از ورود به Simulator::Run () فراخوانی کنید
پیکربندی GtkConfigStore؛
config.ConfigureDefaults ();
config.ConfigureAttributes ();
اکنون، زمانی که اسکریپت را اجرا می کنید، یک رابط کاربری گرافیکی باید ظاهر شود که به شما امکان می دهد منوهای آن را باز کنید
ویژگیهای گرهها/اشیاء مختلف، و سپس اجرای شبیهسازی را زمانی که شما اجرا میکنید، اجرا کنید
انجام شد.
آینده کار
چند بهبود احتمالی وجود دارد:
· ذخیره شماره نسخه منحصر به فرد با تاریخ و زمان در شروع فایل.
· دانه اولیه rng را در جایی ذخیره کنید.
هر RandomVariable را به صورت سریال seed اولیه خود قرار دهید و بعداً دوباره آن را بخوانید.
شیء نام
حفره یا سوراخ فصل
ورود به سیستم
La ns-3 تسهیلات ورود به سیستم را می توان برای نظارت یا اشکال زدایی پیشرفت شبیه سازی استفاده کرد
برنامه ها. خروجی ورود به سیستم را می توان با دستورات برنامه در خود فعال کرد اصلی () برنامه یا
با استفاده از NS_LOG متغیر محیطی.
عبارات ورود به سیستم در ساخت های بهینه سازی شده کامپایل نمی شوند ns-3. برای استفاده از ورود به سیستم، یک
باید ساخت (پیشفرض) اشکالزدایی را بسازد ns-3.
این پروژه هیچ تضمینی در مورد اینکه آیا خروجی ورود به سیستم ثابت باقی می ماند یا خیر نمی دهد
زمان. به کاربران نسبت به ساخت چارچوبهای خروجی شبیهسازی در بالای لاگ هشدار داده میشود
کد، زیرا خروجی و نحوه فعال کردن خروجی ممکن است در طول زمان تغییر کند.
بررسی اجمالی
ns-3 عبارات ورود به سیستم معمولاً برای ثبت رویدادهای مختلف اجرای برنامه استفاده می شود
به عنوان وقوع رویدادهای شبیه سازی یا استفاده از یک تابع خاص.
به عنوان مثال، این قطعه کد از است پروتکل Ipv4L3::IsDestinationAddress():
if (آدرس == iaddr.GetBroadcast ())
{
NS_LOG_LOGIC ("برای من (آدرس پخش رابط)");
بازگشت واقعی؛
}
اگر ورود به سیستم برای آن فعال شده باشد پروتکل Ipv4L3 جزء در شدت منطق or
در بالا (در مورد شدت گزارش به زیر مراجعه کنید)، بیانیه چاپ خواهد شد. در غیر این صورت، آن
سرکوب خواهد شد.
را قادر می سازد تولید
دو روش وجود دارد که کاربران معمولاً خروجی گزارش را کنترل می کنند. اولین مورد با تنظیم است
NS_LOG متغیر محیطی؛ به عنوان مثال:
$ NS_LOG="*" ./waf -- ابتدا اجرا شود
اجرا خواهد شد اول برنامه آموزشی با تمام خروجی ورود به سیستم. (مشخصات NS_LOG
قالب در زیر مورد بحث قرار خواهد گرفت.)
این را می توان با انتخاب اجزای جداگانه ریزتر کرد:
$ NS_LOG="Ipv4L3Protocol"./waf -- ابتدا اجرا شود
خروجی را می توان با گزینه های پیشوند بیشتر تنظیم کرد.
راه دوم برای فعال کردن لاگ این است که از عبارات صریح در برنامه خود استفاده کنید، مانند in
la اول برنامه آموزشی:
INT
اصلی (int argc، char *argv[])
{
LogComponentEnable ("UdpEchoClientApplication"، LOG_LEVEL_INFO)؛
LogComponentEnable ("UdpEchoServerApplication"، LOG_LEVEL_INFO)؛
...
(معنای LOG_LEVEL_INFOو سایر مقادیر ممکن در زیر مورد بحث قرار خواهند گرفت.)
NS_LOG نحو
La NS_LOG متغیر محیطی حاوی لیستی از اجزای گزارش و گزینهها است. ورود به سیستم
اجزا با کاراکترهای «:» از هم جدا می شوند:
$ NS_LOG=" : ..."
گزینههای هر مؤلفه گزارش به صورت پرچم بعد از هر مؤلفه گزارش داده میشوند:
$ NS_LOG=" = | ...: ..."
گزینهها شدت و سطح آن جزء و اختیاری بودن را کنترل میکنند
اطلاعات باید شامل زمان شبیه سازی، گره شبیه سازی، تابع باشد
نام، و شدت نمادین.
ورود اجزاء
به طور کلی یک جزء گزارش به یک کد منبع واحد اشاره دارد . رونوشت فایل، و شامل
کل فایل
برخی از کمککنندهها روشهای خاصی برای فعال کردن ثبت همه اجزا در یک ماژول دارند.
شامل واحدهای کامپایل مختلف، اما به طور منطقی با هم گروه بندی می شوند، مانند ns-3
کد وای فای:
WifiHelper wifiHelper;
wifiHelper.EnableLogComponents ();
La NS_LOG علامت عام مؤلفه ورود به سیستم «*» همه مؤلفه ها را فعال می کند.
برای اینکه ببینید چه مولفههای لاگ تعریف شدهاند، هر یک از این موارد کار میکند:
$ NS_LOG="print-list" ./waf --run ...
$ NS_LOG="foo" # یک توکن با هیچ مؤلفه گزارش مطابقت ندارد
فرم اول نام و پرچم های فعال را برای همه اجزای گزارش که هستند چاپ می کند
مرتبط در آن را با شبیه ساز خراش. فرم دوم همه گزارش های ثبت شده را چاپ می کند
اجزای سازنده، سپس با یک خطا از آن خارج شوید.
شدت و سطح گزینه
پیامهای منفرد متعلق به یک "کلاس شدت" هستند که توسط ماکرو ایجاد کننده تنظیم شده است
پیام در مثال بالا، NS_LOG_LOGIC(..) پیام را در LOG_LOGIC
کلاس شدت
کلاس های شدت زیر به این صورت تعریف می شوند شمردن ثابت ها:
┌───────────────┬───────────────────────────────── ─┐
│کلاس شدت │ معنی │
├───────────────┼───────────────────────────────── ─┤
│LOG_NONE │ پیش فرض، بدون ورود به سیستم │
├───────────────┼───────────────────────────────── ─┤
│LOG_ERROR │ فقط پیام های خطای جدی │
├───────────────┼───────────────────────────────── ─┤
│LOG_WARN │ پیام های هشدار │
├───────────────┼───────────────────────────────── ─┤
│LOG_DEBUG │ برای استفاده در اشکال زدایی │
├───────────────┼───────────────────────────────── ─┤
│LOG_INFO │ اطلاعاتی │
├───────────────┼───────────────────────────────── ─┤
│LOG_FUNCTION │ ردیابی عملکرد │
├───────────────┼───────────────────────────────── ─┤
│LOG_LOGIC │ ردیابی جریان را در داخل │ کنترل کنید
│ │ توابع │
└───────────────┴───────────────────────────────── ─┘
معمولاً شخص می خواهد پیام هایی را در یک کلاس شدت مشخص ببیند و بالاتر. این توسط
تعریف "سطوح" ورود به سیستم فراگیر:
┌───────────────────┬───────────────────────────── ─────┐
│سطح │ معنی │
├───────────────────┼───────────────────────────── ─────┤
│LOG_LEVEL_ERROR │ فقط LOG_ERROR کلاس شدت │
│ │ پیام ها. │
├───────────────────┼───────────────────────────── ─────┤
│LOG_LEVEL_WARN │ LOG_WARN و بالاتر. │
├───────────────────┼───────────────────────────── ─────┤
│LOG_LEVEL_DEBUG │ LOG_DEBUG و بالاتر. │
├───────────────────┼───────────────────────────── ─────┤
│LOG_LEVEL_INFO │ LOG_INFO و بالاتر. │
├───────────────────┼───────────────────────────── ─────┤
│LOG_LEVEL_FUNCTION │ LOG_FUNCTION و بالاتر. │
├───────────────────┼───────────────────────────── ─────┤
│LOG_LEVEL_LOGIC │ LOG_LOGIC و بالاتر. │
├───────────────────┼───────────────────────────── ─────┤
│LOG_LEVEL_ALL │ تمام کلاس های شدت. │
├───────────────────┼───────────────────────────── ─────┤
│LOG_ALL │ مترادف برای LOG_LEVEL_ALL │
└───────────────────┴───────────────────────────── ─────┘
کلاس شدت و گزینه های سطح را می توان در NS_LOG متغیر محیطی توسط
این نشانه ها:
┌─────────┬───────
│کلاس │ سطح │
├─────────┼─────────────
│خطا │ سطح_خطا │
├─────────┼─────────────
│هشدار دادن │ level_warn │
├─────────┼─────────────
│اشکال زدایی کردن │ level_debug │
├─────────┼─────────────
│اطلاعات │ level_info │
├─────────┼─────────────
│تابع │ سطح_تابع │
├─────────┼─────────────
│منطق │ سطح_منطق │
├─────────┼─────────────
│ level_all │
│ تمام │
│ * │
└─────────┴───────
استفاده از نشانه کلاس شدت، پیامهای گزارش را فقط با آن شدت فعال میکند. مثلا،
NS_LOG="*=اخطار" پیام هایی با شدت خروجی نمی دهد خطا. NS_LOG="*=level_debug" اراده
پیام های خروجی در سطوح شدت اشکال زدایی کردن و بالاتر.
کلاس ها و سطوح شدت را می توان با «|» ترکیب کرد. اپراتور:
NS_LOG="*=level_warn|منطق" پیام ها را در سطوح شدت خروجی می دهد خطا, هشدار دادن و منطق.
La NS_LOG علامت عام سطح شدت "*" و تمام مترادف هستند برای level_all.
برای اجزای گزارش که صرفاً در ذکر شده است 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_node │ گره │
├─────────────┼────────────
│پیشوند_سطح │ سطح │
├─────────────┼────────────
│پیشوند_همه │ تمام │
│ * │
└─────────────┴─────
برای اجزای گزارش که صرفاً در ذکر شده است NS_LOG
$ NS_LOG=" :..."
گزینه های پیشوند پیش فرض هستند LOG_PREFIX_ALL.
شدت پیشوند
کلاس شدت یک پیام را می توان با گزینه ها گنجاند پیشوند_سطح or سطح.
به عنوان مثال، این مقدار از NS_LOG ورود به سیستم را برای همه اجزای گزارش ('*') و همه فعال می کند
کلاس های شدت (= همه، و پیام را با کلاس شدت (|پیشوند_سطح).
$ NS_LOG="*=all|prefix_level" ./waf --run scratch-simulator
شبیه ساز خراش
پیام خطا [خطا]
[WARN] پیام هشدار
پیام اشکال زدایی [DEBUG]
[INFO] پیام اطلاعاتی
پیام عملکرد [FUNCT]
پیام منطقی [LOGIC]
زمان پیشوند
زمان شبیه سازی را می توان با گزینه ها گنجاند پیشوند_زمان or زمان. این چاپ می کند
زمان شبیه سازی بر حسب ثانیه
گره پیشوند
شناسه گره شبیه سازی را می توان با گزینه ها گنجاند prefix_node or گره.
عملکرد پیشوند
نام تابع فراخوانی را می توان با گزینه ها گنجاند prefix_func or عملکرد.
NS_LOG کارت های وحشی
علامت عام مؤلفه گزارش «*» همه مؤلفه ها را فعال می کند. برای فعال کردن تمام اجزاء در یک
استفاده از سطح شدت خاص *=.
علامت عام گزینه سطح شدت "*" مترادف آن است تمام. این باید قبل از هر اتفاقی رخ دهد
`| گزینه های جداسازی شخصیت ها برای فعال کردن تمام کلاسهای شدت، استفاده کنید =*,
or =*|.
علامت عام گزینه "*" یا نشانه تمام همه گزینه های پیشوند را فعال می کند، اما باید رخ دهد بعد از a
`| شخصیت. برای فعال کردن یک کلاس یا سطح شدت خاص و همه پیشوندها، استفاده کنید
= |*.
عام گزینه ترکیبی ** تمام شدت ها و همه پیشوندها را فعال می کند. مثلا،
=**.
uber-wildcard *** تمام شدت ها و همه پیشوندها را برای همه اجزای گزارش فعال می کند.
همه اینها معادل هستند:
$ 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 ("پروتکل IPv4L3")؛
...
این ثبت می کند پروتکل Ipv4L3 به عنوان یک جزء لاگ.
(ماکرو با دقت نوشته شده بود تا امکان گنجاندن در داخل یا خارج از آن فراهم شود
فضای نام ns3، و استفاده در پایگاه کد متفاوت خواهد بود، اما هدف اصلی این بود
این را ثبت کنید خارج از فضای نام ns3 در دامنه جهانی فایل.)
2. عبارات ورود به سیستم (تماس های ماکرو) را به توابع و بدنه های تابع خود اضافه کنید.
ورود به سیستم ماکرو
ماکروهای ثبت و سطوح شدت مرتبط هستند
┌───────────────┬──-
│کلاس شدت │ ماکرو │
├───────────────┼─────
│LOG_NONE │ (نیازی نیست) │
├───────────────┼─────
│LOG_ERROR │ NS_LOG_ERROR (...)؛ │
├───────────────┼─────
│LOG_WARN │ NS_LOG_WARN (...)؛ │
├───────────────┼─────
│LOG_DEBUG │ NS_LOG_DEBUG (...)؛ │
├───────────────┼─────
│LOG_INFO │ NS_LOG_INFO (...)؛ │
├───────────────┼─────
│LOG_FUNCTION │ NS_LOG_FUNCTION (...)؛ │
├───────────────┼─────
│LOG_LOGIC │ NS_LOG_LOGIC (...)؛ │
└───────────────┴─
ماکروها به عنوان پخش کننده خروجی عمل می کنند، بنابراین هر چیزی که می توانید به آن ارسال کنید std::out، پیوست
by << اپراتورها مجاز است:
void MyClass::Check (مقدار int، char * مورد)
{
NS_LOG_FUNCTION (این مورد << arg <<)؛
اگر (arg > 10)
{
NS_LOG_ERROR ("مقدار بدی مواجه شد" << مقدار <
" هنگام بررسی " << نام << "!");
}
...
}
توجه داشته باشید که 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 برای اطلاعات بیشتر در مورد اجرا، مانند اندازه a
ساختار داده هنگام افزودن/حذف از آن.
· استفاده کنید NS_LOG_LOGIC برای ردیابی شاخه های منطقی مهم در یک تابع.
· تست کنید که تغییرات لاگ شما باعث شکستن کد نمی شود. چند برنامه نمونه را با
همه اجزای گزارش روشن هستند (مثلاً NS_LOG="***").
ردیابی
زیرسیستم ردیابی یکی از مهم ترین مکانیسم هایی است که باید در آن درک شود ns-3. به
بیشتر موارد ، ns-3 کاربران ایده درخشانی برای برخی شبکه های جدید و بهبود یافته خواهند داشت
ویژگی. به منظور تأیید اینکه این ایده کار می کند، محقق تغییراتی را در یک مورد ایجاد می کند
سیستم موجود و سپس آزمایش هایی را اجرا کنید تا ببینید ویژگی جدید با جمع آوری چگونه رفتار می کند
آماری که رفتار ویژگی را نشان می دهد.
به عبارت دیگر، تمام هدف اجرای یک شبیهسازی، تولید خروجی برای بیشتر است
مطالعه. که در ns-3، زیرسیستمی که محقق را قادر به انجام این کار می کند ردیابی است
زیر سیستم
ردیابی انگیزه
راه های زیادی برای دریافت اطلاعات از یک برنامه وجود دارد. سرراست ترین راه این است
برای چاپ مستقیم اطلاعات در خروجی استاندارد، مانند:
#عبارتند از
...
intmain()
{
...
std::cout << "مقدار x " << x << std::endl;
...
}
این در محیط های کوچک قابل اجرا است، اما با افزایش شبیه سازی های شما
پیچیده است، شما در نهایت با چاپ های بیشتر و بیشتر و وظیفه تجزیه و اجرا مواجه می شوید
محاسبات در خروجی شروع به سخت تر و سخت تر شدن می کند.
نکته دیگری که باید در نظر گرفت این است که هر بار که یک نکته جدید مورد نیاز است، هسته نرم افزار است
باید ویرایش شود و چاپ دیگری معرفی شود. هیچ راه استانداردی برای کنترل همه وجود ندارد
از این خروجی، بنابراین مقدار خروجی تمایل به رشد بدون محدودیت دارد. در نهایت،
پهنای باند مورد نیاز برای خروجی ساده این اطلاعات شروع به محدود کردن زمان اجرا می کند
از شبیه سازی فایلهای خروجی به اندازههای عظیمی میرسند و تجزیه آنها تبدیل به یک میشود
مشکل.
ns-3 مکانیزم ساده ای برای ورود به سیستم و ارائه برخی کنترل بر خروجی از طریق فراهم می کند
ورود اجزاء، اما سطح کنترل اصلاً خیلی ریز نیست. قطع درختان
ماژول یک ابزار نسبتاً صلب است.
مطلوب است که امکاناتی وجود داشته باشد که به شخص اجازه می دهد فقط و فقط به سیستم اصلی دسترسی پیدا کند
اطلاعات مورد نیاز را بدون نیاز به تغییر و کامپایل مجدد سیستم اصلی دریافت کنید. زوج
بهتر است سیستمی باشد که کاربر را در صورت تغییر یا تغییر یک مورد مورد علاقه مطلع کند
اتفاق جالبی افتاد
La ns-3 سیستم ردیابی برای کار در این خطوط طراحی شده است و به خوبی با آن یکپارچه شده است
زیرمجموعههای Attribute و Config که امکان استفاده نسبتاً ساده را فراهم میکنند.
بررسی اجمالی
زیرسیستم ردیابی به شدت به ns-3 مکانیسم های Callback و Attribute شما
باید قبل از اقدام به خواندن و درک بخش های مربوطه از راهنما
سیستم ردیابی را درک کنید
La ns-3 سیستم ردیابی بر اساس مفاهیم منابع ردیابی مستقل و
ردیابی سینک; همراه با مکانیزم یکنواخت برای اتصال منابع به سینک.
منابع ردیابی موجودیت هایی هستند که می توانند رویدادهایی را که در یک شبیه سازی اتفاق می افتد سیگنال دهند و ارائه دهند
دسترسی به داده های اساسی جالب به عنوان مثال، یک منبع ردیابی می تواند زمانی را نشان دهد که a
بسته توسط یک دستگاه شبکه دریافت می شود و امکان دسترسی به محتویات بسته را فراهم می کند
غرق ردیابی علاقه مند یک منبع ردیابی نیز ممکن است نشان دهد که چه زمانی یک حالت جالب است
تغییر در یک مدل اتفاق می افتد به عنوان مثال، پنجره تراکم یک مدل TCP یک عدد اول است
نامزد منبع ردیابی
منابع ردیابی به خودی خود مفید نیستند. آنها باید به کدهای دیگر متصل شوند
که در واقع با اطلاعات ارائه شده توسط منبع کار مفیدی انجام می دهند. در
موجودیت هایی که اطلاعات ردیابی را مصرف می کنند، ردیابی نامیده می شوند. منابع ردیابی هستند
مولد حوادث و ردیابی سینک مصرف کنندگان هستند.
این تقسیم صریح اجازه می دهد تا تعداد زیادی از منابع ردیابی در اطراف پراکنده شوند
سیستم در مکان هایی که نویسندگان مدل معتقدند ممکن است مفید باشد. مگر اینکه کاربر یک را وصل کند
ردیابی به یکی از این منابع، هیچ خروجی نیست. این ترتیب نسبتا اجازه می دهد
کاربران ساده برای اتصال انواع جدید سینک به منابع ردیابی موجود، بدون
نیاز به ویرایش و کامپایل مجدد هسته یا مدل های شبیه ساز.
ممکن است صفر یا بیشتر مصرف کننده رویدادهای ردیابی تولید شده توسط یک منبع ردیابی وجود داشته باشد. یکنفر میتواند
منبع ردیابی را به عنوان نوعی پیوند اطلاعاتی نقطه به چند نقطه در نظر بگیرید.
"پروتکل حمل و نقل" برای این پیوند مفهومی نقطه به چند نقطه است ns-3 تماس لطفا.
از بخش Callback به یاد بیاورید که امکان بازگشت به تماس راهی برای اجازه دادن به دو ماژول است
سیستم برای برقراری ارتباط از طریق فراخوانی عملکرد در حالی که همزمان تماس را جدا می کند
عملکرد از کلاس فراخوانی شده به طور کامل. این همان الزامی است که در بالا ذکر شد
برای سیستم ردیابی
اساسا، یک منبع ردیابی is یک تماس برگشتی که ممکن است چندین عملکرد در آن ثبت شود.
هنگامی که یک trace sink علاقه خود را به دریافت رویدادهای ردیابی ابراز می کند، یک callback به a اضافه می کند
لیستی از تماس های برگشتی که توسط منبع ردیابی نگهداری می شود. هنگامی که یک رویداد جالب اتفاق می افتد، ردیابی
منبع آن را فراخوانی می کند اپراتور() ارائه صفر یا چند پارامتر این به منبع می گوید
فهرست تماس های آن را مرور کنید و هر کدام را به نوبه خود فراخوانی کنید. به این ترتیب پارامتر(های)
به سینک های ردیابی که فقط عملکرد هستند، منتقل می شوند.
La ساده ترین مثال
صرفاً برای تقویت آنچه گفتیم استفاده از یک مثال سریع مفید خواهد بود.:
#include "ns3/object.h"
#include "ns3/uinteger.h"
#include "ns3/traced-value.h""
#include "ns3/trace-source-accessor.h"
#عبارتند از
با استفاده از فضای نام ns3;
اولین کاری که باید انجام دهید این است که فایل های مورد نیاز را وارد کنید. همانطور که در بالا ذکر شد، سیستم ردیابی
به شدت از سیستم های Object و Attribute استفاده می کند. دو مورد اول شامل آوردن در
اعلامیه برای آن سیستم ها پرونده، traced-value.h مورد نیاز را وارد می کند
اعلامیه هایی برای ردیابی داده هایی که از معنای ارزشی پیروی می کنند.
به طور کلی، معناشناسی ارزش فقط به این معنی است که شما می توانید شی را به اطراف منتقل کنید، نه یک
نشانی. برای اینکه اصلاً از معناشناسی ارزش استفاده کنید، باید یک شی با یک داشته باشید
سازنده کپی مرتبط و اپراتور انتساب موجود است. ما الزامات را گسترش می دهیم
برای صحبت در مورد مجموعه ای از عملگرهایی که برای انواع داده های قدیمی (POD) از پیش تعریف شده اند.
عملگر=، عملگر++، عملگر--، عملگر+، عملگر==، و غیره.
معنی همه اینها این است که شما قادر خواهید بود تغییرات را در یک شی ساخته شده با استفاده از آن ردیابی کنید
آن اپراتورها:
کلاس MyObject: عمومی Object
{
عمومی:
استاتیک TypeId GetTypeId (باطل)
{
static TypeId tid = TypeId ("MyObject")
SetParent (Object::GetTypeId ())
.AddConstructor ()
.AddTraceSource ("MyInteger"،
"یک مقدار صحیح برای ردیابی."،
MakeTraceSourceAccessor (&MyObject::m_myInt))
;
برگرد
}
MyObject () {}
TracedValue m_myInt;
};
از آنجایی که سیستم ردیابی با ویژگی ها یکپارچه شده است و ویژگی ها با اشیاء کار می کنند،
باید وجود داشته باشد ns-3 شیء برای منبع ردیابی برای زندگی در. دو خط مهم از
کد هستند .AddTraceSource و TracedValue اعلام.
La .AddTraceSource "قلابهای" مورد استفاده برای اتصال منبع ردیابی به
دنیای بیرون. در TracedValue اعلامیه زیرساختی را فراهم می کند که بیش از حد بارگذاری می کند
اپراتورهایی که در بالا ذکر شد و فرآیند برگشت تماس را هدایت می کند.:
از درجه اعتبار ساقط
IntTrace (Int oldValue، Int newValue)
{
std::cout << "ردیابی" << oldValue << " به " << newValue << std::endl;
}
این تعریف سینک ردیابی است. این به طور مستقیم به یک تابع تماس پاسخ می دهد.
این تابع هر زمان که یکی از عملگرها فراخوانی می شود TracedValue is
اجرا شده.:
INT
اصلی (int argc، char *argv[])
{
Ptr myObject = CreateObject ()
myObject->TraceConnectWithoutContext ("MyInteger"، MakeCallback(&IntTrace));
myObject->m_myInt = 1234;
}
در این قطعه، اولین کاری که باید انجام شود ایجاد شی است که در آن
منبع ردیابی زندگی می کند
مرحله بعدی، TraceConnectWithoutContext، ارتباط بین ردیابی را تشکیل می دهد
منبع و سینک ردیابی توجه کنید MakeCallback تابع قالب به یاد بیاورید از
بخش Callback که این یک عامل تخصصی مسئول ارائه آن را ایجاد می کند
اضافه بار اپراتور() برای "آتش" پاسخ تماس استفاده می شود. عملگرهای بارگذاری شده (++، --، و غیره)
از این استفاده خواهد کرد اپراتور() برای فراخوانی تماس واقعی. در TraceConnectWithoutContext,
پارامتر رشته ای را می گیرد که نام ویژگی اختصاص داده شده به ردیابی را ارائه می دهد
منبع بیایید فعلاً کمی در مورد زمینه را نادیده بگیریم زیرا هنوز مهم نیست.
در نهایت خط،:
myObject->m_myInt = 1234;
باید به عنوان فراخوانی تفسیر شود اپراتور= روی متغیر عضو m_myInt با
عدد صحیح 1234 به عنوان یک پارامتر ارسال شد. به نظر می رسد که این عملگر تعریف شده است (با
TracedValue) برای اجرای یک فراخوانی که void برمی گرداند و دو مقدار صحیح را به عنوان می گیرد
پارامترها -- یک مقدار قدیمی و یک مقدار جدید برای عدد صحیح مورد نظر. دقیقا همینطوره
امضای تابع برای تابع پاسخ به تماس که ارائه کردیم -- IntTrace.
به طور خلاصه، منبع ردیابی، در اصل، متغیری است که فهرستی از تماسهای برگشتی را در خود نگه میدارد. آ
ردیابی سینک تابعی است که به عنوان هدف تماس برگشتی استفاده می شود. ویژگی و نوع شی
سیستم های اطلاعاتی برای ارائه راهی برای اتصال منابع ردیابی به ردیابی سینک ها استفاده می شود. در
عمل "ضربه زدن" به یک منبع ردیابی، اجرای یک اپراتور بر روی منبع ردیابی است که شلیک می کند
پاسخ به تماس ها این باعث می شود که ردیابی تماس های سینک علاقه به منبع را ثبت کند
با پارامترهای ارائه شده توسط منبع فراخوانی می شود.
با استفاده از la پیکربندی زیر سیستم به اتصال به پی گیری منابع
La TraceConnectWithoutContext تماس نشان داده شده در بالا در مثال ساده در واقع بسیار است
به ندرت در سیستم استفاده می شود. به طور معمول، پیکربندی زیرسیستم برای امکان انتخاب استفاده می شود
یک منبع ردیابی در سیستم با استفاده از چیزی که a نامیده می شود پیکربندی مسیر.
برای مثال، ممکن است چیزی شبیه به شکل زیر در سیستم (گرفته شده) پیدا کنید
از جانب examples/tcp-large-transfer.cc):
void CwndTracer (uint32_t oldval، uint32_t newval) {}
...
پیکربندی::ConnectWithoutContext (
"/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CngestionWindow"،
MakeCallback (&CwndTracer))؛
این باید بسیار آشنا به نظر برسد. همان مثال قبلی است با این تفاوت که
تابع عضو ایستا کلاس پیکربندی به جای متد در فراخوانی می شود شیء;
و به جای یک صفت نام، یک مسیر در حال ارائه است.
اولین کاری که باید انجام دهید خواندن مسیر به عقب است. آخرین بخش مسیر باید باشد
an صفت از شیء. در واقع، اگر شما یک اشاره گر به شیء که دارای
"پنجره ازدحام" صفت مفید (به آن زنگ بزنید شی، می توانید این را دقیقاً مانند آن بنویسید
مثال قبلی:
void CwndTracer (uint32_t oldval، uint32_t newval) {}
...
theObject->TraceConnectWithoutContext ("CngestionWindow"، MakeCallback (&CwndTracer));
معلوم می شود که کد برای پیکربندی::ConnectWithoutContext دقیقا همین کار را می کند این
تابع مسیری را طی می کند که نشان دهنده زنجیره ای از شیء اشاره گرها را دنبال می کند و آنها را تا آن زمان دنبال می کند
به انتهای مسیر می رسد و آخرین بخش را به صورت an تعبیر می کند صفت در آخرین
هدف - شی. بیایید از طریق آنچه اتفاق می افتد قدم بزنیم.
کاراکتر "/" پیشرو در مسیر به فضای نامی اشاره دارد. یکی از
فضاهای نام از پیش تعریف شده در سیستم پیکربندی "NodeList" است که لیستی از همه موارد است.
گره ها در شبیه سازی آیتم های موجود در لیست با شاخص هایی در لیست ارجاع داده می شوند، بنابراین
"/NodeList/0" به گره صفر در لیست گره های ایجاد شده توسط شبیه سازی اشاره دارد.
این گره در واقع یک است Ptr و همچنین یک زیر کلاس از an است ns3:: شی.
همانطور که در بخش Object-model توضیح داده شد، ns-3 از یک مدل تجمع شی پشتیبانی می کند. در
بخش مسیر بعدی با کاراکتر "$" شروع می شود که نشان دهنده a است GetObject تماس باید باشد
ساخته شده به دنبال نوع زیر است. هنگامی که یک گره توسط یک مقداردهی اولیه می شود
InternetStackHelper تعدادی از اینترفیس ها در گره جمع می شوند. یکی از این موارد است
پروتکل TCP سطح چهار نوع زمان اجرا این شی پروتکل است ns3::TcpL4Protocol''.
چه زمانی la `` GetObject اجرا می شود، یک اشاره گر به شی از این نوع برمی گرداند.
La پروتکل TcpL4 کلاس یک ویژگی به نام "SocketList" را تعریف می کند که لیستی از
پریز برق. هر سوکت در واقع یک ns3:: شی با خودت خواص. موارد موجود در
فهرست سوکتها مانند NodeList با ایندکس ارجاع میشوند، بنابراین «SocketList/0»
به سوکت صفر در لیست سوکت های روی گره صفر در NodeList اشاره دارد --
اولین گره ساخته شده در شبیه سازی.
این سوکت که نوع آن معلوم می شود ns3::TcpSocketImpl یک ویژگی را تعریف می کند
به نام "CngestionWindow" که یک TracedValue.
پیکربندی::ConnectWithoutContext اکنون یک،:
object->TraceConnectWithoutContext ("CngestionWindow"، MakeCallback (&CwndTracer))؛
با استفاده از اشاره گر شی از "SocketList/0" که ارتباط بین ردیابی را ایجاد می کند
منبع تعریف شده در سوکت تماس برگشتی -- CwndTracer.
حال، هر زمان که تغییری در آن ایجاد شود TracedValue نشان دهنده ازدحام
در پنجره سوکت TCP، فراخوان ثبت شده اجرا می شود و تابع
CwndTracer چاپ کردن مقادیر قدیمی و جدید تراکم TCP نامیده می شود
پنجره.
با استفاده از la ردیابی API
سه سطح از تعامل با سیستم ردیابی وجود دارد:
· کاربر مبتدی می تواند به راحتی کنترل کند که کدام اشیاء در ردیابی شرکت می کنند.
· کاربران متوسط می توانند سیستم ردیابی را برای اصلاح فرمت خروجی تولید شده گسترش دهند
یا از منابع ردیابی موجود به روش های مختلف استفاده کنید، بدون اینکه هسته اصلی را تغییر دهید
شبیه ساز؛
· کاربران پیشرفته می توانند هسته شبیه ساز را برای اضافه کردن منابع ردیابی جدید و سینک ها تغییر دهند.
با استفاده از پی گیری یاران
La ns-3 کمککنندههای ردیابی محیطی غنی برای پیکربندی و انتخاب متفاوت فراهم میکنند
ردیابی رویدادها و نوشتن آنها در فایل ها. در بخش های قبلی، در درجه اول "ساختمان
توپولوژیها، ما انواع مختلفی از روشهای کمکی ردیابی را دیدهایم که برای استفاده طراحی شدهاند
در داخل سایر کمک کنندگان (دستگاه).
شاید دیدن برخی از این تغییرات را به خاطر بیاورید:
pointToPoint.EnablePcapAll ("دوم");
pointToPoint.EnablePcap ("دوم"، p2pNodes.Get (0)->GetId ()، 0);
csma.EnablePcap ("سوم"، csmaDevices.Get (0)، true);
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
با این حال، آنچه ممکن است واضح نباشد این است که یک مدل ثابت برای همه آنها وجود دارد
روش های مرتبط با ردیابی موجود در سیستم اکنون کمی وقت می گذاریم و نگاهی می اندازیم
در "تصویر بزرگ".
در حال حاضر دو مورد استفاده اولیه از کمک ردیابی در وجود دارد ns-3: کمک های دستگاه
و کمک کنندگان پروتکل کمککنندگان دستگاه به مشکل تعیین ردیابیها نگاه میکنند
از طریق یک گره، جفت دستگاه فعال شود. برای مثال، ممکن است بخواهید آن pcap را مشخص کنید
ردیابی باید در یک دستگاه خاص در یک گره خاص فعال شود. این نتیجه از
ns-3 مدل مفهومی دستگاه و همچنین مدل های مفهومی دستگاه های مختلف
کمک کنندگان به دنبال طبیعی از این، فایل های ایجاد شده به دنبال a
- - کنوانسیون نامگذاری
کمککنندگان پروتکل به مشکل تعیین ردیابی از طریق آن میپردازند
یک جفت پروتکل و رابط این نتیجه از ns-3 مدل مفهومی پشته پروتکل،
و همچنین مدل های مفهومی کمک کننده های پشته اینترنت. به طور طبیعی، فایل های ردیابی
باید دنبال شود - - کنوانسیون نامگذاری
بنابراین کمک کننده های ردیابی به طور طبیعی در یک طبقه بندی دو بعدی قرار می گیرند. وجود دارد
نکات ظریفی که مانع از رفتار یکسان هر چهار کلاس می شود، اما ما تلاش می کنیم
کاری کنید که همه آنها تا حد امکان به طور مشابه کار کنند. و در صورت امکان آنالوگ هایی برای آن وجود دارد
همه متدها در همه کلاسها
┌────────────────┬──-
│ │ pcap │ ascii │
├────────────────┼─────
│دستیار کمکی │ │ │
├────────────────┼─────
│راهنمای پروتکل │ │ │
└────────────────┴
ما از رویکردی به نام a استفاده می کنیم MIXIN برای افزودن قابلیت ردیابی به کلاس های کمکی ما. آ
MIXIN کلاسی است که عملکردی را ارائه می دهد که توسط یک زیر کلاس به ارث رسیده است.
ارث بردن از میکسین نوعی تخصص در نظر گرفته نمی شود، اما در واقع راهی است
قابلیت جمع آوری
بیایید نگاهی گذرا به هر چهار مورد و موارد مربوط به آنها بیندازیم میکسین.
Pcap ردیابی دستگاه یاران
هدف این کمککنندهها این است که افزودن یک تسهیلات ردیابی pcap ثابت به یک آسانتر باشد
ns-3 دستگاه ما می خواهیم همه طعم های مختلف ردیابی pcap در سراسر یکسان عمل کنند
همه دستگاهها، بنابراین روشهای این کمکها به دستیاران دستگاه به ارث میرسد. نگاهی بیاندازید
at src/network/helper/trace-helper.h اگر می خواهید در حین نگاه کردن، بحث را دنبال کنید
کد واقعی
کلاس PcapHelperForDevice هست یک MIXIN عملکرد سطح بالایی را برای استفاده فراهم می کند
ردیابی pcap در یک ns-3 دستگاه هر دستگاهی باید یک روش مجازی را پیاده سازی کند
از این کلاس به ارث رسیده است.:
خالی مجازی EnablePcapInternal (std::پیشوند رشته، Ptr nd، bool promiscuous) = 0;
امضای این روش نمایانگر دیدگاه دستگاه محور از وضعیت در این است
مرحله. همه متدهای عمومی که از کلاس به ارث رسیده اند PcapUserHelperForDevice کاهش به
فراخوانی این روش پیاده سازی وابسته به دستگاه. مثلا پایین ترین سطح
روش pcap،:
void EnablePcap (std::پیوند رشته، Ptr nd، bool promiscuous = false، bool explicitFilename = false);
اجرای دستگاه را فراخوانی خواهد کرد EnablePcapInternal به طور مستقیم. همه pcap های عمومی دیگر
روشهای ردیابی مبتنی بر این پیادهسازی برای ارائه سطح کاربر اضافی است
عملکرد. معنای این امر برای کاربر این است که همه کمککنندگان دستگاه در سیستم این کار را انجام خواهند داد
همه روش های ردیابی pcap را در دسترس داشته باشید. و این روش ها همه به یک شکل عمل خواهند کرد
در صورتی که دستگاه پیاده سازی کند EnablePcapInternal به درستی.
Pcap ردیابی دستگاه کمک کننده مواد و روش ها
void EnablePcap (std::پیوند رشته، Ptr nd،
bool promiscuous = false, bool explicitFilename = false);
void EnablePcap (std::پیوند رشته، std::string ndName،
bool promiscuous = false, bool explicitFilename = false);
void EnablePcap (std::پیشوند رشته، NetDeviceContainer d،
bool promiscuous = نادرست);
void EnablePcap (std::پیوند رشته، NodeContainer n،
bool promiscuous = نادرست);
void EnablePcap (std::پیشوند رشته، uint32_t nodeid، uint32_t deviceid،
bool promiscuous = نادرست);
void EnablePcapAll (std::پیوند رشته، bool promiscuous = false);
در هر یک از روش های نشان داده شده در بالا، یک پارامتر پیش فرض به نام وجود دارد بی قاعده که
پیش فرض را به false می دهد. این پارامتر نشان می دهد که ردیابی نباید در آن جمع شود
حالت بی قرار اگر میخواهید ردیابیهای شما شامل تمام ترافیکی باشد که دستگاه مشاهده میکند
(و اگر دستگاه از یک حالت غیرقانونی پشتیبانی می کند) به سادگی یک پارامتر واقعی را به هر یک از آنها اضافه کنید
تماس های بالا مثلا،:
Ptr nd
...
helper.EnablePcap ("پیشوند"، nd، درست)؛
ضبط حالت بی رویه را در NetDevice مشخص شده توسط nd.
دو روش اول همچنین شامل یک پارامتر پیش فرض به نام می باشد explicit Filename که خواهد شد
در زیر مورد بحث قرار گیرد.
شما تشویق می شوید که Doxygen را برای کلاس مطالعه کنید PcapHelperForDevice برای یافتن جزئیات
از این روش ها؛ اما به طور خلاصه ...
شما می توانید ردیابی pcap را روی یک جفت گره/شبکه-دستگاه خاص با ارائه a فعال کنید
Ptr به یک EnablePcap روش. Ptr از دستگاه شبکه ضمنی است
باید دقیقا متعلق به یکی باشد گره. مثلا،:
Ptr nd
...
helper.EnablePcap ("پیشوند"، nd);
شما می توانید ردیابی pcap را روی یک جفت گره/شبکه-دستگاه خاص با ارائه a فعال کنید
std::string نشان دهنده یک رشته سرویس نام شی به an EnablePcap روش.
Ptr از رشته نام به بالا نگاه می شود. دوباره، ضمنی است زیرا
دستگاه شبکه نامگذاری شده باید دقیقاً متعلق به یکی باشد گره. مثلا،:
نام ها::افزودن ("سرور" ...);
نام ها::افزودن ("server/eth0" ...);
...
helper.EnablePcap ("پیشوند"، "سرور/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 ردیابی دستگاه کمک کننده نام فایل انتخاب
به طور ضمنی در توضیحات روش بالا ساخت یک نام فایل کامل توسط
روش اجرا طبق قرارداد، آثار pcap در ns-3 سیستم به شکل هستند
- شناسه > - id>.pcap
همانطور که قبلا ذکر شد، هر گره در سیستم یک شناسه گره اختصاص داده شده به سیستم خواهد داشت. و
هر دستگاه نسبت به گره خود یک شاخص رابط (که شناسه دستگاه نیز نامیده می شود) خواهد داشت.
پس به طور پیش فرض، یک فایل ردیابی pcap در نتیجه فعال کردن ردیابی در اول ایجاد می شود
دستگاه گره 21 با استفاده از پیشوند "پیشوند" خواهد بود پیشوند-21-1.pcap.
شما همیشه می توانید استفاده کنید ns-3 سرویس نام شیء برای روشن تر شدن این موضوع. به عنوان مثال، اگر
شما از سرویس نام شی استفاده می کنید تا نام "سرور" را به گره 21 اختصاص دهید، یعنی pcap حاصل
نام فایل ردیابی به طور خودکار تبدیل می شود، prefix-server-1.pcap و اگر شما نیز اختصاص دهید
نام "eth0" را در دستگاه قرار دهید، نام فایل pcap شما به طور خودکار این را انتخاب می کند و می شود
نام prefix-server-eth0.pcap.
در نهایت، دو تا از روش های نشان داده شده در بالا،:
void EnablePcap (std::پیوند رشته، Ptr nd، bool promiscuous = false، bool explicitFilename = false);
void EnablePcap (std::پیوند رشته، std::string ndName، bool promiscuous = false، bool explicitFilename = false);
یک پارامتر پیش فرض به نام داشته باشید explicit Filename. وقتی روی true تنظیم شود، این پارامتر
مکانیزم تکمیل خودکار نام فایل را غیرفعال می کند و به شما امکان می دهد یک فایل واضح ایجاد کنید
نام فایل. این گزینه فقط در روش هایی موجود است که ردیابی pcap را در a فعال می کنند
تک دستگاه
بهعنوان مثال، به منظور ترتیب دادن یک کمککننده دستگاه برای ایجاد یک pcap ناسازگار
ضبط فایل با نام خاص (my-pcap-file.pcap) در یک دستگاه معین، می توان:
Ptr nd
...
helper.EnablePcap ("my-pcap-file.pcap"، nd، true، true)؛
اول درست پارامتر ردیابی حالت بیجا را فعال می کند و دومی به کمک کننده می گوید
برای تفسیر پیشوند پارامتر به عنوان نام فایل کامل
آسچی ردیابی دستگاه یاران
رفتار کمک کننده ردیابی آسکی MIXIN به طور قابل توجهی شبیه به نسخه pcap است.
نگاهی به src/network/helper/trace-helper.h اگر می خواهید بحث را دنبال کنید
در حالی که به کد واقعی نگاه می کنید.
کلاس AsciiTraceHelperForDevice عملکرد سطح بالایی را برای استفاده از ascii اضافه می کند
ردیابی به کلاس کمکی دستگاه همانطور که در مورد pcap، هر دستگاهی باید a را پیاده سازی کند
روش مجازی منفرد که از ردیابی ascii به ارث رسیده است MIXIN.:
فضای خالی مجازی EnableAsciiInternal (Ptr stream، std::پیوند رشته، Ptr nd) = 0;
امضای این روش نمایانگر دیدگاه دستگاه محور از وضعیت در این است
مرحله؛ و همچنین این واقعیت که کمک کننده ممکن است در حال نوشتن به یک جریان خروجی مشترک باشد. همه از
روش های عمومی مرتبط با ردیابی ascii که از کلاس به ارث رسیده است AsciiTraceHelperForDevice
به فراخوانی این روش پیاده سازی وابسته به دستگاه کاهش دهید. به عنوان مثال
روشهای ردیابی آسکی پایینترین سطح،:
void EnableAscii (std::پیوند رشته، Ptr nd)؛
void EnableAscii (Ptr جریان، Ptr nd)؛
اجرای دستگاه را فراخوانی خواهد کرد EnableAsciiInternal به طور مستقیم، ارائه یک
پیشوند یا جریان معتبر سایر روشهای ردیابی ascii عمومی بر این اساس خواهند بود
توابع سطح پایین برای ارائه عملکرد اضافی در سطح کاربر. این به چه معنی است
کاربر این است که تمام کمککنندگان دستگاه در سیستم همه روشهای ردیابی ascii را خواهند داشت
در دسترس؛ و این روشها در همه دستگاهها به یک شکل عمل خواهند کرد
انجام EnablAsciiInternal به درستی.
آسچی ردیابی دستگاه کمک کننده مواد و روش ها
void EnableAscii (std::پیوند رشته، Ptr nd)؛
void EnableAscii (Ptr جریان، Ptr nd)؛
void EnableAscii (std::پیوند رشته، std::string ndName);
void EnableAscii (Ptr stream, std::string ndName);
void EnableAscii (std::پیوند رشته، NetDeviceContainer d)؛
void EnableAscii (Ptr جریان، NetDeviceContainer d)؛
void EnableAscii (std::پیوند رشته، NodeContainer n)؛
void EnableAscii (Ptr جریان، NodeContainer n)؛
void EnableAscii (std::پیوند رشته، uint32_t nodeid، uint32_t deviceid)؛
void EnableAscii (Ptr stream، uint32_t nodeid، uint32_t deviceid)؛
void EnableAsciiAll (std::پیشوند رشته)؛
void EnableAsciiAll (Ptr جریان)؛
شما تشویق می شوید که Doxygen را برای کلاس مطالعه کنید TraceHelperForDevice برای پیدا کردن
جزئیات این روش ها؛ اما به طور خلاصه ...
دو برابر روش های موجود برای ردیابی ascii نسبت به pcap وجود دارد
ردیابی این به این دلیل است که، علاوه بر مدل pcap-style که در آن آثاری از هر یک وجود دارد
یک جفت گره/دستگاه منحصر به فرد در یک فایل منحصر به فرد نوشته می شود، ما از مدلی پشتیبانی می کنیم که در آن ردیابی وجود دارد
اطلاعات بسیاری از جفتهای گره/دستگاه در یک فایل مشترک نوشته میشود. این بدان معنی است که
- - مکانیسم تولید نام فایل با مکانیزمی جایگزین شده است
به یک فایل مشترک مراجعه کنید. و تعداد متدهای API دو برابر می شود تا به همه اجازه دهد
ترکیبات
درست مانند ردیابی pcap، می توانید ردیابی ascii را در یک جفت گره/شبکه-دستگاه خاص فعال کنید.
با تهیه یک Ptr به یک EnableAscii روش. Ptr ضمنی است زیرا
دستگاه خالص باید دقیقا متعلق به یکی باشد گره. مثلا،:
Ptr nd
...
helper.EnableAscii ("پیشوند"، nd);
در این مورد، هیچ متن ردیابی در فایل ردیابی ascii نوشته نمیشود، زیرا چنین خواهد بود
زائد. سیستم نام فایلی را که باید با استفاده از قوانین مشابه ایجاد شود را انتخاب می کند
در بخش pcap توضیح داده شده است، با این تفاوت که فایل به جای پسوند ".tr" خواهد بود
".pcap".
اگر می خواهید ردیابی ascii را در بیش از یک دستگاه شبکه فعال کنید و همه ردیابی ها ارسال شوند
برای یک فایل، می توانید با استفاده از یک شی برای ارجاع به یک فایل، این کار را نیز انجام دهید:
Ptr nd1;
Ptr nd2;
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAscii (stream, nd1);
helper.EnableAscii (stream, nd2);
در این مورد، زمینههای ردیابی در فایل ردیابی ascii نوشته میشوند، زیرا آنها مورد نیاز هستند
برای رفع ابهام از دو دستگاه. توجه داشته باشید که از آنجایی که کاربر کاملاً است
با مشخص کردن نام فایل، رشته باید شامل ".tr" برای سازگاری باشد.
شما می توانید ردیابی ascii را روی یک جفت گره/شبکه-دستگاه خاص با ارائه a فعال کنید
std::string نشان دهنده یک رشته سرویس نام شی به an EnablePcap روش.
Ptr از رشته نام به بالا نگاه می شود. دوباره، ضمنی است زیرا
دستگاه شبکه نامگذاری شده باید دقیقاً متعلق به یکی باشد گره. مثلا،:
نام ها::افزودن ("مشتری" ...);
نام ها::افزودن ("مشتری/eth0" ...);
نام ها::افزودن ("سرور" ...);
نام ها::افزودن ("server/eth0" ...);
...
helper.EnableAscii ("پیشوند"، "client/eth0");
helper.EnableAscii ("پیشوند"، "سرور/eth0");
این منجر به دو فایل به نام می شود prefix-client-eth0.tr و prefix-server-eth0.tr با
ردیابی برای هر دستگاه در فایل ردیابی مربوطه. از آنجایی که تمام EnableAscii
توابع بیش از حد بارگذاری می شوند تا یک استریم راپر بگیرند، می توانید از آن فرم نیز استفاده کنید:
نام ها::افزودن ("مشتری" ...);
نام ها::افزودن ("مشتری/eth0" ...);
نام ها::افزودن ("سرور" ...);
نام ها::افزودن ("server/eth0" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAscii (stream، "client/eth0");
helper.EnableAscii (stream، "server/eth0");
این منجر به یک فایل ردیابی منفرد به نام می شود trace-file-name.tr که شامل همه
رویدادهای ردیابی برای هر دو دستگاه. رویدادها با زمینه ردیابی ابهام میشوند
رشته های.
میتوانید ردیابی ascii را روی مجموعهای از جفتهای نود/شبکه-دستگاه با ارائه یک علامت فعال کنید
NetDeviceContainer. برای هر NetDevice در ظرف نوع بررسی شده است. برای هر
دستگاه از نوع مناسب (همان نوع که توسط کمکی دستگاه مدیریت می شود)، ردیابی است
فعال شد. دوباره، ضمنی است زیرا دستگاه شبکه یافت شده باید دقیقاً متعلق به آن باشد
یک گره. مثلا،:
NetDeviceContainer d = ...;
...
helper.EnableAscii ("پیشوند"، d);
این منجر به ایجاد تعدادی فایل ردیابی ascii می شود که هر کدام در ادامه می آیند
را - - کنوانسیون .tr. ترکیب همه ردیابی ها در یک
یک فایل به طور مشابه با مثال های بالا انجام می شود:
NetDeviceContainer d = ...;
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAscii (stream, d);
میتوانید ردیابی ascii را روی مجموعهای از جفتهای نود/شبکه-دستگاه با ارائه یک علامت فعال کنید
NodeContainer. برای هر گره در NodeContainer متصل است NetDevices تکرار می شوند.
برای هر یک از NetDevice متصل به هر گره در ظرف، نوع آن دستگاه است
بررسی شد. برای هر دستگاه از نوع مناسب (همان نوع که توسط دستگاه مدیریت می شود
کمک کننده)، ردیابی فعال است.:
NodeContainer n;
...
helper.EnableAscii ("پیشوند"، n);
این منجر به ایجاد تعدادی فایل ردیابی ascii می شود که هر کدام در ادامه می آیند
را - - کنوانسیون .tr. ترکیب همه ردیابی ها در یک
یک فایل به طور مشابه با مثال های بالا انجام می شود:
شما می توانید ردیابی pcap را بر اساس شناسه گره و شناسه دستگاه و همچنین به صورت واضح فعال کنید
پترن. هر یک گره در سیستم دارای شناسه گره عدد صحیح است و هر دستگاه به یک گره متصل است
دارای شناسه دستگاه عدد صحیح است.:
helper.EnableAscii ("پیشوند"، 21، 1);
البته، ردیابی ها را می توان در یک فایل واحد مانند شکل بالا ترکیب کرد.
در نهایت، میتوانید ردیابی pcap را برای همه دستگاههای موجود در سیستم، با همان نوع فعال کنید
که توسط دستیار دستگاه مدیریت می شود.:
helper.EnableAsciiAll ("پیشوند");
این منجر به ایجاد تعدادی فایل ردیابی ascii می شود، یکی برای هر دستگاه موجود در آن
سیستم از نوع مدیریت شده توسط کمک کننده. همه این فایل ها به دنبال خواهد بود
- - کنوانسیون .tr. ترکیب همه ردیابی ها در یک واحد
فایل مشابه نمونه های بالا انجام می شود.
آسچی ردیابی دستگاه کمک کننده نام فایل انتخاب
ضمنی در توضیحات روش به سبک پیشوندی در بالا، ساخت کامل است
نام فایل ها با روش پیاده سازی طبق قرارداد، آثار ascii در ns-3 سیستم هستند
از فرم - شناسه > - id>.tr.
همانطور که قبلا ذکر شد، هر گره در سیستم یک شناسه گره اختصاص داده شده به سیستم خواهد داشت. و
هر دستگاه نسبت به گره خود یک شاخص رابط (که شناسه دستگاه نیز نامیده می شود) خواهد داشت.
بنابراین، به طور پیش فرض، یک فایل ردیابی ascii در نتیجه فعال کردن ردیابی در اول ایجاد می شود
دستگاه گره 21 با استفاده از پیشوند "پیشوند" خواهد بود پیشوند-21-1.tr.
شما همیشه می توانید استفاده کنید ns-3 سرویس نام شیء برای روشن تر شدن این موضوع. به عنوان مثال، اگر
شما از سرویس نام شی استفاده می کنید تا نام "سرور" را به گره 21 اختصاص دهید که نتیجه آن می شود
نام فایل ascii trace به طور خودکار تبدیل می شود prefix-server-1.tr و اگر هم تعیین کنید
نام "eth0" به دستگاه، نام فایل ردیابی ascii شما به طور خودکار این را انتخاب می کند
و فراخوانی شود prefix-server-eth0.tr.
Pcap ردیابی پروتکل یاران
هدف اینها میکسین این است که افزودن یک تسهیلات ردیابی ثابت pcap به آن آسان شود
پروتکل ها ما می خواهیم همه طعم های مختلف ردیابی pcap در همه یکسان عمل کنند
پروتکل ها، بنابراین روش های این کمک کننده ها توسط stack helper ها به ارث می رسد. نگاهی به
src/network/helper/trace-helper.h اگر می خواهید در حین نگاه کردن، بحث را دنبال کنید
کد واقعی
در این بخش روشهایی را که در پروتکل اعمال میشود، توضیح خواهیم داد IPv4. به
ردیابی را در پروتکل های مشابه مشخص کنید، فقط نوع مناسب را جایگزین کنید. مثلا،
استفاده از Ptr به جای یک Ptr و تماس بگیرید EnablePcapIpv6 بجای EnablePcapIpv4.
کلاس PcapHelperForIpv4 عملکرد سطح بالایی را برای استفاده از ردیابی pcap فراهم می کند
در IPv4 پروتکل هر کمک کننده پروتکلی که این روش ها را فعال می کند باید یک واحد را پیاده سازی کند
متد مجازی که از این کلاس به ارث رسیده است. اجرای جداگانه ای برای
IPv6به عنوان مثال، اما تنها تفاوت در نام و امضای روش خواهد بود.
نام متدهای مختلف برای رفع ابهام کلاس مورد نیاز است IPv4 از جانب IPv6 که هر دو هستند
برگرفته از کلاس شیءو روش هایی که دارای امضای یکسانی هستند.:
فضای خالی مجازی EnablePcapIpv4Internal (std::پیشوند رشته، Ptr ipv4، رابط uint4_t) = 32;
امضای این روش نمایانگر پروتکل و نمای رابط محوری است
وضعیت در این سطح همه متدهای عمومی که از کلاس به ارث رسیده اند PcapHelperForIpv4
به فراخوانی این روش پیاده سازی وابسته به دستگاه کاهش دهید. به عنوان مثال
روش pcap پایین ترین سطح،:
void EnablePcapIpv4 (std::پیشوند رشته، Ptr رابط ipv4، uint4_t)؛
اجرای دستگاه را فراخوانی خواهد کرد EnablePcapIpv4Internal به طور مستقیم. همه عمومی های دیگر
روشهای ردیابی pcap بر اساس این پیادهسازی ساخته شدهاند تا سطح کاربر اضافی را ارائه دهند
عملکرد. معنای این امر برای کاربر این است که تمام کمککنندگان پروتکل در سیستم این کار را انجام خواهند داد
همه روش های ردیابی pcap را در دسترس داشته باشید. و این روش ها همه به یک شکل عمل خواهند کرد
اگر کمک کننده پیاده سازی کند، از پروتکل ها عبور می کند EnablePcapIpv4Internal به درستی.
Pcap ردیابی پروتکل کمک کننده مواد و روش ها
این روش ها به گونه ای طراحی شده اند که در یک مکاتبه یک به یک با گره- و
NetDevice- نسخه های مرکزی از نسخه های دستگاه. بجای گره و NetDevice جفت
محدودیت ها، ما از محدودیت های پروتکل و رابط استفاده می کنیم.
توجه داشته باشید که درست مانند نسخه دستگاه، شش روش وجود دارد:
void EnablePcapIpv4 (std::پیشوند رشته، Ptr رابط ipv4، uint4_t)؛
void EnablePcapIpv4 (std::پیوند رشته، std::string ipv4Name، رابط uint32_t)؛
void EnablePcapIpv4 (std::پیوند رشته، Ipv4InterfaceContainer c)؛
void EnablePcapIpv4 (std::پیوند رشته، NodeContainer n)؛
void EnablePcapIpv4 (std::پیوند رشته، uint32_t nodeid، رابط uint32_t)؛
void EnablePcapIpv4All (std::پیشوند رشته)؛
شما تشویق می شوید که Doxygen را برای کلاس مطالعه کنید PcapHelperForIpv4 برای یافتن جزئیات
از این روش ها؛ اما به طور خلاصه ...
میتوانید ردیابی pcap را روی یک جفت پروتکل/رابط خاص با ارائه یک علامت فعال کنید
Ptr و رابط به یک EnablePcap روش. مثلا،:
Ptr ipv4 = node->GetObject ()
...
helper.EnablePcapIpv4 ("پیشوند"، ipv4، 0);
شما می توانید ردیابی pcap را روی یک جفت گره/شبکه-دستگاه خاص با ارائه a فعال کنید
std::string نشان دهنده یک رشته سرویس نام شی به an EnablePcap روش.
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 را روی مجموعهای از جفتهای پروتکل/رابط با ارائه a فعال کنید
NodeContainer. برای هر گره در NodeContainer پروتکل مناسب پیدا می شود. برای
هر پروتکل، اینترفیس های آن شمارش می شود و ردیابی در نتیجه فعال می شود
جفت مثلا،:
NodeContainer n;
...
helper.EnablePcapIpv4 ("پیشوند"، n);
شما می توانید ردیابی pcap را بر اساس شناسه گره و رابط نیز فعال کنید. در این مورد،
node-id به a ترجمه می شود Ptr و پروتکل مناسب در قسمت جستجو می شود
گره پروتکل و رابط حاصل برای مشخص کردن ردیابی به دست آمده استفاده می شود
منبع.:
helper.EnablePcapIpv4 ("پیشوند"، 21، 1);
در نهایت، میتوانید ردیابی pcap را برای تمام رابطهای موجود در سیستم فعال کنید
پروتکلی که همان پروتکلی است که توسط Helper دستگاه مدیریت می شود.:
helper.EnablePcapIpv4All ("پیشوند");
Pcap ردیابی پروتکل کمک کننده نام فایل انتخاب
ضمناً در تمام توضیحات روش فوق، ساخت کامل است
نام فایل ها با روش پیاده سازی طبق قرارداد، ردیابی های pcap برای دستگاه های موجود در
la ns-3 سیستم به شکل هستند - شناسه > - id>.pcap. در شرایطی که
ردیابی پروتکل، یک تناظر یک به یک بین پروتکل ها و گره ها. این هست
چون پروتکل اشیاء به تجمیع می شوند گره اشیاء. از آنجایی که هیچ پروتکل جهانی وجود ندارد
id در سیستم، از شناسه گره مربوطه در نامگذاری فایل استفاده می کنیم. بنابراین یک وجود دارد
امکان برخورد نام فایل در نام فایل های ردیابی به طور خودکار انتخاب شده است. برای این
به همین دلیل، قرارداد نام فایل برای ردیابی پروتکل تغییر کرده است.
همانطور که قبلا ذکر شد، هر گره در سیستم دارای شناسه گره اختصاص یافته به سیستم خواهد بود.
از آنجایی که یک تناظر یک به یک بین نمونه های پروتکل و نمونه های گره وجود دارد
ما از شناسه گره استفاده می کنیم. هر رابط دارای شناسه رابط نسبت به پروتکل خود است. ما استفاده می کنیم
کنوانسیون " -n -من pcap. برای ردیابی نامگذاری فایل در
کمک کنندگان پروتکل
بنابراین، به طور پیش فرض، یک فایل ردیابی pcap در نتیجه فعال کردن ردیابی در ایجاد می شود
رابط 1 پروتکل Ipv4 گره 21 با استفاده از پیشوند "پیشوند" خواهد بود
"prefix-n21-i1.pcap".
شما همیشه می توانید استفاده کنید ns-3 سرویس نام شیء برای روشن تر شدن این موضوع. به عنوان مثال، اگر
شما از سرویس نام شی استفاده می کنید تا نام "serverIpv4" را به Ptr اختصاص دهید روی گره
21، نام فایل ردیابی pcap به طور خودکار تبدیل می شود،
"prefix-nserverIpv4-i1.pcap".
آسچی ردیابی پروتکل یاران
رفتار کمک کننده های ردیابی ascii به طور قابل ملاحظه ای مشابه مورد pcap است. یک را بگیرید
نگاه src/network/helper/trace-helper.h اگر می خواهید در حالی که بحث را دنبال کنید
نگاه کردن به کد واقعی
در این بخش روشهایی را که در پروتکل اعمال میشود، توضیح خواهیم داد IPv4. به
ردیابی را در پروتکل های مشابه مشخص کنید، فقط نوع مناسب را جایگزین کنید. مثلا،
استفاده از Ptr به جای یک Ptr و تماس بگیرید EnableAsciiIpv6 بجای
EnableAsciiIpv4.
کلاس AsciiTraceHelperForIpv4 عملکرد سطح بالایی را برای استفاده از ascii اضافه می کند
ردیابی به کمک پروتکل هر پروتکلی که این روش ها را فعال می کند باید a را پیاده سازی کند
متد مجازی تکی که از این کلاس به ارث برده شده است.:
فضای خالی مجازی EnableAsciiIpv4Internal (Ptr stream، std::پیوند رشته،
Ptr ipv4، رابط uint4_t) = 32;
امضای این روش نمایانگر نمای پروتکل و رابط محوری است
وضعیت در این سطح؛ و همچنین این واقعیت که کمک کننده ممکن است در حال نوشتن به اشتراکی باشد
جریان خروجی همه متدهای عمومی که از کلاس به ارث رسیده اند
PcapAndAsciiTraceHelperForIpv4 به فراخوانی این واحد وابسته به دستگاه کاهش دهید
روش پیاده سازی به عنوان مثال، روش های ردیابی ascii پایین ترین سطح،:
void EnableAsciiIpv4 (std::پیشوند رشته، Ptr رابط ipv4، uint4_t)؛
void EnableAsciiIpv4 (Ptr جریان، Ptr رابط ipv4، uint4_t)؛
اجرای دستگاه را فراخوانی خواهد کرد EnableAsciiIpv4Internal به طور مستقیم، ارائه هر کدام
پیشوند یا جریان سایر روشهای ردیابی ascii عمومی بر این اساس خواهند بود
توابع سطح پایین برای ارائه عملکرد اضافی در سطح کاربر. این به چه معنی است
کاربر این است که تمام کمککنندگان دستگاه در سیستم همه روشهای ردیابی ascii را خواهند داشت
در دسترس؛ و این روشها در تمام پروتکلها به یک شکل عمل خواهند کرد
پروتکل ها اجرا می شوند EnablAsciiIpv4Internal به درستی.
آسچی ردیابی دستگاه کمک کننده مواد و روش ها
void EnableAsciiIpv4 (std::پیشوند رشته، Ptr رابط ipv4، uint4_t)؛
void EnableAsciiIpv4 (Ptr جریان، Ptr رابط ipv4، uint4_t)؛
void EnableAsciiIpv4 (std::پیوند رشته، std::string ipv4Name، رابط uint32_t)؛
void EnableAsciiIpv4 (Ptr stream، std::string ipv4Name، رابط uint32_t);
void EnableAsciiIpv4 (std::پیشوند رشته، Ipv4InterfaceContainer c)؛
void EnableAsciiIpv4 (Ptr جریان، Ipv4InterfaceContainer c)؛
void EnableAsciiIpv4 (std::پیوند رشته، NodeContainer n)؛
void EnableAsciiIpv4 (Ptr جریان، NodeContainer n)؛
void EnableAsciiIpv4 (std::پیوند رشته، uint32_t nodeid، uint32_t deviceid)؛
void EnableAsciiIpv4 (Ptr استریم، uint32_t nodeid، رابط uint32_t)؛
void EnableAsciiIpv4All (std::پیشوند رشته);
void EnableAsciiIpv4All (Ptr جریان)؛
شما تشویق می شوید که Doxygen را برای کلاس مطالعه کنید pcapandasciihelperforipv4 برای پیدا کردن
جزئیات این روش ها؛ اما به طور خلاصه ...
دو برابر روش های موجود برای ردیابی ascii نسبت به pcap وجود دارد
ردیابی این به این دلیل است که، علاوه بر مدل pcap-style که در آن آثاری از هر یک وجود دارد
یک جفت پروتکل/رابط منحصر به فرد در یک فایل منحصر به فرد نوشته می شود، ما از مدلی پشتیبانی می کنیم که در آن
اطلاعات ردیابی برای بسیاری از جفتهای پروتکل/رابط در یک فایل مشترک نوشته میشود. این
به این معنی است که -n - مکانیسم تولید نام فایل جایگزین شده است
توسط مکانیزمی برای ارجاع به یک فایل مشترک؛ و تعداد متدهای API دو برابر می شود
اجازه دادن به همه ترکیب ها
همانطور که در ردیابی pcap، می توانید ردیابی ascii را در یک پروتکل/اینترفیس خاص فعال کنید.
جفت با ارائه a Ptr و رابط به یک EnableAscii روش. مثلا،:
Ptr ipv4;
...
helper.EnableAsciiIpv4 ("پیشوند"، ipv4، 1);
در این مورد، هیچ متن ردیابی در فایل ردیابی ascii نوشته نمیشود، زیرا چنین خواهد بود
زائد. سیستم نام فایلی را که باید با استفاده از قوانین مشابه ایجاد شود را انتخاب می کند
در بخش pcap توضیح داده شده است، با این تفاوت که فایل به جای پسوند ".tr" خواهد بود
".pcap".
اگر می خواهید ردیابی ascii را در بیش از یک رابط فعال کنید و همه ردیابی ها به آن ارسال شوند
یک فایل واحد، می توانید با استفاده از یک شی برای ارجاع به یک فایل، این کار را نیز انجام دهید. ما
قبلاً چیزی شبیه به این در مثال "cwnd" بالا دارید:
Ptr protocol4 = node1->GetObject ()
Ptr protocol4 = node2->GetObject ()
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (stream, protocol1, 1);
helper.EnableAsciiIpv4 (stream, protocol2, 1);
در این مورد، زمینههای ردیابی در فایل ردیابی ascii نوشته میشوند، زیرا آنها مورد نیاز هستند
برای رفع ابهام از دو رابط. توجه داشته باشید که از آنجایی که کاربر کاملاً است
با مشخص کردن نام فایل، رشته باید شامل ".tr" برای سازگاری باشد.
شما می توانید ردیابی ascii را روی یک پروتکل خاص با ارائه a فعال کنید std::string
نشان دهنده یک رشته سرویس نام شی به an EnablePcap روش. Ptr is
از رشته نام به بالا نگاه کرد. در در نام فایل های به دست آمده ضمنی است
یک تناظر یک به یک بین نمونه های پروتکل و گره ها وجود دارد، به عنوان مثال:
نام ها::افزودن ("node1Ipv4" ...);
نام ها::افزودن ("node2Ipv4" ...);
...
helper.EnableAsciiIpv4 ("پیشوند"، "node1Ipv4"، 1);
helper.EnableAsciiIpv4 ("پیشوند"، "node2Ipv4"، 1);
این منجر به دو فایل به نام های "prefix-nnode1Ipv4-i1.tr" و
"prefix-nnode2Ipv4-i1.tr" با ردیابی برای هر رابط در فایل ردیابی مربوطه.
از آنجایی که تمام توابع EnableAscii برای گرفتن یک استریم بسته بارگذاری می شوند، می توانید
از آن فرم نیز استفاده کنید:
نام ها::افزودن ("node1Ipv4" ...);
نام ها::افزودن ("node2Ipv4" ...);
...
Ptr stream = 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 می شود که هر کدام در ادامه می آیند
را -n -من کنوانسیون .tr. ترکیب همه ردیابی ها در یک
یک فایل به طور مشابه با مثال های بالا انجام می شود:
گره های NodeContainer.
...
دستگاه های NetDeviceContainer = deviceHelper.Install (گره ها)؛
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0"، "255.255.255.0")؛
رابط های Ipv4InterfaceContainer = ipv4.Assign (دستگاه ها)؛
...
Ptr stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
...
helper.EnableAsciiIpv4 (جریان، رابط ها)؛
شما می توانید ردیابی ascii را در مجموعه ای از جفت های پروتکل/رابط با ارائه یک فعال کنید
NodeContainer. برای هر گره در NodeContainer پروتکل مناسب پیدا می شود. برای
هر پروتکل، اینترفیس های آن شمارش می شود و ردیابی در نتیجه فعال می شود
جفت مثلا،:
NodeContainer n;
...
helper.EnableAsciiIpv4 ("پیشوند"، n);
این منجر به ایجاد تعدادی فایل ردیابی ascii می شود که هر کدام در ادامه می آیند
را - - کنوانسیون .tr. ترکیب همه ردیابی ها در یک
یک فایل به طور مشابه با مثال های بالا انجام می شود:
شما می توانید ردیابی pcap را بر اساس شناسه گره و شناسه دستگاه نیز فعال کنید. در این مورد،
node-id به a ترجمه می شود Ptr و پروتکل مناسب در قسمت جستجو می شود
گره پروتکل و رابط حاصل برای مشخص کردن ردیابی به دست آمده استفاده می شود
منبع.:
helper.EnableAsciiIpv4 ("پیشوند"، 21، 1);
البته، ردیابی ها را می توان در یک فایل واحد مانند شکل بالا ترکیب کرد.
در نهایت، میتوانید ردیابی ascii را برای تمام اینترفیسهای سیستم، با مرتبط، فعال کنید
پروتکلی که همان پروتکلی است که توسط Helper دستگاه مدیریت می شود.:
helper.EnableAsciiIpv4All ("پیشوند");
این منجر به ایجاد تعدادی فایل ردیابی ascii می شود، یکی برای هر رابط
در سیستم مربوط به پروتکلی از نوع مدیریت شده توسط Helper. همه این فایل ها
را دنبال خواهد کرد -n -من
در یک فایل واحد مشابه مثال های بالا انجام می شود.
آسچی ردیابی دستگاه کمک کننده نام فایل انتخاب
ضمنی در توضیحات روش به سبک پیشوندی در بالا، ساخت کامل است
نام فایل ها با روش پیاده سازی طبق قرارداد، آثار ascii در ns-3 سیستم هستند
از فرم " - - .tr."
همانطور که قبلا ذکر شد، هر گره در سیستم دارای شناسه گره اختصاص یافته به سیستم خواهد بود.
از آنجایی که یک تناظر یک به یک بین پروتکلها و گرهها وجود دارد، برای node-id استفاده میکنیم
برای شناسایی هویت پروتکل هر رابط در یک پروتکل معین دارای یک
شاخص رابط (که به سادگی یک رابط نیز نامیده می شود) نسبت به پروتکل آن. به صورت پیش فرض،
سپس، یک فایل ردیابی ascii در نتیجه فعال کردن ردیابی در اولین دستگاه ایجاد شده است
گره 21، با استفاده از پیشوند "پیشوند"، "prefix-n21-i1.tr" خواهد بود. از پیشوند استفاده کنید
ابهام زدایی چندین پروتکل در هر گره.
شما همیشه می توانید استفاده کنید ns-3 سرویس نام شیء برای روشن تر شدن این موضوع. به عنوان مثال، اگر
شما از سرویس نام شی استفاده می کنید تا نام "serverIpv4" را به پروتکل روی گره اختصاص دهید
21، و همچنین رابط یک را مشخص کنید، نام فایل ردیابی ascii به طور خودکار به دست می آید
تبدیل، "prefix-nserverIpv4-1.tr".
ردیابی پیاده سازی جزئیات
داده ها مجموعه
این فصل چارچوب جمع آوری داده های ns-3 (DCF) را شرح می دهد که ارائه می کند
قابلیت به دست آوردن داده های تولید شده توسط مدل ها در شبیه ساز، برای انجام آنلاین
کاهش و پردازش دادهها، و دادههای خام یا تبدیلشده را به خروجیهای مختلف هدایت میکنند
فرمت.
این چارچوب در حال حاضر از اجراهای مستقل ns-3 پشتیبانی می کند که به هیچ خارجی متکی نیستند
کنترل اجرای برنامه اشیاء ارائه شده توسط DCF ممکن است به آنها متصل شوند ns-3 رد
منابعی برای فعال کردن پردازش داده ها
کد منبع کلاس ها در دایرکتوری موجود است src/stats.
این فصل به شرح زیر سازماندهی شده است. ابتدا مروری بر معماری است
ارایه شده. در ادامه، کمک کنندگان این کلاس ها ارائه می شوند. این درمان اولیه
باید اجازه استفاده اساسی از چارچوب جمع آوری داده ها را برای بسیاری از موارد استفاده بدهد. کاربرانی که
مایل به تولید خروجی خارج از محدوده کمک های فعلی هستند، یا کسانی که مایل به ایجاد هستند
اشیاء جمع آوری داده های خود، باید بقیه فصل را که ادامه می دهد، بخوانند
به جزئیات در مورد تمام انواع شی DCF اساسی و کدگذاری سطح پایین ارائه می دهد
مثال ها.
طرح
DCF از سه کلاس اصلی تشکیل شده است:
· کاوشگر مکانیزمی برای ابزار دقیق و کنترل خروجی داده های شبیه سازی است
برای نظارت بر رویدادهای جالب استفاده می شود. خروجی را به شکل یک یا چند تولید می کند ns-3
منابع ردیابی اشیاء کاوشگر به یک یا چند اثر متصل می شوند غرق (به نام
جمع کننده ها) که نمونه ها را به صورت آنلاین پردازش کرده و آنها را برای خروجی آماده می کند.
· جمع کننده داده های تولید شده توسط یک یا چند شی Probe را مصرف می کند. اجرا می کند
تبدیلهای روی دادهها، مانند عادیسازی، کاهش و محاسبه
آمار اولیه اشیاء جمعآوری دادهای را تولید نمیکنند که مستقیماً توسط آن خروجی شود
ns-3 اجرا؛ در عوض، آنها داده ها را در پایین دست به نوع دیگری از شی به نام خارج می کنند
جمع کننده، که آن عملکرد را انجام می دهد. به طور معمول، گردآورنده ها داده های خود را در خروجی قرار می دهند
شکل منابع ردیابی نیز وجود دارد که به کلکسیونرها اجازه می دهد به صورت زنجیره ای زنجیره شوند.
· جمع کننده نقطه پایانی داده های جمع آوری شده توسط شبکه ای از پروب ها و گردآورندگان است.
مسئولیت اصلی Aggregator جمع آوری داده ها و مربوط به آنها است
ابرداده، به فرمت های خروجی مختلف مانند فایل های متنی ساده، فایل های صفحه گسترده یا
پایگاه های داده
هر سه این کلاس ها این قابلیت را دارند که به صورت پویا خود را روشن یا خاموش کنند
در طول یک شبیه سازی
هر مستقل ns-3 اجرای شبیهسازی که از DCF استفاده میکند معمولاً حداقل یکی را ایجاد میکند
نمونه ای از هر یک از سه کلاس بالا.
[تصویر] نمای کلی چارچوب مجموعه داده ها.UNINDENT
جریان کلی پردازش داده ها به تصویر کشیده شده است داده ها مجموعه چارچوب مروری.
در سمت چپ، دویدن ns-3 شبیه سازی به تصویر کشیده شده است. در جریان اجرای
شبیهسازی، دادهها توسط مدلها از طریق منابع ردیابی یا از طریق ابزارهای دیگر در دسترس قرار میگیرند.
این نمودار نشان می دهد که کاوشگرها می توانند به این منابع ردیابی برای دریافت داده متصل شوند
به صورت ناهمزمان، یا کاوشگرها می توانند برای داده ها نظرسنجی کنند. سپس داده ها به یک شی جمع کننده ارسال می شود
که داده ها را تبدیل می کند. در نهایت می توان یک جمع کننده را به خروجی ها متصل کرد
جمع کننده، برای تولید نمودارها، فایل ها یا پایگاه های داده.
[تصویر] گردآوری چارچوب مجموعه داده ها.UNINDENT
یک تغییر در شکل بالا در ارائه شده است داده ها مجموعه چارچوب تجمع.
این شکل دوم نشان می دهد که اشیاء DCF ممکن است به روشی به هم زنجیر شوند
که اشیاء پایین دست ورودی را از چندین شیء بالادست می گیرند. شکل
به طور مفهومی نشان می دهد که چندین پروب ممکن است خروجی تولید کنند که به یک واحد تغذیه می شود
جمع کننده به عنوان مثال، کلکتوری که نسبت دو شمارنده را خروجی می دهد
به طور معمول هر داده شمارنده را از پروب های جداگانه بدست می آورند. چندین کلکسیونر نیز می توانند
به یک جمعکننده منفرد تغذیه میشود، که (همانطور که از نامش پیداست) ممکن است تعدادی داده جمعآوری کند
جریان ها برای گنجاندن در یک طرح، فایل یا پایگاه داده واحد.
داده ها مجموعه یاران
انعطافپذیری کامل چارچوب جمعآوری دادهها توسط اتصال متقابل ارائه میشود
کاوشگرها، کلکتورها و تجمیع کننده ها. انجام تمامی این ارتباطات متقابل منجر به
بسیاری از دستورات پیکربندی در برنامه های کاربر. برای سهولت استفاده، برخی از رایج ترین
عملیات را می توان ترکیب کرد و در توابع کمکی محصور کرد. علاوه بر این، برخی از
اظهارات مربوط به ns-3 منابع ردیابی به دلیل محدودیتهای موجود، اتصال پایتون ندارند
اتصالات
داده ها مجموعه یاران بررسی اجمالی
در این بخش، مروری بر برخی از کلاسهای کمکی که برای آن ایجاد شدهاند، ارائه میکنیم
پیکربندی چارچوب جمع آوری داده ها را برای برخی موارد استفاده رایج آسان می کند. را
کمککنندهها به کاربران اجازه میدهند تا عملیات مشترک را تنها با چند عبارت در C++ یا خود شکل دهند
برنامه های پایتون اما، این سهولت استفاده با هزینه بسیار کمتری همراه است
انعطاف پذیری نسبت به پیکربندی سطح پایین و نیاز به کدنویسی صریح
پشتیبانی از انواع جدید Probe در Helperها (برای حل مشکلی که در زیر توضیح داده شده است).
تأکید بر کمککنندگان کنونی این است که دادهها را خارج کنند ns-3 ردیابی منابع به
نمودارهای gnuplot یا فایل های متنی، بدون درجه بالایی از سفارشی سازی خروجی یا آماری
پردازش (در ابتدا). همچنین، استفاده به انواع کاوشگر موجود در آن محدود می شود
ns-3. بخشهای بعدی این مستندات به جزئیات بیشتری در مورد ایجاد موارد جدید میپردازد
انواع کاوشگر، و همچنین جزئیات مربوط به قلاب کردن پروب ها، جمع کننده ها و جمع کننده ها
در ترتیبات سفارشی
تا به امروز، دو کمک کننده جمع آوری داده ها پیاده سازی شده است:
· GnuplotHelper
· FileHelper
GnuplotHelper
GnuplotHelper یک کلاس کمکی برای تولید فایل های خروجی است که برای ساخت gnuplot استفاده می شود. در
هدف کلی این است که این توانایی را برای کاربران فراهم کند که به سرعت نمودارهایی را از داده های صادر شده ایجاد کنند
in ns-3 منابع ردیابی به طور پیش فرض، حداقل مقدار تغییر داده انجام می شود.
هدف این است که نمودارهایی با تعداد کمی از دستورات پیکربندی (پیشفرض) تولید کنیم
امکان پذیر است.
GnuplotHelper بررسی اجمالی
GnuplotHelper 3 فایل مختلف را در پایان شبیه سازی ایجاد می کند:
· فایل داده gnuplot با فاصله از هم جدا شده است
· یک فایل کنترل gnuplot
· یک پوسته اسکریپت برای تولید gnuplot
دو دستور پیکربندی وجود دارد که برای تولید نمودارها مورد نیاز است. اولین
بیانیه نمودار را پیکربندی می کند (نام فایل، عنوان، افسانه ها و نوع خروجی، جایی که خروجی
پیش فرض را به PNG تایپ کنید اگر مشخص نیست):
void ConfigurePlot (const std::string &outputFileNameWithoutExtension،
const std::string &title,
const std::string &xLegend،
const std::string &yLegend،
const std::string &terminalType = ".png");
بیانیه دوم منبع ردیابی علاقه را قلاب می کند:
void PlotProbe (const std::string &typeId,
const std:: رشته و مسیر،
const std::string &probeTraceSource،
const std::string &title);
استدلال ها به شرح زیر است:
· typeId: The ns-3 TypeId پروب
· مسیر: مسیر در ns-3 پیکربندی فضای نام برای یک یا چند منبع ردیابی
· probeTraceSource: کدام خروجی پروب (که خود منبع ردیابی است) باید رسم شود
· عنوان: عنوان مرتبط با مجموعه داده(های) (در افسانه gnuplot)
یک نوع در PlotProbe بالا برای تعیین آرگومان اختیاری پنجم است که کنترل می کند
جایی که در طرح کلید (افسانه) قرار می گیرد.
یک مثال کاملاً کار شده (از سی سی هفتم) در زیر نشان داده شده است:
// کمک کننده gnuplot را ایجاد کنید.
gnuplothelper plothelper ؛
// طرح را پیکربندی کنید.
// طرح را پیکربندی کنید. اولین آرگومان پیشوند نام فایل است
// برای فایل های خروجی تولید شده. دوم و سوم و چهارم
// آرگومان ها به ترتیب عنوان طرح، محور x و محور y هستند.
plotHelper.ConfigurePlot ("seventh-packet-byte-count"،
"تعداد بایت بسته در برابر زمان"،
"زمان (ثانیه)"،
"تعداد بایت بسته"،
"png")؛
// نوع پروب، مسیر منبع ردیابی (در فضای نام پیکربندی) و
// کاوش منبع ردیابی خروجی ("OutputBytes") برای رسم. برهان چهارم
// نام برچسب سری داده را در نمودار مشخص می کند. آخرین
// آرگومان طرح را با تعیین محل قرار دادن کلید قالب بندی می کند.
plotHelper.PlotProbe (probeType,
TracePath،
"OutputBytes"،
"تعداد بایت بسته"،
GnuplotAggregator::KEY_BELOW);
در این مثال ، probeType و tracePath به شرح زیر است (برای IPv4):
probeType = "ns3::Ipv4PacketProbe";
tracePath = "/NodeList/*/$ns3::Ipv4L3Protocol/Tx";
probeType یک پارامتر کلیدی برای کار این کمک کننده است. این TypeId باید ثبت شود
در سیستم، و امضای روی سینک ردیابی کاوشگر باید با امضای ردیابی مطابقت داشته باشد
منبعی که به آن وصل شده است. انواع پروب برای تعدادی از انواع داده از پیش تعریف شده است
مربوط به ns-3 مقادیر ردیابی شده، و برای چند امضای منبع ردیابی دیگر مانند
منبع ردیابی 'Tx' ns3::پروتکل IPv4L3 کلاس.
توجه داشته باشید که مسیر منبع ردیابی مشخص شده ممکن است دارای حروف عام باشد. در این مورد، متعدد
مجموعه داده ها در یک نمودار رسم می شوند. یکی برای هر مسیر منطبق
خروجی اصلی تولید شده سه فایل خواهد بود:
هفتم بسته-بایت-count.dat
هفتم بسته-بایت-count.plt
هفتم بسته-بایت-count.sh
در این مرحله، کاربران می توانند فایل .plt را برای سفارشی سازی های بیشتر به صورت دستی ویرایش کنند یا
فقط آن را از طریق gnuplot اجرا کنید. در حال دویدن sh هفتم بسته-بایت-count.sh به سادگی طرح را اجرا می کند
از طریق gnuplot، همانطور که در زیر نشان داده شده است.
[تصویر] Gnuplot دوبعدی ایجاد شده توسط sixth.cc مثال..UNINDENT
مشاهده می شود که عناصر کلیدی (افسانه، عنوان، مکان افسانه، xlabel، ylabel،
و مسیر برای داده ها) همگی در نمودار قرار می گیرند. از آنجایی که دو مسابقه به
مسیر پیکربندی ارائه شده، دو سری داده نشان داده شده است:
· Packet Byte Count-0 مربوط به /NodeList/0/$ns3::Ipv4L3Protocol/Tx است
· Packet Byte Count-1 مربوط به /NodeList/1/$ns3::Ipv4L3Protocol/Tx است
GnuplotHelper ConfigurePlot
GnuplotHelper's ConfigurePlot() تابع را می توان برای پیکربندی نمودارها استفاده کرد.
نمونه اولیه زیر را دارد:
void ConfigurePlot (const std::string &outputFileNameWithoutExtension،
const std::string &title,
const std::string &xLegend،
const std::string &yLegend،
const std::string &terminalType = ".png");
دارای استدلال های زیر است:
┌¬**************************الم ─────────────────┐
│برهان │ شرح │
├¬**************************الم ─────────────────┤
│outputFileNameWithoutExtension │ نام فایل های مرتبط gnuplot به │
│ │ بدون پسوند بنویسید. │
├¬**************************الم ─────────────────┤
│title │ رشته عنوان را برای استفاده برای │ رسم کنید
│ │ این طرح. │
├¬**************************الم ─────────────────┤
│xLegend │ افسانه برای x افقی │
│ │ محور. │
├¬**************************الم ─────────────────┤
│yLegend │ افسانه برای y عمودی │
│ │ محور. │
└¬**************************الم ─────────────────┘
│terminalType │ رشته تنظیم نوع ترمینال برای │
│ │ خروجی. ترمینال پیش فرض │
نوع │ │ "png" است. │
└¬**************************الم ─────────────────┘
GnuplotHelper's ConfigurePlot() تابع پارامترهای مربوط به نمودار را برای این پیکربندی می کند
کمک کننده gnuplot به طوری که یک فایل داده gnuplot با فاصله از هم به نام ایجاد می کند
outputFileNameWithoutExtension + ".dat"، یک فایل کنترلی gnuplot با نام
outputFileNameWithoutExtension + ".plt" و یک اسکریپت پوسته برای تولید gnuplot با نام
outputFileNameWithoutExtension + ".sh".
نمونه ای از نحوه استفاده از این تابع را می توان در قسمت مشاهده کرد سی سی هفتم کد توضیح داده شده در بالا
جایی که به صورت زیر استفاده شد:
plotHelper.ConfigurePlot ("seventh-packet-byte-count"،
"تعداد بایت بسته در برابر زمان"،
"زمان (ثانیه)"،
"تعداد بایت بسته"،
"png")؛
GnuplotHelper PlotProbe
GnuplotHelper's PlotProbe() تابع را می توان برای رسم مقادیر تولید شده توسط پروب ها استفاده کرد.
نمونه اولیه زیر را دارد:
void PlotProbe (const std::string &typeId,
const std:: رشته و مسیر،
const std::string &probeTraceSource،
const std::string &title,
enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE);
دارای استدلال های زیر است:
┌──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┐
│برهان │ شرح │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
│typeId │ شناسه نوع پروب │
│ │ ایجاد شده توسط این یاور. │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
مسیر │ مسیر پیکربندی برای دسترسی به ردیابی │
│ │ منبع. │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
│probeTraceSource │ منبع ردیابی کاوشگر به │
│ │ دسترسی. │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
│title │ عنوانی که باید به │ مرتبط شود
│ │ این مجموعه داده │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
│keyLocation │ محل کلید در │
│ │ طرح. مکان پیش فرض │ است
│ │ داخل. │
└──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┘
GnuplotHelper's PlotProbe() تابع یک مجموعه داده تولید شده با قلاب کردن را ترسیم می کند ns-3
منبع ردیابی با کاوشگر ایجاد شده توسط کمک کننده، و سپس رسم مقادیر از
probeTraceSource. مجموعه داده دارای عنوان ارائه شده خواهد بود و از
"newValue" در هر مهر زمانی.
اگر مسیر پیکربندی بیش از یک تطبیق در سیستم داشته باشد زیرا یک علامت عام وجود دارد، پس
یک مجموعه داده برای هر تطابق رسم خواهد شد. عناوین مجموعه داده ها با پسوند عبارت خواهند بود
کاراکترهای همسان برای هر یک از حروف عام در مسیر پیکربندی، که با فاصله از هم جدا شده اند. برای
به عنوان مثال، اگر عنوان مجموعه داده پیشنهادی رشته "بایت" باشد، و دو علامت عام وجود دارد
در مسیر، عناوین مجموعه داده مانند "bytes-0 0" یا "bytes-12 9" به عنوان امکان پذیر خواهد بود.
برچسب ها برای مجموعه داده هایی که رسم می شوند.
نمونه ای از نحوه استفاده از این تابع را می توان در قسمت مشاهده کرد سی سی هفتم کد توضیح داده شده در بالا
جایی که از آن (با جایگزینی متغیر) به صورت زیر استفاده شد:
plotHelper.PlotProbe ("ns3::Ipv4PacketProbe"،
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx"،
"OutputBytes"،
"تعداد بایت بسته"،
GnuplotAggregator::KEY_BELOW);
دیگر مثال ها
گنوپلو کمک کننده مثال
مثال کمی ساده تر از سی سی هفتم مثال را می توان در یافت
src/stats/examples/gnuplot-helper-example.cc. gnuplot 2 بعدی زیر با استفاده از آن ایجاد شد
مثال.
[تصویر] Gnuplot دو بعدی ایجاد شده توسط gnuplot-helper-example.cc مثال..UNINDENT
در این مثال، یک شی Emitter وجود دارد که شمارنده خود را مطابق a افزایش می دهد
پواسون را پردازش می کند و سپس مقدار شمارنده را به عنوان منبع ردیابی منتشر می کند.
Ptr Emitter = CreateObject ()
نام ها::افزودن ("/Names/Emitter", emitter);
توجه داشته باشید که از آنجایی که در مسیر استفاده شده در زیر هیچ علامت عام وجود ندارد، تنها 1 جریان داده وجود دارد
در طرح ترسیم شده است. این جریان داده منفرد در نمودار به سادگی با عنوان "Emitter Count" شناخته می شود.
بدون پسوند اضافی مانند one will see if wildcards در مسیر وجود دارد.
// کمک کننده gnuplot را ایجاد کنید.
gnuplothelper plothelper ؛
// طرح را پیکربندی کنید.
plotHelper.ConfigurePlot ("gnuplot-helper-example"،
"تعداد امیتر در مقابل زمان"،
"زمان (ثانیه)"،
"تعداد امیتر"،
"png")؛
// مقادیر تولید شده توسط پروب را رسم کنید. مسیری که ما فراهم می کنیم
// به ابهامزدایی از منبع ردیابی کمک میکند.
plotHelper.PlotProbe ("ns3::Uinteger32Probe"،
"/Names/Emitter/Counter"
"خروجی"،
"تعداد امیتر"،
GnuplotAggregator::KEY_INSIDE);
FileHelper
FileHelper یک کلاس کمکی است که برای قرار دادن مقادیر داده در یک فایل استفاده می شود. هدف کلی است
این امکان را برای کاربران فراهم می کند تا به سرعت فایل های متنی فرمت شده را از داده های صادر شده بسازند
in ns-3 منابع ردیابی به طور پیش فرض، حداقل مقدار تغییر داده انجام می شود.
هدف این است که فایلهایی با همان تعداد (پیشفرض) دستورات پیکربندی تولید شود
امکان پذیر است.
FileHelper بررسی اجمالی
FileHelper 1 یا چند فایل متنی را در پایان شبیه سازی ایجاد می کند.
FileHelper می تواند 4 نوع مختلف فایل متنی ایجاد کند:
· فرمت شده
· فاصله جدا شده (پیش فرض)
· جدا شده با ویرگول
· برگه جدا شده است
فایلهای فرمتشده از رشتههای قالب C و تابع sprintf() برای چاپ آنها استفاده میکنند
مقادیر موجود در فایل در حال نوشتن
فایل متنی زیر با 2 ستون از مقادیر قالب بندی شده نامگذاری شده است
هفتم بسته-بایت-count-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
...
فایل متنی مختلف زیر با 2 ستون از مقادیر قالب بندی شده نامگذاری شده است
هفتم بسته-بایت-count-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
...
کد جدیدی که برای تولید دو فایل متنی اضافه شده است در زیر آمده است. جزئیات بیشتر در مورد
این API در بخش بعدی پوشش داده خواهد شد.
توجه داشته باشید که به دلیل وجود 2 مطابقت برای علامت عام در مسیر، 2 فایل متنی جداگانه وجود دارد
ایجاد شدند. اولین فایل متنی که "seventh-packet-byte-count-0.txt" نام دارد.
مربوط به تطابق حروف با علامت "*" جایگزین شده با "0" است. فایل متنی دوم،
که "seventh-packet-byte-count-1.txt" نامگذاری شده است، مربوط به تطابق وایلدکارت با
"*" با "1" جایگزین شد. همچنین توجه داشته باشید که تابع به WriteProbe() خواهد داد
اگر مسیری که دارای حروف عام است مطابقت نداشته باشد، پیام خطا می دهد.
// راهنما فایل را ایجاد کنید.
FileHelper fileHelper;
// فایلی را که باید نوشته شود پیکربندی کنید.
fileHelper.ConfigureFile ("seventh-packet-byte-count",
FileAggregator::FORMATTED);
// برچسب ها را برای این فایل خروجی فرمت شده تنظیم کنید.
fileHelper.Set2dFormat ("زمان (ثانیه) = %.3e\tPacket Byte Count = %.0f");
// مقادیر تولید شده توسط پروب را بنویسید.
fileHelper.WriteProbe ("ns3::Ipv4PacketProbe"،
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx"،
"OutputBytes")؛
FileHelper ConfigureFile
FileHelper's ConfigureFile() تابع را می توان برای پیکربندی فایل های متنی استفاده کرد.
نمونه اولیه زیر را دارد:
void ConfigureFile (const std::string &outputFileNameWithoutExtension،
enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED);
دارای استدلال های زیر است:
┌¬**************************الم ─────────────────┐
│برهان │ شرح │
├¬**************************الم ─────────────────┤
│outputFileNameWithoutExtension │ نام فایل خروجی برای نوشتن │
│ │ بدون تمدید. │
├¬**************************الم ─────────────────┤
│fileType │ نوع فایل برای نوشتن. │
│ │ نوع پیش فرض فایل space │ است
│ │ جدا شد. │
└¬**************************الم ─────────────────┘
FileHelper's ConfigureFile() تابع پارامترهای مربوط به فایل متنی را برای
کمک کننده فایل به طوری که فایلی به نام outputFileNameWithoutExtension plus ایجاد می کند.
اطلاعات اضافی ممکن از موارد منطبق با حروف عام به اضافه "txt." با مقادیر چاپ شده به عنوان
توسط fileType مشخص شده است. نوع فایل پیشفرض با فاصله جدا شده است.
نمونه ای از نحوه استفاده از این تابع را می توان در قسمت مشاهده کرد سی سی هفتم کد توضیح داده شده در بالا
جایی که به صورت زیر استفاده شد:
fileHelper.ConfigureFile ("seventh-packet-byte-count",
FileAggregator::FORMATTED);
FileHelper WriteProbe
FileHelper's WriteProbe() تابع می تواند برای نوشتن مقادیر تولید شده توسط پروب ها استفاده شود
فایل های متنی
نمونه اولیه زیر را دارد:
void WriteProbe (const std::string &typeId,
const std:: رشته و مسیر،
const std::string &probeTraceSource);
دارای استدلال های زیر است:
┌──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┐
│برهان │ شرح │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
│typeId │ شناسه نوع پروب که │ باشد
│ │ ایجاد شد. │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
مسیر │ مسیر پیکربندی برای دسترسی به ردیابی │
│ │ منبع. │
├──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┤
│probeTraceSource │ منبع ردیابی کاوشگر به │
│ │ دسترسی. │
└──────────────────────────────── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ───┘
FileHelper's WriteProbe() تابع فایل های متنی خروجی تولید شده با قلاب کردن را ایجاد می کند
منبع ردیابی ns-3 با یک کاوشگر ایجاد شده توسط کمک کننده، و سپس نوشتن مقادیر از
probeTraceSource. نام فایل های خروجی دارای متن ذخیره شده در متغیر عضو خواهد بود
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/examples/file-helper-example.cc. این مثال فقط از FileHelper استفاده می کند.
فایل متنی زیر با 2 ستون از مقادیر قالب بندی شده نامگذاری شده است file-helper-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 وجود دارد که شمارنده خود را مطابق a افزایش می دهد
پواسون را پردازش می کند و سپس مقدار شمارنده را به عنوان منبع ردیابی منتشر می کند.
Ptr Emitter = CreateObject ()
نام ها::افزودن ("/Names/Emitter", emitter);
توجه داشته باشید که به دلیل اینکه در مسیر استفاده شده در زیر هیچ علامت عام وجود ندارد، تنها 1 فایل متنی وجود دارد
ایجاد شده. این فایل متنی به سادگی "file-helper-example.txt" نامیده می شود، بدون هیچ اضافی
پسوندهایی مانند شما می بینید که اگر علامت های عام در مسیر وجود داشته باشد.
// راهنما فایل را ایجاد کنید.
FileHelper fileHelper;
// فایلی را که باید نوشته شود پیکربندی کنید.
fileHelper.ConfigureFile ("file-helper-example"،
FileAggregator::FORMATTED);
// برچسب ها را برای این فایل خروجی فرمت شده تنظیم کنید.
fileHelper.Set2dFormat ("زمان (ثانیه) = %.3e\tCount = %.0f");
// مقادیر تولید شده توسط پروب را بنویسید. مسیری که ما
// ارائه به ابهامزدایی از منبع ردیابی کمک میکند.
fileHelper.WriteProbe ("ns3::Uinteger32Probe"،
"/Names/Emitter/Counter"
"خروجی")؛
حوزه و محدودیت ها
در حال حاضر فقط این Probes پیاده سازی شده و به GnuplotHelper وصل شده اند
به FileHelper:
· BooleanProbe
· DoubleProbe
· Uinteger8Probe
· Uinteger16Probe
· Uinteger32Probe
· TimeProbe
· PacketProbe
· ApplicationPacketProbe
· Ipv4PacketProbe
بنابراین، این پروب ها تنها TypeId های موجود برای استفاده هستند PlotProbe() و
WriteProbe().
در چند بخش بعدی، هر یک از انواع شیء اساسی (کاوشگر، جمعآور،
و Aggregator) با جزئیات بیشتر، و نشان می دهد که چگونه می توان آنها را با استفاده از یکدیگر متصل کرد
API سطح پایین تر
پروب ها
این بخش عملکردهای ارائه شده توسط کلاس Probe را توضیح می دهد ns-3
شبیه سازی، و مثال هایی در مورد نحوه کدنویسی آنها در یک برنامه ارائه می دهد. این بخش برای
کاربران علاقه مند به توسعه شبیه سازی با ns-3 ابزارها و استفاده از داده ها
مجموعه چارچوب، که کلاس Probe بخشی از آن است، برای تولید خروجی داده با آن
نتایج شبیه سازی آنها
کاوشگر بررسی اجمالی
یک شی Probe قرار است به متغیری از شبیه سازی متصل شود که مقادیر آن
در طول آزمایش به کاربر مربوط است. کاوشگر آنچه بود را ضبط خواهد کرد
مقادیری که در طول شبیه سازی توسط متغیر در نظر گرفته شده و چنین داده هایی را به دیگری منتقل می کند
عضو چارچوب جمع آوری داده ها در حالی که خارج از محدوده این بخش به
بحث کنید که پس از تولید خروجی کاوشگر چه اتفاقی می افتد، کافی است بگوییم که توسط
در پایان شبیه سازی، کاربر اطلاعات دقیقی در مورد مقادیری خواهد داشت
درون متغیری که در حین شبیه سازی کاوش می شود ذخیره می شود.
به طور معمول، یک Probe به یک متصل است ns-3 منبع ردیابی به این ترتیب، هر زمان که
منبع ردیابی یک مقدار جدید صادر می کند، Probe ارزش را مصرف می کند (و آن را به پایین دست صادر می کند
به یک شی دیگر از طریق منبع ردیابی خود).
کاوشگر را می توان به عنوان نوعی فیلتر بر روی منابع ردیابی در نظر گرفت. دلایل اصلی برای
اتصال احتمالی به کاوشگر به جای مستقیم به منبع ردیابی به شرح زیر است:
· پروب ها ممکن است به صورت پویا در طول شبیه سازی با تماس به روشن و خاموش شوند فعال کردن()
و غیر فعال کردن(). به عنوان مثال، خروجی داده ها ممکن است در طول مدت خاموش شود
فاز گرم کردن شبیه سازی
کاوشگرها ممکن است عملیاتی را روی داده ها انجام دهند تا مقادیر پیچیده تر را استخراج کنند
سازه های؛ به عنوان مثال، خروجی مقدار اندازه بسته از یک بسته دریافتی ns3::.
پروب ها یک نام را در فضای نام ns3::Config ثبت می کنند (با استفاده از نام ها::افزودن ()) به طوری که دیگر
اشیاء ممکن است به آنها اشاره کنند.
· کاوشگرها یک روش ثابت را ارائه می دهند که به شخص اجازه می دهد یک پروب را با نام دستکاری کند، مانند
آنچه در ns2measure انجام می شود [Cic06]
Stat::put ("my_metric"، ID، نمونه)؛
معادل ns-3 کد ns2measure فوق، به عنوان مثال است
DoubleProbe::SetValueByPath ("/path/to/probe"، نمونه);
ایجاد
توجه داشته باشید که یک شی کلاس پایه Probe نمی تواند ایجاد شود زیرا یک پایه انتزاعی است
class، یعنی توابع مجازی خالص دارد که پیاده سازی نشده اند. یک شی از
نوع DoubleProbe، که زیر کلاس کلاس Probe است، در اینجا ایجاد می شود تا نشان داده شود
چه باید انجام شود.
یک DoubleProbe در حافظه پویا با استفاده از کلاس اشاره گر هوشمند (Ptr ). به
یک DoubleProbe در حافظه پویا با اشاره گرهای هوشمند ایجاد کنید، فقط باید آن را فراخوانی کنید
ns-3 روش CreateObject():
Ptr myprobe = CreateObject ()
اعلان بالا DoubleProbes را با استفاده از مقادیر پیشفرض برای ویژگیهای خود ایجاد میکند.
چهار ویژگی در کلاس DoubleProbe وجود دارد. دو در شی کلاس پایه
DataCollectionObject و دو در کلاس پایه Probe:
· "Name" (DataCollectionObject)، یک StringValue
· "Enabled" (DataCollectionObject)، یک مقدار Boolean
· "شروع" (پروب)، یک مقدار زمانی
· "توقف" (پروب)، یک مقدار زمانی
با استفاده از روش زیر می توان چنین ویژگی هایی را در ایجاد شیء تنظیم کرد:
Ptr myprobe = CreateObjectWithAttributes (
"Name"، StringValue ("myprobe")،
"فعال"، BooleanValue (نادرست)،
"شروع"، TimeValue (ثانیه (100.0))،
"Stop"، TimeValue (ثانیه (1000.0)))؛
شروع و توقف متغیرهای زمانی هستند که فاصله عمل پروب را تعیین می کنند. در
کاوشگر تنها در صورتی داده خروجی خواهد داد که زمان فعلی شبیه سازی در داخل آن باشد
فاصله مقدار زمانی ویژه 0 ثانیه برای Stop این ویژگی را غیرفعال می کند (یعنی
Probe را برای کل شبیه سازی روشن نگه دارید). فعال پرچمی است که Probe را روشن یا روشن می کند
خاموش است و باید روی true تنظیم شود تا Probe بتواند داده ها را صادر کند. Name نام شیء است
در چارچوب DCF
واردات و صادرات داده ها
ns-3 منابع ردیابی به شدت تایپ می شوند، بنابراین مکانیسم های قلاب کردن پروب ها به یک ردیابی است
منبع و برای صادر کردن داده ها به زیر کلاس های آن تعلق دارد. به عنوان مثال، پیش فرض
توزیع ns-3 یک کلاس DoubleProbe را ارائه می دهد که برای قلاب کردن یک ردیابی طراحی شده است
منبع صادر کننده یک مقدار دو برابر است. در ادامه جزئیات عملکرد DoubleProbe و
سپس در مورد چگونگی تعریف سایر کلاس های Probe توسط کاربر بحث کنید.
DoubleProbe بررسی اجمالی
DoubleProbe به یک با ارزش دوگانه متصل می شود ns-3 منبع ردیابی، و خود صادرات الف
متفاوت با ارزش دوگانه ns-3 منبع ردیابی
کد زیر برگرفته از src/stats/examples/double-probe-example.cc، پایه را نشان می دهد
عملیات لوله کشی DoubleProbe در یک شبیه سازی، جایی که در حال کاوش یک شمارنده است
صادر شده توسط یک شی امیتر (کلاس Emitter).
Ptr Emitter = CreateObject ()
نام ها::افزودن ("/Names/Emitter", emitter);
...
Ptr probe1 = CreateObject ()
// پروب را به شمارنده امیتر وصل کنید
bool connect = probe1->ConnectByObject ("Counter"، emitter);
کد زیر همان شمارنده صادر شده توسط همان شی امیتر را بررسی می کند. این
با این حال، 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 را به عنوان تنظیم کند
به شرح زیر است:
از درجه اعتبار ساقط
Emitter::Count (باطل)
{
...
m_counter += 1.0;
DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe"، m_counter);
...
}
مثال بالا نشان میدهد که چگونه کدی که Probe را فراخوانی میکند نیازی به صریح بودن ندارد
به Probe اشاره می کند، اما می تواند تنظیم مقدار را از طریق فضای نام Config هدایت کند.
این از نظر عملکرد مشابه است آمار::قرار دهید روش معرفی شده توسط کاغذ ns2measure
[Cic06]، و به کاربران اجازه می دهد تا به طور موقت عباراتی مانند Probe را وارد کنند printf اظهارات
در داخل موجود ns-3 مدل ها. توجه داشته باشید که برای اینکه بتوانید از DoubleProbe در این مورد استفاده کنید
به عنوان مثال، 2 چیز لازم بود:
1. فایل هدر ماژول آمار در فایل مثال .cc گنجانده شده است
2. مثال به ماژول آمار در فایل wscript آن وابسته است.
کارهای مشابهی باید انجام شود تا پروب های دیگر در جاهای دیگر اضافه شود ns-3
پایه کد
مقادیر DoubleProbe را نیز می توان با استفاده از تابع DoubleProbe::SetValue() تنظیم کرد.
در حالی که مقادیر DoubleProbe را می توان با استفاده از تابع بدست آورد
DoubleProbe::GetValue().
DoubleProbe مقادیر دو برابری را در منبع ردیابی "Output" خود صادر می کند. یک شی پایین دست
می تواند یک ردیابی سینک (NotifyViaProbe) را به صورت زیر به آن قلاب کند:
متصل = probe1->TraceConnect ("خروجی"، 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) کلاس Probe موجود را در دو کپی کنید
فایل های جدید با نام های مطابق با Probe جدید شما.
· انواع، آرگومان ها و متغیرهای موجود در فایل های کپی شده را با موارد مناسب جایگزین کنید
برای پروب خود تایپ کنید
· اصلاحات لازم را انجام دهید تا کد کامپایل شود و آنطور که می خواهید رفتار کند
مانند.
مثال ها
در اینجا دو مثال به تفصیل مورد بحث قرار خواهد گرفت:
· نمونه دو پروب
· نمونه طرح بسته IPv4
دوبار کاوشگر مثال
مثال کاوشگر دوگانه قبلاً مورد بحث قرار گرفته است. برنامه نمونه را می توان یافت
in src/stats/examples/double-probe-example.cc. برای خلاصه کردن آنچه در این برنامه رخ می دهد،
یک قطره چکان وجود دارد که شمارنده ای را صادر می کند که طبق فرآیند پواسون افزایش می یابد.
به طور خاص، دو روش برای انتشار داده نشان داده شده است:
1. از طریق یک متغیر ردیابی شده که به یک Probe متصل است:
TracedValue m_counter; // معمولاً این نوع عدد صحیح است
2. از طریق یک شمارنده که مقدار آن به یک Probe دوم که با نام آن در ارجاع داده می شود، ارسال می شود
سیستم پیکربندی:
از درجه اعتبار ساقط
Emitter::Count (باطل)
{
NS_LOG_FUNCTION (این)؛
NS_LOG_DEBUG ("شمارش در " << شبیه ساز::اکنون ().GetSeconds ());
m_counter += 1.0;
DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe"، m_counter);
Simulator::Schedule (Seconds (m_var->GetValue ())، &Emitter::Count, this);
}
بیایید با دقت بیشتری به Probe نگاه کنیم. پروب ها می توانند مقادیر خود را به صورت چندگانه دریافت کنند
راه ها:
1. توسط Probe که مستقیماً به منبع ردیابی دسترسی پیدا می کند و یک سینک ردیابی را به آن متصل می کند
2. توسط Probe دسترسی به منبع ردیابی از طریق فضای نام پیکربندی و اتصال a
ردیابی به آن
3. توسط کد فراخوانی که صریحاً Probe را فراخوانی می کند SetValue() روش
4. توسط کد فراخوان به صراحت تماس می گیرد SetValueByPath
("/path/through/Config/namespace"، ...)
انتظار می رود دو تکنیک اول رایج ترین باشند. همچنین در مثال،
قلاب کردن یک تابع برگشت به تماس معمولی نشان داده شده است، همانطور که معمولا در انجام می شود ns-3. این
تابع callback با یک شی Probe مرتبط نیست. در زیر این مورد را 0) می نامیم.
// این تابعی برای آزمایش اتصال یک تابع خام به منبع ردیابی است
از درجه اعتبار ساقط
NotifyViaTraceSource (std:: زمینه رشته، double oldVal، double newVal)
{
NS_LOG_DEBUG ("context: " << context << " قدیمی " << oldVal << " new " << newVal);
}
ابتدا، امیتر باید راه اندازی شود:
Ptr Emitter = CreateObject ()
نام ها::افزودن ("/Names/Emitter", emitter);
// شی Emitter با گره ns-3 مرتبط نیست، بنابراین
// به طور خودکار شروع نمی شود، بنابراین باید خودمان این کار را انجام دهیم
شبیه ساز::زمان بندی (ثانیه (0.0)، و فرستنده::شروع، امیتر)؛
در مثال زیر، DoubleProbes های مختلف با امیتر تعامل دارند.
مورد 0):
// در زیر عملکرد معمولی بدون پروب نشان داده شده است
// (یک تابع سینک را به یک منبع ردیابی متصل کنید)
//
متصل = emitter->TraceConnect ("Counter"، "Sample context"، MakeCallback (&NotifyViaTraceSource));
NS_ASSERT_MSG (متصل، "منبع ردیابی متصل نیست")؛
مورد 1):
//
// Probe1 مستقیماً به شی منبع ردیابی Emitter متصل می شود
//
// probe1 به منبع ردیابی Emitter متصل می شود
Ptr probe1 = CreateObject ()
// نام کاوشگر می تواند به عنوان زمینه آن در ردیابی باشد
probe1->SetName ("ObjectProbe");
// پروب را به شمارنده امیتر وصل کنید
connect = probe1->ConnectByObject ("Counter"، Emitter);
NS_ASSERT_MSG (متصل، "منبع ردیابی به probe1 متصل نیست")؛
مورد 2):
//
// Probe2 به شی منبع ردیابی Emitter متصل می شود
// دسترسی به آن با نام مسیر در پایگاه داده پیکربندی
//
// یک پروب مشابه دیگر ایجاد کنید. این از طریق یک مسیر Config متصل می شود
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 نیست");
پاسخ تماس زیر در این مثال برای اهداف توضیحی به Probe متصل شده است.
به طور معمول، کاوشگر به یک شی جمع کننده متصل می شود.
// این تابعی برای آزمایش اتصال آن به خروجی پروب است
از درجه اعتبار ساقط
NotifyViaProbe (std:: زمینه رشته، double oldVal، double newVal)
{
NS_LOG_DEBUG ("context: " << context << " قدیمی " << oldVal << " new " << newVal);
}
IPv4 بسته طرح مثال
نمونه طرح بسته IPv4 بر اساس مثال fifth.cc از ns-3 آموزش. آی تی
را می توان در یافت src/stats/examples/ipv4-packet-plot-example.cc.
گره 0 گره 1
+----------------+ +----------------+
| ns-3 TCP | | ns-3 TCP |
+----------------+ +----------------+
| 10.1.1.1 | | 10.1.1.2 |
+----------------+ +----------------+
| نقطه به نقطه | | نقطه به نقطه |
+----------------+ +----------------+
| |
+----------------------+
ما فقط به Probe نگاه می کنیم، زیرا نشان می دهد که Probes ممکن است مقادیر را نیز از بسته بندی باز کند
ساختارها (در این مورد، بسته ها) و آن مقادیر را به عنوان خروجی منبع ردیابی گزارش می دهند
نه صرفاً از طریق همان نوع داده عبور کنید.
جنبه های دیگری از این مثال وجود دارد که در ادامه در مستندات توضیح داده خواهد شد.
دو نوع داده ای که صادر می شود خود بسته است (تولید) و تعدادی از
تعداد بایت های بسته (خروجی بایت).
TypeId
Ipv4PacketProbe::GetTypeId ()
{
static 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 <<);
اگر (Enabled ())
{
m_packet = بسته;
m_ipv4 = ipv4;
m_interface = رابط;
m_output (بسته، ipv4، رابط)؛
uint32_t packetSizeNew = packet->GetSize ();
m_outputBytes (m_packetSizeOld، packetSizeNew)؛
m_packetSizeOld = packetSizeNew;
}
}
منابع
[Cic06]
Claudio Cicconetti، Enzo Mingozzi، Giovanni Stea، "یک چارچوب یکپارچه برای
فعال کردن جمعآوری مؤثر دادهها و تجزیه و تحلیل آماری با ns2، Workshop on
ns-2 (WNS2)، پیزا، ایتالیا، اکتبر 2006.
جمع کننده ها
این بخش یک مکان نگهدار برای جزئیات عملکردهای ارائه شده توسط مجموعه است
کلاس به یک ns-3 شبیه سازی، و مثال هایی در مورد نحوه کدنویسی آنها در یک برنامه ارائه می دهد.
توجه داشته باشید: از ns-3.18، کلکتورها هنوز در حال توسعه هستند و هنوز به عنوان بخشی ارائه نشده اند
از چارچوب
جمع کننده ها
این بخش به جزئیات عملکردهای ارائه شده توسط کلاس Aggregator به یک اشاره می کند ns-3
شبیه سازی. این بخش برای کاربران علاقه مند به توسعه شبیه سازی با
ns-3 ابزارها و با استفاده از Data Collection Framework که کلاس Aggregator a است
بخش، برای تولید خروجی داده با نتایج شبیه سازی خود.
جمع کننده بررسی اجمالی
یک شی Aggregator قرار است به یک یا چند منبع ردیابی متصل شود تا بتواند
دریافت ورودی تجمیع کننده ها نقطه پایانی داده های جمع آوری شده توسط شبکه هستند
پروب ها و جمع کننده ها در طول شبیه سازی. این وظیفه جمع کننده است که اینها را بگیرد
مقادیر و تبدیل آنها به فرمت خروجی نهایی خود مانند فایل های متنی ساده،
فایل های صفحه گسترده، نمودارها یا پایگاه های داده.
به طور معمول، یک جمع کننده به یک یا چند کلکتور متصل است. به این ترتیب هر زمان که
منابع ردیابی کلکتورها مقادیر جدیدی را صادر می کنند، Aggregator می تواند ارزش را پردازش کند
که می توان از آن در فرمت خروجی نهایی استفاده کرد که در آن مقادیر داده ها بعد از آن قرار می گیرند
شبیه سازی.
در مورد Aggregators به نکات زیر توجه کنید:
· ممکن است در طول شبیه سازی با فراخوانی، جمع آوری کننده ها به صورت پویا روشن و خاموش شوند
فعال کردن() و غیر فعال کردن(). به عنوان مثال، جمع آوری داده ها ممکن است در طول مدت خاموش شود
مرحله گرم کردن شبیه سازی، به این معنی که این مقادیر در نهایی گنجانده نمی شوند
رسانه خروجی
· تجمیع کننده ها داده ها را از گردآورنده ها از طریق callback دریافت می کنند. هنگامی که یک کلکتور مرتبط است
برای جمعآوری، تماسی با TraceConnect برقرار میشود تا ردیابی Aggregator را ایجاد کند.
روش سینک به عنوان یک تماس.
تا به امروز، دو Aggregator پیاده سازی شده است:
· GnuplotAggregator
· FileAggregator
GnuplotAggregator
GnuplotAggregator فایل های خروجی مورد استفاده برای ساخت gnuplot را تولید می کند.
GnuplotAggregator 3 فایل مختلف را در پایان شبیه سازی ایجاد می کند:
· فایل داده gnuplot با فاصله از هم جدا شده است
· یک فایل کنترل gnuplot
· یک پوسته اسکریپت برای تولید gnuplot
ایجاد
یک شی از نوع GnuplotAggregator در اینجا ایجاد می شود تا نشان دهد چه کاری باید انجام شود.
یک GnuplotAggregator در حافظه پویا با استفاده از کلاس اشاره گر هوشمند اعلام می کند
(Ptr ). برای ایجاد یک GnuplotAggregator در حافظه پویا با اشاره گرهای هوشمند، کافی است
نیاز به تماس دارد ns-3 روش CreateObject(). کد زیر از
src/stats/examples/gnuplot-aggregator-example.cc نحوه انجام این کار را نشان می دهد:
string fileNameWithoutExtension = "gnuplot-aggregator";
// یک جمع کننده ایجاد کنید.
Ptr جمع کننده =
CreateObject (fileNameWithoutExtension)؛
اولین آرگومان سازنده، fileNameWithoutExtension، نام آن است
فایل های مرتبط gnuplot برای نوشتن بدون پسوند. این GnuplotAggregator یک را ایجاد می کند
فایل داده gnuplot جدا شده با فاصله با نام "gnuplot-aggregator.dat"، یک فایل کنترل gnuplot
با نام "gnuplot-aggregator.plt" و یک اسکریپت پوسته برای تولید gnuplot با نام +
"gnuplot-aggregator.sh".
gnuplot ایجاد شده می تواند کلید خود را در 4 مکان مختلف داشته باشد:
· بدون کلید
· کلید داخل طرح (پیش فرض)
· کلید بالای طرح
· کلید زیر طرح
مقادیر enum مکان کلید gnuplot زیر برای تعیین موقعیت کلید مجاز هستند:
enum مکان کلید {
NO_KEY،
KEY_INSIDE،
KEY_ABOVE،
KEY_BELOW
};
اگر می خواستید به جای موقعیت پیش فرض داخل، کلید زیر را داشته باشید، پس
می توانید موارد زیر را انجام دهید
aggregator->SetKeyLocation(GnuplotAggregator::KEY_BELOW);
مثال ها
یک مثال در اینجا به تفصیل مورد بحث قرار خواهد گرفت:
· نمونه Gnuplot Aggregator
گنوپلو جمع کننده مثال
نمونه ای که GnuplotAggregator را تمرین می کند را می توان در آن یافت
src/stats/examples/gnuplot-aggregator-example.cc.
gnuplot 2 بعدی زیر با استفاده از مثال ایجاد شد.
[تصویر] Gnuplot دو بعدی ایجاد شده توسط gnuplot-aggregator-example.cc مثال..UNINDENT
این کد از مثال نحوه ساخت GnuplotAggregator را همانطور که در مورد آن بحث شد نشان می دهد
در بالا.
void Create2dPlot ()
{
استفاده از namespace std؛
string fileNameWithoutExtension = "gnuplot-aggregator";
string plotTitle = "نقشه جمع کننده Gnuplot";
string plotXAxisHeading = "زمان (ثانیه)";
string plotYAxisHeading = "مقدارهای دوگانه";
string plotDatasetLabel = "مقادیر داده";
string databaseContext = "مجموعه داده/مطابق/رشته";
// یک جمع کننده ایجاد کنید.
Ptr جمع کننده =
CreateObject (fileNameWithoutExtension)؛
ویژگی های مختلف GnuplotAggregator از جمله مجموعه داده 2 بعدی که خواهد بود تنظیم شده است
ترسیم شده است.
// ویژگی های جمع کننده را تنظیم کنید.
aggregator->SetTerminal ("png");
aggregator->SetTitle (plotTitle);
aggregator->SetLegend (plotXAxisHeading، plotYAxisHeading)؛
// یک مجموعه داده به جمع کننده اضافه کنید.
aggregator->Add2dDataset (datasetContext، plotDatasetLabel);
// aggregator باید روشن باشد
aggregator->Enable ();
در مرحله بعد، مقادیر 2-D محاسبه می شوند و هر یک به صورت جداگانه در آن نوشته می شود
GnuplotAggregator با استفاده از Write2d() تابع.
زمان دو برابر؛
ارزش دو برابر؛
// مجموعه داده دو بعدی را ایجاد کنید.
برای (زمان = -5.0؛ زمان <= +5.0؛ زمان += 1.0)
{
// منحنی دو بعدی را محاسبه کنید
//
// 2
// ارزش = زمان .
//
ارزش = زمان * زمان;
// این نقطه را به طرح اضافه کنید.
aggregator->Write2d (datasetContext، زمان، مقدار).
}
// غیرفعال کردن گزارش گیری داده ها برای جمع کننده.
aggregator->Disable ();
}
FileAggregator
FileAggregator مقادیر دریافتی خود را به یک فایل ارسال می کند.
FileAggregator می تواند 4 نوع مختلف فایل ایجاد کند:
· فرمت شده
· فاصله جدا شده (پیش فرض)
· جدا شده با ویرگول
· برگه جدا شده است
فایلهای فرمتشده از رشتههای قالب C و تابع sprintf() برای چاپ آنها استفاده میکنند
مقادیر موجود در فایل در حال نوشتن
ایجاد
یک شی از نوع FileAggregator در اینجا ایجاد می شود تا نشان دهد چه کاری باید انجام شود.
یک FileAggregator در حافظه پویا با استفاده از کلاس اشاره گر هوشمند (Ptr ).
برای ایجاد یک FileAggregator در حافظه پویا با اشاره گرهای هوشمند، فقط باید تماس بگیرید
la ns-3 روش CreateObject. کد زیر از
src/stats/نمونه ها/پرونده-همگرایی-مثال.CC نحوه انجام این کار را نشان می دهد:
string fileName = "file-aggregator-formatted-values.txt";
// یک جمع کننده ایجاد کنید که دارای مقادیر فرمت شده باشد.
Ptr جمع کننده =
CreateObject (نام فایل، FileAggregator::FORMATTED);
اولین آرگومان سازنده، نام فایل، نام فایلی است که باید بنویسد. را
آرگومان دوم، fileType، نوع فایلی برای نوشتن است. این FileAggregator یک را ایجاد می کند
فایلی با نام "file-aggregator-formatted-values.txt" و مقادیر آن همانطور که توسط
fileType، یعنی فرمت شده در این مورد.
مقادیر enum نوع فایل زیر مجاز است:
enum نوع فایل {
فرمت شده،
SPACE_SEPARATED،
جدا شده با ویرگول،
TAB_SEPARATED
};
مثال ها
یک مثال در اینجا به تفصیل مورد بحث قرار خواهد گرفت:
· مثال جمع آوری فایل
پرونده جمع کننده مثال
نمونه ای که FileAggregator را تمرین می کند را می توان در آن یافت
src/stats/نمونه ها/پرونده-همگرایی-مثال.CC.
فایل متنی زیر با 2 ستون از مقادیر جدا شده با کاما با استفاده از
مثال.
-5,25
-4,16
-3,9
-2,4
-1,1
0,0
1,1
2,4
3,9
4,16
5,25
این کد از مثال نحوه ساخت FileAggregator را همانطور که در مورد آن بحث شد نشان می دهد
در بالا.
void CreateCommaSeparatedFile ()
{
استفاده از namespace std؛
string fileName = "file-aggregator-comma-separated.txt";
string databaseContext = "مجموعه داده/مطابق/رشته";
// یک جمع کننده ایجاد کنید.
Ptr جمع کننده =
CreateObject (نام فایل، FileAggregator::COMMA_SEPARATED);
ویژگی های FileAggregator تنظیم شده است.
// aggregator باید روشن باشد
aggregator->Enable ();
در مرحله بعد، مقادیر 2-D محاسبه می شوند و هر یک به صورت جداگانه در آن نوشته می شود
FileAggregator با استفاده از Write2d() تابع.
زمان دو برابر؛
ارزش دو برابر؛
// مجموعه داده دو بعدی را ایجاد کنید.
برای (زمان = -5.0؛ زمان <= +5.0؛ زمان += 1.0)
{
// منحنی دو بعدی را محاسبه کنید
//
// 2
// ارزش = زمان .
//
ارزش = زمان * زمان;
// این نقطه را به طرح اضافه کنید.
aggregator->Write2d (datasetContext، زمان، مقدار).
}
// غیرفعال کردن گزارش گیری داده ها برای جمع کننده.
aggregator->Disable ();
}
فایل متنی زیر با 2 ستون مقادیر فرمت شده نیز با استفاده از
مثال.
زمان = -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 را همانطور که در مورد آن بحث شد نشان می دهد
در بالا.
void CreateFormattedFile ()
{
استفاده از namespace std؛
string fileName = "file-aggregator-formatted-values.txt";
string databaseContext = "مجموعه داده/مطابق/رشته";
// یک جمع کننده ایجاد کنید که دارای مقادیر فرمت شده باشد.
Ptr جمع کننده =
CreateObject (نام فایل، FileAggregator::FORMATTED);
ویژگی های FileAggregator، از جمله رشته فرمت C-style برای استفاده، تنظیم شده است.
// قالب را برای مقادیر تنظیم کنید.
aggregator->Set2dFormat ("Time = %.3e\tValue = %.0f");
// aggregator باید روشن باشد
aggregator->Enable ();
در مرحله بعد، مقادیر 2-D محاسبه می شوند و هر یک به صورت جداگانه در آن نوشته می شود
FileAggregator با استفاده از Write2d() تابع.
زمان دو برابر؛
ارزش دو برابر؛
// مجموعه داده دو بعدی را ایجاد کنید.
برای (زمان = -5.0؛ زمان <= +5.0؛ زمان += 1.0)
{
// منحنی دو بعدی را محاسبه کنید
//
// 2
// ارزش = زمان .
//
ارزش = زمان * زمان;
// این نقطه را به طرح اضافه کنید.
aggregator->Write2d (datasetContext، زمان، مقدار).
}
// غیرفعال کردن گزارش گیری داده ها برای جمع کننده.
aggregator->Disable ();
}
آداپتورها
این بخش به جزئیات عملکردهای ارائه شده توسط کلاس Adapter به an ns-3
شبیه سازی. این بخش برای کاربران علاقه مند به توسعه شبیه سازی با
ns-3 ابزارها و با استفاده از Data Collection Framework که کلاس Adapter بخشی از آن است،
برای تولید خروجی داده با نتایج شبیه سازی خود.
توجه: عبارت "آداپتور" ممکن است "آداپتور" نیز نوشته شود. ما املای تراز را انتخاب کردیم
با استاندارد C++
آداپتور بررسی اجمالی
یک آداپتور برای ایجاد ارتباط بین انواع مختلف اشیاء DCF استفاده می شود.
تا به امروز، یک آداپتور پیاده سازی شده است:
· TimeSeriesAdaptor
زمان سلسله آداپتور
TimeSeriesAdaptor به Probes اجازه می دهد تا بدون نیاز به هیچ کدام مستقیماً به Aggregator متصل شوند
کلکسیونر در بین
هر دو کمک کننده DCF پیاده سازی شده از TimeSeriesAdaptors برای بررسی استفاده می کنند.
مقادیر انواع مختلف و خروجی زمان فعلی به اضافه مقدار با هر دو تبدیل شده است
دو برابر شدن
نقش کلاس TimeSeriesAdaptor نقش یک آداپتور است که ارزش خام را دریافت می کند.
دادههای کاوشگر از انواع مختلف و خروجی دو مقدار دو برابری را ارائه میدهد. اولی الف است
مهر زمانی، که ممکن است روی وضوح های مختلف (مثلاً ثانیه، میلی ثانیه و غیره) تنظیم شود
آینده اما در حال حاضر به ثانیه هاردکد شده است. دوم تبدیل الف است
مقدار غیر دو برابر به یک مقدار دو برابر (احتمالا با از دست دادن دقت).
محدوده/محدودیت ها
این بخش دامنه و محدودیت های چارچوب جمع آوری داده ها را مورد بحث قرار می دهد.
در حال حاضر، فقط این پروب ها در DCF پیاده سازی شده اند:
· BooleanProbe
· DoubleProbe
· Uinteger8Probe
· Uinteger16Probe
· Uinteger32Probe
· TimeProbe
· PacketProbe
· ApplicationPacketProbe
· Ipv4PacketProbe
در حال حاضر، هیچ مجموعهای در DCF موجود نیست، اگرچه BasicStatsCollector زیر است.
توسعه است.
در حال حاضر، فقط این Aggregatorها در DCF پیاده سازی شده اند:
· GnuplotAggregator
· FileAggregator
در حال حاضر فقط این آداپتور در DCF پیاده سازی شده است:
آداپتور سری زمانی
آینده مهاجرت کاری
این بخش در مورد کارهای آتی که باید روی چارچوب جمع آوری داده ها انجام شود بحث می کند.
در اینجا مواردی وجود دارد که هنوز باید انجام شوند:
· منابع ردیابی بیشتری را به آن متصل کنید ns-3 کد برای دریافت مقادیر بیشتر از شبیه ساز.
· انواع بیشتری از پروب ها را نسبت به آنچه در حال حاضر وجود دارد، اجرا کنید.
· اجرای بیش از تنها جمع کننده 2 بعدی فعلی، BasicStatsCollector.
· اجرای بیشتر Aggregators.
· بیش از آداپتورها را پیاده سازی کنید.
آماری چارچوب
این فصل کار بر روی گردآوری داده های شبیه سازی و چارچوب آماری را تشریح می کند
ns-3.
کد منبع برای چارچوب آماری در فهرست موجود است src/stats.
اهداف
اهداف اولیه این تلاش به شرح زیر است:
· ارائه قابلیت ثبت، محاسبه، و ارائه داده ها و آمار برای تجزیه و تحلیل
شبیه سازی شبکه
· افزایش عملکرد شبیه سازی با کاهش نیاز به ایجاد ردیابی لاگ های گسترده
به منظور جمع آوری داده ها
· فعال کردن کنترل شبیه سازی از طریق آمار آنلاین، به عنوان مثال پایان دادن به شبیه سازی یا
تکرار آزمایشات
اهداف فرعی مشتق شده و سایر ویژگی های هدف شامل موارد زیر است:
· ادغام با سیستم ردیابی ns-3 موجود به عنوان چارچوب ابزار دقیق
از موتور شبیه سازی داخلی، به عنوان مثال پشته های شبکه، دستگاه های شبکه و کانال ها.
· فعال کردن کاربران برای استفاده از چارچوب آمار بدون نیاز به استفاده از ردیابی
سیستم.
· کمک به کاربران در ایجاد، تجمیع، و تجزیه و تحلیل داده ها در آزمایش های متعدد.
· پشتیبانی از ابزار دقیق ایجاد شده توسط کاربر، به عنوان مثال رویدادهای خاص برنامه و
معیارهای.
· حافظه کم و سربار CPU زمانی که بسته در حال استفاده نیست.
· تا حد امکان از ابزارهای تحلیل و خروجی موجود استفاده کنید. چارچوب ممکن است
ارائه برخی از آمارهای اولیه، اما تمرکز بر جمع آوری داده ها و ساخت آن است
برای دستکاری در ابزارهای تاسیس شده قابل دسترسی است.
· پشتیبانی نهایی برای توزیع تکرارهای مستقل مهم است اما شامل نمی شود
در دور اول ویژگی ها
بررسی اجمالی
چارچوب آمار شامل ویژگی های زیر است:
· چارچوب اصلی و دو گردآورنده داده اصلی: شمارنده، و حداقل/حداکثر/میانگین/کل
نظاره گر.
· برنامه های افزودنی از کسانی که به راحتی با زمان ها و بسته ها کار می کنند.
· خروجی متن ساده فرمت شده برای OMNet++.
· خروجی پایگاه داده با استفاده از از SQLite، یک موتور SQL مستقل، سبک وزن و با کارایی بالا.
· فراداده اجباری و باز برای توصیف و کار با اجراها.
· یک مثال بر اساس آزمایش فرضی بررسی خواص NS-3
عملکرد پیش فرض وای فای موقت این شامل موارد زیر است:
· یک شبکه WiFi ad hoc دو گره با فاصله پارامتری گره ها ایجاد می کند
جدا از هم.
· برنامه های منبع ترافیک UDP و سینک با رفتار کمی متفاوت و
قلاب های اندازه گیری نسبت به کلاس های سهام.
جمع آوری داده ها از هسته NS-3 از طریق سیگنال های ردیابی موجود، به ویژه داده ها در
فریم های ارسال و دریافت شده توسط اشیاء WiFi MAC.
· ابزار دقیق برنامه های کاربردی سفارشی با اتصال سیگنال های ردیابی جدید به آمار
چارچوب، و همچنین از طریق به روز رسانی مستقیم. اطلاعات در مورد کل بسته ها ثبت می شود
ارسال و دریافت، بایت های ارسال شده، و تاخیر سرتاسر.
· نمونه ای از استفاده از برچسب های بسته برای ردیابی تاخیر انتها به انتها.
· یک اسکریپت کنترلی ساده که تعدادی آزمایش از آزمایش را در موارد مختلف اجرا می کند
فاصله داده و پایگاه داده حاصل را برای تولید یک نمودار با استفاده از GNUPlot جستجو می کند.
انجام دادن
موارد با اولویت بالا عبارتند از:
· گنجاندن کد آمار آنلاین، به عنوان مثال برای فواصل اطمینان کارآمد حافظه.
· مقررات در جمع آوری داده ها برای پایان دادن به اجراها، یعنی زمانی که یک آستانه یا
اطمینان برآورده شده است.
جمع آوری داده ها برای ثبت نمونه ها در طول زمان، و خروجی به فرمت های مختلف.
· نوشتن چسب رویداد چرخه ای ساده را نشان دهید تا به طور منظم مقداری ارزش را بررسی کنید.
هر یک از این موارد باید به سادگی در چارچوب فعلی گنجانده شود.
روش
این چارچوب بر اساس اصول اصلی زیر است:
· یک آزمایش آزمایشی توسط یک نمونه از یک برنامه شبیه سازی انجام می شود، چه در
موازی یا سریالی
· یک اسکریپت کنترل نمونه هایی از شبیه سازی را اجرا می کند و در صورت لزوم پارامترها را تغییر می دهد.
· داده ها برای رسم و تجزیه و تحلیل با استفاده از اسکریپت های خارجی جمع آوری و ذخیره می شوند
ابزارهای موجود
· اقدامات در هسته ns-3 با اتصال چارچوب stat به موجود انجام می شود
سیگنال های ردیابی
· سیگنال های ردیابی یا دستکاری مستقیم چارچوب ممکن است برای ابزارهای سفارشی استفاده شود
کد شبیه سازی
آن مولفه های اساسی چارچوب و تعاملات آنها در تصویر نشان داده شده است
شکل زیر [تصویر]
مثال
این بخش مراحل ساخت یک آزمایش را در چارچوب و
تولید داده ها برای تجزیه و تحلیل (نمودار) از آن، نشان دادن ساختار و API همراه
راه
سوال
عملکرد (شبیهسازی شده) دستگاههای شبکه وای فای ns-3 (با استفاده از پیشفرض)
تنظیمات)؟ گره های بی سیم در یک شبیه سازی چقدر می توانند از هم دور باشند قبل از اینکه نتوانند
با اطمینان ارتباط برقرار کنیم؟"
· فرضیه: بر اساس دانش عملکرد واقعی، گره ها باید ارتباط برقرار کنند
به خوبی با حداقل 100 متر فاصله از هم. ارتباط بیش از 200 متر نباید باشد
امکان پذیر است.
اگرچه در زمینههای شبیهسازی سوال خیلی رایجی نیست، اما این یک ویژگی مهم است
که توسعه دهندگان شبیه سازی باید درک اساسی از آن داشته باشند. آن نیز رایج است
مطالعه انجام شده بر روی سخت افزار زنده
شبیه سازی برنامه
اولین کاری که باید در اجرای این آزمایش انجام داد، توسعه شبیه سازی است
برنامه کد این مثال را می توان در اینجا یافت examples/stats/wifi-example-sim.cc.
مراحل اصلی زیر را انجام می دهد.
· اعلام پارامترها و تجزیه خط فرمان با استفاده از ns3:: خط فرمان.
فاصله دو برابر = 50.0;
قالب رشته ("OMNet++")؛
آزمایش رشته ای ("تست فای-فاصله")؛
استراتژی رشته ای ("wifi-default")؛
رشته runID;
CommandLine cmd;
cmd.AddValue("فاصله"، "فاصله از یکدیگر برای قرار دادن گره ها (بر حسب متر)."، فاصله);
cmd.AddValue("format", "Format to use for data output.", format);
cmd.AddValue("experiment", "Identifier for experience.", experience);
cmd.AddValue("استراتژی"، "شناسه برای استراتژی."، استراتژی);
cmd.AddValue("run", "Identifier for run.", 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(nodes);
InternetStackHelper اینترنت؛
internet.Install(nodes);
Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase("192.168.0.0"، "255.255.255.0");
ipAddrs.Assign(nodeDevices);
· تعیین موقعیت گره ها با استفاده از ns3::MobilityHelper. به طور پیش فرض گره ها ساکن هستند
تحرک داشته باشد و حرکت نکند، اما باید در فاصله مشخصی از هم قرار گیرد. وجود دارد
چندین راه برای انجام این کار؛ در اینجا با استفاده از آن انجام می شود ns3::ListPositionAllocator، که ترسیم می کند
موقعیت ها از یک لیست مشخص
MobilityHelper mobility;
Ptr positionAlloc =
CreateObject ()
positionAlloc->Add(Vector(0.0, 0.0, 0.0));
positionAlloc->Add(Vector(0.0، فاصله، 0.0));
mobility.SetPositionAllocator(positionAlloc);
mobility.Install(nodes);
· نصب مولد ترافیک و سینک ترافیک. سهام اپلیکیشنها می تواند باشد
استفاده می شود، اما مثال شامل اشیاء سفارشی در است src/test/test02-apps.(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))؛
// پیکربندی:: تنظیم ("/NodeList/*/ApplicationList/*/$Sender/Destination"،
// Ipv4AddressValue("192.168.0.2"));
· پیکربندی داده ها و آماری که باید جمع آوری شود. پارادایم اساسی این است که الف
ns3:: DataCollector شی ایجاد شده است تا اطلاعات مربوط به این اجرا خاص را نگه دارد
که ناظران و ماشین حساب ها برای تولید واقعی داده ها متصل شده اند. مهم،
اطلاعات اجرا شامل برچسبهایی برای «آزمایش»، «استراتژی»، «ورودی» و
''اجرا کن''. اینها برای شناسایی و گروهبندی آسان دادهها از چندین آزمایش استفاده میشوند.
· آزمایش مطالعه ای است که این کارآزمایی عضوی از آن است. اینجا روی وای فای است
عملکرد و فاصله
· استراتژی کد یا پارامترهای مورد بررسی در این آزمایش است. در این مثال
حل شده است، اما یک برنامه افزودنی واضح، بررسی بیت های مختلف WiFi است
نرخ هایی که هر کدام استراتژی متفاوتی خواهند داشت.
· ورودی مشکل خاصی است که به این آزمایش داده شده است. در اینجا آن را به سادگی است
فاصله بین دو گره
· runID یک شناسه منحصر به فرد برای این آزمایش است که اطلاعات آن با آن برچسب گذاری می شود
برای شناسایی در تحلیل های بعدی اگر هیچ شناسه اجرا داده نشده باشد، برنامه نمونه می سازد
یک شناسه اجرا (ضعیف) با استفاده از زمان فعلی.
آن چهار قطعه ابرداده مورد نیاز است، اما ممکن است بیشتر مورد نظر باشد. ممکن است اضافه شوند
برای ثبت با استفاده از ns3::DataCollector::AddMetadata() روش.
DataCollector داده ها;
data.DescribeRun (آزمایش، استراتژی، ورودی، شناسه اجرا)؛
data.AddMetadata("نویسنده"، "tjkopena");
مشاهده و محاسبه واقعی توسط ns3::DataCalculator اشیاء، که
چندین نوع مختلف وجود دارد اینها توسط برنامه شبیه سازی، متصل به ایجاد شده اند
گزارش یا کد نمونه گیری، و سپس با ثبت نام ns3:: DataCollector بنابراین آنها خواهند کرد
بعداً برای خروجی آنها پرس و جو شود. یک مکانیسم مشاهده آسان، استفاده از موجود است
ردیابی منابع، به عنوان مثال برای ابزار ابزار در هسته ns-3 بدون تغییر آنها
کد در اینجا یک شمارنده مستقیماً به یک سیگنال ردیابی در لایه WiFi MAC متصل میشود
گره هدف
Ptr totalRx = CreateObject ()
totalRx->SetKey("wifi-rx-frames");
Config::Connect("/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->Update();
این برنامه شامل چندین مثال دیگر نیز می باشد که از هر دو حالت اولیه استفاده می کند
ماشین حساب هایی مانند ns3::CounterCalculator و آنهایی که برای مشاهده بسته ها و
بار. که در src/test/test02-apps.(cc|h) همچنین یک تگ سفارشی ساده ایجاد می کند که از آن استفاده می کند
برای ردیابی تاخیر سرتاسر بسته های تولید شده، گزارش نتایج به a
ns3::TimeMinMaxAvgTotalCalculator ماشین حساب داده
· اجرای شبیه سازی، که پس از ساخته شدن بسیار ساده است.
شبیه ساز::Run();
· تولید یا OMNet++ or از SQLite خروجی، بسته به آرگومان های خط فرمان. به
این کار را انجام دهید ns3::DataOutputInterface شی ایجاد و پیکربندی می شود. نوع خاص
این فرمت خروجی را تعیین می کند. سپس به این شیء داده می شود
ns3:: DataCollector شیئی که برای تولید خروجی از آن بازجویی می کند.
Ptr خروجی
if (فرمت == "OMNet++") {
NS_LOG_INFO("ایجاد خروجی داده با فرمت OMNet++.");
خروجی = CreateObject ()
} دیگری {
# ifdef STAT_USE_DB
NS_LOG_INFO("ایجاد خروجی داده با فرمت SQLite.");
خروجی = CreateObject ()
# endif
}
output->Output(data);
· آزاد کردن هر حافظه ای که توسط شبیه سازی استفاده می شود. این باید در پایان اصلی بیاید
تابع برای مثال
شبیه ساز::Destroy();
ورود به سیستم
برای مشاهده جزئیات برنامه، برنامهها و چارچوب آماری مثال، مجموعه را تنظیم کنید
la NS_LOG متغیر مناسب موارد زیر خروجی فراوانی را از همه ارائه می دهد
سه.
$ export NS_LOG=WiFiDistanceExperiment:WiFiDistanceApps
توجه داشته باشید که این کار شبیه سازی را به طور فوق العاده ای کند می کند.
نمونه تولید
کامپایل و اجرای ساده برنامه آزمایشی ضمیمه خواهد شد OMNet++ خروجی فرمت شده مانند
زیر به data.sca.
run run-1212239121
آزمایش attr "تست فای-فاصله"
استراتژی attr "wifi-default"
ورودی attr "50"
توضیحات attr ""
attr "نویسنده" "tjkopena"
تعداد فریمهای wifi-tx اسکالر 30 است
تعداد فریمهای wifi-rx اسکالر 30 است
تعداد بستههای ارسالکننده-tx-اسکالار 30
گیرنده اسکالار-rx-بسته ها 30 عدد می شوند
اسکالار tx-pkt-size count 30
اسکالار tx-pkt-size مجموع 1920
اسکالار tx-pkt-size میانگین 64
اسکالار tx-pkt-اندازه حداکثر 64
اسکالار tx-pkt-size min 64
شمارش تاخیر اسکالر 30
کل تاخیر اسکالر 5884980ns
میانگین تاخیر اسکالر 196166 ثانیه
حداکثر تاخیر اسکالر 196166ns
تاخیر اسکالر حداقل 196166ns
کنترل خط
به منظور خودکار سازی جمع آوری داده ها در انواع ورودی ها (فاصله ها)، یک Bash ساده
اسکریپت برای اجرای یک سری شبیه سازی استفاده می شود. می توان آن را در یافت
examples/stats/wifi-example-db.sh. این اسکریپت قرار است از روی اجرا شود مثال/آمار/
دایرکتوری.
اسکریپت مجموعهای از فواصل را طی میکند و نتایج را در یک صفحه جمعآوری میکند از SQLite
پایگاه داده در هر فاصله پنج آزمایش انجام می شود تا تصویر بهتری از مورد انتظار ارائه شود
کارایی. کل آزمایش فقط چند ده ثانیه طول می کشد تا در سطح پایین اجرا شود
ماشین چون خروجی در طول شبیه سازی وجود ندارد و ترافیک کمی ایجاد می شود.
#!/ بن / شل
DISTANCES="25 50 75 100 125 145 147 150 152 155 157 160 162 165 167 170 172 175 177 180"
TRILS="1 2 3 4 5"
نمونه آزمایشی echo WiFi
اگر [ -e data.db ]
سپس
echo Kill data.db؟
ANS را بخوانید
if [ "$ANS" = "بله" -o "$ANS" = "y" ]
سپس
echo حذف پایگاه داده
rm data.db
fi
fi
برای آزمایش در $TRIALS
do
برای فاصله در $DISTANCES
do
پژواک آزمایشی $آزمایشی، فاصله $فاصله
./bin/test02 --format=db --distance=$distance --run=run-$distance-$trial
انجام شده
انجام شده
تحلیل و بررسی و نتیجه
هنگامی که تمام آزمایشات انجام شد، اسکریپت یک پرس و جو ساده SQL را روی آن اجرا می کند
پایگاه داده با استفاده از از SQLite برنامه خط فرمان پرس و جو میانگین تلفات بسته را محاسبه می کند
هر مجموعه آزمایشی مرتبط با هر فاصله. متفاوت را در نظر نمی گیرد
استراتژیها، اما اطلاعات در پایگاه داده برای ایجاد برخی پسوندهای ساده وجود دارد
و این کار را انجام دهید. سپس داده های جمع آوری شده برای ترسیم نمودار به GNUPlot ارسال می شود.
CMD="انتخاب exp.input,avg(100-((rx.value*100)/tx.value)) \
از Singletons rx، Singletons tx، Experiments exp \
جایی که rx.run = tx.run و \
rx.run = exp.run AND \
rx.name='receiver-rx-packets' AND \
tx.name='sender-tx-packets' \
گروه با exp.input \
ترتیب توسط abs (exp.input) ASC؛"
sqlite3 -noheader data.db "$CMD" > wifi-default.data
sed -i "s/|/ /" wifi-default.data
gnuplot wifi-example.gnuplot
اسکریپت GNUPlot موجود در examples/stats/wifi-example.gnuplot به سادگی خروجی را تعریف می کند
قالب و چند قالب بندی اولیه برای نمودار.
تنظیم پایانه پست اسکریپت پرتره بهبود یافته lw 2 "Helvetica" 14
اندازه مجموعه 1.0، 0.66
#------------------------------------------------ ------
"wifi-default.eps" را تنظیم کنید
عنوان #تنظیم "از دست دادن بسته در طول مسافت"
مجموعه xlabel "فاصله (متر) --- میانگین 5 آزمایش در هر نقطه"
مجموعه xrange [0:200]
تنظیم برچسب "% از دست دادن بسته"
تنظیم yrange [0:110]
طرح "wifi-default.data" با عنوان خطوط "WiFi Defaults"
پایان نتیجه
نمودار به دست آمده هیچ مدرکی دال بر عملکرد پیش فرض مدل WiFi ارائه نمی دهد
لزوما نامعقول است و حداقل به یک وفاداری نشانه ای اطمینان می دهد
واقعیت مهمتر از همه، این تحقیق ساده تا آخر عمر انجام شده است
با استفاده از چارچوب آماری موفقیت! [تصویر]
به موقع
ns-3 برای ادغام در محیط های تست و ماشین مجازی طراحی شده است. به
ادغام با پشته های شبکه واقعی و انتشار/مصرف بسته ها، یک زمان بندی زمان واقعی است
باید سعی کنید ساعت شبیه سازی را با ساعت سخت افزاری قفل کنید. ما در اینجا یک را توضیح می دهیم
جزء این: زمانبندی RealTime.
هدف زمانبندی بیدرنگ این است که باعث پیشرفت ساعت شبیه سازی شود
به طور همزمان با توجه به برخی از پایگاه های زمانی خارجی رخ می دهد. بدون حضور
یک پایه زمانی خارجی (ساعت دیواری)، زمان شبیهسازی فوراً از یک شبیهسازی شده پرش میکند
زمان به بعدی
رفتار
هنگام استفاده از زمانبندی غیر همدرنگ (پیشفرض در ns-3، شبیه ساز پیشرفت می کند
زمان شبیه سازی تا رویداد برنامه ریزی شده بعدی در طول اجرای رویداد، زمان شبیه سازی است
منجمد. با زمانبندی بیدرنگ، رفتار از منظر مشابه است
مدلهای شبیهسازی (یعنی زمان شبیهسازی در طول اجرای رویداد ثابت میشود)، اما بین
وقایع، شبیه ساز تلاش خواهد کرد تا ساعت شبیه سازی را با ماشین در یک راستا نگه دارد
ساعت.
هنگامی که اجرای یک رویداد به پایان می رسد و زمانبندی به رویداد بعدی می رود
زمانبندی زمان اجرای رویداد بعدی را با ساعت ماشین مقایسه می کند. اگر بعدی
رویداد برای زمان آینده برنامه ریزی شده است، شبیه ساز می خوابد تا به آن زمان واقعی برسد
و سپس رویداد بعدی را اجرا می کند.
ممکن است به دلیل پردازش ذاتی در اجرای رویدادهای شبیه سازی،
که شبیه ساز نمی تواند با زمان واقعی همراه شود. در چنین شرایطی به عهده کاربر است
پیکربندی چه باید کرد دو تا هستند ns-3 ویژگی های حاکم بر رفتار در
اول است ns3::RealTimeSimulatorImpl::SynchronizationMode. دو ورودی برای
این صفت هستند بهترین تلاش (پیش فرض) یا HardLimit. در حالت "BestEffort"،
شبیه ساز فقط سعی می کند با اجرای رویدادها به زمان واقعی برسد تا زمانی که به a برسد
نقطه ای که رویداد بعدی در آینده (بیدرنگ) است، در غیر این صورت شبیه سازی به پایان می رسد. که در
پس حالت BestEffort این امکان را دارد که شبیه سازی زمان بیشتری را نسبت به حالت مصرف کند
زمان ساعت دیواری گزینه دیگر "HardLimit" باعث می شود که شبیه سازی متوقف شود
از آستانه تحمل فراتر رفته است. این ویژگی است ns3::RealTimeSimulatorImpl::HardLimit
و پیش فرض 0.1 ثانیه است.
یک حالت عملکرد متفاوت، حالتی است که در آن زمان شبیه سازی شده باشد نه یخ زده در طول یک رویداد
اعدام. این حالت از شبیه سازی بلادرنگ پیاده سازی شد اما از آن حذف شد ns-3 درخت
به دلیل سوالاتی در مورد اینکه آیا مفید خواهد بود یا خیر. اگر کاربران به زمان واقعی علاقه مند هستند
شبیهسازی که زمان شبیهسازی برای آن در طول اجرای رویداد ثابت نمیشود (یعنی هر
تماس گرفتن شبیه ساز::Now() زمان فعلی ساعت دیواری را برمی گرداند، نه زمانی که در آن
رویداد شروع به اجرا کرد)، لطفاً با لیست پستی ns-developers تماس بگیرید.
استفاده
استفاده از شبیه ساز بلادرنگ از منظر برنامه نویسی ساده است.
کاربران فقط باید ویژگی را تنظیم کنند SimulatorImplementationType به Realtime
شبیه ساز مانند زیر:
GlobalValue::Bind ("SimulatorImplementationType"،
StringValue ("ns3::RealtimeSimulatorImpl"));
یک اسکریپت در آن وجود دارد examples/realtime/realtime-udp-echo.cc که مثالی از نحوه انجام آن دارد
رفتار بیدرنگ را پیکربندی کنید تلاش كردن:
$ ./waf -- اجرای realtime-udp-echo
این که آیا شبیه ساز با بهترین تلاش کار می کند یا سیاست محدودیت سخت، تعیین می شود
با ویژگی هایی که در بخش قبل توضیح داده شد.
پیاده سازی
پیاده سازی در فایل های زیر موجود است:
· src/core/model/realtime-simulator-impl.{cc,h}
· src/core/model/synchronizer-wall-clock.{cc,h}
برای ایجاد یک زمانبندی بیدرنگ، به اولین تقریبی که فقط میخواهید ایجاد کنید
زمان شبیه سازی به مصرف زمان واقعی می پرد. ما پیشنهاد می کنیم این کار را با استفاده از ترکیبی از
خواب و مشغله منتظر است. Sleep-waits باعث می شود که فرآیند فراخوانی (رشته) به نتیجه برسد
پردازنده برای مدتی حتی اگر این مدت زمان مشخص را بتوان سپری کرد
به وضوح نانوثانیه، در واقع به یک دانه بندی خاص سیستم عامل تبدیل می شود. که در
لینوکس، دانه بندی به نام جیفی است. به طور معمول این وضوح برای کافی نیست
نیازهای ما (در حد ده میلی ثانیه)، بنابراین ما به سمت پایین گرد می کنیم و برای مقداری می خوابیم
تعداد کمتری از جیفی ها سپس فرآیند پس از تعداد مشخص شده بیدار می شود
جیفیس گذشت. در این زمان، مقداری زمان باقی مانده برای صبر کردن داریم. این بار است
به طور کلی کمتر از حداقل زمان خواب است، بنابراین ما مشغول هستیم و منتظر باقی مانده آن هستیم
زمان. این بدان معناست که نخ فقط در یک چرخه مصرف کننده حلقه for قرار می گیرد تا اینکه
زمان مورد نظر می رسد پس از ترکیبی از انتظارهای خواب و مشغول، زمان واقعی سپری شده است
ساعت (دیواری) باید با زمان شبیه سازی رویداد بعدی و شبیه سازی مطابقت داشته باشد
درآمد
یاران
فصل های بالا شما را با موارد مختلفی آشنا کرد ns-3 مفاهیم برنامه نویسی مانند هوشمند
اشاره گرهایی برای مدیریت حافظه شمارش مرجع، ویژگی ها، فضاهای نام، تماس های برگشتی و غیره.
کاربرانی که در این API سطح پایین کار می کنند می توانند به یکدیگر متصل شوند ns-3 اشیاء با دانه بندی ریز
با این حال، یک برنامه شبیه سازی که به طور کامل با استفاده از API سطح پایین نوشته شود، بسیار طولانی خواهد بود
و کد نویسی خسته کننده است. به همین دلیل، یک به اصطلاح "Helper API" جداگانه روی هم گذاشته شده است
روی هسته ns-3 API. اگر شما خوانده اید ns-3 آموزش، شما قبلا آشنا خواهید شد
با کمک API، زیرا این API است که معمولاً ابتدا کاربران جدید با آن آشنا می شوند.
در این فصل، فلسفه طراحی Helper API را معرفی کرده و آن را با آن مقایسه می کنیم
API سطح پایین اگر کاربر شدیدی از ns-3، احتمالاً به جلو و عقب حرکت خواهید کرد
بین این APIها حتی در همان برنامه.
Helper API چند هدف دارد:
1. بقیه src / هیچ وابستگی به API کمکی ندارد. هر چیزی که بتوان با آن انجام داد
API کمکی را می توان در API سطح پایین نیز کدگذاری کرد
2. ظروف: اغلب شبیه سازی ها نیاز به انجام تعدادی از اقدامات یکسان برای گروه ها دارند
از اشیاء Helper API به شدت از ظروف اشیاء مشابه استفاده می کند
عملیات مشابه یا یکسان را می توان انجام داد.
3. Helper API عمومی نیست. در تلاش برای به حداکثر رساندن استفاده مجدد از کد نیست. بنابراین،
سازه های برنامه نویسی مانند چندشکلی و قالب هایی که به استفاده مجدد از کد دست می یابند
آنقدر رایج نیست به عنوان مثال، کمک های جداگانه CsmaNetDevice و
کمک کننده های PointToPointNetDevice اما از یک پایگاه مشترک NetDevice مشتق نمی شوند
کلاس.
4. Helper API معمولاً با اشیاء تخصیص داده شده پشته (در مقابل heap-allocated) کار می کند. برای
برخی از برنامه ها، ns-3 کاربران ممکن است نیازی به نگرانی در مورد ایجاد شی سطح پایین نداشته باشند
مدیریت Ptr؛ آنها می توانند با ظروف اشیاء و کمک های اختصاص داده شده به پشته بسنده کنند
که روی آنها عمل می کنند.
API کمکی واقعاً در مورد ساختن است ns-3 نوشتن و خواندن برنامه ها آسان تر است، بدون
از بین بردن قدرت رابط سطح پایین. بقیه این فصل برخی از آنها را ارائه می دهد
نمونه هایی از قراردادهای برنامه نویسی Helper API.
ساخت توطئه با استفاده از la گنوپلو طبقه
2 روش متداول برای ساختن نمودار با استفاده از آن وجود دارد ns-3 و gnuplot (-
http://www.gnuplot.info):
1. یک فایل کنترل gnuplot با استفاده از ns-3کلاس Gnuplot.
2. یک فایل داده gnuplot با استفاده از مقادیر تولید شده توسط ns-3.
این بخش در مورد روش 1 است، یعنی در مورد نحوه ساخت یک نمودار با استفاده از آن است ns-3Gnuplot
کلاس اگر به روش 2 علاقه مند هستید، زیر بخش "یک مثال واقعی" را ببینید
بخش "ردیابی" در ns-3 آموزش.
ایجاد توطئه با استفاده از la گنوپلو طبقه
برای ایجاد طرح با استفاده از مراحل زیر باید انجام شود ns-3کلاس Gnuplot:
1. کد خود را طوری تغییر دهید که از کلاس Gnuplot و توابع آن استفاده کند.
2. کد خود را طوری اجرا کنید که یک فایل کنترلی gnuplot ایجاد کند.
3. gnuplot را با نام فایل کنترل gnuplot فراخوانی کنید.
4. فایل گرافیکی که در نمایشگر گرافیکی مورد علاقه شما تولید شده است را مشاهده کنید.
برای جزئیات بیشتر در مرحله 1، کد را از نمونه نمودارهایی که در زیر توضیح داده شده است، مشاهده کنید.
An مثال برنامه که شما با استفاده از la گنوپلو طبقه
نمونه برنامه ای که استفاده می کند ns-3کلاس Gnuplot را می توانید در اینجا پیدا کنید:
src/stats/examples/gnuplot-example.cc
برای اجرای این مثال، موارد زیر را انجام دهید:
$ ./پوسته waf
$ cd build/debug/src/stats/examples
$ ./gnuplot-example
این باید فایل های کنترل gnuplot زیر را در دایرکتوری که در آن مثال است تولید کند
واقع شده است:
plot-2d.plt
plot-2d-with-error-bars.plt
plot-3d.plt
برای پردازش این فایل های کنترل gnuplot، موارد زیر را انجام دهید:
$ gnuplot plot-2d.plt
$ gnuplot plot-2d-with-error-bars.plt
$ gnuplot plot-3d.plt
این باید فایل های گرافیکی زیر را در دایرکتوری که مثال در آن قرار دارد تولید کند
واقع شده:
plot-2d.png
plot-2d-with-error-bars.png
plot-3d.png
شما می توانید این فایل های گرافیکی را در نمایشگر گرافیکی مورد علاقه خود مشاهده کنید. اگر گیمپ دارید
برای مثال روی دستگاه خود نصب شده است، می توانید این کار را انجام دهید:
$ gimp plot-2d.png
$ gimp plot-2d-with-error-bars.png
$ gimp plot-3d.png
An مثال 2-بعدی طرح
طرح 2 بعدی زیر
[تصویر]
با استفاده از کد زیر از gnuplot-example.cc ایجاد شد:
استفاده از namespace std؛
string fileNameWithNoExtension = "plot-2d";
graphics رشته ای FileName = fileNameWithNoExtension + ".png";
string plotFileName = fileNameWithNoExtension + ".plt";
string plotTitle = "نقشه دو بعدی";
string dataTitle = "داده های 2 بعدی";
// طرح را نمونه برداری کنید و عنوان آن را تنظیم کنید.
نمودار Gnuplot (graphicsFileName)؛
plot.SetTitle (plotTitle);
// فایل گرافیکی را بسازید که فایل طرح زمانی که آن را ایجاد می کند
// با Gnuplot استفاده می شود، یک فایل PNG باشد.
plot.SetTerminal ("png");
// برچسب ها را برای هر محور تنظیم کنید.
plot.SetLegend ("X Values"، "Y Values");
// محدوده را برای محور x تنظیم کنید.
plot.AppendExtra ("set xrange [-6:+6]");
// مجموعه داده را نمونهسازی کنید، عنوان آن را تنظیم کنید و نقاط را به شکلی درآورید
// به همراه خطوط اتصال رسم شده است.
مجموعه داده Gnuplot2dDataset.
database.SetTitle (dataTitle);
dataset.SetStyle (Gnuplot2dDataset::LINES_POINTS);
دو برابر x;
دو برابر y;
// مجموعه داده دو بعدی را ایجاد کنید.
برای (x = -5.0; x <= +5.0; x += 1.0)
{
// منحنی دو بعدی را محاسبه کنید
//
// 2
// y = x.
//
y = x * x;
// این نقطه را اضافه کنید.
مجموعه داده.افزودن (x, y);
}
// مجموعه داده را به نمودار اضافه کنید.
plot.AddDataset (مجموعه داده);
// فایل طرح را باز کنید.
ofstream plotFile (plotFileName.c_str());
// فایل طرح را بنویسید.
plot.GenerateOutput (plotFile);
// فایل طرح را ببندید.
plotFile.close ();
An مثال 2-بعدی طرح با خطا میله های زندان
نمودار 2 بعدی زیر با نوارهای خطا در جهت x و y
[تصویر]
با استفاده از کد زیر از gnuplot-example.cc ایجاد شد:
استفاده از namespace std؛
string fileNameWithNoExtension = "Plot-2d-with-error-bars";
graphics رشته ای FileName = fileNameWithNoExtension + ".png";
string plotFileName = fileNameWithNoExtension + ".plt";
string plotTitle = "نقشه دو بعدی با نوارهای خطا";
string dataTitle = "داده های دو بعدی با نوارهای خطا";
// طرح را نمونه برداری کنید و عنوان آن را تنظیم کنید.
نمودار Gnuplot (graphicsFileName)؛
plot.SetTitle (plotTitle);
// فایل گرافیکی را بسازید که فایل طرح زمانی که آن را ایجاد می کند
// با Gnuplot استفاده می شود، یک فایل PNG باشد.
plot.SetTerminal ("png");
// برچسب ها را برای هر محور تنظیم کنید.
plot.SetLegend ("X Values"، "Y Values");
// محدوده را برای محور x تنظیم کنید.
plot.AppendExtra ("set xrange [-6:+6]");
// مجموعه داده را نمونهسازی کنید، عنوان آن را تنظیم کنید و نقاط را به شکلی درآورید
// بدون خطوط اتصال رسم شده است.
مجموعه داده Gnuplot2dDataset.
database.SetTitle (dataTitle);
dataset.SetStyle (Gnuplot2dDataset::POINTS);
// کاری کنید مجموعه داده دارای نوارهای خطا در هر دو جهت x و y باشد.
database.SetErrorBars (Gnuplot2dDataset::XY);
دو برابر x;
دو برابر xErrorDelta;
دو برابر y;
دو برابر yErrorDelta;
// مجموعه داده دو بعدی را ایجاد کنید.
برای (x = -5.0; x <= +5.0; x += 1.0)
{
// منحنی دو بعدی را محاسبه کنید
//
// 2
// y = x.
//
y = x * x;
// عدم قطعیت در جهت x را ثابت کنید و بسازید
// عدم قطعیت در جهت y کسری ثابت از
// مقدار y.
xErrorDelta = 0.25;
yErrorDelta = 0.1 * y;
// این نقطه را با عدم قطعیت در هر دو x و y اضافه کنید
// جهت.
data.Add (x, y, xErrorDelta, yErrorDelta);
}
// مجموعه داده را به نمودار اضافه کنید.
plot.AddDataset (مجموعه داده);
// فایل طرح را باز کنید.
ofstream plotFile (plotFileName.c_str());
// فایل طرح را بنویسید.
plot.GenerateOutput (plotFile);
// فایل طرح را ببندید.
plotFile.close ();
An مثال 3-بعدی طرح
طرح 3 بعدی زیر
[تصویر]
با استفاده از کد زیر از gnuplot-example.cc ایجاد شد:
استفاده از namespace std؛
string fileNameWithNoExtension = "plot-3d";
graphics رشته ای FileName = fileNameWithNoExtension + ".png";
string plotFileName = fileNameWithNoExtension + ".plt";
string plotTitle = "نقشه دو بعدی";
string dataTitle = "داده های 3 بعدی";
// طرح را نمونه برداری کنید و عنوان آن را تنظیم کنید.
نمودار Gnuplot (graphicsFileName)؛
plot.SetTitle (plotTitle);
// فایل گرافیکی را بسازید که فایل طرح زمانی که آن را ایجاد می کند
// با Gnuplot استفاده می شود، یک فایل PNG باشد.
plot.SetTerminal ("png");
// نمودار را 30 درجه حول محور x بچرخانید و سپس آن را بچرخانید
// 120 درجه حول محور z جدید رسم کنید.
plot.AppendExtra ("تنظیم نمای 30، 120، 1.0، 1.0")؛
// صفر محور z را در صفحه محور x و محور y قرار دهید.
plot.AppendExtra ("set ticslevel 0");
// برچسب ها را برای هر محور تنظیم کنید.
plot.AppendExtra ("Set xlabel 'X Values'");
plot.AppendExtra ("Set ylabel 'Y Values'");
plot.AppendExtra ("Set zlabel 'Z Values'");
// محدوده ها را برای محور x و y تنظیم کنید.
plot.AppendExtra ("set xrange [-5:+5]");
plot.AppendExtra ("set yrange [-5:+5]");
// مجموعه داده را نمونهسازی کنید، عنوان آن را تنظیم کنید و نقاط را به شکلی درآورید
// با خطوط متصل شده است.
مجموعه داده Gnuplot3dDataset.
database.SetTitle (dataTitle);
dataset.SetStyle ("با خطوط");
دو برابر x;
دو برابر y;
دو برابر z;
// مجموعه داده دو بعدی را ایجاد کنید.
برای (x = -5.0; x <= +5.0; x += 1.0)
{
برای (y = -5.0؛ y <= +5.0؛ y += 1.0)
{
// سطح سه بعدی را محاسبه کنید
//
// 2 2
// z = x * y.
//
z = x * x * y * y;
// این نقطه را اضافه کنید.
مجموعه داده.افزودن (x, y, z);
}
// خط خالی در انتهای هر داده مقدار x ضروری است
// نقاطی برای کار کردن شبکه سطح سه بعدی.
database.AddEmptyLine ();
}
// مجموعه داده را به نمودار اضافه کنید.
plot.AddDataset (مجموعه داده);
// فایل طرح را باز کنید.
ofstream plotFile (plotFileName.c_str());
// فایل طرح را بنویسید.
plot.GenerateOutput (plotFile);
// فایل طرح را ببندید.
plotFile.close ();
با استفاده از پــایتــون به دویدن ns-3
اتصالات پایتون به کد ++C اجازه ورود می دهد ns-3 از پایتون فراخوانی شود.
این فصل به شما نشان می دهد که چگونه یک اسکریپت پایتون بسازید که بتواند اجرا شود ns-3 و همچنین
فرآیند ایجاد پیوندهای پایتون برای C++ ns-3 ماژول
معرفی
هدف پایتون bindings برای ns-3 دو دسته هستند:
1. به برنامه نویس اجازه دهید تا اسکریپت های شبیه سازی کامل را در پایتون بنویسد (-
http://www.python.org);
2. نمونه اولیه مدل های جدید (مثلاً پروتکل های مسیریابی).
در حال حاضر، تمرکز اولیه اتصالات، هدف اول است، اما هدف دوم
هدف نیز در نهایت پشتیبانی خواهد شد. پیوندهای پایتون برای ns-3 در حال توسعه هستند
با استفاده از ابزار جدیدی به نام PyBindGen (http://code.google.com/p/pybindgen).
An مثال پــایتــون خط که اجرا می شود ns-3
در اینجا چند نمونه کد است که در پایتون نوشته شده و اجرا می شود ns-3، که نوشته شده است
در C++ این مثال پایتون را می توان در آن یافت examples/tutorial/first.py:
واردات ns.applications
واردات 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)
nodes = ns.network.NodeContainer()
گره ها. ایجاد(2)
pointToPoint = ns.point_to_point.PointToPointHelper()
pointToPoint.SetDeviceAttribute("DataRate"، ns.core.StringValue("5Mbps"))
pointToPoint.SetChannelAttribute("Delay"، ns.core.StringValue("2ms"))
دستگاه ها = pointToPoint.Install(nodes)
stack = ns.internet.InternetStackHelper()
stack.Install(nodes)
آدرس = ns.internet.Ipv4AddressHelper()
address.SetBase(ns.network.Ipv4Address("10.1.1.0")، ns.network.Ipv4Mask("255.255.255.0"))
رابط ها = آدرس.تخصیص (دستگاه ها)؛
echoServer = 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(interfaces.GetAddress(1)، 9)
echoClient.SetAttribute("MaxPackets"، ns.core.UintegerValue(1))
echoClient.SetAttribute("Interval"، ns.core.TimeValue(ns.core.seconds (1.0)))
echoClient.SetAttribute("PacketSize"، ns.core.UintegerValue(1024))
clientApps = echoClient.Install(گره ها. دریافت(0))
clientApps.Start(ns.core.seconds(2.0))
clientApps.Stop(ns.core.seconds(10.0))
ns.core.Simulator.Run()
ns.core.Simulator.Destroy()
محل دویدن و پیاده روی پــایتــون اسکریپت
waf شامل چند گزینه است که به طور خودکار مسیر پایتون را برای یافتن ns3 به روز می کند
مدول. برای اجرای برنامه های نمونه، دو راه برای استفاده از waf برای مراقبت از این موضوع وجود دارد. یکی
اجرای یک پوسته وف است. به عنوان مثال:
$ ./waf --shell
$ python examples/wireless/mixed-wireless.py
و دیگری استفاده از گزینه --pyrun برای waf است:
$ ./waf --pyrun examples/wireless/mixed-wireless.py
برای اجرای یک اسکریپت پایتون تحت دیباگر C:
$ ./waf --shell
$ gdb --args python examples/wireless/mixed-wireless.py
برای اجرای اسکریپت پایتون خود که فراخوانی می کند ns-3 و این مسیر را دارد
/path/to/your/example/my-script.py، انجام دهید:
$ ./waf --shell
$ python /path/to/your/example/my-script.py
هشدارهای
پیوندهای پایتون برای ns-3 یک کار در حال پیشرفت هستند و برخی از محدودیت ها توسط آنها شناخته شده است
توسعه دهندگان برخی از این محدودیت ها (نه همه) در اینجا ذکر شده است.
ناتمام پوشش
اول از همه، به خاطر داشته باشید که 100٪ از API در پایتون پشتیبانی نمی شود. برخی از
دلایل عبارتند از:
1. برخی از APIها شامل نشانگرهایی هستند که نیاز به دانستن نوع حافظه دارند
معانی گذران (چه کسی صاحب چه حافظه ای است). چنین دانشی بخشی از عملکرد نیست
امضا، و یا مستند است یا حتی گاهی اوقات مستند نیست. حاشیه نویسی هستند
برای اتصال آن توابع مورد نیاز است.
2. گاهی اوقات از یک نوع داده بنیادی غیر معمول یا ساختار C++ استفاده می شود که هنوز استفاده نشده است
پشتیبانی شده توسط PyBindGen.
3. GCC-XML کلاسهای مبتنی بر الگو را گزارش نمیکند مگر اینکه نمونهسازی شده باشند.
بسیاری از API های گم شده را می توان با زمان، صبر و تخصص کافی و
در صورت ارسال گزارش اشکال، احتمالا بسته بندی می شود. با این حال، گزارش اشکال را ارسال نکنید
گفتن "قطعات ناقص است"، زیرا ما نیروی انسانی برای تکمیل 100٪ کار نداریم.
اتصالات
تبدیل سازندگان
تبدیل سازندگان هنوز به طور کامل توسط PyBindGen پشتیبانی نمی شوند و همیشه به عنوان عمل می کنند
سازنده های صریح هنگام ترجمه یک API به پایتون. به عنوان مثال، در C++ شما می توانید انجام دهید
این:
Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase ("192.168.0.0"، "255.255.255.0");
ipAddrs.Assign (backboneDevices)؛
در پایتون، فعلاً باید انجام دهید:
ipAddrs = ns3.Ipv4AddressHelper()
ipAddrs.SetBase(ns3.Ipv4Address("192.168.0.0"), ns3.Ipv4Mask("255.255.255.0"))
ipAddrs.Assign(backboneDevices)
خط فرمان
CommandLine::AddValue() در پایتون متفاوت از آن کار می کند ns-3. در پایتون،
پارامتر اول رشته ای است که نام گزینه خط فرمان را نشان می دهد. زمانی که گزینه
تنظیم شده است، یک ویژگی با همان نام با نام گزینه بر روی تنظیم شده است خط فرمان()
هدف - شی. مثال:
NUM_NODES_SIDE_DEFAULT = 3
cmd = ns3.CommandLine()
cmd.NumNodesSide = هیچ
cmd.AddValue("NumNodesSide"، "تعداد گره های طرف شبکه (تعداد کل گره ها این عدد مجذور خواهد بود)")
cmd.Parse(argv)
[...]
اگر cmd.NumNodesSide None باشد:
num_nodes_side = NUM_NODES_SIDE_DEFAULT
دیگری:
num_nodes_side = int(cmd.NumNodesSide)
ردیابی
ردیابی مبتنی بر پاسخ به تماس هنوز به درستی برای پایتون پشتیبانی نمی شود، زیرا جدید است ns-3 API نیاز دارد
فراهم شود تا از این امر حمایت شود.
نوشتن فایل Pcap از طریق API معمولی پشتیبانی می شود.
ردیابی Ascii از آن زمان پشتیبانی می شود ns-3.4 از طریق C++ API معمولی که به پایتون ترجمه شده است.
با این حال، ردیابی ascii نیاز به ایجاد یک شی ostream برای عبور به ascii دارد
روش های ردیابی در پایتون، C++ std::ofstream برای اجازه دادن به حداقل بسته بندی شده است
این. مثلا:
ascii = ns3.ofstream("wifi-ap.tr") # فایل را ایجاد کنید
ns3.YansWifiPhyHelper.EnableAsciiAll(ascii)
ns3.Simulator.Run()
ns3.Simulator.Destroy()
ascii.close() # فایل را ببندید
یک اخطار وجود دارد: شما نباید اجازه دهید که شی فایل در حین جمع آوری زباله جمع آوری شود ns-3
هنوز از آن استفاده می کند این بدان معناست که متغیر 'ascii' در بالا نباید اجازه داده شود
خارج از محدوده وگرنه برنامه از کار می افتد.
Cygwin محدودیت
اتصالات پایتون در Cygwin کار نمی کند. این به دلیل یک باگ gccxml است.
ممکن است با اسکن مجدد تعاریف API از داخل cygwin از آن دور شوید
محیط (./waf --python-scan). با این حال محتمل ترین راه حل احتمالا مجبور خواهد بود
این باشد که اتصالات پایتون را در CygWin غیرفعال کنیم.
اگر واقعاً به پیوندهای پایتون در ویندوز اهمیت می دهید، سعی کنید با mingw و native بسازید
در عوض پایتون در غیر این صورت، برای ساخت بدون اتصال پایتون، اتصالات پایتون را غیرفعال کنید
مرحله پیکربندی:
$ ./waf configure --disable-python
کارگر با پــایتــون اتصالات
در حال حاضر دو نوع اتصال پایتون در آن وجود دارد ns-3:
1. پیوندهای یکپارچه شامل تعاریف API برای همه ماژول ها هستند و می توان آنها را در آنها یافت
یک دایرکتوری واحد، اتصالات / پایتون.
2. اتصالات مدولار شامل تعاریف API برای یک ماژول است و در هر یک یافت می شود
ماژول ها پیوستگی دایرکتوری.
پــایتــون اتصالات گردش کار
فرآیندی که توسط آن پیوندهای پایتون انجام می شود به شرح زیر است:
1. به طور دوره ای یک توسعه دهنده از GCC-XML استفاده می کند (http://www.gccxml.org) اسکن مبتنی بر API
اسکریپت، که تعریف API اسکن شده را به عنوان ذخیره می کند bindings/python/ns3_module_*.py فایل ها
یا به عنوان فایل های پایتون در هر ماژول پیوستگی فهرست راهنما. این فایل ها در زیر نگهداری می شوند
کنترل نسخه در اصلی ns-3 مخزن؛
2. سایر توسعه دهندگان مخزن را شبیه سازی کرده و از تعاریف API اسکن شده از قبل استفاده می کنند.
3. هنگام پیکربندی ns-3، pybindgen به طور خودکار دانلود می شود اگر قبلاً نباشد
نصب شده است. منتشر شد ns-3 tarballs یک کپی از pybindgen را ارسال خواهد کرد.
اگر با کامپایل کردن پیوندهای پایتون مشکلی پیش بیاید و بخواهید آنها را نادیده بگیرید
و با C++ ادامه دهید، می توانید پایتون را با این موارد غیرفعال کنید:
$ ./waf --disable-python
دستورالعمل ها برای اداره جدید فایل ها or تغییر کرد API در
بنابراین شما در حال تغییر موجود هستید ns-3 API ها و پیوندهای پایتون دیگر کامپایل نمی شوند؟ انجام دادن
ناامید نشوید، می توانید اتصالات را مجدداً اسکن کنید تا اتصالات جدیدی ایجاد کنید که منعکس کننده تغییرات هستند
به ns-3 API
بسته به اینکه از اتصالات یکپارچه یا مدولار استفاده می کنید، به بحث های زیر مراجعه کنید
یاد بگیرید که چگونه پیوندهای پایتون خود را دوباره اسکن کنید.
یک پارچه پــایتــون اتصالات
پویش la یک پارچه پــایتــون اتصالات
برای اسکن پیوندهای یکپارچه پایتون موارد زیر را انجام دهید:
$ ./waf --python-scan
سازمان of la یک پارچه پــایتــون اتصالات
تعاریف یکپارچه Python API به شرح زیر سازماندهی شده است. برای هر ns-3 واحد
، پرونده bindings/python/ns3_module_ .py API خود را شرح می دهد. هر کدام از آن ها
فایل ها دارای 3 عملکرد سطح بالا هستند:
1. دف ثبت_انواع(مدول)(): این تابع از ثبت انواع جدید مراقبت می کند (به عنوان مثال
کلاس های C++، enums) که در ماژول tha تعریف شده اند.
2. دف register_methods(مدول)(): این تابع برای هر کلاس فراخوانی می کند ، یکی دیگر
تابع register_methods_Ns3 (مدول). این توابع اخیر متد را اضافه می کنند
تعاریف برای هر کلاس؛
3. دف register_functions(مدول)(): این تابع ثبت می کند ns-3 توابع که متعلق به
آن ماژول
پیمانهای پــایتــون اتصالات
بررسی اجمالی
از ns 3.11، اتصالات مدولار به موازات یکپارچه قدیمی اضافه می شوند.
اتصالات
پیوندهای جدید پایتون در فضای نام ns به جای ns3 برای فضای قدیمی تولید میشوند.
اتصالات مثال:
از ns.network import Node
n1 = Node()
با اتصالات ماژولار پایتون:
1. برای هر کدام یک ماژول افزونه پایتون جداگانه وجود دارد ns-3 مدول؛
2. اسکن تعاریف API (apidefs) بر اساس هر ماژول ns انجام می شود.
3. فایل های apidefs هر ماژول در یک زیر شاخه "bindings" ماژول ذخیره می شوند.
فهرست راهنما؛
پویش la پیمانهای پــایتــون اتصالات
برای اسکن پیوندهای ماژولار پایتون برای ماژول هسته، به عنوان مثال، موارد زیر را انجام دهید:
$ ./waf --apiscan=core
برای اسکن پیوندهای ماژولار پایتون برای همه ماژول ها، موارد زیر را انجام دهید:
$ ./waf --apiscan=all
ایجاد a جدید ماژول ها
اگر ماژول جدیدی اضافه میکنید، پیوندهای پایتون به کامپایل شدن ادامه میدهند اما نمیشوند
ماژول جدید را بپوشانید.
برای پوشش دادن یک ماژول جدید، باید a ایجاد کنید bindings/python/ns3_module_ .py فایل،
مشابه آنچه در قسمت های قبل توضیح داده شد و آن را در متغیر ثبت کنید
LOCAL_MODULES() in bindings/python/ns3modulegen.py
اضافه کردن پیمانهای اتصالات به A موجود ماژول ها
برای افزودن پشتیبانی از اتصالات مدولار به یک موجود ns-3 ماژول، به سادگی موارد زیر را اضافه کنید
خط به تابع build() wscript آن:
bld.ns3_python_bindings()
سازمان of la پیمانهای پــایتــون اتصالات
La src/ /پیوندها دایرکتوری ممکن است حاوی فایل های زیر باشد، برخی از آنها
اختیاری:
· callbacks_list.py: این یک فایل اسکن شده است، دست نزنید. حاوی لیستی از
پاسخ به تماس<...> نمونه های الگو در سرصفحه های اسکن شده یافت می شود.
· modulegen__gcc_LP64.py: این یک فایل اسکن شده است، دست نزنید. تعاریف API اسکن شده
برای GCC، معماری LP64 (64 بیتی)
· modulegen__gcc_ILP32.py: این یک فایل اسکن شده است، دست نزنید. تعاریف API اسکن شده
برای GCC، معماری ILP32 (32 بیتی)
· modulegen_customizations.py: می توانید به صورت اختیاری این فایل را به منظور سفارشی کردن آن اضافه کنید
تولید کد pybindgen
· scan-header.h: می توانید به صورت اختیاری این فایل را برای سفارشی کردن فایل هدر که اسکن می شود اضافه کنید
برای ماژول اساسا این فایل به جای ns3/ اسکن می شود -module.h.
به طور معمول، اولین عبارت #include "ns3/ است. -module.h"، به علاوه برخی دیگر
چیزهایی برای اجبار نمونه های قالب.
· module_helpers.cc: میتوانید فایلهای دیگری مانند این را برای پیوند به پایتون اضافه کنید
ماژول افزونه، اما آنها باید در wscript ثبت شوند. نگاه کنید
src/core/wscript برای مثالی از نحوه انجام این کار؛
· .py: اگر این فایل وجود داشته باشد، به ماژول پایتون "frontend" برای ns3 تبدیل می شود
ماژول، و ماژول پسوند (فایل so) تبدیل به _ می شود .پس به جای .بنابراین.
این فایل .py باید همه نمادها را از ماژول وارد کند _ (این بیشتر است
از آنچه به نظر می رسد دشوار است، به عنوان مثال src/core/bindings/core.py را ببینید) و سپس می توانید اضافه کنید
برخی از تعاریف اضافی پایتون خالص.
بیشتر اطلاعات برای توسعه دهندگان
اگر توسعه دهنده هستید و به اطلاعات بیشتری در مورد نیاز دارید ns-3پیوندهای پایتون، لطفاً ببینید
پــایتــون اتصالات ویکی با ما.
تست
بررسی اجمالی
این سند مربوط به آزمایش و اعتبار سنجی است ns-3 نرم افزار.
این سند ارائه می دهد
· پیشینه در مورد اصطلاحات و تست نرم افزار (فصل 2).
· شرح چارچوب تست ns-3 (فصل 3).
· راهنمای توسعه دهندگان مدل یا مشارکت کنندگان مدل جدید برای نحوه نوشتن تست ها (فصل
4)؛
به طور خلاصه، سه فصل اول باید توسط توسعه دهندگان و مشارکت کنندگان ns خوانده شود
نیاز به درک نحوه مشارکت کدهای آزمایشی و برنامه های معتبر و بقیه موارد است
این سند فضایی را برای افراد فراهم می کند تا در مورد چه جنبه هایی از مدل های انتخاب شده گزارش دهند
تایید شده اند.
زمینه
این فصل ممکن است be رد شد by خوانندگان آشنا با la اصول of نرمافزار تست.
نوشتن نرم افزار بدون نقص پیشنهاد دشواری است. ابعاد زیادی برای آن وجود دارد
مشکل و سردرگمی زیادی در مورد اینکه منظور از اصطلاحات مختلف در چیست وجود دارد
زمینه های مختلف ما ارزش آن را پیدا کردهایم که کمی زمان صرف بررسی آن کنیم
موضوع و تعریف برخی اصطلاحات
تست نرم افزار ممکن است به صورت ضعیف به عنوان فرآیند اجرای یک برنامه با
قصد یافتن خطاها وقتی کسی وارد بحث در مورد تست نرم افزار می شود، آن را
به سرعت آشکار میشود که ذهنیتهای متمایز زیادی وجود دارد که میتوان با آنها استفاده کرد
به موضوع نزدیک شوید
برای مثال، میتوان فرآیند را به دستههای عملکردی گستردهای مانند
"تست صحت"، "تست عملکرد"، "تست استحکام" و "امنیت"
روش دیگری برای نگاه کردن به مشکل، چرخه عمر است: «آزمایش نیازمندیها».
«آزمایش طراحی»، «تست پذیرش» و «تست تعمیر و نگهداری» دیدگاه دیگری.
در محدوده سیستم آزمایش شده است. در این مورد ممکن است از "آزمایش واحد" صحبت شود.
«آزمایش مؤلفه»، «تست یکپارچه سازی» و «آزمایش سیستم». این اصطلاحات عبارتند از
همچنین به هیچ وجه استاندارد نشده است، و بنابراین "تست تعمیر و نگهداری" و "رگرسیون".
testing'' ممکن است به جای هم شنیده شود. علاوه بر این، اغلب از این اصطلاحات سوء استفاده می شود.
همچنین تعدادی از رویکردهای فلسفی مختلف برای تست نرم افزار وجود دارد. برای
به عنوان مثال، برخی از سازمان ها از نوشتن برنامه های تست قبل از اجرای واقعی حمایت می کنند
نرم افزار مورد نظر، منجر به "توسعه مبتنی بر آزمایش" می شود. برخی سازمان ها از آن حمایت می کنند
آزمایش از دیدگاه مشتری در اسرع وقت، به دنبال موازی با
فرآیند توسعه چابک: «اوایل آزمایش و اغلب آزمایش کنید.» گاهی اوقات به آن می گویند
"آزمایش چابک." به نظر می رسد که حداقل یک رویکرد برای آزمایش برای هر یک وجود دارد
روش شناسی توسعه
La ns-3 پروژه در کار حمایت از هیچ یک از این فرآیندها نیست، اما
پروژه به عنوان یک کل دارای الزاماتی است که به اطلاع رسانی فرآیند آزمایش کمک می کند.
مانند تمام محصولات اصلی نرم افزاری، ns-3 دارای تعدادی ویژگی است که باید وجود داشته باشد
محصول برای موفقیت از منظر آزمایش، برخی از این ویژگی ها باید باشد
به آن پرداخته شده است ns-3 باید "صحیح"، "قوی"، "عملکرد" و
"قابل نگهداری." در حالت ایده آل باید معیارهایی برای هر یک از این ابعاد وجود داشته باشد
توسط آزمایشها بررسی میشود تا مشخص شود چه زمانی محصول انتظارات خود را برآورده نمیکند /
مورد نیاز است.
درستی
هدف اصلی از آزمایش، تعیین این است که یک قطعه نرم افزار رفتار می کند
''به درستی.'' برای ns-3 این بدان معناست که اگر چیزی را شبیه سازی کنیم، شبیه سازی باید
به طور صادقانه برخی از موجودیت یا فرآیندهای فیزیکی را با دقت مشخص نشان می دهد و
دقت، درستی.
معلوم می شود که از دو منظر می توان به درستی نگاه کرد.
بررسی اینکه یک مدل خاص مطابق با مشخصات آن پیاده سازی شده است
به طور کلی نامیده می شود تایید. فرآیند تصمیم گیری در مورد صحیح بودن مدل
استفاده مورد نظر از آن به طور کلی نامیده می شود اعتبار سنجی.
اعتبار و تایید
مدل کامپیوتری نمایش ریاضی یا منطقی چیزی است. می تواند
نشان دهنده یک وسیله نقلیه، یک فیل (نگاه کنید به داود هارل صحبت در باره مدل سازی an فیل at
SIMUTools 2009، یا یک کارت شبکه مدل ها همچنین می توانند فرآیندهایی مانند جهانی را نشان دهند
گرم شدن، جریان ترافیک آزادراه یا مشخصات پروتکل شبکه. مدل ها می توانند باشند
نمایش های کاملاً وفادار از مشخصات فرآیند منطقی، اما آنها
لزوماً هرگز نمی توان یک شی یا فرآیند فیزیکی را به طور کامل شبیه سازی کرد. در بیشتر موارد، الف
برای شبیه سازی محاسباتی، تعدادی ساده سازی برای مدل انجام شده است
قابل تحمل
هر مدلی یک هدف سیستم که سعی در شبیه سازی دارد. اولین قدم در
ایجاد یک مدل شبیه سازی برای شناسایی این سیستم هدف و سطح جزئیات و
دقتی که شبیه سازی مورد نظر برای بازتولید است. در مورد یک فرآیند منطقی،
سیستم هدف ممکن است به عنوان "TCP همانطور که توسط RFC 793 تعریف شده است" شناسایی شود. در این مورد، آن
احتمالاً ایجاد مدلی که به طور کامل و صادقانه RFC را بازتولید می کند، مطلوب خواهد بود
793. در مورد یک فرآیند فیزیکی این امکان پذیر نخواهد بود. اگر مثلا شما
میخواهید یک کارت شبکه بیسیم را شبیهسازی کنید، ممکن است تشخیص دهید که به «یک» نیاز دارید
پیاده سازی دقیق در سطح MAC از مشخصات 802.11 و [...] نه چندان کند
مدل سطح PHY با مشخصات 802.11a.''
پس از انجام این کار، می توان یک مدل انتزاعی از سیستم هدف ایجاد کرد. این هست
معمولاً تمرینی برای مدیریت معاوضه بین پیچیدگی و نیازهای منابع است
و دقت فرآیند توسعه یک مدل انتزاعی نامیده شده است مدل
صلاحیت در ادبیات در مورد پروتکل TCP، این فرآیند منجر به a
طراحی برای مجموعه ای از اشیا، تعاملات و رفتارهایی که به طور کامل اجرا می شود
RFC 793 اینچ ns-3. در مورد کارت بی سیم، این فرآیند منجر به تعدادی از
مبادلاتی برای شبیه سازی لایه فیزیکی و طراحی یک دستگاه شبکه
و کانال برای ns-3 به همراه اشیاء، تعاملات و رفتارهای مورد نظر.
این مدل انتزاعی سپس به یک توسعه داده می شود ns-3 مدلی که چکیده را پیاده سازی می کند
مدل به عنوان یک برنامه کامپیوتری فرآیند موافقت اجرا با
مدل انتزاعی نامیده می شود مدل تایید در ادبیات
روند تا کنون حلقه باز است. آنچه باقی می ماند این است که تعیین کنیم که یک ns-3 داده شده است
مدل ارتباطی با واقعیت دارد -- که یک مدل نمایش دقیقی از آن است
یک سیستم واقعی، چه یک فرآیند منطقی یا یک موجود فیزیکی.
اگر قرار باشد از یک مدل شبیهسازی برای پیشبینی چگونگی پیشبینی برخی از سیستمهای واقعی استفاده شود
برای رفتار کردن، باید دلیلی برای باور کردن نتایج شما وجود داشته باشد - یعنی آیا می توان به آن اعتماد کرد
یک استنتاج از مدل به یک پیشبینی صحیح برای سیستم واقعی تبدیل میشود.
فرآیند توافق رفتار مدل ns-3 با سیستم هدف مورد نظر
رفتاری که توسط فرآیند صلاحیت مدل تعریف می شود نامیده می شود مدل اعتبار سنجی در
ادبیات. در مورد پیاده سازی TCP، ممکن است بخواهید رفتار آن را با هم مقایسه کنید
مدل ns-3 TCP خود را به برخی از پیاده سازی مرجع به منظور اعتبارسنجی مدل شما. که در
در مورد شبیه سازی لایه فیزیکی بی سیم، ممکن است بخواهید رفتار آن را با هم مقایسه کنید
مدل شما به سخت افزار واقعی در یک محیط کنترل شده،
La ns-3 محیط تست ابزارهایی را فراهم می کند تا هم اعتبارسنجی مدل و هم
آزمایش، و انتشار نتایج اعتبار سنجی را تشویق می کند.
نیرومندی
استحکام کیفیت توانایی تحمل تنش ها یا تغییرات محیطی است.
ورودی ها یا محاسبات، و غیره. یک سیستم یا طراحی "محکم" است اگر بتواند با چنین مواردی مقابله کند.
با حداقل از دست دادن عملکرد تغییر می کند.
این نوع تست معمولا با تمرکز خاصی انجام می شود. به عنوان مثال، سیستم به عنوان
یک کل را می توان روی بسیاری از پیکربندی های مختلف سیستم اجرا کرد تا نشان دهد که می تواند
در تعداد زیادی از محیط ها به درستی عمل کند.
سیستم همچنین می تواند با عملکرد نزدیک یا فراتر از ظرفیت با تولید تحت فشار قرار گیرد
یا شبیه سازی فرسودگی منابع در انواع مختلف. این ژانر تست نامیده می شود
''تست استرس.''
سیستم و اجزای آن ممکن است در معرض به اصطلاح "آزمایش های تمیز" قرار گیرند که نشان می دهد
یک نتیجه مثبت - این است که سیستم در پاسخ به یک بزرگ به درستی عمل می کند
تنوع تنظیمات مورد انتظار
سیستم و اجزای آن نیز ممکن است در معرض "آزمایش های کثیف" قرار گیرند که ورودی ها را ارائه می دهند
خارج از محدوده مورد انتظار به عنوان مثال، اگر یک ماژول انتظار یک رشته با پایانه صفر را داشته باشد
نمایش یک عدد صحیح، یک تست کثیف ممکن است یک رشته تصادفی نامحدود ارائه دهد
کاراکترها برای تأیید اینکه سیستم در نتیجه این ورودی غیرمنتظره خراب نمی شود.
متأسفانه، شناسایی چنین ورودی "کثیفی" و انجام اقدامات پیشگیرانه برای اطمینان از
سیستم به طور فاجعهباری شکست نمیخورد، میتواند به مقدار زیادی سربار توسعه نیاز داشته باشد.
به منظور کاهش زمان توسعه، تصمیمی در اوایل پروژه گرفته شد
میزان اعتبار سنجی پارامتر و رسیدگی به خطا را به حداقل برسانید ns-3 پایگاه کد. برای
به همین دلیل، ما زمان زیادی را برای آزمایش های کثیف صرف نمی کنیم - فقط این آزمایش ها را آشکار می کند
نتایج تصمیم طراحی که می دانیم گرفته ایم.
ما می خواهیم این را نشان دهیم ns-3 نرم افزار در برخی از شرایط کار می کند. ما
چند تعریف را قرض بگیرید تا این موضوع را کمی محدود کنید. این دامنه of قابلیت اجرا is
مجموعه ای از شرایط تجویز شده که مدل برای آنها آزمایش شده است، با آن مقایسه شده است
واقعیت را تا حد ممکن، و برای استفاده مناسب ارزیابی می شود. را محدوده of دقت است
توافق بین مدل کامپیوتری و واقعیت در یک حوزه کاربردی
La ns-3 محیط تست ابزارهایی را برای تنظیم و اجرای تست فراهم می کند
محیط ها را روی سیستم های متعدد (buildbot) و کلاس هایی را برای تشویق تمیز کردن ارائه می دهد
آزمایش هایی برای تأیید عملکرد سیستم در "دامنه کاربرد" مورد انتظار
و "محدوده دقت."
مجری
بسیار خوب، "نمایشگر" یک کلمه واقعی انگلیسی نیست. با این حال، این یک نوشناسی بسیار مختصر است
که اغلب برای توصیف آنچه می خواهیم استفاده می شود ns-3 to be: قدرتمند و به اندازه کافی سریع برای
کار را انجام دهید
این واقعاً در مورد موضوع گسترده تست عملکرد نرم افزار است. یکی از کلیدها
کارهایی که انجام می شود مقایسه دو سیستم برای یافتن عملکرد بهتر است (ر
معیارها). از این برای نشان دادن اینکه مثلاً ns-3 می تواند یک نوع اساسی را انجام دهد
شبیه سازی حداقل به سرعت یک ابزار رقیب، یا می توان برای شناسایی بخش هایی از آن استفاده کرد
سیستمی که عملکرد بدی دارد
در ns-3 چارچوب تست، ما برای زمان بندی انواع مختلف تست ها پشتیبانی می کنیم.
قابلیت نگهداری
یک محصول نرم افزاری باید قابل نگهداری باشد. این، دوباره، یک بیانیه بسیار گسترده است، اما الف
چارچوب تست می تواند به انجام کار کمک کند. هنگامی که یک مدل توسعه یافته، اعتبار سنجی و
تأیید شده، میتوانیم مجموعه آزمایشهایی را برای اطمینان از کل سیستم بارها و بارها اجرا کنیم
که در طول عمر خود معتبر و تأیید شده است.
هنگامی که یک ویژگی پس از نوعی تغییر در سیستم، عملکرد آن طور که در نظر گرفته شده است متوقف می شود
یکپارچه، به طور کلی a نامیده می شود رگرسیون. در اصل اصطلاح رگرسیون بود
به تغییری اطلاق می شود که باعث می شود یک باگ قبلاً رفع شده دوباره ظاهر شود، اما این اصطلاح وجود دارد
برای توصیف هر نوع تغییری که عملکرد موجود را می شکند تکامل یافته است. بسیاری وجود دارد
انواع رگرسیون هایی که ممکن است در عمل رخ دهد.
A محلی رگرسیون تغییری است که در آن تغییر مستقیماً بر مؤلفه تغییر یافته تأثیر می گذارد. برای
به عنوان مثال، اگر یک مؤلفه برای تخصیص و آزادسازی حافظه اصلاح شده باشد، اما نشانگرهای کهنه هستند
استفاده می شود، خود مؤلفه خراب می شود.
A دور رگرسیون یکی از مواردی است که در آن تغییر به یک جزء، عملکرد را به هم می زند
جزء دیگر این نشان دهنده نقض یک امر ضمنی اما احتمالاً ناشناخته است
قرارداد بین اجزا
An افشا رگرسیون وضعیتی است که در آن یک باگ از قبل موجود ایجاد می کند
که هیچ تاثیری نداشت به طور ناگهانی در سیستم آشکار می شود. این ممکن است به سادگی ورزش باشد
یک مسیر کد برای اولین بار
A کارایی رگرسیون یکی از مواردی است که باعث می شود الزامات عملکرد سیستم به
نقض شود. به عنوان مثال، انجام برخی کارها در یک عملکرد سطح پایین که ممکن است تکرار شود
تعداد زیادی بار ممکن است به طور ناگهانی سیستم را از منظرهای خاصی غیر قابل استفاده کند.
La ns-3 چارچوب تست ابزارهایی را برای خودکارسازی فرآیند مورد استفاده برای اعتبار سنجی و
برای کمک به شناسایی سریع رگرسیونهای احتمالی، کد را در مجموعههای آزمایشی شبانه تأیید کنید.
تست چارچوب
ns-3 از یک موتور هسته شبیه سازی، مجموعه ای از مدل ها، برنامه های نمونه و تست ها تشکیل شده است.
با گذشت زمان، مشارکتکنندگان جدید مدلها، آزمایشها و نمونههایی را ارائه میکنند. یک برنامه تست پایتون
test.py به عنوان مدیر اجرای آزمون عمل می کند. test.py می تواند کد تست و نمونه ها را اجرا کند
به دنبال رگرسیون بگردید، می تواند نتایج را به تعدادی فرم خروجی بدهد، و می تواند کد را مدیریت کند
ابزارهای تحلیل پوشش در بالای این لایه لایه می کنیم Buildbots که ساخت خودکار هستند
ربات هایی که با اجرای چارچوب تست بر روی سیستم های مختلف تست استحکام را انجام می دهند
و با گزینه های مختلف پیکربندی.
BuildBots
در بالاترین سطح تست ns-3، ربات های ساخت (build robots) قرار دارند. اگر شما
ناآشنا با این سیستم نگاه کنید http://djmitche.github.com/buildbot/docs/0.7.11/.
این یک سیستم خودکار منبع باز است که اجازه می دهد ns-3 هر کدام دوباره ساخته و آزمایش شوند
زمان چیزی تغییر کرده است با اجرای buildbot ها بر روی تعدادی از سیستم های مختلف ما
می تواند اطمینان حاصل کند ns-3 بر روی تمام سیستم های پشتیبانی شده خود به درستی ساخته و اجرا می شود.
کاربران (و توسعه دهندگان) معمولاً با سیستم buildbot به غیر از to تعامل ندارند
پیام های آن را در مورد نتایج آزمایش بخوانید. اگر نقصی در یکی از موارد تشخیص داده شود
کارهای ساخت و آزمایش خودکار، buildbot یک ایمیل به آن ارسال می کند توسعه دهندگان ns
لیست پستی این ایمیل چیزی شبیه به آن خواهد بود
در URL جزئیات کامل نشان داده شده در ایمیل، می توانید کلمه کلیدی را جستجو کنید ناموفق و
انتخاب کنید stdio لینک مرحله مربوطه برای دیدن دلیل شکست.
buildbot در صورت عدم وجود خطا کار خود را بی سر و صدا انجام می دهد و سیستم دچار مشکل می شود
هر روز چرخه هایی را بسازید و آزمایش کنید تا مطمئن شوید که همه چیز خوب است.
test.py
بیلد بات ها از یک برنامه پایتون استفاده می کنند، test.py، که مسئول اجرای همه موارد است
آزمایشها و جمعآوری گزارشهای حاصله به شکلی قابل خواندن برای انسان. این برنامه است
همچنین برای استفاده کاربران و توسعه دهندگان نیز در دسترس است.
test.py بسیار انعطاف پذیر است و به کاربر اجازه می دهد تعداد و نوع تست ها را مشخص کند
اجرا کن؛ و همچنین مقدار و نوع خروجی برای تولید.
قبل از دویدن test.py، مطمئن شوید که نمونه ها و تست های ns3 با انجام دادن ساخته شده اند
به شرح زیر
$ ./waf پیکربندی --enable-examples --enable-tests
$./waf
به طور پیش فرض، test.py تمام تست های موجود را اجرا می کند و وضعیت را به صورت بسیار مختصر گزارش می کند
فرم. اجرای دستور
$ ./test.py
منجر به تعدادی از PASS, FAIL, تصادف در 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.939s)
FAIL: TestSuite ns3-wifi-propagation-loss-models
PASS: TestSuite object-name-service
PASS: TestSuite pcap-file-object
PASS: TestSuite ns3-tcp-cwnd
...
PASS: TestSuite ns3-tcp-Interoperability
PASS: نمونه csma-broadcast
PASS: نمونه csma-multicast
این حالت برای استفاده توسط کاربرانی در نظر گرفته شده است که علاقه مند به تعیین اینکه آیا آنها هستند یا خیر
توزیع به درستی کار می کند، و توسط توسعه دهندگانی که علاقه مند به تعیین این هستند
تغییراتی که انجام داده اند باعث هر گونه قهقرایی شده است.
تعدادی گزینه برای کنترل رفتار وجود دارد test.py. اگر بدوید
test.py --کمک شما باید یک خلاصه دستوری مانند:
استفاده: test.py [گزینهها]
گزینه های ارسال:
-h ، - کمک کنید این پیام راهنما را نشان دهید و خارج شوید
-b BUILDPATH، --buildpath=BUILDPATH
مسیری را که ns-3 در آن ساخته شده است را مشخص کنید (به طور پیش فرض در
ساخت دایرکتوری برای نوع فعلی)
-c KIND، --constrain=KIND
آزمایش کننده را با نوع آزمون محدود کنید
-e EXAMPLE، --example=EXAMPLE
یک مثال واحد برای اجرا مشخص کنید (هیچ مسیر نسبی وجود ندارد
مورد نیاز)
-g، --grind مجموعه های آزمایشی و نمونه ها را با استفاده از valgrind اجرا کنید
-k، --kinds انواع تست های موجود را چاپ می کند
-l، --list لیست تست های شناخته شده را چاپ می کند
-m، --multiple گزارش خرابی های متعدد از مجموعه های تست و تست
موارد
-n، --nowaf قبل از شروع آزمایش، waf را اجرا نکنید
-p PYEXAMPLE، --pyexample=PYEXAMPLE
یک مثال پایتون را برای اجرا مشخص کنید (با نسبی
مسیر)
-r، --retain تمام فایل های موقت را حفظ می کند (که معمولاً هستند
حذف شده)
-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
منجر به اجرای آن مجموعه آزمایشی می شود.
FAIL: TestSuite ns3-wifi-propagation-loss-models
برای یافتن اطلاعات دقیق در مورد خرابی، باید نوع خروجی را مشخص کرد
دلخواه. به عنوان مثال، اکثر مردم احتمالاً به یک فایل متنی علاقه مند هستند:
$ ./test.py --suite=ns3-wifi-propagation-loss-models --text=results.txt
این باعث می شود که آن مجموعه آزمایشی با وضعیت تست در آن نوشته شده اجرا شود
فایل ''results.txt''.
شما باید چیزی شبیه به زیر در آن فایل پیدا کنید
FAIL: مجموعه آزمایشی "ns3-wifi-propagation-loss-models" (0.02 کاربر واقعی 0.01 سیستم 0.00)
PASS: مورد تست "بررسی ... فریس ... مدل ..." (0.01 کاربر واقعی 0.00 سیستم 0.00)
FAIL: مورد آزمایشی "بررسی ... فاصله ورود ... مدل" (0.01 کاربر واقعی 0.01 سیستم 0.00)
جزئیات:
پیام: مقدار SNR غیرمنتظره ای دریافت کرد
شرایط: [توضیح طولانی از آنچه واقعا شکست خورده است]
واقعی: 176.395
محدودیت: 176.407 + 0.0005
فایل: ../src/test/ns3wifi/propagation-loss-models-test-suite.cc
خط: 360
توجه داشته باشید که مجموعه تست از دو مورد تست تشکیل شده است. اولین مورد آزمایشی بررسی شد
مدل تلفات انتشار فریس و تصویب شد. دومین مورد آزمایشی در بررسی Log ناموفق بود
مدل انتشار از راه دور در این مورد، SNR 176.395 پیدا شد، و آزمایش
انتظار می رود مقدار 176.407 صحیح تا سه رقم اعشار باشد. فایلی که پیاده سازی شد
تست شکست و همچنین خط کدی که باعث شکست شده است فهرست شده است.
در صورت تمایل، می توانید به همین راحتی یک فایل HTML با استفاده از آن بنویسید --html انتخاب
همانطور که در بالا توضیح داده شد.
معمولاً یک کاربر پس از دانلود حداقل یک بار تمام تست ها را اجرا می کند ns-3 تا اطمینان حاصل شود که
محیط او به درستی ساخته شده است و نتایج درستی ایجاد می کند
با توجه به مجموعه های آزمایشی توسعهدهندگان معمولاً مجموعههای آزمایشی را قبل از و اجرا میکنند
پس از ایجاد تغییر برای اطمینان از عدم ایجاد رگرسیون با خود
تغییر می کند. در این مورد، توسعه دهندگان ممکن است نخواهند همه آزمایش ها را اجرا کنند، بلکه فقط یک زیر مجموعه را اجرا کنند. برای
به عنوان مثال، توسعه دهنده ممکن است فقط بخواهد تست های واحد را به صورت دوره ای در حین ساخت اجرا کند
به یک مخزن تغییر می کند. در این مورد، test.py می توان گفت برای محدود کردن انواع
تست هایی که برای یک کلاس خاص از آزمون ها اجرا می شوند. دستور زیر فقط نتیجه خواهد داد
تست های واحد در حال اجرا:
$ ./test.py --constrain=unit
به طور مشابه، دستور زیر فقط منجر به اجرای نمونه آزمایش دود می شود:
$ ./test.py --constrain=unit
برای مشاهده فهرستی سریع از انواع محدودیتهای قانونی، میتوانید درخواست کنید تا فهرست شوند.
دستور زیر
$ ./test.py --kinds
منجر به نمایش لیست زیر می شود:
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.939s) Waf: ورود به فهرست '/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build'
bvt: آزمایشهای تأیید ساخت (برای دیدن اینکه آیا ساخت با موفقیت انجام شده است)
هسته: اجرای تمام تست های مبتنی بر TestSuite (بدون مثال)
مثال: مثالها (برای دیدن اینکه آیا برنامههای نمونه با موفقیت اجرا میشوند)
عملکرد: تست های عملکرد (بررسی کنید که آیا سیستم به همان سرعتی که انتظار می رود است یا خیر)
سیستم: تست های سیستم (ماژول ها را برای بررسی ادغام ماژول ها در بر می گیرد)
واحد: تست های واحد (در ماژول ها برای بررسی عملکرد اولیه)
هر یک از این نوع آزمون ها را می توان به عنوان یک محدودیت با استفاده از --محدودیت گزینه.
برای مشاهده فهرستی سریع از همه مجموعههای آزمایشی موجود، میتوانید از آنها درخواست کنید
ذکر شده. دستور زیر،
$ ./test.py --list
منجر به نمایش لیستی از مجموعه آزمایشی می شود که شبیه به
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.939s)
هیستوگرام
تداخل ns3-wifi
ns3-tcp-cwnd
قابلیت همکاری ns3-tcp
نمونه
دستگاه-مش-شعله
devices-mesh-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
می توان یک برنامه نمونه پایتون را با استفاده از --pyexample گزینه. توجه داشته باشید که
مسیر نسبی برای مثال باید درج شود و مثالهای پایتون به آنها نیاز دارند
پسوندها ورود
$ ./test.py --pyexample=examples/tutorial/first.py
منجر به اجرای آن نمونه واحد می شود.
PASS: نمونههای مثال/آموزش/first.py
از آنجایی که نمونههای پایتون ساخته نمیشوند، نیازی به تعیین دایرکتوری که در آن ns-3 وجود دارد نیست
برای اجرای آنها ساخته شده است.
معمولاً وقتی برنامه های نمونه اجرا می شوند، مقدار زیادی از داده های فایل ردیابی را می نویسند.
این معمولاً در دایرکتوری پایه توزیع ذخیره می شود (به عنوان مثال،
/home/user/ns-3-dev). چه زمانی test.py یک مثال را اجرا می کند، واقعاً کاملاً بی خیال است
با فایل های ردیابی فقط می خواهد تعیین کند که آیا می توان مثال را ساخت و اجرا کرد
بدون اشکال. از آنجایی که این مورد است، فایل های ردیابی در یک نوشته می شوند
/tmp/unchecked-traces فهرست راهنما. اگر مثال بالا را اجرا کنید، باید بتوانید پیدا کنید
مرتبط udp-echo.tr و udp-echo-n-1.pcap فایل های آنجا
لیست نمونه های موجود با محتویات دایرکتوری ''examples'' در تعریف می شود
توزیع. اگر نمونه ای را برای اجرا با استفاده از --مثال گزینه،
test.py هیچ تلاشی برای تصمیم گیری در مورد اینکه آیا مثال پیکربندی شده است یا خیر، انجام نخواهد داد
فقط سعی می کند آن را اجرا کند و نتیجه تلاش را گزارش کند.
چه زمانی test.py اجرا می شود، به طور پیش فرض ابتدا مطمئن می شود که سیستم به طور کامل انجام شده است
ساخته شده. این را می توان با انتخاب شکست داد --نواف گزینه.
$ ./test.py --list --nowaf
منجر به نمایش لیستی از مجموعه های آزمایشی ساخته شده در حال حاضر می شود، مشابه موارد زیر:
ns3-wifi-propagation-loss-models
ns3-tcp-cwnd
قابلیت همکاری ns3-tcp
pcap-file-object
شی-نام-سرویس
مولدهای اعداد تصادفی
به عدم وجود آن توجه کنید وف ساخت پیام ها
test.py همچنین از اجرای مجموعه های آزمایشی و نمونه ها تحت valgrind پشتیبانی می کند. والگریند یک است
برنامه انعطاف پذیر برای اشکال زدایی و پروفایل فایل های اجرایی لینوکس. به طور پیش فرض، valgrind اجرا می شود
ابزاری به نام memcheck که طیف وسیعی از عملکردهای بررسی حافظه از جمله
شناسایی دسترسی ها به حافظه اولیه، استفاده نادرست از حافظه اختصاص داده شده (آزادی مضاعف،
دسترسی پس از رایگان و غیره) و شناسایی نشت حافظه. این را می توان با استفاده از
-- آسیاب کردن گزینه.
$ ./test.py --grind
همانطور که اجرا می شود، test.py و برنامه هایی که به طور غیرمستقیم اجرا می شود، تعداد زیادی از آنها را تولید می کنند
فایل های موقت معمولا محتوای این فایل ها جالب نیست، البته در برخی
در مواردی، مشاهده این فایل ها می تواند مفید باشد (برای اهداف اشکال زدایی). test.py فراهم می کند
--حفظ گزینه ای که باعث می شود این فایل های موقت پس از اجرا نگهداری شوند
تکمیل شد. فایل ها در دایرکتوری به نام ذخیره می شوند خروجی آزمایشی تحت یک زیر شاخه
نامگذاری شده بر اساس زمان هماهنگ جهانی فعلی (همچنین به عنوان میانگین گرینویچ شناخته می شود
زمان).
$ ./test.py --retain
در نهایت، test.py فراهم می کند -- پرحرف گزینه ای که حجم زیادی از اطلاعات را چاپ می کند
در مورد پیشرفت آن انتظار نمی رود که این بسیار مفید باشد مگر اینکه وجود داشته باشد
یک خطا. در این صورت می توانید به خروجی استاندارد و خطای استاندارد دسترسی پیدا کنید
با اجرای مجموعه های آزمایشی و نمونه ها گزارش شده است. پرمخاطب را به روش زیر انتخاب کنید:
$ ./test.py ---verbose
همه این گزینه ها را می توان مخلوط و مطابقت داد. به عنوان مثال، برای اجرای تمام هسته های ns-3
مجموعه تست تحت valgrind، در حالت کلامی، در حالی که یک فایل خروجی HTML، یک
انجام خواهد داد:
$ ./test.py --verbose --grind --constrain=core --html=results.html
تست تاکسونومی
همانطور که در بالا ذکر شد، آزمون ها در تعدادی طبقه بندی کلی تعریف شده به گروه بندی می شوند
به کاربران اجازه می دهد تا به طور انتخابی آزمایش هایی را برای رسیدگی به انواع مختلف آزمایشی که نیاز دارند اجرا کنند
که باید انجام شود.
· ساخت تست های تایید
· آزمون های واحد
· تست های سیستم
· مثال ها
· تست های عملکرد
BuildVerification Tests
اینها تست های نسبتا ساده ای هستند که همراه با توزیع ساخته شده و مورد استفاده قرار می گیرند
تا مطمئن شوید که ساخت تا حد زیادی کار می کند. آزمایشات واحد فعلی ما در
فایل های منبع کدی که آزمایش می کنند و در ماژول های ns-3 تعبیه شده اند. و بنابراین مناسب است
شرح BVT ها 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 که به عنوان پاسخ های مورد انتظار TCP مورد آزمایش ns-3 استفاده می شوند
به یک محرک تولید شده توسط NSC TCP که به عنوان یک پیاده سازی "خوب شناخته شده" استفاده می شود.
مثال ها
نمونه ها توسط فریمورک تست می شوند تا مطمئن شوند که ساخته شده اند و اجرا خواهند شد. هیچ چیز نیست
بررسی شد، و در حال حاضر فایلهای pcap فقط در آن نوشته شدهاند دایرکتوری / tmp دور انداخته شود. اگر
نمونه ها اجرا می شوند (تصادف نمی شوند) آنها این تست دود را با موفقیت پشت سر می گذارند.
عملکرد تست
تست های عملکردی آنهایی هستند که بخش خاصی از سیستم را اعمال و تعیین می کنند
در صورتی که آزمایش ها در زمان معقولی به اتمام رسیده باشد.
محل دویدن و پیاده روی تست
آزمون ها معمولاً با استفاده از سطح بالا اجرا می شوند test.py برنامه برای دریافت لیستی از
گزینه های خط فرمان موجود، اجرا کنید test.py --کمک
برنامه تست test.py هم تست ها و هم نمونه هایی که به آن اضافه شده اند را اجرا می کند
لیست برای بررسی تفاوت بین تست ها و مثال ها به شرح زیر است. تست ها
به طور کلی بررسی کنید که خروجی یا رویدادهای شبیه سازی خاص با رفتار مورد انتظار مطابقت داشته باشد.
در مقابل، خروجی نمونهها بررسی نمیشود و برنامه آزمایشی صرفاً آن را بررسی میکند
از وضعیت برنامه نمونه خارج شوید تا مطمئن شوید که بدون خطا اجرا می شود.
به طور خلاصه، برای اجرای تمام تستها، ابتدا باید تستها را در مرحله پیکربندی پیکربندی کرد و
همچنین (اختیاری) نمونه هایی در صورتی که نمونه هایی بررسی شوند:
$ ./waf --configure --enable-examples --enable-tests
سپس، ns-3 را بسازید و پس از ساخته شدن، فقط اجرا کنید test.py. test.py -h یک عدد نشان خواهد داد
از گزینه های پیکربندی که رفتار test.py را تغییر می دهند.
برنامه test.py برای آزمایشها و مثالهای C++، یک برنامه سطح پایینتر C++ را فراخوانی میکند
دونده آزمون برای اجرای آزمایشات در واقع همانطور که در زیر بحث شد، این دونده آزمون می تواند یک
روشی مفید برای اشکال زدایی تست ها
اشکال زدایی تست
اشکال زدایی برنامه های آزمایشی به بهترین وجه با اجرای آزمون اجرا کننده سطح پایین انجام می شود
برنامه آزمون اجراکننده پل ارتباطی بین کدهای عمومی پایتون به آن است ns-3 کد این است
نوشته شده در C++ و از فرآیند کشف خودکار تست در ns-3 کد برای پیدا کردن و
اجازه اجرای تمام تست های مختلف را می دهد.
دلیل اصلی چرا test.py برای اشکال زدایی مناسب نیست زیرا مجاز نیست
ورود به سیستم با استفاده از NS_LOG متغیر محیطی هنگام اجرا test.py. این
محدودیت برای فایل اجرایی آزمون اجرا کننده اعمال نمی شود. از این رو، اگر می خواهید ورود به سیستم را ببینید
خروجی از تست های شما، شما باید آنها را با استفاده از test-runner مستقیما اجرا کنید.
برای اجرای test-runner، آن را مانند هر فایل اجرایی ns-3 دیگری اجرا می کنید - با استفاده از
واف. برای دریافت لیستی از گزینه های موجود، می توانید تایپ کنید:
$ ./waf --run "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.353s)
--assert: اگر خطایی تشخیص داده شد، به تستها بگویید که segfault (مانند assert).
--basedir=dir: دایرکتوری پایه (جایی که می توان src را پیدا کرد) را روی ''dir'' تنظیم کنید
--tempdir=dir: دایرکتوری موقت (محل یافتن فایل های داده) را روی ''dir'' تنظیم کنید
--constrain=test-type: بررسی های محدود برای آزمایش مجموعه هایی از نوع "test-type"
--help: این پیام را چاپ کنید
--kinds: همه انواع تست های موجود را فهرست کنید
--list: فهرست همه مجموعه های آزمایشی (به صورت اختیاری با نوع آزمون محدود می شود)
--out=file-name: فایل خروجی وضعیت تست را روی "file-name" تنظیم کنید
--suite=suite-name: مجموعه آزمایشی با نام "suite-name" را اجرا کنید
--verbose: پیامها را در مجموعههای تست اجرا روشن کنید
تعدادی چیز در دسترس شماست که اگر داشته باشید برایتان آشنا خواهد بود
نگاه test.py. این را باید انتظار داشت زیرا اجرای آزمایشی فقط یک رابط است
میان test.py و ns-3. ممکن است متوجه شوید که دستورات مربوط به مثال در اینجا گم شده اند.
دلیلش این است که نمونه ها واقعاً نیستند ns-3 آزمایشات test.py آنها را طوری اجرا می کند که انگار هستند
برای ارائه یک محیط تست یکپارچه، اما آنها واقعاً کاملاً متفاوت هستند و نیستند
برای یافتن اینجا
اولین گزینه جدیدی که در اینجا ظاهر می شود، اما در test.py نیست -- ادعا گزینه. این
این گزینه هنگام اشکال زدایی یک مورد آزمایشی هنگام اجرا تحت یک دیباگر مانند مفید است gdbاست. وقتی که
انتخاب شده، این گزینه به پرونده آزمایشی زیربنایی میگوید که باعث نقض بخشبندی شود اگر
یک خطا شناسایی می شود این اثر جانبی خوبی دارد که باعث می شود اجرای برنامه متوقف شود
(شکستن به دیباگر) هنگامی که یک خطا تشخیص داده شد. اگر از gdb استفاده می کنید، می توانید استفاده کنید
این گزینه چیزی شبیه به
$ ./پوسته waf
$ cd build/debug/utils
$ gdb تست دونده
$ run --suite=global-value --assert
اگر یک خطا در مجموعه آزمایشی با مقدار جهانی یافت شود، یک خطای segfault ایجاد می شود
و دیباگر (سطح منبع) در قسمت متوقف می شود NS_TEST_ASSERT_MSG که تشخیص داد
خطا.
گزینه جدید دیگری که در اینجا ظاهر می شود گزینه است -مستقر گزینه. معلوم می شود که برخی
ممکن است نیاز باشد که تست ها به دایرکتوری منبع آن ارجاع دهند ns-3 توزیع برای یافتن محلی
داده ها، بنابراین همیشه برای اجرای یک آزمایش به یک دایرکتوری پایه نیاز است.
اگر تستی را از test.py اجرا کنید، برنامه پایتون گزینه basedir را برای آن ارائه خواهد کرد
شما. برای اجرای یکی از تست ها به طور مستقیم از آزمون-راننده با استفاده از واف، شما نیاز دارید
مجموعه آزمایشی را برای اجرا به همراه دایرکتوری پایه مشخص کنید. بنابراین می توانید از پوسته استفاده کنید
و انجام دهید:
$ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object"
به علامت نقل قول "به عقب" روی pwd فرمان
اگر مجموعه آزمایشی را بدون اشکالزدا اجرا میکنید، یادآوری آن میتواند بسیار دردناک باشد
و به طور مداوم مسیر مطلق دایرکتوری پایه توزیع را تایپ کنید. به خاطر اینکه
این، اگر baseir را حذف کنید، آزمونکننده سعی میکند یکی را برای شما بیابد. آی تی
در دایرکتوری کاری فعلی شروع می شود و درخت دایرکتوری را به دنبال a بالا می برد
فایل دایرکتوری با فایل های نامگذاری شده نسخه و مجوز. اگر یکی را پیدا کند، آن را فرض می کند
باید baseir باشد و آن را برای شما فراهم کند.
تست تولید
بسیاری از مجموعههای آزمایشی نیاز به نوشتن فایلهای موقت (مانند فایلهای pcap) در فرآیند دارند
اجرای تست ها سپس تست ها به یک دایرکتوری موقت برای نوشتن نیاز دارند. پایتون
ابزار تست (test.py) یک فایل موقت را به طور خودکار ارائه می کند، اما اگر به صورت مستقل اجرا شود
این دایرکتوری موقت باید ارائه شود. همانطور که در مورد basedir، می تواند باشد
مزاحم به طور مداوم باید ارائه a -- tempdir، بنابراین دونده آزمون یکی را رقم خواهد زد
اگر یکی را ارائه نکنید برای شما ابتدا به دنبال متغیرهای محیطی با نام می گردد TMP
و TEMP و از آن ها استفاده می کند. اگر هیچ کدام TMP نه TEMP تعریف می شود آن را انتخاب می کند دایرکتوری / tmp. کد
سپس روی یک شناسه برچسب میزند که نشان میدهد چه چیزی دایرکتوری را ایجاد کرده است (ns-3) و سپس زمان
(hh.mm.ss) به دنبال آن یک عدد تصادفی بزرگ. اجرای آزمایشی یک دایرکتوری از آن ایجاد می کند
نامی که به عنوان دایرکتوری موقت استفاده می شود. فایل های موقت سپس به دایرکتوری که
چیزی شبیه نامگذاری خواهد شد
/tmp/ns-3.10.25.37.61537845
زمان به عنوان یک اشاره ارائه شده است تا بتوانید نسبتاً به راحتی آنچه را بازسازی کنید
دایرکتوری مورد استفاده قرار می گیرد اگر شما نیاز دارید به عقب برگردید و به فایل هایی که در آن قرار داده شده اند نگاه کنید
دایرکتوری.
دسته دیگر خروجی، خروجی آزمایشی مانند ردیابی pcap است که برای مقایسه با آنها تولید می شود
خروجی مرجع برنامه آزمایشی معمولاً این موارد را بعد از همه مجموعههای آزمایشی حذف میکند
اجرا کن. برای غیرفعال کردن حذف خروجی تست، اجرا کنید test.py با گزینه "حفظ":
$ ./test.py -r
و خروجی تست را می توان در خروجی آزمایشی/ دایرکتوری.
گزارش of آزمون شکست
هنگامی که یک مجموعه آزمایشی را با استفاده از test-runner اجرا می کنید، به طور پیش فرض تست را بی سر و صدا اجرا می کند.
تنها نشانه ای که نشان می دهد قبولی آزمون را دریافت خواهید کرد غیبت از یک پیام
از جانب واف گفتن اینکه برنامه چیزی غیر از یک کد خروج صفر را برگرداند. برای بدست آوردن
برخی از خروجی های آزمایش، باید یک فایل خروجی را مشخص کنید که آزمایش ها به آن می روند
وضعیت 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 با حالت ''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 کامل، زیرا مجموعههای آزمایشی به گونهای طراحی شدهاند که خروجی آنها به یک Master اضافه شود
فایل وضعیت XML همانطور که در test.py بخش.
اشکال زدایی آزمون دنباله شکست
برای رفع اشکال خرابی های آزمایشی، مانند
CRASH: TestSuite ns3-wifi-interference
شما می توانید از طریق gdb به برنامه زیرین test-runner به صورت زیر دسترسی داشته باشید و سپس آن را بگذرانید
آرگومان "--basedir=`pwd`" اجرا شود (همچنین می توانید آرگومان های دیگری را در صورت نیاز ارسال کنید، اما
Basir حداقل مورد نیاز است):
$ ./waf --command-template="gdb %s" --run "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.380s)
گنو gdb 6.8-debian
حق چاپ (C) 2008 Free Software Foundation, Inc.
L cense GPLv3+: GNU GPL نسخه 3 یا بالاتر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=devices-mesh-dot11s-regression" --run test-runner
طبقه TestRunner
فایل های اجرایی که برنامه های تست اختصاصی را اجرا می کنند از یک کلاس TestRunner استفاده می کنند. این کلاس
ثبت نام و فهرست بندی خودکار آزمون و همچنین راهی برای اجرای آن فراهم می کند
تست های فردی مجموعههای آزمایشی جداگانه از سازندههای جهانی C++ برای اضافه کردن خود به آنها استفاده میکنند
مجموعه ای از مجموعه های آزمایشی که توسط دونده آزمون مدیریت می شود. دونده تست برای فهرست کردن استفاده می شود
تمام تست های موجود و انتخاب یک تست برای اجرا. این یک کلاس کاملاً ساده است
که سه روش ثابت برای ارائه یا افزودن و دریافت مجموعه های آزمایشی به a ارائه می دهد
مجموعه تست ها برای کلاس به داکسیژن مراجعه کنید ns3::TestRunner برای جزئیات بیشتر.
تست سوئیت
همه ns-3 تست ها به مجموعه های تست و موارد تست طبقه بندی می شوند. مجموعه تست یک است
مجموعه ای از موارد آزمایشی که به طور کامل نوع خاصی از عملکرد را اعمال می کند. مانند
در بالا توضیح داده شد، مجموعه های آزمایشی را می توان به عنوان طبقه بندی کرد:
· ساخت تست های تایید
· آزمون های واحد
· تست های سیستم
· مثال ها
· تست های عملکرد
این طبقه بندی از کلاس TestSuite صادر شده است. این کلاس بسیار ساده است،
تنها به عنوان مکانی برای صادرات این نوع و جمع آوری موارد آزمایشی موجود است. از یک کاربر
دیدگاه، برای ایجاد یک TestSuite جدید در سیستم فقط باید یک جدید تعریف کرد
کلاسی که از کلاس به ارث می برد TestSuite و این دو وظیفه را انجام دهد.
کد زیر یک کلاس جدید را تعریف می کند که می تواند توسط آن اجرا شود test.py به عنوان یک آزمون "واحد".
با نام نمایشی، اسم-آزمون-مجموعه-نام من.
کلاس MySuite: عمومی TestSuite
{
عمومی:
MyTestSuite ();
};
MyTestSuite::MyTestSuite ()
: TestSuite ("my-test-suite-name"، UNIT)
{
AddTestCase (MyTestCase جدید)؛
}
MyTestSuite myTestSuite;
کلاس پایه تمام ثبت نام و گزارش مورد نیاز برای خوب بودن را انجام می دهد
شهروند در چارچوب آزمون
تست مورد
تست های فردی با استفاده از یک کلاس TestCase ایجاد می شوند. مدل های رایج برای استفاده از آزمون
مورد شامل «یک مورد آزمایشی برای هر ویژگی» و «یک مورد آزمایشی برای هر روش» است. مخلوط های
ممکن است از این مدل ها استفاده شود.
برای ایجاد یک تست جدید در سیستم، تنها کاری که باید انجام دهید این است که از آن به ارث ببرد
TestCase کلاس پایه، سازنده را نادیده بگیرید تا به نمونه آزمایشی یک نام داده و لغو کنید
la DoRun روش اجرای آزمون
کلاس MyTestCase: عمومی TestCase
{
MyTestCase ();
virtual void DoRun (void);
};
MyTestCase::MyTestCase ()
: TestCase ("برخی از عملکرد را بررسی کنید")
{
}
از درجه اعتبار ساقط
MyTestCase::DoRun (void)
{
NS_TEST_ASSERT_MSG_EQ (درست، درست، "پیام شکست");
}
ابزارگــان
تعدادی ابزار از انواع مختلف وجود دارد که بخشی از آزمایش نیز هستند
چارچوب مثالها شامل یک فایل pcap تعمیم یافته است که برای ذخیره بردارهای آزمایشی مفید است. آ
ظرف عمومی مفید برای ذخیره سازی گذرا بردارهای آزمایش در طول اجرای آزمایش. و
ابزارهایی برای تولید ارائه ها بر اساس نتایج آزمایش اعتبار و تأیید.
این ابزارها در اینجا مستند نیستند، اما برای مثال، لطفاً ببینید که چگونه TCP آزمایش میکند
موجود در src/test/ns3tcp/ از فایل های pcap و خروجی مرجع استفاده کنید.
چگونه به نوشتن تست
هدف اصلی پروژه ns-3 کمک به کاربران برای بهبود اعتبار و
اعتبار نتایج آنها عناصر زیادی برای به دست آوردن مدل های معتبر و
شبیه سازی، و آزمایش یک جزء اصلی است. اگر مدل ها یا نمونه هایی را به آن کمک می کنید
ns-3، ممکن است از شما خواسته شود که کد تست را ارائه دهید. مدل هایی که شما مشارکت می دهید استفاده خواهد شد
برای سالها توسط افراد دیگری که احتمالاً در نگاه اول هیچ ایدهای ندارند
مدل درست است کد تستی که برای مدل خود می نویسید به جلوگیری از آینده کمک می کند
رگرسیون در خروجی و به کاربران آینده در درک راستی آزمایی و
محدودیت های کاربردی مدل های شما
راه های زیادی برای تأیید صحت اجرای یک مدل وجود دارد. در این
در بخش، امیدواریم موارد رایجی را پوشش دهیم که بتوان از آنها به عنوان راهنمای نوشتن جدید استفاده کرد
آزمایشات
نمونه TestSuite اسکلت
هنگام شروع از ابتدا (یعنی عدم اضافه کردن TestCase به TestSuite موجود)، اینها
موارد باید از قبل تصمیم گیری شود:
· مجموعه آزمون چه نام خواهد داشت
· چه نوع آزمایشی خواهد بود (تست تأیید ساخت، تست واحد، تست سیستم یا
آزمون عملکرد)
· جایی که کد آزمایشی در آن قرار می گیرد (چه در یک ماژول ns-3 موجود یا به طور جداگانه در
دایرکتوری src/test/). شما باید فایل wscript را در آن دایرکتوری ویرایش کنید
اگر یک فایل جدید است، کد جدید خود را کامپایل کنید.
برنامه ای به نام src/create-module.py نقطه شروع خوبی است این برنامه می تواند باشد
احضار شده مانند create-module.py روتر برای یک ماژول جدید فرضی به نام روتر. یک بار
اگر این کار را انجام دهید، یک را خواهید دید روتر دایرکتوری و الف test/router-test-suite.cc مجموعه تست
این فایل می تواند نقطه شروعی برای تست اولیه شما باشد. این یک مجموعه تست کاری است،
اگرچه آزمایش های واقعی انجام شده بی اهمیت هستند. آن را در آزمون ماژول خود کپی کنید
دایرکتوری، و جایگزینی جهانی "روتر" را در آن فایل برای چیزی مربوط انجام دهید
به مدلی که می خواهید تست کنید. همچنین می توانید مواردی مانند توضیحات بیشتر را ویرایش کنید
نام مورد آزمایشی
همچنین باید یک بلوک به wscript خود اضافه کنید تا این تست کامپایل شود:
module_test.source = [
"test/router-test-suite.cc"،
]
قبل از اینکه واقعاً شروع به انجام کارهای مفید کنید، ممکن است اجرای آن کمک کند
اسکلت. مطمئن شوید که ns-3 با گزینه "-enable-tests" پیکربندی شده است.
بیایید فرض کنیم که مجموعه آزمایشی جدید شما "روتر" نامیده می شود مانند اینجا:
RouterTestSuite::RouterTestSuite ()
: TestSuite ("روتر"، 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 (واقعی، محدودیت، هزینه، پیام)
استدلال اول واقعی مقدار مورد آزمایش، مقدار دوم است محدود کردن مورد انتظار است
مقدار (یا مقداری که باید در مقابل آن آزمایش شود)، و آخرین آرگومان MSG پیام خطا به است
در صورت عدم موفقیت تست، پرینت بگیرید.
چهار ماکرو اول بالا برای برابری، نابرابری، کمتر یا بیشتر از،
به ترتیب. پنجمین کلان بالا، برابری را آزمایش می کند، اما در یک تحمل خاص.
این نوع برای آزمایش اعداد ممیز شناور برای برابری در برابر یک حد مفید است.
جایی که می خواهید از شکست تست به دلیل خطاهای گرد کردن جلوگیری کنید.
در نهایت، انواعی از موارد فوق وجود دارد که در آن کلمه کلیدی وجود دارد ادعا جایگزین شده است انتظار.
این گونهها بهطور ویژه برای استفاده در روشهای بازگشت (بهویژه تماسهای برگشتی) طراحی شدهاند
خالی. استفاده از آنها را برای تماسهایی که در برنامههای آزمایشی خود استفاده میکنید، رزرو کنید. در غیر این صورت استفاده کنید
la ادعا انواع
چگونه به اضافه کردن an مثال برنامه به la آزمون دنباله
میتوان «تست دود» را انجام داد که نمونهها با موفقیت کامل شوند (بدون
نشت حافظه) با استفاده از examples-to-run.py اسکریپت واقع در دایرکتوری تست ماژول شما.
به طور خلاصه، با گنجاندن نمونه ای از این فایل در دایرکتوری آزمایشی خود، می توانید باعث ایجاد این مشکل شوید
تست runner برای اجرای نمونه های لیست شده. معمولاً بهتر است مطمئن شوید که شما
نمونه هایی را انتخاب کنید که زمان اجرای مناسبی دارند تا تست ها را باتلاق نکنند. دیدن
مثال در src/lte/test/ دایرکتوری.
تست برای بولی نتایج
تست نتایج چه زمانی تصادفی بودن is گرفتار
تست تولید داده ها در برابر a شناخته شده توزیع
ارائه غیر پیش پا افتاده ورودی بردار of داده ها
ذخیره سازی و ارجاع غیر پیش پا افتاده تولید داده ها
ارائه خود را تولید آزمون داده ها
پشتیبــانی
ایجاد a جدید ns-3 مدل
این فصل از طریق فرآیند طراحی یک ns-3 مدل. در بسیاری از موارد تحقیقاتی،
کاربران صرفاً به تطبیق مدلهای موجود راضی نمیشوند، بلکه ممکن است بخواهند این مدل را گسترش دهند
هسته شبیه ساز به روشی جدید. ما از مثال اضافه کردن ErrorModel به a استفاده خواهیم کرد
ساده ns-3 پیوند به عنوان مثال انگیزشی از نحوه برخورد با این مشکل و
از طریق طراحی و اجرا ادامه دهید.
توجه:
مستندات
در اینجا ما بر روند ایجاد مدلهای جدید و ماژولهای جدید و برخی از موارد تمرکز میکنیم
انتخاب های طراحی درگیر برای شفافیت، بحث را به تعویق می اندازیم مکانیک
مستندسازی مدل ها و کد منبع به مستندات فصل.
طرح روش
در نظر بگیرید که چگونه می خواهید کار کند. چه کاری باید انجام دهد به این موارد فکر کنید:
· عملکرد: چه عملکردی باید داشته باشد؟ ویژگی ها یا پیکربندی چیست
در معرض کاربر است؟
· قابلیت استفاده مجدد: دیگران چقدر باید بتوانند از طرح من استفاده مجدد کنند؟ آیا می توانم دوباره از کد استفاده کنم
ns-2 برای شروع؟ چگونه یک کاربر مدل را با بقیه مدل های دیگر ادغام می کند
شبیه سازی؟
· وابستگی ها: چگونه می توانم معرفی وابستگی های خارجی را در کد جدیدم کاهش دهم
تا حد امکان (برای اینکه مدولارتر شود)؟ به عنوان مثال، آیا از هر کدام اجتناب کنم
وابستگی به IPv4 اگر بخواهم توسط IPv6 نیز استفاده شود؟ آیا باید از هر گونه وابستگی اجتناب کنم؟
اصلا روی IP؟
در تماس با ns-3-users or توسعه دهندگان ns اگر سوالی دارید لیست کنید
به ویژه، مهم است که در مورد API عمومی مدل جدید خود فکر کنید و درخواست کنید
بازخورد. همچنین به اطلاع دیگران از کار شما در صورت علاقه کمک می کند
همکاران
مثال: ErrorModel
یک مدل خطا در وجود دارد ns-2. این اجازه می دهد تا بسته ها به یک آبجکت حالت دار ارسال شوند که
بر اساس یک متغیر تصادفی تعیین می کند که آیا بسته خراب است یا خیر. تماس گیرنده می تواند
سپس تصمیم بگیرید که با بسته چه کاری انجام دهید (آن را رها کنید و غیره).
API اصلی مدل خطا تابعی است که یک بسته را به آن ارسال می کند و مقدار بازگشتی آن را می دهد
این تابع یک بولی است که به تماس گیرنده می گوید که آیا خرابی رخ داده است یا خیر. توجه داشته باشید
که بسته به مدل خطا، بافر داده بسته ممکن است خراب باشد یا نباشد.
بیایید این تابع را "IsCorrupt()" بنامیم.
تا کنون، در طراحی خود، ما موارد زیر را داریم:
کلاس ErrorModel
{
عمومی:
/ **
* اگر بسته بهعنوان خطا یا خراب در نظر گرفته شود، \ صحیح است
* \param pkt بسته برای اعمال مدل خطا
*/
bool IsCorrupt (Ptr pkt)؛
};
توجه داشته باشید که ما یک نشانگر const را ارسال نمی کنیم، بنابراین به تابع اجازه می دهیم تا آن را تغییر دهد
بسته اگر () IsCorrupt درست را برگرداند. همه مدل های خطا در واقع بسته را تغییر نمی دهند.
اینکه آیا بافر داده بسته خراب است یا خیر باید مستند شود.
ما همچنین ممکن است نسخه های تخصصی این را بخواهیم، مانند in ns-2، بنابراین اگرچه این نیست
تنها انتخاب طرح برای چندشکلی، ما فرض می کنیم که یک کلاس پایه را زیر کلاس خواهیم گذاشت
ErrorModel برای کلاس های تخصصی، مانند RateErrorModel، ListErrorModel و غیره، مانند
در انجام می شود ns-2.
ممکن است در این مرحله فکر کنید، "چرا IsCorrupt() را به یک روش مجازی تبدیل نکنیم؟ به این معنا که
یک رویکرد؛ دیگری غیرمستقیم کردن تابع غیر مجازی عمومی از طریق a
تابع مجازی خصوصی (این در C++ به عنوان اصطلاح رابط غیر مجازی شناخته می شود و می باشد
تصویب شده در ns-3 کلاس ErrorModel).
بعد، آیا این دستگاه باید وابستگی به IP یا پروتکل های دیگر داشته باشد؟ ما نمی خواهیم
برای ایجاد وابستگی به پروتکل های اینترنت (مدل خطا باید برای
پروتکلهای غیراینترنتی نیز)، بنابراین بعداً آن را در نظر خواهیم داشت.
توجه دیگر این است که چگونه اشیا این مدل خطا را شامل می شوند. ما قرار دادن را متصور هستیم
یک تنظیم کننده صریح در پیاده سازی های خاص NetDevice، به عنوان مثال:
/ **
* یک دریافت ErrorModel را به PointToPointNetDevice ضمیمه کنید.
*
* PointToPointNetDevice ممکن است به صورت اختیاری یک ErrorModel را در خود داشته باشد
* زنجیره دریافت بسته.
*
* @ErrorModel را ببینید
* @param em Ptr به ErrorModel.
*/
void PointToPointNetDevice::SetReceiveErrorModel(Ptr em)؛
باز هم، این تنها گزینه ای نیست که ما داریم (مدل های خطا را می توان به تعداد زیادی ادغام کرد
اشیاء دیگر)، اما مورد استفاده اولیه ما را برآورده می کند، یعنی اجازه دادن به کاربر را مجبور می کند
خطاها در انتقال بسته های موفق در سطح NetDevice.
پس از کمی تفکر و نگاه به موجود ns-2 کد، در اینجا یک نمونه API از یک پایه است
کلاس و زیر کلاس اول که می تواند برای بررسی اولیه ارسال شود:
کلاس ErrorModel
{
عمومی:
ErrorModel ();
مجازی ~ErrorModel ();
bool IsCorrupt (Ptr pkt)؛
void Reset (void);
void Enable (باطل)؛
void غیر فعال کردن (باطل)؛
bool IsEnabled (void) const;
خصوصی:
مجازی Bool DoCorrupt (Ptr pkt) = 0;
خالی مجازی DoReset (void) = 0;
};
enum ErrorUnit
{
EU_BIT،
EU_BYTE،
EU_PKT
};
// تعیین کنید که کدام بسته ها مطابق با یک زیربنای خطا دارند
// توزیع متغیر تصادفی، نرخ خطا و واحد نرخ.
class RateErrorModel: Public ErrorModel
{
عمومی:
RateErrorModel ();
مجازی ~RateErrorModel ();
enum ErrorUnit GetUnit (void) const;
void SetUnit (enum ErrorUnit error_unit);
دو برابر GetRate (باطل) const;
void SetRate (نرخ دو برابر)؛
void SetRandomVariable (const RandomVariable &ranvar);
خصوصی:
مجازی Bool DoCorrupt (Ptr pkt)؛
virtual void DoReset (void);
};
داربست
بیایید بگوییم که شما آماده شروع پیاده سازی هستید. شما یک تصویر نسبتا واضح از
آنچه می خواهید بسازید، و ممکن است برخی از بررسی ها یا پیشنهادات اولیه را از آن درخواست کرده باشید
لیست. یکی از راه های نزدیک شدن به مرحله بعدی (اجرا) ایجاد داربست و
با بلوغ طرح، جزئیات را پر کنید.
این بخش از طریق بسیاری از مراحلی که باید برای تعریف داربست در نظر بگیرید، یا
یک اسکلت غیر کاربردی از آنچه مدل شما در نهایت پیاده سازی خواهد کرد. معمولا خوب است
تمرین کنید که منتظر نمانید تا این جزئیات در انتها یکپارچه شوند، بلکه به جای آن، a
اسکلت مدل خود را در سیستم اولیه و سپس اضافه کردن توابع بعدا یک بار API و
ادغام درست به نظر می رسد.
توجه داشته باشید که می خواهید چند مورد را در ارائه زیر برای مدل خود تغییر دهید
از آنجایی که اگر مدل خطا را کلمه به کلمه دنبال کنید، کدی که تولید می کنید با آن برخورد می کند
مدل خطای موجود موارد زیر فقط یک طرح کلی از نحوه ساخت ErrorModel است
می تواند با مدل های دیگر سازگار شود.
مرور la ns-3 برنامه نویسی سبک سند
در این مرحله، ممکن است بخواهید مکث کنید و آن را بخوانید ns-3 به خصوص سند سبک کدنویسی
اگر قصد دارید کد خود را به پروژه بازگردانید. سبک کدنویسی
سند از صفحه اصلی پروژه پیوند داده شده است: ns-3 برنامه نویسی سبک.
تصمیم بگیرید جایی که in la منبع درخت la مدل باید اقامت داشتن
همه ns-3 کد منبع مدل در دایرکتوری موجود است src /. شما باید کدام را انتخاب کنید
زیرشاخه ای که در آن قرار دارد. اگر به نوعی کد مدل جدیدی است، قرار دادن آن منطقی است
به src / دایرکتوری در جایی، به ویژه برای سهولت ادغام با ساخت
سیستم.
در مورد مدل خطا، بسیار به کلاس بسته مربوط می شود، بنابراین منطقی است
برای پیاده سازی این در src/network/ ماژول که در آن ns-3 بسته ها پیاده سازی می شوند.
واف و متن
ns-3 با استفاده از وف ساخت سیستم شما می خواهید جدید خود را ادغام کنید ns-3 از Waf استفاده می کند
ساخت سیستم شما می خواهید فایل های منبع جدید خود را در این سیستم ادغام کنید. این
نیاز دارد که فایل های خود را به آن اضافه کنید متن فایل موجود در هر دایرکتوری
بیایید با فایل های خالی error-model.h و error-model.cc شروع کنیم و این را به آن اضافه کنیم
src/network/wscript. در واقع فقط یک موضوع اضافه کردن فایل .cc به بقیه موارد است
فایل های منبع، و فایل .h به لیست فایل های سرصفحه.
اکنون، به دایرکتوری سطح بالا بروید و "./test.py" را تایپ کنید. نباید می شکستی
هر چیزی توسط این عملیات
شامل نگهبانان
بعد، بیایید مقداری اضافه کنیم شامل نگهبانان در فایل هدر ما.:
#ifndef ERROR_MODEL_H
#define ERROR_MODEL_H
...
# اندیف
فضای نام ns3
ns-3 با استفاده از ns-3 فضای نام تا نمادهای خود را از فضاهای نام دیگر جدا کند. به طور معمول، الف
کاربر بعدی یک را قرار می دهد ns-3 بلوک فضای نام در هر دو فایل cc و h.:
فضای نام ns3 {
...
}
در این مرحله، ما چند فایل اسکلتی داریم که در آنها میتوانیم کلاسهای جدید خود را تعریف کنیم.
فایل هدر به شکل زیر است:
#ifndef ERROR_MODEL_H
#define ERROR_MODEL_H
فضای نام ns3 {
} // فضای نام ns3
# اندیف
در حالی که error-model.cc فایل به سادگی شبیه این است:
#include "error-model.h"
فضای نام ns3 {
} // فضای نام ns3
این فایلها باید کامپایل شوند زیرا واقعاً محتوایی ندارند. ما اکنون آماده ایم
شروع به اضافه کردن کلاس ها کنید.
اول پیاده سازی
در این مرحله، ما هنوز در حال کار بر روی تعدادی داربست هستیم، اما می توانیم شروع به تعریف خود کنیم
کلاسها، با قابلیتهایی که بعداً اضافه میشوند.
به ارث می برند از جانب la شیء کلاس؟
این یک مرحله طراحی مهم است. آیا از کلاس استفاده کنیم شیء به عنوان یک کلاس پایه برای جدید شما
کلاس.
همانطور که در فصل مربوط به ns-3 Object-model، کلاس هایی که از کلاس ارث می برند
شیء دریافت خواص ویژه:
· ns-3 نوع و سیستم ویژگی (به ویژگی ها مراجعه کنید)
· یک سیستم تجمع شی
· یک سیستم شمارش مرجع اشاره گر هوشمند (کلاس Ptr)
کلاس هایی که از کلاس نشات می گیرند ObjectBase} دو ویژگی اول بالا را دریافت کنید، اما نگیرید
نشانگرهای هوشمند دریافت کنید کلاس هایی که از کلاس نشات می گیرند RefCountBase فقط اشاره گر هوشمند را دریافت کنید
سیستم شمارش مرجع
در عمل، کلاس شیء گونه ای از سه مورد بالا است که ns-3 توسعه دهنده خواهد بود
رایج ترین برخورد.
در مورد ما، میخواهیم از سیستم ویژگی استفاده کنیم و نمونههایی گذرا خواهیم بود
از این شی در سراسر ns-3 عمومی API، بنابراین کلاس شیء برای ما مناسب است
اول کلاس
یکی از راههای ادامه کار این است که با تعریف حداقل توابع شروع کنید و ببینید که آیا این کار را انجام میدهند یا خیر
گردآوری. بیایید مرور کنیم که وقتی از کلاس Object مشتق میشویم، چه چیزی برای پیادهسازی لازم است.:
#ifndef ERROR_MODEL_H
#define ERROR_MODEL_H
#include "ns3/object.h"
فضای نام ns3 {
کلاس ErrorModel: Public Object
{
عمومی:
استاتیک TypeId GetTypeId (باطل)؛
ErrorModel ();
مجازی ~ErrorModel ();
};
class RateErrorModel: Public ErrorModel
{
عمومی:
استاتیک TypeId GetTypeId (باطل)؛
RateErrorModel ();
مجازی ~RateErrorModel ();
};
# اندیف
در اینجا چند نکته قابل ذکر است. ما باید شامل کنیم شیء.h. کنوانسیون در ns-3 این است که اگر
فایل هدر در همان دایرکتوری قرار دارد، ممکن است بدون هیچ مسیری گنجانده شود
پیشوند بنابراین، اگر ErrorModel را در src/core/model دایرکتوری، ما
فقط می توانست بگوید "#include "object.h"اما ما وارد هستیم src/شبکه/مدل، بنابراین ما باید
آن را به عنوان "#include "ns3/object.h"همچنین توجه داشته باشید که این خارج از فضای نام است
اعلام.
دوم، هر کلاس باید یک تابع عضو عمومی استاتیک به نام اجرا کند GetTypeId (خالی).
سوم، این ایده خوبی است که سازنده ها و تخریب کننده ها را به جای اجازه دادن به آنها پیاده سازی کنید
کامپایلر آنها را تولید می کند و تخریب کننده را مجازی می کند. در C++، به آن کپی نیز توجه کنید
اپراتور تخصیص و سازنده های کپی اگر تعریف نشده باشند به طور خودکار تولید می شوند
اگر آنها را نمی خواهید، باید آنها را به عنوان اعضای خصوصی اجرا کنید. این جنبه از
C++ در کتاب Scott Meyers Effective C++ مورد بحث قرار گرفته است. مورد 45.
بیایید اکنون به کدهای پیاده سازی اسکلتی مربوطه در فایل cc نگاه کنیم:
#include "error-model.h"
فضای نام ns3 {
NS_OBJECT_ENSURE_REGISTERED (ErrorModel)؛
TypeId ErrorModel::GetTypeId (باطل)
{
static TypeId tid = TypeId ("ns3::ErrorModel")
SetParent ()
;
برگرد
}
ErrorModel::ErrorModel ()
{
}
ErrorModel::~ErrorModel ()
{
}
NS_OBJECT_ENSURE_REGISTERED (RateErrorModel)؛
TypeId RateErrorModel::GetTypeId (باطل)
{
static TypeId tid = TypeId ("ns3::RateErrorModel")
SetParent ()
.AddConstructor ()
;
برگرد
}
RateErrorModel::RateErrorModel ()
{
}
RateErrorModel::~RateErrorModel ()
{
}
به چه صورت است GetTypeId (خالی) عملکرد؟ این تابع چند کار را انجام می دهد. الف را ثبت می کند
رشته منحصر به فرد در سیستم TypeId. سلسله مراتب اشیاء را در
سیستم ویژگی (از طریق SetParent). همچنین اعلام می کند که اشیاء خاصی را می توان از طریق ایجاد کرد
چارچوب ایجاد شی (AddConstructor).
کلان NS_OBJECT_ENSURE_REGISTERED (نام کلاس) همچنین یک بار برای هر کلاس مورد نیاز است
یک متد GetTypeId جدید تعریف می کند و ثبت واقعی کلاس را در آن انجام می دهد
سیستم. فصل Object-Model این موضوع را با جزئیات بیشتری مورد بحث قرار می دهد.
از جمله خارجی فایل ها
ورود به سیستم پشتیبــانی
در اینجا، نوشتن a ذره در باره اضافه کردن |ns3| ورود به سیستم ماکروها توجه داشته باشید: که LOG_COMPONENT_DEFINE is
انجام شده خارج از la فضای نام ns3
سازنده، خالی عملکرد نمونه های اولیه
کلید متغیر (به طور پیش فرض ارزش های، ویژگی های)
تست برنامه 1
شیء چارچوب
اضافه کردن a نمونه خط
در این مرحله، ممکن است کسی بخواهد که داربست اولیه تعریف شده در بالا را گرفته و آن را اضافه کند
به سیستم. اکنون انجام این مرحله به فرد امکان می دهد از مدل ساده تری هنگام لوله کشی استفاده کند
وارد سیستم شده و همچنین ممکن است نشان دهد که آیا طراحی یا تغییرات API نیاز است یا خیر
ساخته شده است. پس از انجام این کار، ما به ساختن عملکردهای آن باز خواهیم گشت
ErrorModels خود.
اضافه کردن اساسی پشتیبــانی in la طبقه
/* point-to-point-net-device.h */
کلاس ErrorModel;
/ **
* مدل خطا برای دریافت رویدادهای بسته
*/
Ptr m_receiveErrorModel;
اضافه کردن دسترسی
از درجه اعتبار ساقط
PointToPointNetDevice::SetReceiveErrorModel (Ptr ام)
{
NS_LOG_FUNCTION (این << em);
m_receiveErrorModel = em;
}
.AddAttribute ("ReceiveErrorModel"،
"مدل خطای گیرنده مورد استفاده برای شبیه سازی از دست دادن بسته"،
PointerValue ()،
MakePointerAccessor (&PointToPointNetDevice::m_receiveErrorModel)،
MakePointerChecker ())
پلمب به la سیستم
void PointToPointNetDevice::دریافت (Ptr بسته)
{
NS_LOG_FUNCTION (این بسته <);
پروتکل uint16_t = 0;
if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (بسته))
{
//
// اگر یک مدل خطا داشته باشیم و نشان دهد که زمان از دست دادن a است
// بسته خراب، این بسته را فوروارد نکنید، آن را رها کنید.
//
m_dropTrace (بسته)؛
}
دیگر
{
//
// قلاب ردیابی دریافت را بزنید، هدر پروتکل نقطه به نقطه را بردارید
// و این بسته را در پشته پروتکل ارسال کنید.
//
m_rxTrace (بسته)؛
ProcessHeader (بسته، پروتکل)؛
m_rxCallback (این، بسته، پروتکل، GetRemote ())؛
اگر (!m_promiscCallback.IsNull ())
{ m_promiscCallback (این، بسته، پروتکل، GetRemote ()
GetAddress (), NetDevice::PACKET_HOST);
}
}
}
ساختن تهی تابعی خط
/* simple-error-model.cc */
// مدل خطا
// می خواهیم یک مدل خطا به NetDevice نود 3 اضافه کنیم
// می توانیم از طریق کانال و گره یک دسته برای NetDevice بدست آوریم
// اشاره گر
Ptr nd3 = PointToPointTopology::GetNetDevice
(n3, channel2);
Ptr em = ایجاد کنید ()؛
nd3->SetReceiveErrorModel (em);
بول
ErrorModel::DoCorrupt (Packet&p)
{
NS_LOG_FUNCTION؛
NS_LOG_UNCOND ("فاسد!");
بازگشت کاذب؛
}
در این مرحله، میتوانیم برنامه را با ErrorModel ساده خود در گیرنده اجرا کنیم
مسیر PointToPointNetDevice. رشته "فاسد!" برای هر بسته
در گره n3 دریافت شد. در مرحله بعد، به مدل خطا برمی گردیم تا زیر کلاسی را که کار می کند اضافه کنیم
مدل سازی خطای جالب تر
اضافه کردن a زیر کلاس
کلاس پایه بی اهمیت ErrorModel کار جالبی انجام نمی دهد، اما a را ارائه می دهد
رابط کلاس پایه مفید (فاسد () و بازنشانی ())، به توابع مجازی که
را می توان زیر طبقه بندی کرد. بیایید در ادامه آنچه را که BasicErrorModel می نامیم که بر اساس آن است، در نظر بگیریم
la ns-2 کلاس ErrorModel (in ns-2/queue/errmodel.{cc,h}).
از دیدگاه رابط کاربری، میخواهیم این ویژگی چه ویژگیهایی داشته باشد؟ ما دوست داریم
برای اینکه کاربر بتواند نوع ErrorModel استفاده شده در آن را به طور پیش پاافتاده تعویض کند
NetDevice. ما همچنین می خواهیم قابلیت تنظیم پارامترهای قابل تنظیم را داشته باشیم.
در اینجا چند الزام ساده وجود دارد که در نظر خواهیم گرفت:
· امکان تنظیم متغیر تصادفی حاکم بر ضررها (پیش فرض UniformVariable است)
· امکان تنظیم واحد (بیت، بایت، بسته، زمان) دانه بندی که در آن خطاها وجود دارد.
کاربردی.
· امکان تنظیم میزان خطا (مثلاً 10^-3) مطابق با واحد فوق
دانه دانه بودن.
· امکان فعال/غیرفعال کردن (پیش فرض فعال است)
چگونه به زیر کلاس
ما BasicErrorModel را به عنوان زیر کلاس ErrorModel به شرح زیر اعلام می کنیم:
کلاس BasicErrorModel: عمومی ErrorModel
{
عمومی:
استاتیک TypeId GetTypeId (باطل)؛
...
خصوصی:
// توابع مجازی خالص کلاس پایه را پیاده سازی کنید
مجازی Bool DoCorrupt (Ptr پ)؛
virtual bool DoReset (void);
...
}
و تابع GetTypeId زیر کلاس را با تنظیم یک رشته TypeId منحصر به فرد پیکربندی کنید
تنظیم والد روی ErrorModel:
TypeId RateErrorModel::GetTypeId (باطل)
{
static TypeId tid = TypeId ("ns3::RateErrorModel")
SetParent ()
.AddConstructor ()
...
ساختن هسته توابع و واحد تست
ادعا کنید ماکرو
نوشته واحد تست
اضافه کردن a جدید ماژول ها به ns-3
وقتی گروهی از کلاسها، مثالها و تستهای مرتبط ایجاد کردهاید، میتوانند باشند
با هم ترکیب شده به یک ns-3 ماژول به طوری که آنها را می توان با موجود استفاده کرد ns-3 ماژول ها
و توسط سایر محققین.
این فصل شما را از طریق مراحل لازم برای افزودن یک ماژول جدید به آن راهنمایی می کند ns-3.
گام 0 - ماژول ها طرح
همه ماژول ها را می توان در " فهرست راهنما. هر ماژول را می توان در یک فهرست پیدا کرد
که همان نام ماژول را دارد. به عنوان مثال طیف ماژول را می توانید در اینجا پیدا کنید:
src/طیف. ما به نقل از طیف ماژول برای تصویرسازی
یک ماژول نمونه اولیه دارای ساختار دایرکتوری زیر و فایل های مورد نیاز است:
src /
نام ماژول/
اتصالات/
سند/
مثال ها/
متن
یاور/
مدل/
تست/
examples-to-run.py
متن
همه دایرکتوری ها در هر ماژول وجود ندارند.
گام 1 - ساختن a ماژول ها استخوان بندی
یک برنامه پایتون در دایرکتوری منبع ارائه شده است که یک اسکلت برای برنامه جدید ایجاد می کند
مدول. برای اهداف این بحث، فرض می کنیم که ماژول جدید شما نامیده می شود
ماژول جدید. از " دایرکتوری، برای ایجاد ماژول جدید موارد زیر را انجام دهید:
$ ./create-module.py new-module
بعدی، cd به ماژول جدید; شما این طرح دایرکتوری را پیدا خواهید کرد:
ماژول جدید سی دی $
ls دلار
نمونه های doc تست مدل کمکی wscript
در جزئیات بیشتر، create-module.py اسکریپت دایرکتوری ها و همچنین اولیه را ایجاد می کند
اسکلت متن, .h, . رونوشت و اول فایل ها. ماژول کامل با فایل های اسکلت به نظر می رسد
مثل این:
src /
ماژول جدید/
سند/
new-module.rst
مثال ها/
new-module-example.cc
متن
یاور/
new-module-helper.cc
new-module-helper.h
مدل/
new-module.cc
new-module.h
تست/
new-module-test-suite.cc
متن
(در صورت نیاز اتصالات/ فهرست فهرست شده در مرحله 0 به طور خودکار در طول ایجاد خواهد شد
ساخت.)
در ادامه به نحوه سفارشی کردن این ماژول می پردازیم. اطلاع رسانی واف در مورد فایل هایی که
ماژول شما با ویرایش این دو انجام می شود متن فایل ها. ما از طریق آن قدم خواهیم زد
مراحل اصلی این فصل
همه ns-3 ماژول ها به هسته ماژول و معمولا روی ماژول های دیگر. این وابستگی
در مشخص شده است متن فایل (در سطح بالای ماژول، نه جداگانه متن
فایل در مثال ها فهرست راهنما!). در اسکلت متن تماسی که شما را اعلام می کند
ماژول جدید به واف به این شکل خواهد بود (قبل از ویرایش):
def build(bld):
module = bld.create_ns3_module('new-module', ['core'])
بیایید این را فرض کنیم ماژول جدید بستگی دارد به اینترنت, تحرکو aodv ماژول ها بعد از
در حال ویرایش آن متن فایل باید به شکل زیر باشد:
def build(bld):
module = bld.create_ns3_module('new-module', ['internet', 'mobility', 'aodv'])
توجه داشته باشید که فقط وابستگی های ماژول سطح اول باید لیست شوند، به همین دلیل است که حذف کردیم
هسته؛ اینترنت ماژول به نوبه خود بستگی دارد هسته.
ماژول شما به احتمال زیاد دارای فایل های منبع مدل خواهد بود. اسکلت های اولیه (که خواهد شد
کامپایل با موفقیت) در ایجاد می شوند model/new-module.cc و model/new-module.h.
اگر ماژول شما دارای فایلهای منبع کمکی باشد، آنها وارد آن خواهند شد یاور/
فهرست راهنما؛ دوباره، اسکلت های اولیه در آن دایرکتوری ایجاد می شوند.
در نهایت، نوشتن تست ها و مثال ها خوب است. اینها تقریباً قطعاً خواهند بود
برای پذیرش ماژول های جدید در رسمی مورد نیاز است ns-3 درخت منبع یک اسکلت
مجموعه تست و کیس تست در ایجاد شده است تست/ فهرست راهنما. مجموعه تست اسکلت خواهد شد
شامل سازنده زیر است که یک تست واحد جدید به نام را اعلام می کند ماژول جدید، با
تک مورد آزمون متشکل از کلاس NewModuleTestCase1:
NewModuleTestSuite::NewModuleTestSuite ()
: TestSuite ("ماژول جدید"، UNIT)
{
AddTestCase (NewModuleTestCase1)؛
}
گام 3 - اعلام کردن، اظهار داشتن و کردن، شناساندن، اعلان کردن منبع فایل ها
هدر عمومی و فایل های کد منبع ماژول جدید شما باید در قسمت مشخص شود
متن فایل را با ویرایشگر متن خود تغییر دهید.
به عنوان مثال، پس از اعلام طیف ماژول، src/spectrum/wscript را مشخص می کند
فایل های کد منبع با لیست زیر:
def build(bld):
module = bld.create_ns3_module('طیف'، ['اینترنت'، 'انتشار'، 'آنتن'، 'برنامه ها'])
module.source = [
'model/spectrum-model.cc'،
'model/spectrum-value.cc'،
.
.
.
'model/microwave-oven-spectrum-value-helper.cc'،
'helper/spectrum-helper.cc'،
'helper/adhoc-aloha-noack-ideal-phy-helper.cc'،
'helper/waveform-generator-helper.cc'،
'helper/spectrum-analyzer-helper.cc'،
]
اشیاء حاصل از کامپایل این منابع در یک کتابخانه پیوند جمع می شوند.
که به هر برنامه ای که به این ماژول متکی است پیوند داده می شود.
اما چگونه چنین برنامه هایی API عمومی ماژول جدید ما را یاد می گیرند؟ ادامه مطلب
گام 4 - اعلام کردن، اظهار داشتن و کردن، شناساندن، اعلان کردن عمومی سربرگ فایل ها
فایلهای هدر که API عمومی مدل و کمککنندههای شما را تعریف میکنند نیز باید باشند
مشخص شده در متن فایل.
ادامه با طیف در تصویر مدل، فایل های هدر عمومی مشخص شده است
با بیت زیر (توجه داشته باشید که استدلال به بولد تابع می گوید واف به
هدرهای این ماژول را با دیگری نصب کنید ns-3 سرصفحه ها):
headers = bld (features='ns3header')
headers.module = 'طیف'
headers.source = [
'model/spectrum-model.h'،
'model/spectrum-value.h'،
.
.
.
'model/microwave-oven-spectrum-value-helper.h'،
'helper/spectrum-helper.h'،
'helper/adhoc-aloha-noack-ideal-phy-helper.h',
'helper/waveform-generator-helper.h'،
'helper/spectrum-analyzer-helper.h'،
]
سرصفحههایی که به این روش عمومی میشوند برای کاربران مدل شما با شامل قابل دسترسی خواهند بود
اظهاراتی مانند
#include "ns3/spectrum-model.h"
سرصفحههایی که صرفاً به صورت داخلی در پیادهسازی شما استفاده میشوند، نباید در اینجا گنجانده شوند. آنها
هنوز هم برای پیاده سازی شما با شامل عبارت هایی مانند
#include "my-module-implementation.h"
گام 5 - اعلام کردن، اظهار داشتن و کردن، شناساندن، اعلان کردن تست
اگر ماژول جدید شما دارای تست است، باید آنها را در شما مشخص کنید متن فایل توسط
آن را با ویرایشگر متن خود تغییر دهید.
La طیف تست های مدل با بیت زیر مشخص می شوند:
module_test = bld.create_ns3_module_test_library('طیف')
module_test.source = [
'test/spectrum-interference-test.cc'،
'test/spectrum-value-test.cc'،
]
دیدن تست برای اطلاعات بیشتر در مورد نحوه نوشتن موارد تست.
گام 6 - اعلام کردن، اظهار داشتن و کردن، شناساندن، اعلان کردن مثال ها
اگر ماژول جدید شما دارای نمونه هایی است، آنها باید در شما مشخص شوند نمونه ها/wscript
فایل. (اسکلت در سطح بالایی متن به صورت بازگشتی شامل خواهد شد نمونه ها/wscript فقط اگر
نمونه ها در زمان پیکربندی فعال شدند.)
La طیف مدل اولین مثال آن را در تعریف می کند src/spectrum/examples/wscript با
def build(bld):
obj = bld.create_ns3_program('adhoc-aloha-ideal-phy',
['طیف'، 'تحرک'])
obj.source = 'adhoc-aloha-ideal-phy.cc'
توجه داشته باشید که آرگومان دوم تابع create_ns3_program() لیست ماژول ها است
که برنامه در حال ایجاد بستگی به باز هم فراموش نکنید که اضافه کنید ماژول جدید in
لیست. بهترین کار این است که فقط وابستگی های مستقیم ماژول را فهرست کنید و اجازه دهید واف
درخت وابستگی کامل را استنباط کنید.
گاهی اوقات، برای وضوح، ممکن است بخواهید پیاده سازی را برای مثال خود بین بیندازید
چندین فایل منبع در این مورد، فقط آن فایلها را به صورت واضح اضافه کنید
منابع مثال:
obj = bld.create_ns3_program('new-module-example', [new-module])
obj.source = ['new-module-example.cc', 'new-module-example-part.cc']
نمونه های پایتون با استفاده از فراخوانی تابع زیر مشخص می شوند. توجه داشته باشید که دوم
آرگومان برای تابع register_ns3_script() لیستی از ماژول های پایتون است
مثال بستگی به این دارد:
bld.register_ns3_script('new-module-example.py', ['new-module'])
گام 7 - مثال ها دویدن as تست
علاوه بر اجرای کد آزمایشی صریح، چارچوب تست را نیز می توان ابزار کرد
برنامه های نمونه کامل را اجرا کنید تا سعی کنید رگرسیون ها را در نمونه ها مشاهده کنید. با این حال، نه همه
نمونه ها برای آزمون های رگرسیون مناسب هستند. پرونده test/examples-to-run.py کنترل می کند
فراخوانی نمونه ها هنگام اجرای چارچوب تست.
La طیف نمونه های مدل اجرا شده توسط test.py در مشخص شده اند
src/spectrum/test/examples-to-run.py با استفاده از دو لیست زیر C++ و Python
مثال ها:
# لیستی از نمونه های C++ برای اجرا به منظور اطمینان از باقی ماندن آنها
# قابل ساخت و اجرا در طول زمان. هر تاپل در لیست شامل
#
# (نام_مثال، do_run، do_valgrind_run).
#
# برای اطلاعات بیشتر به test.py مراجعه کنید.
cpp_examples = [
("adhoc-aloha-ideal-phy"، "True"، "True")
("adhoc-aloha-ideal-phy-با-مایکروویو"، "True"، "True")،
("adhoc-aloha-ideal-phy-matrix-propagation-loss-model"، "True"، "True")
]
# لیستی از نمونه های پایتون برای اجرا به منظور اطمینان از باقی ماندن آنها
# قابل اجرا در طول زمان. هر تاپل در لیست شامل
#
# (نام_مثال، do_run).
#
# برای اطلاعات بیشتر به test.py مراجعه کنید.
python_examples = [
("sample-simulator.py"، "True")،
]
همانطور که در کامنت مشخص شد، هر ورودی در لیست نمونههای C++ برای اجرا شامل موارد زیر است
تاپل (name_name, do_run do_valgrind_run)، که در آن
· example_name اجرایی است که باید اجرا شود،
· do_run شرطی است که تحت آن مثال اجرا شود، و
· do_valgrind_run شرایطی است که تحت آن مثال تحت valgrind اجرا شود. (این
مورد نیاز است زیرا NSC باعث خرابی دستورالعمل های غیرقانونی با برخی آزمایش ها می شود
تحت والگریند اجرا می شوند.)
توجه داشته باشید که دو شرط عبارتهای پایتون هستند که میتوانند به آن بستگی داشته باشند واف پیکر بندی
متغیرها مثلا،
("tcp-nsc-lfn"، "NSC_ENABLED == درست"، "NSC_ENABLED == نادرست")،
هر ورودی در لیست مثالهای پایتون برای اجرا شامل تاپل است (name_name,
do_run)، جایی که، در مورد مثال های C++،
· example_name اسکریپت پایتون است که باید اجرا شود و
· do_run شرطی است که تحت آن مثال اجرا شود.
مجدداً، شرط یک عبارت پایتون است که می تواند به آن بستگی داشته باشد واف متغیرهای پیکربندی
به عنوان مثال،
("realtime-udp-echo.py"، "ENABLE_REAL_TIME == نادرست")،
گام 8 - مجموعه و ساختن
اکنون می توانید ماژول خود را به طور معمول پیکربندی، بسازید و آزمایش کنید. شما باید دوباره پیکربندی کنید
پروژه به عنوان اولین قدم به طوری که واف اطلاعات جدید را در حافظه پنهان ذخیره می کند متن فایل ها، یا
در غیر این صورت ماژول جدید شما در ساخت گنجانده نخواهد شد.
$ ./waf پیکربندی --enable-examples --enable-tests
$ ./waf ساخت
$ ./test.py
به دنبال مجموعه آزمایشی ماژول جدید خود بگردید (و برنامههای نمونه، اگر ماژول شما دارای آن باشد
فعال) در خروجی تست.
گام 9 - پــایتــون اتصالات
افزودن پیوندهای پایتون به ماژول اختیاری است و مرحله توسط نظر داده می شود
پیش فرض در create-module.py اسکریپت
# bld.ns3_python_bindings()
اگر میخواهید پیوندهای پایتون را اضافه کنید (فقط اگر میخواهید پایتون ns-3 بنویسید لازم است
برنامه ها به جای برنامه های C++ ns-3)، باید موارد فوق را حذف کرده و نصب کنید
سیستم اسکن Python API (در جای دیگری در این راهنما پوشش داده شده است) و ماژول خود را اسکن کنید
ایجاد اتصالات جدید
ایجاد مستندات
ns-3 دو نوع مستندات را ارائه میکند: فصلهای توضیحی به سبک «راهنمای کاربر»، و
اسناد API کد منبع
فصلهای «راهنمای کاربر» به صورت دستی نوشته شدهاند restructuredText فرمت (اول) ، که است
توسط سیستم اسناد پایتون پردازش شده است مجسمه ابوالهول برای تولید صفحات وب و فایل های pdf.
مستندات API از خود کد منبع تولید می شود و با استفاده از اکسیژن، برای تولید
صفحات وب با پیوند متقابل هر دوی اینها مهم هستند: فصل ابوالهول توضیح می دهد چرا
و مروری بر استفاده از یک مدل. اسناد API توضیح می دهد چگونه جزئیات.
این فصل یک نمای کلی سریع از این ابزارها، با تاکید بر استفاده ترجیحی و
سفارشی سازی برای ns-3.
برای ساخت تمام اسناد استاندارد:
$ ./waf docs
برای گزینه های تخصصی تر، به ادامه مطلب مراجعه کنید.
مستند سازی با مجسمه ابوالهول
استفاده می کنیم مجسمه ابوالهول برای تولید فصل های توضیحی که طراحی و استفاده از هر کدام را توضیح می دهد
مدول. در حال حاضر شما در حال خواندن مستندات فصل. این نمایش منبع لینک در
نوار کناری منبع reStructuredText را برای این فصل به شما نشان می دهد.
اضافه کردن جدید فصل
افزودن یک فصل جدید به سه مرحله نیاز دارد (در ادامه با جزئیات بیشتر توضیح داده شده است):
1. را انتخاب کنید کجا؟ فایل(های) مستندات زنده خواهد بود.
2. ارتباط دادن از یک صفحه موجود به اسناد جدید.
3. فایل جدید را به makefile.
کجا؟
اسناد برای یک ماژول خاص، فو، معمولاً باید وارد شود src/foo/doc/. مثلا
src/foo/doc/foo.rst سند سطح بالا برای ماژول خواهد بود. را
src/create-module.py اسکریپت این فایل را برای شما ایجاد خواهد کرد.
برخی از مدل ها به چندین مورد نیاز دارند اول فایل ها و ارقام؛ همه اینها باید وارد شوند
src/foo/doc/ فهرست راهنما. اسناد در واقع توسط یک Sphinx Makefile ساخته شده اند. مخصوصا
اسناد مربوطه، ممکن است داشتن یک محلی مفید باشد makefile در src/foo/doc/
دایرکتوری برای ساده ساختن مستندات این ماژول (انتن نمونه است).
تنظیم این به خصوص سخت نیست، اما خارج از محدوده این فصل است.
در برخی موارد، اسناد شامل چندین مدل میشود. را شبکه ارتباطی فصل یک مثال است. که در
این موارد اضافه کردن اول فایل های مستقیم به doc/models/source/ ممکن است مناسب باشد
ارتباط دادن
ابوالهول باید بداند جایی که فصل جدید شما باید ظاهر شود. در بیشتر موارد، یک مدل جدید
فصل باید در ظاهر شود مدل کتاب. برای افزودن فصل خود به آنجا، ویرایش کنید
doc/models/source/index.rst
.. toctree::
:maxdepth: 1
کدام سازمان ها
انیمیشن
انتن
aodv
برنامه های کاربردی
...
نام سند خود را اضافه کنید (بدون اول پسوند) به این لیست. لطفا نگه دارید
فصلها را به ترتیب حروف الفبا مدلسازی کنید تا اسکن بصری فصلهای خاص را آسانتر کنید.
makefile
شما همچنین باید سند خود را به مناسب اضافه کنید makefile، به طوری که ساخت می داند آن را بررسی کند
برای به روز رسانی کتاب مدل ها Makefile می باشد doc/models/Makefile، کتاب راهنمای Makefile است
doc/manual/Makefile.
# همه فایلهای rst. کتابخانه مدل را که باید در $SOURCETEMP کپی شوند فهرست کنید
منابع = \
source/conf.py \
منبع/_استاتیک \
source/index.rst \
source/replace.txt \
source/organization.rst \
...
$(SRC)/antenna/doc/source/antenna.rst \
...
شما خود را اضافه کنید اول فایل ها به منابع متغیر. برای افزودن ارقام، نظرات موجود در قسمت را بخوانید
makefile تا ببینید کدام متغیر باید حاوی فایل های تصویری شما باشد. باز هم لطفا اینها را نگه دارید
به ترتیب حروف الفبا
بنا مجسمه ابوالهول اسناد
ساخت اسناد Sphinx بسیار ساده است. برای ساختن تمام ابوالهول
مستندات:
$ ./اسفینکس واف
برای ساختن فقط مستندات Models:
$ make -C doc/models
برای دیدن مستندات ایجاد شده، مرورگر خود را به آن نشان دهید doc/models/build/html.
همانطور که می بینید، Sphinx از Make برای هدایت فرآیند استفاده می کند. هدف پیش فرض همه را می سازد
فرم های خروجی را فعال کرد که در ns-3 چند صفحه ای هستند اچ تی ام ال، تک صفحه ای singlehtmlو
پی دی اف (شیرابه). برای ساختن فقط html چند صفحه ای، باید آن را اضافه کنید اچ تی ام ال هدف:
$ make -C doc/models html
این می تواند برای کاهش زمان ساخت (و اندازه گفتگوی ساخت) مفید باشد
فصل شما را می نویسند
قبل از اینکه مستندات خود را به مخزن تحویل دهید، لطفاً بررسی کنید که بدون ساخت است
خطاها یا هشدارها فرآیند ساخت، خروجی های زیادی تولید می کند (عمدتاً چت معمولی).
از LaTeX)، که میتواند تشخیص وجود هشدارهای Sphinx یا وجود آن را دشوار کند
خطاها برای یافتن اخطارها و خطاهای مهم فقط اچ تی ام ال نسخه، سپس جستجو کنید
لاگ ساخت برای هشدار or خطا.
ns-3 جزئیات
ابوالهول مستندات و آموزش خیلی خوب هستند ما اصول اولیه را تکرار نمی کنیم
در اینجا، به جای تمرکز بر استفاده ترجیحی برای ns-3.
· اسناد را با این دو خط شروع کنید:
.. عبارتند از:: replace.txt
.. برجسته:: cpp
خط اول چند جایگزین ساده را امکان پذیر می کند. مثلا تایپ کردن |ns3| به عنوان ارائه می دهد
ns-3. دومی کد منبع پیش فرض زبان برجسته سازی را به صراحت برای آن تنظیم می کند
فایل، زیرا حدس تجزیه کننده همیشه دقیق نیست. (همچنین امکان تنظیم
زبان به صراحت برای یک بلوک کد واحد، به زیر مراجعه کنید.)
· بخش ها:
Sphinx در مورد علامت گذاری عناوین بخش بسیار آزاد است. طبق قرارداد، ما این را ترجیح می دهیم
سلسله مراتب:
.. سلسله مراتب سرفصل:
------------- فصل
************* بخش (#.#)
============= زیربخش (#.#.#)
############# زیربخش
· برجسته سازی نحو:
برای استفاده از برجستهکننده نحو پیشفرض، به سادگی یک بلوک کد منبع را شروع کنید:
┌¡***********************الم ───────────────────
│منبع ابوالهول │ خروجی رندر شده │
├¡***********************الم ──────────────────
│ │ فروبنیتز توسط: │ قابل دسترسی است
│ "Frobnitz" توسط:: │ │ قابل دسترسی است
│ │ Foo::Frobnitz frob; │
│ Foo::Frobnitz frob; │ frob.Set (...); │
│ frob.Set (...); │ │
└¡***********************الم ──────────────────
برای استفاده از یک برجسته کننده نحو خاص، به عنوان مثال، بر هم زدن دستورات پوسته:
┌¡***********************الم ───┐
│منبع ابوالهول │ خروجی رندر شده │
├¡***********************الم ───┤
│ │ │
│ .. منبع کد:: bash │ $ ls │
│ │ │
│ $ ls │ │
└¡***********************الم ───┘
· نمادهای اختصاری:
این مختصرها به شرح زیر است:
┌──────────────────-
│منبع ابوالهول │ خروجی رندر شده │
├─────────────────────-
│ ns-3 │
│ |ns3| │ │
├─────────────────────-
│ ns-2 │
│ |ns2| │ │
├─────────────────────-
│ │ │
│ |بررسی| │ │
├─────────────────────-
│ RFC 6282 │
│ :rfc:`6282` │ │
└─────────────────
مستند سازی با اکسیژن
استفاده می کنیم اکسیژن برای تولید قابل مرور اسناد API داکسیژن تعدادی از
ویژگی های مفید:
· جدول خلاصه کلیه اعضای کلاس.
· نمودارهای وراثت و همکاری برای همه طبقات.
· پیوندها به کد منبع پیادهسازی هر تابع.
· پیوند به هر مکانی که یک عضو استفاده می شود.
· پیوند به هر شیء مورد استفاده در اجرای یک تابع.
· گروه بندی کلاس های مرتبط، مانند تمام کلاس های مربوط به یک پروتکل خاص.
علاوه بر این، ما از TypeId سیستمی برای اضافه کردن به اسناد برای هر کلاس
· پیکربندی مسیرهایی که از طریق آنها می توان به چنین اشیایی دست یافت.
· اسناد و مدارک برای هر خواص، از جمله خواص در کلاس های والد تعریف شده است.
· اسناد و مدارک برای هر پی گیری منابع تعریف شده توسط کلاس
Doxygen با اسکن کد منبع عمل می کند و به دنبال نظرات مشخص شده خاص می گردد. آی تی
همچنین یک مرجع متقابل ایجاد می کند که نشان می دهد جایی که هر فایل، کلاس، متد و متغیر است
استفاده شده.
مرجح سبک
سبک ترجیحی برای نظرات Doxygen، سبک JavaDoc است:
/ **
* شرح مختصری از این کلاس یا متد.
* خطوط مجاور به یک پاراگراف تبدیل می شوند.
*
* توضیحات طولانی تر، با جزئیات زیاد.
*
* خطوط خالی پاراگراف ها را جدا می کند.
*
* با استفاده از کدام الگوریتم کلاس یا متد را توضیح دهید.
* واحدهای آرگومان ها و مقادیر بازگشتی را توضیح دهید.
*
* \note به هر گونه محدودیت یا مشکل توجه کنید.
*
* (برای توابع دارای آرگومان یا بازگشتی با ارزش:)
* \param foo عبارت اسمی مختصر که این استدلال را توصیف می کند.
* \param bar توجه موارد جمله و دوره خاتمه.
* \return عبارت اسمی مختصر که مقدار را توصیف می کند.
*
* \درونی؛ داخلی
*
* همچنین می توانید درباره جزئیات پیاده سازی داخلی صحبت کنید.
* درک این ماده نباید برای استفاده ضروری باشد
* کلاس یا روش.
*/
نمونه کلاس
در این سبک، بلوک نظرات Doxygen با دو کاراکتر «*» شروع میشود: / **، و مقدم است
موردی که مستند می شود
برای مواردی که فقط به توضیح مختصری نیاز دارند، هر یک از این فرم های کوتاه مناسب است:
/** پیاده سازی Destructor. */
void DoDispose ();
int m_count; //!< تعداد ...
به فرم خاص نظر انتهای خط توجه کنید، //!، نشان می دهد که به آن اشاره دارد
ماقبل آیتم استفاده کنید.
برخی موارد قابل توجه:
· از حروف جمله، از جمله سرمایه اولیه استفاده کنید.
· از علائم نگارشی، به خصوص «.» در انتهای جملات یا عبارات استفاده کنید.
· \مختصر برچسب مورد نیاز نیست. جمله اول به عنوان خلاصه استفاده خواهد شد
شرح.
هر کلاس، متد، typedef، متغیر عضو، آرگومان تابع و مقدار بازگشتی باید
در تمام فایل های کد منبع که API رسمی و پیاده سازی را تشکیل می دهند، مستند شود
ns-3، از جمله src/ /مدل/*, src/ /یاور/* و src/ /utils/*.
اسناد برای اقلام در src/ /تست/* و src/ /مثال ها/* ترجیح داده می شود،
اما لازم نیست
مفید امکانات
· اعضای ارثی به طور خودکار اسناد را از والدین به ارث می برند، (اما می توان آنها را جایگزین کرد
توسط اسناد محلی).
1. کلاس پایه را مستند کنید.
2. در کلاس فرعی توابع ارثی را با یک نظر معمولی علامت بزنید:
// روش های ارثی
مجازی void FooBar (باطل)؛
مجازی int BarFoo (دو باز);
توجه داشته باشید که امضاها باید دقیقاً مطابقت داشته باشند، بنابراین استدلال رسمی را نیز لحاظ کنید (خالی)
این برای توابع استاتیک کار نمی کند. دیدن GetTypeId، در زیر، برای مثال.
بنا اکسیژن اسناد
ایجاد مستندات Doxygen بسیار ساده است:
$ ./waf داکسیژن
این با استفاده از پیکربندی پیشفرض ساخته میشود که بخشهای مستندسازی را برای آن ایجاد میکند
تمام موارد، حتی اگر بلوک های مستند نظر صریح نداشته باشند. این را دارد
اثر سرکوب هشدارها برای موارد غیر مستند، اما مطمئن می شود همه چیز ظاهر می شود
در خروجی تولید شده
هنگام نوشتن اسناد، اغلب مفیدتر است که ببینید کدام آیتم ها تولید می شوند
هشدارها، معمولاً در مورد اسناد مفقود. برای مشاهده لیست کامل هشدارها، از
doc/doxygen.warnings.report.sh متن:
$ doc/doxygen.warnings.report.sh
Waf: ورود به دایرکتوری 'build'
...
Waf: خروج از دایرکتوری 'build'
"ساخت" با موفقیت به پایان رسید (3m24.094s)
بازسازی اسناد 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 examples/stats/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 build و تولید کامل انجام شود
گزارش هشدارها، میتوانید فایل گزارش را با «فیلترهای» مختلف بدون نیاز به انجام دوباره پردازش کنید
ساخت کامل داکسیژن توسط، دوباره با استفاده از -s گزینه. می توانید اخطارها را حذف کنید
*/مثال ها/* فایل ها (-e گزینه)، و/یا */تست/* فایل ها (-t).
شاید مفیدترین گزینه هنگام نوشتن نظرات مستندات باشد -m ، که
گزارش را فقط به تطابق فایل ها محدود می کند src/ /*، و گزارش را با
خطوط هشدار واقعی ترکیب با دنده و می توانید روی هشدارهایی که هستند تمرکز کنید
فوری ترین در یک ماژول:
$ doc/doxygen.warnings.report.sh -m mesh/helper
...
خلاصه هشدارهای داکسیژن
----------------------------------------
1 دایرکتوری
فایل های 3
149 هشدار
هشدارهای فیلتر شده
========================================
src/mesh/helper/dot11s/dot11s-installer.h:72: warning: عضو m_root (متغیر) کلاس ns3::Dot11sStack مستند نشده است.
src/mesh/helper/dot11s/dot11s-installer.h:35: warning: نوع بازگشت عضو ns3::Dot11sStack::GetTypeId مستند نیست
src/mesh/helper/dot11s/dot11s-installer.h:56: warning: نوع بازگشت عضو ns3::Dot11sStack::InstallStack مستند نیست
src/mesh/helper/flame/lfame-installer.h:40: warning: Member GetTypeId() (تابع) کلاس ns3::FlameStack مستند نشده است.
src/mesh/helper/flame/flame-installer.h:60: warning: نوع بازگشت عضو ns3::FlameStack::InstallStack مستند نیست
src/mesh/helper/mesh-helper.h:213: warning: عضو m_nاینترفیس (متغیر) کلاس ns3::MeshHelper مستند نشده است.
src/mesh/helper/mesh-helper.h:214: warning: عضو m_spreadChannelPolicy (متغیر) کلاس ns3::MeshHelper مستند نیست.
src/mesh/helper/mesh-helper.h:215: warning: عضو m_stack (متغیر) کلاس ns3::MeshHelper مستند نشده است.
src/mesh/helper/mesh-helper.h:216: هشدار: عضو m_stackFactory (متغیر) از کلاس ns3::MeshHelper مستند نیست.
src/mesh/helper/mesh-helper.h:209: warning: پارامترهای عضو ns3::MeshHelper::CreateInterface (همه) مستند نیستند
src/mesh/helper/mesh-helper.h:119: warning: پارامترهای عضو ns3::MeshHelper::SetStandard (همه) مستند نیستند
حالا فقط موضوع درک کد و نوشتن چند سند است!
ns-3 جزئیات
در مورد ابوالهول، داکسیژن اسناد و مرجع خیلی خوب هستند ما آن را کپی نمی کنیم
اصول اولیه در اینجا، به جای تمرکز بر استفاده ترجیحی برای ns-3.
· از داکسیژن استفاده کنید ماژول ها برای گروه بندی موارد مرتبط
در هدر اصلی یک ماژول، یک گروه Doxgyen ایجاد کنید:
/ **
* پروتکل \defgroup foo Foo.
*/
هر کلاس مرتبط را به عنوان متعلق به گروه علامت گذاری کنید:
/ **
* \ingroup foo
*
* نوع بسته Foo.
*/
کلاس Foo
· آیا می دانستید تایپ شده می تواند استدلال رسمی داشته باشد؟ این امکان مستندسازی عملکرد را فراهم می کند
امضاهای اشاره گر:
/ **
* نوار امضای تابع تماس.
*
* \param ale به اندازه یک پیمانه آل، در اونس امپراتوری.
*/
typedef void (* BarCallback)(const int ale);
· کپی کنید صفت رشته های کمک از GetTypeId روشی برای استفاده به عنوان خلاصه
توضیحات اعضای مرتبط
· \bugid{298} پیوندی به باگ 298 در Bugzilla ما ایجاد می کند.
· \pname{foo} در توضیحات فرمت خواهد شد فو به عنوان یک \param فو پارامتر، آن را روشن می کند
که شما به یک استدلال واقعی اشاره می کنید.
· \RFC{301} پیوندی به RFC 301 ایجاد می کند.
· \درونی؛ داخلی باید فقط برای شروع بحث در مورد جزئیات پیاده سازی استفاده شود، نه برای
علامت خصوصی توابع (آنها قبلاً به عنوان علامت گذاری شده اند خصوصی!)
· کلاس هایی با نام های بی اهمیت، مانند کلاس A، حتی در مجموعه های آزمایشی. اینها
باعث می شود که همه نمونه های نام کلاس تحت اللفظی 'A' به عنوان پیوند ارائه شوند.
همانطور که در بالا ذکر شد، توابع استاتیک مستندات توابع یکسان را به ارث نمی برند
کلاس والدین ns-3 در همه جا از چند توابع استاتیک استفاده می کند. پیشنهاد شده
بلوک اسناد برای این موارد است:
· سازنده/ویرانگر پیش فرض:
کلاس من ()؛ //!< سازنده پیش فرض
~MyClass (); //!< ویرانگر
· تخریب کننده ساختگی و DoDispose:
/** تخریبگر ساختگی، به DoDispose مراجعه کنید. */
~MyClass ();
/** پیاده سازی Destructor */
خالی مجازی DoDispose ();
· GetTypeId:
/ **
* این نوع را ثبت کنید.
* \return شی TypeId.
*/
استاتیک TypeId GetTypeId (باطل)؛
را قادر می سازد زیرمجموعه ها of ns-3 ماژول ها
مانند اکثر پروژه های نرم افزاری، ns-3 از نظر تعداد ماژول ها روز به روز بزرگتر می شود،
خطوط کد و ردپای حافظه با این حال، کاربران فقط می توانند از تعداد کمی از آن ماژول ها استفاده کنند
در یک زمان. به همین دلیل، کاربران ممکن است بخواهند به صراحت فقط زیر مجموعه را فعال کنند
ممکن ns-3 ماژول هایی که آنها در واقع برای تحقیق خود به آنها نیاز دارند.
در این فصل نحوه فعال کردن فقط مورد بحث قرار می گیرد ns-3 ماژول هایی که به آنها علاقه دارید
با استفاده از.
چگونه به قادر ساختن a زیرمجموعه of ns-3's ماژول ها
اگر کتابخانه های مشترک ساخته می شوند، فعال کردن یک ماژول حداقل باعث ایجاد یک ماژول می شود
کتابخانه ای که قرار است ساخته شود:
libns3-modulename.so
اگر ماژول دارای یک کتابخانه آزمایشی است و کتابخانه های آزمایشی در حال ساخت هستند، پس
libns3-modulename-test.so
نیز ساخته خواهد شد ماژول های دیگری که ماژول به آنها وابسته است و کتابخانه های آزمایشی آنها
نیز ساخته خواهد شد.
بهطور پیشفرض، همه ماژولها داخلی هستند ns-3. دو راه برای فعال کردن زیرمجموعه ای از اینها وجود دارد
ماژول ها:
1. از گزینه --enable-modules waf استفاده کنید
2. استفاده از ns-3 فایل پیکربندی
فعال ماژول ها با استفاده از واف -- فعال کردن ماژول ها انتخاب
برای فعال کردن فقط ماژول هسته با مثال و تست، برای مثال، این دستورات را امتحان کنید:
$ ./waf تمیز
$ ./waf configure --enable-examples --enable-tests --enable-modules=core
$ ./waf ساخت
$ ساخت/اشکال زدایی سی دی/
ls دلار
و کتابخانه های زیر باید وجود داشته باشد:
bindings libns3-core.so ns3 scratch utils
نمونههایی از libns3-core-test.so نمونههای src
توجه داشته باشید که ./ واف تمیز مرحله در اینجا انجام می شود تا مشخص شود که کدام کتابخانه های ماژول
ساخته شدند. شما مجبور نیستید انجام دهید ./ واف تمیز به منظور فعال کردن زیر مجموعه های ماژول ها.
اجرای test.py باعث می شود فقط آن دسته از تست هایی اجرا شوند که به هسته ماژول بستگی دارند:
24 از 24 تست با موفقیت انجام شد (24 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
مراحل بالا را برای ماژول "شبکه" به جای ماژول "core" تکرار کنید
زیر ساخته خواهد شد، زیرا شبکه به هسته بستگی دارد:
اتصالات libns3-core.so libns3-network.so ns3 scratch utils
نمونههایی از libns3-core-test.so libns3-network-test.so samples src
اجرای test.py باعث می شود آن دسته از تست هایی که فقط به ماژول های هسته و شبکه وابسته هستند
اجرا شود:
31 از 31 تست با موفقیت انجام شد (31 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
فعال ماژول ها با استفاده از la ns-3 پیکر بندی پرونده
یک فایل پیکربندی، ns3rc. به اضافه شده است ns-3 که به کاربران اجازه می دهد تعیین کنند کدام
ماژول ها باید در ساخت گنجانده شوند.
هنگام فعال کردن زیر مجموعه ای از ns-3 ماژول ها، قوانین تقدم به شرح زیر است:
1. رشته پیکربندی --enable-modules هر فایل .ns3rc را لغو می کند
2. فایل ns3rc در سطح بالا ns-3 در صورت وجود، دایرکتوری بعدی مورد بررسی قرار می گیرد
3. سیستم جستجو می کند ~/.ns3rc اگر دو مورد فوق نامشخص باشند
اگر هیچ یک از موارد فوق ماژول های ساخته شده را محدود نکند، همه ماژول هایی که waf از آنها اطلاع دارد، خواهند بود
ساخته شود.
نسخه نگهداری شده فایل ns3rc در ns-3 مخزن کد منبع در آن قرار دارد
la سودمند فهرست راهنما. دلیل این امر این است که در دایرکتوری سطح بالای the
مخزن، مستعد بررسیهای تصادفی از سوی نگهدارندههایی است که این را فعال میکنند
ماژول هایی که می خواهند استفاده کنند. بنابراین، کاربران باید به صورت دستی .ns3rc را از روی کپی کنند
سودمند دایرکتوری به مکان مورد نظر خود (دایرکتوری سطح بالا یا دایرکتوری اصلی آنها) به
پیکربندی ساخت مدولار مداوم را فعال کنید.
با فرض اینکه در سطح بالایی هستید ns-3 دایرکتوری، می توانید یک کپی از .ns3rc دریافت کنید
فایلی که در سودمند دایرکتوری به شرح زیر
$ cp utils/.ns3rc .
فایل ns3rc اکنون باید در سطح بالای شما باشد ns-3 دایرکتوری، و حاوی
زیر است:
#! /usr/bin/env پایتون
# لیستی از ماژول هایی که با اجرای ns-3 فعال می شوند.
# ماژول هایی که به ماژول های لیست شده بستگی دارند نیز فعال خواهند شد.
#
# همه ماژول ها را می توان با انتخاب "all_modules" فعال کرد.
modules_enabled = ['all_modules']
# اگر میخواهید نمونهها اجرا شوند، این را برابر true قرار دهید.
examples_enabled = نادرست
# اگر میخواهید تستها اجرا شوند، این را برابر true قرار دهید.
tests_enabled = نادرست
از ویرایشگر مورد علاقه خود برای تغییر فایل .ns3rc استفاده کنید تا فقط ماژول اصلی با آن فعال شود
نمونه ها و تست هایی مانند این:
#! /usr/bin/env پایتون
# لیستی از ماژول هایی که با اجرای ns-3 فعال می شوند.
# ماژول هایی که به ماژول های لیست شده بستگی دارند نیز فعال خواهند شد.
#
# همه ماژول ها را می توان با انتخاب "all_modules" فعال کرد.
modules_enabled = ['core']
# اگر میخواهید نمونهها اجرا شوند، این را برابر true قرار دهید.
examples_enabled = درست است
# اگر میخواهید تستها اجرا شوند، این را برابر true قرار دهید.
tests_enabled = درست است
اگر این دستورات را امتحان کنید اکنون فقط ماژول اصلی فعال می شود:
$ ./waf تمیز
$ ./waf پیکربندی کنید
$ ./waf ساخت
$ ساخت/اشکال زدایی سی دی/
ls دلار
و کتابخانه های زیر باید وجود داشته باشد:
bindings libns3-core.so ns3 scratch utils
نمونههایی از libns3-core-test.so نمونههای src
توجه داشته باشید که ./ واف تمیز مرحله در اینجا انجام می شود تا مشخص شود که کدام کتابخانه های ماژول
ساخته شدند. شما مجبور نیستید انجام دهید ./ واف تمیز به منظور فعال کردن زیر مجموعه های ماژول ها.
اجرای test.py باعث می شود فقط آن دسته از تست هایی اجرا شوند که به هسته ماژول بستگی دارند:
24 از 24 تست با موفقیت انجام شد (24 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
مراحل بالا را برای ماژول "شبکه" به جای ماژول "core" تکرار کنید
زیر ساخته خواهد شد، زیرا شبکه به هسته بستگی دارد:
اتصالات libns3-core.so libns3-network.so ns3 scratch utils
نمونههایی از libns3-core-test.so libns3-network-test.so samples src
اجرای test.py باعث می شود آن دسته از تست هایی که فقط به ماژول های هسته و شبکه وابسته هستند
اجرا شود:
31 از 31 تست با موفقیت انجام شد (31 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
فعال/غیرفعال کردن ns-3 تست و مثال ها
La ns-3 توزیع شامل مثالها و آزمایشهای زیادی است که برای اعتبارسنجی استفاده میشود ns-3
سیستم. با این حال، کاربران ممکن است همیشه نخواهند که این نمونه ها و آزمایش ها برای آنها اجرا شود
نصب ns-3.
این فصل به نحوه ساختن می پردازد ns-3 با نمونه ها و تست های آن یا بدون آن.
چگونه به فعال غیرفعال مثال ها و تست in ns-3
3 راه برای فعال کردن/غیرفعال کردن مثال ها و تست ها وجود دارد ns-3:
1. استفاده از build.py زمانی که ns-3 برای اولین بار ساخته شده است
2. استفاده از waf یکبار 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 دایرکتوری now باعث می شود هیچ نمونه یا آزمایشی وجود نداشته باشد
اجرا کن:
0 از 0 تست با موفقیت انجام شد (0 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
اگر می خواهید بسازید ns-3 با مثال و تست، سپس موارد زیر را از قسمت انجام دهید
دایرکتوری ns-3-allinone:
$ ./build.py --enable-examples --enable-tests
اجرای test.py در سطح بالا ns-3 دایرکتوری باعث تمام مثال ها و تست ها می شود
اجرا شود:
170 از 170 تست با موفقیت انجام شد (170 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
فعال غیرفعال مثال ها و تست با استفاده از واف
می توانید از 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 پیکربندی --enable-examples --enable-tests
$ ./waf ساخت
اجرای test.py باعث می شود که همه نمونه ها و تست ها اجرا شوند:
170 از 170 تست با موفقیت انجام شد (170 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
فعال غیرفعال مثال ها و تست با استفاده از la ns-3 پیکر بندی پرونده
یک فایل پیکربندی، ns3rc. به اضافه شده است ns-3 که به کاربران اجازه می دهد مشخص کنند که آیا
نمونه ها و تست ها باید ساخته شوند یا نه. می توانید از این فایل برای فعال/غیرفعال کردن استفاده کنید
یک بار مثال و تست ns-3 ساخته شده است.
هنگام فعال کردن غیرفعال کردن مثالها و تستها، قوانین اولویت به شرح زیر است:
1. رشته های پیکربندی --enable-examples/--disable-examples هر فایل .ns3rc را لغو می کند
2. رشته های پیکربندی --enable-tests/--disable-tests هر فایل .ns3rc را لغو می کند.
3. فایل ns3rc در سطح بالا ns-3 در صورت وجود، دایرکتوری بعدی مورد بررسی قرار می گیرد
4. سیستم جستجو می کند ~/.ns3rc اگر فایل ns3rc در مرحله قبل یافت نشد
اگر هیچ یک از موارد فوق وجود نداشته باشد، نمونه ها و تست ها ساخته نمی شوند.
نسخه نگهداری شده فایل ns3rc در ns-3 مخزن کد منبع در آن قرار دارد
la سودمند فهرست راهنما. دلیل این امر این است که در دایرکتوری سطح بالای the
مخزن، مستعد بررسیهای تصادفی از سوی نگهدارندههایی است که این را فعال میکنند
ماژول هایی که می خواهند استفاده کنند. بنابراین، کاربران باید به صورت دستی .ns3rc را از روی کپی کنند
سودمند دایرکتوری به مکان مورد نظر خود (دایرکتوری سطح بالا یا دایرکتوری اصلی آنها) به
فعال کردن مداوم مثال ها و تست ها را فعال کنید.
با فرض اینکه در سطح بالایی هستید ns-3 دایرکتوری، می توانید یک کپی از .ns3rc دریافت کنید
فایلی که در سودمند دایرکتوری به شرح زیر
$ cp utils/.ns3rc .
فایل ns3rc اکنون باید در سطح بالای شما باشد ns-3 دایرکتوری، و حاوی
زیر است:
#! /usr/bin/env پایتون
# لیستی از ماژول هایی که با اجرای ns-3 فعال می شوند.
# ماژول هایی که به ماژول های لیست شده بستگی دارند نیز فعال خواهند شد.
#
# همه ماژول ها را می توان با انتخاب "all_modules" فعال کرد.
modules_enabled = ['all_modules']
# اگر میخواهید نمونهها اجرا شوند، این را برابر true قرار دهید.
examples_enabled = نادرست
# اگر میخواهید تستها اجرا شوند، این را برابر true قرار دهید.
tests_enabled = نادرست
از سطح بالا ns-3 دایرکتوری، شما می توانید بسازید ns-3 بدون هیچ مثال یا آزمایشی به سادگی
با انجام دادن:
$ ./waf پیکربندی کنید
$ ./waf ساخت
اجرای test.py اکنون باعث نمی شود که هیچ نمونه یا آزمایشی اجرا نشود:
0 از 0 تست با موفقیت انجام شد (0 مورد قبول شد، 0 مورد رد شد، 0 مورد ناموفق، 0 تصادف، 0 خطا valgrind)
اگر می خواهید بسازید ns-3 با مثال ها و تست ها، از ویرایشگر مورد علاقه خود برای تغییر استفاده کنید
مقادیر موجود در فایل .ns3rc برای فایل examples_enabled و tests_enabled درست باشد:
#! /usr/bin/env پایتون
# لیستی از ماژول هایی که با اجرای ns-3 فعال می شوند.
# ماژول هایی که به ماژول های لیست شده بستگی دارند نیز فعال خواهند شد.
#
# همه ماژول ها را می توان با انتخاب "all_modules" فعال کرد.
modules_enabled = ['all_modules']
# اگر میخواهید نمونهها اجرا شوند، این را برابر true قرار دهید.
examples_enabled = درست است
# اگر میخواهید تستها اجرا شوند، این را برابر true قرار دهید.
tests_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 -- tcp-point-to-point را اجرا کنید
وارد کردن دایرکتوری '/home/tomh/ns-3-nsc/build'
تدوین با موفقیت به پایان رسید
فرمان ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] با کد -11 خارج شد
پیغام خطا می گوید که برنامه با موفقیت خاتمه یافته است، اما مشخص نیست
از این اطلاعات چه چیزی ممکن است اشتباه باشد. برای بررسی دقیق تر، سعی کنید آن را در زیر اجرا کنید
la gdb دیباگر:
$ ./waf --run tcp-point-to-point --command-template="gdb %s"
وارد کردن دایرکتوری '/home/tomh/ns-3-nsc/build'
تدوین با موفقیت به پایان رسید
GNU gdb Red Hat Linux (6.3.0.0-1.134.fc5rh)
حق چاپ 2004 Free Software Foundation, Inc.
GDB یک نرم افزار رایگان است که تحت پوشش مجوز عمومی عمومی گنو است و شما هم هستید
از تغییر آن و/یا توزیع کپی از آن تحت شرایط خاص خوش آمدید.
برای مشاهده شرایط عبارت "show copying" را تایپ کنید.
مطلقاً هیچ ضمانتی برای GDB وجود ندارد. برای جزئیات، عبارت "نمایش گارانتی" را تایپ کنید.
این GDB به عنوان "i386-redhat-linux-gnu" پیکربندی شده است... با استفاده از میزبان libthread_db
کتابخانه "/lib/libthread_db.so.1".
(gdb) اجرا شود
برنامه شروع: /home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point
خواندن نمادها از شی مشترک خوانده شده از حافظه هدف ... انجام شد.
سیستم بارگذاری شده DSO را در 0xf5c000 عرضه می کند
برنامه سیگنال SIGSEGV، خطای تقسیم بندی را دریافت کرد.
0x0804aa12 در اصلی (argc=1، argv=0xbfdfefa4)
در ../examples/tcp-point-to-point.cc:136
136 Ptr localSocket = socketFactory->CreateSocket ();
(gdb) p localSocket
$1 = {m_ptr = 0x3c5d65}
(gdb) p socketFactory
$2 = {m_ptr = 0x0}
(gdb) ترک
برنامه در حال اجراست. به هر حال خروج؟ (y یا n) y
ابتدا به نحوه فراخوانی برنامه توجه کنید - دستور اجرا را به عنوان آرگومان به برنامه ارسال کنید
الگوی فرمان "gdb %s".
این به ما میگوید که تلاشی برای عدم ارجاع یک نشانگر تهی socketFactory صورت گرفته است.
بیایید به اطراف خط 136 tcp-point-to-point نگاه کنیم، همانطور که gdb نشان می دهد:
Ptr socketFactory = n2->GetObject (Tcp::iid)؛
Ptr localSocket = socketFactory->CreateSocket ();
localSocket->Bind ();
مقصر در اینجا این است که مقدار بازگشتی GetObject بررسی نمی شود و ممکن است بررسی شود
خالی.
گاهی اوقات ممکن است لازم باشد از آن استفاده کنید والگریند حافظه شطرنجی کردن برای خطاهای ظریف تر از نو،
شما به طور مشابه از valgrind استفاده می کنید:
$ ./waf --run tcp-point-to-point --command-template="valgrind %s"
SOURCE
این سند در نوشته شده است restructuredText برای مجسمه ابوالهول و در آن نگهداری می شود
سند/راهنما دایرکتوری کد منبع ns-3.
با استفاده از خدمات onworks.net از ns-3-manual به صورت آنلاین استفاده کنید