منتدى برمجة الشبكات في بيئة الدوت نت

 اسم العضو:fmo_82  الأحد,28/رمضان/1426 هـ,06:00 صباحاً
[ALIGN=center]بسم الله الرحمن الرحيم[/ALIGN] [COLOR=red]حمل من [URL=http://www.bennymar.com/data/fadidotnet/Network_Programming_For_Beginners.pdf]هنا [/URL]الفصول الثلاث الأولى من كتاب احترف برمجة الشبكات والنظم الموزعة مجانا [/COLOR] [URL=http://www.fadidotnet.org/full_version.htm]الخطة ومعلومات كتاب الدورة هنا[/URL] ملاحظة إلى كل مبرمجين ال VB.NET وحتى تعم الفائدة على الجميع تستطيعون ترجمة الأكواد من C Sharp إلى VB.NET باستخدام الرابط التالي : [URL=http://www.developerfusion.com/utilities/convertcsharptovb.aspx]http://www.developerfusion.com/utilities/convertcsharptovb.aspx[/URL] حيث قمت بتجربة الترجمة لأغلب الأكواد ولم يكن هنالك أي مشاكل , من الممكن وجود بعض الإختلافات في بعد أسماء ال Methods لكن في الأغلب متشابهة ولمعرفة الأسم المقابل لها في VB.NET تستطيع الضغط عليها في C# Editor والضغط على المفتاح F1 .. وأي سؤال أو استفسار بخصوص التحويل إلى ال VB.NET لهذه الأكواد انا مستعد ..  

 اسم العضو:محمد أكرم عليان  الاثنين,29/رمضان/1426 هـ,01:29 مساءً
شكرا للأخ فادي على هذه المبادره الطيبه. مع ان لي افكار اخرى و اقتراحات سوف نناقشها جانبا فيما بعد. 

 اسم العضو:fmo_82  الثلاثاء,30/رمضان/1426 هـ,10:39 مساءً
بسم الله الرحمن الرحيم الدرس الأول : مقدمة في برمجة الشبكات و بروتوكول TCP/IP من المعروف ان الشبكة هي مجموعة من الأجهزة متصلة مع بعضها عبر وسيلة اتصال معينة ومن هنا سيندرج لدينا التقسيم المعروف لمنظمة OSIلعملية الإتصال والتي تتكون من سبعة طبقات كل طبقة منها تشكل وظيفة بعينها وتم اختصارها الى اربعة طبقات في برتوكول TCP/IP (خمسة في بعض الكتب)وتبين الصورة المرفقة هذه الطبقات , [IMG]http://www.arabteam2000.com/picload/pics/20_10_05_01_08_22_1129795702layers.JPG[/IMG] لإجراء عملية الاتصال بين Client و Server يلزم ما يلي : في الجهاز المرسل Client : 1- تبدا عملية توليف الرسالة المرسلة في ال Application Layer ووظيفتها هنا التعامل مع الرسالة نفسها وتحويلها من صيغة نصية الى Data يمكن ارسالها عبر الشبكة , ففي برمجيات الدردشة Chat يتم تحويل النص المكتوب الى ASCII Code ثم يتم تحويل هذا الأسكي الى مجموعة من Binary Code توضع في مصفوفة لتجهيزها وارسالها عبر Socket (بقية الطبقات) وهنا توضيح هذه الخطوة في الكود [CODE]String str=Console.ReadLine(); // كتابة الرسالة هنا ووضعها في متغير من نوع ستريغ ASCIIEncoding asen= new ASCIIEncoding(); // تحويل النص المكتوب الى الأسكي byte[] ba=asen.GetBytes(str); //تحويل الأسكي الى باينري كود وتخزينها في مصفوفة من النوع بايت[/CODE] في نموذج osi يتم تقسيم ال upper Layers الى ثلاثة طبقات Application لتعامل مع البرنامج نفسة او ما يسمى user interface Presentation تمثيل البيانات المرسلة وهي كما ظهرت سابقا بتحويل البيانات الى الASCII Session وفيها البدأ بعملية التخاطب بين الجهازين و التعريف ببعضهم البعض( فتح الجلسة) والتي سأتي على شرحها بعد قليل اما في بروتوكول ال TCP/IP فكتفى بوجود طبقة Application والتي تقوم بعمل الطبقات الثلاث الأولى في OSI في session Layer يتم التعرف وفتح الجلسة بعدة خطوات وهي كما يلي : 1- اجراء الإتصال المبدئي بجهاز server عبر ال IP و البورت المحدد وذلك بعد تحديد عملية الإتصال سواء عبر UDP او عبر TCP 2- التعريف بنفسه وعمل ال Authentication اذا تطلب جهاز السيرفر ذلك 3- قبول او رفض الجلسة ويتم ذلك بإرسال الموافقة على فتح الجلسة او رفضها 4- بدأ الجلسة وقيام السيرفر بعمل Listening على البورت الخاص بالبرنامج عندما يتم الموافقة على فتح الجلسة والبدأ بعملية التخاطب يقوم جهاز المرسل Client بتحميل الرسالة الى الطبقة الأخرى وهي هنا طبقة Transport وفي هذه الطبقة يتم تحديد طبيعة الإتصال سواء عبر TCP - Connection Protocol او عبر ال UDP - Connectionless Protocol ففي البروتوكول الأول يتم تحديد طرفين وهما المرسل والمستقبل وبورت الإتصال اما ال UDP فيتم تحديد الطرف المرسل و المستقبل (اختياري) اي انه يمكن عمل ال Broadcast بدون تحديد جهة معينة لأستقبال الرسالة اي ان اي شخص يقوم بتنصت عبر هذا البورت Listening يستطيع استقبال الرسالة , وهنا مثال يوضح عمل هذه الطبقة [CODE]TcpClient tcpclnt = new TcpClient(); // اختيار برتوكول التي سي بي لعملية الإتصال tcpclnt.Connect("192.168.0.2",8001);//حيث يلزم تحديد الطرف مستقبل الرسالة والبورت المخصص[/CODE] ولارسال الرسالة عبر الشبكة نستخدم في الدوت نت ميثود جاهز يقوم بهذه العملية ويسمى Network Stream وهو المسئول عن التعامل مع وسيلة الإتصال وارسال الرسالة الى الطرف المعني بشكل Stream Data او بستخدام ال Socket نفسه وكمثال على ذلك: [CODE] NetworkStream mynetsream = tcpclnt.GetStream (); StreamWriter myswrite = new StreamWriter (mynetsream); myswrite.WriteLine("Your Message"); [/CODE] وبعد ذلك تسلم الى Network Layer وهي مكون من Datalink Layer و Network Layer في OSI طبعا يتولى نظام التشغيل و بروتوكول TCP/IP ارسال الرسالة عبر الشبكة وهنا ملخص عمل كل من Network Layer و DataLink Layer وبعد ذلك تسلم الى Network Layer وهي مكون من Datalink Layer و Network Layer في OSI طبعا يتولى نظام التشغيل و بروتوكول TCP/IP ارسال الرسالة عبر الشبكة وهنا ملخص عمل كل من Network Layer و DataLink Layer [CODE]Network layer : Layer 3 of the Open Systems Interconnection (OSI) reference model for networking. The network layer is responsible for functions such as the following: - Logical addressing and routing of packets over the network - Establishing and releasing connections and paths between two nodes on a network - Transferring data, generating and confirming receipts, and resetting connections Example about network layer : IP-internet protocol , ICMP -internet control message protocol , Routing DataLink layer: The link layer provides physically means Example : ARP Address Resolution Protocol , RARP Reverse Address Resolution Protocol.[/CODE] وبهذا قمت بشرح كيفية الإتصال عبر Layers . اما بنسبة للجهاز المستقبل Server يقوم بالمرور على نفس الطبقات ولكن بالعكس حيث يستلم كرت الشبكة البكت لتحول الى Datalink ثم Network ثم Transport ثم Application ومنها تحول من Binary الى Ascii ومن Ascii الى Text .. وهذه الكود يوضح مبدأ عمل ال Server [CODE]TcpListener myList=new TcpListener("127.0.0.1",8001); // تحديد البورت والأي بي الخاص بسيرفر والذي سيتم التنصت عليه myList.Start();// البدأ بعملية التنصت Socket s=myList.AcceptSocket(); // قبول اي طلب يأتي لفتح جلسة جديدة عبر السوكت byte[] b=new byte[100];//تكوين مصفوفة لأستقبال الرسالة int k=s.Receive(b); // البدأ بلإستقبال والتحويل من الباينري الى الأسكي for (int i=0;i<k;i++) Console.Write(Convert.ToChar(b[i])); طباعة الرسالة بعد تحويلها من اسكي s.Close(); اغلاق السوكت[/CODE] في الدرس القادم سوف نتحدث بإذن الله بشكل اكثر تفصيلا عن السوكت وعن Threads  

 اسم العضو:fmo_82  الأربعاء,01/شوال/1426 هـ,02:48 مساءً
مجموعة الأمثلة لدرس الأول - للمساعدة في التطبيق [CODE]using System.Net.Sockets; using System.IO; private void button1_Click(object sender, System.EventArgs e) { try { TcpClient myclient = new TcpClient ("127.0.0.1",5000); // الإتصال مع السيرفر NetworkStream mynetsream = tcpclnt.GetStream (); StreamWriter myswrite = new StreamWriter (mynetsream); mynetsream .WriteLine(txt_msg.Text); myswrite.Close (); mynetsream .Close (); myclient.Close (); } catch (Exception ex) { MessageBox.Show (ex.Message ); } }[/CODE] الجزء الخاص ب Server [CODE]using System.Net.Sockets; using System.IO; TcpListener mytcpl; // Objects Declaration Socket mysocket; NetworkStream myns; StreamReader mysr; mytcpl = new TcpListener (5000); // Open The Port mytcpl.Start ();// Start Listening on That Port mysocket = mytcpl.AcceptSocket (); // Accept Any Request From Client and Start a Session myns = new NetworkStream (mysocket);// Receives The Binary Data From Port mysr = new StreamReader (myns); // Convert Received Data to String MessageBox.Show (mysr.ReadLine()); // Print The Message mytcpl.Stop(); يفضل اضافة هذه الميثود عند الحدث الخاص بإغلاق البرنامج private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { try { mytcpl.Stop (); Application.Exit(); } catch (Exception ex) {MessageBox .Show (ex.Message );} }[/CODE]  

 اسم العضو:fmo_82  الأربعاء,01/شوال/1426 هـ,02:54 مساءً
بسم الله الرحمن الرحيم , الدرس الثاني : الجزء الأول قمنا سابقا بتعرف على أجزاء OSI و TCP/IP وبينا كيفية التعامل مع هذه الطبقات في البرنامج , واليوم سوف اشرح بعون الله كيفية التعامل مع Socket بشكل أكثر تفصيلا بالإضافة إلى استخدام ال Thread في برمجيات الشبكة .. أولا : ال Socket : قلنا سابقا أن السوكت هي الأداة التي يتم نقل البيانات من خلالها من جهاز إلى أخر ولاستخدامها يلزم في البداية تعريف النيم سبيس System.Net.Sockets حيث يحتوي هذا النيم سبيس على عدد ضخم من الكلاسس والتي يتم استخدامها في برمجيات الشبكة , انظر الرابط التالي لتعرف على جميع المكونات في التفصيل : [URL=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsockets.asp]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsockets.asp[/URL] و الرابط التالي لتعرف على مكونات System.Net بتفصيل: [URL=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnet.asp]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnet.asp[/URL] يمكنك السوكت من نقل Text او Object ,حيث بينا سابقا كيفية التعامل من السوكت لنقل Text وفي هذا الدرس سنبين كيفية التعامل معه لنقل Object , وكما هو الحال في نقل ال Text كنا نحول التكست الى اسكي ثم الى باينري اما في الأبجكت فيتم التعامل معه باستخدام ال Stream Library والتي يتم الوصول اليها من System.IO وتحتوي هذه المكتبة على Binary Reader و Binary Writer تمكنك من التعامل مع أي Object انظر الصورة المرفقة : [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/312/ObjectLib.jpg[/IMG] حيث تساعدك هذه المكتبة على تحويل أي اوبجكت إلى باينري باستخدام Binary Reader لتسهل إرساله عبر الشبكة باستخدام Network Stream ثم تحويله مرة أخرى إلى اوبجكت باستخدام Binary Writer , وكمثال تطبيقي على هذا سوف نقوم ببناء برنامج يقوم بعملية نقل الصورة من جهاز إلى أخر Client/Server وللبدء قم بإنشاء New Form جديد كما هو في الشكل التالي : [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/312/form1.JPG[/IMG] في البداية قم بإضافة النيم سبيسس التالي : [CODE]using System.Net.Sockets; using System.IO;[/CODE] للإجراء عملية الإرسال لا بد أولا من اخذ اوبجك من الكلاس MemoryStream والتي سوف نستخدمها لتخزين الصورة داخل الذاكرة بشكل Stream لكي نحولها لاحقا إلى مصفوفة Binary ثم إرسالها عبر NetworkStream إلى جهاز السيرفر والذي سأتي على شرحه في الجزأ الثاني من هذا الدرس, انظر الكود التالية : [CODE]try { تحديد الباث الخاص بصورة openFileDialog1.ShowDialog (); string mypic_path =openFileDialog1.FileName; pictureBox1.Image = Image.FromFile(mypic_path); MemoryStream ms = new MemoryStream(); pictureBox1.Image.Save(ms,pictureBox1.Image.RawFormat); تخزين الصورة ووضعها في مصفوفة من النوع بايت byte[] arrImage = ms.GetBuffer(); ms.Close(); الاتصال بجهاز السيرفر عبر العنوان والبورت المحدد TcpClient myclient = new TcpClient (txt_host.Text,5020);//Connecting with server إرسال الصورة المخزنة إلى جهاز السيرفر NetworkStream myns = myclient.GetStream (); BinaryWriter mysw = new BinaryWriter (myns); mysw.Write(arrImage);//send the stream to above address إغلاق السوكت والجلسة واللستريم mysw.Close (); myns.Close (); myclient.Close (); } catch (Exception ex){MessageBox.Show(ex.Message );}[/CODE]  

 اسم العضو:fmo_82  الأربعاء,01/شوال/1426 هـ,02:59 مساءً
بسم الله الرحمن الرحيم الدرس الثاني: الجزء الثاني سوف ابدأ في هذا الجزء شرح الجزء الخاص بالسيرفر والذي يقوم بعملية التصنت على البورت واستقبال ال Stream عبر ال Binary Reader وتحويله إلى اوبجكت مرة أخرى , في هذا المثال نريد استقبال صورة وليس شيء أخر وفي هذه الحالة وفرت لدينا الدوت نيت خصائص جديدة في ال Controls الموجودة فيها ومن ضمنها خاصية Image.FromStream الخاصة ب ال PictureBox والتي تسهل علينا إمكانية عرض الصورة المرسلة من خلال Stream لكي يتم تحويلها من Binary Stream إلى صورة تعرض على ال Picturebox انظر المثال التالي : [CODE]using System.Net.Sockets; using System.IO; ----------------------------- // Objects Declaration TcpListener mytcpl; // Declare TCP Listener Socket mysocket; // Declare an object from Socket Class NetworkStream myns; // StreamReader mysr; ----------------------- void Image_Receiver() { mytcpl = new TcpListener (5000);// Open The Port mytcpl.Start ();// Start Listening on That Port mysocket = mytcpl.AcceptSocket ();// Accept Any Request From Client and Start The Session myns = new NetworkStream (mysocket);// Receive The Binary Data From Port pictureBox1.Image = Image.FromStream(myns); // Show The Image that Resaved as Binary Stream mytcpl.Stop();// Close TCP Session if (mysocket.Connected ==true)//if Connected Start Again { while (true) { Image_Receiver();// Back to First Method } } }[/CODE] ولتطبيق قم بإنشاء New Form جديد كما في الشكل التالي : [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/312/Form_Server.JPG[/IMG] أضف الميثود السابقة في كلاس البرنامج ثم قم باستدعائها بواسطة وضع Image_Receiver()اما في ال Constructer الخاص بالبرنامج أو بحدث بدأ التشغيل الخاص بالفورم , وقم بوضع الميثود التالية في حدث Closing الخاص بالفورم : [CODE]private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { try { mytcpl.Stop (); Application.Exit(); } catch (Exception ex) {MessageBox .Show (ex.Message );} }[/CODE] وذلك لتأكد من إغلاق السوكت عند إنهاء البرنامج ,.. قم بإضافة الكود التالي الى ال Save لكي تتمكن من تخزين الصورة المستقبلة [CODE] private void menuItem1_Click(object sender, System.EventArgs e) { try { saveFileDialog1.ShowDialog (); string mypic_path = saveFileDialog1.FileName; pictureBox1.Image.Save(mypic_path); } catch (Exception){} }[/CODE] قم بتشغيل البرنامج الآن ... ماذا تلاحظ !! لقد لاحظت أن البرنامج بطيء جدا لدرجة لا يمكن فيها فتح أي برنامج أخر , فكر بالسبب .. لن أترككم تفكرون كثيرا كون أن ذلك قد يؤدي إلى تعليق الجهاز بالكامل وخاصة إذا لم يتوفر لديك الحجم الكافي من ذاكرة الرام او إذا كان المعالج لديك بطيء نسبيا .. السبب في ذلك اللوب الذي لا ينتهي وعملية التصنت على البورت والتي لا تنتهي أيضا حيث أن البرنامج يعمل على الجزء العام والمخصص لإدارة نظام التشغيل في المعالج وهذا يعني انه لا يوجد مجال لفتح برنامج جديد إذ أن الموارد جميعها محجوزة , إذا ما هو الحل .... لقد وفرت الدوت نيت الحل لهذه المشكلة وهي باستخدام تكنولوجيا ال Threading والتي تسمح بالمعالجة المتوازية على نفس المعالج وذلك من خلال تقسيم المهام على المعالج وعمل Session منفصلة لكل برنامج وهو ما يسمى بال Multitasking.. وهنا لا يؤثر البرنامج على موارد النظام بشكل كبير انظر الشكل التالي : [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/312/Thread1.JPG[/IMG] لاحظ انه قبل اضافة ال Thread كان البرنامج يعمل على منطقة ال Global Area وهذا هو سبب البطء الشديد وبعد استخدام ال Thread تم عمل Session خاص للبرنامج بحيث يعمل بشكل متوازي مع بقية البرامج .. ولاستخدام ال Thread في البرنامج يلزم أولا تعريف المكتبة او انيم سبيس الخاص به وهو [CODE]using System.Threading;[/CODE] ثم قم باشتقاق اوبجكت منه وادرج اسم الميثود الذي تريد عمل Thread له كما يلي : اكتب هذا الكود في حدث بدأ التشغيل للفورم Form1_Load [CODE]Thread myth; myth= new Thread (new System.Threading .ThreadStart(Image_Receiver)); myth.Start ();[/CODE] ألان قم بإضافة Application.ExitThread في حدث ال Closing Form كما يلي [CODE]private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { try { mytcpl.Stop (); Application.ExitThread (); Application.Exit(); } catch (Exception ex) {MessageBox .Show (ex.Message );} }[/CODE] ميزة ال Thread رائعة جدا اذ تمكنك من تشغيل اكثر من Thread وفي نفس الوقت وفي نفس البرنامج وهو ما يسمى بال Multithreading والذي سأتي على شرحه لاحقا بإذن الله .... 

 اسم العضو:fmo_82  الأربعاء,01/شوال/1426 هـ,03:02 مساءً
السلام عليكم , سوف اقوم بإدراج الأمثلة التي يتم طرحها بعد كل درس .. لكن اتمنى القيام بالتطبيق العملي لكل مثال حتى تعم الفائدة على الجميع ... هنا البرنامج الخاص بدرس الثاني والذي يستخدم فيه بروتوكول ال TCP لنقل الصورة من جهاز Client الى Server .. [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/312/Examble2.jpg[/IMG] المثال :  

 اسم العضو:fmo_82  الأربعاء,01/شوال/1426 هـ,03:08 مساءً
بسم الله الرحمن الرحيم الدرس الثالث : Connectionless Sockets Via UDP تحدثنا سابقا عن ال TCP – Connection Oriented Protocol وقلنا ان بروتوكول ال TCP هو بروتوكول موجه وهذا يعني انه يلزم احتواء ال Header الخاص به على عنوان المرسل و عنوان المستقبل كما يلزم ايضا القيام بعمليات التحقق Authentication و يدعم عمليات التحقق من الوصول و التسليم بشكل الصحيح .... لكن ماذا لو كان كل ذلك غير مهم بنسبة لك اذ تريد من برنامجك ان يقوم بعملية بث اذاعي Broadcast لرسالتك ولا يهمك من سوف يستلم الرسالة و ان السرعة في الإرسال و الإستقبال هي الهدف الأساسي اذا وجب عليك ترك بروتوكول ال TCP والتوجه نحو ال UDP User Datagram Protocol ويسمى ايضا بال Connectionless Protocol في هذا البروتوكول تستطيع عمل ما يسمى بال Broadcast و ال Multicast (البرود-يعني الإرسال الى الكل و الملتي-يعني الإرسال الى مجموعة اثنان او اكثر واليوني-يعني الإرسال لواحد فقط) يوجد شرط وحيد يلزم ان تأخذه بعين الإعتبار عند استخدام ال UDP لعملية البث بستخدام Broadcast وهو ان الشبكة التي تريد عمل بث لها تتصل معها بشكل مباشر Direct Connection اي بدون وجود Router بينك وبين المستقبل اذ ان ال Router يمنع عمليات البث الإذاعي Broadcast حيث يلزم ان تكون الشبكة ضمن ال Range Class سواء A او B او C لأستخدام ال UDP يلزم اولا تعريف النيم سبيس System.Net و ال System.Net.Socket لاحظ انه في ال TCP كان يلزم تعريف رقم البورت والعنوان للجهاز المستقبل اما في ال UDP فتستطيع تعريفه كما هو في TCP كما وتستطيع عمل Broadcast بستخدام IPAddress.Any بعد اشتقاق كائن من الكلاس IPEndPoint (وتعني نقطة الهدف) وتستطيع ايضا عدم تحديد رقم البورت وذلك بستخدام الميثود Bind() حيث يتم تعريفها بنقطة الهدف ب 0 ويتم كل ذلك كما يلي كمثال : التالي هو الجزء الخاص بالسيرفر ووظيفته فتح البورت 9050والتنصت عليها ثم استلام الرسالة عبر هذا البورت وتوزيعها على الكل بدون تحديد رقم بورت معين حيث يتم تسليمها على البورت المخصص لعملية البرودكاست وهو البورت صفر: [CODE]لتعريف نقطة الهدف ورقم البورت الخاصة بسيرفر ونستخدمها لكي يقوم السيرفر بستلام الرسالة IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050); لتحديد نوع البرتوكول المستخدم يتم ذلك كما يلي Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); ثم اعطاء نقطة الهدف ورقم البورت الى الميثود بيند ويستخدم هذا الميثود عند الإستقبال فقط newsock.Bind(ipep); الأن تم استقبال الرسالة ونريد بثها الى كل من يتصل مع السيرفر على البورت السابقة ولعمل ذلك يلزم اولا تعريف نقطة الهدف كما يلي IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint Remote = (EndPoint)(sender); لاحظ ان عنوان نقطة الهدف هو اني ورقم البورت صفر وهذا يعني ارسال الرسالة المستلمة الى الكل وبما فيهم الشخص مرسل الرسالة و السيرفر هنا يتم استلام الرسالة من السيرفر الى السيرفر مرة اخرى عبر الشبكة recv = newsock.ReceiveFrom(data, ref Remote); لطباعة عنوان مرسل الرسالة و الرسالة نفسها Console.WriteLine("Message received from {0}:", Remote.ToString()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); نقوم هنا بإرسال رسالة ترحيبية لكل جهاز جديد يشبك على السيرفر نخبره بها انه تم الموافقة على دخوله ضمن الأجهزة طبعا هذه رسالة اختيارية تستطيع حذفها اذا كنت لا تريدها string welcome = "Welcome Customer ..."; data = Encoding.ASCII.GetBytes(welcome); newsock.SendTo(data, data.Length, SocketFlags.None, Remote); هنا لوب لا نهائي الهدف منه هو عدند استقبال اي رسالة في اي وقت من قبل اي جهاز يقوم السيرفر بستلامها وتسليمها الى كل من هو على الشبكة ... اذا اردت تحديد عدد معين من الرسائل المستلمة تستطيع تغيير الترو الى اي رقم تريده while(true) { data = new byte[1024]; recv = newsock.ReceiveFrom(data, ref Remote); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); newsock.SendTo(data, recv, SocketFlags.None, Remote); } هنا يتم اغلاق السوكت في حالة اذا تم الخروج من اللوب الا نهائي طبعا هنا لن يتم الوصول الى هذه النقطة الا اذا وضعنا كلمة بريك داخل الوب وفق شرط معين وهنا نستطيع وضع جملة شرطية انه في حالة استقبال رسالة او نص رسالة معينة اخرج من اللوب وقم بإغلاق السوكت وهذا يعني انك تستطيع عمل تحكم عن بعد للإغلاق السيرفر كما يمكنك وضع جملة تشغيل اي ملف تنفيذي على السيرفر في حالة ورود نص معين وهكذا server.Close();[/CODE] تم الإنتهاء الأن من شرح الجزأ الخاص بسيرفر .. وسأعرض هنا الكود الخاص به بشكل كامل لكي تستطيع تطبيقه وهذا هو الكود: [CODE]using System; using System.Net; using System.Net.Sockets; using System.Text; // سوف استخدم هذه المكتبة لتحويل الأسكي الى باينري و بالعكس class SimpleUdpSrvr { public static void Main() { int recv; byte[] data = new byte[1024]; IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050); Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); newsock.Bind(ipep); Console.WriteLine("Waiting for a client..."); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint Remote = (EndPoint)(sender); recv = newsock.ReceiveFrom(data, ref Remote); Console.WriteLine("Message received from {0}:", Remote.ToString()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); string welcome = " Welcome Customer ..."; data = Encoding.ASCII.GetBytes(welcome); newsock.SendTo(data, data.Length, SocketFlags.None, Remote); while(true) { data = new byte[1024]; recv = newsock.ReceiveFrom(data, ref Remote); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); newsock.SendTo(data, recv, SocketFlags.None, Remote); } } }[/CODE] الأن الجزء الخاص بال Client , يقتصر العمل هنا على قيام ال Client بفتح جلسة مع السيرفر وذلك بعد تعريفه بنقطة الإستلام ورقم البورت وكما تم في السابق اللا ان الإختلاف هو في الوظيفة اذا يقتصر فقط على استقبال الرسالة من السيرفر وارسال اي رساله له عبر البورت المخصص للقيام بهذه العملية انظر الكود التالي : [CODE]using System; using System.Net; using System.Net.Sockets; using System.Text; class SimpleUdpClient { public static void Main() { byte[] data = new byte[1024]; string input, stringData; IPEndPoint ipep = new IPEndPoint( IPAddress.Parse("127.0.0.1"), 9050); Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // في حالة فقدان الإتصال مع السيرفر يظهر الرسالة التاية string welcome = "Hello, are you there?"; data = Encoding.ASCII.GetBytes(welcome); server.SendTo(data, data.Length, SocketFlags.None, ipep); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint Remote = (EndPoint)sender; data = new byte[1024]; int recv = server.ReceiveFrom(data, ref Remote); Console.WriteLine("Message received from {0}:", Remote.ToString()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); //هذا اللوب لكي تستطيع ارسال عدد غير محدد من الرسائل while(true) { input = Console.ReadLine(); // في حالة اذا اردت انهاء الجلسة اكتب // Exit if (input == "exit") break; server.SendTo(Encoding.ASCII.GetBytes(input), Remote); data = new byte[1024]; recv = server.ReceiveFrom(data, ref Remote); stringData = Encoding.ASCII.GetString(data, 0, recv); Console.WriteLine(stringData); } Console.WriteLine("Stopping client"); server.Close(); } }[/CODE]  

 اسم العضو:fmo_82  الأربعاء,01/شوال/1426 هـ,03:11 مساءً
نقاش تابع لدرس الثالث : السؤال الأول : تحدثت لنا عن البرودكاست وقلت انه بإمكانك البث الى اي جهاز على الشبكة لكنك قمت بستخدام الخاصية any مع انه توجد خاصية افضل منها وهي IPAddress.Broadcast فلماذا استخدمت الخاصية any ولم تستخدم هذه الخاصية؟ تستطيع عمل البرود كاست بطريقتين اما بستخدام IPAddress.Any او بستخدام IPAddress.Broadcast ولكن يختلف في ان الأول يلزمه وجود سيرفر يقوم بعملية التنصت على البورت المحدد حيث يستقبل من خلاله اي رسالة ثم يقوم ببثها الى كل الأجهزة اما الثاني فتستطيع من خلاله عمل بث الى كل الأجهزة حيث لا ضرورة لوجود جهاز سيرفر بحيث ان الكل يمكنه التنصت على بورت معين يستقبل ويرسل من خلالها ... السؤال الثاني: طبعا لم تشرح لنا ال IP Multicasting ومع ذلك استخدمت ال IPAddress.Any وعلى حد علمي ان هذه الخاصية تستخدم في ال Multicasting فلماذا استخدمتها في ال برودكاست ؟؟!!! كنت انوي شرح هذا الموضوع في الدرس القادم وبما انك طرحت هذا السؤال فسوف اشرحها لك, نعم استخدمت الخاصية IPAddress.Any في البرودكاست وكلامك ايضا صحيح حيث تستخدم في ال Multicast لكن الفرق اني لم احدد اي مجموعات ولم اقم بوضع ال IP Multicasting وهو محدد بين 224.0.0.0 و 224.0.0.255 في الشبكات المحلية LAN , لذلك اعتبرناها على انها نوع من البرودكاست .. السؤال الثالث: لا ارى فرقا بين البرود كاست و ال Multicast كون ان كليهما يمكن استخدامهما بوجود سيرفر او بدون وجود سيرفر فما هو الفرق؟؟ لا تستعجل فسوف اشرحها إن شاء الله في الدرس القادم لكن عدوني ان يكون هذا النقاش بشكل دائم في الدروس القادمة ...  

 اسم العضو:محمد أكرم عليان  الأربعاء,01/شوال/1426 هـ,04:24 مساءً
أخ فادي دروس اكثر من رائعه ... و جاري التطبيق ... و عند انتهائي من التطبيق سأطلعك على النتائج أولا بأول ... و سأقوم بفتح النقاش حول الاسئله المطروحه ان شاء الله. أشكرك اخي و مارس ابداعاتك و ننتظر منك المزيد.  

 اسم العضو:fmo_82  الأربعاء,01/شوال/1426 هـ,04:55 مساءً
بسم الله الرحمن الرحيم , اشكرك اخي محمد على تشجيعك ودعمك , الدرس الرابع: IP Multicasting واستخدامها لعمل Multicasting Group تحدثنا سابقا عن برتوكول ال UDP وشرحنا كيفية استخدامه لعمل برود كاست حيث تستطيع عمل البرود كاست بطريقتين إما باستخدام IPAddress.Any والذي يلزمه وجود سيرفر يقوم بعملية التصنت على البورت المحدد حيث يستقبل من خلاله أي رسالة ثم يقوم ببثها إلى كل الأجهزة أو باستخدام IPAddress.Broadcast والذي من خلاله يمكن عمل بث إلى كل الأجهزة حيث لا ضرورة لوجود جهاز سيرفر بحيث أن الكل يمكنه التصنت على بورت معين يستقبل ويرسل من خلالها أي رسالة إلى كل الأجهزة وتشبه عملية البرودكاست عملية البث الإذاعي حيث أن الجميع يستمع إلى شخص واحد ولكن يختلف بأن أي شخص يستطيع الإرسال و الاستقبال وفي نفس الوقت ... , وفي هذا الدرس سوف نتحدث عن ال IP Multicasting وذلك بهدف استخدامه لعمل ال Multicasting , يعتبر هذا الموضوع من المواضيع المهمة جدا في برمجيات الشبكات ولهذا خصصت له درس منفصل عن البقية إذ أن اغلب برمجيات ال Conferences تعتمد عليه بشكل كبير ويعرف Multicast على انه الإرسال إلى مجموعة من المستخدمين ( اثنان أو أكثر ) سواء كان Managed باستخدام Client/Server حيث يكون هنالك جهاز Server في الشبكة وظيفته استقبال الرسائل من ال Group Clients ثم إرسالها إلى كامل المجموعة مرة أخرى انظر إلى الشكل التالي : [IMG]http://x11.putfile.com/10/30204154748.jpg[/IMG] لاحظ انه يتم إرسال طلب الانضمام إلى المجموعة من قبل ال Clients وإذا وافق السيرفر على الطلب يقوم بضم عنوان الجهاز إلى ال IP Address List Members الخاصة به حيث يعيد توزيع الرسائل المستقبلة إلى كل الأعضاء الموافق عليهم و الموجودين في قائمة عناوين الأعضاء . النوع الثاني ويسمى بال unmanaged- peer-to-peer Technique حيث أن كل جهاز يعمل ك server و client في نفس الوقت ولا وجود لجهاز سيرفر مركزي مخصص لعملية الاستقبال والتوزيع حيث تتم الموافقة على طلب الانضمام إلى المجموعة بشكل تلقائي وأي جهاز في المجموعة له الحق في الانضمام ثم الاستقبال و الإرسال إلى كامل المجموعة لاحظ الشكل التالي : [IMG]http://x11.putfile.com/10/30204135116.jpg[/IMG] تم تخصيص عناوين خاصة لل Multicasting وهو ما يسمى بال IP Multicast Address وهي كما يلي : المدى من 224.0.0.0 إلى 224.0.0.255 لشبكات المحلية LAN المدى من 224.0.1.0 إلى 224.0.1.255 لل Internetwork المدى من 224.0.2.0 إلى 224.0.255.255 لل AD-HOC Network block كما يوجد تخصيصات أخرى له سوف آتي على ذكرها عند الحاجة ... قدمت الدوت نيت دعم كبير لل IP Multicast باستخدام ال Socket Namespace حيث يتم تعريفها باستخدام ال الميثود SetSocketOption والتي تقوم بإدارة عمليات الانضمام والخروج من والى المجموعة multicast group (join & leave ) كما تستخدم لإضافة وإلغاء العضوية AddMembership و DropMembership و تستخدم الميثود UdpClient Object لتحديد رقم البورت والتي سيتم استقبال البيانات من خلالها بالإضافة إلى تعريف ال IP Multicasting والذي من خلاله تحدد الجهات التي سوف تستقبل الرسالة من خلال تحديد ال Range IP الخاص بشبكات المحلية LAN حيث يستطيع أي شخص يتنصت على هذا البورت ويستخدم نفس ال Range استقبال هذه الرسالة , يستخدم الكود التالي لإرسال رسالة إلى عدة جهات بحيث نستخدم رقم البورت 9050 و ضمن ال Range 224.100.0.1 كمثال: [CODE]using System; using System.Net; using System.Net.Sockets; using System.Text; class MultiSend { public static void Main() { Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse("224.100.0.1"), 9050); byte[] data = Encoding.ASCII.GetBytes("This is a test message"); server.SendTo(data, iep); server.Close(); } }[/CODE] في البداية قمنا بتعريف السوكت بتحديد الجهة التي سوف تستقبل الرسالة وهي (أي شخص يتنصت على الشبكة) ثم تحديد نوع السوكت والبرتوكول المستخدم , وبعد ذلك تحديد نقطة الهدف وذلك بوضع ال IP Multicast الذي نريد ويتبعه رقم البورت التي سيتم استقبال البيانات من خلالها ( بقية الكود تم شرحه سابقا عندما استخدمنا ال UDP لعمل برود كاست) .. ولإنشاء برنامج الاستقبال سوف نستخدم تعريف السوكت نفسه ونضيف ال UdpClient Object ونسند له رقم البورت التي نريد التصنت عليها [CODE]using System; using System.Net; using System.Net.Sockets; using System.Text; class UdpClientMultiRecv { public static void Main() { UdpClient sock = new UdpClient(9050); // التصنت على رقم البورت هذا sock.JoinMulticastGroup(IPAddress.Parse("224.100.0.1"), 50); وهذا يعني انك سوف تتصنت على المدى المحدد IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); // استقبال البيانات وتعبئة الرسالة في مصفوفة من النوع بايت byte[] data = sock.Receive(ref iep); // التحويل إلى اسكي كود ثم طباعة الرسالة على الشاشة string stringData = Encoding.ASCII.GetString(data, 0, data.Length); Console.WriteLine("received: {0} from: {1}", stringData, iep.ToString()); sock.Close(); } }[/CODE] لاحظ انه توجد طرق متعددة لاستقبال البيانات و إرسالها كما يمكن استخدام الكوديين السابقين في نفس البرنامج للإرسال و الاستقبال كما يمكنك إرسال صورة إلى جانب النص ( انظر الدرس الثاني) أو أي شيء أخر يمكن تحويله إلى Binary إذ ما عليك سوى إضافة ال memory Stream وال Binary Reader وال Binary Writer إلى كود الإرسال و الاستقبال كما يمكنك عمل برنامج لإرسال صورة عبر الكاميرا إلى جهات متعددة باستخدام نفس الخاصية والتي سآتي على شرحها في الدروس اللاحقة إن شاء الله ... في هذا الدرس قمنا بتوضيح الأساسيات في ال IP Multicasting ولزيادة المعلومات انظر نتائج البحث التالية : [URL=http://www.google.com/search?hl=en&lr=&q=I...ing+Programming]http://www.google.com/search?hl=en&lr=&q=I...ing+Programming[/URL] في الدرس القادم سوف نتحدث بإذن الله عن : DNS Programming .. لا تتردد أبدا في كتابة أي استفسار أو سؤال حول هذا الدرس أو الدروس السابقة أو أي موضوع آخر يتحدث عن برمجة الشبكات 

 اسم العضو:عبد الرحمن  الجمعة,03/شوال/1426 هـ,01:03 مساءً
ما شاء الله , جهد مميز . بارك الله فيك. 

 اسم العضو:fmo_82  الأحد,05/شوال/1426 هـ,10:45 صباحاً
بسم الله الرحمن الرحيم, اشكرك اخي عبدالرحمن على تشجيعك ودعمك . الدرس الخامس : DNS Programming تعتبر خدمة DNS واحدة من أهم الخدمات التي تستخدم في الإنترنت والشبكات بشكل عام, وتختصر وظيفة DNS بالقيام بعملية ترجمة ال Domain Name إلى Domain IP من وإلى العكس ويتم ذلك من خلال مجموعة كبيرة جدا من مزودات DNS ( والتي تقوم بتحديث قاعدة البيانات الخاصة بها كل فترة معينة) , تبدأ هذه العملية بقيام الA Client بطلب ال Domain الخاص بال Client B وذلك بإدخال Domain Name الخاص به - حيث تم مسبقا قيام ال Client B بتعريف نفسه في قاعدة البيانات الخاصة ب DNS Server - كما يحتوي كل Client على قاعدة بيانات تحتوي على عناوين ال Domains وتسمى بال local DNS حيث يقوم بالبحث بداخلها على عنوان Domain من خلال Domain Name فإذا لم يجده يقوم بطلب عنوان الدومين من ال DNS Server وبعد إيجاده يقوم ال DNS Server بإرسال العنوان إلى ال Client ويقوم بدوره بتخزين العنوان في Local DNS الخاص به , انظر إلى الشكل التالي: [IMG]http://x11.putfile.com/11/30907413713.gif[/IMG] في الدوت نيت يمكننا التعامل مع DNS باستخدام النيم سبيس System.Net والتي تحتوي على جميع ال Classes DNS والتي تحتوي على كل ال Methods الخاصة ب DNS وتقسم هذه الميثودس إلى قسمين متزامن Synchronous Methods و غير متزامن Asynchronous Methods وهي كما يلي: أولا الميثودس المتزامنة Synchronous Methods وهي : GetHostNameوالتي تستخدم لجلب اسم الهوست وترجع هذه الميثود قيمة String تحتوي على ال Computer Name ولا تأخذ هذه الميثود أي باراميترات ويمكن استخدامها كما يلي : [CODE] string hostname = Dns.GetHostName(); [/CODE] الميثود GetHostByName و الميثود GetHostByAddress وتستخدم كل منها كما يلي : [CODE] IPHostEntry host_ip = Dns.GetHostByName(Computer_Name); // لجلب العنوان باستخدام الاسم IPHostEntry host_name = Dns.GetHostByAddress(IP_Address); // لجلب الاسم باستخدام العنوان [/CODE] الميثود Resolve وهي Overloaded Method حيث ترجع Host Name إذا أرسلت لها IP Address وترجع Host Address إذا أرسلت لها Host Name في ال IPHostEntry ولا يختلف استخدامها عن استخدام الميثودس السابقة . وهذا المثال يبين طريقة استخدامها : [CODE] using System; using System.Net; class FMO_DNS { public static void Main() { IPHostEntry IPHost = Dns.Resolve("www.yahoo.com"); // الدومين الذي نريد معرفة الأي بي الخاص به Console.WriteLine(IPHost.HostName); // جلب اسم الدومين بالكامل IPAddress[] addr = IPHost.AddressList; // وضع قائمة العناوين في مصفوفة for(int i= 0; i < addr.Length ; i++) // طباعة عناصر المصفوفة {  Console.WriteLine(addr[i]); } } } [/CODE] ثانيا الميثودس غير المتزامنة Asynchronous Methods : وتبدأ عادة بكلمة Begin أو End ومن الأمثلة عليها : BeginGetHostByName و BeginResolve و EndGetHostByName و EndResolve طبيعة عملها كما هو الحال في الميثودس المتزامنة لكنها تختلف بكون انه لا يشترط تنفيذها لإكمال عمل البرنامج في حين المتزامن لا تسمح بلإنتقال إلى الخطوة الثانية في البرنامج إلا في حالة انتهاء عملها وقد تسبب هذه السيئة بخفض البريفورمانس بشكل عام في البرنامج لذلك ينصح باستخدام الطريقة الغير متزامنة وتستخدم كما يلي : Begin___ [CODE] public static IAsyncResult BeginResolve(string hostname, AsyncCallback requestCallback, object stateObject) [/CODE] حيث يتم وضع الهوست نيم في البراميتر الأول و البراميتر الثاني يعرف فيه ال delegate وتسمح لك بتمرير مدخلات إلا delegate , ويستخدم End____ كما يلي : [CODE] public static IPHostEntry EndResolve(IasyncResult ar) [/CODE] ولمزيد من المعلومات انظر نتائج البحث التالي : [URL=http://www.google.com/search?hl=en&q=C%23+DNS+Programming]http://www.google.com/search?hl=en&q=C%23+DNS+Programming[/URL] في الدرس القادم سوف نتحدث بإذن الله عن SMTP & HTTP Programming  

 اسم العضو:fmo_82  الأحد,05/شوال/1426 هـ,11:11 صباحاً
يقوم هذا المثال الشامل و البسيط بجلب جميع الأيبز الموجودة على الشبكة : [CODE] using System; using System.IO; using System.Diagnostics; using System.Net; using System.Collections.Specialized; namespace NetworkIPs { public class Names { public StringCollection GetNames() { ProcessStartInfo _startInfo = new ProcessStartInfo("net","view"); _startInfo.CreateNoWindow = true; _startInfo.UseShellExecute = false; _startInfo.RedirectStandardOutput = true; Process _process = Process.Start(_startInfo); StreamReader _reader = _process.StandardOutput; StringCollection _machineNames = GetMachineNamesFromProcessOutput(_reader.ReadToEnd()); StringCollection _machineIPs = new StringCollection(); foreach(string machine in _machineNames) { _machineIPs.Add(IPAddresses(machine)); } return _machineIPs; } private static string IPAddresses(string server) { try { System.Text.ASCIIEncoding ASCII = new System.Text.ASCIIEncoding(); // Get server related information. IPHostEntry heserver = Dns.Resolve(server); //assumin the machine has only one IP address return heserver.AddressList[0].ToString(); } catch { return "Address Retrieval error for " + server; } } //string manipulations private StringCollection GetMachineNamesFromProcessOutput(string processOutput) { string _allMachines = processOutput.Substring( processOutput.IndexOf("\\")); StringCollection _machines= new StringCollection(); while(_allMachines.IndexOf("\\") != -1 ) { _machines.Add(_allMachines.Substring(_allMachines.IndexOf("\\"), _allMachines.IndexOf(" ",_allMachines.IndexOf("\\")) - _allMachines.IndexOf("\\")).Replace("\\",String.Empty)); _allMachines = _allMachines.Substring(_allMachines.IndexOf(" ",_allMachines.IndexOf("\\") + 1)); } return _machines; } } public class Runner { static void Main() { Names _names = new Names(); StringCollection names = _names.GetNames(); foreach(string name in names) Console.WriteLine(name); Console.ReadLine(); } } [/CODE]  

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

 اسم العضو:fmo_82  الاثنين,06/شوال/1426 هـ,05:24 صباحاً
اشكرك اخي محمد على اهتمامك وحرصك بنسبة لشرح الأكواد اقوم في البداية بشرح الأجزاء الرئيسية للكود مثل النيمسبيسس ووظائفها الرئيسية وفي نهاية الدرس اضع كود لبرنامج كامل , بنسبة لشرح فمعك حق , قمت بدروس السابقة بشرح كافة الأكواد لاكن هنالك امور يمكن ان نستخدمها في البرنامج لا يفترض بي شرحها كون لا علاقة لها ببرمجة الشبكات ويفترض ان يكون متتبع الدرس قادر على فهم هذه الأمور مسبقا كونها من الأمور الخاصة بأساسيات البرمجة , لاكن الباب مفتوح لأي استفسار او سؤال في اي جزء من اجزاء الأكواد التي اقوم بوضعها سواء له علاقة ببرمجة الشبكات او ليس له علاقة .. ولك جزيل الشكر على حرصك في توصيل المعلومة بشكل السليم 

 اسم العضو:fmo_82  الأربعاء,08/شوال/1426 هـ,08:23 صباحاً
بسم الله الرحمن الرحيم , الدرس السادس: SMTP & POP3 Programming تحدثنا في الدرس السابق عن برمجة برتوكول DNS والمسئول عن عملية ترجمة Domain من اسم نطاق إلى IP وبالعكس وبينا كيفية القيام بهذه العملية في سي شارب , في هذا الدرس سوف نتحدث عن برمجة بعض البروتوكولات الأخرى لطبقة ال Application Layer وهما هنا ال SMTP والمسئول عن إرسال الرسائل عبر البريد الإلكتروني و ال POP3 والمسئول عن عملية توصيل الرسالة إلى الزبون من خلال عمل Download لها من ال Mail Server وفي الدرس اللاحق سوف نتحدث عن ال HTTP Programming والذي يستخدم بشكل أساسي في تصفح ال Web , مع العلم انه يوجد بروتوكولات كثيرة سوف آتي على شرحها عند الحاجة .. الجزء الأول: SMTP – Simple Mail Transfer Protocol Programming من المعروف أن ال Mail Server يقوم بتجزئة عمليات إرسال و استقبال البريد الإلكتروني عبر الإنترنت إلى ثلاثة أجزاء وهي كما في الشكل التالي : [IMG]http://x11.putfile.com/11/3120507239.jpg[/IMG] MTA – Message Transfer Agent والمسئول عن الإرسال Outgoing والتوصيل Incoming للرسائل MDA- Message Delivery Agent و المسئول عن عمليات ال filtering والتأكد من وصول الرسالة MUA- Message User Agent والمسئول عن عملية قراءة و تخزين الرسالة في Database لدى المستقبل Client وتتم هذه العملية باستخدام بروتوكول POP - Post Office Protocol انظر إلى الشكل التالي : [IMG]http://x11.putfile.com/11/31205083798.jpg[/IMG] و يستخدم برتوكول ال SMTP Simple Mail Transfer Protocol بشكل أساسي في ال MTA أي عمليات إرسال Outgoing وتوصيل Incoming الرسائل . لتطبيق يجب أولا التأكد من أنك تملك حساب SMTP من ال Internet Provider الخاص بك تستطيع تجربة ال Account الخاص بك من خلال برنامج ال Outlook Express الموجود مع ال Windows إذا كنت لا تملك حساب SMTP تستطيع تجربة البرنامج من خلال إنشاء Virtual SMTP Server عن طريق ال IIS وذلك بتثبيتها من : Control Panel >> Add/Remove Programs تأكد من تفعيل كل من ال IIS وال SMTP كما في الشكل التالي : [IMG]http://x11.putfile.com/11/31205095192.jpg[/IMG] ثم إعداد السيرفر من ال IIS كما في الشكل التالي : [IMG]http://x11.putfile.com/11/31205105010.jpg[/IMG] تدعم الدوت نيت استخدام بروتوكول ال SMTP من خلال النيم سبيس System.Web.Mail و تحتوي على الكلاس SmtpMail والتي من خلالها نستخدم الميثود Sendوالتي تستخدم لإرسال الرسالة عبر البورت 25 وهو البورت المخصص لبروتوكول SMTP و تعتبر الميثود Send " overloaded Method " حيث تأخذ عدة أشكال إذ بإمكانك استخدامها مع براميتر واحد إلى أربعة باراميترات , وبشكل افتراضي نستخدم البرامترات التالية : [CODE] SmtpMail.Send(string from, string to, string subject, string body) البراميتر الأول يوضع فيه عنوان المرسل والثاني يوضع فيه عنوان المرسل إليه و البراميتر الثالث لعنوان الرسالة والرابع لنص الرسالة . [/CODE] ولعمل برنامج يقوم بإرسال البريد الإلكتروني قم بإنشاء فورم كما في الشكل التالي: [IMG]http://x11.putfile.com/11/31205114565.jpg[/IMG] ثم قم بإضافة النيم سبيس System.Web.Mail , ( إذا لم تظهر لديك .Mail قم بإدراج النيم سبيس System.Web إلى ال References ) ثم قم بكتابة الكود التالي : [CODE] لا تنسى إضافة النيم سبيس هذا في بداية البرنامج using System.Web.Mail; // ثم كتابة الكود هذا في زر الإرسال try { string from = textBox1.Text; string to = textBox2.Text; string subject = textBox3.Text; string body = textBox4.Text; SmtpMail.SmtpServer = textBox5.Text; SmtpMail.Send(from, to, subject, body); }  catch (Exception ex) {MessageBox.Show(ex.Message);} [/CODE] ملاحظة هامة جدا : هذا الكود يعمل بشكل جيد, لاكن يجب التأكد من تفعيل ال SMTP من ال IIS كما ذكر في السابق وقم بوضع IP الخاص ب ال SMTP (والذي تم تعريفه مسبقا في SMTP Virtual Server )بال Textbox SMTP Server , يجب التأكد أيضا من ال SMTP Server لديك يدعم استخدام المكتبة CDO2 - Microsoft Collaboration Data Objects Version 2 وإلا سوف تحصل على Exception يخبرك بأنه لا يستطيع الوصول إلى CDO2 Object , في العادة يتم استخدمها مع Windows XP و Windows 2000 وتعمل بشكل افتراضي عند تثبيت ال SMTP Virtual Server أو مع Microsoft Exchange Server2003 أما إذا كنت تستخدم Exchange Version 5 أو 5.5 فسوف تحصل على ال Exception السابق الذكر . الجزء الأكثر تقدم: SMTP Advanced Programming يعتبر المثال السابق مثال بسيط لإرسال رسائل عبر SMTP باستخدام CDO2 , وفي العادة عند إنشاء برامج مثل برنامج ال Outlook يتم استخدام ال HTML Format بالإضافة إلا إمكانية إرسال ملحقات وطبعا يعطيك عدة خيارات لإرسال و استقبال البريد الإلكتروني هل باستخدام ال HTTP أو ال POP3 ... وهنا سوف نقوم بإنشاء برنامج بسيط يقوم بإرسال واستقبال البريد الإلكتروني باستخدام ال SMTP و POP3 بنسبة لاستخدام ال POP3 فيجب أن يتوفر لديك حساب POP3 من ال ISP الخاص بك أو أن تقوم بتثبيت Microsoft Exchange Server2003 على جهازك وإعداده بحيث يستخدم ال POP3 إذ عندها سوف تحتاج لوجود Domain Controller مثبت على الجهاز و Windows 2003 Server بالإضافة إلى تثبيت الActive Directory عليه. قدمت الدوت نيت دعم ممتاز لاستخدام هذه الخواص وذلك من خلال النيم سبيس System.Web.Mail وباستخدام الكلاس MailMessage لدعم ال HTML Format و الكلاس MailAttachment لدعم إمكانية إرسال ملحقات مع الرسالة ولاكن لبرمجة ال POP3 يلزم استخدام النيم سبيس System.Net.Sockets و System.Net و System.IO حيث يتم عمل Session خاص مع السيرفر للقيام بعملية تفحص وجود رسائل جديدة وفي حالة وجودها يقوم بتعبئتها في List Box أو Treelist حسب الحاجة وعند الضغط على إحداها يقوم ال Client بعمل Download لرسالة من ال Mail Server ولعمل Advanced SMTP eMail Sender قم بأخذ Object من الكلاس MailMessage كما يلي : [CODE] لا تنسى إضافة النيم سبيس هذا في بداية البرنامج using System.Web.Mail; // try { MailMessage mm = new MailMessage(); ثم إضافة الكود التالي وكما في السابق mm.From = textBox1.Text; mm.To = textBox2.Text; // mm.Cc = لاحظ انه يمكنك من الإرسال لأكثر من شخص هذه حسب الحاجة // mm.Bcc = لاحظ انه يمكنك من الإرسال لأكثر من شخص هذه حسب الحاجة mm.Subject = textBox3.Text; mm.Headers.Add("Reply-To", "fadi822000@yahoo.com"); // لوضع أي إضافات تريدها مع الرسالة mm.Headers.Add("Comments", "This is a test HTML message"); mm.Priority = MailPriority.High; // يمكنك وضع خيارات أهمية الرسالة mm.BodyFormat = MailFormat.Html; // نوع الفورمات المستخدم mm.Body = "<html><body><h1>" + textBox4.Text + "</h1></html>"; SmtpMail.Send(mm); } catch (Exception ex) {MessageBox.Show(ex.Message);} [/CODE] لاحظ أن جسم الرسالة يستخدم كود ال HTML وهذا يمكنك من وضع أي لون أو حجم أو أي شيء يمكن عمله باستخدام ال HTML (راجع قسم ال HTML بالمنتدى لتعرف على هذه اللغة السكربتية الرائعة) , ولجعل البرنامج قادر على إرسال ملحقات يجب استخدام الكلاس MailAttachment وإدراج اسم الملف فيه وكما يلي بالكود : [CODE] MailAttachment myattach = new MailAttachment("Your_Attached_File_path.extension", MailEncoding.Base64); mm.Attachments.Add(myattach); [/CODE] وهنا قد انتهينا من عمل برنامج ال SMTP بشكل كامل , طبعا عملية الDesign وغيرها تعتمد على حسب ذوق وذكاء وخبرة المبرمج. في الجزء الثاني من هذا الدرس سوف نتحدث عن برمجة برتوكول POP3- Post Office Protocol Version 3  

 اسم العضو:عبدالله جابر شقليه  الجمعة,10/شوال/1426 هـ,04:17 مساءً
يعطيك العافيه أخ fmo_82 فعلا دروس أكثر من رائعه ولم اشاهدها من قبل ربنا يقويك ويوفقك على هذه الدروس الجميلة. 

 اسم العضو:fmo_82  الجمعة,10/شوال/1426 هـ,06:32 مساءً
اشكرك اخي عبدالله على مشاركتك معنا واتمنى من الله ان يوفقنا واياكم في نشر العلم والمعرفة فنحن نعلم ونتعلم 

 اسم العضو:fmo_82  الثلاثاء,14/شوال/1426 هـ,08:15 صباحاً
بسم الله الرحمن الرحيم , الدرس السادس الجزء الثاني : POP3- Post Office Protocol Version 3 Programming كما تحدثنا سابقا فإن وظيفة برتوكول ال POP3 والذي يعمل في جزء ال MUA - Mail User Agent على بورت 110 ضمن برتوكول ال TCP تكمن في كونه المسئول عن عملية توصيل الرسالة إلى الزبون Client من خلال عمل Download لها من ال Mail Server حيث تحفظ الرسائل في ال Mail Folder والموجود أساسا في جهاز ال Client أنظر إلى الشكل التالي: [IMG]http://x11.putfile.com/11/31205083798.jpg[/IMG] ومن البدائل لل POP3 برتوكول Interactive Mail Access Protocol – IMAP فمن خلاله يستطيع المستخدم إنشاء Mail Folder خاصة به ولاكن في ال Mail server وليس في جهاز الزبون وتعتبر هذه من ميزات ال IMAP وسيئاته بنفس الوقت إذ أن قراءة الرسالة تتم مباشرة من خلال ال Server حيث تستطيع قراءتها من أكثر من Client ولاكن المشكلة فيه هي تحكم مدير خادم الرسائل Mail Server Administrator بحجم ال Mail Folder إذ تكون في العادة سعتها محدودة أنظر إلى الشكل التالي : [IMG]http://x2.putfile.com/11/31805023244.jpg[/IMG] لاحظ أن ال Mail Folder يقع ضمن Mail Server ويتم قراءته بعد التحقق Authentication من اسم المستخدم وكلمة المرور لاكن كما قلنا فإن مشكلته تكمن في محدودية سعة ال Mail Folder لذا ينصح لشركات الكبيرة استخدام ال POP3 كونه غير محدود السعة فالذي يتحكم في السعة هو ال Client ولا دخل ل Mail Server Administrator بها. وبما أننا قررنا اعتماد ال POP3 لعملية قراءة الرسائل سوف نبدأ ببرمجته إذ يلزم الأمر استخدام النيم سبيس System.Net.Sockets و System.Net و System.IO حيث يتم عمل Session خاص مع السيرفر باستخدام ال Socket للقيام بعملية تفحص وجود رسائل جديدة وفي حالة وجودها يقوم بتعبئة عناوينها في List Box أو Treelist خاص حسب الحاجة وعند الضغط على إحداها يقوم ال Client بعمل Download لرسالة من ال Mail Server إلى ال Mail Folder ثم عرضها في Textbox. ولتطبيق قم بإنشاء فورم جديد كما يظهر في الشكل التالي : [IMG]http://x2.putfile.com/11/31805033967.jpg[/IMG] ثم قم بإضافة النيم سبيسس التالية : [CODE] using System.Net; using System.Net.Sockets; using System.IO; [/CODE] لاحظ انه يتم التعامل مع ال Socket وال Stream لإنشاء Session مع السيرفر باستخدام برتوكول ال TCP وقراءة الرسالة من ال POP3 Server . ثم قم بإضافة التعاريف التالية في بداية البرنامج (أي بعد تعريف الكلاس الرئيسي – في منطقة ال Global Declaration) : [CODE] public TcpClient Server;//اشتقاق اوبجكت من برتوكول التي سي بي وذلك بهدف إنشاء الجلسة public NetworkStream NetStrm;// سوف نستخدمه لإرسال معلومات المستخدم public StreamReader RdStrm; // لقراءة المعلومات الواردة من البوب 3 سيرفر public string Data; // لاستخدامها في البرنامج public byte[] szData; // لتخزين البيانات الواردة من البوب 3 سيرفر public string CRLF = "\r\n";// لاستخدامها في البرنامج [/CODE] في ال Connect Button قم بإضافة الكود التالي : [CODE] // create server POP3 with port 110 // لإنشاء سيشن مع البوب سيرفر عبر البورت المخصص وهو 110 Server = new TcpClient(POPServ.Text,110); try { // initialization NetStrm = Server.GetStream(); RdStrm= new StreamReader(Server.GetStream()); Status.Items.Add(RdStrm.ReadLine()); // Login Process //إدخال اسم المستخدم وكلمة المرور وتمريرها إلى البوب سيرفر Data = "USER "+ User.Text+CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData,0,szData.Length); Status.Items.Add(RdStrm.ReadLine()); Data = "PASS "+ Passw.Text+CRLF; //بعد التأكد من اسم المستخدم وكلمة المرور يتم قراءة صندوق الوارد الخاص بالمستخدم szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData,0,szData.Length); Status.Items.Add(RdStrm.ReadLine()); // Send STAT command to get information ie: number of mail and size Data = "STAT"+CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData,0,szData.Length); Status.Items.Add(RdStrm.ReadLine()); [/CODE] قم بإضافة الكود التالي إلى ال Disconnect Button : [CODE] // Send QUIT command to close session from POP server Data = "QUIT"+CRLF; szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData,0,szData.Length); Status.Items.Add(RdStrm.ReadLine()); //close connection NetStrm.Close(); RdStrm.Close(); [/CODE] ولقراءة الرسائل من صندوق الوارد( بشكل افتراضي سيتم قراءة الرسالة الأخيرة ) قم بإضافة الكود التالي إلى ال Read Last Come Email Button : [CODE] string szTemp; Message.Clear(); try { // retrieve mail with number mail parameter Data = "RETR 1"+CRLF; // لتحديد رقم الرسالة المراد قراءتها szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData,0,szData.Length); szTemp = RdStrm.ReadLine(); // تخزين الرسالة بشكل مؤقت حتى يتم طباعتها if(szTemp[0]!='-') { while(szTemp!=".") { Message.Text += szTemp+CRLF; szTemp = RdStrm.ReadLine(); } } else {Status.Items.Add(szTemp);} } catch(InvalidOperationException err) {Status.Items.Add("Error: "+err.ToString());} [/CODE] وهنا قد قمت بشرح كيفية عمل البوب 3 وبرمجته في الدوت نت وهذا مثال بسيط تستطيع البدء منه لعمل مشروع كامل شبيه بال Outlook الخاص بميكروسوفت حيث تستطيع استخدام ملف ال DLL الخاص بالإنترنت إكسبلورر لعرض الرسائل الواردة بدلا من عرضها على شكل HTML Code كما تستطيع عمل Tree List لوضع الرسائل الواردة حيث يكون لكل رسالة رقم تسلسلي يتم وضعه في الكود السابق لقراءتها حيث استخدمت الرقم 1 بشكل افتراضي والذي يقوم بقراءة الرسالة الأخيرة الواردة . في الدرس القادم سوف نتحدث عن برمجة ال HTTP .. انتظرونا  

 اسم العضو:fmo_82  الجمعة,17/شوال/1426 هـ,10:36 مساءً
الأمثلة الخاصة بدرس السادس : SMTP & POP3 Programming  

 اسم العضو:fmo_82  الأربعاء,22/شوال/1426 هـ,12:44 مساءً
بسم الله الرحمن الرحيم , الدرس السابع: HTTP – Hyper Text Transfer Protocol Programming تتلخص وظيفة ال HTTP بشكل عام على انه البرتوكول المستخدم لتوصيل طلب المستخدم User Request إلى الويب سيرفر ثم قيام ال web server بالرد على ال Request والذي يسمى ب Server Response وبتأكيد تستطيع نقل جميع أشكال ال (Multimedia) من النص وصورة و صوت و فيديو وغيره .. من ال Web Server إلى ال Client Application باستخدام Byte Stream object. يعمل برتوكول ال HTTP على ال Application Layer وهذا يعني استخدامه بشكل مباشر من واجهة المستخدم كما هو الحال في DNS,SMTP,POP3,FTP انظر إلى الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/web.gif[/IMG] أولا : Downloading From Web Server نستطيع التعامل مع ال Web Server في الدوت نيت باستخدام الكلاس WebClient الموجود في النيم سبيس System.Net إذ تقدم لنا جميع الإمكانيات لتوصيل طلب الزبون و الرد عليهUser Request & Server Response وتدعم ال WebClient Class ثلاثة Methods لتحميل البيانات من ال Web Server وهي: 1- DownloadData ووظيفتها جلب البيانات من ال Web Server وتخزينها في Byte Array وتعرض على شكل HTML Code وتستخدم كما يلي كمثال : [CODE]using System; using System.Net; using System.Text; class DownloadData_Method { public static void Main () { WebClient wc = new WebClient(); byte[] response = wc.DownloadData("http://www.google.com"); Console.WriteLine(Encoding.ASCII.GetString(response)); } }[/CODE] 2- DownloadFileووظيفتها نقل ملف ما من ال Web Server وتخزينها مباشرة في Local Computer وهو سهل الاستخدام جدا إذ ما عليك سوا تمرير موقع الملف والمكان الذي تريد تخزين الملف فيه ويستخدم كما يلي كمثال : [CODE]using System; using System.Net; class DownloadFile_Method { public static void Main () { WebClient wc = new WebClient(); string filename = "C:\\ra.zip"; Console.WriteLine("Download in Progress Please Waite..."); wc.DownloadFile("http://www.personalmicrocosms.com/zip/ra.zip", filename); Console.WriteLine("file downloaded"); } }[/CODE] 3- OpenRead ووظيفتها إنشاء Read Only Stream بين الزبون والسيرفر لجلب بيانات من URL محدد وتخزينه في Stream Object بعد تمرير ال URL للموقع الذي تريد عرضه وباستخدام الميثود ReadLine نستطيع عرض البيانات المخزنة في ال Stream Object على شكل HTML Code . ملاحظة : تستخدم الميثود Peek لمعرفة نهاية ال Stream Object . [CODE]using System; using System.IO; using System.Net; class OpenRead_Method { public static void Main () { WebClient wc = new WebClient(); string response; Stream strm = wc.OpenRead("http://www.google.com"); StreamReader sr = new StreamReader(strm); while(sr.Peek() > -1) {  response = sr.ReadLine();  Console.WriteLine(response); } sr.Close(); } }[/CODE] ويحتوي ال WebClient Class على مجموعة من ال Properties والتي تستخدم لجلب معلومات عن ال Web Host مثلproperty ResponseHeaders والذي يستخدم لجلب معلومات هامة عن ال web host مثل عدد ال Headers ونوع ال cash control واسم ال Server و نوع ال Encoding المستخدم وغيرها من المعلومات الهامة, ويستخدم كما يلي كمثال: [CODE]using System; using System.Net; class ResponseHeaders_property { public static void Main () { WebClient wc = new WebClient(); byte[] response = wc.DownloadData("http://www.google.com"); WebHeaderCollection whc = wc.ResponseHeaders; Console.WriteLine("header count = {0}", whc.Count); for (int i = 0; i < whc.Count; i++) { Console.WriteLine(whc.GetKey(i) + " = " + whc.Get(i)); } } } //Output: //header count = 6 //Cache-Control = private //Content-Type = text/html //Set-Cookie = PREF=ID=6ae22f44980c5d78… //7JRA; expires=Sun, 17-Jan-2038 19:14: //Server = GWS/2.1 //Transfer-Encoding = chunked //Date = Wed, 23 Nov 2005 10

58 GMT[/CODE] ثانيا : Uploading to Web Server يدعم ال WebClient أربعة Methods لتحميل البيانات إلى ال Web Server وهي : 1- OpenWrite ويستخدم لإرسال Stream Data إلى ال Web Server وذلك بعد تمرير عنوان ال URL للملف والنص الذي نريد كتابته على ال Web Page طبعا يجب أن تملك الصلاحيات لذلك ويستخدم كما يلي كمثال : [CODE]using System; using System.IO; using System.Net; class OpenWrite_method { public static void Main () { WebClient wc = new WebClient(); string data = "<h1>Welcome to My Page</h1>"; Stream strm = wc.OpenWrite("C:\\mypage.html"); StreamWriter sw = new StreamWriter(strm); sw.WriteLine(data); sw.Close(); strm.Close(); } }[/CODE] 2 – UploadData ويستخدم لنقل محتويات مصفوفة من النوع Byte إلى ال Web Server وهذا يعني انك تستطيع من خلالها رفع أي نوع من البيانات مثل النص الصور الفيديو وغيره إلى ال web server بعد تحويلها إلى Byte Array ويستخدم كما يلي كمثال : [CODE]using System; using System.Net; using System.Text; class UploadData_Method { public static void Main () { WebClient wc = new WebClient(); string data = "This is The Text Before Converted it to Byte"; byte[] dataarray = Encoding.ASCII.GetBytes(data); wc.UploadData("C:\\mydata.txt", dataarray); } }[/CODE] 3- UploadFile وتستخدم هذه الميثود لرفع ملف من ال Local Computer إلى ال Web Host وهي بسطة الاستخدام جدا وتستخدم كما يلي كمثال : [CODE]using System; using System.Net; class UploadFile_Method { public static void Main () { WebClient wc = new WebClient(); wc.UploadFile("http://www.yoursite.com", "C:\\myfile.html"); } }[/CODE] 4- UploadValues وتستخدم لرفع Collection من البيانات وال values الخاصة بها إلى الويب سيرفر وذلك بعد تحويل ال Collection إلى Byte Array ولتعريف Collection نستخدم الكلاس NameValueCollection الموجود في النيم سبيس System.Collections.Specialized وبعد تعريفه نستخدم الميثود add لإضافة ال Collection جديد.. وتستخدم كما يلي كمثال : [CODE]using System; using System.Collections.Specialized; using System.Net; using System.Text; class UploadValues_Method { public static void Main () { WebClient wc = new WebClient(); NameValueCollection nvc = new NameValueCollection(); nvc.Add("firstname", "Fadi"); nvc.Add("lastname", "Abdel-qader"); byte[] response = wc.UploadValues("http://localhost/mypage.aspx", nvc); Console.WriteLine(Encoding.ASCII.GetString(response)); } }[/CODE] ثالثا :المواضيع الأكثر تقدما في ال HTTP Programming: يعتبر هذا الجزء من أهم الأجزاء في برمجة تطبيقات Web Client Applications والذي سوف نتحدث فيه عن استخدام كل من ال HttpWebRequest Class و ال HttpWebResponse Class : 1- استخدام HttpWebRequest Class : يحتوي هذا الكلاس على مجموعة من ال Properties والتي تستخدم بشكل أساسي في تطبيقات ال Web Client Applications لإنشاء مثل : 1- استخدام خاصية ال Web Proxy : والتي نمرر فيها عنوان ال Proxy Server ورقم البورت حتى نستطيع التعامل مع ال HTTP Web Requestsمن خلف Proxy Server أو Firewall ويتم تعريف ال Proxy Server Prosperity كما يلي كمثال : [CODE]using System; using System.Net; class ProxyServer_Property { public static void Main () { HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create( "http://www.google.com"); WebProxy proxysrv = new WebProxy("http://proxy1.server.net:8080"); hwr.Proxy = proxysrv; } }[/CODE] نعرف في البداية ال HttpWebRequest Object ثم نعرف WebProxy Object من الكلاس webProxy ونسند له عنوان ال Proxy Server ورقم البورت وبعد ذلك نستطيع إسناده إلى أي اوبجكت باستخدام الخاصية Proxy التي تكون موجودة عادة في جميع HttpWebRequest Objects .. 2- استخدام ال HttpWebrequest لإرسال بيانات إلى الويب سيرفر باستخدام ال Streams وتستخدم كما يلي كمثال : [CODE]HttpWebrequest hwr = (HttpWebRequest)WebRequest.Create("http://localhost"); Stream strm = hwr.GetRequestStream(); StreamWriter sw = new StreamWriter(strm); sw.WriteLine(data);[/CODE] بعد تعريف ال HttpWebRequest Object نقوم بتعريف Stream Object ونسند له ال Request Stream من خلال الميثود GetRequestStream . 2 - استخدام HttpWebResponse Class: تستخدم ال HttpWebResponse Object لإرجاع بيانات من الويب سيرفر إلى ال Client حيث نستخدم الميثود GetResponse و الميثود BeginGetResponse لهذه العملية ولا يوجد فرق في وظيفة هذه الميثودس سوى أن BeginGetResponse تعتبر asynchronous Method . يحتوي ال HttpWebResponse Object على عدد من ال Properties وهي : 1- CharacterSet : وتستخدم لتحديد نوع ال Character Set 2- ContentEncoding : وتستخدم لعملية ال encoding 3- ContentLength : وتستخدم لمعرفة حجم الرد 4- ContentType : لتحديد نوع ال Respone 5- Cookies : لتعامل مع ال Cookies ولستخدامها يجب أولا إنشاء ملف Cookie فارغ وتعريفه كما يلي كمثال : [CODE]HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create("[URL=http://www.amazon.com]http://www.amazon.com[/URL]"); hwr.CookieContainer = new CookieContainer();[/CODE]وذلك قبل ال HTTP Request ثم نسنده إليه كما يلي : [CODE]HttpWebResponse hwrsp = (HttpWebResponse)hwr.GetResponse(); hwrsp.Cookies = hwr.CookieContainer.GetCookies(hwr.RequestUri);[/CODE] 6- Headers : لمعرفة ال HTTP Headers 7- LastModified : يرجع فيه وقت وتاريخ أخر تعديل 8- Method : لمعرفة الميثود والتي تستخدم في ال HTTP Response 9 – ProtocolVersion : لمعرفة ال HTTP Version 10 – ResponseUri : ال URL الخاص بسيرفر 11 – Server : لمعرفة اسم السيرفر 12 – StatusCode : لمعرفة نوع ال Coding امستخدم 13 – StatusDescription : لإرجاع Text يحتوي على حالة ال HTTP في الدرس القادم سوف نتحدث عن الProgramming Web Services & XML إنشاء الله .. لتحميل كافة الدروس انظر التوقيع لتحميل هذا الدرس على شكل PDF File :  

 اسم العضو:fmo_82  الأربعاء,22/شوال/1426 هـ,12:55 مساءً
لتحميل السبعة دروس السابقة على شكل PDF File :  

 اسم العضو:محمد أكرم عليان  السبت,25/شوال/1426 هـ,09:16 مساءً
راااااائع فعلا امور مفيده اكثر مما تخيلت. مشكور فادي على المجهود الرائع. كان لي اخ فادي ايضا بعض الاضافات و التعديلات على الاكواد التي وضعتها و سأقوم بإرفاقها لك قريبا للنقاش. 

 اسم العضو:fmo_82  السبت,25/شوال/1426 هـ,09:58 مساءً
اشكرك اخي محمد , ونحن بلإنتظار  

 اسم العضو:fmo_82  الثلاثاء,06/ذو القعدة/1426 هـ,08:46 مساءً
بسم الله الرحمن الرحيم الدرس الثامن: Web Services Programming تحدثنا في الدرس السابق عن برمجة ال HTTP وبينا فيه كيفية التفاعل بين ال web server وال client ويعتبر هذا الدرس مكمل لما تحدثنا عنه سابقا, تتلخص وظيفة استخدام ال web services بإمكانية الاستفادة من ال Methods الموجودة بال web server داخل برنامج الزبون وباستخدام برتوكول ال SOAP وهو اختصار ل Simple Object Access Protocol يتم نقل ال Result من ال web Services server إلى ال Client بعد تحويلها إلى ال XML - extensible Markup Language حيث تنقل عبر برتوكول ال HTTP إلى جهاز الزبون والهدف من استخدامه هو تسهيل وصول ال Data من ال web server إلى ال Client من خلال ال firewalls والبيئات المختلفة إذ أن جميع بيئات الشبكات تدعم برتوكول ال HTTP والذي يعمل على البورت 80 . ولا تختلف لغة ال XML عن ال HTML إذ تستخدم نفس القواعد في ال HTML وهي مجموعة من الElements وال Attributes مثل ال </> <> لكن تتميز بمرونة اكبر وكمثال عليها : [CODE] <myStuff> <myName>FADI Abdel-qader</myName> <myTelephone>+962796...</myTelephone> <myEmail>fadi822000@yahoo.com</myEmail> <myAge>23</myAge> <mySex>M</mySex> </myStuff>[/CODE] ويتم استدعائها في الدوت نيت باستخدام النيم سبيسس System.xml حيث يتم قراءتها باستخدام الميثود Load الموجود في ال XmlDocument Class كما يلي : [CODE]using System.Xml; // Then you can Read any XML File as Below: XmlDocument xDoc = new XmlDocument(); xDoc.Load(@"C:\myinfo.xml"); XmlNodeList name = xDoc.GetElementsByTagName("myName"); XmlNodeList telephone = xDoc.GetElementsByTagName("myTelephone"); XmlNodeList email = xDoc.GetElementsByTagName("myEmail"); XmlNodeList age = xDoc.GetElementsByTagName("myAge"); XmlNodeList sex = xDoc.GetElementsByTagName("mySex"); MessageBox.Show( "Name: " + name[0].InnerText +"\n"+ "Telephone: " + telephone[0].InnerText +"\n"+ "Email: "+ email[0].InnerText +"\n"+ "Age: "+ age[0].InnerText +"\n"+ "sex: "+ sex[0].InnerText +"\n"[/CODE] تمر عملية استخدام ال web services بثلاثة مراحل وهي : 1- The web service server : والذي يتم من خلاله إرسال واستقبال البيانات عبر برتوكول ال SOAP باستخدام ال IIS وال ASP.NET . 2- The proxy object : والذي يسمح لل Client بإرسال و استقبال البيانات من وإلى ال web Services Server حيث يتم تعريفه في ال HttpWebRequest من خلال الكلاس WebProxy وهو ما بينته في الدرس السابق. 3- The client application : وهو الواجهة الخاصة بزبون والتي يتم ربطها بال Web Services Server انظر إلى الشكل التالي : [IMG]http://x12.putfile.com/12/33918083661.jpg[/IMG] ولإنشاء web services server نقوم بعمل مشروعWeb Services ASP.NET جديد ونستدعي النيم سبيسس System.Web.Services ثم نقوم بتوريث الكلاس WebService للكلاس الرئيسي للمشروع وكما يلي كمثال: [CODE]using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://my_url.com/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class Service : System.Web.Services.WebService { public Service () {} [WebMethod] public int Add(int a, int b) { return a + b; } }[/CODE]حيث يتم استقبال قيمتين A و B وبعد ذلك يقوم بإرجاع ناتج جمع القيمة الأولى مع القيمة الثانية إلى ال Client على شكلXML باستخدام برتوكول ال SOAP وكما يظهر في الشكل التالي : [IMG]http://x12.putfile.com/12/33918094727.jpg[/IMG] [IMG]http://x12.putfile.com/12/33918110966.jpg[/IMG] ولإنشاء برنامج ال Client يجب أولا تحويل الكلاس السابق إلى Dll File و إرفاقه بال Client Resources ويتم استخدامه كما يلي : [CODE]using System; class Client_side { public static void Main(string[] argv) { My_main_class mm = new My_main_class(); int x = Convert.ToInt16(argv[0]); int y = Convert.ToInt16(argv[1]); int sum = mm.Add(x, y); Console.WriteLine(sum); } }[/CODE] قد بينت هنا الأساسيات في برمجة ال web Services وسيتم الخوض في التفاصيل لاحقا إن شاء الله .. سوف نتحدث في الدرس القادم عن برمجة ال FTP Programming .. لتحميل كافة الدروس انظر التوقيع لتحميل الدرس الأخير : 

 اسم العضو:fmo_82  الأحد,11/ذو القعدة/1426 هـ,12:29 صباحاً
بسم الله الرحمن الرحيم الدرس التاسع FTP – File Transfer Protocol Programming : سوف نبدأ هنا بشرح برتوكول أخر من برتوكولات ال Application Layer وهو برتوكول ال FTP والذي يستخدم بشكل أساسي في عملية تنزيل downloading و رفع uploading الملفات من و إلى ال FTP Server وكالعادة في اغلب برمجيات الشبكات و التي تعتمد على وجود Client/Server حيث يقوم السيرفر بتصنت على البورت المخصص لل FTP وهو البورت 21 باستخدام ال TCP Connection Oriented Protocolحيث يبقى السيرفر بوضع الانتظار لورود طلب من ال Client بإنشاء Session معه وبعد إجراء عمليات التحقق Authentication والتأكد من الصلاحيات يتم الموافقة على البدء بالجلسة حيث يتم تحديد رقم البورت والذي سوف يتم استقبال البيانات من خلاله ويتم الإرسال إلى جهاز الزبون عبر البورت 20 في السيرفر وتتضح هذه العملية كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34320163693.jpg[/IMG] لتفعيل خدمة ال FTP لديك بحيث يعمل جهازك ك FTP Server يجب أولا التأكد من أن ال FTP Services مثبتة لديك مع ال IIS و كما يظهر في الشكل التالي : [IMG]http://x11.putfile.com/12/34320200613.jpg[/IMG] ومن ثم التأكد من تفعيلها ب Services من Control Panel ثم Administrative Tools ثم Services وكما يظهر في الشكل التالي : [IMG]http://x11.putfile.com/12/34320211420.jpg[/IMG] ثم التأكد منه في ال IIS بحيث يظهر كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34320225710.jpg[/IMG] أولا : FTP Commands تشبه عملية الاتصال و الاستخدام لل FTP عملية ال Telnet إلى حد كبير حيث يدعم برتوكول ال FTP مجموعة من الأوامر والتي يتم من خلالها عملية التخاطب مع السيرفر أو مع ال Remote Host وتضح هذه العملية كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34320250579.jpg[/IMG] وهنا شرح لأهم ال Commands FTP: [IMG]http://x11.putfile.com/12/34320272890.jpg[/IMG] ثانيا : التعامل مع ال FTP في الدوت نيت باستخدام COM Components : تدعم الدوت نيت استخدام ال FTP عبر ITC – Internet Transfer Control وهو جزء من ال COM Components Controls وللبدء قم بإنشاء New Windows Application كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34320283851.jpg[/IMG] ثم قم بإضافة النيم سبيسس التالية : [CODE]using System.IO; using System.Reflection;[/CODE] ثم إضافة الكود التالي إلى ال Upload Button : [CODE] private void button1_Click(object sender, System.EventArgs e) { FileInfo thisFile = new FileInfo(tbFile.Text); Type ITC; object[] parameter= new object[2]; object ITCObject; ITC = Type.GetTypeFromProgID("InetCtls.Inet"); ITCObject = Activator.CreateInstance(ITC); parameter[0] = (string)tbServer.Text; parameter[1] = (string)"PUT " + thisFile.FullName + " /" + thisFile.Name; ITC.InvokeMember("execute", BindingFlags.InvokeMethod,null, ITCObject, parameter); }[/CODE] تم في البداية تعريف ال ITC من خلال ال Type Class والموجود ضمن النيم سبيس System.Reflection ثم عرفنا Array من النوع Object وذلك لاستخدامها في تمرير اسم الملف و ال FTP Server إلى الميثود InvokeMember والموجودة ضمن ال ITC Control Object ... سوف تجد الملف الذي سيتم رفعه في المجلد : C:\Inetpub\ftproot ثالثا : التعامل مع ال FTP في الدوت نيت باستخدام ال Web Class : يمكن برمجة ال FTP باستخدام web Class والموجودة ضمن النيم سبيسس System.Net وتشبه عملية التعامل معه كما في التعامل مع الWebRequest و ال webResponse Classes و التي تعاملنا معها في برمجة ال HTTP حيث يمكننا الاستفادة منها لتعامل مع ال FTP Protocol وهي كما يلي : - WebClient إذ تم دعم dot net Framework 2 استخدام الكلاس WebClient والذي يدعم التعامل مع ال FTP والذي يتم استدعائه من النيم سبيسس System.Net ويتم تعريفه كما يلي : [CODE]using System; using System.Net; namespace Web_Client { class Program { public static void Main(string[] args) { string filename = "ftp://ms.com/files/dotnetfx.exe"; WebClient client = new WebClient(); client.DownloadFile(filename, "dotnetfx.exe"); } } }[/CODE] - FtpRequestCreator ويستخدم لتسجيل وبدأ العمل مع ال FTP ويعرف كما يلي : [CODE] using System; using System.Net; namespace FTP { public class FtpRequestCreator : IWebRequestCreate { public FtpRequestCreator() { } public System.Net.WebRequest Create(System.Uri uri) { return new FtpWebRequest(uri); } } }[/CODE] - FtpWebRequest ويستخدم لعمل download or upload a file on an FTP server ويتم تعريفها كما يلي : [CODE] using System; using System.Net; namespace FTP { public class FtpWebRequest : WebRequest { private string username = "Fadi"; internal string password = "fff"; private Uri uri; private bool binaryMode = true; private string method = "GET"; internal FtpWebRequest(Uri uri) { this.uri = uri; } public string Username { get { return username; } set { username = value; } } public string Password { set { password = value; } } public bool BinaryMode { get { return binaryMode; } set { binaryMode = value; } } public override System.Uri RequestUri { get { return uri; } } public override string Method { get { return method; } set { method = value; } } public override System.Net.WebResponse GetResponse() { FtpWebResponse response = new FtpWebResponse(this); return response; } } }[/CODE] - FtpWebResponse ويستخدم لعملية الرد من قبل السيرفر ويتم تعريفها كما يلي: [CODE] using System; using System.IO; using System.Net; using System.Net.Sockets; namespace FTP { public class FtpWebResponse : WebResponse { private FtpWebRequest request; private FtpClient client; internal FtpWebResponse(FtpWebRequest request) { this.request = request; } } } [/CODE] - FtpWebStream ويستخدم لتعريف ال Stream والذي سوف يستخدم لعملية النقل ويعرف بشكل مبدئي كما يلي : [CODE] using System; using System.IO; using System.Net.Sockets; namespace FTP { internal class FtpWebStream : Stream { private FtpWebResponse response; private NetworkStream dataStream; public FtpWebStream(NetworkStream dataStream, FtpWebResponse response) { this.dataStream = dataStream; this.response = response; } } }[/CODE] رابعا : مثال تطبيقي لرفع ملف من جهاز Client إلى جهاز Server باستخدام ال Stream وال Socket: في هذا الجزء سوف نقوم بإنشاء برنامجين Client / Server وبتعامل مع ال Stream Library سوف نقوم بتحويل الملف إلى Byte Array و إرساله عبر ال Stream باستخدام ال Socket و TCP Connection , ولبرمجة الجزء الخاص بالإرسال أو ال Client قم بإنشاء مشروع جديد كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34320370342.jpg[/IMG] سوف نستخدم النيم سبيسس التالية : [CODE]using System.IO; using System.Net; using System.Net.Sockets; using System.Text;[/CODE] في ال Send Button قم بكتابة الكود التالي : [CODE]try { Stream fileStream = File.OpenRead(textBox1.Text); // Alocate memory space for the file byte[] fileBuffer = new byte[fileStream.Length]; fileStream.Read(fileBuffer, 0, (int)fileStream.Length); // Open a TCP Connection and send the data TcpClient clientSocket = new TcpClient(textBox2.Text,8880); NetworkStream networkStream = clientSocket.GetStream(); networkStream.Write(fileBuffer,0,fileBuffer.GetLength(0)); networkStream.Close(); } catch (Exception ex){MessageBox.Show(ex.Message);}[/CODE] قمنا في البداية بقراءة الملف الذي نود إرساله وتخزينه ب Stream Object وحتى نستطيع إرساله عبر ال Socket لابد من تحويله إلى مصفوفة من النوع Byte وقمنا بتسميته ب fileBuffer ثم تعبئته باستخدام الميثود Read والموجودة ضمن fileStream وبعد ذلك قمنا بإنشاء اتصال مع ال Server باستخدام ال TCP Connection حيث تم إرسال محتويات ال fileBuffer إلى ال Server باستخدام NetworkStream Class ... ولبرمجة جزء Server وهو المسئول عن استقبال الملف وتخزينه قم بإنشاء مشروع جديد كما يظهر في الشكل التالي : [IMG]http://x11.putfile.com/12/34320374651.jpg[/IMG] سوف نستخدم النيم سبيسس التالية : [CODE]using System.Threading; using System.Net; using System.Net.Sockets; using System.Text; using System.IO;[/CODE] ثم قم بكتابة ميثود جديدة وليكن اسمها handlerThreadوكما يلي : [CODE] public void handlerThread() { Socket handlerSocket = (Socket)alSockets[alSockets.Count-1]; NetworkStream networkStream = new NetworkStream(handlerSocket); int thisRead=0; int blockSize=1024; Byte[] dataByte = new Byte[blockSize]; lock(this) { // Only one process can access // the same file at any given time Stream fileStream = File.OpenWrite(@"c:\upload"); while(true) { thisRead=networkStream.Read(dataByte,0,blockSize); fileStream.Write(dataByte,0,thisRead); if (thisRead==0) break; fileStream.Close(); } lbConnections.Items.Add("File Written"); handlerSocket = null; }[/CODE] ثم قم بكتابة ميثود أخرى جديدة وذلك لفتح TCP Connection على البورت 8880 وهو افتراضي والتصنت عليها وليكن اسمها listenerThreadوكما يلي : [CODE] public void listenerThread() { TcpListener tcpListener = new TcpListener(8880); tcpListener.Start(); while(true) { Socket handlerSocket = tcpListener.AcceptSocket(); if (handlerSocket.Connected) { lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected."); lock (this) { alSockets.Add(handlerSocket); } ThreadStart thdstHandler = new ThreadStart(handlerThread); Thread thdHandler = new Thread(thdstHandler); thdHandler.Start(); } } }[/CODE] ثم قم بإضافة الكود التالي إلى حدث بدأ تشغيل البرنامج Form Load : [CODE] private void Form1_Load(object sender, System.EventArgs e) { IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName()); lbConnections.Text = "My IP address is " + IPHost.AddressList[0].ToString(); alSockets = new ArrayList(); Thread thdListener = new Thread(new ThreadStart(listenerThread)); thdListener.Start(); }[/CODE] باستخدام ال Thread تم تنفيذ ال listenerThread Method والتي قمنا فيها بتعريف ال tcpListener وتفعيله على البورت 8880 حيث سيتم قبول أي طلب يأتي من ال Client على هذا البورت وبعد ذلك استدعاء الميثود handlerThread والتي سيتم فيها استقبال ال Stream Data وتخزينها في Byte Array ثم قراءتها وتخزينها في المكان المحدد وباستخدام ال fileStream.Write حيث مررنا له ال Stream والذي يحتوي على اسم الملف thisRead وال dataByte Array...  

 اسم العضو:fmo_82  الأحد,11/ذو القعدة/1426 هـ,12:35 صباحاً
وهنا قد تم الانتهاء من ال Chapter1 وفي الجزء التالي من هذه السلسلة سوف نتحدث عن أمور أكثر تقدما في برمجة الشبكات وسوف نأتي على بعض الجزيئيان ونفصلها بشكل اكبر إنشاء الله مثل : Stream Libraries Network Layer Programming Remotting Threading and the Asynchronous Pattern Security & Authentications … لتحميل Chapter1 : تسعة دروس  

 اسم العضو:students  الثلاثاء,13/ذو القعدة/1426 هـ,04:56 صباحاً
أخي فادي تسلم على هذة الدروس المميزة جدا وجزاك الله ألف خير . ونحن في إنتظار المزيد . 

 اسم العضو:fmo_82  الجمعة,16/ذو القعدة/1426 هـ,11:07 مساءً
بسم الله الرحمن الرحيم , الدرس العاشر: Managed I/O: Streams, Readers, and Writers : تحدثنا سابقا في الجزء الأول بشكل عام عن استخدامات ال Streams Library واستخدامها لإرسال Binary Data و Text Data من جهاز إلى آخر وكمثال قمنا بإرسال صورة من ال Client إلى ال Server باستخدام ال Stream Reader & Stream Writer .. إن الهدف من إنشاء مكتبات ال Stream هو تسهيل عملية نقل البيانات من مكان إلى أخر سواء عبر الشبكة أو داخل نفس الجهاز كما هو الحال بتعامل مع الملفات أو التعامل مع الطابعة أو أي طرفية أو جهاز آخر موصول بالكمبيوتر حيث تسهل علينا عملية تحويلها إلى Byte Array وإرسالها وهو ما حل الكثير من المشاكل التي كانت تواجه المبرمجين في التعامل مع Binary Data .. يمكن التعامل مع ال Stream بأسلوبين المتزامن Synchronous والغير متزامن Asynchronous وبشكل افتراضي تعمل جميع ال IO Streams بالأسلوب المتزامن لاكن العيب فيه هو تأثيره الشديد على أدائية النظام إذ يقوم بإغلاق الProcessing Unit في ال Thread المخصصة للبرنامج بحيث لا يسمح بتنفيذ أي أمر آخر إلا بعد الانتهاء من العملية الجارية ولا ينصح ابدآ استخدام الأسلوب المتزامن في حالة إذا كنت تتعامل مع أجهزة قراءة وكتابة بطيئة نسبيا مثل ال Floppy Disk أو ال Magnetic Tape لكنها مهمة جدا بالبرمجيات التي تعتمد على أنظمة الزمن الحقيقي أو ال Real Time Systems حيث أنها تعتمد الأسلوب المتزامن في عملية إرسال واستقبال البيانات وهو ما يمنع القيام بأي عملية أخرى إلى حين الانتهاء من تنفيذ الأمر ومن الأمثلة عليها أنظمة السحب أو الإيداع في الرصيد البنكي أو أنظمة حجز التذاكر أو شحن بطاقة الهاتف وغيرها .. طبعا في حالة إذا كان برنامجك لا يحتاج إلى وجود الخواص السابقة عندها ينصح باستخدام الأسلوب الغير متزامن Asynchronous حيث تستطيع من خلاله تنفيذ عمليات أخرى في وحدة المعالجة وبدون الحاجة لانتظار إنهاء العملية الجارية إذ يتم إنشاء Separate thread لكل عملية طلب إدخال أو إخراج مما لا يؤثر على أدائية النظام وينصح باستخدامه إذا كانت عملية القراءة أو الكتابة تجرى من خلال أجهزة بطيئة نسبيا ويمكن تميز الميثود المتزامن عن الغير متزامن في الدوت نيت بوجود كلمة Begin أو End في بداية اسم الميثود الغير متزامن وكمثال عليها BeginWrite و BeginRead و ال EndWrite و ال EndRead .. أولا: Stream Classes تدعم الدوت نيت عمليات ال Streams بمجموعة من ال Classes والمندرجة تحت النيم سبيسس System.object و System.IO والتي تستخدم لعمليات نقل البيانات ال Binary Data . تستخدم بعض ال Stream Classes , Backing storage , ومن الأمثلة عليها FileStream و ال BufferedStream وال MemoryStream وكذلك فإن بعضها لا يستخدم أي Back Storage ومن الأمثلة عليها ال NetworkStream والتي تستخدم لنقل ال Stream عبر الشبكة وبدون استخدام Backing Storage , و تقسم ال Stream Classes في الدوت نيت كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34919464574.jpg[/IMG] 1- BufferedStream Class : ويستخدم بشكل أساسي لحجز مقدار معين من الذاكرة بشكل مؤقت لتنفيذ عملية معينة كما تستخدم بعض البرمجيات ال Buffering لتحسين الأدائية حيت تكون كذاكرة وسيطة بين المعالجة و الإرسال أو الاستقبال وكمثال عليها برمجيات الطباعة حيث تستخدم الطابعة ذاكرة وسيطة لتخزين البيانات المراد طباعتها بشكل مؤقت , يكمن الهدف الأساسي من استخدام ال Buffering في العمليات التي يكون فيها المعالج أسرع من عمليات الإدخال و الإخراج حيث يتم معالجة البيانات ووضعها في ال Buffer في انتظار إرسالها وهو ما يساهم في تحسين الأدائية بشكل كبير , ويستخدم ال BufferedStream عادتا في برمجيات الشبكات مع ال NetworkStream لتخزين البيانات المراد إرسالها عبر الشبكة في الذاكرة حيث لا يستخدم هذا الكلاس Backing storage كما ذكرنا سابقا .. بشكل افتراضي يتم حجز 4096 bytes عند استخدام ال BufferedStream ويمكن زيادتها أو تقليلها حسب الحاجة .. ويستخدم ال BufferedStream كما يلي كمثال : [CODE] using System; using System.Text; using System.IO; namespace Network_Buffering { class Program { static void Main(string[] args) { ASCIIEncoding asen = new ASCIIEncoding(); byte[] xx = asen.GetBytes("Hello Buffering"); MemoryStream ms = new MemoryStream(xx); readBufStream(ms); } public static void readBufStream(Stream st) { // Compose BufferedStream BufferedStream bf = new BufferedStream(st); byte[] inData = new Byte[st.Length]; // Read and display buffered data bf.Read(inData, 0, Convert.ToInt32(st.Length)); Console.WriteLine(Encoding.ASCII.GetString(inData)); } } }[/CODE] حيث قمنا بتحويل نص إلى Byte Array باستخدام ال ASCIIEncodingوتحميله في عبر ال MemoryStream ثم ارسلناه إلى الميثود readBufStream والتي انشأناها حيث استقبلنا من خلالها ال Stream وحملناه في ذاكرة مؤقتة بستخدام الكلاس ال BufferedStream ثم قمنا بطباعة محتوياته بعد تحويله إلى نص مرة اخرى بستخدام الEncoding.ASCII وطباعته .. 2- MemoryStream Class : وهو شبيه بعملية ال Buffring السابقة إذ يعتبر كحل جيد لتخزين البيانات بشكل مؤقت في الذاكرة قبل الإرسال أو الأستقبال حيث يغنيك عن تخزينها على شكل ملف مما يسرع العملية بشكل كبير ويستخدم كما يلي كمثال حيث استخدمنها لتخزين صورة في الذاكرة : [CODE] MemoryStream ms = new MemoryStream(); pictureBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] arrImage = ms.GetBuffer(); ms.Close();[/CODE] 3- NetworkStream Class : وكما قمنا باستخدامها سابقا , حيث تقوم بتعامل مع ال Stream لإرساله عبر الشبكة باستخدام ال Socket ويتم استدعائها من النيم سبيسس System.Net.Sockets ويعتبر الكلاسNetworkStream بأنه unbuffered إذ لا يحتوي على Backing Storage ويفضل استخدام ال BufferedStream Classمعه لتحسين الأداء وتستخدم كما يلي كمثال حيث نريد إرسال الصورة التي قمنا بتخزينها في المثال السابق بذاكرة إلى جهاز أخر عبر ال Socket : [CODE] TcpClient myclient = new TcpClient (“localhost”,5020);//Connecting with server NetworkStream myns = myclient.GetStream (); BinaryWriter mysw = new BinaryWriter (myns); mysw.Write(arrImage);//send the stream to above address mysw.Close (); myns.Close (); myclient.Close ();[/CODE] 4- FileStream : يتم استدعائها باستخدام النيم سبيسس System.IO وتستخدم بشكل اساسي في التعامل مع الملفات سواء للكتابة إلى ملف أو القراءة من ملف وتعتبر هذه الكلاس Backing Storage Class حيث تستخدم ذاكرة Buffer لتحزين البيانات بشكل مؤقت في الذاكرة لحين الإنتهاء من عملية الكتابة أو القراءة ومن الأمور الهامة فيها تحديد مسار الملف المراد القراءة منه أو الكتابة عليه وتستخدم كما يلي : [CODE]FileStream FS = new FileStream(@"C:\MyStream.txt", FileMode.CreateNew);// Any Action For Example CreateNew to Create Folder[/CODE] يمكننا استخدام ال Enumeration التالية مع ال FileMode : [IMG]http://x11.putfile.com/12/34919493759.jpg[/IMG] 1- Append لإضافة نص ما إلى الملف الموجود اصلا 2- Create لإنشاء ملف جديد ويقوم بعمل overwriting في حالى إذا كان الملف موجود بشكل مسبق 3- CreateNew وهو كما في ال Create إلا انه يعطي Exception في حالة وجود الملف بشكل مسبق 4- Open لقراءة ملف ما حيث يعطي Excption في حالة عدم وجود الملف المحدد 5- OpenOrCreate في حالة إذا وجد الملف يقوم بقراءته وفي حالة عدم وجوده يقوم بإنشائه. 6- Truncate ويستخدم لحذف محتويات الملف وجعله فارغا ثانيا : Stream Members : هنالك مجموعة من الخواصو و المييثودس التي تشترك بها مكتبات ال Stream وهي كما يلي : [IMG]http://x11.putfile.com/12/34919513071.jpg[/IMG] 1- CanRead و CanWrite وتستخدم لمعرفة إذا كان ال Stream المستخدم يقبل عملية القراءة أو الكتابة أم لا حيث ترجع قيمة True في حالة إذا كان يقبل و False في حالة أنه لا يقبل ويستخدم عادة قبل إجراء عملية القراءة أو الكتابة لفحص مدى الصلاحية قبل المحاولة .. 2- CanSeek حيث يستخدم ال Seeking عادة لتحديد موقع ال Current Stream والعادة تدعم الكلاسات التي تستخدم Backing Storage هذه العملية مثل ال FileStream وعندها ترجع قيمة True وترجع قيمة false في حالة إذا كان ال Stream Class لا يحتوي على Backing Storage . 3- CanTimeout وترجع قيمة True في حالة إذا كان ال stream يحتوي على خاصية ال Timeout والتي تعطي وقت محدد للعملية . 4- Length وتستخدم لمعرفة حجم ال Stream بال Byte ويمكن الاستفادة منها لمعرفة نهاية ال Stream أو لتحديد حجم المصفوفة بناء على حجم ال Stream . 5- Position وتستخدم ال Get و Set لمعرفة أو تحديد الموقع ل Stream وتشترك مكتبات ال Stream بمجموعة من الميثودس وهي كما يلي : 1-الميثودس المتزامنة Synchronous Methods : I. Read و ReadByte وتستخدم لقراءة Stream Data وتخزينه في ال Buffer ويمكن تحديد عدد البايتات التي سيتم قراءتها باستخدام ال ReadByte كما نستطيع من خلالها معرفة نهاية ال Stream حيث ترجع ال Read قيمة 0 وال ReadByte قيمة -1 في حالة انتهاء ال Stream. II. Write وال WriteByte وتستخدم لعملية الإرسال عبر ال Stream ويمكن تحديد عدد البايتات التي سيتم كتابتها في كل مرة باستخدام ال WriteByte. 2-الميثودس غير المتزامنة Asynchronous Methods : I. BeginRead وال BeginWrite وتستخدم لعملية القراءة أو الكتابة باستخدام ال Stream الغير المتزامن وتأخذ خمسة باروميترات كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34919545356.jpg[/IMG] 1- ال Byte Buffer والتي سوف تستخدم لعملية القراءة منه أو الكتابة عليه 2- ال offset والذي سوف يحدد فيه موقع القراءة أو الكتابة 3- ال numByte والذي سوف يتم فيه تحديد الحد الأقصى من البايتات التي سيتم كتابتها أو قراءتها 4- ال AsyncCallback وهو Optional Delegate حيث يتم استدعائه عند الانتهاء من عملية القراءة أو الكتابة 5- ال Stateobject وهي User Provided Object وتستخدم لتميز ال Read & Write Request عن غيره ال Requests . ترجع ال Begin Methods ال IAsyncResult والذي يمثل حالة ال Stream Operation . II. EndRead وال EndWrite وتستخدم في حالة إذا أردنا تنفيذ ال Stream Operation بعد الانتهاء من ال Stream Operation الحالي, حيث يبقى بانتظار انتهاء العملية السابقة ثم ينفذ العملية المطلوبة وهناك بعض الميثود والتي تستخدم لإدارة ال Stream وهي : 1- Flush وتستخدم لتفريغ محتويات ال Buffer بعد إتمام العملية المحددة حيث يتم نقل محتويات ال Buffer إلى ال Destination الذي تم تحديده في Stream Object. 2- Close وتستخدم لإغلاق ال Stream وتحرير ال Resources المحجوزة من قبل ال Stream Object وينصح باستخدامها في الجزء الخاص ب Finally block ولتأكد من أن ال Stream سيتم إغلاقه وتحرير كافة الموارد في حالة حدوث أي Exception إثناء التنفيذ ولضمان عدم بقاء هذه الموارد في الذاكرة بعد إغلاق البرنامج. 3- SetLength وتستخدم لتحديد حجم ال Stream والذي نريد إرساله أو استقباله لاكن في حالة إذا كان ال Stream أقل من المحدد في ال SetLength سوف يؤدي ذالك إلى انقطاع ال Stream وعدم وصوله بشكل سليم , لن تستطيع استخدام هذه الخاصية إلا إذا تأكدت انك تملك الصلاحية لذلك من خلال الخاصية CanWrite و CanSeek لذا ينصح بفحص الصلاحية أولا قبل تحديد حجم ال Stream . ثالثا : Stream Manipulation: يمكن استخدام مكتبات ال Stream لنقل Binary Data أو Text وفي العادة يتم استخدام ال BinaryReader و ال BinaryWriter لتعامل مع ال Binary Data ويتم استخدام ال StreamReader وال StreamWriter لتعامل مع ال Text , ويتم استخدام ال ASCIIEncoding أو UnicodeEncoding لتحويل من Stream إلى Text عند الاستقبال ومن Text إلى Stream عند الإرسال حيث تستخدم مجموعة من الميثودس وهي كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34919570962.jpg[/IMG] 1- GetByteCount وهي Overloaded Method حيث تأخذ Character Array أو String وترجع عدد البايتات التي سوف نحتاجها لنقل نص معين .. 2- GetBytes لتحويل ال String إلى Byte Array حتى نستطيع إرسالها باستخدام ال Stream . 3- GetCharCount حيث تأخذ Byte Array وترجع عدد الأحرف التي سوف تكون في ال String أو في ال Character Array . 4- GetChars وتستخدم لتحويل من Byte Array إلى String وتستخدم عند استقبال البيانات من ال Stream حيث نحولها إلى نص مرة أخرى . ولتعامل مع ال StreamReader و ال StreamWriter لنقل Text يجب أولا استدعائها من ال System.IO نيم سبيسس وتستخدم كما يلي: StreamReader للقراءة من ملف: [CODE]StreamReader str = File.OpenText(openFileDialog1.FileName); textBox1.Text = str.ReadToEnd();[/CODE] StreamWriter للكتابة إلى ملف: [CODE]string fname = saveFileDialog1.FileName; StreamWriter fsave = new StreamWriter(fname); fsave.WriteLine(textBox1.Text);[/CODE] و لتعامل مع ال BinaryReader وال BinaryWriter لنقل Binary Data يتم استدعائها من ال System.IO نيم سبيسس وتستخدم كما يلي: BinaryReader لقراءة Binary Data من ال Stream: [CODE]NetworkStream myns = new NetworkStream(mysocket); BinaryReader br = new BinaryReader(myns);[/CODE] BinaryWriterr لإرسال BinaryData إلى ال Stream عبر ال Socket: [CODE]TcpClient myclient = new TcpClient("localhost", 5020); NetworkStream myns = myclient.GetStream(); BinaryWriter mysw = new BinaryWriter(myns); mysw.Write(arrImage);[/CODE] Remote Control Example باستخدام ال Stream Reader & Writer: مثال تطبيقي بسيط سوف نستخدم فيه برنامج شبيه ب Chatting لاكن سوف نستخدمه لإعطاء أوامر إلى ال Server حيث يفترض إذا قمنا بإرسال كلمة notepad إلى ال server بأن يقوم بفتح ال notepad فيه وإذا قمنا مثلا بكتابة Calc وإرسالها إلى السيرفر سوف يفتح الآلة الحاسبة فيه وهكذا : أولا : إنشاء برنامج الإرسال Client : لا يختلف برنامج الإرسال عن برنامج ال Client Chat الذي قمنا بإنشائه في ال Chapter1 ويستخدم فيه كل من TCP Connection وال NetworkStream و ال StreamWriter لإجراء عملية الإرسال فباستخدام الميثود WriteLine الموجودة ضمن ال StreamWriter Object تتم عملية تحويل النص المكتوب في ال Textbox إلى مجموعة من ال Bytes ليتم إرسالها باستخدام ال NetworkStream عبر ال TCP Socket Connection إلى برنامج السيرفر وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34919593177.jpg[/IMG] ثم قم بإضافة النيم سبيسس التالية : [CODE]using System.Net.Sockets ; using System.IO;[/CODE] في Send Button قم بكتابة الكود التالي: [CODE]try { TcpClient myclient = new TcpClient (txt_host.Text,5020); // تعريف السوكت NetworkStream myns = myclient.GetStream (); // إسناده إلى اللستريم اوبجكت StreamWriter mysw = new StreamWriter (myns); mysw.WriteLine(txt_msg.Text); mysw.Close (); myns.Close (); myclient.Close (); } catch (Exception ex) {MessageBox.Show (ex.Message );} [/CODE] ولإنشاء برنامج ال Server والذي يعمل على استقبال ال Stream وتحويله إلى Text مرة أخرى .. قم بإنشاء مشروع جديد كما في الشكل التالي : [IMG]http://x11.putfile.com/12/34920010757.jpg[/IMG] قم بإضافة النيم سبيسس التالية : [CODE]using System.Net.Sockets ; using System.IO; using System.Threading;[/CODE] ثم إضافة التعاريف التالية : [CODE]TcpListener mytcpl;// Objects Declaration Socket mysocket; NetworkStream myns; StreamReader mysr;[/CODE] ثم نقوم بإنشاء ميثود جديدة كما يلي : [CODE]void our_Server () { mytcpl = new TcpListener (5020);// Open The Port mytcpl.Start ();// Start Listening on That Port mysocket = mytcpl.AcceptSocket ();// Accept Any Request From Client and Start a Session myns = new NetworkStream (mysocket);// Receives The Binary Data From Port mysr = new StreamReader (myns);// Convert Received Data to String string order = mysr.ReadLine(); // you can add any order and Response Here if (order=="notepad") System.Diagnostics.Process.Start("notepad"); else if (order=="calc") System.Diagnostics.Process.Start("calc"); else MessageBox.Show("Sorry Sir Your Request is not in my hand",order); mytcpl.Stop();// Close TCP Session if (mysocket.Connected ==true)// Looping While Connected to Receive Another Message { while (true) { our_Server ();// Back to First Method } } }[/CODE] حيث تقوم هذه الميثود بتصنت على ال Socket في حالة ورود أي Request يقوم بالموافقة عليه وإنشاء Session جديدة معه وفي حالة ورود أي بيانات عبر السوكت يتسلمها باستخدام ال StreamReader ويحولها إلى Text ثم نقوم بفحص الرسالة باستخدام الجمل الشرطية فمثلا إذا كانت الرسالة هي notepad يتم استدعائها باستخدام الميثود Start الموجودة ضمن الكلاس Process والموجودة في النيم سبيسس System.Diagnostics... ولتشغيلها ضمن Thread جديد لابد من وضع تعريف الثريد في حدث بدأ التشغيل للفورم كما يلي : [CODE] private void Form1_Load(object sender, System.EventArgs e) { Thread myth; myth= new Thread (new System.Threading .ThreadStart(our_Server)); myth.Start (); }[/CODE] ثم قم بإضافة التالي في حدث ال Form Closing وذلك لتأكد من إغلاق السوكت وال Stream في البرنامج .. [CODE] private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { try { mytcpl.Stop (); Application.ExitThread (); Application.Exit(); } catch (Exception ex) {MessageBox .Show (ex.Message );}[/CODE] وهنا قد تم الانتهاء من شرح ال Stream وال Stream Class في الدرس القادم سوف نتحدث عن ال Network Layer Programming والتي سوف نتطرق فيها إلى أمور اكثر تقدما في برمجة TCP وال UDP ..  

 اسم العضو:fmo_82  الجمعة,16/ذو القعدة/1426 هـ,11:08 مساءً
امثلة الدرس العاشر ,  

 اسم العضو:students  الأربعاء,21/ذو القعدة/1426 هـ,06:42 صباحاً
مشرفنا الغالي أنا تابعت الدروس مؤخرا ولدي أسئلة ولكن على الدروس الأولى حيث راجعت الـدرس الخاص بالـ pop3 وقمت بتنفيذ الـ code ومشي معي بشكل صحيح. ولكن إذا أردت إنزال جميع الرسائل الخاصة بمستخدم معين المفروض أني سوف أجلب عدد الرسائل أولا بالستخدام الـ STAT command ثم أعمل loop بعدد الرسائل وأستخدم داخل الـ loop الأمر RETR وبهذا أكون أنزلت جميع الرسائل . وبناء على الكلام السابق لدي التساؤلات التالية : أولا : هل الكلام الذي ذكرتة صحيح أم أن هناك طريقة أخرى أجلب بها جميع الرسائل . ثانيا : المتغير المؤقت الذي سوف أحفظ فية جميع الرسائل هل يكون من نوع Arraylist . ثالثا : إذا كان هناك بعض الرسائل تحتوي على مرفق أو أكثر (attachment) هل سوف ينطبق علية الكلام السابق أم أنة سوف يكون هناك استثناءات. أتمنى أن لا أكون قد أطلت وأن تجيبني على جميع التساؤلات. وشكرا  

 اسم العضو:fmo_82  الأربعاء,21/ذو القعدة/1426 هـ,09:23 صباحاً
اشكرك اخي students على ملاحظاتك , في المثال السابق استثنيت جلب جميع الرسائل وكتفيت بجلب الرسالة الأخيرة وحتى لا نعقد الكود بشكل اكبر , الطريقة التي ذكرتها باستخدام امر جلب عدد الرسائل ووضعه في Loop ثم تمريره على RETR هي طريقة جيدة ويمكنك استخدامها بدون اي مشاكل , بنسبة للمتغير الذي سوف يتم حفظ الرسائل به فيمكنك استخدام Array من نوع String وسوف يكون لكل رسالة Index خاص تستطيع استدعائها لاحقا أو يمكنك عمل قاعدة بيانات يتم فيها حفظ الرسائل الواردة من ال POP3 وهو في اعتقادي افضل من استخدام Array String فقط , بنسبة لموضوع المرفقات فيتم معالجته باستخدام ال HTTP Request ارجع إلى درس ال HTTP Programming إذ تكون المرفقات في لعادة من النوع Binary ولإنزالها لابد من معرفة ال Link الخاص بها على ال POP3 Server وباستخدام ال HTTP Request تستطيع تحميلها مع كل رسالة على الجهاز .. وبتوفيق 

 اسم العضو:students  الخميس,22/ذو القعدة/1426 هـ,06:42 صباحاً
السلام عليكم ورحمة الله وبركاته أشكرك أخي فادي على الرد وإن شاء الله سوف أقوم بتجريب ومراجعة ما ذكرتة (و سأزعجك مرة أخرى بالأسئلة )  

 اسم العضو:fmo_82  الخميس,22/ذو القعدة/1426 هـ,09:40 صباحاً
شكرا يا اخي على تفاعلك واهلا وسهلا بك  

 اسم العضو:fmo_82  الخميس,22/ذو القعدة/1426 هـ,11:53 مساءً
بسم الله الرحمن الرحيم الدرس الحادي عشر: Socket & Network Layer Programming : في هذا الجزء سوف نبين بشكل أكثر تفصيلا عن برمجة طبقة ال Network Layer وهي التي يتم التعامل معها لإرسال واستقبال البيانات بعد تحويلها من و إلى Stream عبر الشبكة, قمنا سابقا باستخدام ال TCP و UDP للإرسال وللاستقبال وبينا الفرق بينهما وفي هذا الجزء سوف نتحدث عن ال Socket Programming وال TCP & UDP Classes وفي النهاية سوف نتحدث عن Asynchronous Socket . أولا: Socket Programming من المعروف أن السوكت هي الأداة التي يتم نقل البيانات من خلالها من جهاز إلى أخر ولاستخدامها يلزم في البداية تعريف النيم سبيس System.Net.Sockets حيث يحتوي هذا النيم سبيس على عدد ضخم من ال Classes والتي يتم استخدامها في برمجيات الشبكة وسوف نتحدث عن أهما وهو Socket Class إذ يمكننا بمن التعامل مع ال TCP أو ال UDP أو مع أي نوع أخر من البرتوكولات بشكل مباشر ويتكون ال Socket Object Method من ثلاثة باروميترات كما يلي: [CODE]Socket MySocket = new Socket(AddressFamily. , SocketType., ProtocolType.);[/CODE] حيث يتم في الباروميتر الأول تحديد نوعية ال IP Address والذي سوف تتعامل معه ويعطيك عدد كبير من الخيارات ومنها IPX والمستخدم في شبكات ال Novel أو ATM والمستخدم في شبكات ال ATM Networks أو NetBIOS Address وغيرها ... ومن أهم هذه الخيارات الInterNetwork وهو ما نستخدمه بشكل دائم مع البرمجيات الخاصة بالشبكات ويعرف على أن نوع IP هو من النوع IPv4 وهو المعتاد مع نظام مايكروسوفت وأغلب أنظمة التشغيل المعروفة حاليا وفي المستقبل القريب جدا سيتم الإستغناء عنه وليحل محله ال IPv6, في الباروميتر الثاني يتم تحديد نوع ال Socket أي هل سوف نستخدم Stream لإرسال البيانات أو شيء اخر وعادة ما يتم استخدام ال Stream لهذه المهمة حيث اننا سنعتمد نمطية التراسل من النوع Stream , وأخيرا نحدد نوع البروتوكول المستخدم للإتصال فهل هو من النوع UDP أو TCP أو بروتوكولات أخرى مثل ICMP Internet Control Message Protocol أو IGMP Internet Group Management Protocol أو اننا نريد مثلا إنشاء ال Socket لتعريف IP Security Header بإختيار IPSecAuthenticationHeader وغيرها وسوف نأتي على شرح مثل هذه الأمور لاحقا إنشاء الله, وهنا سوف نختار ال TCP أو UDP ومن المعروف أن برتوكول ال TCP هو برتوكول موجه وهذا يعني إجراء عملية التحقق من الوصول والتوصيل إلى شخص ما محدد أما برتوكول ال UDP فهو برتوكول سريع نسبيا و لاكنه لا يدعم عملية التحقق من الوصول السليم للبيانات المرسلة وهو مفيد جدا لإجراء عملية البث الإذاعي Broadcast وإنشاء مجموعات البث Multicast Group وهو ما شرحناه في الدرس الأول والثاني أنظر إلى الشكل التالي ويبين فيه ال Header الخاص بال TCP وال Header الخاص بال UDP ولاحظ الفرق بينهما: أولا ال TCP Header ويتكون من 32 Bits للبكت الواحد حيث يتم فيه تخزين عنوان المرسل في 16 Bits والمستقبل في 16 Bits والرقم التسلسلي للبكت في 32 Bits ورقم التحقق بالإضافة إلى ال Checksum وفي النهاية يتم وضع الجزء الخاص بالبيانات : [IMG]http://x12.putfile.com/12/35520034230.gif[/IMG] [CODE]Data Offset: 4 bits the number of 32 bit words in the TCP Header. This indicates where the data begins. The TCP header (even one including options) is an integral number of 32 bits long. Window: The number of data octets beginning with the one indicated in the acknowledgment field which the sender of this segment is willing to accept. …[/CODE] ثانيا ال UDP Header ويتكون من 32 Bits من البيانات للبكت الواحد ويحتوي على عنوان المرسل 16 Bits أما المستلم و ال Checksum فهما اختياريان وبشكل افتراضي لا يتم استخدامهم في عملية الإرسال: [IMG]http://x12.putfile.com/12/35520075494.jpg[/IMG] [CODE]The Checksum in UDP Header. 16 bits. Computed as the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header, the UDP header, and the data, padded as needed with zero bytes at the end to make a multiple of two bytes. If the checksum is cleared to zero, then checksuming is disabled. If the computed checksum is zero, then this field must be set to 0xFFFF. …[/CODE] استخدام ال Socket Programming لإنشاء TCP Connection : تمر عملية الاتصال باستخدام ال TCP Socket Connection بمجموعة من المراحل وهي كما في الشكل التالي : [IMG]http://x12.putfile.com/12/35520102832.jpg[/IMG] إذ تبدأ العملية في ال Client و ال server بإنشاء ال Socket كما يلي : [CODE]Socket MySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);[/CODE] ثم ربط ال Socket مع الكمبيوتر الحالي باستخدام الميثود Bind وتستخدم فقط عند الاستقبال وكما يلي : [CODE]IPEndPoint ip = new IPEndPoint(IPAddress.Any, 5020); MySocket.Bind(ip);[/CODE] ثم القيام بعملية التصنت على البورت المحدد باستخدام الميثود listen ويمكنك تحدد عدد الأجهزة التي سيتم قبولها ولوضع عدد غير محدد نمرر له الرقم -1 ثم نقوم بالموافقة على الاتصال باستخدام الميثود accept وكما يلي : [CODE]MySocket.Listen(-1); MySocket.Accept();[/CODE] ويتم استقبال البيانات من خلال الميثود Receive حيث تعبئ البيانات في مصفوفة من النوع Byte وكما يلي : [CODE]byte[]Received=new byte[1024]; MySocket.Receive(Received);[/CODE] وهنا قمنا بإنشاء Connection من النوع TCP وبتعريفها على البورت(5020 كمثال) حيث يتم ربطها بال Socket باستخدام الميثود Bind وقمنا بتعريف Listen لا نهائي العدد -1 .. ولتعريف برنامج الإرسال TCP Client باستخدام ال Socket لابد من تعريف السوكت مرة أخرى وإسناد عنوان السيرفر ورقم البورت بنقطة الهدف IPEndPoint ثم إرسال البيانات باستخدام الميثود Send وتتم عملية الإرسال بما تم تعريفه في ال socket حيث سنستخدم Stream Socket وكما يلي : [CODE]String str = Console.ReadLine(); ASCIIEncoding asen = new ASCIIEncoding(); byte[] msg = asen.GetBytes(str); Socket MySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint remote = new IPEndPoint(IPAddress.Parse("192.168.1.101"), 5020); MySocket.Connect(remote); MySocket.Send(msg); MySocket.Close();[/CODE] استخدام ال Socket Programming لإنشاء UDP Connectionless : تمر عملية الاتصال باستخدام ال UDP Socket Connection بمجموعة من المراحل وهي كما في الشكل التالي : [IMG]http://x12.putfile.com/12/35520152384.jpg[/IMG] وتتشابه عملية الاتصال كما في ال TCP إذ تبدأ العملية في ال Client و ال server بإنشاء ال Socket كما يلي : [CODE] Socket MySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Udp);[/CODE] ثم ربط ال Socket مع الكمبيوتر الحالي باستخدام الميثود Bind وتستخدم فقط عند الاستقبال وكما يلي : [CODE]IPEndPoint sender = new IPEndPoint(IPAddress.Any, 5020); MySocket.Bind(sender);[/CODE] ولاستقبال البيانات نستخدم الميثود ReceiveFrom حيث نعرف في البداية End Point Reference بناء على ما تم تعريفه في السابقة ونمرره ك reference مع مصفوفة ال Byte إلى الميثود ReceiveFrom ومن ثم نستطيع تحويل المصفوفة إلى String من خلال الميثود GetString الموجودة ضمن الكلاس ASCII وكما يلي : [CODE]int recv; byte[] data = new byte[1024]; EndPoint Remote = (EndPoint) (sender); recv = newsock.ReceiveFrom(data, ref Remote); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));[/CODE] ويتم في الإرسال استخدام الميثود SendTo حيث نمرر لها البيانات بعد تحويلها من String إلى Byte Array وحجم البيانات المرسلة إذ يمكننا معرفته من خلال الميثود Length ونوع ال Flags حيث نريد عمل Broadcast لرسالة المرسلة واخيرا نمرر له ال EndPoint Object وكما يلي: [CODE]string welcome = "Hello All"; data = Encoding.ASCII.GetBytes(welcome); newsock.SendTo(data, data.Length, SocketFlags.Broadcast, Remote);[/CODE] يمكن وضع هذا الأكواد في Infinity While Loop بحيث لا تنتهي أو يمكن تحديدها بعدد معين من عمليات الإرسال والاستقبال .. ثانيا: Socket Classes Members : 1- IPAddress Class : ويستخدم لتعريف IP Address حيث يمكن إسناده إلى ال IPEndPoint كمثال والصيغة العامة له كما يلي: [CODE]IPAddress newaddress = IPAddress.Parse("192.168.1.1");[/CODE] ويمكن الإختيار بين اربعة خيارات في تحديد العنوان وهي كما يلي : Any ويستخدم لتمثيل أي عنوان متاح على الشبكة Broadcast ويستخدم لتمثيل البث الإذاعي لجميع الأجهزة على الشبكة Loopback ويستخدم لتمثيل العنوان المعروف لل loopback وهو 127.0.0.1 None ويستخدم في حالة عدم وجود Network Interfase في النظام كما يدعم مجموعة من الميثود وأهمها : Equals يستخدم هذا الميثود بشكل عام للمقارنة بين tow Objects وهنا سيستخدم للمقارنة بين عنوانين ويرجع True إذا كانا متشابهين و False إذا كانا مختلفين. GetHashCode وتستخدم لإرجاع العنوان إلى صيغة Hash Code HostToNetworkOrder ويرجع الجزء الخاص بال Network من العنوان NetworkToHostOrder ويرجع الجزء الخاص بال Host من العنوان 2- IPEndPoint Class : حيث استخدمناه لتحديد العنوان وال Port لل Host والذي نريد الاتصال به والصيغة العامة له كما يلي : IPEndPoint end = new IPEndPoint(IPAddress.Parse("192.168.1.1"), 5020); مجموعة الخواص التي تدعم في ال Socket Class وهي كما يلي: AddressFamily ويرجع مجموعة العناوين المعرفة على ال Socket Available ويرجع حجم البيانات الجاهزة للقراءة من ال Socket Blocking ويعطي Get أو Set لمعرفة إذا كان ال socket يستخدم ال Blocking Mode أم لا Connected وتستخدم هذه الخاصية بكثرة لمعرفة إذا كان ال Socket متصل مع ال Remote Host أم لا Handle ويستخدم لمعرفة نظام التشغيل الذي يتعامل مع ال Socket ProtocolType ويستخدم لمعرفة البروتوكول الذي يستخدم في ال Socket RemoteEndPoint ويرجع معلومات عن ال Socket الذي يستخدم مع ال Remote Host وكمثال لاستخداماتها: [CODE]using System; using System.Net; using System.Net.Sockets; class Socket_ Properties { public static void Main() { IPAddress ia = IPAddress.Parse("127.0.0.1"); IPEndPoint ie = new IPEndPoint(ia, 8000); Socket fmo = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Console.WriteLine("AddressFamily: {0}", fmo.AddressFamily); Console.WriteLine("SocketType: {0}", fmo.SocketType); Console.WriteLine("ProtocolType: {0}", fmo.ProtocolType); Console.WriteLine("Blocking: {0}", fmo.Blocking); fmo.Blocking = false; Console.WriteLine("new Blocking: {0}", fmo.Blocking); Console.WriteLine("Connected: {0}", fmo.Connected); fmo.Bind(ie); IPEndPoint iep = (IPEndPoint)fmo.LocalEndPoint; Console.WriteLine("Local EndPoint: {0}", iep.ToString()); fmo.Close(); } }[/CODE] حيث سترجع المعلومات التالية: [CODE]AddressFamily: InterNetwork SocketType: Stream ProtocolType: Tcp Blocking: True new Blocking: False Connected: False Local EndPoint: 127.0.0.1:8000 Press any key to continue . . .[/CODE] ثالثا: TCP & UDP Classes Members : أولا ال Classes الخاصة بالOriented Protocol TCP Connection : [IMG]http://x12.putfile.com/12/35520181216.jpg[/IMG] 1-Class TcpClient: حيث تحتوي على مجموعة من ال Methods وال Properties وهي كما يلي: أولا: أهم الميثود الخاصة بها TCPClient Methods : Connect: وتستخدم لأجراء عملية الاتصال مع ال server حيث نمرر فيها عنوان ال IP الخاص بال Server و رقم البورت وكما يلي: [CODE]TcpClient tcp = new TcpClient(); tcp.Connect(IPAddress.Parse("192.168.1.1"),5020);[/CODE] Close: لإنهاء الاتصال مع ال TCP Socket. EndConnect: لإنهاء Asynchronies Connection حيث ترجع Asynchronies Result. GetStream: ويستخدم لقراءة ال Stream من ال Socket في عملية الإرسال و الاستقبال. ثانيا: أهم الخصائص TCPClient Properties : LingerState : وتأخذ get أو Set لتحديد أو معرفة ال Linger Time NoDelay: وتأخذ get أو Set لتحديد أو معرفة إذا كان هناك وقت معين لتأخير أم لا ExclusiveAddressUse: وتأخذ get أو Set لتحديد أو معرفة السوكت يسمح باستخدام ال Client Port أم لا. SendBufferSize و ReceiveBufferSize: وتأخذ get أو Set لتحديد أو معرفة حجم ال Buffer المستخدم في ال stream والمعرف في TCP Client Object. SendTimeout و ReceiveTimeout: وتأخذ get أو Set لتحديد أو معرفة الوقت المتاح لعملية الإرسال أو الإستقبال حيث يعطي Time Out في حالة أنه لم يجد الطرف الأخر خلال فترة زمنية معينة. 2-Class TcpListener: حيث تحتوي على مجموعة من ال Methods وال Properties وهي كما يلي: [IMG]http://x12.putfile.com/12/35520202076.jpg[/IMG] أولا: أهم الميثود الخاصة بها TcpListener Methods : AcceptSocket: وتستخدم لقبول عملية الاتصال مع ال Client. Start : وهي Overloaded Method حيث انه في حالة تمرير رقم إليها يتم تحديد عدد الأجهزة التي تسمح بوجودها في الطابور أو ال Qouee وبدون تحديد رقم معين يصيح ال Qouee غير محدد. Stop : وتستخدم لإخلاق عملية التصنت ويفضل وضعها في ال Finnaly عند استخدام ال Try و ال Catch حتى يتم إخلاق التصنت في حالة حدوث أي Exception. ثانيا: أهم الخصائص في TcpListener: LocalEndpoint : حيث يرجع ال IP ورقم البورت المستخدم في ال LocalEndpoint المحدد. Server: ومن خلالها نستطيع الوصول إلى كل الخصائص و الميثود في ال TCP Server والتي شرحناها سابقا مثل ال Accept وال Sendto وال Receive و Listen وغيرها ثانيا ال Classes الخاصة بال Protocol UDP Connectionless : 1-Class UdpClient: وتستخدم لتعريف UDP Datagram Protocol Connection قمنا سابقا بتعريفها والتعامل معها وفي هذا الدرس سنبين أهم محتوياتها وهي كما يلي : [IMG]http://x12.putfile.com/12/35520230191.jpg[/IMG] ومن أهم الميثود والخصائص الخاصة بها : JoinMulticastGroup و DropMulticastGroup: لضم أو إلغاء عنوان أو مجموعة من العناوين من ال Multicast Group. EnableBroadcast: وتأخذ Get أو Set لتفعيل ال Broadcasting في ال socket. MulticastLoopback: وتأخذ Get أو Set لمعرفة أو تحديد ال Mlticast Loopback. 2-Class MulticastOption: ويستخدم في ال Multicasting حيث يتم تخزين IP Address List لتعامل معها في Multicast Group لعمل Join و Drop لأي Multicast Group وتستخدم كما يلي كمثال لإضافة عضوية لاستقبال رسائل Multicast : أولا نعرف ال UDP Socket وكما يلي : [CODE]mcastSocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp);[/CODE] ثانيا نقوم بتعريف Address List ثم نسند إليها ال IP الذي نريد إدخاله في ال Group أو نجعل ال User يدخل العنوان بنفسه نربطها بالسكوت باستخدام الميثود Bind وكما يلي : [CODE]IPAddress localIPAddr = IPAddress.Parse(Console.ReadLine()); mcastSocket.Bind(IPlocal);[/CODE] ثالثا نقوم بتعريف ال Multicast Option ونسند لها العنوان المحدد كما يلي: [CODE]MulticastOption mcastOption; mcastOption = new MulticastOption(localIPAddr);[/CODE] ومن ثم نضيف التغير على ال حيث تأخذ هذه الميثود ثلاثة باروميترات الأول لتحديد مستوى التغيير على IP أو على IPv6 أو على Socket أو TCP أو UDP وفي حالتنا هذه سوف نستخدم التغير على IP إذ ما نريده هو ضم IP إلى Multicast Group وفي الباروميتر الثاني نحدد نوع التغيير حيث نريد إضافة عضوية ويمكن الاختيار بين إضافة عضويه AddMembership أو إلغاء عضوية DropMembership وأخيرا نسند إليه ال MulticastOption Object والذي قمنا بإنشائه و كما يلي: [CODE]mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,mcastOption);[/CODE] في الدرس القادم سوف نتحدث عن ال Asynchronous Sockets ونطبق مجموعة من الأمثلة العملية عليها إنشاء الله.  

 اسم العضو:students  السبت,01/ذو الحجة/1426 هـ,06:19 صباحاً
السلام عليكم ورحمة الله وبركاته أولا تسلم على هذة الدروس الي زي العسل مع أني مقصر جدا في التطبيق وما زلت في البداية جدا الله يعينني ويعينك علي لقد قرأت الدرس الخاص بالـ HTTP وأريد تطبيق المفاهيم التي وردت فية على هيئة مثال حتى تتوضح لي المفاهيم ولغيري : المثال هو: لنفرض أنة لدينا صفحة إنترنت تتعامل مع قاعدة بيانات(access ) . هذة الصفحة تعمل كالإميل أي أن هناك عدة مشتركين يدخلون إلى هذة الصفحة ويتصفحون البريد الخاص بهم وأيضا يقومون بإرسال أي رسالة يريدونها ، أي مثل صفحات الـ YAHOO , HOTMAIL . وبالإعتماد على هذا المثال لدي الملاحضات التالية : أولا: عملية إنزال الرسائل الخاصة بكل مستخدم من الـ POP3 سوف تتم بالطريقة التي ذكرناها في المشاركة السابقةوكما تفضلت فإن إنزال الرسائل سوف تتم إلى قاعدة بيانات. ولكن أنا قلت أنة إذا كان مع الرسالة مرفق بالطبع سوف يكون هناك معلومات في الرسالة عن إسم المرفق وليكن pic.rar (مع أنة كان هناك رموز ومعلومات غريبة لم أفهم إلى ماذا تشير بالضبط) وبالإشارة إلى الرد الذي قلتة مسبقا (إذ تكون المرفقات في ا لعادة من النوع Binary ولإنزالها لابد من معرفة ال Link الخاص بها على ال POP3 Server ) لدي التساؤلات التالية : ـ كيف أعرف الـ link الخاص بالمرفق هل سوف يكون موجود ضمن الرسالة التي سوف أنزلها ، وبصراحة أكثر أنا أنزلت رسالة تحتوي على مرفق الشيء الوحيد الذي أستطعت أن أستخلصة من الرسالة والذي يشير إلى المرفق هو أسم المرفق. ـ بفر ض أننا عرفنا الـ link وليكن مثلا [URL=http://somthing/pic.rar]http://somthing/pic.rar[/URL] أنا أتصور أن المرفق الذي سوف أنزلة سيكون ملف ولذلك سوف أستخدم طريقة الـ DownloadFile الذي شرحتة في الـ Downloading From Web Server لإنزالة أم لان البيانات من نوع binary لا تنفع هذة الطريقة وما هي الطريقة التي يجب أن أستخدمها؟؟؟؟؟؟؟؟؟؟؟؟؟. - لأني سوف أقوم بتخزين الرسائل في قاعدة بيانات فأنا أريد تخزينها بشكل مفصل (date ,from ,subject,messeage) وأقوم بإلغاء الأشياء الزائدة , أستطعت أن أخرج التفاصيل السابقة بإستثناء الرسالة نفسها(message) كيف أصل إلى الرسالة بالضبط ، مثلا إذا أردت أخذ الجزء الخاص بـ from سوف إبحث داخل الرسالة عن :from وأقوم بأخذ الـ string التي تليها ، وهكذا مع البقية بإستثناء الـ messeage نفسها كيف أصل إليها. وشكرا  

 اسم العضو:fmo_82  السبت,01/ذو الحجة/1426 هـ,08:29 صباحاً
اهلا وسهلا بك اخي students , [QUOTE]عملية إنزال الرسائل الخاصة بكل مستخدم من الـ POP3 سوف تتم بالطريقة التي ذكرناها في المشاركة السابقةوكما تفضلت فإن إنزال الرسائل سوف تتم إلى قاعدة بيانات.[/QUOTE] انصحك بلإطلاع على الموضوع التالي: [URL=http://www.codeproject.com/csharp/despop3client.asp]http://www.codeproject.com/csharp/despop3client.asp[/URL] إذ انه في ال Yahoo و ال Hotmail وجميع البريد الإلكتروني المعتمد على ال HTTP يتم ارسال المرفق بشكل Binary Data مدمجة مع الرسالة حيث يقوم البريد الإلكتروني بفصل الملحق عن نص الرسالة الأصلية وهو ما سوف تجد طريقته في الرابط السابق .. في حالة كنت تعمل على إنشاء Email Server بنفسك فيفضل أن ترسل ال Link الخاص بالملف المرفق مع الرسالة بدلا من ارسال الملف مع نص الرسالة كما تعمل جميع ال HTTP Email Server وفي هذه الطريقة سوف تستخدم ال DownloadFile بحيث سيتم تخزين الملف على نفس الجهاز وليس على قاعدة البيانات , أو أن تقوم بإرساله بشكل منفصل عن نص الرسالة بحيث تستخدم ال Stream Reader&Writer لنص الرسالة وال Binary Reader&Writer للملحقات ثم عند الإستقبال تقوم بتخزين ال Stream في قاعدة بيانات المستخدم , بحيث تكون من النوع Image للمرفقات (SQL Server) أو memo في حالة (MS Access) .. انظر إلى البرنامج الموجود في المرفقات  

 اسم العضو:students  الأحد,02/ذو الحجة/1426 هـ,05:05 صباحاً
السلام عليكم ورحمة الله وبركاته أشكرك أخي فادي على هذا التجواب , إن شاء الله سوف أقرأ الموضوع وأطلع على البرنامج.  

 اسم العضو:students  الأحد,02/ذو الحجة/1426 هـ,02:50 مساءً
أخي فادي العفو منك ولكني أنزلت البرنامج الذي أعطيتة لي كمرفق وقمت بتنفيذة أكثر من مرة وفي أوقات متفرقة( وذلك بعد ما غيرت الـ usetname والـ password وكذلك اسم الـسيرفر بالطبع) وعند الضغط على recive لم أرى أي شيء أي كأني لم أعمل شيء وعندما أضغط على cancel تظهر الرسالة التالية RecieveCallback errorSystem.Net.Sockets.SocketException: The I/O operation has been aborted because of either a thread exit or an application request at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) at PramodSingh.LibPOP3.POP3.ReceiveCallback(IAsyncResult ar) 

 اسم العضو:fmo_82  الثلاثاء,04/ذو الحجة/1426 هـ,08:24 صباحاً
بسم الله الرحمن الرحيم, الدرس الثاني عشر: Asynchronous Sockets Programming : سوف نتحدث في هذا الدرس عن استخدام ال Asynchronous Socket بشكل أكثر تفصيلا عما تحدثنا به سابقا وسوف نطبق مجموعة من الأمثلة العملية على استخدام الاتصال الغير متزامن في برمجيات الشبكات ... من المعروف أن الاتصال المتزامن مهم جدا في البرمجيات التي تحتاج إلى العمل في الزمن الحقيقي حيث لا يسمح باستخدام الاتصال لأمر آخر إلى بعد انتهاء العملية الجارية واستخدامه مهم جدا في العمليات التي تتطلب مثل هذه الأمور لا كن لا ينصح أبدا استخدامه في حالة إذا كانت الجهة المستقبلة للبيانات تستخدم Slow Connection كاعتماد الشبكة على ال Dialup لربط الجهازين المرسل مع المستقبل أو في حالة إذا كان هنالك مجموعة كبيرة من المستخدمين تستخدم السيرفر حيث يمنع الأسلوب المتزامن بقية المستخدمين على الشبكة من إجراء عملية الإرسال في حالة كون ال Server يستقبل بيانات من جهاز آخر , وفي هذه الحالة ينصح باستخدام الاتصال الغير المتزامن إذ يعتبر مهم جدا في حالة إذا أردنا من البرنامج القيام بعدة مهام وعلى نفس ال Thread وباستخدام نفس ال Connection , أو كما ذكرنا سابقا في حالة إذا كان الاتصال بطيء نسبيا أو انه يوجد عدد مستخدمين يستخدمون نفس ال Server .. أولا Asynchronous Socket Class and its members : تدعم الدوت نيت الاتصال غير المتزامن بمجموعة من ال methods الموجودة ضمن ال Socket Class والتي يتم استدعائها من ال System.Net.Socket Namespaces وقد ميزت الدوت نيت هذه الميثودس بوجود ال Begin في بداية أسم الميثود, ولكل Begin Method يوجد Method End مقابلة لها والتي تستخدم لإرجاع callback result عند انتهاء ال Begin Method من التنفيذ وهي كما يلي: [IMG]http://x11.putfile.com/1/205005746.jpg[/IMG] 1- BeginAccept و تستخدم لقبول ال Client Request وإسناده إلى الObject AsyncCallback وباستخدام هذه الطريقة سوف يتمكن ال Server من استقبال عدد من ال Clients Requests في نفس الوقت وبدون الحاجة لانتظار الانتهاء من العملية الجارية حيث يتم في كل مرة استدعاء الميثود باستخدام ال AsyncCallback Delegate وتستخدم كما يلي كما يلي: [CODE]m_mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp); IPEndPoint ipLocal = new IPEndPoint (IPAddress.Any, 5020); m_mainSocket.Bind (ipLocal); m_mainSocket.Listen (10); m_mainSocket.BeginAccept (new AsyncCallback (Client_request_method), null);[/CODE] حيث سيتم إضافة ال Client Request فيReference Callback منفصل عن السابق وهنا لابد من إنشاء method لاستقبال ال Client Request وإنهاء ال Client Accepted Object باستخدام الميثود EndAccept : [CODE]public void Client_request_method(IAsyncResult ar) { Socket listener = (Socket)ar.AsyncState; Myclient = listener.EndAccept(ar); Myclient.Send(/* data to be send*/ ); listener.BeginAccept(new AsyncCallback(Client_request_method), listener); Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString()); }[/CODE] في Dot Net 2005 أصبحت ال BeginAccept Method تأخذ عدة أشكال كما يلي: الشكل الأول في الدوت نيت 2003 و 2005 وتأخذ AsyncCallBack Delegate و State Object لإرجاع معلومات عن حالة ال Request في ال Socket وكما يلي: MySocket.BeginAccept(AsyncCallback , object state) الشكل الثاني في الدوت نيت 2005 حيث يمكنك فيه تحديد حجم البيانات المستلمة [CODE]MySocket.BeginAccept(int Data_ Receive_Size , AsyncCallback , object state) [/CODE] الشكل الثالث في الدوت نيت 2005 حيث بمكن فيه تحديد ال Accepted Socket [CODE]MySocket.BeginAccept(Socket accept_Socket ,int Data_ Receive_Size , AsyncCallback , object state)[/CODE] 2- BeginConnect وتستخدم لبدأ Asynchronous Connection على ال Socket ورقم البورت المحدد حيث يسند لها ال IPEndPoint وال Asynchronous Callback وال State Object وكما يلي: [CODE]MySocket.BeginConnect(EndPoint IP,Syncallback Result,object state)[/CODE] وتستخدم كما يلي كمثال: [CODE]Socket MySocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipend = new IPEndPoint(IPAddress.Parse("192.168.1.101"), 5020); MySocket.BeginConnect(ipend, new AsyncCallback(Connected), MySocket);[/CODE] في ال Connected Method يتم تحديد ال CallBack Socket كما يلي: [CODE] public static void Connected(IAsyncResult iar) { Socket sock = (Socket)iar.AsyncState; try { sock.EndConnect(iar); } catch (SocketException) { Console.WriteLine("Unable to connect to host"); }}[/CODE] 3- BeginReceive وتستخدم لإستقبال بيانات من ال Client وتخزينها في Byte Array والصيغة العامة لها كما يلي: [CODE]MySocket.BeginReceive(Byte[] buffer,int offset, SocketFlags,AsyncCallback, object sate)[/CODE] ويستخدم كما يلي كمثال: [CODE]byte[] data = new byte[1024]; MySocket.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceivedData), MySocket); void ReceivedData(IAsyncResult iar) { Socket remote = (Socket)iar.AsyncState; int recv = remote.EndReceive(iar); string receivedData = Encoding.ASCII.GetString(data, 0, recv); Console.WriteLine(receivedData); }[/CODE] كما تستخدم الميثود BeginReceiveFrom لإستقبال البيانات من موقع محدد باستخدام ال UDP حيث يضاف إلى التركيب السابق IPEndPoint Refrance Object . 4- BeginSend وتستخدم لإرسال بيانات إلى الطرف المستقبل عبر ال Asynchronous Socket والصيغة العامة لها كما يلي: [CODE]MySocket.BeginSend (Byte[] buffer,int offset, SocketFlags,AsyncCallback, object sate)[/CODE] وتستخدم كما يلي كمثال: [CODE]private static void SendData(IAsyncResult iar) { Socket server = (Socket)iar.AsyncState; int sent = server.EndSend(iar); } byte[] data = Encoding.ASCII.GetBytes("Hello Word"); MySocket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendData), MySocket);[/CODE] كما تستخدم الميثود BeginSendto لإرسال البيانات إلى Remote Host محدد باستخدام ال UDP حيث يضاف إلى التركيب السابق IPEndPoint Refrance Object . 5- كما تم إضافة مجموعة من الميثود الجديدة في الدوت نيت 2005 وهي: BegonDiconnect لإنهاء الاتصال و BeginSendFile لإرسال ملف و ال BeginReceiveMessageFrom والتي تستخدم لإستقبال عدد محدد من البيانات وتخزينها في مكان محدد في ال Bufer .. التركيب التالي:BeginSendFile تأخذ ال [CODE]MySocket.BeginSendFile(string filename,AsyncCallback Asyn,object state)[/CODE] وال BeginReceiveMessageFrom التركيب التالي: [CODE]MySocket.BeginReceiveMessageFrom(byte Buffer ,int offset,int size,SocketFlags sf,ref EndPoint,AsyncCallback ascb,object state)[/CODE] وال BegonDiconnect التركيب التالي: [CODE]MySocket.BeginDisconnect(bool reuseSocket,AsyncCallback ascb,object state)[/CODE] ثانيا: تطبيقات ال Asynchronous Socket في الدوت نيت : تمر عملية الاتصال الغير متزامن بمجموعة من المراحل تبدأ بإنشاء الObject Socket في ال Server Side بعد ذلك يتم تعريف ال BeginConnect لبدأ Asynchronous Connection على ال Socket حيث يتم إسناد Object IPEndPoint والMethod Asynchronous Callback وال State Object لها وتبدأ في هذه الحالة عملية الاتصال بال Socket , وبعد ذلك تمرر إلى ال BeginAccept لقبول ال Client Request حيث يتم قبول الطلب ويرسل Acknowledgement إلى ال Client ليعلمه فيها بقبول الجلسة وإمكانية البدء للإرسال و يستطيع ال Client بعد الموافقة على الجلسة البدء بالإرسال باستخدام الميثود BeginSend ويستقبل ال Server الرسالة من ال Client باستخدام الميثود BeginReceive وكما ذكرنا سابقا فإن لكل عملية Begin تقابلها الميثود End للاستعداد لإجراء عملية أخرى على نفس ال Thread في البرنامج وهو ما ميز الاتصال الغير متزامن عن الاتصال المتزامن. [IMG]http://x11.putfile.com/1/205002690.jpg[/IMG] وبناء على المفاهيم السابقة سوف نقوم الآن بإنشاء برنامج Client/Server Chatting يعتمد على ال Asynchronous Socket لإرسال واستقبال البيانات . وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي: [IMG]http://x11.putfile.com/1/205052218.jpg[/IMG] سوف نستخدم ال Namespaces التالية: [CODE]using System.Net; using System.Net.Sockets; using System.Text; [/CODE] في ال Global Declaration (أي بعد تعريف ال Main Class)قم بإضافة التعاريف التالية: [CODE]public class Form1 : System.Windows.Forms.Form { Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 5020); private byte[] data = new byte[1024]; private int size = 1024;[/CODE] في ال Form Load قم بإضافة الكود التالي حيث سنعرف Connection يعتمد على ال TCP ويعمل على البورت 5020 ثم تعريف عملية قبول الاتصال باستخدام ال BeginAccept : [CODE]private void Form1_Load(object sender, System.EventArgs e) { server = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 5020); server.Bind(iep); server.Listen(5); server.BeginAccept(new AsyncCallback(AcceptConn), server); }[/CODE] ثم إنشاء Accept Callback Method والذي سيتم فيه إنهاء ال Accepted Request باستخدام ال EndAccept Method وبعد ذلك إرسال Acknowledgement إلى ال Client تخبره فيها بقبول الطلب وترسل باستخدام ال BeginSend Method كما يلي: [CODE]void AcceptConn(IAsyncResult iar) { Socket oldserver = (Socket)iar.AsyncState; Socket client = oldserver.EndAccept(iar); conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString(); string stringData = "Welcome to my server"; byte[] message1 = Encoding.ASCII.GetBytes(stringData); client.BeginSend(message1, 0, message1.Length, SocketFlags.None,new AsyncCallback(SendData), client); }[/CODE] ثم إنشاء Send Callback method لإنهاء ال BeginSend وكما يلي: [CODE]void SendData(IAsyncResult iar) { Socket client = (Socket)iar.AsyncState; int sent = client.EndSend(iar); client.BeginReceive(data, 0, size, SocketFlags.None,new AsyncCallback(ReceiveData), client); }[/CODE] ثم إنشاء Receive Callback method لإنهاء ال BeginReceive وكما يلي: [CODE]void ReceiveData(IAsyncResult iar) { Socket client = (Socket)iar.AsyncState; int recv = client.EndReceive(iar); if (recv == 0) { client.Close(); conStatus.Text = "Waiting for client..."; server.BeginAccept(new AsyncCallback(AcceptConn), server); return; } string receivedData = Encoding.ASCII.GetString(data, 0, recv); results.Items.Add(receivedData); byte[] message2 = Encoding.ASCII.GetBytes(receivedData); client.BeginSend(message2, 0, message2.Length, SocketFlags.None,new AsyncCallback(SendData), client); }[/CODE] وهنا قد تم الانتهاء من برنامج ال Server والآن سوف نقوم بإنشاء برنامج ال Client وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي: [IMG]http://x11.putfile.com/1/205063440.jpg[/IMG] سوف نستخدم ال Namespaces التالية: [CODE]using System.Net; using System.Net.Sockets; using System.Text;[/CODE] في ال Global Declaration (أي بعد تعريف ال Main Class)قم بإضافة التعاريف التالية: [CODE]public class Form1 : System.Windows.Forms.Form { private Socket client; private byte[] data = new byte[1024]; private int size = 1024; [/CODE] في ال Connect Button قم بكتابة الكود التالي: [CODE]conStatus.Text = "Connecting..."; Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(textBox1.Text), 5020); newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);[/CODE] ثم قم بإنشاء Callback Connect method كما يلي: [CODE]void Connected(IAsyncResult iar) { client = (Socket)iar.AsyncState; try { client.EndConnect(iar); conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString(); client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client); } catch (SocketException) { conStatus.Text = "Error connecting"; } }[/CODE] ثم إنشاء Receive Callback method لإنهاء ال BeginReceive وكما يلي: [CODE]void ReceiveData(IAsyncResult iar) { Socket remote = (Socket)iar.AsyncState; int recv = remote.EndReceive(iar); string stringData = Encoding.ASCII.GetString(data, 0, recv); results.Items.Add(stringData); }[/CODE] ثم إضافة الكود التالي في ال Send Button : [CODE] try { byte[] message = Encoding.ASCII.GetBytes(newText.Text); newText.Clear(); client.BeginSend(message, 0, message.Length, SocketFlags.None,new AsyncCallback(SendData), client); newText.Focus(); } catch(Exception ex){MessageBox.Show(ex.Message);} ثم إنشاء Send Callback method لإنهاء ال BeginSend وكما يلي: void SendData(IAsyncResult iar) { try { Socket remote = (Socket)iar.AsyncState; int sent = remote.EndSend(iar); remote.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), remote); } catch(Exception ex){MessageBox.Show(ex.Message);} }[/CODE] ثم إنشاء Receive Callback method لإنهاء ال BeginReceive وكما يلي: [CODE] void ReceiveData(IAsyncResult iar) { try { Socket remote = (Socket)iar.AsyncState; int recv = remote.EndReceive(iar); string stringData = Encoding.ASCII.GetString(data, 0, recv); results.Items.Add(stringData); } catch(Exception ex){MessageBox.Show(ex.Message);} }[/CODE] وكما لاحظنا فإن برنامج ال Client لا يختلف كثيرا عن برنامج ال Server حيث نعرف في ال Server ال Socket Connection وال BeginAccept Method أما في ال Client فنعرف ال Socket Connection و ال BeginConnect Method وتبقى عملية الإرسال والاستقبال هي نفسها في Server وال Client ...  

 اسم العضو:fmo_82  الثلاثاء,04/ذو الحجة/1426 هـ,08:35 صباحاً
وهنا قد تم الانتهاء من الجزء الثاني وفي الجزء الثالث من هذه السلسلة سوف نتحدث ال Multicasting بشكل أكثر تفصيلا كما سوف نتحدث Network Security Programming والتي تضم ال Cryptographyوال Authentication Protocols [ALIGN=center][IMG]http://x12.putfile.com/1/1303453962.jpg[/IMG][/ALIGN] لتحميل ال Chapter 2 ثلاثة دروس : 

 اسم العضو:fmo_82  الجمعة,14/ذو الحجة/1426 هـ,04:41 مساءً
بسم الله الرحمن الرحيم , يعتبر هذا الدرس واحد من أهم الدروس التي عرضناها سابقا إذ سوف نتعلم فيه كيفية بناء أنظمة متقدمة مثل ال Conference Systems بشتى أنواعها معتمدا على Multicasting Programming . الدرس الثالث عشر: Advanced Multicasting Systems : قمنا سابقا بتعريف ال Multicasting وبينا الفرق بينها وبين ال Broadcasting وبينا أنواعها وكيفية التعامل معها في الدوت نيت وفي هذه الدرس سوف نتحدث عنها بشكل أكثر تفصيلا وذلك لأهميتها الكبيرة في برمجيات الشبكات وخاصة برمجيات ال Conferencing... أولا : Architecture of Multicast Sockets : من المعروف انه يتم التعامل مع ال Multicasting عبر برتوكول ال UDP وباستخدام ال Class D Subnet Mask وتتم عملية إدارة المجموعات باستخدام برتوكول ال IGMP – Internet Group Management Protocol والذي هو جزء من ال Internet Protocol Model وكما يتضح من الشكل التالي فإن برتوكول ال IGMP يحتوي على عمليات التحقق من الوصول السليم للبيانات (حيث يتم إرسال حجم البيانات الكلي لرسالة وهي اختيارية إذ يمكن إلغائها بوضع الرقم صفر) , و تحتوي أيضا على ال TTL Time to Live والذي يحدد فيه العمر الافتراضي لكل رسالة, ونوع العملية الإدارية ( ضم إلى مجموعة , إلغاء من مجموعة , أو إرجاع معلومات عن المجموعة Membership Query) وأخيرا عنوان المجموعة التي يتم تحديدها برمجيا ضمن ال Range المحدد لل Class D . [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/IGMP.JPG[/IMG] وتم تخصيص ال Range في ال Multicasting من 224.0.0.0 إلى 239.255.255.255 ونستطيع تحديده بثلاثة طرق فإما بشكل يدوي Static أو Dynamic أو على أساس ال Scope-Relative وبشكل عام تستخدم هذه التوزيعات كما يلي كمثال: التخصيص 224.0.0.1 ويستخدم في جميع الشبكات المحلية فقط حيث لا يتم تمريره إلى شبكة أخرى عبر ال Router أما إذا أردنا التمرير إلى شبكات أخرى عبر ال Router فنستخدم التخصيص 224.0.0.2 و لكن بشرط استخدام نفس ال Subnet في الشبكات الأخرى ... ولمعرفة جميع التخصيصات لل Multicasting انظر الرابط التالي: [URL=http://www.iana.org/assignments/multicast-addresses]http://www.iana.org/assignments/multicast-addresses[/URL] يتم نقل ال Multicast Packets بين ال Backbone Tunnels باستخدام ال Unicast Tunnel حيث يتم إرسالها من داخل الشبكة إلى ال Router و ترسل من Router إلى أخر عبر ال Backbone Tunnel باستخدام أسلوب ال Unicast وهو ما يوفر الكثير من ال Bandwidth في الشبكة حيث ترسل نسخة واحدة إلى ال Router ويقوم هو بتوزيعها على الأجهزة باستخدام ال Unicast المشكلة الوحيدة في ال Multicast هو انه يعتمد بشكل كامل على استخدام ال UDP Connectionless Protocol. ويمكننا استخدام ال Multicasting في ثلاثة أنواع من الشبكات وهي شبكات ال Peer to Peer حيث لا وجود لجهاز Server والكل يستقبل و يرسل من و إلى ال Group الذي هو فيه, والنوع الثاني Server Based Network حيث يتم إرسال رسالة واحدة إلى ال Server ويقوم ال Server بتوزيعها على بقية الأجهزة في الشبكة , أما النوع الثالث فيتم من خلال ال Router , وكما يتضح من الشكل التالي فإن عملية الإرسال تتم بعد انضمام ال Client إلى المجموعة التي تملك ال IP Multicast ويرسل ال Client رسالة واحدة إلى ال Router حيث يقوم ال Router بتوزيعها على الأجهزة في المجموعة مستخدما ال Routing Table. [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/Multicast_routing.JPG[/IMG] وكما كان الحال في الإرسال باستخدام ال Broadcasting يتم الإرسال في Multicasting من جهاز محدد إلى مجموعة معينة وليس إلى الكل كما في ال Broadcast , حيث تُكون كل مجموعة من الأجهزة Group خاص ويتم التخصيص كما ذكرنا سابقا وفق ال IP Multicasting حيث تمتلك كل مجموعة نفس ال IP Multicast ويوجد عدة أشكال لل Multicasting ومن الأمثلة عليها الإرسال إلى مجموعة one to Group و الإرسال إلى أكثر من مجموعة one to Multi Group : 1 – الإرسال مجموعة One to Group: وفيه يملك ال User Sender نفس ال IP Multicasting الذي يملكه ال Receiver Users ويتم الإرسال من داخل ال Group إلى جميع أعضائه حيث ترسل ك Unicast إلى ال Access Point حيث يقوم بتوزيعها على كافة الأعضاء في المجموعة بأسلوب ال Broadcast وكما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/1OnetoGroup.JPG[/IMG] - الإرسال إلى أكثر من مجموعة One to Multi-Groups: وفيه قد يكون ال IP Multicasting لل User Sender مختلف عن Receiver Users ويتم الإرسال من User داخل ال Group إلى المجموعة الذي هو عضو منها وإلى مجموعات أخرى , ويتم تحديدها باستخدام Address List للمجموعات التي نريد الإرسال لها ... [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/2OnetoMGroup.JPG[/IMG] ثانيا :Using Multicast Sockets with .NET: شرحنا سابقا كيفية التعامل مع ال Multicasting في الدوت نيت وتعرفنا على ال Members وال Classes الخاصة بها وهنا سوف نبين بشيء من التفصيل هذه العمليات ونطبق عليها مجموعة من الأمثلة وبعد ذلك سنقوم ببناء نظام Conference System معتمدا على ال Multicasting ... من العمليات الأساسية في التعامل مع ال Multicasting : 1- الانضمام أو الخروج من مجموعة Joining || Drop Group : لا تلزم عملية الانضمام إلى ال Multicast Group أي عمليات تحقق سوى التصنت على ال port وال IP Multicasting المحدد , ويتم ذلك بعد تعريف udpClient Object وباستخدام ال JoinMulticastGroup Method يتم تعريف ال IP Multicasting الذي سوف ننضم إليه وكما يلي: [CODE]UdpClient sock = new UdpClient(9050); sock.JoinMulticastGroup(IPAddress.Parse("225.100.0.1"), 50); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0);[/CODE] وكما يلي لإلغاء عملية الانضمام من مجموعة: [CODE]sock.DropMulticastGroup(IPAddress.Parse("225.100.0.1"));[/CODE] إذ تستخدم الMethods JoinMulticastGroup و DropMulticastGroup لضم أو إلغاء عنوان أو مجموعة من العناوين من ال Multicast Group , وباستخدام Class MulticastOption: يمكننا تخزين IP Address List لتعامل معها في Multicast Group لعمل Join و Drop لأي Multicast Group وتستخدم كما يلي كمثال لإضافة عضوية لاستقبال رسائل Multicast : أولا نعرف ال UDP Socket وكما يلي : [CODE]mcastSocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp);[/CODE] ثانيا نقوم بتعريف Address List ثم نسند إليها ال IP الذي نريد إدخاله في ال Group أو نجعل ال User يدخل العنوان بنفسه نربطها بالسكوت باستخدام الميثود Bind وكما يلي : [CODE]IPAddress localIPAddr = IPAddress.Parse(Console.ReadLine()); mcastSocket.Bind(IPlocal);[/CODE] ثالثا نقوم بتعريف ال Multicast Option ونسند لها العنوان المحدد كما يلي: [CODE]MulticastOption mcastOption; mcastOption = new MulticastOption(localIPAddr);[/CODE] ومن ثم نضيف التغير على SetSocketOption حيث تأخذ هذه الميثود ثلاثة باروميترات الأول لتحديد مستوى التغيير على IP أو على IPv6 أو على Socket أو TCP أو UDP وفي حالتنا هذه سوف نستخدم التغير على IP إذ ما نريده هو ضم IP إلى Multicast Group وفي الباروميتر الثاني نحدد نوع التغيير حيث نريد إضافة عضوية ويمكن الاختيار بين إضافة عضويه AddMembership أو إلغاء عضوية DropMembership وأخيرا نسند إليه ال MulticastOption Object والذي قمنا بإنشائه و كما يلي: [CODE]mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,mcastOption);[/CODE] 2- الإرسال إلى مجموعة Sending Data to a Multicast Group: حتى نستطيع الإرسال باستخدام ال IP Multicasting لابد أولا من تعريف ال Socket Object باستخدام ال UDP Connection وإسناد ال IP Multicasting ورقم ال Port إلى ال Object IPEndPoint ... ونستطيع الإرسال باستخدام ال sendto method حيث نسند لها ال data as Bytes Array وال IPEndPoint Object وكما يلي لإرسال رسالة نصية: [CODE]Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse((“225.100.0.1”), 9050); byte[] data = Encoding.ASCII.GetBytes(msg.Text); server.SendTo(data, iep); server.Close(); msg.Clear(); msg.Focus();[/CODE] ولإرسال Binary Data كإرسال صورة مثلا لابد من استخدام ال Memory Stream لتخزين الصورة في الذاكرة على هيئة Stream ثم تحويلها إلى Byte Array وبعد ذلك إرسالها باستخدام ال sendto Method وكما يلي: [CODE]MemoryStream ms = new MemoryStream(); PictureBox1.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg); byte[] arrImage = ms.GetBuffer(); ms.Close(); Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(“225.100.0.1”), 5020); server.SendTo(arrImage,iep);[/CODE] 3- الاستقبال من مجموعة Receiving Data From a Multicast Group: حتى نستطيع الاستقبال من مجموعة لابد أولا من تحديد ال IP Multicast الخاص بالمجموعة و الانضمام إليه ثم استقبال البيانات باستخدام ال Receive Method ويتم ذلك كما يلي لاستقبال رسالة نصية وعرضها في list Box: [CODE]UdpClient sock = new UdpClient(9050); sock.JoinMulticastGroup(IPAddress.Parse(“225.100.0.1”), 50); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); byte[] data = sock.Receive(ref iep); string stringData = Encoding.ASCII.GetString(data, 0, data.Length); listBox1.Items.Add(iep.Address.ToString() +" :_ "+stringData );[/CODE] ولاستقبال صورة نستخدم ال memory Stream لاستقبال البيانات من ال Receive Method وتخزينها في الذاكرة على هيئة Stream Data ثم تحويلها إلى صورة مرة أخرى باستخدام ال image.FromStream Method وكما يلي: [CODE]UdpClient sock = new UdpClient(5020); sock.JoinMulticastGroup(IPAddress.Parse(“225.100.0.1”)); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); byte[] data = sock.Receive(ref iep); MemoryStream ms = new MemoryStream(data); pictureBox1.Image = Image.FromStream(ms); sock.Close();[/CODE] ملاحظات هامة في استخدام ال Multicasting في برمجيات الشبكات : 1- من الملاحظ أننا لا نستطيع استخدام ال Network Stream لعملية إرسال ال Multicasting إذ يتطلب استخدامها وجود TCP Socket Connection وهو غير متاح في ال Multicasting ويستعاض عنها باستخدام ال memory Stream لإرسال Binary Stream عبر ال sendto method ... 2- لا يمكنك استخدام ال Multicasting ك loopback في حالة عدم وجود شبكة أو اتصال لذلك لن تستطيع تجربة أي من تطبيقات ال Multicasting في حالة عدم اتصالك بالشبكة. 3- يمكن لكل جهاز أن ينضم إلى أكثر من مجموعة بحيث يستقبل من جهات متعددة, كذلك يستطيع الإرسال إلى عدة مجموعات. 4- في العادة تكون السعة المسموحة لإرسال ال Multicasting Data عبر ال sendto Method محدودة لذلك يمكنك استخدام ال Binary Reader & Writer وال Stream Reader & Writer لإرسال والاستقبال بدلا منها ... 5- تتم عملية اختيار ال IP Multicast وفق لل Network Topology التي تملكها لذلك لابد من التقيد بالعناوين المحددة وهو ما بينته سابقا .. ثالثا تطبيق مشروع نظام المؤتمرات Multicasting Conferencing Systems : في هذا التطبيق سوف نفترض وجود غرفة صفية حيث يقوم المحاضر بإلقاء المحاضرة عن بعد أمام طلابه إذ نريد هنا جعل الطلاب يرون الأستاذ وكما يستطيع الأستاذ رؤية طلابه بالإضافة إلى إمكانية عرض المحاضرة على ال Power Point Slides كما يستطيع الطلاب التحدث مع الأستاذ باستخدام Text Chatting ... سوف نقوم هنا بتقسيم نظام المؤتمرات إلى ثلاثة أنظمة رئيسية وهي نظام مؤتمرات الفيديو ونظام مؤتمرات سطح المكتب ونظام المؤتمرات النصية, في البداية سوف نقوم بعمل الشاشة الرئيسية للبرنامج و كما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/p0.JPG[/IMG] 1- Full/Half Duplex Multicast Video Conferencing System: وفرت لنا Microsoft مجموعة من ال Classes الخارجية والتي تتعامل مع ال DirectX 9 مباشرة حيث نستطيع استخدامها لتعامل مع الكاميرا أو ال Scanner أو الصوت أو أي طرفية أخرى وفي هذا التطبيق سوف نستخدم الClasses Direct Show Dot Net لالتقاط صورة عبر الكاميرا وعرضها على ال Picture box حيث نستطيع إرسالها لاحقا إلى ال Multicast Group باستخدام ال memory Stream وال Sendto method وهو ما بيناه سابقا .. وحتى نستطيع استخدامها سوف نضم ال Direct Show Classes إلى المشروع وكما يلي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/P1.JPG[/IMG] وحتى نتعامل معها سوف نستدعيها باستخدام : [CODE]using DShowNET; using DShowNET.Device;[/CODE] وسيكون شكل برنامج الإرسال عبر الكاميرا كما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/p2.JPG[/IMG] سوف نستخدم ال DeviceSelector Class لإختيار جهاز الإدخال عند بداية تشغيل البرنامج وكما يلي: [CODE]DeviceSelector selector = new DeviceSelector( capDevices ); selector.ShowDialog( this ); dev = selector.SelectedDevice;[/CODE] و لإلتاط الصورة عبر الكاميرا سوف نقوم بإنشاء method جديدة كما يلي : [CODE]void OnCaptureDone() { try { Trace.WriteLine( "!!DLG: OnCaptureDone" ); toolBarBtnGrab.Enabled = true; int hr; if( sampGrabber == null )return; hr = sampGrabber.SetCallback( null, 0 ); int w = videoInfoHeader.BmiHeader.Width; int h = videoInfoHeader.BmiHeader.Height; if( ((w & 0x03) != 0) || (w < 32) || (w > 4096) || (h < 32) || (h > 4096) ) return; int stride = w * 3; GCHandle handle = GCHandle.Alloc( savedArray, GCHandleType.Pinned ); int scan0 = (int) handle.AddrOfPinnedObject(); scan0 += (h - 1) * stride; Bitmap b = new Bitmap( w, h, -stride, PixelFormat.Format24bppRgb, (IntPtr) scan0 ); handle.Free(); savedArray = null; Image old = pictureBox.Image; pictureBox.Image = b; if( old != null ) old.Dispose(); toolBarBtnSave.Enabled = true;} catch( Exception){} }[/CODE] ثم عمل Timer وإضافة الكود التالي فيه لاستمرار عملية التقاط الصورة: [CODE]int hr; int size = videoInfoHeader.BmiHeader.ImageSize; savedArray = new byte[ size + 64000 ];[/CODE] ولإرسال الصورة إلى الطرف الأخر سوف نستخدم method إرسال الصورة ونضعه في Timer وكما يلي: [CODE]try { MemoryStream ms = new MemoryStream(); pictureBox.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg); byte[] arrImage = ms.GetBuffer(); ms.Close(); Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(textBox1.Text), 5020); server.SendTo(arrImage, iep); server.Close();} catch (Exception){}[/CODE] وهنا يستطيع المحاضر إرسال الصورة عبر الكاميرا إلى طلابه كما سوف يتمكن من رؤية طلابه عبر الكاميرا وسوف نفترض هنا استخدامه لشبكة لا سلكية حيث سيرسل البيانات إلى ال Access Point بأسلوب ال Unicast وسوف يتولا ال Access Point توزيع البيانات إلى جميع الأعضاء المنضمين إلى ال Multicast Group ويرسلها لهم باستخدام ال Broadcast وكما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/3VCS.JPG[/IMG] وكما نلاحظ في الشكل السابق فإن المحاضر ينضم إلى مجموعتين مجموعة الأساتذة وهي 225.100.1.1 حيث سيستقبل صورة طلابه عليها, ومجموعة الطلاب 224.100.0.1 والتي سوف يرسل الصورة إليها .. وكما نلاحظ ايضا فإن عملية الإرسال بين ال Access Point1 وال Access Point2 تتم باستخدام ال Unicast ... وحتى يستطيع الطلاب رؤية أستاذهم والأستاذ رؤية طلابه , لابد من إنشاء برنامج الاستقبال حيث سنستخدم نفس ال method التي شرحنها سابقا لاستقبال الصورة وللبدء قم بعمل New Form جديد كما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/p3.JPG[/IMG] سوف نستخدم ال Namespaces التالية لاستقبال الصورة من ال Multicast Group : [CODE]using System.Net.Sockets ; using System.Net; using System.IO; using System.Threading;[/CODE] ثم قم بكتابة method الاستقبال كما يلي: [CODE]void Image_Receiver() { UdpClient sock = new UdpClient(5020); sock.JoinMulticastGroup(IPAddress.Parse(textBox1.Text)); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0);   byte[] data = sock.Receive(ref iep); MemoryStream ms = new MemoryStream(data); pictureBox1.Image = Image.FromStream(ms); sock.Close(); }[/CODE]وحتى نستدعيها لابد من استخدام ال Threading حتى لا يتأثر نظام التشغيل بعملية الاستقبال , وحتى نقوم بذلك قم بعمل Timer وضع فيه الكود التالي لاستخدام ال Threading : [CODE]Thread myth; myth= new Thread (new System.Threading .ThreadStart(Image_Receiver));  myth.Start ();[/CODE] وحتى تتمكن من تخزين الصورة الملتقطة عبر الكاميرا على هيئة JPEG Image File قم بإنشاء saveFileDialog واستدعيه كما يلي: [CODE]try { saveFileDialog1.Filter = "JPEG Image (*.jpg)|*.jpg" ; if(saveFileDialog1.ShowDialog() == DialogResult.OK) { string mypic_path = saveFileDialog1.FileName; pictureBox1.Image.Save(mypic_path); } } catch (Exception){}[/CODE] وهنا قد تم الانتهاء من المشروع الأول وهو ال Video Conference System , وحتى يستطيع المحاضر عرض المحاضرة باستخدام برنامج ال Power Point سوف نقوم بعمل مشروع مؤتمرات سطح المكتب ... 2- Full/Half Duplex Multicast Desktop Conferencing System: الهدف من هذا المشروع هو تمكين الأستاذ من عرض المحاضرة باستخدام برنامج ال Power Point حيث سترسل صورة سطح المكتب من جهاز الأستاذ إلى أجهزة الطلبة , ولا تختلف عملية الإرسال عن البرنامج السابق في شيء سوى إنشاء Classes لتقوم بالتقاط صورة سطح المكتب ومن ثم إرسالها إلى ال Multicast Group ومن ثم استقبالها وعرضها على الطلاب باستخدام Data Show Projector ... وهنا مخطط عمل البرنامج [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/4DCS.JPG[/IMG] وكما نلاحظ من الشكل التالي فإن الأستاذ يقوم بشرح المحاضرة على جهازه الشخصي ويرسل الصورة إلى الطلاب وكما نلاحظ أيضا فإن هذه العملية هي أحادية الاتجاه وكما يمكن جعلها باتجاهين Full || Half Duplex لكن لابد من إنشاء مجموعة جديدة لعملية الإرسال من الطالب إلى الأستاذ حيث يعرض الأستاذ محاضرته ويرسلها إلى مجموعة الطلاب ويستطيع أحد الطلاب عرض جهازه على الأستاذ إذ يرسل الصورة إلى مجموعة الأستاذ ... ولإنشاء برنامج إرسال صورة سطح المكتب قم بعمل New Form جديد كما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/p4.JPG[/IMG] في البداية سوف نقوم بعمل Three Classes لالتقاط صورة سطح المكتب وكما يلي: أولا PlatFormInvokeGDI32.cs لالتقاط صورة سطح المكتب باستخدام ال GDI+ وال API: [CODE]using System; using System.Runtime.InteropServices; namespace SampleGrabberNET { //This class shall keep the GDI32 APIs being used in our program. public class PlatformInvokeGDI32 { #region Class Variables public const int SRCCOPY = 13369376; #endregion #region Class Functions [DllImport("gdi32.dll",EntryPoint="DeleteDC")] public static extern IntPtr DeleteDC(IntPtr hDc); [DllImport("gdi32.dll",EntryPoint="DeleteObject")] public static extern IntPtr DeleteObject(IntPtr hDc); [DllImport("gdi32.dll",EntryPoint="BitBlt")] public static extern bool BitBlt(IntPtr hdcDest,int xDest,int yDest,int wDest,int hDest,IntPtr hdcSource,int xSrc,int ySrc,int RasterOp); [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleBitmap")] public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); [DllImport ("gdi32.dll",EntryPoint="CreateCompatibleDC")] public static extern IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport ("gdi32.dll",EntryPoint="SelectObject")] public static extern IntPtr SelectObject(IntPtr hdc,IntPtr bmp); #endregion #region Public Constructor public PlatformInvokeGDI32() { } #endregion }}[/CODE] ثانيا PlatformInvokeUSER32.cs إذ سوف نستخدمها مع ال Class السابق لالتقاط صورة سطح المكتب باستخدام ال user32 API : [CODE]using System; using System.Runtime.InteropServices; namespace SampleGrabberNET { // This class shall keep the User32 APIs being used in our program. public class PlatformInvokeUSER32 { #region Class Variables public const int SM_CXSCREEN=0; public const int SM_CYSCREEN=1; #endregion #region Class Functions [DllImport("user32.dll", EntryPoint="GetDesktopWindow")] public static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll",EntryPoint="GetDC")] public static extern IntPtr GetDC(IntPtr ptr); [DllImport("user32.dll",EntryPoint="GetSystemMetrics")] public static extern int GetSystemMetrics(int abc); [DllImport("user32.dll",EntryPoint="GetWindowDC")] public static extern IntPtr GetWindowDC(Int32 ptr); [DllImport("user32.dll",EntryPoint="ReleaseDC")] public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDc); #endregion #region Public Constructor public PlatformInvokeUSER32() { } #endregion } //This structure shall be used to keep the size of the screen. public struct SIZE { public int cx; public int cy; } }[/CODE] ثالثا: CaptureScreen.cs والتي سوف نستخدمها بشكل مباشر في البرنامج حيث يتعامل مع الClass PlatFormInvokeGDI32 وال PlatformInvokeUSER32 Class : [CODE]using System; using System.Drawing; namespace SampleGrabberNET { //This class shall keep all the functionality for capturing the desktop. public class CaptureScreen { #region Public Class Functions public static Bitmap GetDesktopImage() { //In size variable we shall keep the size of the screen. SIZE size; //Variable to keep the handle to bitmap. IntPtr hBitmap; //Here we get the handle to the desktop device context. IntPtr hDC = PlatformInvokeUSER32.GetDC(PlatformInvokeUSER32.GetDesktopWindow()); //Here we make a compatible device context in memory for screen device context. IntPtr hMemDC = PlatformInvokeGDI32.CreateCompatibleDC(hDC); //We pass SM_CXSCREEN constant to GetSystemMetrics to get the X coordinates of screen. size.cx=PlatformInvokeUSER32.GetSystemMetrics(PlatformInvokeUSER32.SM_CXSCREEN); //We pass SM_CYSCREEN constant to GetSystemMetrics to get the Y coordinates of screen. size.cy=PlatformInvokeUSER32.GetSystemMetrics(PlatformInvokeUSER32.SM_CYSCREEN); //We create a compatible bitmap of screen size using screen device context. hBitmap = PlatformInvokeGDI32.CreateCompatibleBitmap(hDC, size.cx, size.cy); //As hBitmap is IntPtr we can not check it against null. For this purspose IntPtr.Zero is used. if (hBitmap!=IntPtr.Zero) { //Here we select the compatible bitmap in memory device context and keeps the reference to Old bitmap. IntPtr hOld = (IntPtr) PlatformInvokeGDI32.SelectObject(hMemDC, hBitmap); //We copy the Bitmap to the memory device context. PlatformInvokeGDI32.BitBlt(hMemDC, 0, 0,size.cx,size.cy, hDC, 0, 0, PlatformInvokeGDI32.SRCCOPY); //We select the old bitmap back to the memory device context. PlatformInvokeGDI32.SelectObject(hMemDC, hOld); //We delete the memory device context. PlatformInvokeGDI32.DeleteDC(hMemDC); //We release the screen device context. PlatformInvokeUSER32.ReleaseDC(PlatformInvokeUSER32.GetDesktopWindow(), hDC);//Image is created by Image bitmap handle and stored in local variable. Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap); //Release the memory to avoid memory leaks. PlatformInvokeGDI32.DeleteObject(hBitmap); //This statement runs the garbage collector manually. GC.Collect();//Return the bitmap return bmp; }//If hBitmap is null return null. return null; } #endregion } }[/CODE] وحتى نستطيع التحكم في حجم الصورة سوف نكتب ال method التالية: [CODE]public Bitmap ResizeBitmap( Bitmap b, int nWidth, int nHeight ) { Bitmap result = new Bitmap( nWidth, nHeight ); using( Graphics g = Graphics.FromImage( (Image) result ) ) g.DrawImage( b, 0, 0, nWidth, nHeight ); return result; }[/CODE] سوف نستخدم ال Namespaces التالية في البرنامج لتعامل مع ال Multicasting : [CODE]using System.Net; using System.Net.Sockets; using System.IO;[/CODE] ثم نقوم بعمل Timer لالتقاط صورة سطح المكتب و إرسالها إلى ال Multicast Group المحدد : [CODE]Bitmap bt = new Bitmap(CaptureScreen.GetDesktopImage()); picScreen.Image = ResizeBitmap(bt, 352, 200 ); MemoryStream ms = new MemoryStream(); picScreen.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg); byte[] arrImage = ms.GetBuffer(); ms.Close(); Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(textBox1.Text), 5020); server.SendTo(arrImage,iep); server.Close();[/CODE] 3- Full/Half Duplex Multicast Text Conferencing System: وحتى يستطيع الطلبة التحدث إلى الأستاذ باستخدام ال Text Chat Multicast Conference System سوف نقوم بإنشاء New Form جديد وكما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/p5.JPG[/IMG] ثم قم بإضافة ال Namespaces التالية: [CODE]using System.Net; using System.Net.Sockets; using System.Text; using System.Threading;[/CODE] سوف نستخدم ال method التالية لإجراء عملية الإرسال حيث سترسل الرسالة عند الضغط على ال Enter بعد كتابة الرسالة في ال Textbox المخصص : [CODE]private void msg_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {if(e.KeyChar == '\r'){ try{ Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(txt_host.Text), 9050); byte[] data = Encoding.ASCII.GetBytes(msg.Text); server.SendTo(data, iep); server.Close(); msg.Clear(); msg.Focus(); }catch(Exception){}}}[/CODE] وسوف نستخدم الميثود التالية لعملية الاستقبال حيث ستعرض الرسالة المستقبلة في list Box مخصص: [CODE]public void server() { try { UdpClient sock = new UdpClient(9050); sock.JoinMulticastGroup(IPAddress.Parse(txt_host.Text), 50); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); byte[] data = sock.Receive(ref iep); string stringData = Encoding.ASCII.GetString(data, 0, data.Length); listBox1.Items.Add(iep.Address.ToString() +" :_ "+stringData ); sock.Close(); listBox1.Focus(); msg.Focus(); myth.Abort(); } catch(Exception){} }[/CODE]ولاستدعائها لابد من استخدام ال Threading , قم بعمل Timer واستدعي فيه ال method السابقة باستخدام ال Thread وكما يلي: [CODE]Thread myth; myth= new Thread (new System.Threading .ThreadStart(server)); myth.Start ();[/CODE] سوف نشغل ال Timer عند الضغط على زر الاتصال باستخدام timer1.Enabled = true وفي زر إنهاء الاتصال قم بإضافة الكود التالي: [CODE]timer1.Enabled = false; txt_host.ReadOnly = false; msg.Enabled=false; try { Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(txt_host.Text), 9050); byte[] data = Encoding.ASCII.GetBytes("has Left the Room"); server.SendTo(data, iep); server.Close(); msg.Clear(); msg.Focus(); } catch(Exception){}[/CODE] وهنا قد تم الانتهاء من الدرس الثالث عشر وفي الدرس التالي سوف نتحدث عن ال Network Security Programming وأساليب تشفير وحماية البيانات واستخدامها في برمجيات الشبكات ... لتحميل الدرس ونظام المؤتمرات انظر المرفقات : 

 اسم العضو:students  الاثنين,17/ذو الحجة/1426 هـ,05:12 صباحاً
السلام عليكم ورحمة الله وبركاته الله يجزيك عن المبرمجين العرب ألف خير وأن شاء الله تستمر في أعطاء هذا العلم النافع وإن لم تجد مشاركة أو تفاعل في الوقت الراهن فسوف يظل علم يستفاد منة. أطلعت على الدرس وبصراحة لم أطبقة بعد لانني لم أزل في الدروس الذي قبلة (تلميذ مهمل جدا ) ولكن جذب أنتباهي أستخدامك ثلاث كلاسات لإلتقاط صورة لسطح المكتب حيث أنني في مشروع تخرجي أحتجت لإلتقاط صور لسطح المكتب ولم أستخدم إلا هذا الكود( الذي أخرجتة من الإنترنت للأمانة العلمية): [CODE] [DllImport("gdi32.dll")] private static extern int CreateDC(string lpDriverName, string lpDeviceName, string lpOutput, string lpInitData); [DllImport("gdi32.dll")] private static extern int CreateCompatibleDC(int hDC); [DllImport("gdi32.dll")] private static extern int CreateCompatibleBitmap(int hDC, int nWidth, int nHeight); [DllImport("gdi32.dll")] private static extern int GetDeviceCaps(int hdc, int nIndex); [DllImport("gdi32.dll")] private static extern int SelectObject(int hDC, int hObject); [DllImport("gdi32.dll")] private static extern int BitBlt(int srchDC, int srcX, int srcY, int srcW, int srcH, int desthDC, int destX, int destY, int op); [DllImport("gdi32.dll")] private static extern int DeleteDC(int hDC); [DllImport("gdi32.dll")] private static extern int DeleteObject(int hObj); try { const int SRCCOPY = 13369376; int FW, FH; int hSDC, hMDC; int hBMP, hBMPOld; int r; //string dirname = clsstartup.arraygeneralsetting[8].ToString()+ @"\Temp\Pic"; hSDC = CreateDC("DISPLAY", "", "", ""); hMDC = CreateCompatibleDC(hSDC); FW = GetDeviceCaps(hSDC, 8); FH = GetDeviceCaps(hSDC, 10); hBMP = CreateCompatibleBitmap(hSDC, FW, FH); hBMPOld = SelectObject(hMDC, hBMP); r = BitBlt(hMDC, 0, 0, FW, FH, hSDC, 0, 0, SRCCOPY); hBMP = SelectObject(hMDC, hBMPOld); r = DeleteDC(hSDC); r = DeleteDC(hMDC); Bitmap imgdesktop = Image.FromHbitmap(new IntPtr(hBMP)); DeleteObject(hBMP); imgdesktop.Save(dirname, System.Drawing.Imaging.ImageFormat.Jpeg); } catch(Exception ex) { }[/CODE] أولا : أود أن أعرف هل هناك فرق أم أنهما طريقتان مختلفتان ولا يوجد بينهما فرق مع العلم من أنة جميع الدوال الموجودة هناوالبرمجة تقريبا أنت قمت باستخدامها وأضفت عليها. ثانيا : ما فائدة تقسيمك الكود إلى ثلاثة كلاسات لماذا لم تسرد البرمجة كاملة في كلاس واحد ومن ثم تفوم باستخدامة ولماذا أستخدمت دوال الـ api (حيث كان أستاذي في الجامعة يجن جنونة عندما أذكر لة دوال api في الـ .net)هل لانة لا يوجد كلاسات في الـ .net تدعم هذا الشيء. وشكرا  

 اسم العضو:fmo_82  الاثنين,17/ذو الحجة/1426 هـ,06:04 صباحاً
الأخ students بانسبة للكود السابق الذي وضعته في الدرس فهو ليس ابتكاري وإنما مأخوذ عن ال MSDN وطريقة التقسيم هذه مهمة جدا إذ تنظم العمل بشكل كبير مما يزيد من فاعلية البرنامج وتسهيل استخدامه لاحقا حيث فصلنا الكلاسات التي تتعامل مع ال API واستدعيناها باستخدام الكلاس الأخير وكأنك تتعامل مع Based Function في الدوت نيت وهذه الطريقة متبعة في اغلب البرمجيات لتسهيل التعامل مع ادوات ال API في برمجيات اخرى لاحقا , الكود الذي تفضلت بوضعه جيد لاكن قارن اداءه مع اداء الكود الموجود في الدرس وسوف تعرف الفرق .. واخيرا لا مناص من استخدام ال API في جميع للغات البرمجة التي تعتمد على نظام التشغيل Windows وهو ماسهل على المبرمجين بشكل كبير جدا فمثلا لست مضطرا لبرمجة الاف الأكواد لتشغيل ملف صوت إذ سوف تطر في عدم استخدام ال API إلى كتابة الاف من الأكواد لتعامل مع كرت الصوت والبورت ونظام العرض و و و و ... وهو ما عمل ثورة حقيقية في عالم البرمجة وظهرت هذه الدوال بعد اصدار مايكروسوفت نظام التشغيل Windows 95 حيث وجدت الحاجة لوجود قاعدة يعتمد عليها المبرمجين لتعامل مع ال Hardware في الكمبيوتر وعندها اصدرت ال DirectX ... اعتذر عن الإطالة وارجو ان اكون قد وصلت الفكرة 

 اسم العضو:students  الاثنين,17/ذو الحجة/1426 هـ,06:49 صباحاً
أشكرك أخ فادي والحمد لله وصلت الفكرة  

 اسم العضو:fmo_82  الجمعة,28/ذو الحجة/1426 هـ,01:51 مساءً
بسم الله الرحمن الرحيم الدرس الرابع عشر: Network Security Programming: تتلخص الفكرة من الأمن بحماية البيانات من الدخول غبر المخول unauthorized Access باستخدام عدة أساليب وأهمها : -Data Encryption & Decryption التشفير وفك التشفير -Authentications التحقق من هوية الشخص مرسل الرسالة -Set Policies & Permissions تحديد وتنفيذ السياسات و الصلاحيات دعمت في الدوت نيت جميع أساليب الحماية التي ذكرناها سابقا باستخدام ال Security Namespaces والتي تحتوي على مجموعة ضخمة من المكتبات الفرعية وهي كما في الشكل التالي [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/0.JPG[/IMG] أولا : Cryptography Namespace Overview : Cryptography in .NET: وهي المكتبة التي تهتم بكل ما يخص عمليات تشفير وفك تشفير البيانات من Clear Text إلى Cipher Text وبالعكس وتستخدم بشكل أساسي لتشفير البيانات قبل عملية الإرسال وفك تشفيرها عند الاستلام , ونستطيع تقسيم طرق التشفير فيها إلى ثلاثة أقسام رئيسية هي: A- Symmetric algorithms: الأسلوب المتماثل وفيه يستخدم المفتاح السري ذاته لعملية التشفير وفك التشفير وهي طريقة سريعة لإجراء عملية التشفير وفك التشفير لا كنها ليست آمنة كطريقة الغير المتماثلة ودعمت الدوت نيت التشفير المتماثل بمجموعة من ال Classes Algorithms وهي: - الكلاس الذي يدعم التشفير باستخدام الDES-Data Encryption Standard : DESCryptoServiceProvider - الكلاس الذي يدعم RC2 Algorithms : RC2CryptoServiceProvider - الكلاس الذي يدعم Algorithms Rijndael Managed : RijndaelManaged الطريقة المعتادة في التشفير بالأسلوب المتماثل هي تشفير الرسالة وإرسالها عبر الشبكة لاكن باستخدام هذه الطريقة فإن نسبة الخطأ التي قد تكون عالية جدا وقد نفقد بعض هذه البيانات مما يؤدي إلى فقد الرسالة أو قد تسرق وتجرى عليها عمليات لمحاولة فك الشيفرة ناهيك عن الحجم الهائل التي قد تحجزه من ال Network Bandwidth ..وتم حل هذه المشكلة بجعل عملية التشفير تتم على مستوى ال Stream نفسه ويستخدم لهذه العملية ال CryptoStream Class حيث يتم استخدام مفتاحين لتشفير مفتاح التشفير Encryption Kay ومفتاح لفك التشفير IV Installation Victor Decryption ويشترط استخدام نفس المفتاحين في عملية التشفير وفك التشفير ويستخدم الكلاس السابق مع ال MemoryStream أو FileStream حيث نمرر له ال Stream Data ونوع التشفير سواء DES أو TripleDES أو RC2 , وكمثال سوف نستخدم ال TripleDES إذيجب أن يتكون كلا المفتاحين من 16 Bits ... [CODE]Symmetric Stream Encryption Example: byte[] Key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; byte[] IV = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; string phrase = msg.Text; MemoryStream ms = new MemoryStream();   TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); CryptoStream csw = new CryptoStream(ms,tdes.CreateEncryptor(Key, IV), CryptoStreamMode.Write); csw.Write(Encoding.ASCII.GetBytes(phrase), 0, phrase.Length); csw.FlushFinalBlock(); byte[] cryptdata = ms.GetBuffer(); textBox1.Text=Encoding.ASCII.GetString(cryptdata, 0, (int)ms.Length); [/CODE] [CODE] Symmetric Stream Decryption Example: byte[] Keyy = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; byte[] IVv = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; ms.Position = 0; byte[] data = new byte[1024]; CryptoStream csr = new CryptoStream(ms,tdes.CreateDecryptor(Keyy, IVv),CryptoStreamMode.Read); int recv = csr.Read(data, 0, data.Length); string newphrase = Encoding.ASCII.GetString(data, 0, recv); textBox1.Text=newphrase;[/CODE] في برمجيات الشبكات نقوم في البداية بتشفير البيانات المرسلة باستخدام أي من الأساليب السابقة لتشفير ثم نحول البيانات المشفرة إلى Stream لإرسالها عبر ال Socket باستخدام ال Network Stream , ثم يقوم الطرف المستقبل باستقبال الرسالة باستخدام ال Network Stream عبر ال Socket , عملية فك التشفير تكون كما هي الخوارزمية المستخدمة ثم تحمل الرسالة إلى ال memory stream وتخزن في Byte Array عندها يمكن أن تحول إلى رسالة مرة أخرى وكما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/DE.JPG[/IMG] B- Asymmetric algorithms: الأسلوب الغير متماثل وهو أكثر أمانا من الأسلوب المتماثل إذ تشفر البيانات باستخدام مفتاح عام Public Kay ولفك التشفير يستخدم مفتاح خاص Private Kay ويكون هناك علاقة بين المفتاحين ويستخدم 128 Bits لتشفير وهو أفضل أساليب التشفير للبيانات ودعمت الدوت نيت التشفير الغير متماثل والذي يدعم تشفير المفتاح الخاص Private Kay باستخدام Tow Algorithms Classes وهي: - DSACryptoServiceProvider for Digital Signature Algorithm التواقيع الرقمية :والهدف منها التحقق من هوية الشخص مرسل الرسالة وكمثال يقوم المرسل بتوليد ملخص لرسالة باستخدام الHash Function وبعد ذلك يقوم بتشفير ملخص الرسالة الذي تم توليده لتكوين المفتاح الخاص والذي سيستخدم كتوقيع رقمي للمرسل ثم يرسل المفتاح العام مع الرسالة, أما بما يتعلق بالمستلم فيقوم بفك تشفير الملخص باستخدام المفتاح العام ويجب أن يتم ذلك باستخدام نفس الخوارزمية التي اتبعها المرسل في تشفير الملخص, فإذا كان ملخص الرسالة التي ولدها المستلم هي نفسها التي ولدها المرسل عندها يتحقق من أن الشخص مرسل الرسالة هو نفسه . في البداية سوف ننشئ instance من ال DSACryptoServiceProvider لتوليد المفتاح العام والخاص ثم نكون ال Hash sign Value ونخزنه في Byte Array ولفحصه نولد hash sign value جديد ونقارنه بالسابق فإذا تشابها عندها نقرر أن الشخص هو نفسه صاحب الرسالة المرسلة وكما يلي: [CODE] using System; using System.Security.Cryptography; class DSACSPSample { static void Main() { try { //Create a new instance of DSACryptoServiceProvider to generate //a new key pair. DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); //The hash value to sign. byte[] HashValue = {59,4,248,102,77,97,142,201,210,12,224,93,25,41,100,197,213,134,130,135}; //The value to hold the signed value. byte[] SignedHashValue = DSASignHash(HashValue, DSA.ExportParameters(true), "SHA1"); //Verify the hash and display the results. if(DSAVerifyHash(HashValue, SignedHashValue, DSA.ExportParameters(false), "SHA1")) {Console.WriteLine("The hash value was verified.");} else {Console.WriteLine("The hash value was not verified.");}} catch(ArgumentNullException e) {Console.WriteLine(e.Message);} } public static byte[] DSASignHash(byte[] HashToSign, DSAParameters DSAKeyInfo, string HashAlg) { try { //Create a new instance of DSACryptoServiceProvider. DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); //Import the key information. DSA.ImportParameters(DSAKeyInfo); //Create an DSASignatureFormatter object and pass it the //DSACryptoServiceProvider to transfer the private key. DSASignatureFormatter DSAFormatter = new DSASignatureFormatter(DSA); //Set the hash algorithm to the passed value. DSAFormatter.SetHashAlgorithm(HashAlg); //Create a signature for HashValue and return it. return DSAFormatter.CreateSignature(HashToSign); } catch(CryptographicException e) {Console.WriteLine(e.Message);return null;} } public static bool DSAVerifyHash(byte[] HashValue, byte[] SignedHashValue, DSAParameters DSAKeyInfo, string HashAlg) { try { //Create a new instance of DSACryptoServiceProvider. DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); //Import the key information. DSA.ImportParameters(DSAKeyInfo); //Create an DSASignatureDeformatter object and pass it the //DSACryptoServiceProvider to transfer the private key. DSASignatureDeformatter DSADeformatter = new DSASignatureDeformatter(DSA); //Set the hash algorithm to the passed value. DSADeformatter.SetHashAlgorithm(HashAlg); //Verify signature and return the result. return DSADeformatter.VerifySignature(HashValue, SignedHashValue); } catch(CryptographicException e){Console.WriteLine(e.Message);return false;}}} [/CODE] - RSACryptoServiceProvider ويستخدم في إجراء التشفير وفك التشفير الغير متماثل وهو non inherited Class في البداية سوف ننشئ instance جديد من ال RSACryptoServiceProvider وذلك لتوليد المفتاح العام والخاص ونرفق المفتاح العام مع الرسالة ومن ثم يقوم المستلم بفك الرسالة باستخدام المفتاح الخاص وتتم كما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/encryp.jpg[/IMG] وهنا مثال توضيحي لطريقة التشفير وفك التشفير باستخدام ال RSA Algorithm : [CODE] using System; using System.Security.Cryptography; using System.Text; class RSACSPSample { static void Main() { try { //Create a UnicodeEncoder to convert between byte array and string. UnicodeEncoding ByteConverter = new UnicodeEncoding(); //Create byte arrays to hold original, encrypted, and decrypted data. byte[] dataToEncrypt = ByteConverter.GetBytes("Data to Encrypt"); byte[] encryptedData; byte[] decryptedData; //Create a new instance of RSACryptoServiceProvider to generate //public and private key data. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); //Pass the data to ENCRYPT, the public key information //(using RSACryptoServiceProvider.ExportParameters(false), //and a boolean flag specifying no OAEP padding. encryptedData = RSAEncrypt(dataToEncrypt,RSA.ExportParameters(false), false); //Pass the data to DECRYPT, the private key information //(using RSACryptoServiceProvider.ExportParameters(true), //and a boolean flag specifying no OAEP padding. decryptedData = RSADecrypt(encryptedData,RSA.ExportParameters(true), false); //Display the decrypted plaintext to the console. Console.WriteLine("Decrypted plaintext: {0}", ByteConverter.GetString(decryptedData)); } catch(ArgumentNullException) {Console.WriteLine("Encryption failed.");} }[/CODE] ننشئ الميثود التي ستقوم بتشفير الرسالة: [CODE] static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding) { try{ //Create a new instance of RSACryptoServiceProvider. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); //Import the RSA Key information. This only needs //to include the public key information. RSA.ImportParameters(RSAKeyInfo); //Encrypt the passed byte array and specify OAEP padding. //OAEP padding is only available on Microsoft Windows XP or //later. return RSA.Encrypt(DataToEncrypt, DoOAEPPadding); } //Catch and display a CryptographicException //to the console. catch(CryptographicException e){Console.WriteLine(e.Message);return null;} }[/CODE] ننشئ الميثود التي ستقوم بفك تشفير الرسالة: [CODE] static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo,bool DoOAEPPadding) { try { //Create a new instance of RSACryptoServiceProvider. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); //Import the RSA Key information. This needs //to include the private key information. RSA.ImportParameters(RSAKeyInfo); //Decrypt the passed byte array and specify OAEP padding. //OAEP padding is only available on Microsoft Windows XP or //later. return RSA.Decrypt(DataToDecrypt, DoOAEPPadding); } //Catch and display a CryptographicException //to the console. catch(CryptographicException e){Console.WriteLine(e.ToString());return null;} }}[/CODE] C- Hashing algorithms: وهو أقوى الأساليب البرمجية لتشفير البيانات إذ يستخدم فيه algorithm 512 bits كحد أقصى بدلا من 128 bits باستخدام Message Digest Algorithms MAC وهنا لن تستطيع فك تشفير الرسالة وإرجاعها إلى حالتها السابقة ويستخدم بشكل أساسي لتوليد ال Passwords وفي توليد التواقيع الرقمية Digital Signature وفي اغلب الحالات تستخدم لتخزين كلمة المرور Password في ال Database بشكل امن. ويستخدم ال SHA1Managed و ال SHA256Managed وال SHA384Managed وال SHA512Managed لتعريف Hash Object ومنه نستخدم ال ComputeHash Method لتوليد ال hash code وتخزينه في byte Array وكما يلي كمثال: [CODE] SHA1Managed shaM1 = new SHA1Managed (); byte[] my_kay1= ASCIIEncoding.ASCII.GetBytes("convert this text to hash code"); byte[] hashed_kay1 = shaM1.ComputeHash(my_kay1); MessageBox.Show(ASCIIEncoding.ASCII.GetString(hashed_kay1)); SHA256Managed shaM2 = new SHA256Managed(); byte[] my_kay2= ASCIIEncoding.ASCII.GetBytes("convert this text to hash code"); byte[] hashed_kay2 = shaM2.ComputeHash(my_kay2); MessageBox.Show(ASCIIEncoding.ASCII.GetString(hashed_kay2)); SHA384Managed shaM3 = new SHA384Managed (); byte[] my_kay3= ASCIIEncoding.ASCII.GetBytes("convert this text to hash code"); byte[] hashed_kay3 = shaM3.ComputeHash(my_kay3); MessageBox.Show(ASCIIEncoding.ASCII.GetString(hashed_kay3)); SHA512Managed shaM4 = new SHA512Managed (); byte[] my_kay4= ASCIIEncoding.ASCII.GetBytes("convert this text to hash code"); byte[] hashed_kay4 = shaM4.ComputeHash(my_kay4); MessageBox.Show(ASCIIEncoding.ASCII.GetString(hashed_kay4)); [/CODE] ثانيا: Permission Namespace Overview : وتدعم ال Permission Namespace في الدوت نيت ثلاثة أنواع من الصلاحيات وهي ال Socket permissions وال Identity Permissions وال Role- based permissions ... Socket Permission: وتمكنك من تحديد صلاحيات استخدام ال Socket في برمجيات الشبكات باستخدام SocketPermission و SocketPermissionAttribute ضمن ال System.Net وال System.Security.Permissions Namespaces وكمثال نستطيع منع Client Host Address معين من الاتصال مع ال Listener Application , ويتم ذلك بتعريف Attribute SocketPermission نحدد فيها نوع العملية وال Access Kind و عنوان ال Host الذي سيطبق عليه ال Permission ورقم ال Port ونوع ال Transport سواء موجه أو غير موجه TCP أو UDP. نريد في هذا المثال منع اتصال ال127.0.0.1 Address loopback بال Socket عبر جميع ال Ports وبغض النظر عن نوع ال Socket المستخدم. [CODE][SocketPermission(SecurityAction.Deny, Access="Connect", Host="127.0.0.1",Port="All", Transport="All")][/CODE] يمكننا ال object SecurityAction من تحديد نوع العملية التي نريدها وكما يلي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/permission.JPG[/IMG] Assert: وتعني السماح Client Host معين من إجراء عملية محددة Demand: وتعني تطبيق الصلاحيات على جميع ال Classes التي تقع في منطقة ال Stack أعلى ال Defined Abstract Deny: وتعني منع ال Client Host من إجراء عملية معينة. InheritanceDemand : وفيها تطبق الصلاحيات على ال Class الذي سيرث ال Class الحالي. PermitOnly: وفيه يمنع جميع ال Access عدا ال Client User المحدد. ... وفي الAccess property نحدد نوع عملية المنع أو السماح وتأخذ خيارين هما : Accept لمنع أو السماح ل Client Socket من عمل Binding مع ال IP Address و ال Port المحدد. Connect لمنع أو السماح ل Client Socket من عمل connect مع ال Remote Host المحدد. في ال Host وال Port نحدد عنوان ال Host الذي سيطبق عليه ال Permission و رقم ال Port التي يتصل بها ( في ال Port property نستطيع تمرير كلمة all لدلالة على تطبيق الصلاحية على جميع ال Ports ) وأخيرا نحدد ال Transport property والتي سنعرف فيها نوع ال Socket المستخدم وتأخذ الخيارات التالية: All بدون تحديد نوع ال Socket إذ تطبق هذه ال Permession على جميع ال Socket Types. Connectionless إذا كانت ال Socket تستخدم Datagram Protocols وكمثال بروتوكول UDP. ConnectionOriented إذا كانت ال Socket تستخدم Oriented Protocols وكمثال بروتوكول TCP. TCP إذ تستطيع تحديده مباشرة. UDP إذ تستطيع تحديده مباشرة. سيكون الدرس التالي حسب طلب الأعضاء 

 اسم العضو:الوفي دوما  الجمعة,26/محرم/1427 هـ,11:59 صباحاً
السلام عليكم أخي الفاضل : فادي ,,, لك جزيل الشكر و الإمتنان على هذه الدروس الراااائعه و على نفسك الطيبه و الكريمه المعطائه لي طلب ألا وهو : أتمنى أن يكون الدرس القادم عن كيفية إرسال الصوت من الClient إلى ال Server ؟؟؟ مثلاً في برنامج زي الماسنجر !! لك جزيل الشكر ,,, أطيب المُنى أخوك : الوفي دومـاً 

 اسم العضو:fmo_82  الجمعة,26/محرم/1427 هـ,03:26 مساءً
انشاء الله سيكون هذا هو الدرس التالي وقد احتاج بعض الوقت لتجهيزه لما فيه من تعقيد بعض الشيء لاكن انشاء الله سأحاول تيسيره قدر الإمكان , تستطيع الرجوع إلى المشاركة التالية مؤقتا إلى حين الإنتهاء من اعداد الدرس [URL=http://www.arabmoheet.net/forum/default.asp?codepage=3&topic_no=4072&page=3&#entry22079]http://www.arabmoheet.net/forum/default.asp?codepage=3&topic_no=4072&page=3&#entry22079[/URL] واهلا وسهلا بك 

 اسم العضو:fmo_82  الثلاثاء,21/فر/1427 هـ,04:56 مساءً
انتظروا الفصل الخاص بالـVoice Over IP Programming والذي سيتم إضافته غدا بمشيئة الله ... [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP.JPG[/IMG]  

 اسم العضو:محمد أكرم عليان  الثلاثاء,21/فر/1427 هـ,05:18 مساءً
 

 اسم العضو:fmo_82  الثلاثاء,21/فر/1427 هـ,10:18 مساءً
بسم الله الرحمن الرحيم, الفصل الحادي عشر : Voice Over IP Programming المقدمة: تتلخص الفكرة الأساسية من نقل الصوت عبر بروتوكول الإنترنت IP بتحويل الصوت إلى مجموعة من الـ Bits تجمع في Byte Array ثم كبسلته ليتم نقله ك Datagram Packets عبر الشبكة , وللاستقبال الصوت في الطرف الأخر يتم تجميع ال Packets مرة أخرى في مصفوفة Byte Array , وتتم عملية القراءة وفق مبدأ الـFIFO – First In First Out أي القادم أولا يعرض أولا ... تكمن المشكلة الأساسية بنقل الصوت في مدى توفر الشروط اللازمة حتى يتم إيصال وعرض الصوت بالشكل السليم و وفق الترتب الذي أرسل عليه , وتعتبر محدودبات ومشاكل بروتوكولات ال Transport Layer من أهم ما دعا Microsoft من العزوف عن دعم الـ Dot Net لعملية نقل الصوت وخاصة في بيئة النظام الحالي , ومن المعروف أن نظام التشغيل Windows XP يدعم الاتصال باستخدام بروتوكول TCP أو UDP فقط وهذا يعني انك إذا كنت تعمل تحت منصة نظام التشغيل Windows XP فإن أي عملية اتصال لن تكون إلا باستخدام واحد من هذه البروتوكولات ... أولا : The Requirements of Voice Communication Systems سوف نناقش في هذا الجزء متطلبات نقل الصوت عبر الشبكة ومشاكل نقل الصوت باستخدام بروتوكول الـ TCP و الـ UDP ... – متطلبات نقل الصوت المثلى : 1 - أسلوب النقل Stream 2 – البروتوكول المستخدم لنقل الصوت يجب أن يدعم Delivered on Sequence 3 – تعتمد سرعة النقل على مدى حجم الضغط المستخدم Voice Compression والجودة المطلوبة ويفضل في هذه الحالة أن لا تقل سرعة النقل عن 31 KB\S بمعدل لا يقل عن 8.000 KHz كحد أدنى لجودة الصوت. - السؤال الذي يطرح نفسه الآن , هل وفر بروتوكول الـ TCP والـ UDP هذه الأمور ؟ أولا بروتوكول ال TCP : يدعم بروتوكول ال TCP كل هذه الأمور وبكفاءة عالية لاكن المشكلة الوحيدة في هذا البروتوكول هو عدم إمكانية استخدامه لعمل Conference System Multicast إذ انه من المعروف أن ال Multicasting وال Broadcasting من الأمور الخاصة ببروتوكول ال UDP ولا يدعم ال TCP أي من هذه الأمور وهو ما بينته في الفصل السابق, إذ يعتر الـ TCP بروتوكول موجه Oriented Protocol لذلك لا يمكن الاعتماد عليه في حالة حاجتنا لعمل Multicast Conference System أو في حالة البث الإذاعي Broadcasting .. إذا الحل الأخر والوحيد هو بروتوكول الـ UDP في حالة حاجتنا لهذه الأمور. ثانيا بروتوكول ال UDP : لا يعتبر هذا البروتوكول حل جيد لعملية نقل الصوت بالكفاءة العالية إذ أنه لا يدعم عمليةDelivered on Sequence وهو ما سبب من استحالة عمل Fragmented للـ Packets المرسل ومن المعروف أن حجم Ethernet Encapsulation لا يزيد عن 1500 KB للـ Packet الواحد وهو الحجم الأقصى للـ Datagram Encapsulation الخاص بالـ Ethernet لذلك في حالة قمنا بعمل Fragmented لصوت فإننا لن نضمن وصول الصوت وفق الترتيب المرسل وهو ما يسبب مشكلة كبيرة في عملية إعادة ترتيب الـ Fragments المرسل ومن هذه النقطة قدمت الكثير من الشركات والمنظمات العالمية حلول خاصة لعملية نقل الصوت عبر ال UDP منها منظمة الـ ITU- International Telecommunications Union بتقديمها أسلوب النقل H.323 ومنظمة IETF Internet Engineering Task Force بتقديمها أسلوب النقل RTP – Real Time Transport Protocol , حيث أضاف هذا المعيار تحسينات على بروتوكول ال UDP لعملية نقل الصوت في الزمن الحقيقي إذ يستخدم أسلوب ال Stream المستخدم في TCP لاكن تحت منصة ال UDP وقد حل هذا المعيار بعض هذه المشاكل لاكن ليس جميعها , إذ أن الحاجة أصبحت ملحة لوجود بروتوكول يدعم عملية النقل وفق الترتيب الصحيح Delivered on Sequence بالإضافة إلى دعم الاتصال ك Stream ودعم لل IP Multicasting وال Broadcasting , وكان الحل بإنشاء بروتوكول أخر وهو الـSCTP – Stream Control Transmission Protocol لاكن المشكلة أن منصة Windows لا تدعم هذا البروتوكول وقد تم دعمه بشكل كامل في نظام التشغيل Linux , كما وعدت Microsoft بدعم هذا البروتوكول في الإصدار التالي من نظام التشغيل Windows والذي سآتي على شرحه في الجزء التالي من هذا الفصل. ثانيا : The Concept Of Voice Communication : تمر عملية التقاط الصوت بمجموعة من المراحل تبدأ بالتقاط الصوت من المايكروفون وتمثيل الذبذبات الصوتية ثم تحويلها إلى مجموعة من الـ Bits وذلك بعمل Sampling لذبذبات الصوتية الملتقطة وبعد هذه العملية يمكننا نقل الصوت عبر الشبكة وتمر عملية نقل الصوت عبر الشبكة بمجموعة من المراحل وهي : 1- في الـ Application Layer , طريقة التقاط الصوت وتحويله إلى Bits وهو ما ذكرته سابقا , و استخدام تقنيات لضغط الصوت Audio Compression Teachings وحتى يمكن إرساله عبر الإمكانيات المحدودة لشبكة الاتصال. 2- في الـ Transport Layer , وهو من أهم الأمور التي يجب أخذها بعين الاعتبار إذ أن المفاضلة بين اختيار بروتوكول الـ UDP أو الـTCP تعتمد على مدى الحاجة التي نريدها ودقة الصوت من جهة أخرى إذ أن أفضل طريقة لنقل الصوت هي استخدام تقنيات الـStream لاكن من المعروف أن بروتوكول الـUDP لا يدعم عملية النقل ك Stream كونه لا يدعم التوصيل وفق الترتيب Delivered on Sequence إذ أننا في هذه الحالة لن نتمكن من عمل الـ Fragmentation للـ Buffer حيث لن نضمن وصول الـ Fragments وفق الترتيب الذي أرسل عليه وسوف نضطر إلى التقيد بمحدوديات الـ Ethernet للـ Packet وهي 1500 KB للـ Packet الواحد ولحل هذه المشكلة سوف نلجأ إلى تبني بعض التقنيات الجديدة والتي تعتمد على بروتوكول الـ UDP وحتى يتم نقل الصوت ك Stream ومنها أسلوب النقل H.323 والذي ذكرته سابقا , لاكن لم تدعم الدوت نيت أي من هذه التقنيات , لذلك عندما نريد نقل صوت من جهاز إلى آخر ك Stream لابد لنا من استخدام بروتوكول الـ TCP لاكن كما ذكرنا سابقا فإنه لا يدعم الـ IP Multicasting و الـ Broadcasting 3- في الـ Network Layer يتم عنونة الـ Packets وإذا ما قررنا اعتماد الـ UDP فإننا سوف نتمكن من عمل البث الإذاعي Broadcasting ومجموعات البث Multicasting 4- في الـ Data Link Layer سيتم تحديد طبيعة ولإرسال سواء باستخدام الـ Ethernet أو غيره وفي هذه الحالة سيتم الاعتماد على الـ Ethernet لاكن مشكلته كما ذكرتها سابقا بمحدودية حجم الـ Frame إذ لا تتجاوز الـ 1500 KB 5- في الـ Physical Layer طبعا المشاكل التي قد تحدث إثناء عملية النقل كثيرة جدا وقد يحدث تأخير Delay لسبب أو لآخر أو قد تضيع بعض الـ Bits إثناء الإرسال لذلك لابد من وجود بروتوكولات تدعم التصحيح لكل هذه المشاكل والتي قد تحدث إثناء عملية الإرسال. يستقبل الطرف المقابل الـ Bits من طبقة الـ Physical Layer وتمر عبر الـ Data Link Layer ومن ثم الـ Network Layer وفي إثناء هذه المرحلة فإن مستقبل الـ Packets قد يكون هو الشخص المعني في حالة كان أسلوب البث Unicast أو قد يكون جزء من مجموعة الاستقبال Multicast أو قد يكون من ضمن الشبكة التي تم الإرسال لها ك Broadcast لذلك في حالة كونه جزء من مجموعة فإن جهة الإرسال غير معنية بالجهة التي سوف تستقبل الـ Packets وفي هذه الحالة فإنه غير معني سواء استقبلت جزء من الـ Packets أو كلها حيث لن يتم إرسال أي Acknowledgment إلى المرسل لذلك قد تحدث الكثير من المشاكل إثناء هذه المرحلة منها ضياع جزء من الـ Packets المرسل والذي سوف يسبب وصول الصوت بشكل متقطع , وطبعا سوف يكون الاعتماد في هذه الحالة على بروتوكولات الطبقة الأعلى وهي هنا Transport Layer فإذا كان المرسل والمستقبل يستخدم الـ TCP فإن كل هذه المشاكل سوف تحل لاكن المشكلة تكمن في كونه يستخدم الـ UDP حيث لا يوجد حل إلا بإتباع معيار مساند يضمن وصول كافة الـ Packets بترتيب الذي أرسل عليه وبدون ضياع أجزاء من الـ Packets المرسل. الشكل التالي يوضح عملية ضياع بعض الـ Packets إثناء الإرسال باستخدام شبكة Ethernet Wireless LAN و IP Multicasting UDP مما سوف يسبب تقطيع في الصوت: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP_img1.JPG[/IMG] ثالثا: How to Create a Voice Chat Throw Dot Net Using Unmanaged API’s Functions : كما قلنا سابقا فإن الدوت نيت لم تدعم أي من عمليات التقاط وعرض الصوت , لاكن لإجراء هذه العمليات لابد من استخدام مجموعة ملفات الـ DLL والتي تأتي مع نظام التشغيل ومنها ملف winmm.dll الشهير , والخاص بالتعامل مع وسائل الـ Multimedia في نظام التشغيل , حيث يدعم هذا الملف مجموعة من الـ Methods لالتقاط الصوت عبر المايكروفون وتخزينه في Byte Array Buffer ومن ثم عرضه مرة اخرى وهذه الـ Method هي : waveInGetNumDevs والتي تستخدم لتحديد عدد أجهزة الإدخال والمربوطة مع الـ Sound Card ولا تأخذ أي باروميترات. waveInAddBuffer وتستخدم لتخزين الـBits الواردة من جهاز الإدخال في Byte Array Buffer وتأخذ هذه الـMethod ثلاثة باروميترات وهي: [CODE]waveInAddBuffer(IntPtr hwi, ref WaveHdr pwh, int cbwh) [/CODE] حيث يمرر للأول جهاز الإدخال والذي تم اختياره و يحدد في الثاني Reference لموقع تخزين الـ Buffer وفي الثالث يحدد حجم الـ Buffer المستلم الـميثود waveInClose و waveInOpen لفتح وإغلاق الاتصال مع جهاز الإدخال. الميثود waveInPrepareHeader لتجهيز وحجز الـ Buffer وتأخذ نفس الباروميترات الموجودة في waveInAddBuffer. الميثود waveInUnprepareHeader ويتم استدعائها بعد تعبئة الـ Buffer حتى يتم إرسال الـ Buffer ومن ثم تفريغه للاستعداد لتعبئته مرة أخرى. الميثود waveInReset لإرجاع مؤشر الـPointer الخاص بالـ Buffer إلى صفر الميثود waveInStart و الميثود waveInStop بدأ وإغلاق عملية الإدخال من المايكروفون. ولاستخدام هذه الميثود في الدوت نيت نقوم بتعريفها أولا باستخدام DllImport وكما يلي: [CODE][DllImport(winmm.dll)] public static extern int waveInGetNumDevs(); [DllImport(winmm.dll)] public static extern int waveInAddBuffer(IntPtr hwi, ref WaveHdr pwh, int cbwh); [DllImport(winmm.dll)] public static extern int waveInClose(IntPtr hwi); [DllImport(winmm.dll)] public static extern int waveInOpen(out IntPtr phwi, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags); [DllImport(winmm.dll)] public static extern int waveInPrepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize); [DllImport(winmm.dll)] public static extern int waveInUnprepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize); [DllImport(winmm.dll)] public static extern int waveInReset(IntPtr hwi); [DllImport(winmm.dll)] public static extern int waveInStart(IntPtr hwi); [DllImport(winmm.dll)] public static extern int waveInStop(IntPtr hwi); [/CODE] وكما سوف نستخدم مجموعة الـMethods التالية لتحويل الـ Byte Array Buffer إلى صوت مرة أخرى وعرضه على جهاز الإخراج : [CODE] [DllImport(winmm.dll)] public static extern int waveOutGetNumDevs(); [DllImport(winmm.dll)] public static extern int waveOutPrepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize); [DllImport(winmm.dll)] public static extern int waveOutUnprepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize); [DllImport(winmm.dll)] public static extern int waveOutWrite(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize); [DllImport(winmm.dll)] public static extern int waveOutOpen(out IntPtr hWaveOut, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags); [DllImport(winmm.dll)] public static extern int waveOutReset(IntPtr hWaveOut); [DllImport(mmdll)] public static extern int waveOutClose(IntPtr hWaveOut); [DllImport(mmdll)] public static extern int waveOutPause(IntPtr hWaveOut); [DllImport(mmdll)] public static extern int waveOutRestart(IntPtr hWaveOut); [DllImport(mmdll)] public static extern int waveOutGetPosition(IntPtr hWaveOut, out int lpInfo, int uSize); [DllImport(mmdll)] public static extern int waveOutSetVolume(IntPtr hWaveOut, int dwVolume); [DllImport(mmdll)] public static extern int waveOutGetVolume(IntPtr hWaveOut, out int dwVolume); [/CODE] وحتى نتمكن من عرض محتويات الـ Buffer نستخدم التعريف التالي: [CODE] using System; using System.Runtime.InteropServices; using System.Resources; using System.IO; public class Winmm { public const UInt32 SND_ASYNC = 1; public const UInt32 SND_MEMORY = 4; [DllImport("Winmm.dll")] public static extern bool PlaySound(byte[] data, IntPtr hMod, UInt32 dwFlags); public Winmm() {} public static void PlayWavResource(byte[] buffer) { PlaySound(buffer, IntPtr.Zero, SND_ASYNC | SND_MEMORY); } }[/CODE] حيث نمرر للـ PlaySound Method الـ Byte Buffer والمستلم من Method الاستقبال الخاصة بالـ Socket وكما يلي: [CODE] void Voice_Receiver() { UdpClient sock = new UdpClient(5020); sock.JoinMulticastGroup(IPAddress.Parse(multicast_IP.Text)); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); byte[] voice_Come = sock.Receive(ref iep); Winmm.PlayWavResource(voice_Come); sock.Close(); }[/CODE] البدء بإنشاء برنامج المحادثة الصوتية Voice Chat System : سوف نجزئ عملية التقاط الصوت وتخزينه في الـ Buffer ثم عرضه مرة أخرى في مجموعة من الـClasses وهو تقسيم تم استخدامه في الكثير من البرمجيات الخاصة ب Microsoft ومنها برنامج Windows Sound Recorder وسوف نجمع هذه الـ Classes في ملف واحد نسميه Voice Library وسوف أرفق محتويات هذه الـ Classes في ملحقات هذا الفصل , وهذه الـ Classes هي: WaveIn Class وسوف نستخدمه لوضع كافة الـ Methods الخاصة بالتقاط الصوت وتخزينه في Byte Array WaveOut Clasas وسوف نستخدمه لعرض الصوت الأتي من الـ Buffer ثم عرضه WaveStream Class والذي سوف نستخدمه لتحويل الصوت إلى Stream حيث يسهل إرساله عبر الشبكة ويشبه عمله عمل MemoryStream المستخدمة في الدوت نيت الميثود FifoStream لتنظيم الـ Stream بحيث يتم عرض الداخل أولا خارج أولا الميثود WaveNative ويتم فيها وضع كافة التعريفات للـ Methods الخاصة بالملف winmm.dl والتي شرحناها سابقاّ. سوف نستخدم في هذا المثال بروتوكول الـ UDP لعملية النقل ومعتمدا على أسلوب البث Full Diplex Unicast Voice Chat System وللبدء سوف يكون الشكل العام لبرنامج الاتصال كما يلي : [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP_img2.JPG[/IMG] وسوف نقوم بكبسلة الـ Classes السابقة في ملف Voice.dll وسوف نضعه في الـ References الخاصة بالبرنامج وحتى نستطيع استخدام هذا الملف في جميع البرامج التي سوف تستخدم عملية الاتصال الصوتي بعد هذه العملية سنقوم الملف باستخدام الـ Using وكما يلي: [CODE] using System.Net; using System.Net.Sockets; using System.Threading; using Voice;[/CODE] ثم نقوم بتعريف الـSocket والـThread والذي سوف نستخدمه في البرنامج ويفضل وضع هذه التعريفات في بداية البرنامج أي بعد تعريف الـ Class الرئيسي والهدف من هذه العملية هي القدرة على إغلاق الـ Socket والـ Thread عند إطفاء البرنامج وحتى لا تبقى في الذاكرة عند إغلاق برنامج الاتصال , ويتم ذلك كما يلي: [CODE] public class Form1 : System.Windows.Forms.Form { private Socket socket; private Thread thread; [/CODE] وسوف نعرف Object من الـClasses السابقة ونعرف الـBuffer الذي سيتم تسجيل الصوت المراد إرساله والـBuffer الذي سيتم عرض الصوت المستلم من الـSocket [CODE] private WaveOutPlayer m_Player; private WaveInRecorder m_Recorder; private FifoStream m_Fifo = new FifoStream(); private byte[] m_PlayBuffer; private byte[] m_RecBuffer;[/CODE] في الـ Constructure الخاص بالبرنامج أو في الـ Form Load Event قم بكتابة التعريف الخاص بالـ Socket والـ Thread [CODE] public Form1() { InitializeComponent(); socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); thread = new Thread(new ThreadStart(Voice_In)); }[/CODE] سوف نضع في الـ Voice_In Methodالكود الخاص بعملية استقبال الصوت من الـSocket وكما يلي: [CODE] private void Voice_In() { byte[] br; socket.Bind(new IPEndPoint(IPAddress.Any, 5020)); while (true) { br = new byte[16384]; socket.Receive(br); m_Fifo.Write(br, 0, br.Length); } }[/CODE] حيث يتم استقبال الصوت من الشبكة باستخدام الـ Receive Method ثم نمرر الصوت المستقبل إلى الـ m_Fifo.Write Method وحتى يتم تنفيذه وتحويله إلى صوت مرة أخرى. أما الـMethod التي تقوم بتسجيل الصوت وإرساله إلى الجهاز الأخر فهي: [CODE] private void Voice_Out(IntPtr data, int size) { //for Recorder if (m_RecBuffer == null || m_RecBuffer.Length < size) m_RecBuffer = new byte[size]; System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size); //Microphone ==> data ==> m_RecBuffer ==> m_Fifo socket.SendTo(m_RecBuffer, new IPEndPoint(IPAddress.Parse(Peer_IP.Text),5030)); } [/CODE] لاحظ أنه في حالة إذا ما أردنا عمل برنامج Full Duplex بحيث يرسل ويستقبل في نفس الوقت فإننا بحاجة إلى تعريف Tow Ports واحد للإرسال وأخرى للاستقبال وفي الطرف الأخر تكون Port الإرسال لديك هي Port الاستقبال لديه والعكس صحيح ... في زر البدء يتم تنفيذ الميثود التالية: [CODE] private void Start() { Stop(); try { WaveFormat fmt = new WaveFormat(44100, 16, 2); m_Player = new WaveOutPlayer(-1, fmt, 16384, 3, new BufferFillEventHandler(Filler)); m_Recorder = new WaveInRecorder(-1, fmt, 16384, 3, new BufferDoneEventHandler(Voice_Out)); } catch { Stop(); throw; } }[/CODE] أما في زر الإيقاف فيتم تنفيذ الميثود التالية: [CODE] private void Stop() { if (m_Player != null) try { m_Player.Dispose(); } finally { m_Player = null; } if (m_Recorder != null) try { m_Recorder.Dispose(); } finally { m_Recorder = null; } m_Fifo.Flush(); // clear all pending data }[/CODE] الميثود التي تقوم بعرض الـ Voice Buffer والمستلم من Socket على السماعة: [CODE] private void Filler(IntPtr data, int size) { if (m_PlayBuffer == null || m_PlayBuffer.Length < size) m_PlayBuffer = new byte[size]; if (m_Fifo.Length >= size) m_Fifo.Read(m_PlayBuffer, 0, size); else for (int i = 0; i < m_PlayBuffer.Length; i++) m_PlayBuffer[i] = 0; System.Runtime.InteropServices.Marshal.Copy(m_PlayBuffer, 0, data, size); // m_Fifo ==> m_PlayBuffer==> data ==> Speakers }[/CODE] رابعا: Testing TCP,UDP and Thinking in SCTP to Transfer Voice Throw Networks : لإنشاء برنامج Multicast Half Duplex Voice Chat System نقوم بإضافة التعريفات التالية والخاصة بالـ Multicasting والتي شرحناها في الفصل السابق , وسوف نعتمد على وجود برنامجين واحد للمحاضر يتم من خلاله تسجيل الصوت وآخر لطالب حيث يستمع فيه لمحاضرة المعلم وكما في الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP_img3.JPG[/IMG] في برنامج الإرسال (برنامج المعلم) لا يختلف الكود بشيء فقط عند الإرسال يتم ذلك باستخدام الـ IP Multicasting وكما يلي: [CODE] private void Voice_Out(IntPtr data, int size) { //for Recorder if (m_RecBuffer == null || m_RecBuffer.Length < size) m_RecBuffer = new byte[size]; System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size); //Microphone ==> data ==> m_RecBuffer ==> m_Fifo socket.SendTo(m_RecBuffer, new IPEndPoint(IPAddress.Parse("224.0.1.7"), 5020)); } [/CODE] في الطرف المستقبل نقوم بالانضمام إلى الـIP Multicast Group ومن ثم الاستقبال من خلاله وكما يلي: [CODE] private void Voice_In() { UdpClient sock = new UdpClient(5000); sock.JoinMulticastGroup(IPAddress.Parse("224.0.1.7")); IPEndPoint iep = new IPEndPoint(IPAddress.Any,0); while (true) { m_Fifo.Write(sock.Receive(ref iep), 0,sock.Receive(ref iep).Length); } }[/CODE] الآن نفذ البرنامج ... لاحظ أن الصوت قد يتقطع أحيانا وبتأكيد السبب واضح وهو أنه في حالة استخدام بروتوكول الـ UDP والـ Multicasting فإن عملية الإرسال ستكون عشوائية وهذا قد يسبب ضياع واحد أو أكثر من الـPackets المرسلة عبر الشبكة كل فترة وبما أن بروتوكول الـ UDP لا يدعم أي من عمليات التحقق من الوصول وعمليات التوصيل على الترتيب فإن حدوث واحد أو أكثر من هذه المشاكل أمر محتمل ... دعنا الآن نجرب عملية الإرسال باستخدام بروتوكول TCP , لاحظ أن هذا البروتوكول هو بروتوكول موجه Oriented Protocol كما يدعم جميع عمليات التحقق من الوصول بالإضافة إلى كونه يدعم الاتصال بين الطرفين باستخدام أسلوب الـ Stream وهو ما يميز هذا البروتوكول عن غيره إذ أننا في حالة استخدامه لن نضطر إلى الأخذ بحجم البيانات المرسلة حيث يتم عمل Fragmentation لها بكل سهولة بالإضافة إلى سهولة تجميعها مرة أخرى وبدون الخوف من مشاكل الـ Delivered Out on Sequence ... كل ما علينا تغييره هو تعريف الـ Socket السابق وجعله كما يلي : [CODE] socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream , ProtocolType.Tcp);[/CODE] أما في عملية الإرسال فيمكننا استخدام الـNetwork Stream Class وكما يلي: [CODE] private void Voice_Out(IntPtr data, int size) { //for Recorder if (m_RecBuffer == null || m_RecBuffer.Length < size) m_RecBuffer = new byte[size]; System.Runtime.InteropServices.Marshal.Copy(data, m_RecBuffer, 0, size); //Microphone ==> data ==> m_RecBuffer ==> m_Fifo sock.Connect(new IPEndPoint(IPAddress.Parse("10.0.0.10"),5020)); NetworkStream ns = new NetworkStream (socket); ns.Write (m_RecBuffer,0,m_RecBuffer.Length); } [/CODE] في الطرف المستقبل نقوم باستخدام الـ Network Stream مرة أخرى لاكن للاستقبال: [CODE] private void Voice_In() { Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream , ProtocolType.Tcp); sock.Bind(new IPEndPoint(IPAddress.Parse("10.0.0.10"),5020)); NetworkStream ns = new NetworkStream (sock); while (true) { byte[] buffer = new byte [16384]; ns.Read (buffer,0,16384); m_Fifo.Write(buffer, 0, buffer.Length); } } [/CODE] لاحظ أن دقة الصوت أصبحت ممتازة كما أنه لا يوجد أي تقطيع في الصوت لاكن المشكلة تكمن في أننا لن نستطيع الاستفادة من هذه الإمكانيات الرائعة في الـMulticasting أو الـBroadcasting ... والحل الوحيد هو إما استخدام المعايير السابقة مع بروتوكول الـUDP أو استخدام بروتوكول الـTCP أو الانتظار لحين الانتهاء من مشروع Long Horn حتى تدعم Microsoft بروتوكول الـSCTP ... السؤال الذي يطرح نفسه الآن ما هو الجديد بهذا البروتوكول هل حل المشكلة؟؟ الجواب بكل بساطة نعم قد حل المشكلة حيث أن معمارية هذا البروتوكول الذي استفاد من ميزات الـTCP والدعم المقدم من قبل الـUDP لعمليات الـMulticasting إذ أصبح لدينا الآن منصة قوية يعتمد عليها في عمل الـFragmentation وإعادة ترتيبها بكل سهولة بالإضافة إلى دعمه عملية Delivered on Sequence وهذا واضح من بنية الـHeader الخاصة بهذا البروتوكول انظر إلى الشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP_img4.JPG[/IMG] خامسا: How to Create a Voice Conference System Using Microsoft Direct Play 9 : دعمت Microsoft تقنيات رائعة جدا للنقل الصوت في الإصدار الخاص بDirect Play9 ويسمى أيضا DirectPlay Transport Protocol وهو جزء من مجموعة الـDirectX وكان الهدف من إطلاقها وجود معيار موحد لمبرمجين الألعاب فيما يخص الـNetwork Games, وتعتمد هذه المكتبة على مجموعة من المعايير الخاصة بتشبيك حيث كان الهدف منها هو جعل عملية الاتصال ممكنة تحت جميع البيئات المختلفة و سواء كان البروتوكول المستخدم هو الـTCP/IP أو IPX الخاص بNovel فإن عملية الاتصال ممكنة وبدون أي اختلافات من النواحي البرمجية, ومن أهم ميزات الـ DirectPlay Transport Protocol: - Reliable delivery of messages حيث يدعم عملية التحقق التوصيل للجهة المعنية - Sequential a delivery of messages حيث يدعم التوصيل وفق الترتيب الصحيح - Send prioritization حيث يدعم عملية وضع أولويات للإرسال بناء على الأهمية - Streaming Session حيث تدعم عملية النقل كStream Data , قدمت Microsoft هذه الحلول كبدائل لدعم بروتوكول الـSCTP المنتظر , وقد حلت جميع المشكلات التي كانت تواجه المبرمجين لنقل الصوت عبر بروتوكول الـTCP أو الـUDP وحل محله أسلوب آخر لربط ضمن مستوى طبقة الـ Transport Layer , وتحتوي الـ Direct Play على مجموعة ضخمة من الـClasses ومن أهمها : أولا : الـ Connect Classes والخاصة بعملية الربط: الـ Address , Guid , Peer Classes حيث تستخدم عند إنشاء الاتصال مع الطرف الأخر , وتستخدم DirectPlay طريقة لتمييز البرنامج عن الأخر بتوليد Hash Code خاص بكل برنامج ويتم ذلك باستخدام الـ Guid Class ويتم تمرير الكود المولد وعنوان الجهاز المقابل إلى الـ Peer Class وهذه العملية شبيهة بشكل كبير لعملية الربط باستخدام الـ Socket في بروتوكول TCP/IP , ويتم استخدامها كما يلي كمثال: [CODE] using Microsoft.DirectX.DirectPlay; . . . Address hostAddress = new Address(); hostAddress.ServiceProvider = Address.ServiceProviderTcpIp; // Select TCP/IP service provider ApplicationDescription dpApp = new ApplicationDescription(); appGuid = Guid.NewGuid(); // Create a GUID for the application dpApp.GuidApplication = appGuid; // Set the application GUID dpApp.SessionName = "My Session"; // Optional Session Name myPeer.Host(dpApp, hostAddress); // Begin hosting[/CODE] طبعا يجب الاختيار طبيعة البروتوكول المستخدم سواء كان TCP/IP أو IPX وحتى نستطيع وضع العنوان المقابل أو الـ IP Address ويتم ذلك كما يلي: [CODE] using Microsoft.DirectX.DirectPlay; ServiceProviderInfo[] mySPInfo; Peer myPeer; System.Windows.Forms.ListBox listBox1; ApplicationDescription myAppDesc; . . myPeer = new Peer(); hostAddress = new Address(); peerAddress = new Address(); // Set the service provider to TCP/IP peerAddress.ServiceProvider = Address.ServiceProviderTcpIp; hostAddress.ServiceProvider = Address.ServiceProviderTcpIp; // Attach FindHostResponseEventHandler to receive FindHostResponseMessages myPeer.FindHostResponse += new FindHostResponseEventHandler(myEnumeratedHosts); // Call FindHosts to start the enumeration myPeer.FindHosts(myAppDesc, hostAddress, peerAddress, null, 10, 0, 0, FindHostsFlags.OkToQueryForAddressing);[/CODE] حيث تم تعريف نوع البروتوكول المستخدم وهو TCP/IP ويتم البحث عن الطرف الأخر في الشبكة باستخدام الـ FindHosts Method والموجودة ضمن الـPeer Class , وتتم عملية الربط مباشرة باستخدام الـ Connect Method والموجودة ضمن الـ Peer Class وكما يلي: [CODE] using Microsoft.DirectX.DirectPlay; // Structure for FindHostResponseMessages public struct HostInfo { public ApplicationDescription appdesc; public Address deviceAddress; public Address senderAddress; } . . . Peer myPeer = new Peer(); HostInfo hostinfo = new HostInfo(); // The FindHostResponseEventHandler public void myEnumeratedHosts(object o, FindHostResponseEventArgs args) { hostinfo.appdesc = args.Message.ApplicationDescription; hostinfo.deviceAddress = args.Message.AddressDevice; hostinfo.senderAddress = args.Message.AddressSender; } // Attach the ConnectCompleteEventHandler to receive ConnectCompleteMessages myPeer.ConnectComplete += new ConnectCompleteEventHandler(OnConnectComplete); // Call connect passing the Host information returned in the FindHostResponse event myPeer.Connect(hostinfo.appdesc, hostinfo.deviceAddress, hostinfo.senderAddress, null, ConnectFlags.OkToQueryForAddressing);[/CODE] ثانيا: Microsoft.DirectX.DirectPlay.Voice والخاصة بكل عمليات تسجيل ونقل وعرض الصوت: تمر عملية تسجيل ونقل وعرض الصوت بمجموعة من المراحل ونلخصها بالشكل التالي: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP_img5.JPG[/IMG] وسوف نقسمها إلى مجموعة من الـ Classes حسب الوظيفة لكل منها , 1- الـ Classes الخاصة بطرف الـ Server لإنشاء وإدارة الـ Sessions : Server Class ويستخدم كما يلي كمثال: [CODE] Server server = new Voice.Server(peerObject);[/CODE] حيث نسند له ال Peer Object والذي تم اشتقاقه من الـ Peer Class , ويحتوي الـ Server Object على الـ Methods الخاصة بعملية بدأ وإنهاء الجلسة بلإضافة إلى مجموعة من العمليات الأخرى: [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP_img6.JPG[/IMG] ولبدأ الجلسة يجب أولا إسناد خصائص الجلسة إلى الـStartSession Method حيث يتم تعريفها من خلال الـ SessionDescription و كما يلي: [CODE] //set up session description for the voice server Voice.SessionDescription sessionDesc = new Voice.SessionDescription(); sessionDesc.BufferAggressiveness = Voice.BufferAggressiveness.Default; sessionDesc.BufferQuality = Voice.BufferQuality.Default; sessionDesc.Flags = 0; sessionDesc.SessionType = type; sessionDesc.GuidCompressionType = compressionType; [/CODE] ولإنشاء Voice Session نقوم بإنشاء Method نمرر لها ال Peer Object والـ Voice Session Type ونوع الضغط المستخدم Compression Type ويتم ذلك كما يلي: [CODE] protected void CreateVoiceSession(Peer dpp, Voice.SessionType type, Guid compressionType) { try { //set up session description for the voice server Voice.SessionDescription sessionDesc = new Voice.SessionDescription(); sessionDesc.BufferAggressiveness = Voice.BufferAggressiveness.Default; sessionDesc.BufferQuality = Voice.BufferQuality.Default; sessionDesc.Flags = 0; sessionDesc.SessionType = type; sessionDesc.GuidCompressionType = compressionType; //start the session try { server.StartSession(sessionDesc); mIsHost = true; mInSession = true; } catch(DirectXException dxe) { throw dxe; } } catch(Exception e) { throw e; } }[/CODE] ويتم استدعائها كما يلي: [CODE] CreateVoiceSession(host, Voice.SessionType.Peer, mConfigForm.CompressionGuid);[/CODE] 2- الـ Classes الخاصة بطرف الـ Client للاتصال مع الـ Sessions التي أنشئها الـServer: الـ Client Class ومن أهم الـMethods الموجودة في الـ Client Class : [IMG]http://www.arabmoheet.net/forum/Members_Upload_Pics/6228/VOIP_img7.JPG[/IMG] الميثود Connect وتستخدم لربط مع الVoice Session حيث يرسل الـ Server رقم الSession للـ Client وعندها يتمكن الـ Client من الدخول إلى الجلسة , ويتم ذلك كما يلي: [CODE] protected void ConnectToVoiceSession(Peer dpp, Form wnd) { try { Voice.SoundDeviceConfig soundConfig = new Voice.SoundDeviceConfig(); //Set sound config to defaults soundConfig.GuidPlaybackDevice = DSoundHelper.DefaultVoicePlaybackDevice; soundConfig.GuidCaptureDevice = DSoundHelper.DefaultVoiceCaptureDevice; soundConfig.Window = wnd; //TODO: add error message for specific failures? //Connect to voice session client.Connect(soundConfig, mClientConfig, Voice.VoiceFlags.Sync); //set state mInSession = true; //set transmit targets to all players int[] xmitTargets = new int[1]; xmitTargets[0] = (int) PlayerID.AllPlayers; client.TransmitTargets = xmitTargets; //get sound device config to check for half-duplex soundConfig = client.SoundDeviceConfig; mHalfDuplex = ((soundConfig.Flags & Voice.SoundConfigFlags.HalfDuplex) != 0); } catch(Exception e) {throw e;} } }[/CODE] لاحظ أن المشاكل في البروتوكولين الـ TCP والـUDP قد تم حلها في الـ DirectPlay لاكن وكما هو معروف فإن الهدف من إنشاء الـ Direct Play لم يكن سوى لدعم برمجة الألعاب ومع المرونة الكبيرة التي تقدمها الـ Direct Play في عملية الاتصال الصوتي إلا أنها تفتقر لميزات الـ Voice Over IP والتي يقدمها بروتوكول الـ SCTP الخاص بالـ Linux... وهكذا بينا ملخص عن أهم الطرق لاتصال الصوتي عبر الشبكة وطرق برمجة الـ Voice Chat تحت منصة الدوت نيت واهم ميزات وعيوب بروتوكولات الـTransport Layer ومدى إمكانياتها لنقل الصوت عبر الشبكة وأخيرا شرح لأهم الـ Classes والمستخدمة في الاتصال الصوتي باستخدام الـ DirectPlay Transport Protocol. ------------------------------------------------------------------------------ مثال الـ Voice Chat System والـ DirectPlay Voice Chat System بلإضافة إلى الفصل على شكل ملف PDF File ---- كل ذلك بالمرفقات ------------------------------------------------------------------------------  

 اسم العضو:mr_csharp  الأربعاء,22/فر/1427 هـ,04:48 مساءً
شكرا جزيلا لك اخي فادي ... وبارك الله فيك انتا عملاق 

 اسم العضو:الوفي دوما  الأربعاء,22/فر/1427 هـ,04:52 مساءً
السلام عليكم جزيل الشكر لك أخي الكريم : فادي ... على إبداعك المتواصل لك أرق المُنى أيها النبيل في أمان الله 

 اسم العضو:fmo_82  الأربعاء,05/ربيع الثاني/1427 هـ,10:00 مساءً
بسم الله الرحمن الرحيم , سأقوم بتجزئة الموضوع إلى جزئين نظرا لكبره وسأنشر في البداية الجزء الأول وإذا وجدت التفاعل الجاد سأنشر الجزء الثاني بإذن الله [IMG]http://www.arabteam2000.com/picload/pics_10_05/03_05_06_04_31_32_1146699092Topics.GIF[/IMG] الجزء الأول: أولا- The Serialization Programming : The Serialization Classes & Members : يمكننا من خلال الـSerialization عمل Serializing لـ Object من جهاز إلى آخر سواء عبر الشبكة المحلية باستخدام الـ Stream Socket أو عبر الإنترنت باستخدام الـ Web Services والـRemotting , ويمكننا استخدام الـ Serialization في الدوت نيت من خلال الـ System.Runtime.Serialization Namespace حيث يحتوي هذا الـ Namespace على عدد ضخم من الـ Classes والتي تساعد في عمل Serialization لأي Object عبر الإنترنت أو الشبكة المحلية, ويبين الجدول التالي أهم هذه الـ Classes والتي يمكننا الاستفادة منها في بناء النظم الموزعة: Formatters , Formatter & FormatterServices : ويحتوي هذا الـ Class على كل الوظائف الرئيسية لعمل Serialization لأي Object ومنها يستخدم الـ Serialize Method لإرسال Serializing Object عبر الـ Stream والـ Deserialize والتي تستخدم للاستقبال الـ Serializing Object من الـStream و تحويله إلى Object مرة أخرى. وتأخذ عملية الإرسال نوعين هما الإرسال عبر بروتوكول الـ Soap ويأتي ضمن الـ Namespace System.Runtime.Serialization.Formatters.Soap حيث يجب إضافته إلى الـ Reference للمشروع وقد بينا في الفصل السابق كيفية عمل بروتوكول الـ SOAP حيث يحول الـ Object إلى XML Serial Stream , والطريقة الثانية هي بتحويل الـObject إلى Binary Serial Stream ويأتي ضمن الـNamespace : System.Runtime.Serialization.Formatters.Binary والذي سيتم شرحه بالتفصيل في الأمثلة القادمة في هذا الفصل. FormatterConverter : حيث يحتوي على الـ IFormatter Interface والـ IConvertible Interface لأستخدمهما في عمليات تمثيل الـ Object حتى يمكن إرساله عبر الـ Serializing Stream ... ObjectIDGenerator : ويستخدم لتوليد رقم ID عشوائي لأي Object حيث يحتوي هذا الـ Class على Tow Methods الأول يقوم بتوليد رقم تسلسلي للـ Object يسمى GetID والثاني يرجع قيمة الـ ID الخاص بالـ Object ويسمى HasId ويأخذ كل منهما اسم الـ Object الذي نريد توليد رقم تسلسلي له وقيمة True أو False لتحديد فيما إذا كانت هذه هي المرة الأولى التي تم فيها توليد رقم تسلسلي للـ Object أم لا... [CODE]GetId ( object_name,out bool) -->to Set an ID HasId( object_name,out bool) --> to Return the ID [/CODE] SerializationInfo : ويحتوي على كل المعلومات التي يمكن أن نحتاج لها لعملية الـ Serialize و الـ Deserialize لأي Object مثلا AssemblyName و الـ FullTypeName والـ MemberCount وتحويلات الـ Data Types للـ Objects وغيرها... لإنشاء أي Serializable Class يجب أولا أن يعرف بالـ [Serializable] Attribute حيث يعرف أن هذا الـ Class من الـ Classes التي يمكن أن يتم عمل Serializing عليها وكما يلي كمثال لعمل Serializable Class للـ Bank_Tier الخاص بالمثال السابق: [CODE]C#: [Serializable] public class Bank_Tier { public string Customer_Name; public string Address; public int zip_code; public string payment_method; public string ecard_number; public float depositor; public string acount_number; public Bank_Tier() { // Get_Session_ID(); } } VB.NET: <Serializable()> _ Public Class Bank_Tier Public Customer_Name As String Public Address As String Public zip_code As Integer Public payment_method As String Public ecard_number As String Public depositor As Single Public acount_number As String Public Sub New() ' Get_Session_ID() End Sub End Class[/CODE] ولإنشاء البرنامج الخاص بعملية الإرسال لابد من تحديد طريقة الإرسال سواء كـBinary Stream Data أو XML Data ففي الأول سنستخدم الـ BinaryFormatter والموجود ضمن الـ System.Runtime.Serialization.Formatters.Binary Namespace أما الثاني فسيستخدم مع الـ SOAP Protocol والمعرف ضمن الـ SOAPFormatter Class والموجود ضمن الـ System.Runtime.Serialization.Formatters.Soap Namespace. ولعمل Serialization للـ Class السابق باستخدام الـ SOAP Formatter لابد أولا من تعريف الـ Namespaces التالية: [CODE]System.Runtime.Serialization System.Runtime.Serialization.Formatters.Soap[/CODE] ثم نقوم بعمل Instance من الـ Bank Web Services حيث نستطيع فيما بعد إسناد المعلومات الآتية من الـ Presentation Tier إليه ثم إرسالها إلى الـ Bank Server باستخدام الـ Remotting أو الـNetworkStream أو حفظها على الجهاز كـ Binary Data أو XML File وكما يلي كمثال: لتخزين المخرجات بـ XML File باستخدام بروتوكول الـ SOAP : [CODE]C#: Bank_Tier bt = new Bank_Tier(); bt.acount_number = acount_number; bt.Address = Address; bt.depositor=depositor; bt.ecard_number = ecard_number; bt.payment_method = payment_method; bt.zip_code = zip_code; Stream str = new FileStream("bank_result.xml", FileMode.Create, FileAccess.ReadWrite); IFormatter formatter = new SoapFormatter(); formatter.Serialize(str, bt); str.Close(); VB.NET: Dim bt As Bank_Tier = New Bank_Tier bt.acount_number = acount_number bt.Address = Address bt.depositor=depositor bt.ecard_number = ecard_number bt.payment_method = payment_method bt.zip_code = zip_code Dim str As Stream = New FileStream("bank_result.xml", FileMode.Create, FileAccess.ReadWrite) Dim formatter As IFormatter = New SoapFormatter formatter.Serialize(str, bt) str.Close()[/CODE] وسكون الـ Output ملف XML يحتوي على البيانات التي تم إدخالها وكما يلي: [CODE]- <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> - <SOAP-ENV:Body> - <a1:Form1_x002B_Bank_Tier id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Serialization/Serialization%2C%20Version%3D1.0.2309.39316%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> <Customer_Name xsi:null="1" /> <Address id="ref-3">Amman Jordan</Address> <zip_code>962</zip_code> <payment_method id="ref-4">Master Card</payment_method> <ecard_number id="ref-5">66-6655-444433-55655</ecard_number> <depositor>600</depositor> <acount_number id="ref-6">3399948845</acount_number> </a1:Form1_x002B_Bank_Tier> </SOAP-ENV:Body> </SOAP-ENV:Envelope>[/CODE] وبتأكيد نستطيع استخدام هذا المثال لإرسال البيانات عبر الـ Network Stream أو باستخدام الـ Remotting , كما يمكننا الاستفادة من الـ Serialization لتمثيل أي Object على شكل XML أو Binary Data لاستخدامها في أمور أخرى... سنبين في المثال التالي كيفية الاستفادة من الـ BinaryFormatter Class لإرسال Object أو Binary Data من جهاز إلى آخر عبر الشبكة كما سنبين كيفية الاستفادة من الـ SOAP Protocol لإرسال Binary Data كـ XML Stream: وكمثال نريد إرسال صورة من جهاز إلى آخر بعد تحويلها إلى Binary Stream باستخدام الـ MemoryStream وكما يلي: أولا : باستخدام الـ BinaryFormatter في برنامج الإرسال: [CODE] C#: using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization; . . private void Send_Image_Using_BinaryFormatter { MemoryStream ms = new MemoryStream (); pictureBox1.Image.Save (ms,System.Drawing.Imaging.ImageFormat.Jpeg); object op = (object) ms; BinaryFormatter br = new BinaryFormatter (); TcpClient myclient = new TcpClient ("localhost",5000); NetworkStream myns = myclient.GetStream (); br.Serialize (myns,op); myns.Close (); myclient.Close (); } VB.NET Imports System.Runtime.Serialization.Formatters.Binary Imports System.Runtime.Serialization . . Private Property Send_Image_Using_BinaryFormatter() As void Dim ms As MemoryStream = New MemoryStream () pictureBox1.Image.Save (ms,System.Drawing.Imaging.ImageFormat.Jpeg) Dim op As Object = CObj(ms) Dim br As BinaryFormatter = New BinaryFormatter Dim myclient As TcpClient = New TcpClient("localhost", 5000) Dim myns As NetworkStream = myclient.GetStream() br.Serialize (myns,op) myns.Close () myclient.Close () End Property[/CODE] استخدام الـ BinaryFormatter في برنامج الاستقبال: ولاستخدام بروتوكول الـ BinarFormatter في برنامج الاستقبال سنستخدم الميثود المعاكسة للـ Serialize وهي Deserialize ثم نقوم بعمل Casting للـ Object المستقبل ونحوله إلى MemoryStream Object مرة أخرى , عندها نستطيع عرضه على الـ Picture box باستخدام الـ FromStream Method والموجودة ضمن الـ Image Class : [CODE]C#: void Image_Receiver() { NetworkStream myns; TcpListener mytcpl; Socket mysocket; Thread myth; mytcpl = new TcpListener (5000); mytcpl.Start (); mysocket = mytcpl.AcceptSocket (); myns = new NetworkStream (mysocket); BinaryFormatter br = new BinaryFormatter (); object op; op= br.Deserialize (myns); // Deserialize the Object from Stream MemoryStream mm = (MemoryStream) op; // Casting The Object to MemoryStream Object pictureBox1.Image = Image.FromStream(mm); mytcpl.Stop(); if (mysocket.Connected ==true) {while (true){Image_Receiver();}} } . . private void server_Load(object sender, System.EventArgs e) { Thread myth; myth= new Thread (new System.Threading .ThreadStart(Image_Receiver)); myth.Start (); } VB.NET Imports System.Runtime.Serialization.Formatters.Binary Imports System.Runtime.Serialization . . Private Sub Image_Receiver() Dim myns As NetworkStream Dim mytcpl As TcpListener Dim mysocket As Socket Dim myth As Thread mytcpl = New TcpListener(5000) mytcpl.Start() mysocket = mytcpl.AcceptSocket() myns = New NetworkStream(mysocket) Dim br As BinaryFormatter = New BinaryFormatter Dim op As Object op = br.Deserialize(myns) ' Deserialize the Object from Stream Dim mm As MemoryStream = CType(op, MemoryStream) ' Casting The Object to MemoryStream Object pictureBox1.Image = Image.FromStream(mm) mytcpl.Stop() If mysocket.Connected = True Then Do While True Image_Receiver() Loop End If End Sub . . Private Sub server_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim myth As Thread myth = New Thread(New System.Threading.ThreadStart(AddressOf Image_Receiver)) myth.Start() End Sub[/CODE] ثانيا : استخدام الـ SOAP في برنامج الإرسال: حيث سترسل الصورة كـ XML Data ثم تحول في الطرف المقابل إلى صورة مرة أخرى وكل ذلك يتم باستخدام بروتوكول الـ SOAP وكما يلي في برنامج الإرسال: [CODE]C#: using System.Runtime.Serialization.Formatters.Soap; using System.Runtime.Serialization; . . private void Send_Image_Using_ SoapFormatter { server fr = new server (); fr.Show(); MemoryStream ms = new MemoryStream (); pictureBox1.Image.Save (ms,System.Drawing.Imaging.ImageFormat.Jpeg); object op = (object) ms; TcpClient myclient = new TcpClient ("localhost",5000); NetworkStream myns = myclient.GetStream (); IFormatter formatter = new SoapFormatter(); formatter.Serialize(myns, op); myns.Close(); } VB.NET: Imports System.Runtime.Serialization.Formatters.Soap Imports System.Runtime.Serialization . . Private void Property SoapFormatter() As Send_Image_Using_ Dim fr As server = New server fr.Show() Dim ms As MemoryStream = New MemoryStream pictureBox1.Image.Save (ms,System.Drawing.Imaging.ImageFormat.Jpeg) Dim op As Object = CObj(ms) Dim myclient As TcpClient = New TcpClient("localhost", 5000) Dim myns As NetworkStream = myclient.GetStream() Dim formatter As IFormatter = New SoapFormatter formatter.Serialize(myns, op) myns.Close() End Property[/CODE]استخدام الـ SoapFormatter في برنامج الاستقبال: ولاستخدام بروتوكول الـ SOAP في برنامج الاستقبال سنستخدم الميثود المعاكسة للـ Serialize وهي Deserialize ثم نقوم بعمل Casting للـ Object المستقبل ونحوله إلى MemoryStream Object مرة أخرى , عندها نستطيع عرضه على الـ Picture box باستخدام الـ FromStream Method والموجودة ضمن الـ Image Class : [CODE]C#: using System.Runtime.Serialization.Formatters.Soap; using System.Runtime.Serialization; . . void Image_Receiver() { NetworkStream myns; TcpListener mytcpl; Socket mysocket; mytcpl = new TcpListener (5000); mytcpl.Start (); mysocket = mytcpl.AcceptSocket (); myns = new NetworkStream (mysocket); object op; IFormatter formatter = new SoapFormatter(); op= formatter.Deserialize(myns); myns.Close(); MemoryStream mm = (MemoryStream) op; pictureBox1.Image = Image.FromStream(mm); mytcpl.Stop(); if (mysocket.Connected ==true) { while (true) {Image_Receiver();} } } . . private void server_Load(object sender, System.EventArgs e) { Thread myth; myth= new Thread (new System.Threading .ThreadStart(Image_Receiver)); // Start Thread Session myth.Start (); } VB.NET: Imports System.Runtime.Serialization.Formatters.Soap Imports System.Runtime.Serialization . . Private Sub Image_Receiver() Dim myns As NetworkStream Dim mytcpl As TcpListener Dim mysocket As Socket mytcpl = New TcpListener(5000) mytcpl.Start() mysocket = mytcpl.AcceptSocket() myns = New NetworkStream(mysocket) Dim op As Object Dim formatter As IFormatter = New SoapFormatter op = formatter.Deserialize(myns) myns.Close() Dim mm As MemoryStream = CType(op, MemoryStream) pictureBox1.Image = Image.FromStream(mm) mytcpl.Stop() If mysocket.Connected = True Then Do While True Image_Receiver() Loop End If End Sub . . Private Sub server_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim myth As Thread myth = New Thread(New System.Threading.ThreadStart(AddressOf Image_Receiver)) ' Start Thread Session myth.Start() End Sub[/CODE] وهكذا بينا كيفية استخدام الـ Serialization في بيئة الدوت نيت بنوعيها الـ Binary والـXML Data , سيتم الحديث في الجزء التالي من هذا الفصل عن الـ Remotting واستخدامها في برمجيات الشبكات والنظم الموزعة , وسنقوم بتطبيق إنشاء نظام eLearning Distributed System ...  

 اسم العضو:fmo_82  الخميس,06/ربيع الثاني/1427 هـ,03:48 مساءً
ثانيا: Remotting Programming : يعتبر موضوع الـ Remotting من المواضيع الهامة جدا في برمجة الشبكات , إذ يقدم لنا إمكانيات رائعة في مشاركة و استخدام الـ Remote Methods والموجودة على الـ Remote Server وتشبه عملية التعامل مع الـ Remotting عملية الـ Web Services إلى حد كبير حيث يتطلب استخدامها عمل Proxy Object في طرف الـClient, لكن مع إمكانيات اكبر حيث تقوم بإنشاء الـServer بنفسك ولست مضطرا لتثبيت الـ IIS أو غيره من التطبيقات الوسيطة للاستفادة من خدمات الـ Remote Server , وتستطيع من خلاله تنفيذ أي عملية معالجة على الـ Server مما يعزز من مبدأ الـ Distributed Systems والذي شرحناه في الجزء الأول من هذا الفصل حيث تبقى الـ methods و عملية المعالجة الخاصة بها على الـ Server في حين يتم إرسال الـ Result إلى الـ Clients كـ XML Data أو Binary Data حسب قناة الاتصال المستخدمة سواء HttpChannel أو TcpChannel , وتمرر إلى الـ Client عبر الـ Proxy Object والذي ربط الـ Remote Class الموجود على الـ Server مع الـ Client لاحظ الشكل التالي: [IMG]http://www.arabteam2000.com/picload/pics_10_05/04_05_06_10_17_29_1146763049dotnet_remoting.gif[/IMG] 1- Using Remotting in Dot Net : يمكن استخدام الـ Remotting بطريقتين الأولى عبر بروتوكول الـ HTTP حيث تتم عملية التراسل كـ XML Data بين الـ Server والـ Clients وتتم باستخدام بروتوكول الـ SOAP أما الطريقة الثانية فتتم باستخدام الـ TCP Protocol حيث تكون عملية التراسل كـ Binary Data بين الـ Server وبقية الـ Clients , ويفضل دائما استخدام الـ TCP Channel في الحالتين التاليتين: الأولى: إذا كانت قناة الاتصال سريعة نسبيا الثانية: توافقية البيئات حيث تستخدم نظام التشغيل Microsoft Windows في جميع الـ clients , ويعتبر هذه الأمر من أهم عيوب استخدام الـ TCP Channel وخاصة في حالة الـWeb حيث لا تضمن البيئة التي سيعمل عليها الـ Client ويفضل في هذه الحالة استخدام الـ HTTP Channel , لكن تبقى أدائية الـ TCP Channel أفضل من الـ HTTP ... وما يميز الـ HTTP Channel هو استخدامه بروتوكول الـ SOAP والذي يتعامل مع الـXML في عملية التراسل مما يضمن توافقيته مع جميع البيئات. يلزم استخدام الـ Remotting في الدوت نيت ثلاثة أمور : أولا, تحديد طبيعة القناة المستخدمة سواء عبر الـ HTTP كـXML أو عبر الـ TCP كـBinary Formatter ودعمت الدوت نيت كلا منهما في الـClass HttpChannel والموجود ضمن System.Runtime.Remoting.Channels.Http Namespace والـTcpChannel Class والموجود ضمن الـ System.Runtime.Remoting.Channels.Tcp Namespace (يجب إضافته إلى الـ References في المشروع), حيث يجب تعريفها في كلا الطرفين الـ Client والـ Server وكما يلي: [CODE]C#: HttpChannel http_Channel = new HttpChannel(Port_Number); VB.NET: Dim http_Channel As HttpChannel = New HttpChannel(Port_Number)[/CODE] وفي حالة استخدام الـ TcpChannel كما يلي: [CODE] C#: TcpChannel Tcp_Channel = new TcpChannel(Port_Number); VB.NET: Dim Tcp_Channel As TcpChannel = New TcpChannel(Port_Number)[/CODE] بعد ذلك يجب تسجيل القناة المستخدمة باستخدام الميثود RegisterChannel والموجودة ضمن الـ ChannelServices Class ضمن الـSystem.Runtime.Remoting.Channels Namespace , ويتم ذلك في كلا الطرفين أيضا الـ Client والـ Server وكما يلي: [CODE] C#: ChannelServices.RegisterChannel(chan); VB.NET: ChannelServices.RegisterChannel(chan)[/CODE] بعد ذلك يجب تعريف الـ Class الذي سيتم مشاركته على الـ Server ويتم ذلك باستخدام الميثود RegisterWellKnownServiceType والموجودة ضمن الـ RemotingConfiguration Class والموجود ضمن الـ System.Runtime.Remoting Namespace ويتم ذلك كما يلي في طرف الـ Server: [CODE]C#: RemotingConfiguration.RegisterWellKnownServiceType (Type.GetType ("Class_File_Name, Distributed_Class_Name"), "unique_Service_Name", WellKnownObjectMode.SingleCall); VB.NET: RemotingConfiguration.RegisterWellKnownServiceType (Type.GetType ("Class_File_Name, Distributed_Class_Name"), "unique_Service_Name", WellKnownObjectMode.SingleCall)[/CODE] وتأخذ الـ RegisterWellKnownServiceType Method ثلاثة باروميترات الأول الـType الخاص باسم الـ Remote Class مع اسم الـ Dll File ومساره والذي نريد توزيعه ويأخذ الباروميتر الثاني اسم الـ URI الخاص بالـ Object الذي نريد توزيعه ويجب أن يكون الـ URI Object اسم فريد unique على مستوى الـ Application Port , ويأخذ الباروميتر الثالث نوع الـ Remote Instance Object فإذا تم اختيار SingleCall فهذا يعني إنشاء New Instance جديد لكل Client يقوم بإنشاء Instance من الـ Remote Class , وإذا تم اختيار Singleton فهذا يعني استخدام نفس الـ Remote Instance Object لكل الـ Clients , وينصح استخدام SingleCall في حالة كان النظام الموزع سيستخدم Session لكل User وينصح باستخدام Singleton في حالة كان الـ Server سيبث نفس المعلومات إلى كل الـ Clients على الشبكة... أما في الـ Client فيجب تعريف نوع الـ Channel سواء TCP أو HTTP Channel حسب نوع القناة التي تم استخدمها في الـ Server ولا يتم وضع رقم الـ Port في الـ Client Channel ونكتفي بوضعه في الـ URI Object ويتم تعريف القناة في الـ Client كما يلي: [CODE]C#: HttpChannel http_Channel = new HttpChannel VB.NET: Dim http_Channel As HttpChannel = New HttpChannel()[/CODE] وفي حالة استخدام الـ TcpChannel كما يلي: [CODE] C#: TcpChannel Tcp_Channel = new TcpChannel(); VB.NET: Dim Tcp_Channel As TcpChannel = New TcpChannel()[/CODE] ويتم تسجيل القناةRegisterChannel في الـ Client كما هو الحال في الـ Server وكما يلي: [CODE] C#: ChannelServices.RegisterChannel(chan); VB.NET: ChannelServices.RegisterChannel(chan)[/CODE] بعد ذلك نقوم بتعريف New Instance Object من الـ Remote Client حيث يجب أن يحتوي الـ Client Project على الـ Dll File الخاص بالـ Distributed Class حيث نقوم في البداية بتعريف الـ URI والذي سيحتوي على الـ Protocol المستخدم ويتبع بعنوان الجهاز أو الـ DNS الخاص بالـ Server ومن ثم رقم الـ Port المستخدم و اسم الخدمة التي تم تعريفها في الـ Server ويتم ذلك كما يلي: في حالة استخدام TCP Channel : [CODE] C#: string URI = "Tcp://"+Remote_IP.Text+":Port/ unique_Service_Name "; VB.NET: Dim URI As String = "Tcp://" & Remote_IP.Text & ": Port/ unique_Service_Name "[/CODE] في حالة استخدام HTTP Channel : [CODE] C#: string URI = "Http://"+Remote_IP.Text+": Port / unique_Service_Name"; VB.NET: Dim URI As String = " Http://" & Remote_IP.Text & ": Port / unique_Service_Name "[/CODE] وبعد ذلك نقوم بإنشاء New Instance Object من الـ Remote Class ويتم ذلك باستخدام الـ GetObject Method والموجود ضمن الـ Activator Class ونمرر لها الـ Distributed Class Type و الـ URI الذي عرفناه , وكما يلي: [CODE] C#: Distributed_Class_Name obj = (Distributed_Class_Name) Activator.GetObject (typeof (Distributed_Class_Name), URI); VB.NET: Dim obj As Distributed_Class_Name = CType(Activator.GetObject(GetType(Distributed_Class_Name), URI), Distributed_Class_Name)[/CODE] ملاحظة هامة جدا: يجب أن يتم توريث الـ MarshalByRefObject Class إلى الـ Distributed Class الذي نريد توزيعه والموجود ضمن System Namespace وعند توريث الـ MarshalByRefObject إلى الـ Distributed Class سيتم تنفيذ كافة العمليات أو الـ Process على الـ Server وسيحصل الـ Client على الـ Result النهائي في حين إذا تم استخدام الـMarshalByValueObject عندها سيتم استخدام الـ Remote Class و لكن ستتم عملية المعالجة على الـ Client Side ... وهكذا بينا كيفية استخدام الـ Remotting في الدوت نيت , سنقوم الآن بتطبيق هذه المفاهيم في مشروع حيث سنقوم بإنشاء Distributed Class يقوم بعملية التقاط لصورة سطح المكتب الخاص بالـ Server وبثها إلى الـ Client مستخدما الـ TcpChannel بين الـ Server والـ Client وسنفترض في هذا المثال إنشاء Remote Classroom حيث يقوم المعلم بإلقاء محاضرة إلى طلابه ويتم بث صورة الكاميرا وسطح المكتب الخاص بالمعلم عبر الإنترنت إلى الطلاب في الـ Classroom والموجودين في دول متعددة وكما في الشكل التالي: [IMG]http://www.arabteam2000.com/picload/pics_10_05/04_05_06_10_18_44_1146763124Remotting_Classrooms.JPG[/IMG] سنستخدم في هذا المثال الـ TCP Channel والـ HttpChannel وسنقارن الأداء في كل منهما ,برنامج المحاضر (Lecturer Project) وسيكون الشكل العام له كما هو مبين في الشكل التالي حيث: [IMG]http://www.arabteam2000.com/picload/pics_10_05/04_05_06_10_19_28_1146763168Remotting_Server.JPG[/IMG] برنامج الـ Client ويمكن أن يكون من خلال الإنترنت في حالة كان لديك Real IP أو في الشبكة المحلية وكما هو مبين في الشكل التالي: [IMG]http://www.arabteam2000.com/picload/pics_10_05/04_05_06_10_21_24_1146763284Remotting_Client.JPG[/IMG] ولإنشاء الـ Remote Class والذي سيقوم بجلب صورة سطح المكتب , سنستخدم دوال الـ API ومنها الـ GetDesktopWindow Method والموجودة ضمن الـuser32.dl والـ BitBlt Method لرسم الصورة , ثم سنقوم بتحويل الصورة إلى Byte Array وحتى نستطيع إرسالها إلى الـ Clients , وبتأكيد سنستخدم طريقة MarshalByRefObject وحتى تتم عملية التقاط ومعالجة الصورة على الـ Server Side , ويتم ذلك كما يلي : [CODE]C#: using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.IO; public class ScreenCapture : System.MarshalByRefObject { [DllImport("user32.dll")] private static extern IntPtr GetDesktopWindow(); [DllImport("gdi32.dll")] private static extern bool BitBlt( IntPtr hdcDest, // handle to destination DC int nXDest, // x-coord of destination upper-left corner int nYDest, // y-coord of destination upper-left corner int nWidth, // width of destination rectangle int nHeight, // height of destination rectangle IntPtr hdcSrc, // handle to source DC int nXSrc, // x-coordinate of source upper-left corner int nYSrc, // y-coordinate of source upper-left corner System.Int32 dwRop // raster operation code ); private const Int32 SRCCOPY = 0xCC0020; [DllImport("user32.dll")] private static extern int GetSystemMetrics(int nIndex); private const int SM_CXSCREEN = 0; private const int SM_CYSCREEN = 1; public Size GetDesktopBitmapSize() { return new Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); } public byte[] GetDesktopBitmapBytes() { Size DesktopBitmapSize = GetDesktopBitmapSize(); Graphics Graphic = Graphics.FromHwnd(GetDesktopWindow()); Bitmap MemImage = new Bitmap(DesktopBitmapSize.Width, DesktopBitmapSize.Height, Graphic); Graphics MemGraphic = Graphics.FromImage(MemImage); IntPtr dc1 = Graphic.GetHdc(); IntPtr dc2 = MemGraphic.GetHdc(); BitBlt(dc2, 0, 0, DesktopBitmapSize.Width, DesktopBitmapSize.Height, dc1, 0, 0, SRCCOPY); Graphic.ReleaseHdc(dc1); MemGraphic.ReleaseHdc(dc2); Graphic.Dispose(); MemGraphic.Dispose(); Graphics g = System.Drawing.Graphics.FromImage(MemImage); System.Windows.Forms.Cursor cur = System.Windows.Forms.Cursors.Arrow; cur.Draw(g,new Rectangle(System.Windows.Forms.Cursor.Position.X-10,System.Windows.Forms.Cursor.Position.Y-10,cur.Size.Width,cur.Size.Height)); MemoryStream ms = new MemoryStream(); MemImage.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg); return ms.GetBuffer(); } } VB.NET Imports System Imports System.Drawing Imports System.Drawing.Imaging Imports System.Runtime.InteropServices Imports System.IO Public Class ScreenCapture : Inherits System.MarshalByRefObject <DllImport("user32.dll")> _ Private Shared Function GetDesktopWindow() As IntPtr End Function <DllImport("gdi32.dll")> _ Private Shared Function BitBlt(ByVal hdcDest As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As System.Int32) As Boolean End Function Private Const SRCCOPY As Int32 = &HCC0020 <DllImport("user32.dll")> _ Private Shared Function GetSystemMetrics(ByVal nIndex As Integer) As Integer End Function Private Const SM_CXSCREEN As Integer = 0 Private Const SM_CYSCREEN As Integer = 1 Public Function GetDesktopBitmapSize() As Size Return New Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)) End Function Public Function GetDesktopBitmapBytes() As Byte() Dim DesktopBitmapSize As Size = GetDesktopBitmapSize() Dim Graphic As Graphics = Graphics.FromHwnd(GetDesktopWindow()) Dim MemImage As Bitmap = New Bitmap(DesktopBitmapSize.Width, DesktopBitmapSize.Height, Graphic) Dim MemGraphic As Graphics = Graphics.FromImage(MemImage) Dim dc1 As IntPtr = Graphic.GetHdc() Dim dc2 As IntPtr = MemGraphic.GetHdc() BitBlt(dc2, 0, 0, DesktopBitmapSize.Width, DesktopBitmapSize.Height, dc1, 0, 0, SRCCOPY) Graphic.ReleaseHdc(dc1) MemGraphic.ReleaseHdc(dc2) Graphic.Dispose() MemGraphic.Dispose() Dim g As Graphics = System.Drawing.Graphics.FromImage(MemImage) Dim cur As System.Windows.Forms.Cursor = System.Windows.Forms.Cursors.Arrow cur.Draw(g, New Rectangle(System.Windows.Forms.Cursor.Position.X - 10, System.Windows.Forms.Cursor.Position.Y - 10, cur.Size.Width, cur.Size.Height)) Dim ms As MemoryStream = New MemoryStream MemImage.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Return ms.GetBuffer() End Function End Class[/CODE] وبتأكيد يجب تحويل الـ Class السابق إلى Dll File ثم وضعه بجانب الملف التنفيذي للمشروع , وأيضا إضافته ضمن الـ References في مشروع الـ Client وحتى نستطيع عمل الـ Casting على الـ Object القادم من الـ Sever ... أولا : إنشاء الـ Remotting Server : سيحتوي برنامج الـ Server على الأمور التالية: [IMG]http://www.arabteam2000.com/picload/pics_10_05/04_05_06_10_22_30_1146763350Server_Table.JPG[/IMG] سنقوم الآن بإنشاء وتسجيل TCP Remote Channel ثم إنشاء الـ Server Object ويتم ذلك كما يلي: [CODE]C#: TcpChannel chan = new TcpChannel(6600); ChannelServices.RegisterChannel(chan); RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("ScreenCapture, ScreenCapture"), "MyCaptureScreenServer",WellKnownObjectMode.Singleton); VB.NET Dim chan As TcpChannel = New TcpChannel(6600) ChannelServices.RegisterChannel(chan) RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("ScreenCapture, ScreenCapture"), "MyCaptureScreenServer",WellKnownObjectMode.Singleton)[/CODE] قمنا بتسمية الـ Server Object بـ MyCaptureScreenServer و طبيعة الـ Instance سيكون Singleton وهذا يعني استخدام نفس الـ Instance Object لكل الـ Clients و في حالة إذا أردنا إنشاء New Instance Object لكل Client Request فيجب استخدام الـ SingleCall وفي حالتنا هذه ينصح باستخدام الأول وحتى لا يزيد الـ Load على الـServer في حالة ربطه على مجموعة كبيرة من الـ Clients إذ أن المعلومات التي يتم بثها إلى الـ Clients هي نفسها ... ولربط الـ WebCamCapture Class في الـ Picturebox نضع الكود التالي في حدث ImageCaptured الخاص بالـ WebCamCapture Class وكما يلي: [CODE]C#: private void webCamCapture1_ImageCaptured(object source, WebCam_Capture.WebcamEventArgs e) { pictureBox1.Image = e.WebCamImage; } VB.NET: Private Sub webCamCapture1_ImageCaptured(ByVal source As Object, ByVal e As WebCam_Capture.WebcamEventArgs) pictureBox1.Image = e.WebCamImage End Sub[/CODE] والآن نستطيع تشغيل الكاميرا عند الضغط على الـ Start Button الموجود في الـ main Menu ونضع في الحدث الخاص بها كود التشغيل ونمرر له الـ Period Time لكل عملية التقاط وهو مثلا 1 Milliseconds ويتم ذلك كما يلي: [CODE]C#: this.webCamCapture1.TimeToCapture_milliseconds = 1; this.webCamCapture1.Start(0); VB.NET: Me.webCamCapture1.TimeToCapture_milliseconds = 1 Me.webCamCapture1.Start(0)[/CODE] ثانيا : إنشاء الـ Remotting Client : ويحتوي أيضا على الأمور التالية: [IMG]http://www.arabteam2000.com/picload/pics_10_05/04_05_06_10_23_34_1146763414Client_Table.JPG[/IMG] وسنقوم بتعريف المتغيرات والـ Objects التالية في الـ Global Declaration للبرنامج: [CODE] C#: ScreenCapture obj; TcpChannel chan; string URI; VB.NET: Dim obj As ScreenCapture Dim chan As TcpChannel Dim URI As String[/CODE] سنستخدم الـScreenCapture Object لعمل الـ Casting على الـ Incoming Remote Instance Object , وسنستخدم الـ TcpChannel Object لإنشاء الـ Remotting Channel وسنضع في الـ URI String Variable الـ URI الخاص بالـ Server Object والذي تم تعريفه في الـ Server . ثم سنقوم بوضع التعريفات الأساسية للـ TCP Channel والـ Remote Object في الـConstructer الخاص بالمشروع وكما يلي: [CODE] C#: public Form1() { URI = "Tcp://"+textBox1.Text+":6600/MyCaptureScreenServer"; chan = new TcpChannel(); ChannelServices.RegisterChannel(chan); obj = (ScreenCapture)Activator.GetObject(typeof(ScreenCapture), URI); } VB.NET: URI = "Tcp://" & textBox1.Text & ":6600/MyCaptureScreenServer" chan = New TcpChannel() ChannelServices.RegisterChannel(chan) obj = CType(Activator.GetObject(GetType(ScreenCapture), URI), ScreenCapture)[/CODE] حيث سيتم تمرير الـ Remote IP أو الـ DNS الخاص بالـ Server من الـ TextBox ويتبعه رقم الـ Port والـ Remote Object الذي تم تعريفه في الـ Client... ولجلب الصورة سنضع الكود التالي في Timer حيث يجلب الصورة من الـ Server كل فترة محددة: [CODE] C#: private void timer1_Tick(object sender, System.EventArgs e) { try { URI = "Tcp://"+textBox1.Text+":6600/MyCaptureScreenServer"; byte[] buffer = obj.GetDesktopBitmapBytes(); MemoryStream ms = new MemoryStream(buffer); pictureBox1.Image = Image.FromStream(ms); } catch(Exception ex){timer1.Enabled=false; MessageBox.Show(ex.Message);} } VB.NET: Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Try URI = "Tcp://" & textBox1.Text & ":6600/MyCaptureScreenServer" Dim buffer As Byte() = obj.GetDesktopBitmapBytes() Dim ms As MemoryStream = New MemoryStream(buffer) pictureBox1.Image = Image.FromStream(ms) Catch ex As Exception timer1.Enabled = False MessageBox.Show(ex.Message) End Try End Sub[/CODE] ولتحويل قناة الاتصال إلى Http Channel فقط قم بتغيير الـ TcpChannel إلى HttpChannel وعندها ستتمكن من مشاهدة الـ Remote Methods عبر الـ Internet Browser ولمشاهدتها نضيف الـ WSDL – Services Definition Language Query التالي إلى الـ URI الخاص بالـ Remote Object: [CODE]http://10.0.0.10:6600/MyCaptureScreenServer?wsdl[/CODE] وستظهر لنا الـ Remote Interface Class بهيئة XML لاحظ الشكل التالي: [IMG]http://www.arabteam2000.com/picload/pics_10_05/04_05_06_10_24_30_1146763470xml.JPG[/IMG] وتستطيع الاستفادة من التركيب السابق للـ Class في حالة لم تتمكن من الحصول على الـ Dll File الخاص بالـ Remote Class , حيث تستطيع تحويل الـ XML السابق إلى ملف Dll لوضعه مع الـ References في برنامج الـ Client ويتم ذلك باستخدام الـMetadata Namespace ومنها الـ w3cxsd2001 Standard حيث يوضع الجزء الأول الخاص بالـ XML Namespace في الـ Serializable Attribute وكما يلي كمثال: [CODE] C#: using System; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Metadata; using System.Runtime.Remoting.Metadata.W3cXsd2001; [Serializable,SoapType(XmlNamespace=@"http://http://schemas.microsoft.com/clr/nsassem/ScreenCapture/ScreenCapture%2C%20Version%3D1.0.2314.30913%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull")] public class ScreenCapture : System.MarshalByRefObject {// Your Methods with Return Values Only} VB.NET: Imports System Imports System.Runtime.Remoting.Messaging Imports System.Runtime.Remoting.Metadata Imports System.Runtime.Remoting.Metadata.W3cXsd2001 <Serializable(), SoapTypeAttribute(XmlNamespace:="http://http://schemas.microsoft.com/clr/nsassem/ScreenCapture/ScreenCapture%2C%20Version%3D1.0.2314.30913%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"), Serializable(), SoapTypeAttribute(XmlNamespace:="http://http://schemas.microsoft.com/clr/nsassem/ScreenCapture/ScreenCapture%2C%20Version%3D1.0.2314.30913%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull")> _ Public Class ScreenCapture : Inherits System.MarshalByRefObject ‘Your Methods with Return Values Only End Class[/CODE] وللاختيار بين الـ TCP أو الـ HTTP Channel فيفضل دائما في حالة كان الـ Remote Object موجود على جهاز تتصل معه عبر الإنترنت استخدام الـ HTTP Channel بسبب محدودية سرعة الاتصال بالإضافة إلى كونه يتوافق مع أي نظام سواء Windows أو غيره لكن يبقى آداء وسرعة الـ TCP Channel أفضل فقط في الـ Local Network ... وهكذا بينا كيفية استخدام الـ Remotting في الدوت نيت وطبقنا عملية إنشاء Distributed eLearning System , وبتأكيد تستطيع الآن إضافة ميزة نقل الصوت إلى جانب نقل صورة الشاشة والكاميرا الخاصة بالمحاضر (لمزيد من المعلومات ارجع إلى الفصل الخاص بالـVOIP) , وسنبين في الجزء التالي من هذا الفصل كيفية إنشاء برنامج Remote Desktop Application مع خاصية التحكم (والذي سيتم الحديث عنه في النسخة الورقية من الكتاب) ... لتحميل الدرس والأمثلة انظر المرفقات:  

 اسم العضو:محمد أكرم عليان  الخميس,06/ربيع الثاني/1427 هـ,03:55 مساءً
اررررررررحم يا معلم ارررررحم .... الله ينور عليك يا فادي .... فعلا شي رائع. بس ابداعاتك هاي بتحرج ناس تانيه عامله حالها الهه في البرمجه و هيا مش عارفه راسها من رجليها اصلا ... طيب يسترجي واحد فيهم يقرب على دروسك و يتفلسف فيها اشوف ما شاء الله عليك  

 اسم العضو:fmo_82  الخميس,06/ربيع الثاني/1427 هـ,06:12 مساءً
الرحمة من عند ربنا اشكرك محمد على تشجيعك وبارك الله بك اتمنى فعلا من الأعضاء المشاركة والتفاعل مع مثل هذه المواضيع لاكن كما ارى إلا الآن عدد الذين حملوا الدرس (صفر )  

 اسم العضو:الوفي دوما  الخميس,06/ربيع الثاني/1427 هـ,07:58 مساءً
أروووع من الراااائع ... ماذا عساي أقول ؟؟ الكلم في حرم الثناء يختفي !! جزيل الشكر لك يالغالي .. ووفقك الله لكل خير أرق المُنى 

 اسم العضو:fmo_82  الثلاثاء,11/ربيع الثاني/1427 هـ,12:10 مساءً
بعد ملاحظة وجود اعضاء يسئلون عن طرق ربط برنامجين الفيديو والفويس كونفيرانس , فكرت بربطها مع بعضها ولكي يسهل فهمها بشكل اكبر وهذا هو البرنامج في المرفقات [IMG]http://www.arabteam2000.com/picload/pics_10_05/09_05_06_06_53_59_1147182839Peer_Conference_System.JPG[/IMG] اذا واجهتك اي صعوبة في فهم الكود او كان لديك اقتراح في تطويره لا تتردد في وضع اقتراحك  

 اسم العضو:عبدالله جابر شقليه  الثلاثاء,11/ربيع الثاني/1427 هـ,05:26 مساءً
للأمانه شي بخوت يا فازي وشي عبقري وكلمة مبدع بحقك قليلة. أتمنى لك التوفيق والاسترار في ابداعاتك ومساعدة أخوانك الآخرين. 

 اسم العضو:fmo_82  الأربعاء,12/ربيع الثاني/1427 هـ,08:19 صباحاً
اشكرك اخي عبدالله على تشجيعك وجزاك الله كل خير  

 اسم العضو:kadhum  الخميس,20/ربيع الثاني/1427 هـ,08:52 صباحاً
شكرا لك يا اخي 

 اسم العضو:fmo_82  الأحد,06/جمادى الثانية/1427 هـ,12:12 صباحاً
بسم الله الرحمن الرحيم احببت ان اضيف جزء من فصل برمجة امن الشبكات إلى المنتدى ولكي يساهم بإذن الله برفع مستوى اخوننا المبرمجين في مجال امن الشبكات وخاصة ما يتعلق بطرق تأمين الإتصال الصوتي عبر الإنترنت وغيره ... [ALIGN=center][URL=http://www.fadidotnet.org/Downloads/RSA%20Chat%20System.zip]Download The Example Code[/URL][/ALIGN] أولا: RSACryptoServiceProvider: ويستخدم في إجراء التشفير وفك التشفير الغير متماثل وهو non inherited Class في البداية سوف ننشئ instance جديد من الـRSACryptoServiceProvider وذلك لتوليد المفتاح العام والخاص ونرفق المفتاح العام مع الرسالة ومن ثم يقوم المستلم بفك الرسالة باستخدام المفتاح الخاص لاحظ الشكل التالي: [IMG]http://www.fadidotnet.org/online_book/RSA1.JPG[/IMG] ولتطبيق إنشاء مشروع تشفير وفك تشفير يستخدم طريقة الـRSA Algorithm , سنقوم بالبداية بإنشاء Tow Methods الأولى نمرر لها الـString Plain Message والـPrivateKay وذلك لتشفير الرسالة بناءا عليه ، وأخرى لفك التشفير ونمرر لها الرسالة المشفرة كـ Byte Array والمفتاح الخاص كـString ، وسنستخدم الـRSACryptoServiceProvider Class لتشفير الرسالة باستخدام الـ RSA Algorithms ، ونمرر له الـ Private Kay كـ CspParameters Object وباستخدام الـ Encrypt Method والـ DecryptMethod ضمن الـ الـRSACryptoServiceProvider Class نتمم عملية التشفير وفك التشفير ونمرر لها الرسالة المراد تشفيرها أو فك تشفيرها بالإضافة إلى قيمة True أو False لتفعيل طريقة التشفير كـFOAEP ويدعم هذا الأسلوب إصدارات الـ Windows XP وما بعدها ، لذلك يفضل اختيار False دائما ولضمان التوافقية مع الإصدارات الأقدم من نظام التشغيل ... [CODE]C#: public byte[] Encrypt(string strData,CspParameters PrivateKey) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(PrivateKey); byte[] data = rsa.Encrypt(Encoding.Unicode.GetBytes(strData), false); return data; } public byte[] Decrypt(byte[] en_data,CspParameters PrivateKey) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(PrivateKey); byte[] data = rsa.Decrypt(en_data, false); return data; } VB.NET: Public Function Encrypt(ByVal strData As String, ByVal PrivateKey As CspParameters) As Byte() Dim rsa As RSACryptoServiceProvider = New RSACryptoServiceProvider(PrivateKey) Dim data As Byte() = rsa.Encrypt(Encoding.Unicode.GetBytes(strData), False) Return data End Function Public Function Decrypt(ByVal en_data As Byte(), ByVal PrivateKey As CspParameters) As Byte() Dim rsa As RSACryptoServiceProvider = New RSACryptoServiceProvider(PrivateKey) Dim data As Byte() = rsa.Decrypt(en_data, False) Return data End Function[/CODE] ولاستخدام الـ Methods السابقة يجب أولا إنشاء Instance Object من الـ CspParameters Class قم نمرر المفتاح العام إلى الـ KeyContainerName Proparity ضمن الـ Instance Object الخاص بالـCspParameters Class وكما يلي: [CODE]C#: public byte[] mymsg; Try //لتشفير { CspParameters cp = new CspParameters(); cp.KeyContainerName = text_private.Text; mymsg = Encrypt(text_msg_to_send.Text,cp); text_encrypted.Text = Encoding.Unicode.GetString(mymsg); } catch (Exception ex){MessageBox.Show(ex.Message);} try//لفك التشفير { CspParameters cp = new CspParameters(); cp.KeyContainerName = text_private1.Text; byte[] my_msg = Decrypt(mymsg,cp); text_decrypted.Text = Encoding.Unicode.GetString(my_msg); } catch (Exception ex){MessageBox.Show(ex.Message);} VB.NET: Public mymsg As Byte() Try 'لتشفير Dim cp As CspParameters = New CspParameters cp.KeyContainerName = text_private.Text mymsg = Encrypt(text_msg_to_send.Text,cp) text_encrypted.Text = Encoding.Unicode.GetString(mymsg) Catch ex As Exception  MessageBox.Show(ex.Message) End Try Try ' لفك التشفير Dim cp As CspParameters = New CspParameters cp.KeyContainerName = text_private1.Text Dim my_msg As Byte() = Decrypt(mymsg, cp) text_decrypted.Text = Encoding.Unicode.GetString(my_msg) Catch ex As Exception  MessageBox.Show(ex.Message) End Try[/CODE] في برمجيات الشبكات نقوم في البداية بتشفير البيانات المرسلة باستخدام أي من الأساليب السابقة لتشفير ثم نحول البيانات المشفرة إلى Stream لإرسالها عبر الـSocket باستخدام الـNetwork Stream كمثال، ثم يقوم الطرف المستقبل باستقبال الرسالة باستخدام الـNetwork Stream عبر الـSocket ،ويجب أن تكون عملية فك التشفير كما هي الخوارزمية المستخدمة إثناء التشفير سواء RSA أو DES أو التواقيع الرقمية ، ثم نستطيع تحمل الرسالة إلى الـMemory stream حيث ستستقبل الرسالة كـStream Data ، وبعد ذلك يمكن تحويلها إلى Byte Array لفك تشفيرها لتحويلها إلى رسالة مرة أخرى، لاحظ الشكل التالي: [IMG]http://www.fadidotnet.org/online_book/RSA2.JPG[/IMG] سنقوم الآن بإنشاء برنامج بسيط (Client / Server) لإرسال نص من جهاز إلى آخر وسنخدم فيه الـ RSA لتشفير النص المرسل حيث سيتفق الطرفان على الـ Private Kay والذي سيستخدم لتشفير و فك تشفير الرسالة... و سيكون الشكل العام للبرنامج كما في الشكل التالي ويبين طرفان مرسل ومستقبل ويقوم المرسل بتشفير الرسالة باستخدام المفتاح العام ويتفق الطرفان على المفتاح الخاص والذي سيتم فك الرسالة من خلاله: [IMG]http://www.fadidotnet.org/online_book/RSA%20_Chat.jpg[/IMG] أولا المرسل أو الـ Client : وسنستخدم فيه الطريقة المعروفة لتشفير الرسائل باستخدام الـ RSA algorithms حيث سيتم تحويل الرسالة المشفرة إلى Byte Array وسنستخدم الـ Serialization لإرسالها حيث سيتم إرسالها كـ Serialization Object ويتم كل ذلك كما يلي: [CODE] C#: using System.Text; using System.Security.Cryptography; using System.Net.Sockets; using System.Net; using System.IO; using System.Runtime.Serialization.Formatters.Binary; . . . public byte[] mymsg; public byte[] Encrypt(string strData,CspParameters PrivateKey) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(PrivateKey); byte[] data = rsa.Encrypt(Encoding.Unicode.GetBytes(strData), false); return data; } . . . try { CspParameters cp = new CspParameters(); cp.KeyContainerName = text_private.Text; mymsg = Encrypt(text_msg_to_send.Text,cp); text_encrypted.Text = Encoding.Unicode.GetString(mymsg); object op = (object) mymsg; BinaryFormatter br = new BinaryFormatter (); TcpClient myclient = new TcpClient (text_IP.Text,7000); NetworkStream myns = myclient.GetStream (); br.Serialize (myns,op); myns.Close (); myclient.Close (); } catch (Exception ex){MessageBox.Show(ex.Message);} VB.NET: Imports System.Text Imports System.Security.Cryptography Imports System.Net.Sockets Imports System.Net Imports System.IO Imports System.Runtime.Serialization.Formatters.Binary . . . Public mymsg As Byte() Public Function Encrypt(ByVal strData As String, ByVal PrivateKey As CspParameters) As Byte() Dim rsa As RSACryptoServiceProvider = New RSACryptoServiceProvider(PrivateKey) Dim data As Byte() = rsa.Encrypt(Encoding.Unicode.GetBytes(strData), False) Return data End Function . . . Try Dim cp As CspParameters = New CspParameters cp.KeyContainerName = text_private.Text mymsg = Encrypt(text_msg_to_send.Text,cp) text_encrypted.Text = Encoding.Unicode.GetString(mymsg) Dim op As Object = CObj(mymsg) Dim br As BinaryFormatter = New BinaryFormatter Dim myclient As TcpClient = New TcpClient(text_IP.Text, 7000) Dim myns As NetworkStream = myclient.GetStream() br.Serialize (myns,op) myns.Close () myclient.Close () Catch ex As Exception  MessageBox.Show(ex.Message) End Try[/CODE] ثانيا المستقبل أو الـ Server : وفي طرف المستقبل الـ Server يتم استقبال الـ Encrypted Message as an Object ثم تحول إلى Byte Array بعد عمل الـ Casting عليها ومن ثم نمرر الـ Byte Array المستلم إلى الـ RSA Decryption Method ليتم فك تشفيرها باستخدام المفتاح الخاص والذي تم الاتفاق عليه ... [CODE] C#: using System.Text; using System.Security.Cryptography; using System.Net.Sockets; using System.IO; using System.Threading; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters; . . . public byte[] mymsg; NetworkStream myns; TcpListener mytcpl; Socket mysocket; Thread myth; public byte[] Decrypt(byte[] en_data,CspParameters PrivateKey) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(PrivateKey); byte[] data = rsa.Decrypt(en_data, false); return data; } . . . void RSA_Server ()//استقبال الرسالة بشكل مشفر { mytcpl = new TcpListener (7000); mytcpl.Start (); mysocket = mytcpl.AcceptSocket (); myns = new NetworkStream (mysocket); BinaryFormatter br = new BinaryFormatter (); object op; op= br.Deserialize (myns); // Deserialize the Object from Stream    mymsg = (byte[]) op; text_encrypted.Text = Encoding.Unicode.GetString(mymsg);   mytcpl.Stop();  while (true)   {  RSA_Server();   } } . . . try // فك تشفير الرسالة { CspParameters cp = new CspParameters(); cp.KeyContainerName = text_private1.Text; byte[] my_msg = Decrypt(mymsg,cp); text_decrypted.Text = Encoding.Unicode.GetString(my_msg); } catch (Exception ex){MessageBox.Show(ex.Message);} VB.NET: Imports System.Text Imports System.Security.Cryptography Imports System.Net.Sockets Imports System.IO Imports System.Threading Imports System.Runtime.Serialization.Formatters.Binary Imports System.Runtime.Serialization.Formatters . . . Public mymsg As Byte() Private myns As NetworkStream Private mytcpl As TcpListener Private mysocket As Socket Private myth As Thread Public Function Decrypt(ByVal en_data As Byte(), ByVal PrivateKey As CspParameters) As Byte() Dim rsa As RSACryptoServiceProvider = New RSACryptoServiceProvider(PrivateKey) Dim data As Byte() = rsa.Decrypt(en_data, False) Return data End Function . . . Private Sub RSA_Server() ' استقبال الرسالة بشكل مشفر mytcpl = New TcpListener(7000) mytcpl.Start() mysocket = mytcpl.AcceptSocket() myns = New NetworkStream(mysocket) Dim br As BinaryFormatter = New BinaryFormatter Dim op As Object op = br.Deserialize(myns) ' Deserialize the Object from Stream mymsg = CType(op, Byte()) text_encrypted.Text = Encoding.Unicode.GetString(mymsg) mytcpl.Stop() Do While True RSA_Server() Loop End Sub . . . Try ' فك تشفير الرسالة Dim cp As CspParameters = New CspParameters cp.KeyContainerName = text_private1.Text Dim my_msg As Byte() = Decrypt(mymsg, cp) text_decrypted.Text = Encoding.Unicode.GetString(my_msg) Catch ex As Exception  MessageBox.Show(ex.Message) End Try[/CODE] نستطيع من خلال هذا المثال استخدام أسلوب التشفير هذا مع الـVoice Over IP Applications لكن تبقى مشكلة محدوديات الاتصال الصوتي ومتطلباته من أكثر الأمور التي تواجه طرق تشفير الصوت في الإنترنت ومن هنا يجب استخدام الأساليب الخاصة بضغط البيانات الصوتية قبل وبعد عملية التشفير .... جزء من فصل برمجة أمن الشبكات - كتاب احترف برمجة الشبكات والنظم الموزعة 

 اسم العضو:fmo_82  الاثنين,06/رجب/1427 هـ,10:42 صباحاً
Part From Chapter: ROW Socket Programming in Dot Net بسم الله الرحمن الرحيم يعتبر موضوع الـ Row Socket من المواضيع الهامة وخاصة للبرمجيات التي تعتمد على التعامل مع البروتوكولات في المستوى الأدنى من الـ Transport Layer ومنها بروتوكول الـ ARP والـ RARP والمستخدم بشكل أساسي لجلب الـ MAC أو الـ Physical Address للـ Ethernet Card والـ IGMP المخصص لإدارة المجموعات في الـ Multicasting بالإضافة إلى بروتوكول الـ ICMP والذي يستخدم بشكل أساسي في عملية الـ Ping بالإضافة إلى الكثير من العمليات الأخرى لإرسال حالة الـ Message بعد إرسالها إلى الـ Destination ,ومن المعروف أن الـ ICMP و الـ ARP تصنف من البروتوكولات التي تعمل على مستوى الـNetwork Layer ضمن الـ TCP/IP Model وهذا يعني أنها Connectionless Protocols، و لا تعتمد هذه البروتوكولات على استخدام أي من البروتوكولات في الـTransport Layer إذ لا حاجة لاستخدام الـ Ports عند التعامل معها... لتعامل مع الـ Row Socket في الدوت نيت يجب أولا تعريف الـ Row Socket Type بعد ذلك يمكننا اختيار أي من البروتوكولات التي تعمل على الـ Network Layer وتدعم الـRow Socket التعامل مع البروتوكولات التالية وكما هو واضح في الجدول: [CODE]Protocol Name Description GGP Gateway-to-Gateway Protocol ICMP Internet Control Message Protocol IGMP Internet Group Management Protocol IP A raw IP packet IPX Novell IPX Protocol ND Net Disk Protocol PUP Xerox PARC Universal Protocol (PUP) ROW A raw IP packet SPX Version 1 & 2 Novell SPX Protocol[/CODE] وكمثال لبرمجة بروتوكول الـ ICMP يجب أولا تعريف الـ Row Socket كما يلي: [CODE]C#: Socket row_socket = new Socket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Icmp); VB.NET: Dim row_socket As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp)[/CODE] ويعتبر بروتوكول الـ ICMP بروتوكول Connectionless وهذا يعني عدم حاجته أيضا لإجراء عملية الـConnect أو الـ Binding مع الـ Socket لذلك نحدد له فقط في الـ IPEndPoint Object الـ IP Address للـ Destination ودون تحديد رقم الـ Port حيث تأخذ القيمة صفر وكما يلي: [CODE]C#: IPEndPoint iep = new IPEndPoint(IPAddress.Parse("10.0.0.10"), 0); VB.NET: Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse("10.0.0.10"), 0)[/CODE] وتتم عملية الإرسال مباشرة باستخدام الـ Sendto Method بعد تحديد الشكل العام للـICMP Header Format حيث ترسل محتوياته كـ Byte Array وتتم عملية الاستقبال باستخدام الـ ReceiveFrom Method وبنفس الطريقة التي أرسل بها ، ولإنشاء ICMP Header Class يجب التقيد بالشكل العام لهذا البروتوكول والـData Type لكل Field وكما هو واضح في الجدول 15-3 التالي: [CODE]Data Variable Size Type Type 1 byte Byte Code 1 byte Byte Checksum 2 bytes Unsigned 16-bit integer Message multibyte Byte array[/CODE] ولإنشاء الـ ICMP Class يجب التقيد بالتركيب العام للـ ICMP Header وكما يلي: [CODE]C#: class ICMP { public byte Type; public byte Code; public UInt16 Checksum; public int MessageSize; public byte[] Message = new byte[1024]; } VB.NET: Class ICMP Public Type As Byte Public Code As Byte Public Checksum As UInt16 Public MessageSize As Integer Public Message As Byte() = New Byte(1024) End Class[/CODE] سنقوم الآن بتنفيذ برنامج بسيط لإجراء عملية الـ Ping ومن المعروف أن الـ Ping يستخدم الـ Type 8 لإرسال والـ Type 0 عند الاستقبال حيث يقوم الطرف المقابل باستقبال الرسالة وإعادة إرسالها كما هي إلى الـSourceAddress ، وإذا تم استقبال الـ ICMP Message بالـ Type 0 هذا يعني انه تم الوصول إلى الـDestination ويمكن التحقق من وصول الـ ICMP Header بالشكل الصحيح بعد حساب ناتج الـ Checksum فإذا تطابق مع مقلوب مجموع الـHeader Data عندها نستطيع معرفة أنه تم تسليم الـMessage لـ Destination بشكل الصحيح وللبدء بالتطبيق سيكون الشكل العام للبرنامج كما في الشكل التالي: [IMG]http://www.fadidotnet.org/Downloads/ICMP_Trace_Ping.jpg[/IMG] ولإنشاء الـ ICMP Class يجب أولا تعريف الـ ICMP Header وتحويله إلى Byte Array بعد إسناد الـPing Data التي نريدها إليه وكما يلي: [CODE]C#: using System; using System.Net; using System.Net.Sockets; using System.Text; class ICMP { public byte Type; public byte Code; public UInt16 Checksum; public int MessageSize; public byte[] Message = new byte[1024]; public ICMP() { } public ICMP(byte[] data, int size) { Type = data[20]; Code = data[21]; Checksum = BitConverter.ToUInt16(data, 22); MessageSize = size - 24; Buffer.BlockCopy(data, 24, Message, 0, MessageSize); } public byte[] getBytes() { byte[] data = new byte[MessageSize + 9]; Buffer.BlockCopy(BitConverter.GetBytes(Type), 0, data, 0, 1); Buffer.BlockCopy(BitConverter.GetBytes(Code), 0, data, 1, 1); Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, data, 2, 2); Buffer.BlockCopy(Message, 0, data, 4, MessageSize); return data; } public UInt16 getChecksum() { UInt32 chcksm = 0; byte[] data = getBytes(); int packetsize = MessageSize + 8; int index = 0; while ( index < packetsize) { chcksm += Convert.ToUInt32(BitConverter.ToUInt16(data, index)); index += 2; } chcksm = (chcksm >> 16) + (chcksm & 0xffff); chcksm += (chcksm >> 16); return (UInt16)(~chcksm); } } VB.NET: Imports Microsoft.VisualBasic Imports System Imports System.Net Imports System.Net.Sockets Imports System.Text Friend Class ICMP Public Type As Byte Public Code As Byte Public Checksum As UInt16 Public MessageSize As Integer Public Message As Byte() = New Byte(1023) Public Sub New() End Sub Public Sub New(ByVal data As Byte(), ByVal size As Integer) Type = data(20) Code = data(21) Checksum = BitConverter.ToUInt16(data, 22) MessageSize = size - 24 Buffer.BlockCopy(data, 24, Message, 0, MessageSize) End Sub Public Function getBytes() As Byte() Dim data As Byte() = New Byte(MessageSize + 9 - 1) Buffer.BlockCopy(BitConverter.GetBytes(Type), 0, data, 0, 1) Buffer.BlockCopy(BitConverter.GetBytes(Code), 0, data, 1, 1) Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, data, 2, 2) Buffer.BlockCopy(Message, 0, data, 4, MessageSize) Return data End Function Public Function getChecksum() As UInt16 Dim chcksm As UInt32 = System.Convert.ToUInt32(0) Dim data As Byte() = getBytes() Dim packetsize As Integer = MessageSize + 8 Dim index As Integer = 0 Do While index < packetsize chcksm +=chcksm Convert.ToUInt32(BitConverter.ToUInt16(data, index)) index += 2 Loop chcksm = (chcksm >> 16) + (chcksm And &HFFFF) chcksm += (chcksm >> 16) Return System.Convert.ToUInt32((Not chcksm)) End Function End Class[/CODE] حيث قمنا بإنشاء الـ getBytes Method لتحويل الـ ICMP Packet إلى Byte Array باستخدام الـBitConverter.GetBytes Method وأنشئنا الـ getChecksum Method لحساب الـ Checksum للـICMP Packet حيث سيسند إليه وسيستخدم لعملية التحقق من وصول الـ Packet Header للـ Destination بالشكل الصحيح ... ويمكن استخدام الـ Class السابق مباشرة بعد تعريف Row Socket ثم تعريف IPEndpoint Object لإسناده إلى sendto Method ثم اشتقاق instance Object من الـICMP Class السابق و إسناد قيم ابتدائية للـ ICMP Header وإنشاء ICMP Message وتحويلها إلى Byte Array وفي النهاية يمكننا إرسالها إلى الـ Destination باستخدام الـ sendto method وبتأكيد يمكننا تغير مدة الـ Time Out للمدة التي سينتظرها الـSource إلى حين الدخول على الـ SocketException في حالة عدم الاستجابة ويتم كل ذلك كما يلي: [CODE]C#: byte[] data = new byte[1024]; int recv; Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Raw,ProtocolType.Icmp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(textBox1.Text),0); EndPoint ep = (EndPoint)iep; ICMP packet = new ICMP(); packet.Type = 0x08; packet.Code = 0x00; packet.Checksum = 0; Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, packet.Message, 0, 1); data = Encoding.ASCII.GetBytes("Ping Message OK"); Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length); packet.MessageSize = data.Length + 4; int packetsize = packet.MessageSize + 4; UInt16 chcksum = packet.getChecksum(); packet.Checksum = chcksum; host.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout, 1000); host.SendTo(packet.getBytes(), packetsize, SocketFlags.None, iep); VB.NET: Dim data As Byte() = New Byte(1023) Dim recv As Integer Dim host As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw,ProtocolType.Icmp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(textBox1.Text),0) Dim ep As EndPoint = CType(iep, EndPoint) Dim packet As ICMP = New ICMP() packet.Type = &H08 packet.Code = &H00 packet.Checksum = 0 Buffer.BlockCopy(BitConverter.GetBytes(CShort(1)), 0, packet.Message, 0, 2) Buffer.BlockCopy(BitConverter.GetBytes(CShort(1)), 0, packet.Message, 2, 2) data = Encoding.ASCII.GetBytes("Ping Message OK") Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length) packet.MessageSize = data.Length + 4 Dim packetsize As Integer = packet.MessageSize + 4 Dim chcksum As UInt16 = packet.getChecksum() packet.Checksum = chcksum host.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout, 1000) host.SendTo(packet.getBytes(), packetsize, SocketFlags.None, iep)[/CODE] ولاستقبال الرد على الرسالة من الـ Destination سنستخدم نفس التعريف السابق للـ Socket حيث سنستخدم الـReceiveFrom Method ونسند إليها الـ Reference Value للـ IPEndpoint الذي أرسلنا من خلاله الرسالة ، ونسند الرد الذي تم استقباله إلى الـ ICMP Instance Object الذي أنشئ من الـ ICMP Class ، ويتم كل ذلك كما يلي: [CODE]C#: try { data = new byte[1024]; recv = host.ReceiveFrom(data, ref ep); } catch (SocketException) { listBox1.Items.Clear(); listBox1.Items.Add("No response from remote host"); return; } ICMP response = new ICMP(data, recv); listBox1.Items.Clear(); listBox1.Items.Add("response from: "+ ep.ToString()); listBox1.Items.Add(" Type: "+ response.Type); listBox1.Items.Add(" Code: "+ response.Code); int Identifier = BitConverter.ToInt16(response.Message, 0); int Sequence = BitConverter.ToInt16(response.Message, 2); listBox1.Items.Add(" Identifier: "+ Identifier); listBox1.Items.Add(" Sequence: "+ Sequence); string stringData = Encoding.ASCII.GetString(response.Message,4, response.MessageSize - 4); listBox1.Items.Add(" data: "+stringData); host.Close(); VB.NET: Try data = New Byte(1023) recv = host.ReceiveFrom(data, ep) Catch e1 As SocketException listBox1.Items.Clear() listBox1.Items.Add("No response from remote host") Return End Try Dim response As ICMP = New ICMP(data, recv) listBox1.Items.Clear() listBox1.Items.Add("response from: " & ep.ToString()) listBox1.Items.Add(" Type: " & response.Type) listBox1.Items.Add(" Code: " & response.Code) Dim Identifier As Integer = BitConverter.ToInt16(response.Message, 0) Dim Sequence As Integer = BitConverter.ToInt16(response.Message, 2) listBox1.Items.Add(" Identifier: " & Identifier) listBox1.Items.Add(" Sequence: " & Sequence) Dim stringData As String = Encoding.ASCII.GetString(response.Message,4, response.MessageSize - 4) listBox1.Items.Add(" data: " & stringData) host.Close()[/CODE] ويمكننا أيضا استخدام الـ Class السابق لإنشاء برنامج لعمل الـ Tracing ومن المعروف بالـ Routing Tracing انه يقوم بتعقب الـ Hops أو الـ Routers التي يمر عبرها الـPacket حيث يرجع كل Router يمر الـ Packet من خلاله ICMP Replay Message تحتوي على الـ Message التي أرسلت بالإضافة إلى الـ IP للـ Router الذي تم تمرير الـMessage من خلاله والوقت الذي استغرق للوصول إلى كل Router حتى وصول الـ Packet إلى الـ Destination وكما هو واضح من تعريف الـ Tracing فإن البرنامج سيعتمد على جلب الـ IP لكل Router يمر من خلاله إلى حين الوصول إلى الطرف المعني ويمكن إجراء هذه العملية باستخدام الـ IpTimeToLive ضمن الـSetSocketOption Method حيث نضعها داخل Loop وفي كل مرة نزيد الـ Loop بمقدار واحد ونسند قيمته إلى الـ TTL حيث يعبر كل TTL عن Hop أو Router تم المرور من خلاله ويتم إرسال Ping Message إلى ذلك الـ Hop وخلال ذلك نقيس الفترة الزمنية المستغرقة بين عملية إرسال الـ Ping واستقبال الرد من كل Hop إلى حين الوصول إلى آخر Hop مر الـ Packet من خلاله ويمكننا قياس ذلك باستخدام الـ TickCount ضمن الـEnvironment Class وترجع هذه الـ Property قيمة Integer بالـ Millisecond من بدأ نظام التشغيل بالعمل إلى الوقت الحالي حيث يمكننا اخذ هذه القيمة عند بداية عمل الـ Ping وأخذها مرة أخرى عند استقبال الرد ومن ثم طرح القيمة الأولى من الثانية ...، ويتم كل ذلك كما يلي: [CODE]C#: byte[] data = new byte[1024]; int recv, timestart, timestop; Socket trace_socket = new Socket(AddressFamily.InterNetwork,SocketType.Raw, ProtocolType.Icmp); IPHostEntry dest = Dns.Resolve(textBox2.Text); IPEndPoint iep = new IPEndPoint(dest.AddressList[0], 0); EndPoint ep = (EndPoint)iep; ICMP packet = new ICMP(); packet.Type = 0x08; packet.Code = 0x00; packet.Checksum = 0; Buffer.BlockCopy(BitConverter.GetBytes(1), 0, packet.Message, 0, 2); Buffer.BlockCopy(BitConverter.GetBytes(1), 0, packet.Message, 2, 2); data = Encoding.ASCII.GetBytes("Tracing is OK,FADI Abdel-qader"); Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length); packet.MessageSize = data.Length + 4; int packetsize = packet.MessageSize + 4; UInt16 chcksum = packet.getChecksum(); packet.Checksum = chcksum; trace_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout, 1000); int badcount = 0; for (int i = 1; i < 50; i++) { trace_socket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.IpTimeToLive, i); timestart = Environment.TickCount; trace_socket.SendTo(packet.getBytes(), packetsize, SocketFlags.None, iep); try { data = new byte[1024]; recv = trace_socket.ReceiveFrom(data, ref ep); timestop = Environment.TickCount; ICMP response = new ICMP(data, recv); if (response.Type == 11) listBox1.Items.Add("hop response from ms"+ i+ ep.ToString()+ (timestop-timestart)); if (response.Type == 0) { listBox1.Items.Add(" reached in hops, ms " + ep.ToString()+ i+ (timestop-timestart)); break; } badcount = 0; } catch (SocketException) { listBox1.Items.Add("hop No response from remote host "+ i); badcount++; if (badcount == 5) { listBox1.Items.Add("Unable to contact remote host"); break; } } } trace_socket.Close(); VB.NET: Dim data As Byte() = New Byte(1023) Dim recv, timestart, timestop As Integer Dim trace_socket As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp) Dim dest As IPHostEntry = Dns.Resolve(textBox2.Text) Dim iep As IPEndPoint = New IPEndPoint(dest.AddressList(0), 0) Dim ep As EndPoint = CType(iep, EndPoint) Dim packet As ICMP = New ICMP  packet.Type = &H08  packet.Code = &H00  packet.Checksum = 0 Buffer.BlockCopy(BitConverter.GetBytes(1), 0, packet.Message, 0, 2) Buffer.BlockCopy(BitConverter.GetBytes(1), 0, packet.Message, 2, 2) data = Encoding.ASCII.GetBytes("Tracing is OK,FADI Abdel-qader") Buffer.BlockCopy(data, 0, packet.Message, 4, data.Length) packet.MessageSize = data.Length + 4 Dim packetsize As Integer = packet.MessageSize + 4 Dim chcksum As UInt16 = packet.getChecksum() packet.Checksum = chcksum trace_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout, 1000) Dim badcount As Integer = 0 For i As Integer = 1 To 49 trace_socket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.IpTimeToLive, i) timestart = Environment.TickCount trace_socket.SendTo(packet.getBytes(), packetsize, SocketFlags.None, iep) Try data = New Byte(1023) recv = trace_socket.ReceiveFrom(data, ep) timestop = Environment.TickCount Dim response As ICMP = New ICMP(data, recv) If response.Type = 11 Then listBox1.Items.Add("hop response from ms" & i+ ep.ToString()+ (timestop-timestart)) End If If response.Type = 0 Then listBox1.Items.Add(" reached in hops, ms " & ep.ToString()+ i+ (timestop-timestart)) Exit Try End If badcount = 0 Catch e1 As SocketException listBox1.Items.Add("hop No response from remote host " & i) badcount += 1 If badcount = 5 Then listBox1.Items.Add("Unable to contact remote host") Exit For End If End Try Next i trace_socket.Close()[/CODE] وهكذا بينا كيفية استخدام الـ ICMP في الدوت نيت وكيفية استخدامه لإنشاء برنامج لعمل الـ Ping وآخر لعمل الـRouting Tracing ، Introduction to Packet Sniffing Applications تكمن الفكرة الأساسية من الـ Packet Sniffing Applications بالتصنت على الـNetwork Layer أو الـRowSocket بعد اختيار الـNetwork Interface إذ أنها لا تعمل ضمن نطاق Port محدد ونستطيع من خلال الـ Row Socket التقاط أي Packet يمر من خلال الـ Network Interface Card ولتحليل الـPacket لابد من معرفة الحجم الكلي لكل Header ثم إضافته ، وبشكل دائم يتم إضافة الـ Header Length إلى كل Header ضمن كل طبقة من طبقات الـ TCP/IP ، لاحظ موقع الـ Header Length في كل Header من بروتوكولات الـTCP/IP : [IMG]http://www.arabteam2000.com/picload/pics_10_05/25_07_06_05_09_34_1153872574row.JPG[/IMG] ويمكننا فصل كل Layer عن الأخرى بعد معرفة الـ Header Length لكل Layer ، لاحظ من الشكل السابق انه يمكننا معرفة الحجم الكلي للـ Packet من خلال الجزء الأول منه والمسمى بالـ Frame , ويمكننا مثلا معرفة الـ IP Address لطرف المرسل من خلال تخزين الـ Packet الملتقط في Byte Array ثم تغيير الـ offset للـمكان الذي نريد القراءة منه ، إذ يأتي موقع الـ IP Source Address في الـ IP Packet دائما بعد 12 Bytes لاحظ الشكل التالي: [IMG]http://www.arabteam2000.com/picload/pics_10_05/25_07_06_05_16_23_1153872983row_.JPG[/IMG] ويجب دائما إنشاء Class أو Struct يحتوي على الـ Header Elements لكل Protocol يتم التعامل معه وحتى نستطيع تحليله لاحقا ، وتحديد سعة كل منها بناء على السعة الحقيقية لها وكمثال لإنشاء Struct خاص بالـIPHeader : [CODE]C#: public struct IPHeader { [FieldOffset(0)] public byte ip_verlen; //IP version and IP Header length [FieldOffset(1)] public byte ip_tos; //Type of Service [FieldOffset(2)] public ushort ip_totallength; //Total Packet Length [FieldOffset(4)] public ushort ip_id; //Unique ID [FieldOffset(6)] public ushort ip_offset; //Flags and Offset [FieldOffset(8)] public byte ip_ttl; //Time To Live [FieldOffset(9)] public byte ip_protocol; //Protocol (TCP, UDP, ICMP, Etc.) [FieldOffset(10)] public ushort ip_checksum; //IP Header Checksum [FieldOffset(12)] public uint ip_srcaddr; //Source IP Address [FieldOffset(16)] public uint ip_destaddr; //Destination IP Address } VB.NET: Public Structure IPHeader <FieldOffset(0)> _ Public ip_verlen As Byte 'IP version and IP Header length <FieldOffset(1)> _ Public ip_tos As Byte 'Type of Service <FieldOffset(2)> _ Public ip_totallength As System.UInt16 'Total Packet Length <FieldOffset(4)> _ Public ip_id As System.UInt16 'Unique ID <FieldOffset(6)> _ Public ip_offset As System.UInt16 'Flags and Offset <FieldOffset(8)> _ Public ip_ttl As Byte 'Time To Live <FieldOffset(9)> _ Public ip_protocol As Byte 'Protocol (TCP, UDP, ICMP, Etc.) <FieldOffset(10)> _ Public ip_checksum As System.UInt16 'IP Header Checksum <FieldOffset(12)> _ Public ip_srcaddr As System.UInt32 'Source IP Address <FieldOffset(16)> _ Public ip_destaddr As System.UInt32 'Destination IP Address End Structure[/CODE] ولتفعيل عملية التصنت على الـ IP Layer يجب تعريف Row Socket ونحدد فيها الـ IP كـ Protocol Type ثم نقوم بعمل الـ Binding مع الـ IP Address للـ Interface Card الذي نريد التصنت عليه ، وبتأكيد لا تحتاج الـ Row Socket تحديد Port معين إذ أنها لا تتعامل مع أي من الـ Transport Layer Protocols ، ويتم ذلك كما يلي: [CODE]C#: socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); socket.Bind(new IPEndPoint(IPAddress.Parse(“10.0.0.10”), 0)); socket.BeginReceive(m_Buffer, 0, m_Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnReceive), null); VB.NET: socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP) socket.Bind(New IPEndPoint(IPAddress.Parse(“10.0.0.10”), 0)) socket.BeginReceive(m_Buffer, 0, m_Buffer.Length, SocketFlags.None, New AsyncCallback(AddressOf Me.OnReceive), Nothing)[/CODE] ثم إضافة الـ AsyncCallback Method للـ BeginReceive Method السابقة ويتم ذلك كما يلي: [CODE]C#: private void OnReceive(IAsyncResult ar) { int received = socket.EndReceive(ar); if (socket != null) { byte[] packet = new byte[received]; Array.Copy(Buffer, 0, packet, 0, received); // Here The all Captured Packet in The Buffer } socket.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnReceive), null);   } VB.NET: Private Sub OnReceive(ByVal ar As IasyncResult) Dim received As Integer = socket.EndReceive(ar) If Not socket Is Nothing Then Dim packet As Byte() = New Byte(received) Array.Copy(Buffer, 0, packet, 0, received) ‘ Here The all Captured Packet in The Buffer End If socket.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, New AsyncCallback(AddressOf Me.OnReceive), Nothing) End Sub[/CODE] وفي هذه المرحلة فإن أي Packet يمر من خلال الـ Network Layer يتم التقاطه وتخزينه في الـ Buffer السابق، حيث يمكن تحليله لاحقا بحسب حجم الـ Header للـPacket الملتقط بالإضافة إلى معرفة الحجم لكل Element في الـ Header ... امل من الله أن تكونوا قد استفتم من هذا الدرس وان يكون قد فتح لكم افاق جديدة لتفكير  

 اسم العضو:fmo_82  الجمعة,15/شعبان/1427 هـ,09:10 صباحاً
Make your H323 Calls Voice Chat under TAPI H323 More and More [ALIGN=center][IMG]http://www.fadidotnet.org/Downloads/h323.jpg[/IMG][/ALIGN] [URL=http://www.arabteam2000-forum.com/index.php?act=Attach&type=post&id=34531]Download it Now[/URL] 

 اسم العضو:ss  الثلاثاء,26/شعبان/1427 هـ,07:08 مساءً
ماشاء الله زادك الله علماً في درسك الاول قمت بكتابة هذا الكود String str=Console.ReadLine(); // كتابة الرسالة هنا ووضعها في متغير من نوع ستريغ ASCIIEncoding asen= new ASCIIEncoding(); // تحويل النص المكتوب الى الأسكي byte[] ba=asen.GetBytes(str); //تحويل الأسكي الى باينري كود وتخزينها في مصفوفة من النوع بايت حيث تم تحويل السطر الثاني الى فيجوال بيسك دوت نت وظهر كالتالي Private mynetsream As NetworkStream = tcpclnt.GetStream ويظهر خطاء عند اضافة الكود في tcpclnt.getstream وعلى ما اعتقد هو بسبب جلب مكتبه مع اني جلبت system.net.sockets system.io ولكن تبقى المشكله فاتمنى التوضيح وجزاك الله خير على ما تقوم به 

 اسم العضو:fmo_82  السبت,01/رمضان/1427 هـ,10:19 صباحاً
اخي العزيز ss يرجى توضيح نوع الخطأ كما وارجو استخدام خاصية الكود الموجودة في محرر المشاركة لتوضيح القراءة وشكرا جزيلا 

 اسم العضو:ss  السبت,01/رمضان/1427 هـ,11:19 مساءً
[QUOTE] وهنا توضيح هذه الخطوة في الكود <br><br><DIV class=codetop> كود</DIV><DIV dir="ltr" class=quotemain><p align="left">String str=Console.ReadLine(); // كتابة الرسالة هنا ووضعها في متغير من نوع ستريغ<br>ASCIIEncoding asen= new ASCIIEncoding(); // تحويل النص المكتوب الى الأسكي<br>byte[] ba=asen.GetBytes(str); //تحويل الأسكي الى باينري كود وتخزينها في مصفوفة من النوع بايت</p></DIV><br>في نموذج osi يتم تقسيم ال[/QUOTE] هذه المشاركه والخطاء بالضبط ASCIIEncoding asen= new ASCIIEncoding حيث يعطيني خطاء  

 اسم العضو:ss  الأحد,02/رمضان/1427 هـ,01:00 مساءً
الخطاء نفس الجمله اي لا يقبل ان يترجم البرنامج حيث انه خطاء قبل تنفيذ البرنامج اي يعطي خط متعرج اسفله جمله غير صحيحه 

 اسم العضو:fmo_82  الأحد,02/رمضان/1427 هـ,04:34 مساءً
استخدام الـASCIIEncoding يحتاج إلى استدعاء System.Text 

 اسم العضو:gold_way  الثلاثاء,02/شوال/1427 هـ,06:57 مساءً
السلام و رحمة الله وبركاته اشكرك اخى محمد على مجهودك الرائع والجميل اتمنى ان يجعلك الله عون في تطوير المنتدى وشكرا جزيلا على الموضوع.  

 اسم العضو:الباشق1  الأربعاء,06/محرم/1428 هـ,02:51 مساءً
مشكور اخي وفقك الله 

 اسم العضو:Malak  الأحد,15/فر/1428 هـ,10:50 صباحاً
مشكور وجزاك الله خير الموضوع اكثر من رائع 

 اسم العضو:yousif1  الثلاثاء,03/رجب/1428 هـ,03:21 صباحاً
[COLOR=blue][SIZE=4][ALIGN=center]

[IMG]http://www.arabmoheet.net/forum/pics/bsmla.gif[/IMG][/ALIGN] مشكووووووووووووووووووووووووووووووور

[/COLOR][/SIZE] 

 اسم العضو:ali1  الأحد,15/رجب/1428 هـ,04:21 صباحاً
بصراحة لا يسعني الا ان اشكر الجميع لما لمسته من خبرة وتعاون رائع واتمني التوفيق للجميع ولقد تابعت الموضوع ولكن لست متخصص في هذا الموضوع ولقد صادفني موضعكم لاني بابحث عن مساعدتي في عمل مشاركة قاعدة بيانات موجودة في مصر وقدرتي علي العمل عليها وانا بالسعودية ولكن لم انجح في هذا حتي الان فهل من الممكن مساعدتي وسوف اوضح لكم الامر حتي ترشدوني وتفتوني فيها المشكلة تتمثل في كيفية الوصول الي كمبيوتر بعيد في دولة اخري وقدرتي علي العمل علي هذا الكمبيوتر بما لديه من ملفات عن طريق ip ووسيلته الانترنت بحيث يكون الجهاز رقم 1 في دولة مصر مثلا وبه قاعدة بيانات وهو يعتبر بالنسبة لي الخادم وانا في السعودية ولدي كمبيوتر رقم 2 ولدي برنامج يحتاج الي مسار لكي اصل الي قاعدة بيانات الموجودة في كمبيوتر رقم 1 واستطيع ان اعمل عليها وفي نفس الوقت المستخدم لكمبيوتر رقم 1 يستخدم نفس قاعدة البيانات ويكون الربط بطريقة سهلة وغير مكلفة فارجوا من يرشدني الي ذلك وجزاكم الله خير 

 اسم العضو:MarTino  الأحد,24/شوال/1428 هـ,02:23 مساءً
كلمة شكر والله قليلة ولكن لايسعني غلا ان اتوجة إلى الله عز وجل بالدعاء لك ولي ولسائر الامة الاسلامة وبصراحة حملت الامثلة لكن لن اطلع عليها الان لانني مبتدء بس بنتظر فترة وبدرسها جيداً تحياتي للأعضا الفعالين 

 اسم العضو:Eg_Casper  الخميس,20/ذو القعدة/1428 هـ,07:58 صباحاً
شكرا للأخ فادي على هذه المبادره الطيبه 

 اسم العضو:azama  الثلاثاء,09/ربيع الثاني/1429 هـ,08:19 مساءً
الاخ فادى .... لا اجد من الكلمات ما اعبر به عن امتنانى لمجهودك الرائع فى عرض هذه الدروس و اقل ما استطيعه هو الدعاء لك بان يجعل هذا العمل فى ميزان حسناتك يوم القيامة و ان يزيد من امثالك - javascript:smilie('')شكرا 

 اسم العضو:بحرالحياه  الخميس,18/رمضان/1429 هـ,05:24 مساءً
متشكره جدا بجد مجهود فعلا ربنا يجعله ف ميزان حسناتك 

 اسم العضو:pelegruso  الخميس,02/شوال/1429 هـ,10:39 مساءً
جزاك الله ألف خير على كل هدا العمل الهادف .جعله الله في ميزان حسناتك .أمين. أخي الفاضل عندي سؤال وأتمنى أن يحظى بالأهتمام من طرفكم. يتعلق الأمر بكيفية التقاط الصورة عبر الكاميرا .الشئ الدي قمتم به عند استخدامكم للمثود OncaptureDonne. هل تفضلتم بشرح عمل هده المثود والتعليق عليها خاصة هده ال statement: if( ((w & 0x03) != 0) || (w < 32) || (w > 4096) || (h < 32) || (h > 4096 وجزاكم الله خير الجزاء 

 اسم العضو:pelegruso  الأحد,05/شوال/1429 هـ,03:36 مساءً
المرجو الاجابة على استفساري.وشكرا 

 اسم العضو:KLD  الأحد,02/ذو الحجة/1429 هـ,04:02 مساءً
[ALIGN=center]بسم الله الرحمن الرحيم[/ALIGN] [ALIGN=center]شكراً لك اخي الكريم فادي على المعلومات القيمة في المستوى المتقدم وعسى الله يثبت لك الاجر. وددت ان احصل على نسخة من كتابك في المكتبات او البريد السريع.[/ALIGN] 

 اسم العضو:وليد الشيخ85  الجمعة,08/ذو القعدة/1431 هـ,12:23 مساءً
[B](emI4_prv)(emI4_prv)(emI4_prv) السلام عليكم اخ فادي ارجو المساعدة يا شباب انا نفذت المشروع ولكن يعطني البرنامج خطأ ولم اعرفه بعد وهو An unhanded exception of type System.Net.Socket.SocketException (occurred in System.dll ولم اعرف ما هو السبب وايضا" الجزء الخاص بعرض محتويات ال اين اضعه ؟؟؟ لم اجده public class Winmm Buffer ] 

 اسم العضو:وليد الشيخ85  الثلاثاء,12/ذو القعدة/1431 هـ,08:36 صباحاً
السلام عليكم اخ فادي ارجو المساعدة يا شباب انا نفذت المشروع ولكن يعطني البرنامج خطأ ولم اعرفه بعد وهو An unhanded exception of type System.Net.Socket.SocketException (occurred in System.dll ولم اعرف ما هو السبب وايضا" الجزء الخاص بعرض محتويات ال اين اضعه ؟؟؟ لم اجده public class" Winmm" Buffer (emI4_prv)(emI4_prv)(emI4_prv) 

جميع الحقوق محفوظة لـمنتديات المحيط العربي 2004 - 2021