fmo_82

سلسلة دروس C# Network Programming

237 ردود في هذا الموضوع

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

الدرس الثاني عشر: 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 من التنفيذ وهي كما يلي:

205005746.jpg

1- BeginAccept و تستخدم لقبول ال Client Request وإسناده إلى الObject AsyncCallback وباستخدام هذه الطريقة سوف يتمكن ال Server من استقبال عدد من ال Clients Requests في نفس الوقت وبدون الحاجة لانتظار الانتهاء من العملية الجارية حيث يتم في كل مرة استدعاء الميثود باستخدام ال AsyncCallback Delegate وتستخدم كما يلي كما يلي:

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

حيث سيتم إضافة ال Client Request فيReference Callback منفصل عن السابق وهنا لابد من إنشاء method لاستقبال ال Client Request وإنهاء ال Client Accepted Object باستخدام الميثود EndAccept :

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

في Dot Net 2005 أصبحت ال BeginAccept Method تأخذ عدة أشكال كما يلي:

الشكل الأول في الدوت نيت 2003 و 2005 وتأخذ AsyncCallBack Delegate و State Object لإرجاع معلومات عن حالة ال Request في ال Socket وكما يلي:

MySocket.BeginAccept(AsyncCallback , object state)

الشكل الثاني في الدوت نيت 2005 حيث يمكنك فيه تحديد حجم البيانات المستلمة

MySocket.BeginAccept(int Data_ Receive_Size , AsyncCallback , object state)

الشكل الثالث في الدوت نيت 2005 حيث بمكن فيه تحديد ال Accepted Socket

MySocket.BeginAccept(Socket accept_Socket ,int Data_ Receive_Size , AsyncCallback , object state)

2- BeginConnect وتستخدم لبدأ Asynchronous Connection على ال Socket ورقم البورت المحدد حيث يسند لها ال IPEndPoint وال Asynchronous Callback وال State Object وكما يلي:

MySocket.BeginConnect(EndPoint IP,Syncallback Result,object state)

وتستخدم كما يلي كمثال:

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

في ال Connected Method يتم تحديد ال CallBack Socket كما يلي:

        public static void Connected(IAsyncResult iar)
       {
           Socket sock = (Socket)iar.AsyncState;
           try
           {
               sock.EndConnect(iar);
           }
           catch (SocketException)
           {
               Console.WriteLine("Unable to connect to host");
           }}

3- BeginReceive وتستخدم لإستقبال بيانات من ال Client وتخزينها في Byte Array والصيغة العامة لها كما يلي:

MySocket.BeginReceive(Byte[] buffer,int offset, SocketFlags,AsyncCallback, object sate)

ويستخدم كما يلي كمثال:

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

كما تستخدم الميثود BeginReceiveFrom لإستقبال البيانات من موقع محدد باستخدام ال UDP حيث يضاف إلى التركيب السابق IPEndPoint Refrance Object .

4- BeginSend وتستخدم لإرسال بيانات إلى الطرف المستقبل عبر ال Asynchronous Socket والصيغة العامة لها كما يلي:

MySocket.BeginSend (Byte[] buffer,int offset, SocketFlags,AsyncCallback, object sate)

وتستخدم كما يلي كمثال:

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

كما تستخدم الميثود BeginSendto لإرسال البيانات إلى Remote Host محدد باستخدام ال UDP حيث يضاف إلى التركيب السابق IPEndPoint Refrance Object .

5- كما تم إضافة مجموعة من الميثود الجديدة في الدوت نيت 2005 وهي:

BegonDiconnect لإنهاء الاتصال و BeginSendFile لإرسال ملف و ال BeginReceiveMessageFrom والتي تستخدم لإستقبال عدد محدد من البيانات وتخزينها في مكان محدد في ال Bufer ..

التركيب التالي:BeginSendFile تأخذ ال

MySocket.BeginSendFile(string filename,AsyncCallback Asyn,object state)

وال BeginReceiveMessageFrom التركيب التالي:

MySocket.BeginReceiveMessageFrom(byte Buffer ,int offset,int size,SocketFlags sf,ref EndPoint,AsyncCallback ascb,object state)

وال BegonDiconnect التركيب التالي:

MySocket.BeginDisconnect(bool reuseSocket,AsyncCallback ascb,object state)

ثانيا: تطبيقات ال 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 في البرنامج وهو ما ميز الاتصال الغير متزامن عن الاتصال المتزامن.

205002690.jpg

وبناء على المفاهيم السابقة سوف نقوم الآن بإنشاء برنامج Client/Server Chatting يعتمد على ال Asynchronous Socket لإرسال واستقبال البيانات .

وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي:

205052218.jpg

سوف نستخدم ال Namespaces التالية:

using System.Net;
using System.Net.Sockets;
using System.Text;

في ال Global Declaration (أي بعد تعريف ال Main Class)قم بإضافة التعاريف التالية:

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;

في ال Form Load قم بإضافة الكود التالي حيث سنعرف Connection يعتمد على ال TCP ويعمل على البورت 5020 ثم تعريف عملية قبول الاتصال باستخدام ال BeginAccept :

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

ثم إنشاء Accept Callback Method والذي سيتم فيه إنهاء ال Accepted Request باستخدام ال EndAccept Method وبعد ذلك إرسال Acknowledgement إلى ال Client تخبره فيها بقبول الطلب وترسل باستخدام ال BeginSend Method كما يلي:

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

ثم إنشاء Send Callback method لإنهاء ال BeginSend وكما يلي:

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

ثم إنشاء Receive Callback method لإنهاء ال BeginReceive وكما يلي:

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

وهنا قد تم الانتهاء من برنامج ال Server والآن سوف نقوم بإنشاء برنامج ال Client وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي:

205063440.jpg

سوف نستخدم ال Namespaces التالية:

using System.Net;
using System.Net.Sockets;
using System.Text;

في ال Global Declaration (أي بعد تعريف ال Main Class)قم بإضافة التعاريف التالية:

public class Form1 : System.Windows.Forms.Form
{
private Socket client;
private byte[] data = new byte[1024];
private int size = 1024;  

في ال Connect Button قم بكتابة الكود التالي:

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

ثم قم بإنشاء Callback Connect method كما يلي:

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

ثم إنشاء Receive Callback method لإنهاء ال BeginReceive وكما يلي:

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

ثم إضافة الكود التالي في ال Send Button :

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

}

ثم إنشاء Receive Callback method لإنهاء ال BeginReceive وكما يلي:

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

وكما لاحظنا فإن برنامج ال Client لا يختلف كثيرا عن برنامج ال Server حيث نعرف في ال Server ال Socket Connection وال BeginAccept Method أما في ال Client فنعرف ال Socket Connection و ال BeginConnect Method وتبقى عملية الإرسال والاستقبال هي نفسها في Server وال Client ...

L12_Asynchronous_Sockets.rar

Asynchronous_Example.rar

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

وهنا قد تم الانتهاء من الجزء الثاني وفي الجزء الثالث من هذه السلسلة سوف نتحدث ال Multicasting بشكل أكثر تفصيلا كما سوف نتحدث Network Security Programming والتي تضم ال Cryptographyوال Authentication Protocols

304092983.jpg

لتحميل ال Chapter 2 ثلاثة دروس :

C__Network_Programming_Chapter2.rar

تم تعديل بواسطه fmo_82
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم ورحمة الله وبركاته

أخي fmo_82 جزاك الله خير في الحقيقة دروس رائعة وبالفعل تستحق التثبيت قد قرأت الكثير منها وأنا بانتظار انتهاء فترة الاختبارات في الجامعة حتى أتفرغ لدراستها والاستفادة من خبرتك وأسأل الله أن لا يحرمك الأجر والثواب وأن يجازيك على هذا العمل خير الجزاء

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بسم الله الرحمن الرحيم , يعتبر هذا الدرس واحد من أهم الدروس التي عرضناها سابقا إذ سوف نتعلم فيه كيفية بناء أنظمة متقدمة مثل ال 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 .

وتم تخصيص ال 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 انظر الرابط التالي:

http://www.iana.org/assignments/multicast-addresses

يتم نقل ال 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.

وكما كان الحال في الإرسال باستخدام ال 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 وكما في الشكل التالي:

1OnetoGroup.JPG

- الإرسال إلى أكثر من مجموعة One to Multi-Groups:

وفيه قد يكون ال IP Multicasting لل User Sender مختلف عن Receiver Users ويتم الإرسال من User داخل ال Group إلى المجموعة الذي هو عضو منها وإلى مجموعات أخرى , ويتم تحديدها باستخدام Address List للمجموعات التي نريد الإرسال لها ...

2OnetoMGroup.JPG

ثانيا :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 الذي سوف ننضم إليه وكما يلي:

UdpClient sock = new UdpClient(9050); 
sock.JoinMulticastGroup(IPAddress.Parse("225.100.0.1"), 50);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0);

وكما يلي لإلغاء عملية الانضمام من مجموعة:

sock.DropMulticastGroup(IPAddress.Parse("225.100.0.1"));

إذ تستخدم الMethods JoinMulticastGroup و DropMulticastGroup لضم أو إلغاء عنوان أو مجموعة من العناوين من ال Multicast Group , وباستخدام Class MulticastOption: يمكننا تخزين IP Address List لتعامل معها في Multicast Group لعمل Join و Drop لأي Multicast Group وتستخدم كما يلي كمثال لإضافة عضوية لاستقبال رسائل Multicast :

أولا نعرف ال UDP Socket وكما يلي :

mcastSocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,
ProtocolType.Udp);

ثانيا نقوم بتعريف Address List ثم نسند إليها ال IP الذي نريد إدخاله في ال Group أو نجعل ال User يدخل العنوان بنفسه نربطها بالسكوت باستخدام الميثود Bind وكما يلي :

IPAddress localIPAddr = IPAddress.Parse(Console.ReadLine());
mcastSocket.Bind(IPlocal);

ثالثا نقوم بتعريف ال Multicast Option ونسند لها العنوان المحدد كما يلي:

MulticastOption mcastOption;
mcastOption = new MulticastOption(localIPAddr);

ومن ثم نضيف التغير على SetSocketOption حيث تأخذ هذه الميثود ثلاثة باروميترات الأول لتحديد مستوى التغيير على IP أو على IPv6 أو على Socket أو TCP أو UDP وفي حالتنا هذه سوف نستخدم التغير على IP إذ ما نريده هو ضم IP إلى Multicast Group وفي الباروميتر الثاني نحدد نوع التغيير حيث نريد إضافة عضوية ويمكن الاختيار بين إضافة عضويه AddMembership أو إلغاء عضوية DropMembership وأخيرا نسند إليه ال MulticastOption Object والذي قمنا بإنشائه و كما يلي:

mcastSocket.SetSocketOption(SocketOptionLevel.IP,  SocketOptionName.AddMembership,mcastOption);

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 وكما يلي لإرسال رسالة نصية:

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

ولإرسال Binary Data كإرسال صورة مثلا لابد من استخدام ال Memory Stream لتخزين الصورة في الذاكرة على هيئة Stream ثم تحويلها إلى Byte Array وبعد ذلك إرسالها باستخدام ال sendto Method وكما يلي:

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

3- الاستقبال من مجموعة Receiving Data From a Multicast Group:

حتى نستطيع الاستقبال من مجموعة لابد أولا من تحديد ال IP Multicast الخاص بالمجموعة و الانضمام إليه ثم استقبال البيانات باستخدام ال Receive Method ويتم ذلك كما يلي لاستقبال رسالة نصية وعرضها في list Box:

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

ولاستقبال صورة نستخدم ال memory Stream لاستقبال البيانات من ال Receive Method وتخزينها في الذاكرة على هيئة Stream Data ثم تحويلها إلى صورة مرة أخرى باستخدام ال image.FromStream Method وكما يلي:

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

ملاحظات هامة في استخدام ال 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 ...

سوف نقوم هنا بتقسيم نظام المؤتمرات إلى ثلاثة أنظمة رئيسية وهي نظام مؤتمرات الفيديو ونظام مؤتمرات سطح المكتب ونظام المؤتمرات النصية, في البداية سوف نقوم بعمل الشاشة الرئيسية للبرنامج و كما في الشكل التالي:

p0.JPG

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 إلى المشروع وكما يلي:

P1.JPG

وحتى نتعامل معها سوف نستدعيها باستخدام :

using DShowNET;
using DShowNET.Device;

وسيكون شكل برنامج الإرسال عبر الكاميرا كما في الشكل التالي:

p2.JPG

سوف نستخدم ال DeviceSelector Class لإختيار جهاز الإدخال عند بداية تشغيل البرنامج وكما يلي:

DeviceSelector selector = new DeviceSelector( capDevices );
selector.ShowDialog( this );
dev = selector.SelectedDevice;

و لإلتاط الصورة عبر الكاميرا سوف نقوم بإنشاء method جديدة كما يلي :

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

ثم عمل Timer وإضافة الكود التالي فيه لاستمرار عملية التقاط الصورة:

int hr;
int size = videoInfoHeader.BmiHeader.ImageSize;
savedArray = new byte[ size + 64000 ];

ولإرسال الصورة إلى الطرف الأخر سوف نستخدم method إرسال الصورة ونضعه في Timer وكما يلي:

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

وهنا يستطيع المحاضر إرسال الصورة عبر الكاميرا إلى طلابه كما سوف يتمكن من رؤية طلابه عبر الكاميرا وسوف نفترض هنا استخدامه لشبكة لا سلكية حيث سيرسل البيانات إلى ال Access Point بأسلوب ال Unicast وسوف يتولا ال Access Point توزيع البيانات إلى جميع الأعضاء المنضمين إلى ال Multicast Group ويرسلها لهم باستخدام ال Broadcast وكما في الشكل التالي:

3VCS.JPG

وكما نلاحظ في الشكل السابق فإن المحاضر ينضم إلى مجموعتين مجموعة الأساتذة وهي 225.100.1.1 حيث سيستقبل صورة طلابه عليها, ومجموعة الطلاب 224.100.0.1 والتي سوف يرسل الصورة إليها .. وكما نلاحظ ايضا فإن عملية الإرسال بين ال Access Point1 وال Access Point2 تتم باستخدام ال Unicast ...

وحتى يستطيع الطلاب رؤية أستاذهم والأستاذ رؤية طلابه , لابد من إنشاء برنامج الاستقبال حيث سنستخدم نفس ال method التي شرحنها سابقا لاستقبال الصورة وللبدء قم بعمل New Form جديد كما في الشكل التالي:

p3.JPG

سوف نستخدم ال Namespaces التالية لاستقبال الصورة من ال Multicast Group :

using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;

ثم قم بكتابة method الاستقبال كما يلي:

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

وحتى نستدعيها لابد من استخدام ال Threading حتى لا يتأثر نظام التشغيل بعملية الاستقبال , وحتى نقوم بذلك قم بعمل Timer وضع فيه الكود التالي لاستخدام ال Threading :

Thread myth;
myth= new Thread  (new System.Threading .ThreadStart(Image_Receiver));
 myth.Start ();

وحتى تتمكن من تخزين الصورة الملتقطة عبر الكاميرا على هيئة JPEG Image File قم بإنشاء saveFileDialog واستدعيه كما يلي:

try
{
 
saveFileDialog1.Filter = "JPEG Image (*.jpg)|*.jpg";
if(saveFileDialog1.ShowDialog() == DialogResult.OK)
 {

string mypic_path = saveFileDialog1.FileName;
pictureBox1.Image.Save(mypic_path);
 }
}
catch (Exception){}

وهنا قد تم الانتهاء من المشروع الأول وهو ال Video Conference System , وحتى يستطيع المحاضر عرض المحاضرة باستخدام برنامج ال Power Point سوف نقوم بعمل مشروع مؤتمرات سطح المكتب ...

2- Full/Half Duplex Multicast Desktop Conferencing System:

الهدف من هذا المشروع هو تمكين الأستاذ من عرض المحاضرة باستخدام برنامج ال Power Point حيث سترسل صورة سطح المكتب من جهاز الأستاذ إلى أجهزة الطلبة , ولا تختلف عملية الإرسال عن البرنامج السابق في شيء سوى إنشاء Classes لتقوم بالتقاط صورة سطح المكتب ومن ثم إرسالها إلى ال Multicast Group ومن ثم استقبالها وعرضها على الطلاب باستخدام Data Show Projector ...

وهنا مخطط عمل البرنامج

4DCS.JPG

وكما نلاحظ من الشكل التالي فإن الأستاذ يقوم بشرح المحاضرة على جهازه الشخصي ويرسل الصورة إلى الطلاب وكما نلاحظ أيضا فإن هذه العملية هي أحادية الاتجاه وكما يمكن جعلها باتجاهين Full || Half Duplex لكن لابد من إنشاء مجموعة جديدة لعملية الإرسال من الطالب إلى الأستاذ حيث يعرض الأستاذ محاضرته ويرسلها إلى مجموعة الطلاب ويستطيع أحد الطلاب عرض جهازه على الأستاذ إذ يرسل الصورة إلى مجموعة الأستاذ ...

ولإنشاء برنامج إرسال صورة سطح المكتب قم بعمل New Form جديد كما في الشكل التالي:

p4.JPG

في البداية سوف نقوم بعمل Three Classes لالتقاط صورة سطح المكتب وكما يلي:

أولا PlatFormInvokeGDI32.cs لالتقاط صورة سطح المكتب باستخدام ال GDI+ وال API:

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

ثانيا PlatformInvokeUSER32.cs إذ سوف نستخدمها مع ال Class السابق لالتقاط صورة سطح المكتب باستخدام ال user32 API :

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

ثالثا: CaptureScreen.cs والتي سوف نستخدمها بشكل مباشر في البرنامج حيث يتعامل مع الClass PlatFormInvokeGDI32 وال PlatformInvokeUSER32 Class :

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

وحتى نستطيع التحكم في حجم الصورة سوف نكتب ال method التالية:

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

سوف نستخدم ال Namespaces التالية في البرنامج لتعامل مع ال Multicasting :

using System.Net;
using System.Net.Sockets;
using System.IO;

ثم نقوم بعمل Timer لالتقاط صورة سطح المكتب و إرسالها إلى ال Multicast Group المحدد :

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

3- Full/Half Duplex Multicast Text Conferencing System:

وحتى يستطيع الطلبة التحدث إلى الأستاذ باستخدام ال Text Chat Multicast Conference System سوف نقوم بإنشاء New Form جديد وكما في الشكل التالي:

p5.JPG

ثم قم بإضافة ال Namespaces التالية:

using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

سوف نستخدم ال method التالية لإجراء عملية الإرسال حيث سترسل الرسالة عند الضغط على ال Enter بعد كتابة الرسالة في ال Textbox المخصص :

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

وسوف نستخدم الميثود التالية لعملية الاستقبال حيث ستعرض الرسالة المستقبلة في list Box مخصص:

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

ولاستدعائها لابد من استخدام ال Threading , قم بعمل Timer واستدعي فيه ال method السابقة باستخدام ال Thread وكما يلي:

Thread myth;	
myth= new Thread  (new System.Threading .ThreadStart(server));
myth.Start ();

سوف نشغل ال Timer عند الضغط على زر الاتصال باستخدام timer1.Enabled = true وفي زر إنهاء الاتصال قم بإضافة الكود التالي:

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

وهنا قد تم الانتهاء من الدرس الثالث عشر وفي الدرس التالي سوف نتحدث عن ال Network Security Programming وأساليب تشفير وحماية البيانات واستخدامها في برمجيات الشبكات ... :rolleyes:

لتحميل الدرس ونظام المؤتمرات انظر المرفقات :

L13_Advanced_Multicasting_System.rar

Multicast_Conference_System.rar

تم تعديل بواسطه fmo_82
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ما شاء الله تبارك الله .

أخي فادي جهد مشكور ، و إلمام كامل بالمادة العلمية .

بارك الله لك في عملك ، وجزاك عنا خير الجزاء .

بالمناسبة ، هل عندك خلفية عن دوال المكتبة Packet.dll ؟

تم تعديل بواسطه MSVS
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اشكرك اخي MSVS على تشجيعك ودعمك ,

بانسبة لدوال ال Packet.dll فيوجد شرح جيد لها في الرابط التالي :

http://www.codeproject.com/csharp/pacanal.asp

واهلا وسهلا بك :)

تم تعديل بواسطه fmo_82
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بارك الله فيك استاذ فادي وشكرا على المجهود الجبار

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم ورحمة الله وبركاته

بجد والله أنت فنان ، فجزاك الله خيرا

وعلى كل حال أصبر عليا كلها أيام قلائل وأتفرغ للشبكات والمهم متتعبش مني من كثرة الأسئلة :D

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الأخ arsin_lopin و mamoud اشكر لكم تشجيعكم وبارك الله بكم :)

الأخ احمد مشكور على التشجيع وإن شاء الله تتفرغ حتى نتعاون لتطوير السلسلة :rolleyes:

واهلا وسهلا بكم :)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم ورحمة الله

الأخ فادى ، مجهودك أكثر من رائع ويستحق التقدير ، جزاك الله خيرا

ان شاء الله سأواصل دروسك بعد انتهاء الامتحانات

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

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

الدرس الرابع عشر: Network Security Programming:

تتلخص الفكرة من الأمن بحماية البيانات من الدخول غبر المخول unauthorized Access

باستخدام عدة أساليب وأهمها :

-Data Encryption & Decryption التشفير وفك التشفير

-Authentications التحقق من هوية الشخص مرسل الرسالة

-Set Policies & Permissions تحديد وتنفيذ السياسات و الصلاحيات

دعمت في الدوت نيت جميع أساليب الحماية التي ذكرناها سابقا باستخدام ال Security Namespaces والتي تحتوي على مجموعة ضخمة من المكتبات الفرعية وهي كما في الشكل التالي

0.JPG

أولا : 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 ...

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

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;

في برمجيات الشبكات نقوم في البداية بتشفير البيانات المرسلة باستخدام أي من الأساليب السابقة لتشفير ثم نحول البيانات المشفرة إلى Stream لإرسالها عبر ال Socket باستخدام ال Network Stream , ثم يقوم الطرف المستقبل باستقبال الرسالة باستخدام ال Network Stream عبر ال Socket , عملية فك التشفير تكون كما هي الخوارزمية المستخدمة ثم تحمل الرسالة إلى ال memory stream وتخزن في Byte Array عندها يمكن أن تحول إلى رسالة مرة أخرى وكما في الشكل التالي:

DE.JPG

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

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

- RSACryptoServiceProvider

ويستخدم في إجراء التشفير وفك التشفير الغير متماثل وهو non inherited Class في البداية سوف ننشئ instance جديد من ال RSACryptoServiceProvider وذلك لتوليد المفتاح العام والخاص ونرفق المفتاح العام مع الرسالة ومن ثم يقوم المستلم بفك الرسالة باستخدام المفتاح الخاص وتتم كما في الشكل التالي:

encryp.jpg

وهنا مثال توضيحي لطريقة التشفير وفك التشفير باستخدام ال RSA Algorithm :

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

ننشئ الميثود التي ستقوم بتشفير الرسالة:

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

ننشئ الميثود التي ستقوم بفك تشفير الرسالة:

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

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 وكما يلي كمثال:

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

ثانيا: 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 المستخدم.

[SocketPermission(SecurityAction.Deny, Access="Connect", Host="127.0.0.1",Port="All", Transport="All")]

يمكننا ال object SecurityAction من تحديد نوع العملية التي نريدها وكما يلي:

permission.JPG

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 إذ تستطيع تحديده مباشرة.

------------------------------------------------------------------------------------------------

ملاحظة : لم اتمكن من رفع الدرس على PDF File و الأمثلة , ربما بسبب خلل ما مؤقت في المنتدى

-------------------------------------------------------------------------------------------------

سيكون الدرس التالي حسب طلب الأعضاء

تستطيع تحميل كامل السلسلة على PDF File بحجم 162 صفحة مع دعم ال VB.NET وال C# رابط التحميل

تم تعديل بواسطه fmo_82
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم

أخي الفاضل : فادي ,,, لك جزيل الشكر و الإمتنان على هذه الدروس الراااائعه و على نفسك الطيبه و الكريمه المعطائه

لي طلب ألا وهو : أتمنى أن يكون الدرس القادم عن كيفية إرسال الصوت من الClient إلى ال Server ؟؟؟

مثلاً في برنامج زي الماسنجر !!

لك جزيل الشكر ,,, أطيب المُنى

أخوك : الوفي دومـاً

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

إن شاء الله سيكون هذا هو الدرس التالي وقد احتاج بعض الوقت لتجهيزه لما فيه من تعقيد بعض الشيء لكن إن شاء الله سأحاول تيسيره قدر الإمكان , تستطيع الرجوع إلى المشاركة التالية مؤقتا إلى حين الإنتهاء من اعداد الدرس

http://www.arabmoheet.net/forum/default.as...e=3entry22079

واهلا وسهلا بك

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم ورحمة الله وبركاته

بداية أشكر الأخ الفاضل فادي على هذا الجهد الرائع

بدأت دراسة الموضوع، عندي في البيت جهازين كمبيوتر وضعت على كل جهاز كرت شبكة وقمت بتأسيس الشبكة وقمت بتجربة برنامج إرسال الصور ولكن واجهت المشاكل التالية:

في البداية كنت أضع عنوان الجهاز المستقبل server بدلا من localhost

فكانت تظهر هذه المشاكل

25_02_06_08_58_47_1140886727robot.JPG

ولكن شغلت برنامج client مرة أخرى على الجهاز الآخر وطبعا شغلت server على الجهاز المقابل فظهرت ارسالة التالية

25_02_06_09_03_36_1140887016server.JPG

ولكم مني جزيل الشكر

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اخي electronics حاول التأكد من الأمور التالية:

1- قم بعمل ping بين الجهازين وتأكد ان كل منهما يمكنه الوصول الى الأخر ( ping 192.16.25.12 )

2- تأكد من انك تستطيع الوصول إلى ملفات الجهاز المقابل وذلك بتفعيل الـ Guest User ثم عمل Share لأحد المجلدات

3- هل تستخدم Firewall إذا كان اجابتك نعم فقم بفتح البورت الذي يتم استخدامه في البرنامج وهي 5020 من الـ Firewall

بتوفيق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم ورحمة الله وبركاته

أخي فادي

بالنسبة لـ ping تعمل

ولكن لم أقم بتفعيل Guest User ولكن أستطيع نقل الملفات بين الجهازين

وقمت بإطفاء الـ fire wall

ولكن لا نتيجة

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

حاولت تشغيل البرنامج على أحد مختبرات الجامعة لدينا وظهرت لي الرسالة التالية

26_02_06_03_09_27_1140952167untitled.JPG

مع العلم أن الأجهزة لا تملك Real IP Address

ولكم جزيل الشكر

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

طلعت مشكلة الجامعة هي الـ Fire Wall وبعد ما أوقفته اشتغل البرنامج

بس بقي مشكلة البيت الله يسر وتشتغل

وجزاك الله كل خير أخي فادي

والسلام عليكم ورحمة الله وبركاته

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم ورحمة الله وبركاته

حاولت إعادة كتابة برنامج نقل الصور باستخدام UDP ولكن لم تنجح المحاولة

هذا الكود

إذا فيه غلط أرجو إخباري

الجزء الخاص بالـ Server

public void WaitFrom()
 {
 int recv;
 IPEndPoint ipep = new IPEndPoint(IPAddress.Any,5000);
 news = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
 news.Bind(ipep);
 IPEndPoint sender = new IPEndPoint(IPAddress.Any,0);
 EndPoint remote = (EndPoint)(sender);
 while ( true)
 {
   byte [] bb = new byte [900000];
   recv = news.ReceiveFrom(bb,ref remote);
   MemoryStream m = new MemoryStream(bb);
   m.Close();
   pictureBox1.Image= Image.FromStream(m);
 }
   

 }

الجزء الخاص ب client

private void button1_Click(object sender, System.EventArgs e)
 {
 try
 {
   openFileDialog1.ShowDialog();
   Path = openFileDialog1.FileName;
   pictureBox1.Image=Image.FromFile(Path);
   MemoryStream m = new MemoryStream();
   Image img=pictureBox1.Image;
   img.Save(m,img.RawFormat);
               m.Close();
   byte [] bb = m.GetBuffer();
   // Create Connection
   IPEndPoint ipep = new IPEndPoint( IPAddress.Parse("192.16.25.12"),5000);
   Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
   server.SendTo(bb,ipep);
   server.Close();

 }

 catch {}

 }

أرجو المساعدة ولكم جزيل الشكر

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الخطأ في الكود الخاص بالسيرفر ...

أنت قمت بعمل binding لل socket على بورت معين >>> قم باستقبال ال Data على هذا البورت

recv = news.ReceiveFrom(bb,ref remote); // Wrong
recv = news.Receive(bb); // Right

أيضا لا داعي لهذين السطرين :

IPEndPoint sender = new IPEndPoint(IPAddress.Any,0);                    // why Zero?!!!!
EndPoint remote = (EndPoint)(sender);

فالمشكلة أخي الكريم أنك تقوم باستقبال ال Data دون ان تحدد البورت

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

أخي baha_ashour أشكرك على الرد ولكن للأسف ما زال البرنامج لا يعمل

لقد ألحقت المشروعين النظر فيها عسى أن يكون هناك خطأ آخر قد غفلت عنه

وجزاكم الله خيرا

والسلام عليكم ورحمة الله وبركاته

UDP_Image_Sender_Server.rar

UDP_ImageSender_Client.rar

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

المشكلة الآن ... أنك تقوم بأغلاق ال MemoryStream في السيرفر

حيث أنه لا تستطيع تحويلها الى Image اذا كانت مغلقة ...

MemoryStream m = new MemoryStream(bb);
//m.Close();      ====>  DON'T CLOSE IT
pictureBox1.Image= Image.FromStream(m);

اذا أردت المزيد عن نقل الصور باستخدام ال UDP :

Desktop Monitoring

تم تعديل بواسطه baha_ashour
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
بسم الله الرحمن الرحيم ,

الدرس الثاني : الجزء الأول

قمنا سابقا بتعرف على أجزاء OSI و TCP/IP وبينا كيفية التعامل مع هذه الطبقات في البرنامج , واليوم سوف اشرح بعون الله كيفية التعامل مع Socket بشكل أكثر تفصيلا بالإضافة إلى استخدام ال Thread في برمجيات الشبكة ..

أولا : ال Socket : قلنا سابقا أن السوكت هي الأداة التي يتم نقل البيانات من خلالها من جهاز إلى أخر ولاستخدامها يلزم في البداية تعريف النيم سبيس System.Net.Sockets  حيث يحتوي هذا النيم سبيس على عدد ضخم من الكلاسس والتي يتم استخدامها في برمجيات الشبكة , انظر الرابط التالي لتعرف على جميع المكونات في التفصيل :

http://msdn.microsoft.com/library/default....mnetsockets.asp

و الرابط التالي لتعرف على مكونات System.Net بتفصيل:

http://msdn.microsoft.com/library/default....rfsystemnet.asp

يمكنك السوكت من نقل Text او Object ,حيث بينا سابقا كيفية التعامل من السوكت لنقل Text وفي هذا الدرس سنبين كيفية التعامل معه لنقل Object , وكما هو الحال في نقل ال Text كنا نحول التكست الى اسكي ثم الى باينري اما في الأبجكت فيتم التعامل معه باستخدام ال Stream Library  والتي يتم الوصول اليها من System.IO  وتحتوي هذه المكتبة على Binary Reader  و Binary Writer تمكنك من التعامل مع أي Object انظر الصورة المرفقة :

21_10_05_07_33_20_1129905200ObjectLib.jpg

حيث تساعدك  هذه المكتبة على تحويل أي اوبجكت إلى باينري باستخدام Binary Reader لتسهل إرساله عبر الشبكة باستخدام Network Stream ثم تحويله مرة أخرى إلى اوبجكت باستخدام Binary Writer , وكمثال تطبيقي على هذا سوف نقوم ببناء برنامج يقوم بعملية نقل الصورة من جهاز إلى أخر Client/Server وللبدء قم بإنشاء New Form  جديد كما هو في الشكل التالي :

21_10_05_07_35_14_1129905314form1.JPG

في البداية قم بإضافة النيم سبيسس التالي : 

using System.Net.Sockets;
using System.IO;

للإجراء عملية الإرسال لا بد أولا من اخذ اوبجك من الكلاس MemoryStream والتي سوف نستخدمها لتخزين الصورة داخل الذاكرة بشكل Stream لكي نحولها لاحقا إلى مصفوفة Binary  ثم إرسالها عبر NetworkStream إلى جهاز السيرفر والذي سأتي على شرحه في الجزأ الثاني من هذا الدرس, انظر الكود التالية :

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

لدي سؤال : التعليقات التي تستخدم في البرامج في أي لغة بنوعيها وحيدة السطر ومتعددة الأسطر ما هي فوائدها وأضرارها ؟

// or /*

*/

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .