الدرس الثالث : Connectionless Sockets Via UDP

عام 0 geek4arab
Spread the love

بسم الله الرحمن الرحيم

الدرس الثالث : 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والتنصت عليها ثم استلام الرسالة عبر هذا البورت وتوزيعها على الكل بدون تحديد رقم بورت معين حيث يتم تسليمها على البورت المخصص لعملية البرودكاست وهو البورت صفر:

لتعريف نقطة الهدف ورقم البورت الخاصة بسيرفر ونستخدمها لكي يقوم السيرفر بستلام الرسالة
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();

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

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);
   }
  }
}

الأن الجزء الخاص بال Client , يقتصر العمل هنا على قيام ال Client بفتح جلسة مع السيرفر وذلك بعد تعريفه بنقطة الإستلام ورقم البورت وكما تم في السابق اللا ان الإختلاف هو في الوظيفة اذا يقتصر فقط على استقبال الرسالة من السيرفر وارسال اي رساله له عبر البورت المخصص للقيام بهذه العملية انظر الكود التالي :

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();
	}
}

انتظرونا في الدرس القادم …

 

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

هنا البرنامج الخاص بدرس الثاني والذي يستخدم فيه بروتوكول ال TCP لنقل الصورة من جهاز Client الى Server ..

23_10_05_06_47_51_1130118471Examble.JPG

المثال :

Images Sender.zip

 

المصدر والنقاش هنا

الكاتب geek4arab

geek4arab

مواضيع متعلقة

التعليقات مغلقة