تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
[مقال] برمجة إتصال TCP عبر الشبكة المحلية
#1
شرح بالكود عن طريقة انشاء اتصال TCP بلغة الفيجول بيسك
بسم الله الرحمن الرحيم

يتميز هذا النوع من الاتصال بالمزايا التالية :
1- تكون البيانات المرسله موجهة الى شخص معين حسب الـIP الخاص به ولا يستطيع أي شخص آخر إستلامها .
2- يحتاج الى معرفة الـIP الخاص بالطرف البعيد .
3- يحتاج لبدء عملية إتصال مع الطرف البعيد قبل الشروع في نقل البيانات .
4- تصل البيانات بأمان الى المستلم بدون نقص أو تغيير .
5- لا يتميز بالسرعة .

لبدء الاتصال نحتاج لانشاء Socket جديد (الكلاس الأساسي الذي يقوم بالاتصال والارسال والاستلام) وهو موجود ضمن فضاء الاسماء System.Net.Sockets :

Dim sender As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ' l

ونبدأ الاتصال بالشكل الآتي :
sender.Connect(IPAddress.Parse("192.168.0.1"), 8001) ' l
سيبدأ الكمبيوتر بمحاولة الاتصال ولكي ينجح ذلك يجب ان يكون الطرف البعيد منتظرا لهذا الاتصال كما في الكود :
Dim reciever As New Socket(Sockets.AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ' l
reciever.Bind(New IPEndPoint(IPAddress.Any, 8001)) ' l
reciever.Listen(0) ' l
Dim someOne As Socket = reciever.Accept

السطر الاول يقوم بانشاء socket جديد.
والثاني يقوم بحجز المنفذ port .
والثالث يقوم ببدء التنصت على المنفذ المحجوز.
والرابع يستلم طلبات الاتصال ويحولها الى socket آخر جديد ليكون مختصا بهذا الاتصال.
ونلاحظ في السطر الاخير ان البرنامج يتوقف عن أي اعمال اخرى ويتفرغ فقط لانتظار الاتصال.

وبعد نجاح الاتصال يمكننا ارسال البيانات وتلقيها , والبيانات المراد ارسالها يجب ان تكون على شكل مصفوفة بايت أحادية لذا وجب تحويلها ونحن لسنا بصدد شرح ذلك الا ان النصوص يمكن تحويلها بسهولة الى بيانات ثنائية :
System.Text.Encoding.UTF8.GetBytes(stringMessage) ' l
وتحويل البايتات الى نص :
System.Text.Encoding.UTF8.GetString(byteArray) ' l
وأما ارسال الرسالة فيتم عن طريق الاجراء Send :
sender.Send(messageBytes) ' l
ويستطيع الطرف البعيد استلام الرسالة عن طريق الدالة Receive :
Dim messeageBytes(1023) As Byte
someOne.Receive(messeageBytes) ' l

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

في البرنامج التالي مثال أساسي عن كيفية الاتصال والارسال والاستلام
.rar   Ex1_Sync.rar (الحجم : 40.07 ك ب / التحميلات : 56)

وهناك طريقة أخرى جاهزة لكتابة الكود تسمى Asynchronous operation وهي لا تجعل البرنامج يتوقف بل ترسل النتيجة عند وصولها الى إجراء معين ليعالجها كما في الكود التالي :
receiver.BeginAccept(AddressOf OnAccept, receiver) ' l
حيث أن الاجراء OnAccept يقوم بمعالجة الاتصال الوارد عند وصوله والى ذلك الحين يستمر البرنامج بالعمل بشكل طبيعي , ولكن اعلم ان هذا الاجراء سوف يتم تنفيذه من مسار آخر لذلك يكون من الصعب الوصول الى ادوات الفورم بشكل طبيعي لذلك نحتاج لرفع بعض اجراءات الامان لاكمال التجربة , اكتب في حدث تحميل الفورم Form1_Load :
CheckForIllegalCrossThreadCalls = False
وأما الاجراء OnAccept فيكون شكله الاساسي هكذا :
Private Sub OnAccept(ar As IAsyncResult) ' l

   Dim receiver As Socket = ar.AsyncState
   Try
       someOne = receiver.EndAccept(ar) ' l
       Dim address As IPAddress = CType(someOne.RemoteEndPoint, IPEndPoint).Address
   Catch ex As Exception
       MsgBox(ex.Message) ' l
   End Try
End Sub

الباراميتر ar يمثل النتيجة التي حصل عليها الامر السابق BeginAccept وتحمل الخاصية ar.AsyncState المتغير receiver الذي حفظناه مع الامر السابق BeginAccept , ويعطينا الامر EndAccept الاتصال الجديد على شكل socket وان كان الاتصال فاشلا فيحدث خطأ في هذا السطر يمكن معرفة تفاصيله بواسطة تركيب Try وان كان الاتصال ناجحا نستطيع معرفة عنوان المتصل من الخاصية RemoteEndPoint كما في الكود أعلاه.
أما الامر المطول الاخر Receive فيمكن كتابته بنفس الطريقة للتخلص من حالة توقف البرنامج :
Dim messeageBytes(1023) As Byte
someOne.BeginReceive(messeageBytes, 0, messeageBytes.Length, SocketFlags.None, AddressOf OnReceive, messeageBytes) ' l
المتغير messageBytes يمثل المصفوفة المجهزة لحمل الرسالة الواردة وعند حفظ المصفوفة في الباراميتر الاخير من الامر BeginReceive سنحصل عليها مرة اخرى في الاجراء OnReceive :
Private Sub OnReceive(ar As IAsyncResult)

   Try
       Dim length As Integer = someOne.EndReceive(ar) ' l
       Dim messageBytes As Byte() = ar.AsyncState
       Dim message As String = System.Text.Encoding.UTF8.GetString(messageBytes.Take(length).ToArray) ' l
   Catch ex As Exception
       MsgBox(ex.Message) ' l
   End Try

End Sub

المتغير length يحمل طول الرسالة وياخذ قيمته من الدالة EndReceive كما كانت تفعل الدالة Receive واما الرسالة فهي محفوظة في المصفوفة messageBytes والموجودة في الخاصية ar.AsyncState والمتغير message يحفظ الرسالة بعد استقطاع الجزء المستخدم فقط وتحويله الى نص كما في الكود أعلاه.
ويتم اغلاق الاتصال عن طريق الاجراء Disconnect :
sender.Disconnect(True)
وهذا الامر ينتظر من الطرف البعيد اغلاق اتصاله بنفس الطريقة :
someOne.Disconnect(True)
يستطيع الطرف البعيد التنبؤ بان الطرف المتصل يحاول اغلاق الاتصال عندما تصل رسالة طولها صفر وهكذا يغلق كلا اتصاله عن الاخر , وهذه الطريقة في اغلاق الاتصال تسمح باستخدام نفس الـsocket مرة أخرى لتكوين إتصال جديد .
والبرنامج المرفق التالي عبارة عن تحويل من الطريقة العادية الغير عملية الى طريقة المسارات المتعددة
.rar   Ex2_Async.rar (الحجم : 41.15 ك ب / التحميلات : 55)

في الطريقتين السابقتين كان الارسال من طرف واحد والاستقبال من الطرف الاخر , ولم نجعل للطرف الاول قدرة على الاستقبال ولا للثاني قدرة على الارسال , وتوفير هذه الميزة سهل للغاية الا انني توقعت اشتباك الشرح وصعوبة الفهم في حالة شرحها دفعة واحدة . فيمكن ان يتم الارسال في نفس الوقت الذي ننتظر استلام رسالة من الطرف الاخر , أي أنه يمكن استخدام الدالة Send عندما تعمل الدالة Receive في مسار آخر محاولة استلام رسالة , وفي حال قيام كلا الطرفين بالارسال والتنصت في نفس الوقت يصبح التخاطب أكثر سهولة وفاعلية .

في جميع الحالات السابقة كان التخاطب بين طرفين لا اكثر وهذا هو أساس بروتوكول TCP فهو موجه الى شخص معين كما أسلفنا لكن مع ذلك يمكننا الالتفاف على هذه النقطة وايجاد حلول للتواصل مع اكثر من شخصين في نفس الوقت , وهناك طريقتين أساسيتين لهذا للتواصل :
الاولى : Peer to peer : أساس هذه الطريقة أن كل شخص اذا اراد ارسال بيانات عليه ان يرسلها الى جميع المتصلين واذا ارادوا بدورهم الرد عليه فعلى كل واحد منهم ان يرد عليه على حده .
الثانية : Client-Server : في هذه الطريقة يتحمل احد الاشخاص مسؤوليات خاصة يدعى السيرفر واذا اراد شخص ارسال بيانات يرسلها الى السيرفر الذي يقوم بنشرها وارسالها الى جميع المتصلين .

البرنامج التالي هو عبارة عن برنامج محادثة صغير يعتمد طريقة client-server ويستخدم الأوامر غير المتزامنة Asynchronous مثل BeginAccept ويستخدم أيضا مسار تنفيذ جديد لانتظار الرسائل الواردة
.rar   Ex3_Chat.rar (الحجم : 46.01 ك ب / التحميلات : 94)

أتمنى أن يكون الشرح وافياً

<يعطيك العافية>
الرد
تم الشكر بواسطة: Amir_Alzubidy , sendbad100 , sendbad100 , tryold , dubai.eig , dubai.eig , asemshahen5
#2
جزاك الله خير
حلو تطبيق هذه الفكرة في مختبرات الحاسوب ، و بالتالي نظام مراسلة ذو كفاءة .
وَقُل رَّبِّ اغْفِرْ وَارْحَمْ وَأَنتَ خَيْرُ الرَّاحِمِينَ
الرد
تم الشكر بواسطة: Fantastico



التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم