برنامج لعرض المتصلين بالشبكة
س: كيف يمكن معرفة عناوين IP وأسماء الأجهزة المتصلة بالشبكة؟
ج: كتبت لكم برنامجا يقوم بالبحث عن
الأجهزة المتصلة بالشبكة.. يمكنكم تحميل البرنامج من هذا الرابط (مرفق الكود
المصدري، بكل من فيجوال بيزيك دوت نت وسي شارب):
بدأ الأمر بمحاولة مني لإجابة سؤال
من أحد الأصدقاء عن معرفة الأجهزة المتصلة بالشبكة.. كان الأامر يبدو بسيطا
للغاية، فكل المطلوب هو عمل أزيز Ping لكل عناوين ال IP المحتملة داخل الشبكة.. هذه العملية ترسل بعض البيانات غير الهامة
لعنوان IP وتنتظر الرد.. فإذا تأخر الرد عن
وقت معين Timeout فمعنى هذا أنه لا يوجد جهاز متصل
له هذا العنوان.. أما إذا جاء الرد، فمعناه أن هذا عنوان جهاز متصل بالشبكة.
تحديد عناوين الشبكة سهل.. فلو طلب
المستخدم العناوين في الشبكة 10.0.0.x فستكون محصورة بين 10.0.0.1 و 10.0.0.254.
ويمكن عمل Ping في دوت نت باستخدام الفئة Ping كالتالي:
Dim p As New Ping ()
Dim reply = p.Send("10.0.0.1", 1000)
If reply IsNot Nothing AndAlso reply.Status = IPStatus.Success Then
// هذا العنوان متصل
End If
إلى هنا والأمر بسيط وجميل ولا
يحتاج جهدا.. أليس كذلك؟
لكن المشكلة ظهرت عند التجربة
العملية.. فعملية فحص كل عنوان في الشبكة تستغرق وقتا خاصة أن العناوين غير
الموجودة تعطل البرنامج لمدة تساوي مدة وقت الانتظار Timeout.. في الكود السابق جعلت هذا الوقت 1000 مللي ثانية
(= ثاتية واحدة).. هذا معناه أن فحص 254 عنوانا ستستغرق أكثر من 254 ثانية أي
حوالي 4 دقائق!.. ولم يفد كثيرا تقليل وقت الانتظار إلى 100 مللي ثانية!
كما أن بعض الشبكات قد تحتوي على
عناوين تصل إلى 255 × 255 عنوانا (أكثر من 65 ألف عنوان!!).. ولا داعي للحديث عن
الشبكات الأكبر من هذا!
إذن فاستخدام هذه الطريقة غير عملي
على الإطلاق!
وكان الحل هو تنفيذ عمليات الـ Ping بطريقة غير متزامنة Asynchronous، لأن هذا معناه أن البرنامج سيرسل
كل عملية Ping ولا ينتظر نتائجها، بل يرسل
التالية والتالية... إلخ مباشرة.. ثم يقرأ النتائج حينما تصل.. هذا سيجعل تنفيذ
البرنامج أسرع بشكل كبير، لأن هذه العمليات تتم على التوازي لا التوالي، وبالتالي
سيكون الوقت الكلي للبرنامج مساويا تقريبا لوقت تنفيذ عملية Ping واحدة أو أكبر بفروق طفيفة!
ولحسن الحظ تمتلك الفئة Ping وسائل غير متزامنة مثل SendAsync.. رائع جدا.. على بركة الله.
لكني عندما جربت هذه الوسيلة، فوجئت
أنها لا تعمل بشكل صحيح في مشاريع تماذج الويندوز، ووجدت آخرين يشتكون من نفس
الأمر!
وهذا معناه أنني مضطر لتنفيذ
العمليات غير المتزامنة بنفسي يدويا باستخدام العمليات الفرعية Threads، وهذا احتاج الكثير من الكود لحل
مشاكل التصارع على البيانات بين العمليات الفرعية!
على سبيل المثال:
لكي أعلم أن تنفيذ كل العمليات
الفرعية قد انتهى (لأعرض النتائج للمستخدم)، حاولت استخدام متغير أزيد قيمته في
نهاية كل عملية فرعية، وعند فحص قيمته لو ساوى 254 إذن فالمهمة قد انتهت.
لكن هذا فشل تماما، بسبب تصارع
العمليات الفرعية على تغيير قيمة هذا المتغير في نفس اللحظة، وبالتالي ظل يأخذ
قيما متضاربة غير حقيقية!.. ولم تنجح جملة SyncLoc (أو lock في سي شارب) في منع المشكلة لسبب غير واضح لي حتى الآن!
وقد حللت هذه المشكلة بجعل كل عملية
فرعية عند انتهائها تضيف عنوان الـ IP الذي تفحصه إلى قائمة List.. فهنا لا يوجد تصارع على القراءة، وإنما كل عملية
فرعية تضيف عنصرا جديدا إلى نهاية القائمة.
على كل حال الكود لديكم، وفيه أفكار
كثيرة مهمة، وقد جعلته عاما، بحيث يمكن للمستخدم اختيار عدد العناوين التي يريد
فحصها بدءا من IP
معين.. فمثلا: لو اختار العنوان 10.0.0.10 وطلب فحص 1000 عنوان، فسأفحص هذا
العنوان ثم أضيف 1 عليه وأفحصه ثم أزيد 1 آخر.. وهكذا، حتى لو انتقلت من خانة إلى
أخرى من خانات العنوان (كأن أصل إلى 10.0.10.100).. والحقيقة أنني سمحت للمستخدم ـ
إذا أراد ـ أن يفحص العناوين حتى 10.255.255.254.. هذا غير عملي، لكنه للتعميم.
البرنامج سريع، يمكنه أن يفحص أول
254 عنوان في أقل من 4 ثوان.. إلا إذا اختار المستخدم زيادة زمن الانتظار Timeout، فالوقت الكلي دائما سيكون أكبر
من أو يساوي زمن الانتظار.
من الفوائد أيضا التي ستجدونها في
المشروع، الأداة التي يكتب فيها المستخدم عنوان IP..
ليست من برمجتي، لكني وجدتها على الإنترنت، وهي موجودة في الملف IPAddressControlLib.dll (والكود الكامل الخاص بها موجود
على الإنترنت لمن أراده.. لكتها تعمل بشكل مستقر ولا تحتاج لتطوير).
أرجو أن يفيدكم هذا البرنامج
كمبرمجين ومستخدمين أيضا.. وبالمناسبة: أنا كتبته بدقة لأستخدمه بنفسي، لأن لدي
برنامج Advanced
IP Scanner
وحينما قارنت نتائج برنامجي به فوجئت أن Advanced IP Scanner كان يخدعني وأن بعض العناوين لا تظهر لسبب ما!!..
فعمليا برنامجي أدق منه.
ولا تبخلوا بمشاركة المنشور،
ليستفيد به أصدقاؤكم، حتى من غير المبرمجين.