2006 أحترف برمجة الشبكات والنظم الموزعة (النسخة الورقية الكاملة ( 2006 اإلصدار SocketCoder.COM
|
|
- نسيب النمري
- منذ 4 سنوات سابقة
- المشاهدات:
النسخ
1 2006 أحترف برمجة الشبكات والنظم الموزعة (النسخة الورقية الكاملة ( 2006 اإلصدار SocketCoder.COM
2 الرخصة وحقوق النشر :SCPL SocketCoder Public License 1 تسمى ھذه الرخصة SCPL SocketCoder Public License وقيامك بتحميل أو استخدام أي منتج من منتجات SocketCoder.Com يعتبر موافقة مسبقة من قبلك بااللتزام بتعليمات ھذه الرخصة. 2 ال يوجد أي شروط تقيد عملية توزيع المنتجات الخاضعة لھذه الرخصة الكترونيا سواء من خالل البريد اإللكتروني أو المنتديات أو مواقع اإلنترنت بشرط ذكر المصدر ووضع الرابط الرئيسي للمنتج. 3 تعتبر جميع المشاريع والمكتبات واألكواد والوثائق الخاضعة لھذه الرخصة مجانية بالكامل لألھداف التعليمية فقط لذلك ال يمكنك استخدامھا بشكل تجاري دون إذن وموافقة من الناشر. 4 أبتدء من تاريخ 2009/11/31 تم أخضاع كتاب (احترف برمجة الشبكات والنظم الموزعة بالدوت نيت 2006) إلى رخصة SCPL وبذلك سيكون كل مافي الكتاب مجاني بالكامل بشكل ألكتروني وبذلك ال يحق لك بيعه أو بيع جزء منه أو إعادة طباعته بھدف بيعه بشكل ورقي كذلك ال يحق لك اقتباس أي جزء منه دون مراسلة الناشر ببيان رغبتك بذلك وذكر المصدر بشكل التالي (احترف برمجة الشبكات والنظم الموزعة بالدوت نيت 2006 فادي عبد القادر الناشر (SocketCoder.Com ~2~
3 حول المؤلف: Fadi M. Abdelqader Systems Engineer & Developer المؤلفات الورقية حتى (2009): - Professional Network, Distributed Systems & TCP/IP Programming In.NET Framework 1.1 & 2.0 (2006 Release). أھم المؤلفات اإللكترونية المجانية حتى (2009): - The SocketCoder e-reference For Network, Distributed Systems And TCP/IP Programming In.NET 3.5, Arabic (SocketCoder.Com 2009) أھم األبحاث و المشاريع المجانية المفتوحة المصدر لألھداف التعليمية إلى (2009): - (SocketCoder) RTP Multicasting VOIP Library (June-2008) - (SocketCoder) Remote Desktop Controlling System (June ) - Large set of SCOL (SocketCoder Open License) learning Samples in network programming, conferencing, security & E-Learning Check ~3~
4 المقدمة: يناقش ھذا الكتاب معظم األمور المتعلقة ببرمجة الشبكات باستخدام لغات الدوت نيت بأسلوب سلس وبسيط إذ ينتقل بك من المستوى المبتدئ إلى المتوسط إلى المتقدم بأسلوب جميل وممتع و يبدأ الكتاب بمقدمة عامة عن TCP/IP Models وتطبيقات Client/Server باستخدام لغات الدوت نيت كما ويحتوي على شرح مفصل عن Socket Programming والProtocols Transport Layer وال Network Layer Programming وبناء أنظمة متقدمة باستخدام الMulticasting كأنظمة المؤتمرات وال Voice Chat Systems ويحتوي الكتاب على شرح ألھم األمور المتعلقة بال Voice Over IP Programming وال TAPI Telephony وبرمجيات ال Remote Desktop وأنظمة التحكم عن بعد وغيرھا باإلضافة إلى طرق تحليل والتصنت على ال Packets المرسلة باستخدام ال Raw Programming والSniffing Packet كما ويحتوي على شرح مفصل ألھم برتوكوالت ال Application Layer وتصميم و بناء النظم الموزعة واستخداماتھا في برمجيات الشبكات وأخيرا شرح مفصل عن طرق الحماية ووضع الصالحيات والسياسات في برمجيات الشبكات. ~4~
5 قبل البدء بقراءة الكتاب: يستخدم الكتاب الطريقة المتسلسلة في طرح ومناقشة المواضيع و األكواد لذلك البد من البدء بقراءة المواضيع بشكل متسلسل إذ أنه وفي كل فصل يتم شرح األكواد الجديدة فقط كما ويجب أن يمتلك القارئ األساسيات البرمجية تحت أي لغة من لغات الدوت نيت قبل البدء بقراءة الكتاب. ما ھي األمور الجديدة في ھذا الكتاب ولمن ھو موجه: يطرح الكتاب معظم المواضيع المتعلقة ببرمجة الشبكات والنظم الموزعة بأسلوب مبسط للغاية ويعتبر الكتاب األول والذي يناقش المواضيع المتعلقة ببرمجة برمجيات المحادثة الصوتية ال Voice Over IP والمرئية Video Conference Systems وبناء أنظمة التعليم اإللكتروني عن بعد Remote elearning Systems تحت منصة الدوت نيت خصص ھذا الكتاب لطالب والمبرمجين المھتمين بمجال برمجة الشبكات والنظم الموزعة. ~5~
6 ملخص الفصول: Part1 etworks & TCPIP Programming Overview: Chapter 1: TCP/IP Layers & Message Encapsulation Overview Chapter 2: IPv4 & IPv6 Architecture Overview Chapter 3: IP Multicasting Overview Part2 Streaming: Chapter 4: Streaming (Classes & Members) Chapter 5: Applied Streaming in Dot Net Part3 Transport & etwork Layer Programming: Chapter 6: Transport TCP & UDP (Classes & Members) Chapter 7: Synchronous Socket Programming Chapter 8: Asynchronous Socket Programming Chapter 9: Advanced Multicasting Systems (Architecture & Conference Systems) Chapter 10 VOIP - Voice Over IP Programming Chapter 11 Raw Socket & Packet Sniffing Programming Part4 Application Layer Programming: Chapter 12 DNS Programming Chapter 13 HTTP Programming Chapter 14 Web Services & XML Programming Chapter 15 Remoting & Distributed Systems Programming & Design Chapter 16 SMTP & POP3 Programming Chapter 17 FTP Programming Part5 etwork Security Programming: Chapter 18 Cryptography Chapter 19 Socket Permissions Part6 Multithreading Chapter 20 Multithreading (Using & Managing) ~6~
7 Part 1 etworks & TCPIP Programming Overview: فھرس المحتويات: Chapter 1: TCP/IP Layers & Message Encapsulation Overview - TCP/IP Layers Encapsulation Overview - TCP / UDP Connection Establishment - TCP & UDP Header Encapsulation - Using TCP Connection Oriented in Dot Net to Send Unicast Messages - Introduction to Binary Streaming in Dot Net - Using UDP Connectionless in Dot Net to Send Uni & Broadcast Messages Chapter 2: IPv4 & IPv6 Architecture Overview - IPv4 Architecture - Classful IP Address - Unicast IP - Broadcast IP - Multicast IP - CIDR Nation Overview - IPv6 Architecture Overview Chapter 3: IP Multicasting Overview - IP Multicasting Overview - Using IP Multicasting in Dot Net to Create a Multicast Groups Part2 Streaming: Chapter 4: Streaming (Classes & Members) - Stream Classes - Stream Members - Stream Manipulation Chapter 5: Applied Streaming in Dot Net - Create a Simple Remote Control Application Using Stream Reader & Writer Classes - Create a Simple Remote Desktop Application - Create a Simple Application to Store & Read Images (Binary Data) in Microsoft Access & Microsoft SQL Server Database Management System By Using Streams Library & ADO.NET ~7~
8 Part3 Transport & etwork Layer Programming: Chapter 6: Transport TCP & UDP (Classes & Members) - TCP Classes Members - UDP Classes Members Chapter 7: Synchronous Socket Programming - Introduction to Socket Programming - Synchronous Socket Programming - Synchronous Socket Classes & Members Chapter 8: Asynchronous Socket Programming - Asynchronous Socket Class and its members - Applied Asynchronous Socket in Dot Net Chapter 9: Advanced Multicasting Systems - Architecture of Multicast Socket - Using Multicast Socket with.net - Multicast Conferencing Systems: - Full/Half Duplex Multicast Video Conferencing System. - Full/Half Duplex Multicast Desktop Conferencing System. - Full/Half Duplex Multicast Text Conferencing System Chapter 10 VOIP - Voice Over IP Programming - The Concept & Requirements of Voice Communication Systems - How to Create a Voice Chat Through Dot Net Using Unmanaged API s Functions - Testing UDP Multicasting, TCP and Thinking in SCTP to Transfer Voice Through Networks - How to Create a Voice Conference System Using Microsoft Direct Play 9 - Create an Advanced Video/Voice Conference System By Using API & TAPI Telephony & Managed Socket Library in Dot Net. Chapter 11 Raw Socket & Packet Sniffing Programming - Introduction to Raw Socket & Raw Protocols - Raw Socket Programming o ICMP Internet Control Message Protocol Programming (Ping & Tracing) o Using ARP Protocol to Get The MAC of a Remote Machine in Dot Net - Introduction to Packet Sniffing Applications ~8~
9 Part 4 Application Layer Programming: Chapter 12 D S Programming - Synchronous DNS Members - Asynchronous DNS Members Chapter 13 HTTP Programming - The Concept of HTTP Protocol - Using HTTP in Dot Net - Advanced HTTP Programming - Using HttpWebRequest - Using HttpWebResponse Chapter 14 Web Services & XML Programming - Introduction to Web services & XML - Create A Simple Web Service Application - Create A Simple GIS System Using (ADO.NET With Web Services) Chapter 15 Remoting & Distributed Systems Programming & Design - The Distributed Systems Concept & Design Design a Distributed ecommerce System by Using ASP.NET and Web Services. - Serialization Programming The Serialization (Classes & Members) Using BinaryFormatter & SoapFormatter to Serialize Objects & Images Through Network - Remoting Programming Remoting (Classes & Members) Using Remoting Applications in Dot Net Create an Advanced Distributed elearning System (Remote Class Room) Create an Advanced Remote Desktop Application With Remote (Mouse/Keyboard) Control Features Chapter 16 SMTP & POP3 Programming - SMTP Protocol - SMTP Concept - Using SMTP in Dot Net - Advanced SMTP Programming - POP3 Protocol Programming Chapter 17 FTP Programming - Introduction to FTP File Transfer Protocol - Create a Simple Application to Transfer Files By Using COM - Create a Simple Application to Transfer Files By Using Web Classes - Create a Simple Application to Transfer Files By Using Socket Programming & Streaming Libraries ~9~
10 Part5 etwork Security Programming: Chapter 18 Cryptography - Cryptography in Dot Net: Symmetric Encryption DES (Data Encryption Standard) Asymmetric Encryption RSA (Rivest Shamir Adleman) Digital Signature Algorithms Hashing Algorithms Using Security Encryption Standards With Network Applications Create an Advanced RSA Client Server Chat System. Chapter 19 Socket Permissions - Permission Namespace Overview - Security Action - Socket Access property Part6 Multithreading Chapter 20 Multithreading Using & Managing - Introduction to Threading in Dot Net - Threading Classes & Members - Multithreading & Network Applications Appendixes (A): etwork Programming Members - System.Net Namespace - System.Net.Socket Namespace - Socket Option Members - System.Threading Namespace - TAPI Telephony Functions - Remoting TCP / HTTP Channels Members Appendixes (B): ASCII Code Table, References ~10~
11 Part1 Networks & TCP/IP Programming Overview Chapter 1 TCP/IP Layers & Message Encapsulation Overview & Introduction to Network Programming Chapter2 IPv4 & IPv6 Architecture Overview Chapter3 IP Multicasting Overview ~11~
12 Chapter 1 TCP/IP Layers & Message Encapsulation Overview & Introduction to etwork Programming - TCP/IP Layers Encapsulation Overview - TCP / UDP Connection Establishment - TCP & UDP Header Encapsulation - Using TCP Connection Oriented in Dot Net to Send Unicast Messages - Introduction to Binary Streaming in Dot Net - Using UDP Connectionless in Dot Net to Send Uni & Broadcast Messages ~12~
13 TCP/IP Layers Encapsulation Overview : 1.1 من المعروف أن الشبكة ھي مجموعة من األجھزة متصلة مع بعضھا عبر وسيلة اتصال معين ة ومن ھنا سيندرج لدينا التقسيم المعروف لمنظمة OSI لعملية االتصال والتي تمر بسبعة طبقات لكل طبقة منھا وظيفة معينة يتم إضافتھا كHeaders على البيانات المرسلة.وتم اختصارھا إلى خمسة طبقات في برتوكول TCP/IP وتبين الصورة المرفقة ھذه الطبقات: تبدأ عملي ة تولي ف الرس الة المرس لة ف ي ال Application Layer ووظيفتھ ا ھن ا التعام ل م ع الرسالة نفسھا وتحويلھا من صيغة نصية إلى Data يمكن إرسالھا عبر الشبكة ففي برمجي ات الدردشة Chat يتم تحويل النص المكتوب إلى ASCII Code ثم إلى مجموع ة م ن Binary Code أو ال Bits توضع في مص فوفة لتجھيزھ ا وإرس الھا عب ر Socket وال ذي ي ربط طبق ة ال Layer Transport م ع ال Network Layer أو ال Internet Layer ويوض ح الش كل التالي طبيعة عمل الSocket : ~13~
14 حي ث ي ربط رق م ال Port المح دد ف ي Transport Layer م ع Destination IP ف ي Network Layer ويقوم الServer بالطرف المقابل بالموافقة على طلب الClient وتقتصر وظيف ة ال Socket ف ي ال Server عل ى رب ط رق م ال Port م ع ال Option Socket الت ي ي تم تحديدھا ثم البدء بعملية التصنت على الPort الذي تم تحدي ده ويمك ن ف ي ھ ذه المرحل ة وض ع شروط معينة لقبول الجلسة مثل عمليات التحق ق ال Authentication أو م ا ش ابه أو الموافق ة بشكل مباشر. في نموذج OSI تم تقسيم ال upper Layers إلى ثالثة طبقات: User Interface لتعامل مع البرنامج نفسه أو ما يسمى Application Presentation تمثيل البيانات المرسلة أو استخدام أس اليب لض غط البيان ات أو تش فيرھا ف ي ال دوت ني ت ت تم عملي ة تمثي ل الرس الة باس تخدام أي م ن ال Classes ض من ال Encoding :ASCIIEncoding وكمثال الClass System.Text Namespace ضمن ال Class C# String str=console.readline(); ASCIIEncoding asen= new ASCIIEncoding(); byte[] ba=asen.getbytes(str); VB. ET Dim str As String = Console.ReadLine Dim asen As ASCIIEncoding = New ASCIIEncoding Dim ba As Byte() = asen.getbytes(str) Session وفيھا البدء بعملية التخاطب بين الجھازين والتعريف ببعضھم البعض (فتح الجلسة) وتتم عادة في الTCP بمجموعة من المراحل تسمى Three Way Hand Shake أما في الUDP فيتم البدء باإلرسال دون إجراء أي من عمليات التحقق السابقة أما في بروتوكول ال TCP/IP فكتفا بوجود طبقة Application Layer والتي تقوم بعمل الطبقات الثالث األولى في OSI في Session Layer يتم التعرف وفتح الجلسة بعدة خطوات وھي كما يلي: 1- إجراء االتصال المبدئي بال Server عبر ال IP وال Port المحدد وذلك بعد تحديد عملية االتصال سواء عبر ال UDP أو عبر ال.TCP 2- التعريف بنفسه وعمل ال Authentication إذا تطلب الServer ذلك 3- قبول أو رفض الجلسة ويتم ذلك بإرسال الموافقة على فتح الجلسة أو رفضھا 4- بدأ الجلسة وقيام الServer بعمل Listening على الPort الخاص بالبرنامج وھنا مثال يوضح عمل ھذه الطبقة باستخدام ال : TCP Protocol TcpClient tcpclnt = new TcpClient(" ",8001); Dim tcpclnt As TcpClient = New TcpClient(" ", 8001) عندما يتم الموافقة على فتح الجلسة والبدء بعملية التخاطب يقوم جھاز المرسل ال Client بتحميل الرسالة إلى الطبقة األخرى وھي ھنا طبقة ال Transport وفي ھذه الطبقة يتم تحديد ~14~
15 طبيعة االتصال سواء عبر TCP - Connection Protocol أو عبر ال- UDP Connectionless Protocol ففي البروتوكول األول يتم تحديد طرفين وھما المرسل والمستقبل وPort االتصال أما ال UDP فيمكن أن يكون الطرف المستقبل كل األجھزة Broadcast وھذا يعني أن أي شخص يقوم بتصنت عبر ھذا ال Port يستطيع استقبال الرسالة كما يمكن من عمل الMulticasting (اإلرسال إلى مجموعة (Group ويتم ذلك بوضع الIP Broadcast أو الIP Multicast مع رقم الPort في الSocket (لمعرفة كيفية استخراج ال Broadcast IP وال Multicast IP أنظر الفصل الثاني). وإلرسال الرسالة عب ر الش بكة باس تخدام ال TCP نس تخدم ف ي ال دوت ن ت Class ج اھز يق وم بھ ذه العملي ة ويس مى NetworkStream وھ و المس ئول ع ن التعام ل م ع وس يلة االتص ال وإرس ال الرس الة إل ى الط رف المعن ي بش كل Stream Data أو باس تخدام ال Socket نفس ه وكمثال على ذلك: NetworkStream mynetsream = tcpclnt.getstream (); StreamWriter myswrite = new StreamWriter (mynetsream); myswrite.writeline("your Message"); myswrite.close (); mynetsream.close (); tcpclnt.close (); Dim mynetsream As NetworkStream = tcpclnt.getstream Dim myswrite As StreamWriter = New StreamWriter(mynetsream) myswrite.writeline("your Message") myswrite.close () mynetsream.close () tcpclnt.close () وبعد ذلك تسلم إلى ال Network Layer إذ تتم عنونة الرسالة ووضع عنوان المرسل والمستقبل عليھا وتسلم إلى الطبقة األدنى ليتم إرسالھا عبر ال Physical Tunnel ويحتوي الLayer Network على مجموعة من البروتوكوالت منھا IP,IPv6,ARB-Address Resolution Protocol ولكل منھا وظيفة معينة سنأتي على شرحھا الحقا... أما بنسبة للجھاز المستقبل ال Server فيقوم بالمرور على نفس الطبقات ولكن بالعكس حيث يستلم كرت الشبكة الBits لتحول إلى Data link Layer ثم إلى ال Network Layer ثم الLayer Transport ثم الLayer Application ومنھا تحول من Binary إلى ASCII ومن ASCII إلى Text وفي حالة استخدام الClasses Stream فإن ھذه العملية تتم بشكل آلي.. ويوضح الكود التالي مبدأ عمل الServer : ~15~
16 using System.IO; using System.Net.Sockets; using System.Threading; TcpListener mylistener; NetworkStream myntl; public void Listener() mylistener = new TcpListener(8001); mylistener.start(); Socket mysocket; StreamReader str; while (true) mysocket = mylistener.acceptsocket(); myntl = new NetworkStream(mysocket); str = new StreamReader(myntl); textbox1.text = str.readtoend(); Imports System.IO Imports System.Net.Sockets Imports System.Threading Private mylistener As TcpListener Private myntl As NetworkStream Public Sub Listener() mylistener = New TcpListener(8001) mylistener.start() Dim mysocket As Socket Dim str As StreamReader Do While True mysocket = mylistener.acceptsocket() myntl = New NetworkStream(s) str = New StreamReader(myntl) textbox1.text = str.readtoend() Loop End If End Sub ~16~
17 مالحظة ھامة جدا: سوف يؤدي ال Infinity Loop والذي وضعناه إلى توقف البرنامج عن االستجابة والسبب أن ال Loop يعمل على نفس ال Thread والمخصص لل Form إذ لن ينفذ إي شيء إال بعد انتھاء ال Loop وھو ما لن يحدث أبدا إذ انه Infinity Loop قدمت لنا الدوت نيت الحل لھذه المشكلة وھي باستخدام تكنولوجيا ال Multithreading والتي تسمح بالمعالجة المتوازية على نفس المعالج وذلك من خالل تقسيم المھام على المعالج وعمل Session منفصلة لكل برنامج وھو ما يسمى بال..Multitasking وھكذا لن يؤثر البرنامج على موارد النظام كما لن يؤثر ال Infinity Loop على اداء البرنامج العام انظر الشكل التالي : الحظ انه قبل إضافة ال Thread كان ال Loop يعمل على منطقة ال Global Area وھذا ھو سبب عدم االستجابة وبعد استخدام ال Thread تم عمل Session أو Pipe خاص لدالة التي تحتوي على ال Loop بحيث تعمل بشكل متوازي مع البرنامج والستخدام ال Thread يلزم أوال تعريف الNamespace : System.Threading using System.Threading; imports System.Threading ثم اشتقاق Instance منه وإدراج اسم الدال ة الت ي تري د عم ل Thread لھ ا ف ي ال Delegate الخاص بھا كما يلي: Thread myth; myth= new Thread (new System.Threading.ThreadStart(Listener)); myth.start (); Imports System.Threading Dim myth As Thread ~17~
18 myth = New Thread(New System.Threading.ThreadStart(Listener)) myth.start اآلن قم بإضافة myth.aport() في حدث ال Closing Form كما يلي: private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) mylistener.stop(); myth.abort(); Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Try mylistener.stop() myth.aport() Catch ex As Exception Msgbox(ex.Message) End Try End Sub ميزة ال Thread رائعة ج دا إذ تمكن ك م ن تش غيل وإدارة أكث ر م ن Thread ف ي نف س الوق ت وفي نفس البرنامج وھو ما يسمى بال Multithreading انظر الفصل العشرون... بعد إجراء عملية العنونة يقوم المرسل بسؤال عن عنوان الAddress MAC الخاص بالServer وتتم ھذه العملية عبر بروتوكول الProtocol ARP-Address Resolution ويقوم ھذا البروتوكول بالتحقق من وجود الAddress MAC في الTable MAC وفي حالة عدم وجوده يقوم بإرسالRequest ARB Broadcast Message إلى كل األجھزة على الشبكة يسأل فيھا عن صاحب الAddress IP المراد اإلرسال له فإذا وجده يرسل الجھاز المعني Unicast ARP Replay Message يخبره فيھا بعنوان الAddress MAC الخاص به وبعد استالم الرسالة يقوم بتخزين العنوان المعني في ال MAC Table أو الCash MAC الموجود في الجھاز ولكي يتم استخدامه في المرات الالحقة الحظ الشكل التالي: ~18~
19 وبع د ھ ذه المرحل ة ي تم تحدي د ن وع ال Encapsulation ھ ل س يكون ك Internet Data Link ال Layer ف ي ذل ك وي تم Ethernet Encapsulation أو Encapsulation والشكل التالي يوضح كل ھذه العمليات: وفي النھاية يكون الشكل العام للPacket كما يلي: ويجب التفريق بين عملية اإلرسال باستخدام الEthernet وعملية اإلرسال باستخدام الInternet أو الConnection Serial إذ أنه في الEthernet تتم عملية اإلرسال بعد معرفة الAddress MAC لطرف األخر باستخدام الARP أما في الInternet فيتم الوصول وفق مبدأ الProtocol PPP Point to Point الحظ الشكل التالي: ~19~
20 في كل طبقة يتم إضافة Header على الData يحتوي على معلومات التحكم أو ال Control Data ويتراوح حجم ال Header ف ي ال Transport وال Network Layer م ن 20 إل ى 60 بايت حسب الOptions التي يتم إضافتھا إلى ال.Header في المثال التالي سنقوم باستخدام برن امج ال Ethereal وھ و برن امج يق وم بعملي ة ال Packet Sniffing والذي يمكن تثبيته من الموقع الخاص به وھو: مثال على استخدام الARB والD S والHTTP : الحظ الشكل التالي ف ي برن امج ال Ethereal وال ذي يق وم بعملي ات التص نت والتحلي ل للبيان ات الم ارة م ن خ الل ال Card Network Interface حي ث قمن ا بطل ب ال دخول عل ى موق ع الGoogle باستخدام الExplorer :Internet الحظ أن أول عملية كانت السؤال ع ن ال Address MAC الخ اص بال Gateway وھ و ھن ا حي ث أرس لت ھ ذه الرس الة ك Message Broadcast وف ي العملي ة الثاني ة ق ام الRouter بالرد على الRequest ARP وأرسل عنوان الAddress MAC الخاص به بع د ھذه العملية س يقوم ال Client باالستفس ار ع ن عن وان ال Google بإرس ال DNS Request DNS ال ف ي بال Google الخ اص IP ال Address وج د ق د المث ال الحظ أنه ف ي Query ~20~
21 Table والموجودة ضمن نظام التش غيل وھ ذا يعن ي ان ه ت م ال دخول عل ى ال Google م ن قب ل والدليل على ذلك أن الAddress IP الخاص بالGoogle موجود ف ي ال Table DNS وبع د ھ ذه العملي ة ق ام موق ع ال Google ب الرد عل ى الطل ب يخب ره بوج وده وض من العن وان المح دد الحظ أن العمليات من 8 إلى 20 ھي عمليات طلب و إرسال لمحتويات الصفحة الخاصة بموقع الGoogle وتتم باستخدام ال.HTTP Protocol TCP / UDP Connection Establishment : 1.2 تمر عملية إنشاء االتصال بمجموع ة م ن المراح ل وف ي الع ادة يق وم الط رف المرس ل بإرس ال طلب إنشاء االتصال إلى الطرف األخر وعند الموافق ة عل ى إج راء االتص ال ي تم الب دء بإرس ال مجموعة من المعلومات إلى الطرف المستقبل في بروتوكول ال TCP ت تم ھ ذه العملي ة بثالث ة مراحل تسمى Three-way hand-shake وكما ھو واضح في الشكل التالي: 1- حيث يقوم الطرف المرسل بتوليد رقم تسلسلي Sequence Number ويرسله إلى الServer ويكون ھذا الرقم المولد نقطة البدء لعملية اإلرسال بحيث يتم زيادته بمقدار واحد One) ( increment By عند كل عملية إرسال. 2- يستلم الطرف المقابل الNumber Sequence ويقوم بإرس ال Acknowledgment إل ى المرسل مضاف إليه الرقم التسلسلي الذي تم إرساله. 3- عند ھذه المرحلة يكون قد تم الموافقة على بدأ الجلسة وعندھا يقوم بإرسال طلبه مرفق مع ه الAcknowledgment الذي أرسل من قبل المستقبل. أما في بروتوكول ال UDP فتتم بدون إرسال Acknowledgments وال يتحقق الUDP من عمليات الوصول كما ھو الحال في الTCP وھو م ا س يتم توض يحه ف ي الج زء الت الي م ن ھ ذا الفصل. ~21~
22 TCP & UDP Header Encapsulation : 1.3 في طبقة الLayer Transport يتم التعامل مع إحدى البروتوكولين TCP أو الUDP حيث سنحدد فيھا طبيعة اإلرسال فإذا كان المطلوب ھو اإلرسال كStream ونوع اإلرسال ھو Unicast فيتم اختيار الTCP أما في حالة كان المطلوب ھو اإلرسال كBroadcast أو Multicast فيتم اختيار الUDP لعملية اإلرسال وسوف نبين في الجزء التالي من ھذا الفصل مبدأ عملية اإلرسال باستخدام بروتوكول الTCP وبروتوكول الUDP... TCP Encapsulation : يتميز ھذا البروتوكول بدعمه لكل عمليات التحكم سواء على مستوى ال Data Flow أو حجم الBuffer كما يدعم عمليات التحقق من الوصول وفق الترتيب السليم Delivered on Sequence وھذا واضح من تركيب ال Header الخاصة به أنظر إلى الشكل التالي: : Source & Destination Port ف ي المنطق ة المخصص ة ب Port اإلرس ال واالس تقبال ي تم تحدي د ال Port Source والPort Destination الخاصة بالبرنامج الذي يجري عملية االتصال وم ن المع روف أن ه ال يمكن ألكثر من برنامج استخدام نفس رقم الPort لكن يمكن للبرنامج الواحد استخدام أكث ر م ن Port Address وبتأكي د ف إن عملي ة اختي ار ال Port ليس ت عش وائية إذ يج ب االبتع اد ع ن األرقام التي تبدأ ب 0 وتنتھ ي 1023 إذ أنھ ا أرق ام لبروتوك والت معروف ة وي تم اس تخدامھا ف ي نظام التشغيل ومن األمثلة عليھا بروتوكول الHTTP والذي يستخدم ال Port 80 وبروتوك ول ال FTP والذي يستخدم الPort 21 وغيره ويفض ل عن د اختي ار ال Port أن ال يب دأ ب رقم يق ل عن انظر إلى الشكل التالي: ~22~
23 : Sequence & Acknowledgment umber ويحتوي كل منھما على 32 Bits ويدل ھذا الرقم على رقم التسلسل للPacket عن د إرس اله أو اس تقباله وي تم تولي ده عش وائيا عن د بداي ة االتص ال أم ا رق م ال Acknowledgment فيحت وي على الرقم التسلسلي لل Packet ال ذي ت م التأك د م ن وص وله وت تم ھ ذه العملي ة كم ا ف ي الش كل التالي: : Header Length & Validation Controls ويحت وي الج زء الث اني م ن ال Header الخ اص بال TCP عل ىBits 32 مقس مة عل ى ال Bits Windows Size 16 و 16Bits أخ رى لل Header Length + Validation Controls الحظ الشكل التالي: ويحت وي ال Length Header عل ى حج م ال Header الخ اص بال TCP مقس وم عل ى 4 أي لمعرفة حجم الHeader نضرب ال( Length HLEN (Header ب 4 أم ا ال Validation Controls فھي 6 Controls تأخذ كل منھا 1 Bit فإذا كانت قيمته 0 فھذا يعني أن ھ ذه األداة غير مستخدمة وإذا كانت 1 فھذا يعني أن ھذه األداة مستخدمة وكما في الشكل التالي: : Window Size ويعرف فيه حجم الPacket الذي يمكن إرساله من خالل الشبكة بناء على سرعة الوصول بين ك ل SYN Packet و ACK Packet أي الوق ت المس تغرق لعملي ة التوص يل لك ل Packet وقد تزيد أو تنقص بناءا على أدائية الشبكة. ~23~
24 : Check Sum وھي 16 Bits وتستخدم لعملية التحقق من وصول ال Header TCP بش كل الس ليم حي ث ي تم جمع كافة قيم الHeader TCP (كل 16 Bits لوحدھا) ثم قلبھا ووضع الناتج ف ي ال Check Sum وفي الطرف المستقبل يقوم بتأك د م ن ال Checksum بض رب قيم ة ال HLEN ب 4 ث م مقارن ة الن اتج م ع مقل وب ال Checksum وكم ا ھ و واض ح ف ي الش كل الت الي وال ذي يظھ ر الChecksum في ال IP Protocol إذ انھا تتم بنفس الطريقة بال TCP والUDP : : Urgent Pointer م ن المع روف أن ال Data المرس لة عب ر ال TCP ي تم تجميعھ ا ف ي ال Buffer قب ل أن ي تم عرضھا حيث يتم تحديد موقع الData القادمة الجديدة في الBuffer ومن ھنا نحن بحاج ة إل ى وجود Pointer يؤشر على موقع الData في الBuffer وھو ھنا الPointer Urgent الحظ الشكل التالي والذي يوض ح عملي ة وض ع Data قادم ة جدي دة إل ى ال Buffer الخ اص بالجھ از المستقبل : ~24~
25 و : Dot et Binary Streaming Overview : يمكن من خالل الClasses Stream نقل Text أو Binary Data بينا سابقا كيفية التعامل من ال Socket لنق ل Text باس تخدام ال Stream Reader وال Stream Writer وف ي ھ ذا الج زء س نبين كيفي ة التعام ل مع ه لنق ل Object (أي ن وع أخ ر م ن البيان ات ويمك ن أن يك ون صورة Image أو صوت Voice أو أي شيء آخ ر يمك ن أن يح ول إل ى..) Binary Data وكما ھو الحال في نقل ال Text كنا نحول ال Text إلى ASCII Code ث م إل ى Binary أم ا ف ي ال Object في تم نقل ه إم ا ك Object Serialization (انظ ر الفص ل الخ امس عش ر) أو باستخدام الReader Binary و ال Binary Writer والت ي تمكن ك م ن التعام ل م ع أي ن وع من البيانات كما وتستخدم الReader Stream وال Stream Writer لتعام ل م ع ال Text وال FileStream لتس ھيل التعام ل م ع الملف ات باإلض افة إل ى ال MemoryStream والت ي تس تخدم ك Buffer لحف ظ البيان ات قب ل إرس الھا أو بع د اس تقبالھا وتق وم أيض ا بتحوي ل الStream إلى مجموعة من ال Bits وال Bits إل ى Stream م رة أخ رى الح ظ الش كل الت الي والذي يوضح تسلسل مكتبات الStream في الدوت نيت: وكمثال تطبيقي على ھذا سوف نقوم ببناء برنامج يقوم بعملية نقل صورة Image من جھاز إلى أخر Client/Server وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي : ~25~
26 في البداية قم بإضافة ال Namespaces التالية: using System.Net.Socket; using System.IO; Imports System.Net.Socket Imports System.IO لإلجراء عملية اإلرسال ال بد أوال من اشتقاق Instance من الكالس MemoryStream والتي سوف نستخدمھا لتخزين الصورة داخل الذاكرة بشكل مؤقت لكي نحولھا الحقا إلى مصفوفة Binary ثم إرسالھا باستخدام NetworkStream عبر ال Socket إلى الServer : 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 The server NetworkStream myns = myclient.getstream (); BinaryWriter mysw = new BinaryWriter (myns); mysw.write(arrimage);//send the stream to The above address mysw.close (); myns.close (); myclient.close (); catch (Exception ex)messagebox.show(ex.message ); openfiledialog1.showdialog Dim mypic_path As String = openfiledialog1.filename picturebox1.image = Image.FromFile(mypic_path) Dim ms As MemoryStream = New MemoryStream picturebox1.image.save(ms, picturebox1.image.rawformat) Dim arrimage As Byte() = ms.getbuffer ms.close Dim myclient As TcpClient = New TcpClient(txt_host.Text, 5020) ~26~
27 Try Dim myns As NetworkStream = myclient.getstream Dim mysw As BinaryWriter = New BinaryWriter(myns) mysw.write(arrimage) mysw.close myns.close myclient.close Catch ex As Exception Msgbox(ex.Message) End Try في الجزء الخاص بالServer تتم عملية التصنت على ال Port واستقبال ال Stream عبر الSocket وقراءتھا باستخدام ال Binary Reader وتحويله إلى Object (صيغته التي كان عليھا قبل اإلرسال) مرة أخرى في ھذا المثال نريد استقبال صورة وفي ھذه الحالة وفرت لدينا الدوت نيت خصائص جديدة في ال Controls الموجودة فيھا ومن ضمنھا Method Image.FromStream الخاصة بال Picture Box والتي تسھل علينا إمكانية عرض الصورة المرسلة من خالل Stream لكي يتم تحويلھا من Stream إلى صورة تعرض على الPicturebox وكما في المثال التالي: قم بإنشاء مشروع جديد وكما في الشكل التالي : using System.Net.Socket ; using System.IO; تتم عملية استقبال الصورة كما يلي: TcpListener mytcpl; // Declare TCP Listener Socket mysocket; // Declare an object from Socket Class NetworkStream myns; // StreamReader mysr; ~27~
28 void Image_Receiver() mytcpl = new TcpListener (5020);// Open The Port mytcpl.start ();// Start Listening mysocket = mytcpl.acceptsocket (); myns = new NetworkStream (mysocket); 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 Private mytcpl As TcpListener Private mysocket As Socket Private picturebox1 As System.Windows.Forms.PictureBox Private mainmenu1 As System.Windows.Forms.MainMenu Private menuitem1 As System.Windows.Forms.MenuItem Private savefiledialog1 As System.Windows.Forms.SaveFileDialog Private myns As NetworkStream Sub Image_Receiver() mytcpl = New TcpListener(5000) mytcpl.start() mysocket = mytcpl.acceptsocket myns = New NetworkStream(mysocket) picturebox1.image = Image.FromStream(myns) mytcpl.stop() If mysocket.connected = True Then While True Image_Receiver() End While End If End Sub ولتنفي ذ ال Method Image_Receiver ب Thread منفص ل ع ن ال Thread الخ اص بالبرنامج نقوم بتمريرھ ا إل ى ال Thread Delegate Instance ض من ال Thread Class وكما يلي: ~28~
29 Thread myth; myth= new Thread (new System.Threading.ThreadStart(Image_Receiver)); myth.start (); Imports System.Threading Dim myth As Thread myth = New Thread(New System.Threading.ThreadStart(Image_Receiver)) myth.start ويجب إغالق ال Thread وال Socket ف ي ال Closing Event الخ اص بال Form وكم ا يلي: private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) try mytcpl.stop (); thread.aport(); catch (Exception ex) MessageBox.Show (ex.message ); Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Try mytcpl.stop() thread.aport() Catch ex As Exception Msgbox(ex.Message) End Try End Sub ويمكن إضافة الكود التالي إلى ال Save Button لحفظ الصورة المستقبلة: try savefiledialog1.filter = "JPEG Image (*.jpg) *.jpg" ; if(savefiledialog1.showdialog() == DialogResult.OK) ~29~
30 string mypic_path = savefiledialog1.filename; picturebox1.image.save(mypic_path); catch (Exception) Try savefiledialog1.filter = "JPEG Image (*.jpg) *.jpg" If savefiledialog1.showdialog = DialogResult.OK Then Dim mypic_path As String = savefiledialog1.filename picturebox1.image.save(mypic_path) End If Catch generatedexceptionvariable0 As Exception End Try UDP-User Datagram Protocol- Encapsulation : سوف نبين في ھذا الجزء طبيعة االتصال باستخدام الUDP حيث يتميز ھذا البروتوكول بإمكانية اإلرسال ك Multicast و Broadcast بعكس الTCP الذي يدعم اإلرسال كUnicast فقط لكن مشكلة ھذا البروتوكول ھو عدم دعمه لعمليات التحكم على مستوى الFlow Data أو حجم الBuffer كما ال يدعم عمليات التحقق من الوصول وفق الترتيب السليم Delivered on Sequence وتعتبر ھذه األمور من أھم عيوبه ويوضح الشكل التالي التركيب العام لھذا البروتوكول: الSum Check و الLength أو الLength Header ھي نفسھا في الTCP لكن الحظ عدم وجود أي من األمور الخاصة بالManagement Buffer أو ال Delivered On Sequence في الHeader الخاص بالUDP والمشكلة ھنا أننا ال نستطيع عمل Fragmentation للPackets حيث أن إعادة تجميعھا بالترتيب الصحيح أمر غير مضمون كما أنه ال وجود ألي Acknowledgment لتحقق من وصول البيانات أو عدم وصولھا الحظ الشكل التالي والذي يوضح طبيعة التراسل باستخدام الUDP : ~30~
31 الس تخدام ال UDP ف ي ال دوت ني ت يل زم أوال تعري ف System.Net Namespace والSystem.Net.Socket الحظ ان ه ف ي ال TCP ك ان يل زم تعري ف رق م ال Port والعن وان للجھ از المس تقبل أم ا ف ي ال UDP فتس تطيع تعريف ه كم ا ھ و ف ي TCP كم ا وتس تطيع عم ل Broadcast باستخدام IPAddress.Any عن د االس تقبال أو IPAddress.Broadcast عن د اإلرسال بعد اشتقاق كائن من الكالس IPEndPoint وتستطيع أيض ا ع دم تحدي د رق م ال Port وذلك بتمرير الرقم صفر 0 إلى الMethod Bind في ال Socket المخصصة لالستقبال. في المثال التالي يتم فتح الPort 5020 والتصنت عليھ ا ث م اس تالم الرس الة عب ر ھ ذا ال Port وتوزيعھا على الكل: 1) IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 5020); VB. ET Dim ipep As IPEndPoint = New IPEndPoint(IPAddress.Any, 5020) وتتم عملية إنشاء الSocket وتحديد نوع البرتوكول المستخدم كما يلي: 2) Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) VB. ET Dim newsock As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) ثم نمرر IPEndpoint Object إلى الدالة... Send في ال Bind Method والتي يتم وضعھا في الطرف المستقبل فقط يتم استخدامھا لربط ال IP : Socket بال ورقم الPort Address 3) newsock.bind(ipep); newsock.bind(ipep) ~31~
32 اآلن تم استقبال الرس الة ونري د بثھ ا إل ى ك ل م ن يتص ل م ع ال Server عل ى ال Port الس ابقة ولعمل ذلك يلزم أوال تعريف IPEndPoint Object كما يلي : 4) IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint Remote = (EndPoint)(sender); recv = newsock.receivefrom(data, ref Remote); Dim sender As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim Remote As EndPoint = CType((sender), EndPoint) recv = newsock.receivefrom(data, Remote) 5) ولطباعة عنوان مرسل الرسالة و الرسالة نفسھا: Console.WriteLine("Message received from 0:", Remote.ToString()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); Console.WriteLine("Message received from 0:", Remote.ToString) Console.WriteLine(Encoding.ASCII.GetString(Data, 0, recv)) نقوم ھنا بإرسال رسالة ترحيبية لكل جھاز جديد يق وم بش بك م ع ال Server لنخب ره بھ ا ان ه ت م ~32~ الموافقة على انضمامه: string welcome = "Welcome Customer..."; data = Encoding.ASCII.GetBytes(welcome); newsock.sendto(data, data.length, SocketFlags.None, Remote); Dim welcome As String = "Welcome Customer..." Data = Encoding.ASCII.GetBytes(welcome) newsock.sendto(data, Data.Length, SocketFlags.None, Remote) الھدف من ال : Infinity Loop إبقاء عملية االستقبال مستمرة باإلضافة إل ى أن ه عن د اس تقبال أي رسالة في أي وقت من قبل أي جھاز يقوم الServer باستالمھا وتسليمھا إلى ك ل م ن ھ و على الشبكة... إذا أردت تحديد عدد معين من الرسائل المستلمة تستطيع تغيير ال True في ال infinity loop إلى أي رقم تريده. while(true) data = new byte[1024]; recv = newsock.receivefrom(data, ref Remote); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
33 newsock.sendto(data, recv, SocketFlags.None, Remote); server.close(); While True Data = New Byte(1024) recv = newsock.receivefrom(data, Remote) Console.WriteLine(Encoding.ASCII.GetString(Data, 0, recv)) newsock.sendto(data, recv, SocketFlags.None, Remote) End While server.close() يتم ھنا إغالق ال Socket في حالة إذا تم الخروج من Infinity Loop و لن يتم الوصول إلى Infinity Loop ~33~ ھذه النقطة إال إذا تم مقاطعته بوضع Break ضمن ال وفق شرط معين نحدده الحقا وكمثال للقيام باستقبال رسالة أو نص رسالة معينة سيتم الخروج من ال Loop وسيتم إغالق ال Socket وھذا يعني انك تستطيع إغالق ال Server عن بعد كما يمكنك وضع جملة تشغيل أي ملف تنفيذي على الServer في حالة ورود نص معين وھكذا... using System; using System.Net; using System.Net.Socket; using System.Text; class SimpleUdpSrvr public static void Main() int recv; byte[] data = new byte[1024]; IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 5020); 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);
34 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); Imports System Imports System.Net Imports System.Net.Socket Imports System.Text Class SimpleUdpSrvr Public Shared Sub Main() Dim recv As Integer Dim data(1024) As Byte Dim ipep As IPEndPoint = New IPEndPoint(IPAddress.Any, 5020) Dim newsock As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) newsock.bind(ipep) Console.WriteLine("Waiting for a client...") Dim sender As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim Remote As EndPoint = CType((sender), EndPoint) recv = newsock.receivefrom(data, Remote) Console.WriteLine("Message received from 0:", Remote.ToString) Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)) Dim welcome As String = " 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, Remote) Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)) newsock.sendto(data, recv, SocketFlags.None, Remote) End While End Sub End Class ~34~
35 ثاني ا الج زء الخ اص بال Client يقتص ر العم ل ھن ا عل ى قي ام ال Client بإنش اء جلس ة م ع الServer وذلك بعد تعريفه بال IPEndPoint ورقم الPort وكما تم في السابق. using System; using System.Net; using System.Net.Socket; using System.Text; class SimpleUdpClient public static void Main() byte[] data = new byte[1024]; string input, stringdata; IPEndPoint ipep = new IPEndPoint( IPAddress.Parse(" "), 5020); 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(); ~35~
36 Imports System Imports System.Net Imports System.Net.Socket Imports System.Text Class SimpleUdpClient Public Shared Sub Main() Dim data(1024) As Byte Dim input As String Dim stringdata As String Dim ipep As IPEndPoint = New IPEndPoint(IPAddress.Parse(" "), 5020) Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim welcome As String = "Hello, are you there?" data = Encoding.ASCII.GetBytes(welcome) server.sendto(data, data.length, SocketFlags.None, ipep) Dim sender As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim Remote As EndPoint = CType(sender, EndPoint) data = New Byte(1024) Dim recv As Integer = server.receivefrom(data, Remote) Console.WriteLine("Message received from 0:", Remote.ToString) Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)) While True input = Console.ReadLine If input = "exit" Then ' break End If server.sendto(encoding.ascii.getbytes(input), Remote) data = New Byte(1024) recv = server.receivefrom(data, Remote) stringdata = Encoding.ASCII.GetString(data, 0, recv) Console.WriteLine(stringData) End While Console.WriteLine("Stopping client") server.close() End Sub End Class ويمك ن تطبي ق ال Broadcast Address عل ى ال UDP Socket وذل ك بع د تفعيلھ ا م ن ال Options Socket (لمزي د م ن المعلوم ات ع ن ال SocketOption Class أنظ ر Broadcast إلرس ال كمث ال يل ي كم ا العملي ة وت تم المرفق ات) ف ي Appendixes (A) Message إلى كل األجھزة المتصلة على الشبكة المحلية: ~36~
37 - Client using System; using System.Net; using System.Net.Sockets; using System.Text; public class Broadcast public static void Main() Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Broadcast, 5000); byte[] data = Encoding.ASCII.GetBytes( Hello All ); sock.setsocketoption(socketoptionlevel.socket, SocketOptionName.Broadcast, 1); sock.sendto(data, iep); sock.close(); - Client Imports System Imports System.Net Imports System.Net.Sockets Imports System.Text Public Class Broadcast Public Shared Sub Main() Dim sock As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Broadcast, 5000) Dim data As Byte() = Encoding.ASCII.GetBytes( Hello All ) sock.setsocketoption(socketoptionlevel.socket, SocketOptionName.Broadcast, 1) sock.sendto(data, iep) sock.close() End Sub End Class - Server using System; using System.Net; using System.Net.Sockets; using System.Text; public class RecvBroadcst public static void Main() ~37~
38 Socket sock = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 5000); sock.bind(iep); EndPoint ep = (EndPoint)iep; Console.WriteLine("Ready to receive..."); byte[] data = new byte[1024]; int recv = sock.receivefrom(data, ref ep); string stringdata = Encoding.ASCII.GetString(data, 0, recv); Console.WriteLine("received: 0 from: 1",stringData, ep.tostring()); - Server Imports System Imports System.Net Imports System.Net.Sockets Imports System.Text Public Class RecvBroadcst Public Shared Sub Main() Dim sock As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 5000) sock.bind(iep) Dim ep As EndPoint = CType(iep, EndPoint) Console.WriteLine("Ready to receive...") Dim data As Byte() = New Byte(1023) Dim recv As Integer = sock.receivefrom(data, ep) Dim stringdata As String = Encoding.ASCII.GetString(data, 0, recv) Console.WriteLine("received: 0 from: 1", stringdata, ep.tostring()) End Sub End Class وھكذا بينا مراحل االتصال باستخدام الTCP/IP واس تخدام ال TCP وال UDP ف ي ال دوت نيت سيتم الحديث في الفصل التالي عن etwork Layer Encapsulation ومعمارية بروتوكول الIPv4 والIPv6... ~38~
39 Chapter 2 IPv4 & IPv6 Architecture Overview - IPv4 Architecture - Classful IP Address i. Unicast IP ii. Broadcast IP iii. Multicast IP - CIDR Nation Overview - IPv6 Architecture Overview ~39~
40 :The Internet Protocol في الLayer Network تتم عملية عنونة الPacket باستخدام بروتوكول اإلنترنت IP وتتم ھذه المرحلة بناءا على البروتوكول المستخدم في الLayer Transport فإذا تم استخدام الTCP عندھا ال نستطيع إال أن يكون العنوان المستخدم ھو Unicast أما في حالة كان الUDP ھو البروتوكول المستخدم عندھا نستطيع وضع عنوان Unicast أو Multicast أو Broadcast وسوف نأتي في الجزء التالي من ھذا الفصل على شرح تركيب بروتوكول اإلنترنت IPv4 وطرق وضع عناوين الUnicast والMulticast والBroadcast فيه: IPv4 Architecture : 2.1 يوضح الشكل التالي التركيب العام لبروتوكول اإلنترنت : IPv4 يتراوح حج م ال Header الخ اص بال IPv4 م ن 20 إل ى 60 Bytes بن اءا عل ى ال Options المس تخدم ف إذا ل م ي تم اس تخدام ال Options عن دھا س يكون حج م ال Header ثاب ت وھ و 20 Bytes وفي ھذه الحالة يمكننا معرفة حجم الData المرسلة عبر الTCP كما يلي: Data = total Length (20 Bytes for IPv4 Header+ 20 Bytes For TCP Header) وتقسم الBytes 20 الخاصة بالHeader IPv4 كما يلي: ويتم تمثيله 0100 في الBinary. وھو ھنا IPv4 المستخدم يوضع فيھا الVersion 4 Bits للLength Header ويوضع في حجم الHeader مقسوم على 4 4 Bits لل Services Type of حي ث يمث ل فيھ ا م دى ج ودة الخدم ة المطلوب ة للبروتوك ول 8 Bits المس تخدم ف ي ال Layer Application ومنھ ا Minimum Delay أو ال Maximum Services وغيرھا... ترتيب الFragments وإعادة وتستخدم لعمليات الFragmentation 32 Bits TTL ويعب ر ع ن ع دد ال Hops أو Time to Live وتس تخدم لتحدي د ال 8 Bits الRouters التي يسمح للPacket المرور من خاللھ ا إل ى أن تنتھ ي والع دد االفتراض ي لھ ا 16 hops وعند مرورھا بكل Router يتم طرح 1 من قيمتھا. ~40~
41 8 Bits أخ رى لتحدي د ن وع البروتوك ول المس تخدم ف ي ال Layer Upper س واء TCP أو... UDP 16 Bits لل Checksum وال تختلف طريقة حسابه عن الطريق ة المس تخدمة ف ي ال TCP أو الUDP والتي شرحناھا في الفصل األول. 32 Bits لتحديد عنوان الجھاز المرسل 32 Bits أخرى لتحديد عنوان الجھاز المستقبل وس ف نب ين ف ي الج زء الت الي م ن ھ ذا الفص ل طريق ة تولي د ال Unicast وال Broadcast والUnicast باستخدام الClassful وال : CIDR - Classless InterDomain Routing Classful IP Address : تعتبر عملية العنونة باستخدام الClassful بسيطة جدا ويقس م فيھ ا العن وان إل ى ج زأين يعب ر الجزء األول عن عنوان ال Network ID والجزء الثاني عن ال ID Host وكم ا ھ و موض ح في الشكل التالي: حيث يبدأ ال Class A من 1 إلى 126 ويكون قيمة الBit األول في الBinary صفر 0 ويبدأ Class B من 128 إلى 191 ويكون قيمة ال Bit األول في الBinary واحد 1 ويبدأ Class C من 192 إلى 223 ويكون قيمة ال Bit األول والثاني في الBinary واحد واحد أما Class D فيبدأ من 224 وتكون الثالثة Bits األولى منه 111 ويستخدم لتعبير عن ال Multicast Group...والشكل التالي يوضح ھذه التقسيمات: والستخراج عنوان ال Broadcast م ن أي م ن التقس يمات الس ابقة ي تم تعبئ ة ال Bits الخاص ة بالID Host بواحد وكمثال لمعرفة ال Broadcast Address للعنوان يج ب أوال تحديد إلى أي Class ينتمي ھ ذا العن وان وم ن الواض ح أن ه ينتم ي إل ى Class A ألن الج زء الخاص بال Network ID يبدأ ب 10 وھ و ب ين 1 وال 126 إذا الج زء الخ اص بال ID Host ~41~
42 ھو ولتحويله إلى Broadcast Address نضع قيمة 255 في الجزء الخاص بال Host Class لل Broadcast Address ويصبح العنوان كما يلي: وھو ال ID... Classful في الNation A لكن المشكلة في الNation Classful أنه محدود إلى درجة كبي رة فم ثال القيم ة العظم ى لع دد العناوين لل Class A ھو Host وكان الحل بإمكانية دمج ال Subnets لجع ل إمكاني ة توليد عناوين أكثر للPart Host وھو ما يسمى بالClassless... CIDR - Classless InterDomain Routing IP Address : وت تم ھ ذه العملي ة باس تئجار مجموع ة م ن ال Bits الخاص ة بال Part Network وض مھا إل ى الPart Host وكمثال لتوليد 1024 عنوان جديد من العنوان /24 نقوم باستئجار 2 Bits من الBits 24 الخاصة بال ID Network عن دھا يص بح ال Subnet كم ا يل ي : /22 ويص بح لل = 10 Bits Host ID أي 2 10 Addresses وكما ھو واضح في الشكل التالي: ولمعرفة ال Broadcast الخاص بالعنوان الجديد /22 نقوم بتقسيم ال 22 Bits على العنوان حيث كل جزء يأخذ 8 Bits وكما يلي: ث م نح ول ال one s ف ي الج زء الثال ث إل ى عش ري وس يكون ف ي المث ال 252 وھ ذا يعن ي أن الRange Addresses ستبدأ ب وستنھي ب إذا سيكون ال Broadcast IP ھو : الح ظ أن مش كلة المحدودي ة للعن اوين ق د حل ت بش كل جزئ ي باس تخدام ال CIDR لك ن مازال ت اإلمكانيات محدودة إذا أردنا توليد عناوين لمالي ن م ن األجھ زة وك ان الح ل ف ي ال IPv6 حي ث زاد فيه حجم العناوين من 32 Bits إلى 128 Bits والذي سيتم الحديث عن ه ف ي الج زء الت الي من ھذا الفصل. IPv6 Architecture : 2.2 ال IPv6 وھ و الجي ل الت الي لل IPv4 ح ل ال IPv6 الكثي ر م ن المش اكل الت ي تواج ه ال IPv4 ونلخصھا بمجموعة من النقاط: - الحاجة إلى عناوين أكثر حيث أن القيمة العظمى للAddress IPv4 تبقى محدودة م ع زي ادة الطلب على عناوين الIP s في العالم. - قد يؤدي الIPv4 إلى مجموعة من المشاكل وخاصة في Routing Table والتي قد تم حلھ ا في الIPv6 - مشكلة الSecurity في الIPv4 حيث لم يدعم أي من عمليات التشفير والتحقق وقد حلت ھذه المشكلة في الIPv4 Network على مستوى الLayer Authentication ~42~
43 باستخدام بروتوكول الIPSec حيث يتم تشفير الIP والPort على مستوى الSocket لكن أصبحت الحاجة ملحة لجعل ھذه الSecurity مدمجة على مستوى الLayer. Network - تطوير مبدأ الBroadcast حيث تم تطويره إلى الcast any إذ يتم إرسال رسالة واحدة إلى كل جھاز على الشبكة وفي حالة وجد الجھاز المعني يتوقف الRouter عن اإلرسال والھدف في ھذه الطريقة إيجاد طريقة تخفض من الBandwidth المستخدم عند البحث عن جھاز ما على الشبكة حل الIPv6 كل ھذه المشاكل حيث دعم ما يعادل Addresses وھو رقم كبير جدا كما قلل من حجم الTable Routing مما سرع عمليات التوجيه Routing كما دعم عمليات الAuthentication والتشفير على مستوى الLayer Network كم تم حذف ال Type of Services وحل محلھا الPriority أي األولويات ويوضح الشكل التالي الHeader الخاصة بالIPv6 : يستخدم الIPv6 ال hexadecimal بدال من الDecimal في الIPv4 لتمثيل العنوان وتكون الصيغة العامة له كما يلي كمثال: 69dc:8864:ffff:ffff:0:1280:8c0a:ffff الحظ انه يتكون من ثمانية منازل بدال من 4 بالIPv4 في كل منزلة يوضع بھا 16. Bits ولتمثيله في الHexadecimal نعطي 4 Digits لكل منزلة فيه وكما في الشكل التالي: Geographicbased Addresses وتقسم العناوين في الIPv6 إلى نوعين Provider-Based Addresses و حيث يقوم الISP s بتوزيع العناوين على الClients باستخدام الStandard الخاص Provider-Based Addresses وأما ال Geographic-based Addresses فھو مخصص إلعطاء العناوين الدولية أي انه سيكون لكل دولة رمز خاص يكون في بداية العنوان وكما يلي: ~43~
44 - Provider-Based Addresses a) Registry ID b) Provider ID c) Subscriber ID d) Subscriber Subnet e) Host Number - Geographic-based Addresses a) Registry ID b) World Zone c) Country, City, etc. الحظ الشكل التالي: وھك ذا بين ا ف ي ھ ذا الفص ل مب دأ عم ل ال IPv4 وال IPv6 وكيفي ة تولي د عن اوين ال Unicast والBroadcast باستخدام ال Classful وال. CIDR Nation سيتم الحديث في الفصل التالي عن ال IP Multicasting واستخدامھا لعمل الGroup Multicast في الدوت نيت... ~44~
45 Chapter 3 IP Multicasting Programming Overview - IP Multicasting Overview - Using IP Multicasting in Dot Net to Create a Multicast Groups ~45~
46 : IP Multicasting Overview :3.1 تحدثنا في الفصل األول عن برتوكول ال UDP وشرحنا كيفية استخدامه لعمل برود كاست حيث تستطيع عمل البرود كاست بطريقتين إما بجود Server يقوم بعملية التصنت على الPort المحدد و يستقبل من خالله أي رسالة ثم يقوم ببثھا إلى كل األجھزة أو باستخدام الIPAddress.Broadcast في طرف المرسل والذي من خالله يمكن عمل بث إلى كل األجھزة حيث ال ضرورة لوجود جھاز Server بحيث أن الكل يمكنه التصنت على ال Port المحدد و يستقبل ويرسل من خاللھا أي رسالة إلى كل األجھزة وتشبه عملية الBroadcast عملية البث اإلذاعي حيث أن الجميع يستمع من الكل ويرسل إلى الكل أما إذا أردنا تقسيم اإلرسال إلى مجموعات عندھا يجب استخدام ال IP Multicasting وذلك بھدف استخدامه لعمل ال Multicast Group يعتبر ھذا الموضوع من المواضيع المھمة جدا في برمجيات الشبكات ولھذا خصصت له فصل منفصل عن البقية (انظر الفصل التاسع) إذ أن اغلب برمجيات ال Conferences تعتمد عليه بشكل كبير ويعرف Multicast على انه اإلرسال إلى مجموعة من المستخدمين سواء كان Managed باستخدام Client/Server حيث يكون ھنالك جھاز Server في الشبكة وظيفته استقبال الرسائل من ال Client ثم إرسالھا إلى كامل المجموعة مرة أخرى انظر إلى الشكل التالي : الحظ انه يتم إرسال طلب االنضمام إلى المجموعة من قبل ال Clients وإذا وافق الServer على الطلب يقوم بضم عنوان الجھاز إلى ال IP Address List الخاصة به وتشترك كل مجموعة بنفس ال IP Multicast ويتم اإلرسال إلى جميع أعضاء المجموعة التي تشترك بنفس ال IP Multicast والذي يقع ضمن ال Class D وھو ما بيناه في الفصل السابق. النوع الثاني ويسمى بال peer-to-peer Technique - unmanaged حيث أن كل جھاز يعمل ك server و client في نفس الوقت وال وجود لجھاز Server مركزي مخصص لعملية االستقبال والتوزيع حيث تتم الموافقة على طلب االنضمام إلى المجموعة بشكل تلقائي وأي جھاز في المجموعة له الحق في االنضمام ثم االستقبال واإلرسال إلى كامل المجموعة الحظ الشكل التالي : ~46~
47 تم تخصيص عناوين خاصة لل Multicasting وھو ما يسمى بال IP Multicast Address وھي كما يلي : المدى من إلى لشبكات المحلية LAN المدى من إلى لل Internetwork المدى من إلى لل AD-HOC Network block Multicasting Group واستخدامھا لعمل IP Multicasting :3.2 قدمت الدوت نيت دعم جيد لل IP Multicast باستخدام ال Socket Namespace حيث يتم تعريفھا باستخدام الدالة SetSocketOption والذي نعرف من خالله ال IGMP Protocol والذي يقوم بإدارة عمليات االنضمام والخروج من والى المجموعة join) multicast group & leave ( كما يستخدم إلضافة وإلغاء العضوية AddMembership و DropMembership باإلضافة إلى العمليات المتعلقة بال Multicast Routing ويمكن استخدام الObject UdpClient لتحديد رقم الPort والذي سيتم استقبال البيانات من خالله باإلضافة إلى تعريف ال IP Multicasting والذي من خالله تحدد الجھات التي سوف تستقبل الرسالة حيث يستطيع أي شخص يتنصت على ھذا الPort ويستخدم نفس ال IP Multicast استقبال ھذه الرسالة يستخدم الكود التالي إلرسال رسالة إلى عدة جھات بحيث نستخدم رقم الPort 5020 و ضمن ال Group كمثال: using System; using System.Net; using System.Net.Socket; 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(" "), 5020); byte[] data = Encoding.ASCII.GetBytes("This is a test message"); server.sendto(data, iep); ~47~
48 server.close(); Imports System Imports System.Net Imports System.Net.Socket Imports System.Text Class MultiSend Public Shared Sub Main() Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Pars(" "), 5020) Dim data As Byte() = Encoding.ASCII.GetBytes("This is a test message") server.sendto(data, iep) server.close() End Sub End Class في البداية قمنا بتعريف الSocket وتحديد الجھة التي سوف تستقبل الرسالة وھي ) يأ Socket يتنصت على الشبكة باستخدام ال IP Multicast Group المحدد) ثم تحديد نوع الSocket والبرتوكول المستخدم... وإلنشاء برنامج االستقبال سوف نستخدم تعريف ال Socket نفسه ونضيف ال UdpClient التي نريد التصنت عليه ويمكن أيضا تحديد الTTL Port ونسند له رقم ال Object للPacket Multicast ويعبر عن عدد الRouters التي يسمح للPacket بالمرور من خاللھا وفي ھذا المثال حددناھا ب 50: Hops using System; using System.Net; using System.Net.Socket; using System.Text; class UdpClientMultiRecv public static void Main() UdpClient sock = new UdpClient(5020); sock.joinmulticastgroup(ipaddress.parse(" "), 50); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); ~48~
49 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(); Imports System Imports System.Net Imports System.Net.Socket Imports System.Text Class UdpClientMultiRecv Public Shared Sub Main() Dim sock As UdpClient = New UdpClient(5020) sock.joinmulticastgroup(ipaddress.parse(" "), 50) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim data As Byte() = sock.receive(iep) Dim stringdata As String = Encoding.ASCII.GetString(data, 0, data.length) Console.WriteLine("received: 0 from: 1", stringdata, iep.tostring) sock.close() End Sub End Class الحظ انه توجد طرق متعددة الستقبال البيانات و إرسالھا كما يمكن استخدام الكوديين السابقين في نفس البرنامج لإلرسال و االستقبال كما يمكنك إرسال صورة إلى جانب النص أو أي شيء أخر يمكن تحويله إلى Binary إذ ما عليك سوى إضافة ال memory Stream لتمثيل الصورة ك Byte Array إلى كود اإلرسال و االستقبال كما يمكنك عمل برنامج إلرسال أوامر إلى ال Clients لتحكم بھم عن بعد وكمثال عمل Shutdown لجميع األجھزة التي تعمل على نفس ال Multicast Group ويمكنك أيضا عمل برنامج إلرسال صورة عبر الكاميرا إلى جھات متعددة باستخدام نفس الخاصية والتي سآتي على شرحھا في الفصل التاسع... Advanced Multicast Systems ~49~
50 Part 2 Streaming in Dot Net Chapter4 Streaming in Dot Net Chapter5 Applied Streaming in Dot Net ~50~
51 Chapter 4 Streaming in Dot et Managed I/O: Streams, Readers, and Writers - Stream Classes - Stream Members - Stream Manipulation ~51~
52 : Managed I/O: Streams, Readers, and Writers : 2.1 إن الھدف من إنشاء مكتبات ال Stream تسھيل عملية نقل البيانات من مكان إلى آخر سواء عبر الشبكة أو ضمن الComputer Local كما ھو الحال بتعامل مع الملفات أو التعامل مع الطابعة أو أي طرفية أو جھاز آخر موصول بالكمبيوتر حيث تسھل علينا عملية تحويلھا إلى Byte Array وإرسالھا وھو ما حل الكثير من المشاكل التي كانت تواجه المبرمجين في التعامل مع.. Binary Data يمكن التعامل مع الStream بأسلوبين المتزامن Synchronous والغير متزامن Asynchronous وبشكل افتراضي تعمل جميع الStreams IO باألسلوب المتزامن لكن العيب فيه ھو تأثيره الشديد على أدائية النظام إذ يقوم بإغالق الUnit Processing في الThread المخصصة للبرنامج بحيث ال يسمح بتنفيذ أي أمر آخر إال بعد االنتھاء من العملية الجارية وال ينصح ابدآ استخدام األسلوب المتزامن في حالة إذا كنت تتعامل مع أجھزة قراءة وكتابة بطيئة نسبيا مثل الDisk Floppy أو الTape Magnetic لكنھا مھمة جدا بالبرمجيات التي تعتمد على أنظمة الزمن الحقيقي أو الSystems Real Time حيث أنھا تعتمد األسلوب المتزامن في عملية إرسال واستقبال البيانات وھو ما يمنع القيام بأي عملية أخرى إلى حين االنتھاء من تنفيذ األمر ومن األمثلة عليھا أنظمة السحب أو اإليداع في الرصيد البنكي أو أنظمة حجز التذاكر أو شحن بطاقة الھاتف وغيرھا.. طبعا في حالة إذا كان برنامجك ال يحتاج إلى وجود الخواص السابقة عندھا ينصح باستخدام األسلوب الغير متزامن Asynchronous حيث تستطيع من خالله تنفيذ عمليات أخرى في وحدة المعالجة وبدون الحاجة النتظار إنھاء العملية الجارية إذ يتم إنشاء Separate thread لكل عملية طلب إدخال أو إخراج مما ال يؤثر على أدائية النظام وينصح باستخدامه إذا كانت عملية القراءة أو الكتابة تجرى من خالل أجھزة بطيئة نسبيا ويمكن تميز الدوال المتزامن عن الغير متزامن في الدوت نيت بوجود كلمة Begin أو End في بداية اسم الدالة الغير متزامن وكمثال عليھا.. الEndRead و و الEndWrite BeginRead و BeginWrite أوال: Stream Classes تدعم الدوت نيت عمليات الStreams بمجموعة من الClasses والمندرجة تحت System.IO Namespace والتي تستخدم لعمليات اإلدخال و اإلخراج لنقل البيانات. تستخدم بعض الClasses Backing storage Stream ومن األمثلة عليھا FileStream و الBufferedStream والMemoryStream وكذلك فإن بعضھا ال يستخدم أي Back Storage ومن األمثلة عليھا الNetworkStream والتي تستخدم لنقل الStream عبر الشبكة وبدون استخدام Backing Storage و تقسم الClasses Stream في الدوت نيت كما في الشكل التالي : ~52~
53 1- Class : BufferedStream ويستخدم بشكل أساسي لحجز مقدار معين من الذاكرة بشكل مؤقت لتنفيذ عملية معينة كما تستخدم بعض البرمجيات الBuffering لتحسين األدائية حيت تكون كذاكرة وسيطة بين المعالجة واإلرسال أو االستقبال وكمثال عليھا برمجيات الطباعة حيث تستخدم الطابعة ذاكرة وسيطة لتخزين البيانات المراد طباعتھا بشكل مؤقت و يكمن الھدف األساسي من استخدام الBuffering في العمليات التي يكون فيھا المعالج أسرع من عمليات اإلدخال و اإلخراج حيث يتم معالجة البيانات ووضعھا في الBuffer في انتظار إرسالھا وھو ما يساھم في تحسين األدائية بشكل كبير ويستخدم الBufferedStream عادتا في برمجيات الشبكات مع الNetworkStream لتخزين البيانات المراد إرسالھا عبر الشبكة في الذاكرة حيث ال يستخدم ھذا الكالس Backing storage كما ذكرنا سابقا.. بشكل افتراضي يتم حجز 4096 bytes عند استخدام الBufferedStream ويمكن زيادتھا أو تقليلھا حسب الحاجة.. ويستخدم الBufferedStream كما يلي كمثال : C# 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); ~53~
54 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)); Imports System Imports System.Text Imports System.IO Namespace Network_Buffering Class Program Shared Sub Main(ByVal args As String()) Dim asen As ASCIIEncoding = New ASCIIEncoding Dim xx As Byte() = asen.getbytes("hello Buffering") Dim ms As MemoryStream = New MemoryStream(xx) readbufstream(ms) End Sub Public Shared Sub readbufstream(byval st As Stream) Dim bf As BufferedStream = New BufferedStream(st) Dim indata(st.length) As Byte bf.read(indata, 0, Convert.ToInt32(st.Length)) Console.WriteLine(Encoding.ASCII.GetString(inData)) End Sub End Class End Namespace حيث قمنا بتحويل نص إلى Byte Array باستخدام الASCIIEncoding وتحميله في عبر الMemoryStream ثم ارسلناه إلى الدالة readbufstream والتي انشأناھا حيث استقبلنا من خاللھا الStream وحملناه في ذاكرة مؤقتة باستخدام الكالس الBufferedStream ثم قمنا بطباعة محتوياته بعد تحويله إلى نص مرة اخرى باستخدام ال Encoding.ASCII وطباعته.. 2- Class : MemoryStream وھو شبيه بعملية الBuffring السابقة إذ يعتبر كحل جيد لتخزين البيانات بشكل مؤقت في الذاكرة ك Stream Data قبل اإلرسال أو األستقبال حيث يغنيك عن تخزينھا على شكل ملف مما يسرع العملية بشكل كبير ويستخدم ايضا إلجراء عمليات التحويل من Byte إلى Stream والعكس ويستخدم كما يلي كمثال حيث استخدمنھا لتخزين صورة في الذاكرة : ~54~
55 C# MemoryStream ms = new MemoryStream(); picturebox1.image.save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] arrimage = ms.getbuffer(); ms.close(); Dim ms As MemoryStream = New MemoryStream picturebox1.image.save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrimage As Byte() = ms.getbuffer ms.close 3- Class etworkstream :ويستخدم لتعامل مع الStream إلرساله عبر الشبكة باستخدام الSocket ويتم استدعائھا من System.Net.Socket Namespaces ويعتبر الكالس NetworkStreamبأنه unbuffered إذ ال يحتوي على Backing Storage ويفضل استخدام الClass BufferedStream معه لتحسين األداء وتستخدم كما يلي كمثال حيث نريد إرسال الصورة التي قمنا بتخزينھا في المثال السابق بذاكرة إلى جھاز آخر عبر الSocket : C# 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 (); Dim myclient As TcpClient = New TcpClient(localhost, 5020) Dim myns As NetworkStream = myclient.getstream Dim mysw As BinaryWriter = New BinaryWriter(myns) mysw.write(arrimage) mysw.close myns.close myclient.close 4- FileStream : يتم استدعائھا باستخدام System.IO Namespaces وتستخدم بشكل اساسي في التعامل مع الملفات سواء للكتابة إلى ملف أو القراءة من ملف ويستخدم ايضا لتحويل الملف إلى Byte Array وحتى يسھل نقله عبر الشبكة و يعتبر ھذا الكالس Backing Storage Class حيث تستخدم ذاكرة Buffer لتحزين البيانات بشكل مؤقت في الذاكرة لحين اإلنتھاء من عملية الكتابة أو القراءة ومن األمور الھامة فيھا تحديد مسار الملف المراد القراءة منه أو الكتابة عليه وتستخدم كما يلي : ~55~
56 C# FileStream FS = new FileStream(@"C:\MyStream.txt", FileMode.CreateNew);// Any Action For Example CreateNew to Create Folder Dim FS As FileStream = New FileStream("C:\MyStream.txt", FileMode.CreateNew) يمكننا استخدام الEnumeration التالية مع الFileMode : 1- Append إلضافة نص ما إلى الملف الموجود اصال 2- Create إلنشاء ملف جديد ويقوم بعمل overwriting في حالى إذا كان الملف موجود بشكل مسبق 3- CreateNew وھو كما في الCreate إال انه يعطي Exception في حالة وجود الملف بشكل مسبق 4- Open لقراءة ملف ما حيث يعطي Excption في حالة عدم وجود الملف المحدد 5- OpenOrCreate في حالة إذا وجد الملف يقوم بقراءته وفي حالة عدم وجوده يقوم بإنشائه. 6- Truncate ويستخدم لحذف محتويات الملف وجعله فارغا. لمزي د م ن المعلوم ات ح ول اس تخدام ال FileStream انظ ر الفص ل الس ابع عش ر FTP. Programming ~56~
57 ثانيا : Members : Stream ھنال ك مجموع ة م ن الخ واص الStream وھي كما يلي : و ال Methods (Members) الت ي تش ترك بھ ا مكتب ات 1- CanRead و CanWrite وتستخدم لمعرفة إذا كان الStream المستخدم يقبل عملية القراءة أو الكتابة أم ال حيث ترجع قيمة True في حالة إذا كان يقبل و False في حالة أنه ال يقبل ويستخدم عادة قبل إجراء عملية القراءة أو الكتابة لفحص مدى الصالحية قبل المحاولة.. 2- CanSeek حيث يستخدم الSeeking عادة لتحديد موقع الStream Current وترجع ھذه الخاصية قيمة True في حالة كان الStream يدعم الSeeking و False في حالة أنه ال يدعم الSeeking وفي العادة تدعم الClasses التي تستخدم Backing Storage ھذه العملية مثل الFileStream وعندھا ترجع قيمة. True 3- CanTimeout وترجع قيمة True في حالة إذا كان الstream يحتوي على خاصية الTimeout والتي تعطي وقت محدد للعملية. 4- Length وتستخدم لمعرفة حجم الStream بالByte ويمكن االستفادة منھا لمعرفة نھاية الStream أو لتحديد حجم المصفوفة بناء على حجم الStream. Stream لمعرفة أو تحديد موقع ال Set و وتستخدم الGet Position 5- وتشترك مكتبات الStream بمجموعة من الMethods وھي كما يلي : الدوال المتزامنة : Synchronous Methods Read I. و ReadByte وتستخدم لقراءة Stream Data وتخزينه في الBuffer ويمكن تحديد عدد البايتات التي سيتم قراءتھا باستخدام الReadByte كما نستطيع من خاللھا معرفة نھاية الStream حيث ترجع الRead قيمة 0 والReadByte قيمة -1 في حالة انتھاء الStream. Write.II والWriteByte وتستخدم لعملية اإلرسال عبر الStream ويمكن تحديد عدد البايتات التي سيتم كتابتھا في كل مرة باستخدام الWriteByte. الدوال غير المتزامنة : Asynchronous Methods BeginRead I. والBeginWrite وتستخدم لعملية القراءة أو الكتابة باستخدام الStream الغير المتزامن وتأخذ خمسة باروميترات كما في الشكل التالي : -1-2 الBuffer Byte والتي سوف تستخدم لعملية القراءة منه أو الكتابة عليه الoffset وھو المؤشر أو ال Pointer والذي نستطيع تحديد موقع القراءة أو الكتابة من وعلى الBuffer. ~57~ -1-2
58 الnumByte والذي سوف يتم فيه تحديد الحد األقصى من البايتات التي سيتم كتابتھا أو قراءتھا. الAsyncCallback وھو Optional Delegate حيث يتم استدعائه إلنھاء عملية القراءة أو الكتابة بدون حجز ال Thread وحتى يبقى ال Stream في وضعية االنتظار. الStateobject وھو User Provided Object ويستخدم لتميز ال & Read. عن غيره من الRequests Write Request ترجع الMethods Begin الIAsyncResult والذي يمثل حالة ال Stream. Operation وھناك بعض الدوال والتي تستخدم إلدارة الStream وھي : 1- Flush وتس تخدم لتفري غ محتوي ات ال Buffer بع د إتم ام العملي ة المح ددة حي ث ي تم نق ل محتويات الBuffer إلى الDestination الذي تم تحديده في ال.Stream Object 2- Close وتس تخدم إلغ الق ال Stream وتحري ر ال Resources المحج وزة م ن قب ل الObject Stream وينصح باستخدامھا في الجزء الخاص ب Finally block ولتأك د م ن أن الStream سيتم إغالقه وتحري ر كاف ة الم وارد ف ي حال ة ح دوث أي Exception إثن اء التنفي ذ ولضمان عدم بقاء ھذه الموارد في الذاكرة بعد إغالق البرنامج. 3- SetLength وتس تخدم لتحدي د حج م ال Stream وال ذي نري د إرس اله أو اس تقباله لك ن ف ي حال ة إذا ك ان ال Stream أق ل م ن المح دد ف ي ال SetLength س وف ي ؤدي ذال ك إل ى انقط اع الStream وعدم وصوله بش كل س ليم ل ن تس تطيع اس تخدام ھ ذه الخاص ية إال إذا تأك دت ان ك تمل ك الص الحية ل ذلك م ن خ الل الخاص ية CanWrite و CanSeek ل ذا ينص ح بفح ص الصالحية أوال قبل تحديد حجم الStream. ثالثا : Manipulation :Stream يمك ن اس تخدام مكتب ات ال Stream لنق ل Binary Data أو Text وف ي الع ادة ي تم اس تخدام ال BinaryReader و ال BinaryWriter لتعام ل م ع ال Data Binary وي تم اس تخدام ال StreamReader وال StreamWriter لتعام ل م ع ال Text وي تم اس تخدام ال ASCIIEncoding أو UnicodeEncoding لتحوي ل م ن Stream إل ى Text عن د االستقبال ومن Text إلى Stream عند اإلرسال حيث تستخدم مجموع ة م ن ال دوال وھ ي كم ا في الشكل التالي : -1 GetByteCount وھ ي Overloaded Method حي ث تأخ ذ Character Array أو String وترجع عدد البايتات التي سوف نحتاجھا لنقل نص معين.. ~58~
59 2- GetBytes لتحوي ل ال String إل ى Byte Array حت ى نس تطيع إرس الھا باس تخدام الStream. 3- GetCharCount حيث تأخذ Byte Array وترجع عدد األحرف التي سوف تك ون ف ي الString أو في الArray. Character 4- GetChars وتس تخدم لتحوي ل م ن Byte Array إل ى String وتس تخدم عن د اس تقبال البيانات من الStream حيث نحولھا إلى نص مرة أخرى. ولتعامل م ع ال StreamReader و ال StreamWriter لنق ل Text يج ب أوال اس تدعائھا م ن الSystem.IO Namespace وتستخدم كما يلي: StreamReader للقراءة من ملف: C# StreamReader str = File.OpenText(openFileDialog1.FileName); textbox1.text = str.readtoend(); Dim str As StreamReader = File.OpenText(openFileDialog1.FileName) textbox1.text = str.readtoend C# string fname = savefiledialog1.filename; StreamWriter fsave = new StreamWriter(fname); fsave.writeline(textbox1.text); Dim fname As String = savefiledialog1.filename Dim fsave As StreamWriter = New StreamWriter(fname) fsave.writeline(textbox1.text) StreamWriter للكتابة إلى ملف: و لتعام ل م ع ال BinaryReader وال BinaryWriter لنق ل Binary Data ي تم اس تدعائھا من الSystem.IO Namespace حيث تستخدم BinaryReader لقراءة Binary Data م ن ال Stream وال BinaryWriterr إلرس ال BinaryData إل ى ال Stream عب ر الSocket وكما يلي كمثال: C# NetworkStream myns = new NetworkStream(mysocket); BinaryReader br = new BinaryReader(myns); TcpClient myclient = new TcpClient("localhost", 5020); NetworkStream myns = myclient.getstream(); BinaryWriter mysw = new BinaryWriter(myns); mysw.write(arrimage); ~59~
60 Dim myns As NetworkStream = New NetworkStream(mysocket) Dim br As BinaryReader = New BinaryReader(myns) Dim myclient As TcpClient = New TcpClient("localhost", 5020) Dim myns As NetworkStream = myclient.getstream Dim mysw As BinaryWriter = New BinaryWriter(myns) mysw.write(arrimage) وھكذا بينا أھم مكتبات الStream في الدوت نيت وطرق التعامل معھا والفرق بين الStreams المتزامن والغير متزامن سوف نطبق في الفصل التالي مجموعة من األمثلة العملية على الSteaming في بيئة الدوت نيت... ~60~
61 Chapter 5 Applied Streaming in Dot et - Create a Simple Remote Control Application Using StreamReader & StreamWriter Classes - Create a Remote Desktop Application By Using TCP Streaming Connection - Create a Simple Application to Store & Read Images (Binary Data) in Microsoft Access & Microsoft SQL Server Database Management System By Using Streams Library & ADO.NET ~61~
62 المقدمة: سوف نناقش في ھذا الفصل مجموعة من التطبيقات باستخدام ال TCP Streaming ومنھا نظام لتحكم عن بعد بإطفاء وتشغيل البرامج وإطفاء وتشغيل األجھزة ونظام آخر لمراقبة سطح المكتب عن بعد وأخيرا طريقة تخزين الData Binary في قواعد البيانات Access و SQL Server Database باستخدام مكتبات الStreams. :Stream Reader & باستخدام الWriter Remote Control Example 5.1 مث ال تطبيق ي بس يط س وف نس تخدم في ه برن امج ش بيه ب Chatting لك ن س يتم اس تخدامه إلعطاء أوامر إلى الServer حيث يفترض إذا قمنا بإرسال كلمة notepad إلى ال server بأن يقوم بفتح الnotepad فيه وإذا قمنا مثال بكتابة Calc وإرسالھا إلى الServer سوف يفتح اآللة الحاسبة فيه وھكذا : أوال : إنش اء برن امج اإلرس ال : Client ال يختل ف برن امج اإلرس ال ع ن برن امج ال Client TCP Connection م ن ك ل في ه ويس تخدم ال Chapter1 ف ي بإنش ائه قمن ا ال ذي Chat وال NetworkStream و ال StreamWriter إلج راء عملي ة اإلرس ال فباس تخدام الدال ة WriteLine الموجودة ضمن الObject StreamWriter تتم عملية تحوي ل ال نص المكت وب في الTextbox إلى مجموعة من الBytes ليتم إرسالھا باستخدام الNetworkStream عبر الConnection TCP Socket إلى برنامج الServer وللبدء ق م بإنش اء مش روع جدي د كم ا في الشكل التالي : C# using System.Net.Socket ; using System.IO; imports System.Net.Socket imports System.IO ثم قم بإضافة ال Namespaces التالية : في Send Button قم بكتابة الكود التالي: try TcpClient myclient = new TcpClient (txt_host.text,5020); NetworkStream myns = myclient.getstream (); StreamWriter mysw = new StreamWriter (myns); mysw.writeline(txt_msg.text); ~62~
63 mysw.close (); myns.close (); myclient.close (); catch (Exception ex) MessageBox.Show (ex.message ); Try Dim myclient As TcpClient = New TcpClient(txt_host.Text, 5020) Dim myns As NetworkStream = myclient.getstream Dim mysw As StreamWriter = New StreamWriter(myns) mysw.writeline(txt_msg.text) mysw.close myns.close myclient.close Catch ex As Exception Msgbox(ex.Message) End Try وإلنش اء برن امج ال Server وال ذي يعم ل عل ى اس تقبال ال Stream وتحويل ه إل ى Text م رة أخرى.. قم بإنشاء مشروع جديد كما في الشكل التالي : C# using System.Net.Socket ; using System.IO; using System.Threading; ثم قم بإضافة ال Namespaces التالية : imports System.Net.Socket imports System.IO imports System.Threading ثم إضافة التعاريف التالية إلى منطقة ال : Global Declaration TcpListener mytcpl; Socket mysocket; NetworkStream myns; StreamReader mysr; ~63~
64 Private mytcpl As TcpListener Private mysocket As Socket Private myns As NetworkStream Private mysr As StreamReader وإنشاء دالة الServer والتي ستستقبل الCommands من الClients : void our_server () mytcpl = new TcpListener (5020); mytcpl.start (); mysocket = mytcpl.acceptsocket (); myns = new NetworkStream (mysocket); mysr = new StreamReader (myns); 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(); if (mysocket.connected ==true) while (true) our_server (); Sub our_server() mytcpl = New TcpListener(5020) mytcpl.start() mysocket = mytcpl.acceptsocket myns = New NetworkStream(mysocket) mysr = New StreamReader(myns) Dim order As String = mysr.readline If order = "notepad" Then System.Diagnostics.Process.Start("notepad") Else If order = "calc" Then System.Diagnostics.Process.Start("calc") Else ~64~
65 Msgbox("Sorry Sir Your Request is not in my hand", order) End If End If mytcpl.stop() If mysocket.connected = True Then While True our_server() End While End If End Sub حيث تقوم ھذه الدالة بتصنت على الSocket في حالة ورود أي Request يقوم بالموافقة عليه وإنش اء Session جدي دة مع ه وف ي حال ة ورود أي بيان ات عب ر ال Socket يتس لمھا باس تخدام ال StreamReader ويحولھ ا إل ى Text ث م نق وم بفح ص الرس الة باس تخدام الجم ل الش رطية فم ثال إذا كان ت الرس الة ھ ي notepad ي تم اس تدعائھا باس تخدام الدال ة Start الموج ودة ض من الكالس Process والموجودة في...System.Diagnostics Namespaces ولتش غيلھا ض من Thread جدي د الب د م ن وض ع تعري ف ال Thread ف ي ح دث ب دأ التش غيل للForm كما يلي : C# Thread myth; private void Form1_Load(object sender, System.EventArgs e) myth= new Thread (new System.Threading.ThreadStart(our_Server)); myth.start (); Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim myth As Thread myth = New Thread(New System.Threading.ThreadStart(our_Server)) myth.start() End Sub ث م ق م بإض افة الت الي ف ي ح دث ال Closing Form وذل ك لتأك د م ن إغ الق ال Socket والStream وإنھاء الThread في البرنامج.. private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) try mytcpl.stop (); myth.aport(); ~65~
66 catch (Exception ex) MessageBox.Show (ex.message ); Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Try mytcpl.stop() myth.aport(); Catch ex As Exception Msgbox(ex.Message) End Try End Sub كما يمكننا بنفس الخطوات السابقة إنشاء برنامج يقوم بإطفاء الComputer Clients عن بع د وذلك بتنفيذ الملف Shutdown.EXE (والمرفق مع الكتاب) عند ورود كلمة Shutdown أو تنفيذ أمر ال RPC Remote Procedure Call والذي يأتي مع نظام التشغيل Windows. 2000/XP ~66~
67 5.2 مثال إلنشاء نظام Remote Desktop إلرسال صورة سطح المكتب إلى ال :Server في ھذا المثال سنقوم بإنشاء برنامج Remote Desktop بسيط لنقل صورة سطح المكتب من جھاز إلى آخر باستخدام ال TCP وال : Stream Library أوال إنشاء برنامج ال : Client لتطبيق سنقوم بإنشاء مشروع جديد كما في الشكل التالي: System.Net System.Net.Socket System.IO سوف نستخدم ال Namespaces التالية: تتم عملية التقاط صورة سطح المكتب باستخدام دوال ال API إذ ان ه ال يوج د مكتب ة معين ة ف ي الدوت نيت إلجراء ھذه العملية وقد قمت بكبسلة ھذه الدوال ف ي المل ف CaptureScreen.dll لتس ھيل اس تخدامھا الحق ا واللتق اط ص ورة س طح المكت ب نس تخدم الدال ة Image ك المكت ب حيث ترجع صورة س طح CaptureScreen.GetDesktopImage() وإلرس الھا الب د م ن تحوي ل ھ ذه الص ورة إل ى Stream ووض عھا ف ي ال Buffer قب ل عملي ة اإلرسال وتتم ھذه العملية باستخدام ال MemoryStream Class والذي شرحناه سابقا وكما يلي: MemoryStream ms = new MemoryStream(); Image img = CaptureScreen.GetDesktopImage(); img.save(ms,system.drawing.imaging.imageformat.jpeg); byte[] arrimage = ms.getbuffer(); Dim ms As MemoryStream = New MemoryStream Dim img As Image = CaptureScreen.GetDesktopImage() img.save(ms,system.drawing.imaging.imageformat.jpeg) Dim arrimage As Byte() = ms.getbuffer() وإلرسال الصور الملتقطة إلى الجھاز اآلخر البد من تعريف Socket وكما يلي في حالة استخدام : TCP Socket TcpClient myclient; MemoryStream ms; NetworkStream myns; ~67~
68 BinaryWriter mysw; myclient = new TcpClient (Server_IP.Text,5020); myns = myclient.getstream (); mysw = new BinaryWriter (myns); mysw.write(arrimage); ms.close(); mysw.close (); myns.close (); myclient.close (); Dim myclient As TcpClient Dim ms As MemoryStream Dim myns As NetworkStream Dim mysw As BinaryWriter myclient = New TcpClient (Server_IP.Text,5020) myns = myclient.getstream () mysw = New BinaryWriter (myns) mysw.write(arrimage) ms.close() mysw.close () myns.close () myclient.close () ويمكننا وضع ھذا الكود ضمن Infinity Loop Method ومن ثم إنشاء New Thread لھ ا أو نضعھا في Timer ويحدد ال Interval فيه بن اء عل ى س رعة اإلرس ال الت ي نحتاجھ ا م ن جھة ومقدرة الشبكة من جھة أخرى وكشبكة LAN فإن 100 MS تعتبر ممتازة. ~68~
69 ثانيا إنشاء برنامج ال : Server ولتطبيقه سنقوم بإنشاء مشروع جديد كما في الشكل التالي: سوف نستخدم ال Namespaces التالية: System.Net System.Net.Socket System.IO ثم نعرف ال TCP Socket وال Thread وال TCP Listener كما يلي: Thread myth; TcpListener mytcpl = new TcpListener (5020); Socket mysocket; NetworkStream myns; Dim myth As Thread Dim mytcpl As TcpListener = New TcpListener(5020) Dim mysocket As Socket Dim myns As NetworkStream void ServerMethod () try ثم نقوم بتعريف دالة االستقبال وكما يلي : mytcpl.start (); ~69~
70 mysocket = mytcpl.acceptsocket (); myns = new NetworkStream (mysocket); picturebox1.image = Image.FromStream(myns); mytcpl.stop(); if (mysocket.connected ==true) while (true) ServerMethod (); myns.flush(); catch (Exception) Private Sub ServerMethod() Try mytcpl.start() mysocket = mytcpl.acceptsocket() myns = New NetworkStream(mysocket) picturebox1.image = Image.FromStream(myns) mytcpl.stop() If mysocket.connected = True Then Do While True ServerMethod() Loop End If myns.flush() Catch e1 As Exception End Try End Sub ولتشغيل ال Thread نضع الكود التالي في حدث بدأ التشغيل لل : Form myth= new Thread (new System.Threading.ThreadStart(ServerMethod)); myth.start (); ~70~
71 myth= New Thread (New System.Threading.ThreadStart(AddressOf ServerMethod)) myth.start () وھكذا بينا طريقة إرسال صورة سطح المكت ب م ن جھ از إل ى آخ ر س وف نب ين ف ي الج زء الخاص بالنظم الموزعة (الفصل الخ امس عش ر) كيفي ة إض افة خاص ية ال تحكم بال Mouse والKeyboard للRemoteServer وذلك باستخدام دوال الAPI. 5.3 مث ال لتخ زين ص ورة ف ي قاع دة بيان ات Access و SQL Server باس تخدام الADO. ET ومكتبات الStream : سنس تخدم ف ي ھ ذا المث ال ال Memory Stream Class لتمثي ل ص ورة بال ذاكرة عل ى ش كل GetBuffer Method باس تخدام الحق ا Bytes إل ى تحويلھ ا يمكنن ا حي ث Stream Data وكما يلي: try MemoryStream stream = new MemoryStream(); picturebox.image.save(stream,system.drawing.imaging.imageformat. Jpeg); byte[] arr = stream.getbuffer(); Store_it (arr); catch(exception ex) MessageBox.Show(ex.Message); VB. ET Try Dim stream As MemoryStream = New MemoryStream picturebox.image.save(stream,system.drawing.imaging.imageformat. Jpeg) Dim arr As Byte() = stream.getbuffer() Store_it (arr) Catch ex As Exception MessageBox.Show(ex.Message) End Try أوال استخدام : Microsoft Access بعد تحويل الصورة إلى Byte Array سنرسلھا إلى ال Store_it Method والت ي سنس تخدم من خاللھا الOleDbParameter لتمرير الArray Byte إلى الDatabase وكما يلي: ~71~
72 public void Store_it (byte[] content) try oledbconnection1.open(); OleDbCommand insert = new OleDbCommand( "insert into img values (?)",oledbconnection1); insert.parameters.add(new OleDbParameter("@pic", OleDbType.Binary)).Value = content; insert.executenonquery(); catch(exception ex) MessageBox.Show(ex.Message); finally oledbconnection1.close(); VB. ET Public Sub Store_it(ByVal content As Byte()) Try oledbconnection1.open() Dim insert As OleDbCommand = New OleDbCommand("insert into img values (?)", oledbconnection1) insert.parameters.add(new OleDbParameter("@pic", OleDbType.Binary)).Value = content insert.executenonquery() Catch ex As Exception MessageBox.Show(ex.Message) Finally oledbconnection1.close() End Try End Sub وتتم عملية قراءة الصورة من قاعدة باستخدام الطريقة المعتادة لقراءة البيانات لكن يجب أن يتم تحويل الData Binary والتي سيتم وضعھا ف ي ال Dataset إل ى Stream م رة أخ رى وت تم ھذه العملية كما يلي: oledbdataadapter1.selectcommand.commandtext = "select * from img"; ~72~
73 oledbdataadapter1.fill(dspictures1); byte[] arrpicture = ((byte[]) (dspictures1.tables[0].rows[0]["pic"])); MemoryStream ms = new MemoryStream(arrPicture); picturebox2.image = Image.FromStream(ms); VB. ET oledbdataadapter1.selectcommand.commandtext = "select * from img" oledbdataadapter1.fill(dspictures1) Dim arrpicture As Byte() = (CType(dsPictures1.Tables(0).Rows(0)("pic"), Byte())) Dim ms As MemoryStream = New MemoryStream(arrPicture) picturebox2.image = Image.FromStream(ms) حي ث قمن ا بعم ل Casting لمخرج ات ال Dataset وتخزينھ ا ف ي Byte Array وبع د ذل ك وبتمري ر ال Array إل ى ال Class MemoryStream س يتم تحوي ل ال Array Byte إل ى FromStream باستخدام ال PictureBox مرة أخرى وعندھا يمكننا عرضھا على Stream... Method ثانيا استخدام : Microsoft SQL Server ال تختلف عملية التخزين بقاعدة بيانات SQL Server عن الAccess Microsoft سوى انه ي تم اس تخدام ال SqlParameter ب دال م ن OleDbParameter كم ا أن ص يغة ال String Connection س تختلف ب ين ال Database Access وال SQL Server Database حيث يمرر لألول مسار المل ف الخ اص بقاع دة البيان ات أم ا الث اني فيم رر ل ه اس م الجھاز الذي يحتوي على ال SQL Server وكما يلي كمثال: إلنشاء ال :Connection String string SQL_CONNECTION_STRING = "Server=SQL_SERVER_NAME;DataBase=DB_NAME;Integrated Security=SSPI"; VB. ET Dim SQL_CONNECTION_STRING As String = "Server=SQL_SERVER_NAME;DataBase=DB_NAME;Integrated Security=SSPI" ثم يمرر إلى ال Connection Object كما يلي: SqlConnection My_Connection = new SqlConnection(connectionstring); ~73~
74 VB. ET Dim My_Connection As SqlConnection = New SqlConnection(connectionstring) لتخزين الصورة في قاعدة البيانات : SQL Server public void Store_it (byte[] content) try My_Connection.Open(); SqlCommand insert = new SqlCommand( "insert into img values (@pic)",my_connection); insert.parameters.add(new SqlParameter("@pic", SqlDbType.Binary)).Value = content; insert.executenonquery(); catch(exception ex) MessageBox.Show(ex.Message); finally My_Connection.Close(); VB. ET Public Sub Store_it(ByVal content As Byte()) Try My_Connection.Open() Dim insert As SqlCommand = New SqlCommand("insert into img values (@picid)", My_Connection) insert.parameters.add(new SqlParameter("@pic", SqlDbType.Binary)).Value = content insert.executenonquery() Catch ex As Exception MessageBox.Show(ex.Message) Finally My_Connection.Close() End Try End Sub ولعرض الصورة في Picture Box مرة أخرى : SqlDataAdapter.SelectCommand.CommandText = "select * from img"; SqlDataAdapter.Fill(dsPictures1); byte[] arrpicture = ((byte[]) (dspictures1.tables[0].rows[0]["pic"])); MemoryStream ms = new MemoryStream(arrPicture); ~74~
75 picturebox2.image = Image.FromStream(ms); VB. ET SqlDataAdapter.SelectCommand.CommandText = "select * from img" SqlDataAdapter.Fill(dsPictures1) Dim arrpicture As Byte() = (CType(dsPictures1.Tables(0).Rows(0)("pic"), Byte())) Dim ms As MemoryStream = New MemoryStream(arrPicture) picturebox2.image = Image.FromStream(ms) سيتم الحديث في الجزء التالي عن استخدام Transport Layer & etwork Layer Programming وبرمجة بروتوكوالتھا في بيئة الدوت نيت. ~75~
76 Part 3 Transport & Network Layer Programming Chapter6 Transport TCP & UDP (Classes & Members) Chapter7 Synchronous Socket Programming Chapter8 Asynchronous Socket Programming Chapter9 Advanced Multicasting Systems Chapter10 Voice Over IP Programming Chapter11 Raw Socket Programming ~76~
77 Chapter 6 Transport TCP & UDP (Classes & Members) - TCP Classes Members - UDP Classes Members ~77~
78 : TCP & UDP Classes Members : 6 س وف نتح دث ف ي ھ ذا الفص ل ع ن ال TCP Classes وال UDP Classes واھ م الMembers لكل منھما والتي يتم التعامل معھا في ال Transport Layer Classes ومن المع روف أن ف ي ھ ذه الطبق ة إذا اس تخدمنا ال TCP يمك ن ال تحكم بخص ائص اإلرس ال ومنھ ا الOffset وال Flags باإلضافة إلى وضع وتحديد ال Source و الPort Destination ل دى الطرف المرسل والمستقبل. أوال الHeader TCP ويتكون من 32 Bits لل Packet الواحد حي ث ي تم في ه تخ زين عن وان Port المرس ل ف ي 16 Bits والمس تقبل ف ي 16 Bits وال رقم التسلس لي ف ي 32 Bits ورق م التحقق باإلضافة إلى الChecksum وفي النھاية يتم وضع الجزء الخاص بالبيانات وھو ما ت م شرحه في الفصل األول بتفصيل الحظ الشكل التالي: TCP Header 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. ثانيا الHeader UDP ويتكون م ن 32 Bits م ن البيان ات لل Packet الواح د ويحت وي عل ى عنوان المرسل 16 Bits والمستلم 16 Bits و الChecksum وال :Total Length UDP Header ~78~
79 أوال الClasses الخاصة بال : TCP Connection Oriented Protocol Class-1 :TcpClient ويس تخدم لتعري ف Simple TCP Socket إذ يم رر ل ه الIPAddress وال Port للجھة التي نريد االتصال معھا ويحتوي ھذا الك الس عل ى مجموع ة من الMethods وال Properties ونلخصھا بالتالي: أوال: : TCPClient Methods ال IP عن وان فيھ ا نم رر حي ث ال server م ع االتص ال عملي ة ألج راء وتس تخدم :Connect الخاص بالServer ورقم الPort وكما يلي: TcpClient tcp = new TcpClient(); tcp.connect(ipaddress.parse(" "),5020); Dim tcp As TcpClient = New TcpClient tcp.connect(ipaddress.parse(" "), 5020).TCP إلنھاء االتصال مع الSocket :Close :GetStream ويستخدم لق راءة ال Stream م ن ال Socket ف ي عملي ة اإلرس ال و االس تقبال وتستخدم عادة لربط الSocket مع ال.NetworkStream Class ثانيا: أھم الخصائص : TCPClient Properties Linger لتحديد أو معرفة الTime Set أو get وتأخذ : LingerState : odelay وتأخذ get أو Set لتحديد أو معرفة إذا كان ھناك وقت معين لتأخير أم ال :ExclusiveAddressUse وتأخذ get أو Set لتحديد أو معرفة إذا ك ان ال Socket يس مح باستخدام الPort Client أم ال وتس تخدم ع ادة م ع ال SocketOption Class (لمزي د م ن المعلومات أنظر ال (A) (Appendixes SendBufferSize و :ReceiveBufferSize وتأخ ذ get أو Set لتحدي د أو معرف ة حج م الBuffer المستخدم في الstream والمعرف في.TCP Client Object ~79~
80 SendTimeout و :ReceiveTimeout وتأخ ذ get أو Set لتحدي د أو معرف ة الوق ت المتاح لعملية اإلرسال أو اإلستقبال حيث يعطي Time Out في حالة أنه لم يجد الطرف األخر خالل فترة زمنية معينة. وال Properties ال Methods م ن حيث تحتوي على مجموع ة :TcpListener Class-2 وھي كما يلي: أوال: أھم الدوال في ال :TcpListener وتستخدم لقبول عملية االتصال مع الClient. :AcceptSocket : Start وھي Overloaded Method حي ث ان ه ف ي حال ة تمري ر رق م إليھ ا ي تم تحدي د ع دد األجھ زة الت ي تس مح بوجودھ ا ف ي ال Qouee وف ي حال ة ع دم تمري ر رق م مع ين تص بح الQouee غير محدد. استخدام ال Try عند وتستخدم إلغالق عملية التصنت ويفضل وضعھا في الFinally : Stop و الCatch وحتى يتم إنھاء عملية التصنت حتى لو حدث أي.Exception ثانيا: أھم الخصائص في :TcpListener ال LocalEndpoint ف ي المس تخدم ال Port ورق م ال IP يرج ع حي ث : LocalEndpoint المحدد. TCP ال Server ف ي و ال دوال الخص ائص ك ل إل ى الوص ول ومن خاللھا نس تطيع :Server والتي شرحناھا سابقا مثل الAccept والSendto والReceive و Listen وغيرھا ~80~
81 ثانيا الClasses الخاصة بال : UDP Connectionless Protocol UDP Datagram Protocol Connection لتعري ف وتس تخدم :UdpClient Class-1 قمنا سابقا بتعريفھا والتعامل معھا وفي ھذا الجزء سنبين أھم محتوياتھا وھي كما يلي : ومن أھم الدوال والخصائص الخاصة بھا : JoinMulticastGroup و :DropMulticastGroup لض م أو إلغ اء عن وان أو مجموعة من العناوين من الGroup.Multicast الsocket. في لتفعيل الBroadcasting Set أو Get وتأخذ :EnableBroadcast.Mlticast لمعرفة أو تحديد الLoopback Set أو Get وتأخذ :MulticastLoopback IP تخ زين ي تم حي ث ال Multicasting ف ي ويس تخدم :MulticastOption Class-2 Multicast ألي Drop و Join لعمل Multicast Group لتعامل معھا في Address List : Multicast وتستخدم كما يلي كمثال إلضافة عضوية الستقبال رسائل Group أوال نعرف الSocket UDP وكما يلي : mcastsocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); mcastsocket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) ثانيا نقوم بتعريف Address List ثم نسند إليھا الIP الذي نريد ضمه في الGroup أو نجعل الUser يدخل العنوان بنفسه بعد ذلك نربطھا بالSocket باستخدام الدالة Bind وكما يلي: ~81~
82 IPAddress localipaddr = IPAddress.Parse(Console.ReadLine()); mcastsocket.bind(iplocal); Dim localipaddr As IPAddress = IPAddress.Parse(Console.ReadLine) mcastsocket.bind(iplocal) ثالثا نقوم بتعريف الOption Multicast ونسند لھا العنوان المحدد كما يلي: MulticastOption mcastoption; mcastoption = new MulticastOption(localIPAddr); Dim mcastoption As MulticastOption mcastoption = New MulticastOption(localIPAddr) ولتفعيلھ ا يج ب تعريفھ ا ف ي ال SocketOptions Method و تأخ ذ ھ ذه الدال ة ثالث ة باروميترات األول لتحديد مس توى التغيي ر عل ى IP أو عل ى IPv6 أو عل ى Socket أو TCP أو UDP (لمزيد من المعلومات أنظر ال A Appendixes في المرفقات) وفي حالتنا ھذه س وف نس تخدم التغي ر عل ى IP إذ م ا نري ده ھ و ض م IP إل ى Multicast Group وف ي الب اروميتر الث اني نح دد ن وع التغيي ر حي ث نري د إض افة عض وية ويمك ن االختي ار ب ين إض افة عض ويه AddMembership أو إلغ اء عض وية DropMembership وأخي را نس ند إلي ه الObject MulticastOption والذي قمنا بإنشائه و كما يلي: mcastsocket.setsocketoption(socketoptionlevel.ip, SocketOptionName.AddMembership,mcastOption); mcastsocket.setsocketoption(socketoptionlevel.ip, SocketOptionName.AddMembership, mcastoption) وھك ذا بين ا أھ م الخص ائص والت ي يمك ن ال تحكم بھ ا ف ي بيئ ة ال دوت ني ت والمتعلق ة بالProtocols Transport Layer و ال etwork Layer Protocols في الفص ل الت الي س يتم الح ديث بش كل مفص ل ع ن بقي ة ال Members والت ي ي تم التعام ل معھ ا ف ي ال Protocols etwork Layer وط رق التعام ل م ع ال Synchronous Socket والSocket.Asynchronous ~82~
83 Chapter 7 etwork Layer & Synchronous Socket Programming - Introduction to Socket Programming - Synchronous Socket Programming - Synchronous Socket Classes & Members ~83~
84 : etwork Layer & Synchronous Socket Programming :7 ف ي ھ ذا الج زء س وف نب ين بش كل أكث ر تفص يال ع ن برمج ة طبق ة ال Layer Network وال Socket وھ ي الت ي ي تم التعام ل معھ ا إلرس ال واس تقبال البيان ات بع د تحويلھ ا م ن و إل ى Stream عب ر الش بكة قمن ا س ابقا باس تخدام ال TCP وال UDP لإلرس ال ولالس تقبال وبين ا الفرق بينھما وف ي ھ ذا الج زء س وف نتح دث ع ن ال Programming Socket وال Classes والMembers الخاصة بالClass..Socket Introduction to Socket Programming :7.1 من المعروف أن ال Socket ھي األداة الت ي ي تم نق ل البيان ات م ن خاللھ ا م ن جھ از إل ى أخ ر والس تخدامھا يل زم ف ي البداي ة تعري ف System.Net.Socket Namespace حي ث يحت وي ھذا Namespace على عدد كبير من الClasses والتي ي تم اس تخدامھا ف ي برمجي ات الش بكة وسوف نتحدث عن أھمھا وھو Socket Class إذ يمكننا من التعامل مع ال TCP أو ال UDP أو مع أي نوع أخر من البرتوكوالت بشكل مباشر ويتكون الMethod Socket Object م ن ثالثة باروميترات كما يلي: Socket MySocket = new Socket(AddressFamily., SocketType., ProtocolType.); Dim MySocket As Socket = New Socket(AddressFamily, SocketType, ProtocolType) حيث يتم في الباروميتر األول تحديد نوعية الAddress IP والذي سوف تتعامل معه ويعطيك عدد كبير من الخيارات ومنھا IPX والمستخدم في شبكات الNovel أو ATM والمستخدم في شبكات الNetworks ATM أو NetBIOS Address وغيرھا... ومن أھم ھذه الخيارات ال InterNetwork وھ و م ا نس تخدمه بش كل دائ م م ع البرمجي ات الخاص ة بالش بكات ويع رف عل ى أن ن وع ال IP ھ و IPv4 وھ و المعت اد م ع نظ ام مايكروس وفت وأغل ب أنظم ة التش غيل المعروفة حاليا وفي المستقبل القريب جدا سيتم اإلستغناء عنه وليحل محله الIPv6 (لمزي د م ن المعلومات انظر الفصل الثاني) في الباروميتر الثاني يتم تحديد نوع الSocket أي ھل س وف نس تخدم Stream أو Dgram إلرس ال البيان ات أو Raw Socket (ويس تخدم ال Raw Socket م ع البروتوك والت الت ي ال تطل ب التعام ل م ع Port مح دد وم ن األمثل ة عليھ ا ال لمزيد من المعلومات انظر الفصل الخامس عشر) وبشكل دائم يتم استخدام الStream ICMP ف ي حال ة إس تخدام ال TCP وال Dgram ف ي حال ة اس تخدام ال UDP وأخي را نح دد ن وع البروتوكول المستخدم لإلتصال ھل ھو من النوع UDP أو TCP أو بروتوكوالت أخرى مث ل ال ICMP Internet Control Message Protocol أو ال Internet Group IGMP IP Security لتعري ف ال Socket إنش اء م ثال نري د أو انن ا Management Protocol Header بإختيار IPSecAuthenticationHeader وغيرھا وھنا سوف نختار الTCP أو UDP وم ن المع روف أن برتوك ول ال TCP ھ و برتوك ول موج ه وھ ذا يعن ي إج راء عملي ة التحق ق م ن الوص ول والتوص يل إل ى ش خص م ا مح دد أم ا برتوك ول ال UDP فھ و برتوك ول سريع نسبيا و لكنه ال يدعم عملية التحقق من الوص ول الس ليم للبيان ات المرس لة وھ و مفي د ج دا إلجراء عملية البث اإلذاعي Broadcast وإنشاء مجموع ات الب ث Multicast Group وھ و ما شرحناه في الفصل األول والثاني والثالث. ~84~
85 7.2 اس تخدام ال Programming Synchronous Socket إلنش اء TCP :Connection تمر عملية االتصال باس تخدام ال Connection TCP Socket بمجموع ة م ن المراح ل وكم ا في الشكل التالي : إذ تبدأ العملية في الClient و الserver بإنشاء الSocket وكما يلي : Socket MySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Dim MySocket As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ثم ربط ال Socket م ع الكمبي وتر الح الي باس تخدام الدال ة Bind وتس تخدم فق ط عن د االس تقبال وكما يلي : IPEndPoint ip = new IPEndPoint(IPAddress.Any, 5020); MySocket.Bind(ip); Dim ip As IPEndPoint = New IPEndPoint(IPAddress.Any, 5020) MySocket.Bind(ip) ث م القي ام بعملي ة التص نت عل ى ال Port المح دد باس تخدام الدال ة listener ويمكن ك تح دد ع دد األجھزة التي سيتم قبولھ ا ولوض ع ع دد غي ر مح دد نم رر ل ه ال رقم -1 ث م نق وم بالموافق ة عل ى االتصال باستخدام الدالة accept وكما يلي : ~85~
86 MySocket.Listen(-1); MySocket.Accept(); MySocket.Listen(-1) MySocket.Accept ويتم استقبال البيانات م ن خ الل الدال ة Receive حي ث تعب ئ البيان ات ف ي مص فوفة م ن الن وع Byte وكما يلي : byte[]received=new byte[1024]; MySocket.Receive(Received); Dim Received(1024) As Byte MySocket.Receive(Received) وھن ا قمن ا بإنش اء Connection م ن الن وع TCP وبتعريفھ ا عل ى ال 5020)Port كمث ال) حيث يتم ربطھا بالSocket باستخدام الدالة Bind وقمنا بتعريف Listen ال نھائي العدد -1.. ولتعري ف برن امج اإلرس ال TCP Client باس تخدام ال Socket الب د م ن تعري ف ال Socket وإس ناد عن وان ال Server ورق م ال Port بال Object IPEndPoint Instance ث م إرس ال البيانات باستخدام الدالة Send وتتم عملية اإلرسال بما تم تعريفه في الsocket حيث سنستخدم Stream Socket وكما يلي : 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(" "), 5020); MySocket.Connect(remote); MySocket.Send(msg); MySocket.Close(); Dim str As String = Console.ReadLine Dim asen As ASCIIEncoding = New ASCIIEncoding Dim msg As Byte() = asen.getbytes(str) Dim MySocket As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim remote As IPEndPoint = New IPEndPoint(IPAddress.Parse(" "), 5020) ~86~
87 MySocket.Connect(remote) MySocket.Send(msg) MySocket.Close 7.3 استخدام الProgramming Synchronous Socket إلنشاء UDP : Connectionless تمر عملية االتصال باستخدام الConnection UDP Socket بمجموع ة م ن المراح ل وھ ي كما في الشكل التالي: وتشبه عملية استخدام الUDP الTCP إال حد كبير إذ تبدأ العملية في ال Client و ال Server بإنشاء الSocket كما يلي : Socket MySocket = new Socket(AddressFamily.InterNetwork, SocketType. Dgram, ProtocolType.Udp); Dim MySocket As Socket = New Socket(AddressFamily.InterNetwork, SocketType. Dgram, ProtocolType.Udp) ثم ربط الSocket مع الكمبيوتر الحالي باستخدام الدالة Bind وتستخدم فقط عند االستقبال وكما يلي : IPEndPoint sender = new IPEndPoint(IPAddress.Any, 5020); MySocket.Bind(sender); Dim sender As IPEndPoint = New IPEndPoint(IPAddress.Any, 5020) MySocket.Bind(sender) والس تقبال البيان ات نس تخدم الدال ة ReceiveFrom حي ث نع رف ف ي البداي ة EndPoint Reference بناء على ما تم تعريفه في السابق ونمرره ك Reference Object مع مصفوفة ~87~
88 الByte إلى الدالة ReceiveFrom ومن ثم نستطيع تحويل المصفوفة إل ى String م ن خ الل الدالة GetString الموجودة ضمن ASCII Class وكما يلي : 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)); Dim recv As Integer Dim data(1024) As Byte Dim Remote As EndPoint = CType((sender), EndPoint) recv = newsock.receivefrom(data, Remote) Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)) ويتم في اإلرسال استخدام الدالة SendTo حيث نمرر لھا البيانات بعد تحويلھا من String إلى Byte Array وحجم البيان ات المرس لة إذ يمكنن ا معرفت ه م ن خ الل الخاص ية Length ون وع الFlags واخيرا نمرر ل ه ال EndPointObject وال ذي يع رف ال IP Address وال Port لSocket وكما يلي كمثال إلرسال : Broadcast Message string welcome = "Hello All"; data = Encoding.ASCII.GetBytes(welcome); newsock.sendto(data, data.length, SocketFlags.Broadcast, Remote); Dim welcome As String = "Hello All" data = Encoding.ASCII.GetBytes(welcome) newsock.sendto(data, data.length, SocketFlags.Broadcast, Remote) :Synchronous Socket Classes Members Class : IPAddress ويس تخدم لتعري ف ال IPAddress حي ث يمك ن إس ناده إل ى ال IPEndPoint كمث ال ويمك ن أن نك ون م ن خالل ه Array of Address ف ي حال ة إرس ال رسالة ما إلى مجموعة أما الصيغة العامة له فھي كما يلي: IPAddress newaddress = IPAddress.Parse(" "); Dim newaddress As IPAddress = IPAddress.Parse(" ") ~88~
89 ويمكن االختيار بين اربعة خيارات في تحديد العنوان وھي كما يلي : Any ويستخدم لتمثيل أي عنوان متاح على الشبكة (عند اإلستقبال ويعني اإلستقبال من الكل). Broadcast ويستخدم لتمثيل البث اإلذاع ي لجمي ع األجھ زة عل ى الش بكة (عي ث يق وم بعملي ة حساب الBroadcast IP دون ت دخل المس تخدم لمعرف ة كيفي ة حس اب ال Broadcast أنظ ر الفصل الثاني). Loopback ويستخدم لتمثيل العنوان المعروف لل loopback وھو كما يدعم مجموعة من الدوال وأھمھا : Equals تستخدم ھذه الدالة بشكل عام للمقارن ة ب ين tow Objects وھن ا ستس تخدم للمقارن ة بين عنوانين وترجع True إذا كانا متشابھين و False إذا كانا مختلفين. Hash Code وتستخدم إلرجاع العنوان إلى صيغة GetHashCode HostTo etworkorder ويرجع الجزء الخاص بالNetwork من العنوان etworktohostorder ويرجع الجزء الخاص بالHost من العنوان : IPEndPoint Class حي ث اس تخدمناه لتحدي د العن وان وال Port لل Host وال ذي نري د االتصال به والصيغة العامة له كما يلي : IPEndPoint end = new IPEndPoint(IPAddress.Parse(" "), 5020); Dim end As IPEndPoint = New IPEndPoint(IPAddress.Parse(" "), 5020) مجموعة الخواص التي تدعم في الClass Socket وھي كما يلي: ويرجع مجموعة العناوين المعرفة على الSocket AddressFamily ويرجع حجم البيانات الجاھزة للقراءة من الSocket Available Blocking ال Mode يس تخدم ال socket لمعرفة إذا ك ان Set أو Get ويعطي Blocking أم ال Connected وتس تخدم ھ ذه الخاص ية بكث رة لمعرف ة إذا ك ان ال Socket متص ل م ع الHost Remote أم ال Remote ويستخدم لمعرفة البروتوكول الذي يستخدم في الSocket ProtocolType RemoteEndPoint ويرج ع معلوم ات ع ن ال Socket ال ذي يس تخدم م ع ال Host ~89~
90 وكمثال الستخداماتھا: using System; using System.Net; using System.Net.Socket; class Socket_ Properties public static void Main() IPAddress ia = IPAddress.Parse(" "); 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(); imports System imports System.Net imports System.Net.Socket Public Shared Sub Main() Dim ia As IPAddress = IPAddress.Parse(" ") Dim ie As IPEndPoint = New IPEndPoint(ia, 8000) Dim fmo As Socket = 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 ~90~
91 Console.WriteLine("new Blocking: 0", fmo.blocking) Console.WriteLine("Connected: 0", fmo.connected) fmo.bind(ie) Dim iep As IPEndPoint = CType(fmo.LocalEndPoint, IPEndPoint) Console.WriteLine("Local EndPoint: 0", iep.tostring) fmo.close() End Sub AddressFamily: InterNetwork SocketType: Stream ProtocolType: Tcp Blocking: True new Blocking: False Connected: False Local EndPoint: :8000 Press any key to continue... حيث سترجع المعلومات التالية: وھكذا بينا كيفية برمجة ال Synchronous Socket في بيئة ال دوت ني ت س وف نتح دث في الفصل التالي عن برمجة Asynchronous Socket في بيئة الدوت نيت. ~91~
92 Chapter 8 Asynchronous Socket - Asynchronous Socket Class and its members - Applied Asynchronous Socket in Dot Net ~92~
93 : Asynchronous Socket Programming :8 سوف نتحدث في ھذا الجزء عن اس تخدام ال Asynchronous Socket بش كل أكث ر تفص يال عما تحدثنا به س ابقا وس وف نطب ق مجموع ة م ن األمثل ة العملي ة عل ى اس تخدام االتص ال الغي ر متزامن في برمجيات الشبكات... من المعروف أن االتصال المتزامن مھم جدا في البرمجي ات الت ي تحت اج إل ى العم ل ف ي ال زمن الحقيقي حيث ال يسمح باستخدام االتصال ألمر آخر إلى بعد انتھ اء العملي ة الجاري ة واس تخدامه مھم جدا في العمليات الت ي تتطل ب مث ل ھ ذه األم ور لك ن ال ينص ح أب دا اس تخدامه ف ي حال ة إذا كانت الجھة المستقبلة للبيانات تستخدم Slow Connection كاعتماد الش بكة عل ى ال Dialup لربط الجھازين المرسل مع المستقبل أو في حالة إذا كان ھنالك مجموعة كبيرة من المستخدمين تس تخدم ال Server حي ث يمن ع األس لوب المت زامن بقي ة المس تخدمين عل ى الش بكة م ن إج راء عملية اإلرسال في حالة كون الServer يستقبل بيانات من جھاز آخر وفي ھذه الحالة ينصح باستخدام االتصال الغير المتزامن إذ يعتبر مھم جدا في حال ة إذا أردن ا م ن البرن امج القي ام بع دة مھام وعلى نفس الThread وباستخدام نفس ال Connection أو كم ا ذكرن ا س ابقا ف ي حال ة إذا كان االتصال بطيء نسبيا أو انه يوجد عدد مستخدمين يستخدمون نفس الServer.. : أوال Asynchronous Socket Class and its members ت دعم ال دوت ني ت االتص ال غي ر المت زامن بمجموع ة م ن ال Methods الموج ودة ض من الClass Socket والت ي ي تم اس تدعائھا م ن ال Namespaces System.Net.Socket وق د ميزت ال دوت ني ت ھ ذه ال Methods بوج ود ال Begin ف ي بداي ة أس م الدال ة ولك ل Begin Method يوج د End Method مقابل ة لھ ا والت ي تس تخدم إلرج اع callback result عن د انتھاء الMethod Begin من التنفيذ وھي كما يلي: Object ال إل ى وإس ناده Client ال Request لقب ول و تس تخدم BeginAccept 1- AsyncCallback وباس تخدام ھ ذه الطريق ة س وف ي تمكن ال Server م ن اس تقبال ع دد م ن الRequests Clients ف ي نف س الوق ت وب دون الحاج ة النتظ ار االنتھ اء م ن العملي ة الجاري ة حيث يتم في كل مرة استدعاء الدالة باستخدام ال Delegate AsyncCallback وتس تخدم كم ا يلي كما يلي: ~93~
94 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); m_mainsocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim iplocal As IPEndPoint = New IPEndPoint(IPAddress.Any, 5020) m_mainsocket.bind(iplocal) m_mainsocket.listen(10) m_mainsocket.beginaccept(new AsyncCallback(Client_request_method), Nothing) حيث سيتم إضافة الRequest Client في Callback Reference منفصل عن السابق وھنا الب د م ن إنش اء method الس تقبال ال Request Client وإنھ اء ال Client Accepted :EndAccept باستخدام الدالة Object 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()); Dim listener As Socket = CType(ar.AsyncState, Socket) Myclient = listener.endaccept(ar) Myclient.Send listener.beginaccept(new AsyncCallback(Client_request_method), listener) Console.WriteLine("Socket connected to 0", client.remoteendpoint.tostring) ~94~
95 في Dot et 2005 أصبحت الMethod Begin Accept تأخذ عدة أشكال كما يلي: الشكل األول في الدوت نيت 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) Remote الMachine أو الServer مع وتستخدم لربط الClient BeginConnect 2- كConnection Asynchronous حيث يسند لھا الObject IPEndPoint Instance (يحدد فيه ال IP Address ورقم الPort ) ويسند لھا أيضا الCallback Asynchronous والObject State وكما يلي: MySocket.BeginConnect(EndPoint IP,Syncallback Result,object state) وتستخدم كما يلي كمثال: Socket MySocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipend = new IPEndPoint(IPAddress.Parse(" "), 5020); MySocket.BeginConnect(ipend, new AsyncCallback(Connect_him), MySocket); ~95~
96 Dim MySocket As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim ipend As IPEndPoint = New IPEndPoint(IPAddress.Parse(" "), 5020) MySocket.BeginConnect(ipend, new AsyncCallback(Connect_him), MySocket) في الMethod Connect_him يتم تحديد الSocket CallBack كما يلي: public static void Connect_him (IAsyncResult iar) Socket sock = (Socket)iar.AsyncState; try sock.endconnect(iar); catch (SocketException) Console.WriteLine("Unable to connect to host"); Public Shared Sub Connected(ByVal iar As IAsyncResult) Dim sock As Socket = CType(iar.AsyncState, Socket) Try sock.endconnect(iar) Catch generatedexceptionvariable0 As SocketException Console.WriteLine("Unable to connect to host") End Try End Sub Byte Array ف ي وتخزينھ ا ال Client م ن بيان ات إلس تقبال وتس تخدم BeginReceive 3- والصيغة العامة لھا كما يلي: MySocket.BeginReceive(Byte[] buffer,int offset, SocketFlags,AsyncCallback, object sate) ~96~ وتستخدم كما يلي كمثال: byte[] data = new byte[1024]; MySocket.BeginReceive(data, 0, data.length, SocketFlags.None, new AsyncCallback(ReceivedData), MySocket);
97 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); Dim data(1024) As Byte MySocket.BeginReceive(data, 0, data.length, SocketFlags.None, New AsyncCallback(ReceivedData), MySocket) Sub ReceivedData(ByVal iar As IAsyncResult) Dim remote As Socket = CType(iar.AsyncState, Socket) Dim recv As Integer = remote.endreceive(iar) Dim receiveddata As String = Encoding.ASCII.GetString(data, 0, recv) Console.WriteLine(receivedData) End Sub كم ا تس تخدم الدال ة BeginReceiveFrom إلس تقبال البيان ات م ن موق ع مح دد باس تخدام الUDP حيث يضاف إلى التركيب السابق. IPEndPoint Refrance Object Asynchronous ال عب ر المس تقبل الط رف وتستخدم إلرسال بيانات إل ى BeginSend 4- 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); Private Shared Sub SendData(ByVal iar As IAsyncResult) Dim server As Socket = CType(iar.AsyncState, Socket) Dim sent As Integer = server.endsend(iar) ~97~ وتستخدم كما يلي كمثال:
98 End Sub Dim data As Byte() = Encoding.ASCII.GetBytes("Hello Word") MySocket.BeginSend(data, 0, data.length, SocketFlags.None, AddressOf 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) ~98~
99 ثانيا: تطبيقات الSocket Asynchronous في الدوت نيت : تمر عملية االتصال الغير متزامن بمجموعة من المراحل تبدأ بإنشاء الObject Socket في الSide Server بعد ذلك يتم تعريف الBeginConnect لبدأ Asynchronous والMethod IPEndPoint Object يتم إسناد حيث على الSocket Connection Asynchronous Callback والObject State لھا وتبدأ في ھذه الحالة عملية االتصال بالSocket وبعد ذلك تمرر إلى الBeginAccept لقبول الRequest Client حيث يتم قبول الطلب ويرسل Acknowledgement إلى الClient ليعلمه فيھا بقبول الجلسة وإمكانية البدء لإلرسال و يستطيع الClient بعد الموافقة على الجلسة البدء باإلرسال باستخدام الدالة BeginReceive الدالة باستخدام من الClient الرسالة ويستقبل الServer BeginSend وكما ذكرنا سابقا فإن لكل عملية Begin تقابلھا الدالة End لالستعداد إلجراء عملية أخرى على نفس الThread في البرنامج وھو ما ميز االتصال الغير متزامن عن االتصال المتزامن. نالحظ في الشكل السابق بقاء ال Server بوضعية اإلنتظار إذ أنه وفي كل عملية طلب للRequest ما يتم إنھائة باستخدام ال Endxxx Method وتستدعى ھذه الMethod باستخدام ال Delegate المخصص إلجراء عملية اإلتصال الغير متزامن وھي AsyncCallback وتشبه ھذه العملية إلى حد كبير عملية الدخول المباشر إلى المعالجة إذ ال تنتظر إنھاء ال Server لعملية المعالجة الحالية في حالة ورود طلب جديد وھكذا يسلم أي طلب جديد إلى ال Endxxx Method إلنھائه وإبقاء حالة ال Server بوضع اإلنتظار... وبناء على المفاھيم السابقة سوف نقوم اآلن بإنشاء برنامج Client/Server Chatting على الSocket Asynchronous إلرسال واستقبال البيانات. يعتمد ~99~
100 وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي: سوف نستخدم ال amespaces التالية: using System.Net; using System.Net.Socket; using System.Text; Imports System.Net Imports System.Net.Socket Imports System.Text في الDeclaration Global (أي بعد تعريف الClass Main )قم بإضافة التعاريف التالية: 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; Public Class Form1 Inherits System.Windows.Forms.Form Private server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Private iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 5020) Private data As Byte() = New Byte(1024) Private size As Integer = 1024 ~100~
101 ف ي ال Load Form ق م بإض افة الك ود الت الي حي ث س نعرف Connection يعتم د عل ى ال TCP ويعم ل عل ى ال Port 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); Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) server = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 5020) server.bind(iep) server.listen(5) server.beginaccept(new AsyncCallback(AcceptConn), server) End Sub ث م إنش اء Accept Callback Method وال ذي س يتم في ه إنھ اء ال Accepted Request باس تخدام ال Method EndAccept وبع د ذل ك إرس ال Acknowledgement إل ى ال Client تخب ره فيھ ا بقب ول الطل ب وترس ل باس تخدام الMethod BeginSend كما يلي: 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); Sub AcceptConn(ByVal iar As IAsyncResult) Dim oldserver As Socket = CType(iar.AsyncState, Socket) Dim client As Socket = oldserver.endaccept(iar) constatus.text = "Connected to: " + client.remoteendpoint.tostring Dim stringdata As String = "Welcome to my server" ~101~
102 Dim message1 As Byte() = Encoding.ASCII.GetBytes(stringData) client.beginsend(message1, 0, message1.length, SocketFlags.None, New AsyncCallback(SendData), client) End Sub ثم إنشاء 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); Sub SendData(ByVal iar As IAsyncResult) Dim client As Socket = CType(iar.AsyncState, Socket) Dim sent As Integer = client.endsend(iar) client.beginreceive(data, 0, size, SocketFlags.None, New AsyncCallback(ReceiveData), client) End Sub ثم إنشاء 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); Sub ReceiveData(ByVal iar As IAsyncResult) Dim client As Socket = CType(iar.AsyncState, Socket) Dim recv As Integer = client.endreceive(iar) ~102~
103 If recv = 0 Then client.close() constatus.text = "Waiting for client..." server.beginaccept(new AsyncCallback(AcceptConn), server) Return End If Dim receiveddata As String = Encoding.ASCII.GetString(data, 0, recv) results.items.add(receiveddata) Dim message2 As Byte() = Encoding.ASCII.GetBytes(receivedData) client.beginsend(message2, 0, message2.length, SocketFlags.None, New AsyncCallback(SendData), client) End Sub وھن ا ق د ت م االنتھ اء م ن برن امج ال Server واآلن س وف نق وم بإنش اء برن امج ال Client وللبدء قم بإنشاء مشروع جديد كما في الشكل التالي: using System.Net; using System.Net.Socket; using System.Text; imports System.Net imports System.Net.Socket imports System.Text سوف نستخدم ال amespaces التالية: في الDeclaration Global (أي بعد تعريف الClass Main )قم بإضافة التعاريف التالية: ~103~
104 public class Form1 : System.Windows.Forms.Form private Socket client; private byte[] data = new byte[1024]; private int size = 1024; في الButton Connect قم بكتابة الكود التالي:.. 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); Private client As Socket Private data As Byte() = New Byte(1024) Private size As Integer = constatus.text = "Connecting..." Dim newsock As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Dim iep As IPEndPoint = 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) ~104~
105 constatus.text = "Error connecting"; Sub Connected(ByVal iar As IAsyncResult) client = CType(iar.AsyncState, Socket) Try client.endconnect(iar) constatus.text = "Connected to: " + client.remoteendpoint.tostring client.beginreceive(data, 0, size, SocketFlags.None, New AsyncCallback(ReceiveData), client) Catch generatedexceptionvariable0 As SocketException constatus.text = "Error connecting" End Try End Sub ثم إنشاء 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); Sub ReceiveData(ByVal iar As IAsyncResult) Dim remote As Socket = CType(iar.AsyncState, Socket) Dim recv As Integer = remote.endreceive(iar) Dim stringdata As String = Encoding.ASCII.GetString(data, 0, recv) results.items.add(stringdata) End Sub ثم إضافة الكود التالي في الButton : Send 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); ~105~
106 Try Dim message As Byte() = Encoding.ASCII.GetBytes(newText.Text) newtext.clear client.beginsend(message, 0, message.length, SocketFlags.None, New AsyncCallback(SendData), client) newtext.focus Catch ex As Exception Msgbox(ex.Message) End Try ثم إنشاء 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); Sub SendData(ByVal iar As IAsyncResult) Try Dim remote As Socket = CType(iar.AsyncState, Socket) Dim sent As Integer = remote.endsend(iar) remote.beginreceive(data, 0, size, SocketFlags.None, New AsyncCallback(ReceiveData), remote) Catch ex As Exception Msgbox(ex.Message) End Try End Sub ثم إنشاء 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); ~106~
107 catch(exception ex)messagebox.show(ex.message); Sub ReceiveData(ByVal iar As IAsyncResult) Try Dim remote As Socket = CType(iar.AsyncState, Socket) Dim recv As Integer = remote.endreceive(iar) Dim stringdata As String = Encoding.ASCII.GetString(data, 0, recv) results.items.add(stringdata) Catch ex As Exception Msgbox(ex.Message) End Try End Sub وكما الحظنا فإن برنامج الClient ال يختلف كثيرا عن برنامج ال Server حي ث نع رف ف ي الServer الConnection Socket وال Method BeginAccept أم ا ف ي ال Client فنع رف ال Connection Socket و ال Method BeginConnect وتبق ى عملي ة اإلرسال واالستقبال ھي نفسھا في Server والClient... سيتم الحديث في الفصل التالي عن طرق برمجة أنظمة ال Multicasting Conference Systems في بيئة الدوت نيت. ~107~
108 Chapter 9 Advanced Multicasting Systems - Architecture of Multicast Socket - Using Multicast Socket with.net - Multicast Conferencing Systems: 1. Full/Half Duplex Multicast Video Conferencing System. 2. Full/Half Duplex Multicast Desktop Conferencing System. 3. Full/Half Duplex Multicast Text Conferencing System ~108~
109 : Advanced Multicasting Systems :9 قمنا سابقا بتعريف ال Multicasting وبينا الفرق بينھا وبين ال Broadcasting وبينا أنواعھا وكيفية التعامل معھا في الدوت نيت وفي ھذه الفصل سوف نتحدث عنھا بشكل أكثر تفصيال وذلك ألھميتھا الكبيرة في برمجيات الشبكات وخاصة برمجيات الConferencing. : Architecture of Multicast Socket أوال : من المعروف انه يتم التعامل مع الMulticasting عبر برتوكول الUDP وباستخدام الMask Class D Subnet وتتم عملية إدارة المجموعات باستخدام برتوكول ال IGMP Internet Protocol والذي ھو جزء من ال Internet Group Management Protocol Model وكما يتضح من الشكل التالي فإن برتوكول الIGMP يحتوي على عمليات التحقق من الوصول السليم للبيانات (حيث يتم إرسال حجم البيانات الكلي لرسالة وھي اختيارية إذ يمكن إلغائھا بوضع الرقم صفر) و تحتوي أيضا على الLive TTL Time to والذي يحدد فيه العمر االفتراضي لكل رسالة بناء على عدد ال Hops التي سيمر منھا ال Packet ونوع العملية اإلدارية (ضم إلى مجموعة إلغاء من مجموعة أو إرجاع معلومات عن المجموعة (Membership Query وأخيرا عنوان المجموعة التي يتم تحديدھا برمجيا ضمن الRange المحدد لل. Class D وتم تخصيص الRange في الMulticasting IP من إلى ونستطيع تحديده بثالثة طرق إما بشكل يدوي Static أو Dynamic أو على أساس الScope-Relative وبشكل عام تستخدم ھذه التوزيعات كما يلي كمثال: كمثال التخص يص يس تخدم ف ي جمي ع الش بكات المحلي ة حي ث ال ي تم تمري ره إل ى شبكة أخرى عب ر ال Router. لمعرف ة جمي ع التخصيص ات لل Multicasting انظ ر ال رابط التالي الخاص بمنظمة ال :Iana يتم نقل الPackets Multicast بين الTunnels Backbone ك Unicastحيث يتم إرسالھا من داخل الشبكة إلى الRouter و ترسل من Router إلى أخر عبر ال Tunnel Backbone بأسلوب الUnicast وھو ما يوفر الكثي ر م ن ال Bandwidth ف ي الش بكة حي ث ترس ل نس خة واحدة إلى الRouter ويقوم ھو بتوزيعھا على األجھزة كBroadcast المش كلة الوحي دة ف ي ال Multicast ھ و ان ه يعتم د بش كل كام ل عل ى اس تخدام ال UDP Connectionless.Protocol ويمكنن ا اس تخدام ال Multicasting ف ي ثالث ة أن واع م ن الش بكات وھ ي ش بكات ال Peer to Peer حيث ال وجود لجھاز Server والكل يستقبل و يرسل من و إلى الGroup الذي ھو فيه ~109~
110 والن وع الث اني Server Based Network حي ث ي تم إرس ال رس الة واح دة إل ى ال Server ويق وم ال Server بتوزيعھ ا عل ى بقي ة األجھ زة ف ي الش بكة أم ا الن وع الثال ث في تم م ن خ الل الRouter وكما يتضح من الشكل التالي فإن عملي ة اإلرس ال ت تم بع د انض مام ال Client إل ى المجموعة التي تملك الMulticast IP ويرسل الClient رسالة واح دة إل ى ال Router حي ث يقوم الRouter بتوزيعھا على األجھزة في المجموعة مستخدما الTable.Routing وكما كان الح ال ف ي اإلرس ال باس تخدام ال Broadcasting ي تم اإلرس ال ف ي Multicasting من جھاز محدد إلى مجموعة معينة وليس إلى الك ل كم ا ف ي ال Broadcast حي ث ت ك ون ك ل مجموع ة م ن األجھ زة Group خ اص وي تم التخص يص كم ا ذكرن ا س ابقا وف ق ال IP Multicasting حي ث تمتل ك ك ل مجموع ة نف س ال Multicast IP ويوج د ع دة أش كال للMulticasting ومن األمثلة عليھا اإلرسال إل ى مجموع ة one to Group و اإلرس ال إل ى أكثر من مجموعة : one to Multi Group 1 اإلرسال من واحد إلى مجموعة :One to Group وفي ه يمل ك ال User Sender نف س ال Multicasting IP ال ذي يملك ه ال Users Receiver وي تم اإلرس ال م ن داخ ل ال Group إل ى جمي ع أعض ائه حي ث ترس ل ك Unicast إل ى ال Point Access حي ث يق وم بتوزيعھ ا عل ى كاف ة األعض اء ف ي المجموع ة بأس لوب الBroadcast وكما في الشكل التالي: ~110~
111 2- اإلرسال إلى أكثر من مجموعة :One to Multi-Groups وفيه قد يكون الMulticasting IP لل Sender User مختلف ع ن Receiver Users وي تم اإلرس ال م ن User داخ ل ال Group إل ى المجموع ة ال ذي ھ و عض و منھ ا وإل ى مجموع ات أخرى ويتم تحديدھا باستخدام Address List للمجموعات التي نريد اإلرسال لھا... ~111~
112 ثانيا. ET: :Using Multicast Socket with شرحنا سابقا كيفية التعامل مع الMulticasting في الدوت ني ت وتعرفن ا عل ى ال Members وال Classes الخاص ة بھ ا وھن ا س وف نب ين بش يء م ن التفص يل ھ ذه العملي ات ونطب ق عليھ ا مجموع ة م ن األمثل ة وبع د ذل ك س نقوم ببن اء نظ ام Conference System معتم دا عل ى الMulticasting. من العمليات األساسية في التعامل مع الMulticasting : -1 االنضمام أو الخروج من مجموعة : Joining Drop Group ال تل زم عملي ة االنض مام إل ى ال Group Multicast أي عملي ات تحق ق س وى التص نت عل ى ال port وال Multicasting IP المح دد وي تم ذل ك بع د تعري ف udpclient Object وباس تخدام ال Method JoinMulticastGroup ي تم تعري ف ال Multicasting IP ال ذي سوف ننضم إليه وكما يلي: UdpClient sock = new UdpClient(5020); sock.joinmulticastgroup(ipaddress.parse(" "), 50); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 0); Dim sock As UdpClient = New UdpClient(5020) sock.joinmulticastgroup(ipaddress.parse(" "), 50) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) وكما يلي إللغاء عملية االنضمام من مجموعة : sock.dropmulticastgroup(ipaddress.parse(" ")); sock.dropmulticastgroup(ipaddress.parse(" ")) إذ تس تخدم ال JoinMulticastGroup Methods و DropMulticastGroup لض م أو إلغ اء عن وان أو مجموع ة م ن العن اوين م ن ال Group Multicast وباس تخدام Class Multicast ف ي معھ ا لتعام ل IP Address List تخ زين يمكنن ا :MulticastOption Group لعم ل Join و Drop ألي Multicast Group وتس تخدم كم ا يل ي كمث ال إلض افة عضوية الستقبال رسائل : Multicast أوال نعرف الSocket UDP وكما يلي : mcastsocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); ~112~
113 mcastsocket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) ثاني ا نق وم بتعري ف Address List ث م نس ند إليھ ا ال IP ال ذي نري د إدخال ه ف ي ال Group أو نجعل الUser يدخل العنوان بنفسه نربطھا بالسكوت باستخدام الدالة Bind وكما يلي : IPAddress localipaddr = IPAddress.Parse(Console.ReadLine()); mcastsocket.bind(iplocal); Dim localipaddr As IPAddress = IPAddress.Parse(Console.ReadLine) mcastsocket.bind(iplocal) ثالثا نقوم بتعريف الOption Multicast ونسند لھا العنوان المحدد كما يلي: MulticastOption mcastoption; mcastoption = new MulticastOption(localIPAddr); Dim mcastoption As MulticastOption MulticastOption(localIPAddr New = mcastoption) وم ن ث م نض يف التغي ر عل ى SetSocketOption حي ث تأخ ذ ھ ذه الدال ة ثالث ة ب اروميترات األول لتحديد مستوى التغيير على IP أو على IPv6 أو على Socket أو TCP أو UDP وفي حالتنا ھذه س وف نس تخدم التغي ر عل ى IP إذ م ا نري ده ھ و ض م IP إل ى Multicast Group وفي الباروميتر الثاني نحدد نوع التغيير حيث نريد إضافة عضوية ويمكن االختيار ب ين إض افة عض ويه AddMembership أو إلغ اء عض وية DropMembership وأخي را نس ند إلي ه الObject MulticastOption والذي قمنا بإنشائه و كما يلي: mcastsocket.setsocketoption(socketoptionlevel.ip, SocketOptionName.AddMembership,mcastOption); Dim mcastoption As MulticastOption mcastoption = New MulticastOption(localIPAddr) -2 اإلرسال إلى مجموعة :Sending Data to a Multicast Group حت ى نس تطيع اإلرس ال باس تخدام ال Multicasting IP الب د أوال م ن تعري ف ال Socket Object باستخدام ال Connection UDP وإس ناد ال Multicasting IP ورق م ال Port إل ى الObject... IPEndPoint ونستطيع اإلرسال باستخدام الmethod sendto حيث نسند لھا الArray data as Bytes والObject IPEndPoint وكما يلي إلرسال رسالة نصية: ~113~
114 Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(( ), 5020); byte[] data = Encoding.ASCII.GetBytes(msg.Text); server.sendto(data, iep); server.close(); msg.clear(); msg.focus(); Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(" "), 5020) Dim data As Byte() = Encoding.ASCII.GetBytes(msg.Text) server.sendto(data, iep) server.close msg.clear msg.focus وإلرس ال Binary Data كإرس ال ص ورة م ثال الب د م ن اس تخدام ال Stream Memory لتخ زين الص ورة ف ي ال ذاكرة عل ى ھيئ ة Stream ث م تحويلھ ا إل ى Byte Array وبع د ذل ك إرسالھا باستخدام الMethod sendto وكما يلي: MemoryStream ms = new MemoryStream(); PictureBox1.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Jp eg); byte[] arrimage = ms.getbuffer(); ms.close(); Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse( ), 5020); server.sendto(arrimage,iep); Dim ms As MemoryStream = New MemoryStream PictureBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrimage As Byte() = ms.getbuffer ms.close ~114~
115 Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(" "), 5020) server.sendto(arrimage, iep) -3 االستقبال من مجموعة :Receiving Data From a Multicast Group حتى نستطيع االستقبال من مجموعة البد أوال من تحديد الMulticast IP الخاص بالمجموع ة و االنض مام إلي ه ث م اس تقبال البيان ات باس تخدام ال Method Receive وي تم ذل ك كم ا يل ي الستقبال رسالة نصية وعرضھا في :list Box UdpClient sock = new UdpClient(5020); sock.joinmulticastgroup(ipaddress.parse( ), 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 ); Dim sock As UdpClient = New UdpClient(5020) sock.joinmulticastgroup(ipaddress.parse(" "), 50) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim data As Byte() = sock.receive(iep) Dim stringdata As String = Encoding.ASCII.GetString(data, 0, data.length) listbox1.items.add(iep.address.tostring + " :_ " + stringdata) والستقبال صورة نستخدم الStream memory الستقبال البيانات من الMethod Receive وتخزينھا في الذاكرة على ھيئة Stream Data ث م تحويلھ ا إل ى ص ورة م رة أخ رى باس تخدام الMethod image.fromstream وكما يلي: UdpClient sock = new UdpClient(5020); sock.joinmulticastgroup(ipaddress.parse( )); 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(); ~115~
116 Dim sock As UdpClient = New UdpClient(5020) sock.joinmulticastgroup(ipaddress.parse(" "), 50) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim data As Byte() = sock.receive(iep) Dim stringdata As String = Encoding.ASCII.GetString(data, 0, data.length) listbox1.items.add(iep.address.tostring + " :_ " + stringdata) مالحظات ھامة في استخدام الMulticasting في برمجيات الشبكات : 1- م ن المالح ظ أنن ا ال نس تطيع اس تخدام ال Stream Network لعملي ة إرس ال الMulticasting إذ يتطلب استخدامھا وجود TCP Socket Connection وھو غي ر مت اح ف ي ال Multicasting ويس تعاض عنھ ا باس تخدام ال Stream memory إلرس ال Binary... sendto عبر الmethod Stream 2- ال يمكن ك اس تخدام ال Multicastingك loopback ف ي حال ة ع دم وج ود ش بكة أو اتص ال لذلك لن تستطيع تجربة أي من تطبيقات الMulticasting في حالة عدم اتصالك بالشبكة. 3- يمكن لكل جھاز أن ينضم إل ى أكث ر م ن مجموع ة بحي ث يس تقبل م ن جھ ات متع ددة ك ذلك يستطيع اإلرسال إلى عدة مجموعات. 4- ف ي الع ادة تك ون الس عة المس موحه إلرس ال ال Data Multicasting عب ر ال sendto Method محدودة والسبب األساسي لھذه المشكلة ھي استخدام ال Multicasting بروتوكول ال UDP والذي ال يمكن تجزئة ال Data المرسلة ف ي حال ة اس تخدام حي ث ال ي دعم التوص يل وف ق الترتي ب مم ا يحص ر إمكاني ات اإلرس ال ب الحجم األقص ى لل Ethernet.Encapsoulation ~116~
117 ثالثا تطبيق مشروع نظام المؤتمرات :Multicasting Conferencing Systems في ھذا التطبيق سوف نفترض وجود غرفة صفية حيث يقوم المحاضر بإلقاء المحاضرة عن بعد أمام طالبه إذ نريد ھنا جعل الطالب يرون األستاذ وكما يستطيع األستاذ رؤية طالبه Power Point باإلضافة إلى إمكانية عرض المحاضرة على ال (Full Duplex System) By )كما Get Desktop Screen) Slides يستطيع الطالب التحدث مع األستاذ باستخدام...Voice والChatting Text Chatting سوف نقوم ھنا بتقسيم نظام المؤتمرات إلى ثالثة أنظمة رئيسية وھي نظام مؤتمرات الفيديو ونظام مؤتمرات سطح المكتب ونظام المؤتمرات النصية وسنضيف عليه الحقا نظام المحادثة الصوتية في البداية سوف نقوم بإنشاء الشاشة الرئيسية للبرنامج و كما في الشكل التالي: ~117~
118 : Full/Half Duplex Multicast Video Conferencing System -1 وفرت لنا Microsoft مجموعة من الClasses الخارجية والتي تتعامل م ع ال DirectX 9 مباشرة حيث نستطيع استخدامھا لتعامل مع الك اميرا أو ال Scanner أو الص وت أو أي طرفي ة أخ رى وف ي ھ ذا التطبي ق س وف نس تخدم ال Classes Direct Show Dot Net اللتق اط ص ورة عب ر الك اميرا وعرض ھا عل ى ال box Picture حي ث نس تطيع إرس الھا الحق ا إل ى الGroup Multicast باستخدام الStream memory والmethod Sendto وھ و م ا بين اه سابقا.. وحتى نستطيع استخدامھا سوف نضم الClasses Direct Show إلى المشروع وكما يلي: using DShowNET; using DShowNET.Device; وحتى نتعامل معھا سوف نستدعيھا باستخدام : imports DShowNET imports DShowNET.Device وسيكون شكل برنامج إرسال الكاميرا كما في الشكل التالي: ~118~
119 سوف نستخدم الClass DeviceSelector الختيار جھاز اإلدخال عند بداية تشغيل البرنامج وكما يلي: DeviceSelector selector = new DeviceSelector( capdevices ); selector.showdialog( this ); dev = selector.selecteddevice; Dim selector As DeviceSelector = New DeviceSelector(capDevices) selector.showdialog(me) 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; ~119~
120 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) Private Sub OnCaptureDone() Try Trace.WriteLine("!!DLG: OnCaptureDone") toolbarbtngrab.enabled = True Dim hr As Integer If sampgrabber Is Nothing Then Return End If hr = sampgrabber.setcallback(nothing, 0) Dim w As Integer = videoinfoheader.bmiheader.width Dim h As Integer = videoinfoheader.bmiheader.height If ((w And &H3) <> 0) OrElse (w < 32) OrElse (w > 4096) OrElse (h < 32) OrElse (h > 4096) Then Return End If Dim stride As Integer = w * 3 Dim handle As GCHandle = GCHandle.Alloc(savedArray, GCHandleType.Pinned) Dim scan0 As Integer = CInt(handle.AddrOfPinnedObject()) scan0 += (h - 1) * stride Dim b As Bitmap = New Bitmap(w, h, -stride, PixelFormat.Format24bppRgb, New IntPtr(scan0)) handle.free() savedarray = Nothing Dim old As Image = picturebox.image picturebox.image = b If Not old Is Nothing Then old.dispose() End If toolbarbtnsave.enabled = True Catch e1 As Exception End Try End Sub ثم عمل Timer وإضافة الكود التالي فيه الستمرار عملية التقاط الصورة: ~120~
121 int hr; int size = videoinfoheader.bmiheader.imagesize; savedarray = new byte[ size ]; Dim hr As Integer Dim size As Integer = videoinfoheader.bmiheader.imagesize savedarray = New Byte(size ) وإلرسال الصورة إلى الطرف األخر سوف نستدعي دالة إرسال الصورة والتي قمنا بإنشائھا من خالل استخدام Timer ولھدف استمرار عملية اإلرسال كل فترة معينة وكما يلي: try MemoryStream ms = new MemoryStream(); picturebox.image.save(ms,system.drawing.imaging.imageformat.jpe g); 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) Try Dim ms As MemoryStream = New MemoryStream picturebox.image.save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrimage As Byte() = ms.getbuffer ms.close Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(textBox1.Text), 5020) server.sendto(arrimage, iep) server.close Catch generatedexceptionvariable0 As Exception End Try ~121~
122 وھنا يستطيع المحاضر إرسال الص ورة عب ر الك اميرا إل ى طالب ه كم ا س وف ي تمكن م ن رؤي ة طالبه عبر الكاميرا وسوف نفترض ھنا استخدامه لش بكة ال س لكية حي ث سيرس ل البيان ات إل ى الPoint Access بأسلوب الUnicast وسوف يتولى الPoint Access توزيع البيانات إل ى جميع األعضاء المنضمين إلى الGroup Multicast ويرسلھا لھم كBroadcast وكما ف ي الشكل التالي: وكما نالحظ ف ي الش كل الس ابق ف إن المحاض ر ينض م إل ى مجم وعتين مجموع ة األس اتذة وھ ي حيث سيستقبل صورة طالبه عليھا ومجموعة الط الب والت ي سوف يرسل الصورة إليھا.. وكما نالحظ أيضا ف إن عملي ة اإلرس ال ب ين ال Point1 Access والPoint2 Access تتم باستخدام الUnicast... وحتى يستطيع الطالب رؤية أستاذھم واألستاذ رؤية طالبه الب د م ن إنش اء برن امج االس تقبال حيث سنستخدم نفس الmethod التي شرحنھا سابقا الستقبال الصورة وللب دء ق م بعم ل New Form جديد كما في الشكل التالي: ~122~
123 سوف نستخدم ال Namespaces التالية الستقبال الصورة من الGroup : Multicast using System.Net.Socket ; using System.Net; using System.IO; using System.Threading; imports System.Net.Socket imports System.Net imports System.IO imports 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(); Sub Image_Receiver() Dim sock As UdpClient = New UdpClient(5020) sock.joinmulticastgroup(ipaddress.parse(textbox1.text)) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) ~123~
124 Dim data As Byte() = sock.receive(iep) Dim ms As MemoryStream = New MemoryStream(data) picturebox1.image = Image.FromStream(ms) sock.close() End Sub وحتى نستدعيھا البد من استخدام ال Threading وحت ى نق وم ب ذلك ق م بعم ل Timer وض ع فيه الكود التالي الستخدام الThreading : Thread myth; myth= new Thread (new System.Threading.ThreadStart(Image_Receiver)); myth.start (); Dim myth As Thread 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) Try savefiledialog1.filter = "JPEG Image (*.jpg) *.jpg" If savefiledialog1.showdialog = DialogResult.OK Then Dim mypic_path As String = savefiledialog1.filename picturebox1.image.save(mypic_path) End If Catch generatedexceptionvariable0 As Exception End Try وھك ذا ق د ت م االنتھ اء م ن المش روع األول وھ و ال System Video Conference وحت ى يس تطيع المحاض ر ع رض المحاض رة باس تخدام برن امج ال Point Power س وف نق وم بعم ل مشروع مؤتمرات سطح المكتب... ~124~
125 :Full/Half Duplex Multicast Desktop Conferencing System -2 الھدف من ھذا المشروع ھو تمكين األستاذ من عرض المحاضرة باستخدام برنامج ال Power Point حيث سترسل صورة سطح المكتب م ن جھ از األس تاذ إل ى أجھ زة الطلب ة وال تختل ف عملية اإلرسال عن البرنامج السابق في شيء سوى إنشاء Classes لتقوم بالتقاط صورة سطح المكتب ومن ثم إرسالھا إلى الGroup Multicast ومن ثم اس تقبالھا وعرض ھا عل ى الط الب باستخدام. Data Show Projector ويوضح الشكل التالي مخطط عمل المشروع: وكما نالحظ من الشكل التالي فإن األستاذ يقوم بشرح المحاضرة على جھازه الشخصي ويرس ل الصورة إلى الطالب وكما نالحظ أيضا فإن ھذه العملي ة ھ ي أحادي ة االتج اه وكم ا يمك ن جعلھ ا باتج اھين Full Half Duplex لك ن الب د م ن إنش اء مجموع ة جدي دة لعملي ة اإلرس ال م ن الطالب إلى األستاذ حيث يعرض األس تاذ محاض رته ويرس لھا إل ى مجموع ة الط الب ويس تطيع أحد الطالب عرض جھازه على األستاذ إذ يرسل الصورة إلى مجموعة األستاذ... ~125~
126 وإلنش اء برن امج إرس ال ص ورة س طح المكت ب ق م بعم ل New Form جدي د كم ا ف ي الش كل التالي: وإللتقاط صورة س طح المكت ب سنس تخدم دوال ال API ومنھ ا ال GetDesktopWindow Method والموجودة ضمن الuser32.dl وال Method BitBlt لرس م الص ورة ث م س نقوم بتحويل الصورة إلى Byte Array وحتى نستطيع إرسالھا إلى ال Clients ويتم ذلك كم ا يل ي : using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.IO; public class ScreenCapture [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 ); ~126~
127 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. ET Imports System Imports System.Drawing Imports System.Drawing.Imaging Imports System.Runtime.InteropServices Imports System.IO ~127~
128 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) ~128~
129 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 وحتى نستطيع التحكم في حجم الصورة سنستخدم ال Bitmap Class وال Graphics Class إذ سنمرر لھا الHeight وال Width والصورة التي نريد تغيير حجمھا وكما يلي: 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; Public Function ResizeBitmap(ByVal b As Bitmap, ByVal nwidth As Integer, ByVal nheight As Integer) As Bitmap Dim result As Bitmap = New Bitmap(nWidth, nheight) ' Using Dim g As Graphics = Graphics.FromImage(CType(result, Image)) Try g.drawimage(b, 0, 0, nwidth, nheight) Finally CType(g, IDisposable).Dispose() End Try Return result End Function سوف نستخدم الNamespaces التالية في البرنامج لتعامل مع الSocket : Multicasting using System.Net; using System.Net.Socket; using System.IO; imports System.Net ~129~
130 imports System.Net.Socket imports System.IO ثم نقوم بعمل Timer اللتقاط صورة سطح المكتب و إرسالھا إلى الGroup Multicast المحدد: Bitmap bt = new Bitmap(CaptureScreen.GetDesktopBitmapBytes ()); picscreen.image = ResizeBitmap(bt, 600, 400 ); 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(); Dim bt As Bitmap = New Bitmap(CaptureScreen.GetDesktopBitmapBytes) picscreen.image = ResizeBitmap(bt, 600, 400) Dim ms As MemoryStream = New MemoryStream picscreen.image.save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrimage As Byte() = ms.getbuffer ms.close Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(textBox1.Text), 5020) server.sendto(arrimage, iep) server.close ~130~
131 :Full/Half Duplex Multicast Text Conferencing System -3 وحت ى يس تطيع الطلب ة التح دث إل ى األس تاذ باس تخدام ال Text Chat Multicast Conference System سوف نقوم بإنشاء New Form جديد وكما في الشكل التالي: using System.Net; using System.Net.Socket; using System.Text; using System.Threading; ثم قم بإضافة الNamespaces التالية: imports System.Net imports System.Net.Socket imports System.Text imports 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), 5020); byte[] data = Encoding.ASCII.GetBytes(msg.Text); server.sendto(data, iep); ~131~
132 server.close(); msg.clear(); msg.focus(); catch(exception) Private Sub msg_keypress(byval sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) If e.keychar = Microsoft.VisualBasic.Chr(13) Then Try Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(txt_host.Text), 5020) Dim data As Byte() = Encoding.ASCII.GetBytes(msg.Text) server.sendto(data, iep) server.close() msg.clear() msg.focus() Catch generatedexceptionvariable0 As Exception End Try End If End Sub وسوف نستخدم الدالة التالية لعملية االستقبال حيث ستعرض الرسالة المستقبلة في list Box مخصص: public void server() try UdpClient sock = new UdpClient(5020); 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(); ~132~
133 catch(exception) Public Sub server() Try Dim sock As UdpClient = New UdpClient(5020) sock.joinmulticastgroup(ipaddress.parse(txt_host.text), 50) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim data As Byte() = sock.receive(iep) Dim stringdata As String = Encoding.ASCII.GetString(data, 0, data.length) listbox1.items.add(iep.address.tostring + " :_ " + stringdata) sock.close() listbox1.focus() msg.focus() myth.abort() Catch generatedexceptionvariable0 As Exception End Try End Sub والستدعائھا البد من استخدام الThreading قم بعمل Timer واستدعي فيه الmethod السابقة باستخدام الDelegate ThreadStart وكما يلي: Thread myth; myth= new Thread (new System.Threading.ThreadStart(server)); myth.start (); Dim myth As Thread 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), 5020); ~133~
134 byte[] data = Encoding.ASCII.GetBytes("has Left the Room"); server.sendto(data, iep); server.close(); msg.clear(); msg.focus(); catch(exception) timer1.enabled = False txt_host.readonly = False msg.enabled = False Try Dim server As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(txt_host.Text), 5020) Dim data As Byte() = Encoding.ASCII.GetBytes("has Left the Room") server.sendto(data, iep) server.close msg.clear msg.focus Catch generatedexceptionvariable0 As Exception End Try تعرفنا في ھذا الفصل على كيفية عمل Multicast Conference Systems في بيئ ة ال دوت ني ت وط رق إنش اء ال System Video Conference وال Desktop Conference System وال Text Conference System و ستتمكن بعد قراءة الفصل التالي م ن إنش اء ال. Voice Conference System س يتم الح ديث ف ي الفص ل الت الي ع ن ال Voice Over IP Programming واس تخدامه لعمل Voice Chat وSystem Voice Conference باستخدام ال API s وال Direct Play 9 باإلضافة إلى استخدام الTelephony TAPI في بيئة الدوت نيت. ~134~
135 Chapter 10 Voice Over IP Programming - The Concept & Requirements of Voice Communication Systems - How to Create a Voice Chat Through Dot Net Using Unmanaged API s Functions - Testing UDP Multicasting, TCP and Thinking in SCTP to Transfer Voice Through Networks - How to Create a Voice Conference System Using Microsoft Direct Play 9 - Design an Advanced Video/Voice Conferencing System By Using API & TAPI Telephony to Transfer Video/Voice Through Networks & Voice Through Analog Telephone Line ~135~
136 : Voice Over IP Programming - 10 تتلخص الفكرة األساسية من نق ل الص وت عب ر بروتوك ول اإلنترن ت IP بتحوي ل الص وت إل ى مجموعة من ال Bits تجمع في Byte Array ث م كبس لته لي تم نقل ه ك Datagram Packets أو ك Stream Data عب ر الش بكة ولالس تقبال الص وت ف ي الط رف األخ ر ي تم تجمي ع ال FIFO ال وتتم عملية القراءة وفق مب دأ Byte Array مرة أخرى في مصفوفة Packets First In First Out أي القادم أوال يعرض أوال... تكمن المشكلة األساسية بنقل الصوت في مدى توفر الشروط الالزمة حتى ي تم إيص ال وع رض الص وت بالش كل الس ليم و وف ق الترت ب ال ذي أرس ل علي ه وتعتب ر مح دوديات ومش اكل بروتوكوالت ال Transport Layer من أھ م م ا دع ا Microsoft م ن الع زوف ع ن دع م ال Dot Net لعملي ة نق ل الص وت وخاص ة ف ي بيئ ة النظ ام الح الي واكتف ت بجعلھ ا آداه خارجي ة باس تخدام ال API أو Managed باس تخدام ال DirectX وم ن المع روف أن نظ ام التش غيل Windows XP يدعم االتصال باستخدام بروتوكول TCP أو UDP فقط وھ ذا يعن ي ان ك إذا كن ت تعم ل تح ت منص ة نظ ام التش غيل Windows XP ف إن أي عملي ة اتص ال ل ن تك ون إال باستخدام واحد من ھذه البروتوكوالت. أوال : Systems : The Requirements of Voice Communication سوف نناقش في ھذا الجزء متطلبات نقل الصوت عبر الش بكة ومش اكل نق ل الص وت باس تخدام بروتوكول ال TCP و ال... UDP متطلبات نقل الصوت المثلى : 1 يفضل أن يكون أسلوب النقل ك Stream ويدعم ھذا األسلوب في ك ال البروتوك ولين الTCP والSCTP أما الUDP فقط في حالة استخدامه مع الRTP 2 البروتوكول المستخدم لنقل الصوت يجب أن يدعم Delivered on Sequence 3 تعتم د س رعة النق ل عل ى م دى حج م الض غط المس تخدم Voice Compression والجودة المطلوبة ويفضل في ھذه الحالة أن ال تقل سرعة النق ل ع ن 31 KB\S بمع دل ال يق ل عن KHz كحد أدن ى لج ودة الص وت وم ن الممك ن أعتم اد اس اليب ض غط أخ رى مث ل 711.G لمعرفة كيفي أستخدامه بالدوت نيت أنظر الرابط التالي - السؤال الذي يطرح نفسه اآلن ھل وفر بروتوكول ال TCP وال UDP ھذه األمور أوال بروتوك ول ال : TCP ي دعم بروتوك ول ال TCP ك ل ھ ذه األم ور وبكف اءة عالي ة لك ن المش كلة ف ي ھ ذا البروتوك ول ھ و أن ه ل يس Real Time ك ذلك ع دم إمكاني ة اس تخدامه لعم ل Multicast Conference System إذ ان ه م ن المع روف أن ال Multicasting وال Broadcasting م ن األم ور الخاص ة ببروتوك ول ال UDP وال ي دعم ال TCP أي م ن ھ ذه األم ور وھ و م ا بينت ه ف ي الفص ل الس ابق ويمك ن أن يك ون ھ ذا البروتوك ول Real Time Protocol ف ي حال ة قمن ا بإلغ اء ال Acknowledgment ف ي ال Header TCP إذ يعت ر الTCP بروتوكول موجه Oriented Protocol لذلك ال يمكن االعتماد عليه في حال ة حاجتن ا لعمل Multicast Conference System أو في حالة البث اإلذاعي. Broadcasting ثاني ا بروتوك ول ال : UDP ال يعتب ر ھ ذا البروتوك ول ح ل جي د لعملي ة نق ل الص وت بالكف اءة العالية (فقط في حالة ما أردنا نقل ص وت ع الي الدق ة) إذ أن ه ال ي دعم عملي ة Delivered on Sequence وھو م ا س بب م ن اس تحالة عم ل Fragmentation لل Packets المرس ل وم ن المع روف أن حج م Ethernet Encapsulation ال يزي د ع ن 1500 Bytes لل Packet ~136~
137 الواحد وھ و الحج م األقص ى لل Datagram Encapsulation الخ اص بال Ethernet ل ذلك في حالة قمنا بعمل Fragmentation لصوت فإننا ل ن نض من وص ول الص وت وف ق الترتي ب المرسل وھو ما يسبب مشكلة كبيرة في عملية إعادة ترتيب ال Fragments المرسل ومن ھ ذه النقطة قدمت الكثير من الشركات والمنظمات العالمية حلول خاصة لعملية نقل الصوت عبر ال Real Time Messaging Protocol منھا شركة أدوبي بتقديمھا بروتوكول النق ل UDP IETF Internet ومنظم ة RTMP RTP Real Time Transport بتقديمھا بروتوكول النقل Engineering Task Force Protocol حيث أضاف ھذا المعيار تحسينات على بروتوكول ال UDP لعملية نقل الص وت في الزمن الحقيقي إذ يستخدم أسلوب ال Stream المستخدم في.TCP ثانيا Communication: : The Concept Of Voice تمر عملية التقاط الصوت بمجموعة من المراحل تبدأ بالتقاط الصوت من المايكروفون وتمثيل الذب ذبات الص وتية ث م تحويلھ ا إل ى مجموع ة م ن ال 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 BYTES لل Packet الواحد ولحل ھذه المشكلة سوف نلج أ إل ى تبن ي بع ض التقني ات الجدي دة والتي تعتمد على بروتوكول ال UDP وحتى يتم نقل الصوت ك Stream ومنھا أس لوب النق ل 323.H والذي ذكرته سابقا لكن لم تدعم الدوت نيت أي من ھذه التقني ات ل ذلك عن دما نري د نقل صوت من جھاز إل ى آخرك Stream الب د لن ا م ن اس تخدام بروتوك ول ال TCP لك ن كم ا ذكرنا سابقا فإنه ال يدعم ال IP Multicasting و ال Broadcasting 3- ف ي ال Network Layer ي تم عنون ة ال Packets وإذا م ا قررن ا اعتم اد ال UDP فإنن ا سوف نتمكن من عمل البث اإلذاعي Broadcasting ومجموعات البث Multicasting 4- في ال Data Link Layer سيتم تحديد طبيعة وإلرس ال س واء باس تخدام ال Ethernet أو غي ره وف ي ھ ذه الحال ة س يتم االعتم اد عل ى ال Ethernet لك ن مش كلته كم ا ذكرتھ ا س ابقا بمحدودية حجم ال Frame إذ ال تتجاوز ال 1500 BYTES 5- في ال Physical Layer طبعا المشاكل التي ق د تح دث إثن اء عملي ة النق ل كثي رة ج دا وق د يحدث تأخير Delay لسبب أو آلخر أو قد تضيع بعض ال Bits إثن اء اإلرس ال ل ذلك الب د م ن وجود بروتوكوالت تدعم التصحيح لكل ھذه المشاكل والتي قد تحدث إثناء عملية اإلرسال. يستقبل الطرف المقابل ال Bits من طبق ة ال Physical Layer وتم ر عب ر ال Data Link Layer ومن ثم ال Network Layer وف ي إثن اء ھ ذه المرحل ة ف إن مس تقبل ال Packets ق د يكون ھو الشخص المعني في حالة كان أسلوب البث Unicast أو قد يكون ج زء م ن مجموع ة االستقبال Multicast أو قد يكون من ضمن الشبكة التي تم اإلرسال لھا ك Broadcast ل ذلك ~137~
138 ف ي حال ة كون ه ج زء م ن مجموع ة ف إن جھ ة اإلرس ال غي ر معني ة بالجھ ة الت ي س وف تس تقبل الPackets وفي ھذه الحالة فإنه غير معني سواء استقبلت جزء من ال Packets أو كلھا حيث لن يتم إرسال أي Acknowledgment إلى المرسل لذلك قد تح دث الكثي ر م ن المش اكل إثن اء ھذه المرحلة منھا ضياع جزء من ال Packets المرس ل وال ذي س وف يس بب وص ول الص وت بشكل متقطع وطبعا سوف يك ون االعتم اد ف ي ھ ذه الحال ة عل ى بروتوك والت الطبق ة األعل ى وھ ي ھن ا Transport Layer ف إذا ك ان المرس ل والمس تقبل يس تخدم ال TCP ف إن ك ل ھ ذه المشاكل سوف تحل لكن المشكلة تكمن في كونه يستخدم ال UDP حيث ال يوجد حل إال بإتب اع معيار مساند يضمن وصول كافة ال Packets بترتيب الذي أرسل عليه وب دون ض ياع أج زاء من ال Packets المرسل. الشكل التالي يوضح عملية ضياع بعض ال Packets إثناء اإلرسال باستخدام شبكة Ethernet Wireless LAN و UDP IP Multicasting مما سوف يسبب تقطيع في الصوت: ثالثا: How to Create a Voice Chat Through Dot et Using : Unmanaged API s Functions كما بينا سابقا فإن الدوت نيت لم تدعم أي م ن عملي ات التق اط وع رض الص وت لك ن إلج راء ھذه العمليات البد من استخدام الAPI s والمغلفة ضمن ملفات ال DLL والت ي ت أتي م ع نظ ام التشغيل ومنھا ملف winmm.dll الشھير والخاص بالتعام ل م ع وس ائل ال Multimedia في نظام التشغيل حي ث ي دعم ھ ذا المل ف مجموع ة م ن ال Methods اللتق اط الص وت عب ر الم ايكروفون وتخزين ه ف ي Byte Array Buffer وم ن ث م عرض ه م رة أخ رى وھ ذه الMethod ھي : waveinget umdevs والتي تستخدم لتحديد عدد أجھزة اإلدخال والمربوطة مع الCard Sound وال تأخذ أي باروميترات. Byte ف ي اإلدخ ال جھ از م ن ال واردة ال Bits لتخ زين وتس تخدم waveinaddbuffer Array Buffer وتأخذ ھذه الMethod ثالثة باروميترات وھي: waveinaddbuffer(intptr hwi, ref WaveHdr pwh, int cbwh) حي ث يم رر ل ألول جھ از اإلدخ ال وال ذي ت م اختي اره و يح دد ف ي الث اني Reference لموق ع تخزين ال Buffer وفي الثالث يحدد حجم ال Buffer المستلم الدالة waveinclose و waveinopen لفتح وإغالق االتصال مع جھاز اإلدخال. الدال ة waveinprepareheader لتجھي ز وحج ز ال Buffer وتأخ ذ نف س الب اروميترات الموجودة في.waveInAddBuffer الدالة waveinunprepareheader ويتم استدعائھا بعد تعبئة ال Buffer حتى يتم إرسال ال Buffer ومن ثم تفريغه لالستعداد لتعبئته مرة أخرى. الدالة waveinreset إلرجاع مؤشر الPointer الخاص بال Buffer إلى صفر الدالة waveinstart و الدالة waveinstop بدأ وإغالق عملية اإلدخال من المايكروفون. ~138~
139 والستخدام ھذه الدوال في الدوت نيت نقوم بتعريفھا أوال باستخدام DllImport وكما يلي: [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); VB. ET <DllImport(winmm.dll)> _ Public Shared Function waveingetnumdevs() As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveinaddbuffer(byval hwi As IntPtr, ByRef pwh As WaveHdr, ByVal cbwh As Integer) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveinclose(byval hwi As IntPtr) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveinopen(<system.runtime.interopservices.out()> ByRef phwi As IntPtr, ByVal udeviceid As Integer, ByVal lpformat As WaveFormat, ByVal dwcallback As WaveDelegate, ByVal dwinstance As Integer, ByVal dwflags As Integer) As Integer End Function ~139~
140 <DllImport(winmm.dll)> _ Public Shared Function waveinprepareheader(byval hwavein As IntPtr, ByRef lpwaveinhdr As WaveHdr, ByVal usize As Integer) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveinunprepareheader(byval hwavein As IntPtr, ByRef lpwaveinhdr As WaveHdr, ByVal usize As Integer) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveinreset(byval hwi As IntPtr) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveinstart(byval hwi As IntPtr) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveinstop(byval hwi As IntPtr) As Integer End Function وكم ا س وف نس تخدم مجموع ة ال Methods التالي ة لتحوي ل ال Byte Array Buffer إل ى صوت مرة أخرى وعرضه على جھاز اإلخراج : [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); ~140~
141 [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); VB. ET <DllImport(winmm.dll)> _ Public Shared Function waveoutgetnumdevs() As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveoutprepareheader(byval hwaveout As IntPtr, ByRef lpwaveouthdr As WaveHdr, ByVal usize As Integer) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveoutunprepareheader(byval hwaveout As IntPtr, ByRef lpwaveouthdr As WaveHdr, ByVal usize As Integer) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveoutwrite(byval hwaveout As IntPtr, ByRef lpwaveouthdr As WaveHdr, ByVal usize As Integer) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveoutopen(<system.runtime.interopservices.out()> ByRef hwaveout As IntPtr, ByVal udeviceid As Integer, ByVal lpformat As WaveFormat, ByVal dwcallback As WaveDelegate, ByVal dwinstance As Integer, ByVal dwflags As Integer) As Integer End Function <DllImport(winmm.dll)> _ Public Shared Function waveoutreset(byval hwaveout As IntPtr) As Integer End Function <DllImport(mmdll)> _ Public Shared Function waveoutclose(byval hwaveout As IntPtr) As Integer End Function <DllImport(mmdll)> _ Public Shared Function waveoutpause(byval hwaveout As IntPtr) As Integer ~141~
142 End Function <DllImport(mmdll)> _ Public Shared Function waveoutrestart(byval hwaveout As IntPtr) As Integer End Function <DllImport(mmdll)> _ Public Shared Function waveoutgetposition(byval hwaveout As IntPtr, <System.Runtime.InteropServices.Out()> ByRef lpinfo As Integer, ByVal usize As Integer) As Integer End Function <DllImport(mmdll)> _ Public Shared Function waveoutsetvolume(byval hwaveout As IntPtr, ByVal dwvolume As Integer) As Integer End Function <DllImport(mmdll)> _ Public Shared Function waveoutgetvolume(byval hwaveout As IntPtr, <System.Runtime.InteropServices.Out()> ByRef dwvolume As Integer) As Integer End Function وحتى نتمكن من عرض محتويات ال Buffer نستخدم التعريف التالي: 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 static void PlayWavResource(byte[] buffer) PlaySound(buffer, IntPtr.Zero, SND_ASYNC SND_MEMORY); VB. ET Imports System Imports System.Runtime.InteropServices ~142~
143 Imports System.Resources Imports System.IO Public Class Winmm Public Const SND_ASYNC As UInt32 = System.Convert.ToUInt32(1) Public Const SND_MEMORY As UInt32 = System.Convert.ToUInt32(4) <DllImport("Winmm.dll")> _ Public Shared Function PlaySound(ByVal data As Byte(), ByVal hmod As IntPtr, ByVal dwflags As UInt32) As Boolean End Function Public Sub New() End Sub Public Shared Sub PlayWavResource(ByVal buffer As Byte()) PlaySound(buffer, IntPtr.Zero, SND_ASYNC Or SND_MEMORY) End Sub End Class حيث نمرر لل PlaySound Method ال Byte Buffer والمس تلم م ن Method االس تقبال الخاصة بالSocket وكما يلي: 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(); VB. ET Private Sub Voice_Receiver() Dim sock As UdpClient = New UdpClient(5020) sock.joinmulticastgroup(ipaddress.parse(multicast_ip.text)) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Dim voice_come As Byte() = sock.receive(iep) Winmm.PlayWavResource(voice_Come) sock.close() End Sub ~143~
144 البدء بإنشاء برنامج المحادثة الصوتية : 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 وسيكون الشكل العام لبرنامج االتصال كما يلي : وس وف نق وم بكبس لة ال Classes الس ابقة ف ي مل ف Voice.dll وس وف نض عه ف ي الReferences الخاصة بالبرنامج وحتى نستطيع استخدام ھذا المل ف ف ي جمي ع الب رامج الت ي سوف تستخدم عملية االتصال الص وتي بع د ھ ذه العملي ة يمك ن اس تخدام المل ف باس تدعائه ك أي Managed Library Class في الدوت نيت وكما يلي: using System.Net; using System.Net.Socket; using System.Threading; using Voice; VB. ET Imports System.Net Imports System.Net.Socket Imports System.Threading Imports Voice ~144~
145 ثم نقوم بتعريف الSocket والThread والذي سوف نستخدمه في البرنامج ويفض ل وض ع ھذه التعريفات في بداية البرنامج أي بعد تعري ف ال Class الرئيس ي والھ دف م ن ھ ذه العملي ة ھي القدرة على إغالق ال Socket والThread عند إطفاء البرنامج وحتى ال تبقى في الذاكرة عند إغالق برنامج االتصال ويتم ذلك كما يلي: public class Form1 : System.Windows.Forms.Form private Socket socket; private Thread thread; VB. ET Public Class Form1 : Inherits System.Windows.Forms.Form Private socket As Socket Private thread As Thread وسوف نعرف Object من الClasses السابقة ونعرف الBuffer الذي سيتم تسجيل الص وت المراد إرساله والBuffer الذي سيتم عرض الصوت المستلم من الSocket private WaveOutPlayer m_player; private WaveInRecorder m_recorder; private FifoStream m_fifo = new FifoStream(); private byte[] m_playbuffer; private byte[] m_recbuffer; VB. ET Private m_player As WaveOutPlayer Private m_recorder As WaveInRecorder Private m_fifo As FifoStream = New FifoStream Private m_playbuffer As Byte() Private m_recbuffer As Byte() في ال Constructor الخ اص بالبرن امج أو ف ي ال Form Load Event ق م بكتاب ة التعري ف الخاص بال Socket وال : Thread public Form1() InitializeComponent(); socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); thread = new Thread(new ThreadStart(Voice_In)); ~145~
146 VB. ET socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) thread = New Thread(AddressOf Voice_In) سوف نضع في الMethod Voice_In الكود الخاص بعملية استقبال الصوت من الSocket وكما يلي: 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); VB. ET Private Sub Voice_In() Dim br As Byte() socket.bind(new IPEndPoint(IPAddress.Any, 5020)) Do While True br = New Byte(16383) socket.receive(br) m_fifo.write(br, 0, br.length) Loop End Sub حي ث ي تم اس تقبال الص وت م ن الش بكة باس تخدام ال Method Receive ث م نم رر الص وت المستقبل إلى الMethod m_fifo.write وحتى يتم تنفيذه وتحويله إلى صوت مرة أخرى. أما الMethod التي تقوم بتسجيل الصوت وإرساله إلى الجھاز األخر فھي: 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); ~146~
147 //Microphone ==> data ==> m_recbuffer ==> m_fifo socket.sendto(m_recbuffer, new IPEndPoint(IPAddress.Parse(Peer_IP.Text),5030)); VB. ET Private Sub Voice_Out(ByVal data As IntPtr, ByVal size As Integer) 'for Recorder If m_recbuffer Is Nothing OrElse m_recbuffer.length < size Then m_recbuffer = New Byte(size - 1) End If 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)) End Sub الحظ أنه في حال ة إذا م ا أردن ا عم ل برن امج Full Duplex بحي ث يرس ل ويس تقبل ف ي نف س الوقت فإننا بحاجة إلى تعري ف Tow Ports واح د لإلرس ال وأخ رى لالس تقبال وف ي الط رف األخر تكون Port اإلرسال لديك ھي Port االستقبال لديه والعكس صحيح. في زر البدء يتم تنفيذ الدالة التالية حيث استخدمنا ال WaveFormat لتحديد جودة الصوت بBits, 2 Channels & KHz 16 وأسندت إلى الClass WaveOutPlayer والذي سيستخدم لتعبئة الBuffer وفي حال تعبئته يتم إرساله إلى ال Voice_Out Method إلرساله عبر الشبكة إلى الجھاز اآلخر : 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; VB. ET Private Sub Start() Stop() Try ~147~
148 Dim fmt As WaveFormat = New WaveFormat(44100, 16, 2) m_player = New WaveOutPlayer(-1, fmt, 16384, 3, New BufferFillEventHandler(AddressOf Filler)) m_recorder = New WaveInRecorder(-1, fmt, 16384, 3, New BufferDoneEventHandler(AddressOf Voice_Out)) Catch Stop() Throw End Try End Sub أما في زر اإليقاف فيتم تنفيذ الدالة التالية حيث سيتم تفريغ محتويات ال Buffer وإيقاف تسجيل الصوت: 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 VB. ET Private Sub [Stop]() If Not m_player Is Nothing Then Try m_player.dispose() Finally m_player = Nothing End Try End If If Not m_recorder Is Nothing Then Try m_recorder.dispose() Finally m_recorder = Nothing End Try ~148~
149 End If m_fifo.flush() ' clear all pending data End Sub وتستخدم ال Filler Method لتعبئة الصوت في ال Buffer وإلتمام عملية عرضه على السماعات( :( Output Device 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 VB. ET Private Sub Filler(ByVal data As IntPtr, ByVal size As Integer) If m_playbuffer Is Nothing OrElse m_playbuffer.length < size Then m_playbuffer = New Byte(size - 1) End If If m_fifo.length >= size Then m_fifo.read(m_playbuffer, 0, size) Else Dim i As Integer = 0 Do While i < m_playbuffer.length m_playbuffer(i) = 0 i += 1 Loop End If System.Runtime.InteropServices.Marshal.Copy(m_PlayBuffer, 0, data, size) ' m_fifo ==> m_playbuffer==> data ==> Speakers End Sub ~149~
150 رابعا: Testing TCP,UDP and Thinking in SCTP to Transfer Voice : Through etworks إلنشاء برنامج Multicast Half Duplex Voice Chat System نقوم بإضافة التعريف ات التالية والخاصة بالMulticasting والتي شرحناھا ف ي الفص ل الس ابق وس وف نعتم د عل ى وجود برنامجين واحد للمحاضر يتم من خالله تس جيل الص وت وآخ ر لطال ب حي ث يس تمع في ه لمحاضرة المعلم وكما في الشكل التالي: في برنامج اإلرسال (برنامج المعلم) ال يختلف الكود بشيء فقط عند اإلرسال يتم ذلك باس تخدام ال IP Multicasting وكما يلي: 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(" "), 5020)); VB. ET Private Sub Voice_Out(ByVal data As IntPtr, ByVal size As Integer) 'for Recorder ~150~
151 If m_recbuffer Is Nothing OrElse m_recbuffer.length < size Then m_recbuffer = New Byte(size - 1) End If System.Runtime.InteropServices.Marshal.Copy(data, m_recbuffer, 0, size) 'Microphone ==> data ==> m_recbuffer ==> m_fifo socket.sendto(m_recbuffer, New IPEndPoint(IPAddress.Parse(" "), 5020)) End Sub ف ي الط رف المس تقبل نق وم باالنض مام إل ى ال Group IP Multicast وم ن ث م االس تقبال م ن خالله وكما يلي: private void Voice_In() UdpClient sock = new UdpClient(5000); sock.joinmulticastgroup(ipaddress.parse(" ")); IPEndPoint iep = new IPEndPoint(IPAddress.Any,0); while (true) m_fifo.write(sock.receive(ref iep), 0,sock.Receive(ref iep).length); VB. ET Private Sub Voice_In() Dim sock As UdpClient = New UdpClient(5000) sock.joinmulticastgroup(ipaddress.parse(" ")) Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Any, 0) Do While True m_fifo.write(sock.receive(iep), 0, sock.receive(iep).length) Loop End Sub اآلن نفذ البرنامج... الحظ أن الصوت قد يتقطع أحيانا وبتأكيد السبب واضح وھو أنه ف ي حال ة استخدام بروتوكول ال UDP والMulticasting فإن عملية اإلرسال ستكون عشوائية وھذا قد يسبب ضياع واحد أو أكثر من الPackets المرسلة عبر الشبكة كل فترة وبما أن بروتوكول ال UDP ال ي دعم أي م ن عملي ات التحق ق م ن الوص ول وعملي ات التوص يل عل ى الترتي ب ف إن حدوث واحد أو أكثر من ھذه المشاكل أمر محتمل. دعنا اآلن نختب ر عملي ة اإلرس ال باس تخدام بروتوك ول TCP الح ظ أن ھ ذا البروتوك ول ھ و بروتوك ول موج ه Oriented Protocol كم ا ي دعم جمي ع عملي ات التحق ق م ن الوص ول باإلضافة إلى كونه يدعم االتصال بين الطرفين باستخدام أسلوب ال Stream وھو ما يمي ز ھ ذا البروتوكول عن غيره إذ أننا في حالة استخدامه ل ن نض طر إل ى األخ ذ بحج م البيان ات المرس لة حيث يتم عم ل Fragmentation لھ ا بك ل س ھولة باإلض افة إل ى س ھولة تجميعھ ا م رة أخ رى وبدون الخوف من مشاكل ال. Delivered Out on Sequence ~151~
152 كل ما علينا تغييره ھو تعريف ال Socket السابق وجعله كما يلي : socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); VB. ET socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) أما في عملية اإلرسال فيمكننا استخدام الClass Network Stream وكما يلي: 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(" "),5020)); NetworkStream ns = new NetworkStream (socket); ns.write (m_recbuffer,0,m_recbuffer.length); VB. ET Private Sub Voice_Out(ByVal data As IntPtr, ByVal size As Integer) 'for Recorder If m_recbuffer Is Nothing OrElse m_recbuffer.length < size Then m_recbuffer = New Byte(size - 1) End If System.Runtime.InteropServices.Marshal.Copy(data, m_recbuffer, 0, size) 'Microphone ==> data ==> m_recbuffer ==> m_fifo sock.connect(new IPEndPoint(IPAddress.Parse(" "), 5020)) Dim ns As NetworkStream = New NetworkStream(socket) ns.write(m_recbuffer, 0, m_recbuffer.length) End Sub في الطرف المستقبل نقوم باستخدام ال Network Stream مرة أخرى لكن لالستقبال: private void Voice_In() Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ~152~
153 sock.bind(new IPEndPoint(IPAddress.Parse(" "),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); VB. ET Private Sub Voice_In() Dim sock As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) sock.bind(new IPEndPoint(IPAddress.Parse(" "), 5020)) Dim ns As NetworkStream = New NetworkStream(sock) Do While True Dim buffer As Byte() = New Byte(16383) ns.read(buffer, 0, 16384) m_fifo.write(buffer, 0, buffer.length) Loop End Sub الحظ أن دق ة الص وت أص بحت ممت ازة كم ا أن ه ال يوج د أي تقطي ع ف ي الص وت لك ن المش كلة تكم ن ف ي أنن ا ل ن نس تطيع االس تفادة م ن ھ ذه اإلمكاني ات الرائع ة ف ي ال Multicasting أو الBroadcasting... والحل الوحيد ھو إما استخدام المعايير الس ابقة م ع بروتوك ول ال UDP وھ و م ا ت م اس تخدامه اآلن في معظ م البرمجي ات يمكن ك الرج وع إل ى الق رص الم دمج المث ال OpenH323 لمعرف ة كيفية استخدام ال UDP وال RTP لنق ل الص وت وف ق المعي ار H323. أو اس تخدام بروتوك ول الTCP وھو جيد في حالة كان عامل التزامن غي ر مھ م ب ين المرس ل والمس تقبل وكمث ال عل ى ذل ك برن امج Windows Media Server وال ذي يس تخدم ال TCP م ع ال HTTP لنق ل الصوت والصورة أو استخدام أسلوب النقل عبر ال Direct Play ضمن ال.DirectX السؤال الذي يطرح نفسه اآلن ما ھو الجديد بھذا البروتوكول ھل حل المشكلة الجواب بك ل بس اطة نع م ق د ح ل المش كلة حي ث أن معماري ة ھ ذا البروتوك ول ال ذي اس تفاد م ن ميزات الTCP والدعم المقدم من قبل الUDP لعمليات الMulticasting إذ أصبح ل دينا اآلن منصة قوية يعتمد عليھا في عمل الFragmentation وإعادة ترتيبھا بكل سھولة باإلضافة إلى دعم ه عملي ة Delivered on Sequence وھ ذا واض ح م ن بني ة ال Header الخاص ة بھ ذا البروتوكول انظر إلى الشكل التالي: ~153~
154 خامسا: How to Create a Voice Conference System Using Microsoft : Direct Play 9 دعمت Microsoft تقنيات رائعة جدا للنق ل الص وت ف ي اإلص دار الخ اص ب Play9 Direct ويس مى أيض ا DirectPlay Transport Protocol وھ و ج زء م ن مجموع ة ال DirectX وك ان الھ دف م ن إطالقھ ا وج ود معي ار موح د لمب رمجين األلع اب فيم ا يخ ص ال Network Games وتعتمد ھذه المكتب ة عل ى مجموع ة م ن المع ايير الخاص ة بتش بيك حي ث ك ان الھ دف منھا ھ و جع ل عملي ة االتص ال ممكن ة تح ت جمي ع البيئ ات المختلف ة و س واء ك ان البروتوك ول المس تخدم ھ و ال TCP/IP أو IPX الخ اص ب Novel ف إن عملي ة االتص ال ممكن ة وب دون أي اختالفات من النواحي البرمجية ومن أھم ميزات ال :DirectPlay Transport Protocol - messages Reliable delivery of حيث يدعم عملية التحقق التوصيل للجھة المعنية - messages Sequential a delivery of حيث يدعم التوصيل وفق الترتيب الصحيح - prioritization Send حيث يدعم عملية وضع أولويات لإلرسال بناء على األھمية Stream حيث تدعم عملية النقل كData Streaming Session - قدمت Microsoft ھذه الحلول كبدائل لدعم بروتوك ول ال SCTP المنتظ ر وق د حل ت جمي ع المش كالت الت ي كان ت تواج ه المب رمجين لنق ل الص وت عب ر بروتوك ول ال TCP أو ال UDP وح ل محل ه أس لوب آخ ر ل ربط ض من مس توى طبق ة ال Transport Layer وتحت وي ال Direct Play على مجموعة ضخمة من الClasses ومن أھمھا : أوال : ال Connect Classes والخاصة بعملية الربط: ال Guido, Peer Classes Address حي ث تس تخدم عن د إنش اء االتص ال م ع الط رف األخر وتستخدم DirectPlay طريقة لتمييز البرنامج عن األخر بتوليد Hash Code خاص بكل برن امج وي تم ذل ك باس تخدام ال Class Guido وي تم تمري ر الك ود المول د وعن وان الجھ از المقابل إلى ال Peer Class وھذه العملية شبيھة بشكل كبير لعملية الربط باستخدام ال Socket في بروتوكول TCP/IP ويتم استخدامھا كما يلي كمثال: ~154~
155 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 VB. ET Imports Microsoft.DirectX.DirectPlay... Private Address hostaddress = New Address() Private hostaddress.serviceprovider = Address.ServiceProviderTcpIp ' Select TCP/IP service provider Private dpapp As ApplicationDescription = New ApplicationDescription Private appguid = Guid.NewGuid() ' Create a GUID for the application Private dpapp.guidapplication = appguid ' Set the application GUID Private dpapp.sessionname = "My Session" ' Optional Session Name mypeer.host(dpapp, hostaddress) ' Begin hosting طبعا يجب االختيار طبيعة البروتوكول المستخدم سواء كان TCP/IP أو IPX وحتى نس تطيع وضع العنوان المقابل أو ال IP Address ويتم ذلك كما يلي: using Microsoft.DirectX.DirectPlay; ServiceProviderInfo[] myspinfo; Peer mypeer; System.Windows.Forms.ListBox listbox1; ApplicationDescription myappdesc;.. mypeer = new Peer(); hostaddress = new Address(); peeraddress = new Address(); ~155~
156 // 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); VB. ET Imports Microsoft.DirectX.DirectPlay Private myspinfo As ServiceProviderInfo() Private mypeer As Peer Private listbox1 As System.Windows.Forms.ListBox Private myappdesc As ApplicationDescription Private mypeer = New Peer Private hostaddress = New Address Private peeraddress = New Address ' Set the service provider to TCP/IP Private peeraddress.serviceprovider = Address.ServiceProviderTcpIp Private hostaddress.serviceprovider = Address.ServiceProviderTcpIp ' Attach FindHostResponseEventHandler to receive FindHostResponseMessages Private mypeer.findhostresponse += New FindHostResponseEventHandler(myEnumeratedHosts) ' Call FindHosts to start the enumeration mypeer.findhosts(myappdesc, hostaddress, peeraddress, Nothing, 10, 0, 0, FindHostsFlags.OkToQueryForAddressing) حيث تم تعريف نوع البروتوكول المستخدم وھو TCP/IP ويتم البحث عن الطرف األخر في الش بكة باس تخدام ال Method FindHosts والموج ودة ض من ال Class Peer وت تم عملي ة الربط مباشرة باستخدام الMethod Connect والموجودة ضمن ال Peer Class وكما يلي: using Microsoft.DirectX.DirectPlay; // Structure for FindHostResponseMessages public struct HostInfo public ApplicationDescription appdesc; ~156~
157 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); VB. ET Imports Microsoft.DirectX.DirectPlay ' Structure for FindHostResponseMessages Public Structure HostInfo Public appdesc As ApplicationDescription Public deviceaddress As Address Public senderaddress As Address End Structure Private mypeer As Peer = New Peer Private hostinfo As HostInfo = New HostInfo ' The FindHostResponseEventHandler ~157~
158 Public Sub myenumeratedhosts(byval o As Object, ByVal args As FindHostResponseEventArgs) hostinfo.appdesc = args.message.applicationdescription hostinfo.deviceaddress = args.message.addressdevice hostinfo.senderaddress = args.message.addresssender End Sub ' Attach the ConnectCompleteEventHandler to receive ConnectCompleteMessages Private mypeer.connectcomplete += New ConnectCompleteEventHandler(OnConnectComplete) ' Call connect passing the Host information returned in the FindHostResponse event mypeer.connect(hostinfo.appdesc, hostinfo.deviceaddress, hostinfo.senderaddress, Nothing, ConnectFlags.OkToQueryForAddressing) ~158~
159 ثانيا: Microsoft.DirectX.DirectPlay.Voice والخاصة بكل عمليات تسجيل ونقل وعرض الصوت: تمر عملية تسجيل ونقل وعرض الصوت بمجموعة من المراحل ونلخصھا بالشكل التالي: وسوف نقسمھا إلى مجموعة من ال Classes حسب الوظيفة لكل منھا. 1- ال Classes الخاصة بطرف ال Server إلنشاء وإدارة ال : Sessions Server Class ويستخدم كما يلي كمثال: Server server = new Voice.Server(peerObject); VB. ET Dim server As Server = New Voice.Server(peerObject) ~159~
160 حيث نسند له ال Peer Object والذي تم اشتقاقه من ال Peer Class ويحتوي ال Server Object عل ى ال Methods الخاص ة بعملي ة ب دأ وإنھ اء الجلس ة باإلض افة إل ى مجموع ة م ن العمليات األخرى: ولب دأ الجلس ة يج ب أوال إس ناد خص ائص الجلس ة إل ى ال Method StartSession حي ث ي تم تعريفھا من خالل ال SessionDescription و كما يلي: //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; VB. ET 'set up session description for the voice server Dim sessiondesc As Voice.SessionDescription = New Voice.SessionDescription sessiondesc.bufferaggressiveness = Voice.BufferAggressiveness.Default sessiondesc.bufferquality = Voice.BufferQuality.Default sessiondesc.flags = 0 sessiondesc.sessiontype = type sessiondesc.guidcompressiontype = compressiontype وإلنشاء Voice Session نقوم بإنشاء Method نم رر لھ ا ال Peer Object وال Voice Session Type ونوع الضغط المستخدم Compression Type ويتم ذلك كما يلي: protected void CreateVoiceSession(Peer dpp, Voice.SessionType type, Guid compressiontype) try ~160~
161 //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; VB. ET Protected Sub CreateVoiceSession(ByVal dpp As Peer, ByVal type As Voice.SessionType, ByVal compressiontype As Guid) Try 'set up session description for the voice server Dim sessiondesc As Voice.SessionDescription = 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 dxe As DirectXException ~161~
162 Throw dxe End Try Catch e As Exception Throw e End Try End Sub CreateVoiceSession(host, Voice.SessionType.Peer, mconfigform.compressionguid); ويتم استدعائھا كما يلي: VB. ET CreateVoiceSession(host, Voice.SessionType.Peer, mconfigform.compressionguid) 2- ال Classes الخاصة بطرف ال Client لالتصال مع ال Sessions التي أنشئھا الServer : ال Client Class ومن أھم الMethods الموجودة في ال : Client Class الدال ة Connect وتس تخدم ل ربط م ع ال Session Voice حي ث يرس ل ال Server رق م الSession لل Client وعندھا يتمكن ال Client من الدخول إلى الجلسة ويتم ذلك كما يلي: 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; ~162~
163 //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; VB. ET Protected Sub ConnectToVoiceSession(ByVal dpp As Peer, ByVal wnd As Form) Try Dim soundconfig As Voice.SoundDeviceConfig = 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 Dim xmittargets As Integer() = New Integer(0) xmittargets(0) = CInt(PlayerID.AllPlayers) client.transmittargets = xmittargets 'get sound device config to check for half-duplex soundconfig = client.sounddeviceconfig ~163~
164 mhalfduplex = ((soundconfig.flags And Voice.SoundConfigFlags.HalfDuplex) <> 0) Catch e As Exception Throw e End Try End Sub الحظ أن المشاكل في البروتوكولين ال TCP والUDP ق د ت م حلھ ا ف ي ال DirectPlay لك ن وكما ھو معروف فإن الھدف من إنشاء ال Direct Play ل م يك ن س وى ل دعم برمج ة األلع اب ومع المرونة الكبيرة التي تقدمھا ال Direct Play في عملي ة االتص ال الص وتي إال أنھ ا تفتق ر لميزات ال Voice Over IP والتي يقدمھا بروتوكول ال SCTP الخاص بال...Linux وھكذا بينا ملخص عن أھم الط رق التص ال الص وتي عب ر الش بكة وط رق برمج ة ال Voice Transport ال Layer بروتوك والت وعي وب مي زات واھ م ني ت ال دوت منص ة تح ت Chat ومدى إمكانياتھا لنق ل الص وت عب ر الش بكة وأخي را ش رح ألھ م ال Classes والمس تخدمة ف ي االتص ال الص وتي باس تخدام ال DirectPlay Transport Protocol س نقوم اآلن بتطبي ق برن امج Video Voice Conference System باس تخدام ال TCP إلرس ال الص ورة وال UDP إلرسال الصوت. ~164~
165 ثالث ا: تص ميم برن امج للمحادث ة الص وتية والمرئي ة وط رق التعام ل م ع ال TAPI Telephony في بيئة الدوت نيت: Design an Advanced Video /Voice Conferencing System By Using API & TAPI Telephony to Transfer Video/Voice Through etworks & Voice Through Analog Telephone Line: مالحظة ھامة جدا: يفترض بك قبل البدء بقراءة ھذا الجزء من فصل ال VOIP قراءة المواضيع التالية: Streaming in Dot et -1 TCP,UDP Socket Programming -2 Advanced Multicasting Systems الجزء األول من ھذا الفصل VOIP بين ا ف ي الج زء األول م ن ھ ذا الفص ل كيفي ة اس تخدام ال API unmanaged methods م ن المل ف winmm.dll المخص ص لتعام ل م ع ال Multimedia ف ي بيئ ة نظ ام التش غيل واس تخدمنا مجموع ة ال Methods لتس جيل الص وت م ن الم ايكروفون وتحويل ه إل ى Byte Array إلرس اله وم ن ث م تحوي ل ال Byte Array إل ى ص وت م رة أخ رى باس تخدام أس لوب العرض... FIFO First in First Out وس نحاول ف ي ھ ذا المث ال االس تفادة م ن خ دمات الtelephony TAPI وذلك لنقل الصوت من الحاسوب إلى طرف آخر يستخدم الھاتف النق ال أو الھ اتف األرض ي Analog Phone ويمك ن االس تفادة م ن ال TAPI telephony بع دة طرق أسھلھا االستفادة من البرنامج الموجود مع نظام التشغيل TAPI V3.0 والمتاح مع نظام التشغيل... Windows XP وسيكون المخطط العام للمشروع كما في الشكل التالي: 1- سيحتوي المش روع عل ى Database Server وتقتص ر وظيفت ه عل ى تخ زين معلوم ات الموظفين في الشركة كأرقام الھوات ف و العن اوين ال Computers Names الخاص ة ب أجھزة الموظفين... ~165~
166 2- س يتمكن جمي ع الم وظفين م ن االتص ال الص وتي والمرئ ي م ع أي م ن أقس ام الش ركة باإلضافة إلى استخدام الTelephony TAPI لالتصال مع ال Analog Phone وبالعكس... وللب دء بتطبي ق المش روع س نقوم بتص ميم قاع دة بيان ات تحت وي عل ى أس ماء الم وظفين والName Computer لكل منھم وأقسامھم وأرقام ھواتفھم كما يلي: Computer Name (hidden for Clients) Telephone Number Group ID Other Info ( Address) String (Primary Kay) String String String (foreign Kay) String وج دول آخ ر يحت وي عل ى ال Group ID وال Group Name حي ث يض اف إلي ه أس ماء األقسام في الشركة وي رتبط م ع ج دول معلوم ات الم وظفين بال... Group ID بع د تص ميم قاع دة البيان ات الس ابقة س نبدأ بتص ميم شاش ة ال Client الت ي سيس تخدمھا الم وظفين داخ ل الشركة وسيكون الشكل العام لھا كما يلي: حي ث يح دد الموظ ف أو الم دير اس م القس م ال ذي يري د االتص ال مع ه وعن د اختي ار اس م القس م سيظھر ال Combo box المقابل جميع أسماء الموظفين الذين يعملون في ذلك القسم وفي حال اختيار إحداھم فإنه يقوم بعمل SELECT Query عل ى ال Telephone Number الخ اص بالموظف باإلضافة إلى ال Computer_Name الخاصة ب ه حي ث يمكن ه إم ا إج راء مكالم ة باستخدام ال TAPI Telephony أو إجراء مكالمة داخلي ة باس تخدام ال VOIP وف ي الحال ة األولى فإن االتصال سيتم عبر ال Modem وخطوط االتصاالت العادية أما ف ي حال ة اختي ار االتصال بال VOIP عندھا يتم البدء بإرسال الصوت إلى ال Computer_Name ال ذي يري د ~166~
167 االتصال معه (يستخرج من قاعدة البيان ات عن د اختي ار اس م الموظ ف)و ي تم بإرس ال تنبي ه إل ى ال Client إلخب اره بوج ود مكالم ة ص وتية منتظ رة وف ي ح ال الموافق ة يح ول الص وت إل ى ال Computer الخ اص ب الموظف وت تم العملي ة ف ي االتص ال المرئ ي ب نفس الطريق ة الت ي شرحناھا في االتصال الصوتي... تتم عملية اس تخدام ال TAPI Telephony ف ي ال دوت ني ت باس تخدام دوال ال API ويمكنن ا االستفادة من الMethods التي يوفرھا الملف المخصص لتعامل مع ال TAPI Telephony وھو tapi32.dll ويحتوي ھذا الملف على عدد ضخم من ال Methods والتي يمك ن التعام ل معھا في بيئة الدوت نيت وكمثال عليھا: Method ame tapirequestmakecall(string stnumber, string stdummy1, string stdummy2, string stdummy3) phoneshutdown (hphoneapp app) [DllImport("tapi32.dll")] static extern long phoneshutdown(long hphoneapp); LONGWINAPIphoneSetVolume( HPHONE hphone, DWORD dwhookswitchdev, DWORD dwvolume) Description وتستخدم إلجراء عملية االتصال باستخدام ال Modem حيث يمرر لھا رقم الھاتف الذي نريد إجراء اتصال معه وتستخدم إلغالق برنامج ال TAPI Telephony وتستخدم ھذه الدالة لتحديد درجة الصوت ويمرر لھا الدرجة بال Hex حيث تعبر القيمة 0x على عدم وجود صوت أما القيمة 0x0000FFFF فتعبر عن ال maximum... volume تنويه : لإلطالع على كافة ال Methods الخاصة بال TAPI Telephony أنظر الملحقات (Part 5). Appendixes A سنس تخدم ف ي ھ ذا المش روع ال tapirequestmakecall Method والت ي نم رر لھ ا رق م الھاتف إلجراء عملية االتصال ويتم تعريفھا كما يلي: [System.Runtime.InteropServices.DllImport("tapi32.dll")] static extern long tapirequestmakecall(string stnumber, string stdummy1, string stdummy2, string stdummy3);... long RetVal = tapirequestmakecall(telephone_number, "", "", ""); <System.Runtime.InteropServices.DllImport("tapi32.dll")> _ ~167~
168 Shared Function tapirequestmakecall(byval stnumber As String, ByVal stdummy1 As String, ByVal stdummy2 As String, ByVal stdummy3 As String) As Long End Function.. Dim RetVal As Long = tapirequestmakecall(telephone_number, "", "", "") استقبال الصوت من السيرفر // Voice_In() private void byte[] br; r.bind(new IPEndPoint(IPAddress.Any, int.parse(text_receiveingport.text))); while (true) br = new byte[16384]; r.receive(br); m_fifo.write(br, 0, br.length); ~168~ تتم عملية استقبال وإرسال الصوت كما يلي: إرسال الصوت إلى السيرفر//( size private void Voice_Out(IntPtr data, int if (m_recbuffer == null m_recbuffer.length < size) m_recbuffer = new byte[size]; System.Runtime.InteropServices.Marshal.Copy(data, m_recbuffer, 0, size); r.sendto(m_recbuffer, new IPEndPoint(IPAddress.Parse(Server_name), int.parse(text_sendingport.text))); استقبال الصوت من السيرفر ' Voice_In() Private Sub Dim br As Byte() r.bind(new IPEndPoint(IPAddress.Any, Integer.Parse(text_ReceiveingPORT.Text))) Do While True br = New Byte(16383) r.receive(br) m_fifo.write(br, 0, br.length) Loop End Sub
169 Private Sub Voice_Out(ByVal data As IntPtr, ByVal size As Integer) إرسال الصوت إلى السيرفر' If m_recbuffer Is Nothing OrElse m_recbuffer.length < size Then m_recbuffer = New Byte(size - 1) End If System.Runtime.InteropServices.Marshal.Copy(data, m_recbuffer, 0, size) r.sendto(m_recbuffer, New IPEndPoint(IPAddress.Parse(Server_name), Integer.Parse(text_SendingPort.Text))) End Sub وتتم عملية إرسال واستقبال صورة الكاميرا من وإلى ال Server كما يلي: private void Start_Receiving_Video_Conference() try // Open The Port mytcpl = new TcpListener (int.parse(text_camera_rec_port.text)); mytcpl.start (); // Start Listening on That Port mysocket = mytcpl.acceptsocket (); ns = new NetworkStream (mysocket); picturebox2.image = Image.FromStream(ns); mytcpl.stop(); if (mysocket.connected ==true) while (true) Start_Receiving_Video_Conference (); myns.flush(); catch (Exception) private void Start_Sending_Video_Conference(string remote_ip,int port_number) try ~169~
170 MemoryStream ms = new MemoryStream();// Store it in Binary Array as Stream picturebox1.image.save(ms,system.drawing.imaging.imageformat.jp eg); byte[] arrimage = ms.getbuffer(); myclient = new TcpClient (server_ip,port_number);//connecting with server myns = myclient.getstream (); mysw = new BinaryWriter (myns); mysw.write(arrimage);//send the stream to above address ms.flush(); mysw.flush(); myns.flush(); ms.close(); mysw.close (); myns.close (); myclient.close (); catch (Exception ex) MessageBox.Show(ex.Message,"Video Conference Error Message",MessageBoxButtons.OK,MessageBoxIcon.Error); Private Sub Start_Receiving_Video_Conference() Try mytcpl = New TcpListener(Integer.Parse(text_Camera_rec_port.Text)) mytcpl.start() mysocket = mytcpl.acceptsocket() ns = New NetworkStream(mysocket) picturebox2.image = Image.FromStream(ns) mytcpl.stop() If mysocket.connected = True Then Do While True Start_Receiving_Video_Conference() Loop End If myns.flush() Catch e1 As Exception End Try End Sub ~170~
171 Private Sub Start_Sending_Video_Conference(ByVal remote_ip As String, ByVal port_number As Integer) Try Dim ms As MemoryStream = New MemoryStream picturebox1.image.save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrimage As Byte() = ms.getbuffer() myclient = New TcpClient(server_IP, port_number) myns = myclient.getstream() mysw = New BinaryWriter(myns) mysw.write(arrimage) ms.flush() mysw.flush() myns.flush() ms.close() mysw.close() myns.close() myclient.close() End Try في الطرف األخر فإن االخ تالف يج ب أن يك ون ف ي ال Port وكمث ال إذا أرس ل الموظ ف م ن قس م المبيع ات إل ى الموظ ف ف ي قس م الحاس وب عل ى ال Port 5000 فيج ب ف ي ھ ذه الحال ة استقبال الص وت ف ي الط رف اآلخ ر عل ى نف س ال Port الت ي ت م اإلرس ال عليھ ا أم ا ف ي حال ة اس تخدام Server عن دھا يمك ن لك ل ال Clients اإلرس ال عل ى Port مع ين إل ى ال Server وكذلك قيام الServer بإرسال الMessages إلى كل الClients على Port محدد. ~171~
172 Chapter 11 Raw Socket Programming - Introduction to Raw Socket & Raw Protocols - Raw Socket Programming o ICMP Internet Control Message Protocol Programming (Ping & Tracing) o Using ARP Protocol to Get The MAC of a Remote Machine in Dot Net - Introduction to Packet Sniffing Applications ~172~
173 أوال Introduction to Raw Socket & Raw Protocols يعتبر موضوع ال Raw Socket من المواض يع الھام ة وخاص ة للبرمجي ات الت ي تعتم د عل ى التعامل مع البروتوكوالت في المس توى األدن ى م ن ال Transport Layer ومنھ ا بروتوك ول الARP وال RARP والمستخدم بشكل أساسي لجلب ال MAC أو ال Physical Address لل Ethernet Card (لمزي د م ن المعلوم ات انظ ر الفص ل األول) وال IGMP المخص ص إلدارة المجموعات في ال Multicasting باإلضافة إلى بروتوكول ال ICMP والذي يس تخدم بش كل أساس ي ف ي عملي ة ال Ping باإلض افة إل ى الكثي ر م ن العملي ات األخ رى إلرس ال حال ة ال Message بع د إرس الھا إل ى ال Destination ويأخ ذ ال Header الخ اص بھ ذا البروتوكول 64 Byte مقسمة كما ھو واضح في الشكل التالي: ICMP Header 16 Bytes ويح دد فيھ ا ن وع الرس الة المرس لة وال Code الخ اص بھ ذه الرس الة وتقس م إل ى ن وعين Query اس تعالم أو Error Message تقري ر لخط أ م ا ويوض ح الج دول 11-1 ھ ذه األنواع: TYPE CODE Description 0 0 Echo Reply x ~173~ Query Error 3 0 Network Unreachable X 3 1 Host Unreachable X 3 2 Protocol Unreachable X 3 3 Port Unreachable X 3 4 Fragmentation needed but no frag. bit set 3 5 Source routing failed X 3 6 Destination network unknown X 3 7 Destination host unknown X 3 8 Source host isolated (obsolete) X 3 9 Destination network administratively prohibited 3 10 Destination host administratively prohibited 3 11 Network unreachable for TOS X 3 12 Host unreachable for TOS X X X X
174 TYPE CODE Description 3 13 Communication administratively prohibited by filtering Query Error 3 14 Host precedence violation X 3 15 Precedence cutoff in effect X 4 0 Source quench 5 0 Redirect for network 5 1 Redirect for host 5 2 Redirect for TOS and network 5 3 Redirect for TOS and host 8 0 Echo request x 9 0 Router advertisement 10 0 Route solicitation 11 0 TTL equals 0 during transit X 11 1 TTL equals 0 during reassembly X 12 0 IP header bad (catchall error) X 12 1 Required options missing X 13 0 Timestamp request (obsolete) x 14 Timestamp reply (obsolete) x 15 0 Information request (obsolete) x 16 0 Information reply (obsolete) x 17 0 Address mask request x 18 0 Address mask reply x جدول 11-1 أنواع ال ICMP Messages 16 Bytes أخ رى ويوض ع فيھ ا الك ود الخ اص بال Checksum لتحق ق م ن وص ول ال Header الخاص بال Message ICMP بش كل الص حيح (ارج ع إل ى الفص ل األول لمزي د من المعلومات حول ال Checksum وطريقة حسابه) وھو اختياري. ICMP Packet لل التسلس لي و 16 ل رقم Packet ID 16 لل إل ى مقس مة 32 Bytes المرسل. ومن البروتوكوالت الھامة أيضا في ال Network Layer بروتوكول ال ARP Address Resolution Protocol إذ يس تخدم لجل ب ال MAC Address للجھ ة الت ي تري د اإلرس ال إليھ ا وم ن االس تخدامات األخ رى لھ ذا البروتوك ول إج راء عملي ة ال Filtering لل MAC Address وتستخدم ھذه العملية بشكل كبير لحماية الشبكات الالسلكية من عملي ة ال دخول غي ر المخول حيث تضاف ال MAC Addresses المسموح لھا باستخدام الشبكة ضمن ال MAC List في ال Router لمنع الدخول لغير األجھزة التي تملك MAC Address مشابه للموجود ض من ال List... MAC ويحت وي ال Header الخ اص ب ه عل ى ك ل م ن ال Hardware X ~174~
175 Hardware & Protocol Type إل ى باإلض افة Protocol Address وال Address المستخدم لھذا البروتوكول ويوضح الشكل التالي التركيب العام له: ومن المعروف أن ال ICMP و ال ARP تصنف من البروتوكوالت الت ي تعم ل عل ى مس توى ال Layer Network ض من ال TCP/IP Model وھ ذا يعن ي أنھ ا Connectionless Protocols و ال تعتم د ھ ذه البروتوك والت عل ى اس تخدام أي م ن البروتوك والت ف ي الLayer Transport إذ ال حاجة الستخدام ال Ports عند التعامل معھا... سنبين في الجزء الت الي م ن ھ ذا الفص ل كيفي ة برمج ة ال Raw Socket وبروتوكوالتھ ا مث ل الICMP باإلضافة إلى طرق التعامل مع ال ARP Protocol في الدوت نيت. ثانيا : Programming : Raw Socket لتعامل مع ال Raw Socket في الدوت نيت يجب أوال تعريف ال Raw Socket Type بع د ذل ك يمكنن ا اختي ار أي م ن البروتوك والت الت ي تعم ل عل ى ال Network Layer وت دعم الSocket Raw التعامل مع البروتوكوالت التالية وكما ھو واضح في الجدول 15-2 التالي: Protocol ame 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 Raw Socket و يبين البروتوكوالت التي تدعمھا ال 15-2 Table ~175~
176 وكمثال لبرمجة بروتوكول ال ICMP يجب أوال تعريف ال Raw Socket كما يلي: Socket row_socket = new Socket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Ic mp); Dim row_socket As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp) ويعتب ر بروتوك ول ال ICMP بروتوك ول Connectionless وھ ذا يعن ي ع دم حاجت ه أيض ا إلج راء عملي ة ال Connect أو ال Binding م ع ال Socket ل ذلك نح دد ل ه فق ط ف ي ال Object IPEndPoint ال IP Address لل Destination ودون تحدي د رق م ال Port حيث تأخذ القيمة صفر وكما يلي: IPEndPoint iep = new IPEndPoint(IPAddress.Parse(" "), 0); Dim iep As IPEndPoint = New IPEndPoint(IPAddress.Parse(" "), 0) وتتم عملية اإلرسال مباشرة باستخدام ال Sendto Method بعد تحديد الشكل العام لل ICMP Header Format حيث ترسل محتوياته ك Byte Array وتتم عملية االس تقبال باس تخدام ال ICMP Header وإلنش اء بھ ا أرس ل الت ي الطريق ة وب نفس ReceiveFrom Method Class يج ب التقي د بالش كل الع ام لھ ذا البروتوك ول وال Type Data لك ل Field وكم ا ھ و واضح في الجدول 15-3 التالي: Data Variable Size Type Type 1 byte Byte Code 1 byte Byte Checksum 2 bytes Unsigned 16-bit integer Message multibyte Byte array Table 15-3, ICMP Message Format وإلنشاء ال ICMP Class يجب التقيد بالتركيب السابق لل ICMP Header ويتم ذلك كما يلي: class ICMP public byte Type; public byte Code; ~176~
177 public UInt16 Checksum; public int MessageSize; public byte[] Message = new byte[1024]; 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 سنقوم اآلن بتنفيذ برنامج بسيط إلج راء عملي ة ال Ping وم ن المع روف أن ال Ping يس تخدم ال 8 Type إلرسال وال Type 0 عند االس تقبال حي ث يق وم الط رف المقاب ل باس تقبال الرس الة وإعادة إرس الھا كم ا ھ ي إل ى ال SourceAddress وإذا ت م اس تقبال ال ICMP Message بال 0 Type ھ ذا يعن ي ان ه ت م الوص ول إل ى ال Destination ويمك ن التحق ق م ن وص ول الHeader ICMP بالشكل الصحيح بعد حساب ناتج ال Checksum ف إذا تط ابق م ع مقل وب مجموع الData Header عندھا نستطيع معرفة أنه تم تس ليم ال Message ل Destination بشكل الصحيح وكما ھو واضح في الشكل التالي: وللبدء بالتطبيق سيكون الشكل العام للبرنامج كما في الشكل التالي : ~177~
178 وإلنش اء ال ICMP Class يج ب أوال تعري ف ال ICMP Header وتحويل ه إل ى Byte Array بعد إسناد الData Ping التي نريدھا إليه وكما يلي: 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]; ~178~
179 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); 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 ~179~
180 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 حي ث قمن ا بإنش اء ال getbytes Method لتحوي ل ال ICMP Packet إل ى Byte Array باس تخدام ال Method BitConverter.GetBytes وأنش ئنا ال getchecksum Method لحساب ال Checksum لل Packet ICMP حي ث سيس ند إلي ه وسيس تخدم لعملي ة التحق ق م ن وصول ال Packet Header لل Destination بالشكل الصحيح. ويمك ن اس تخدام ال Class الس ابق مباش رة بع د تعري ف Raw Socket ث م تعري ف IPEndpoint Object إلس ناده إل ى sendto Method ث م اش تقاق instance Object م ن ال Class ICMP الس ابق و إس ناد ق يم ابتدائي ة لل ICMP Header وإنش اء ICMP Destination ال إل ى إرس الھا يمكنن ا النھاي ة وف ي Byte Array إل ى وتحويلھ ا Message باستخدام ال sendto method وبتأكيد يمكننا تغير مدة ال Time Out للم دة الت ي س ينتظرھا الSource إلى حين الدخول على ال SocketException ف ي حال ة ع دم االس تجابة وي تم ك ل ذلك كما يلي: 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); ~180~
181 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.r eceivetimeout, 1000); host.sendto(packet.getbytes(), packetsize, SocketFlags.None, iep); 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 ~181~
182 host.setsocketoption(socketoptionlevel.socket,socketoptionname.r eceivetimeout, 1000) host.sendto(packet.getbytes(), packetsize, SocketFlags.None, iep) والستقبال الرد على الرسالة من ال Destination سنستخدم نفس التعريف السابق لل Socket حي ث سنس تخدم ال Method ReceiveFrom ونس ند إليھ ا ال Reference Value للIPEndpoint الذي أرسلنا من خالله الرسالة ونسند الرد الذي تم استقباله إلى ال ICMP Instance Object الذي أنشئ من ال ICMP Class ويتم كل ذلك كما يلي: 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(); ~182~
183 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() ويمكنن ا أيض ا اس تخدام ال Class الس ابق إلنش اء برن امج لعم ل ال Tracing وم ن المع روف بال Tracing Routing ان ه يق وم بتعق ب ال Hops أو ال Routers الت ي يم ر عبرھ ا الPacket حيث يرجع كل Router يمر ال Packet من خالله ICMP Replay Message تحت وي عل ى ال Message الت ي أرس لت باإلض افة إل ى ال IP لل Router ال ذي ت م تمري ر ال Message م ن خالل ه والوق ت ال ذي اس تغرق للوص ول إل ى ك ل Router حت ى وص ول الPacket إلى ال Destination وسيكون الشكل العام للبرنامج كما يلي: ~183~
184 وكما ھو واضح من تعريف ال Tracing فإن البرنامج سيعتمد على جلب ال IP لك ل Router يم ر م ن خالل ه إل ى ح ين الوص ول إل ى الط رف المعن ي ويمك ن إج راء ھ ذه العملي ة باس تخدام ال IpTimeToLive ض من ال Method SetSocketOption حي ث نض عھا داخ ل Loop وفي كل مرة نزيد ال Loop بمقدار واحد ونسند قيمته إلى ال TTL حيث يعب ر ك ل TTL ع ن Hop ال ذل ك إل ى Ping Message إرس ال وي تم خالل ه م ن الم رور ت م Router أو Hop وخالل ذلك نقيس الفترة الزمنية المستغرقة بين عملية إرس ال ال Ping واس تقبال ال رد م ن ك ل Hop إلى حين الوصول إلى آخر Hop مر ال Packet من خالله ويمكننا قياس ذل ك باس تخدام ال TickCount ضمن الClass Environment وترجع ھ ذه ال Property قيم ة Integer بال Millisecond من بدأ نظام التشغيل بالعمل إلى الوقت الحالي حيث يمكنن ا اخ ذ ھ ذه القيم ة عند بداية عمل ال Ping وأخذھا مرة أخرى عند استقبال الرد ومن ثم ط رح القيم ة األول ى م ن الثانية... ويتم كل ذلك كما يلي: 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); ~184~
185 packet.messagesize = data.length + 4; int packetsize = packet.messagesize + 4; UInt16 chcksum = packet.getchecksum(); packet.checksum = chcksum; trace_socket.setsocketoption(socketoptionlevel.socket,socketoption Name.ReceiveTimeout, 1000); int badcount = 0; for (int i = 1; i < 50; i++) trace_socket.setsocketoption(socketoptionlevel.ip,socketoptionnam e.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; ~185~
186 trace_socket.close(); 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,socketoption Name.ReceiveTimeout, 1000) Dim badcount As Integer = 0 For i As Integer = 1 To 49 trace_socket.setsocketoption(socketoptionlevel.ip,socketoptionnam e.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 ~186~
187 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() وھكذا بين ا كيفي ة اس تخدام ال ICMP ف ي ال دوت ني ت وكيفي ة اس تخدامه إلنش اء برن امج لعم ل ال Ping وآخ ر لعم ل ال Tracing Routing س وف نب ين ف ي الج زء الت الي م ن ھ ذا الفص ل كيفي ة التعام ل م ع ال ARP Protocol ف ي ال دوت ني ت لجل ب ال MAC Address ألي Destination على الشبكة. استخدام ال ARP Protocol لجلب ال MAC Address في برمجيات الشبكات : يمكنن ا جل ب ال MAC Address ألي IP Host م ن خ الل األم ر nbtstat م ن خ الل الPrompt Command الحظ الشكل التالي: ويمكنن ا االس تفادة م ن ھ ذا ال Command م ن داخ ل ال دوت ني ت باس تخدام ال Class ProcessStartInfo وال Class Process الموج ود ض من الNamespace System.Diagnostics حيث نمرر ال Command وال Arguments ال ذي نري د تنفي ذه إل ى ال Object ProcessStartInfo Instance ث م ننف ذ األم ر بتمري ر الobject instance السابق إلى ال Process.Start Method ويتم ذلك كما يلي: public string GetMac(string IP) string str1=string.empty; try ~187~
188 string str2=string.empty; ProcessStartInfo info1 = new ProcessStartInfo(); Process process1 = new Process(); info1.filename = "nbtstat"; info1.redirectstandardinput = false; info1.redirectstandardoutput = true; info1.arguments = "-A " + IP; info1.useshellexecute = false; process1 = Process.Start(info1); int num1 = -1; while (num1 <= -1) num1 = str2.trim().tolower().indexof("mac address", 0); if (num1 > -1) break; str2 = process1.standardoutput.readline(); process1.waitforexit(); str1 = str2.trim(); catch (Exception exception2) throw exception2; return str1; Public Function GetMac(ByVal IP As String) As String Dim str1 As String = String.Empty Try Dim str2 As String = String.Empty Dim info1 As ProcessStartInfo = New ProcessStartInfo Dim process1 As Process = New Process info1.filename = "nbtstat" info1.redirectstandardinput = False info1.redirectstandardoutput = True info1.arguments = "-A " & IP info1.useshellexecute = False process1 = Process.Start(info1) Dim num1 As Integer = -1 Do While num1 <= -1 num1 = str2.trim().tolower().indexof("mac address", 0) If num1 > -1 Then Exit Do End If str2 = process1.standardoutput.readline() Loop ~188~
189 process1.waitforexit() str1 = str2.trim() Catch exception2 As Exception Throw exception2 End Try Return str1 End Function ولتنفي ذ ال Method الس ابقة نم رر ال IP Address (الخ اص بالجھ از ال ذي نري د أن نجل ب الAddress MAC له) إلى ال Method السابقة حيث قمنا بفصل ال MAC Address ع ن بقية المعلومات التي يخرجھا لنا باستخدام ال... Trim Method وھكذا بينا كيفية استخدام كل من البروتوكولين ال ICMP وال ARP في ال دوت ني ت س وف نبين في الجزء التالي من ھذا الفصل مبدأ عم ل برمجي ات ال Packet Sniffing وس نقوم م ن خالله ببناء برنامج Sniffing بسيط. ثالثا : Applications Introduction to Packet Sniffing تكم ن الفك رة األساس ية م ن ال Packet Sniffing Applications بالتص نت عل ى ال Layer Network أو ال RawSocket بع د اختي ار ال Interface Network إذ أنھ ا ال تعمل ضمن نطاق Port محدد ونستطيع من خالل ال Raw Socket التق اط أي Packet يم ر من خالل ال Network Interface Card ولتحليل ال Packet الب د م ن معرف ة الحج م الكل ي لك ل Header ث م إض افته وبش كل دائ م ي تم إض افة ال Header Length إل ى ك ل Header ضمن كل طبقة من طبقات ال TCP/IP الحظ موقع ال Header Length في كل Header من بروتوكوالت الTCP/IP : ويمكننا فصل كل Layer عن األخرى بعد معرفة ال Header Length لك ل Layer الح ظ م ن الش كل الس ابق ان ه يمكنن ا معرف ة الحج م الكل ي لل Packet م ن خ الل الج زء األول من ه والمس مى بال Frame ويمكنن ا معرف ة موق ع ال Data ف ي ال Packet م ن خ الل المعادل ة التالية: ~189~
190 Data in Application Layer = (IP Header Length + Options) and Total Length - (Transport Protocol Header Length + Options) ويمكنن ا م ثال معرف ة ال IP Address لط رف المرس ل م ثال م ن خ الل تخ زين ال Packet الملتقط في Byte Array ثم تغيير ال offset لل مكان ال ذي نري د الق راءة من ه إذ ي أتي موق ع الAddress IP Source في ال IP Packet دائما بعد 12 Bytes الحظ الشكل التالي: ويجب دائما إنش اء Class أو Struct يحت وي عل ى ال Header Elements لك ل Protocol يتم التعامل معه وحتى نستطيع تحليله الحقا وتحديد سعة كل منھا بناء على السعة الحقيقية لھا وكمثال إلنشاء Struct خاص بالIPHeader : 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 ~190~
191 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 ولتفعيل عملية التص نت عل ى ال IP Layer يج ب تعري ف Raw Socket ونح دد فيھ ا ال IP كType Protocol ثم نقوم بعم ل ال Binding م ع ال IP Address لل Interface Card ال ذي نري د التص نت علي ه وبتأكي د ال تحت اج ال Raw Socket تحدي د Port مع ين إذ أنھ ا ال تتعامل مع أي من ال Transport Layer Protocols ويتم ذلك كما يلي: socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); socket.bind(new IPEndPoint(IPAddress.Parse( ), 0)); socket.beginreceive(m_buffer, 0, m_buffer.length, SocketFlags.None, new AsyncCallback(this.OnReceive), null); socket = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP) socket.bind(new IPEndPoint(IPAddress.Parse( ), 0)) socket.beginreceive(m_buffer, 0, m_buffer.length, SocketFlags.None, New AsyncCallback(AddressOf Me.OnReceive), Nothing) ثم إضافة ال AsyncCallback Method لل BeginReceive Method السابقة ويتم ذلك كما يلي: private void OnReceive(IAsyncResult ar) ~191~
192 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); 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 وفي ھذه المرحلة فإن أي Packet يمر من خالل ال Network Layer ي تم التقاط ه وتخزين ه في ال Buffer السابق حيث يمكن تحليله الحقا بحسب حج م ال Header لل Packet المل تقط باإلضافة إلى معرفة الحجم لكل Element في ال... Header وھكذا بينا كيفية التعامل مع ال Raw Socket في الدوت نيت وكيفية استخدامھا لبرمجة بروتوكوالت الICMP وال... Raw IP سيتم الحديث في الجزء التالي عن برمجة بروتوكوالت ال Application Layer والRemoting في بيئة الدوت نيت. ~192~
193 Part 4 Application Layer Programming Chapter12 DNS Programming Chapter13 HTTP Programming Chapter14 Web Services & XML Programming Chapter15 Remoting & Distributed Systems Programming & Design Chapter16 SMTP & POP3 Programming Chapter17 FTP Programming ~193~
194 Chapter 12 D S Programming - Synchronous DNS Members - Asynchronous DNS Members ~194~
195 :D S Programming :12 تعتبر خدمة DNS واحدة من أھم الخ دمات الت ي تس تخدم ف ي اإلنترن ت والش بكات بش كل ع ام وتختصر وظيفة DNS بالقيام بعملية ترجمة الName Domain إلى Domain IP والعكس وي تم ذل ك م ن خ الل مجموع ة كبي رة ج دا م ن م زودات ) DNS والت ي تق وم بتح ديث قاع دة البيانات الخاصة بھا كل فترة معينة) تبدأ ھذه العملية في الشبكات المحلية بقي ام ال A Client بطلب الDomain الخاص بالB Client وذلك بإدخال Domain Name الخاص به -حي ث تم مسبقا قيام الB Client بتعريف نفسه في قاعدة البيانات الخاص ة ب - DNS Server كم ا يحتوي كل Client على قاعدة بيانات تحتوي على عن اوين ال Domains وتس مى بال local DNS حيث يقوم بالبحث بداخلھا على عنوان Domain من خالل Domain Name فإذا لم يجده يق وم بطل ب عن وان ال دومين م ن ال Server DNS وبع د إيج اده يق وم ال Server DNS بإرسال العنوان إلى الClient ويقوم ب دوره بتخ زين العن وان ف ي Local DNS الخ اص ب ه انظر إلى الشكل التالي: ف ي ال دوت ني ت يمكنن ا التعام ل م ع DNS باس تخدام System.Net Namespace والت ي تحتوي عل ى جمي ع ال Classes و ال Methods الخاص ة ب DNS وتقس م دوال ال DNS Asynchronous مت زامن و غي ر Synchronous Methods مت زامن إلى قس مين Class Methods وھي كما يلي: أوال الدوال المتزامنة Synchronous Methods وھي : GetHostName والتي تستخدم لجلب اسم ال Host وترجع ھذه الدالة قيمة String تحتوي على الName Computer وال تأخذ ھذه الدالة أي باروميترات ويمكن استخدامھا كما يلي : string hostname = Dns.GetHostName(); Private hostname As String = Dns.GetHostName الدالة GetHostByName و الدالة GetHostByAddress وتستخدم كل منھا كما يلي: لجلب // Dns.GetHostByName(Computer_Name); IPHostEntry host_ip = العنوان باستخدام االسم ~195~
196 لجلب // Dns.GetHostByAddress(IP_Address); IPHostEntry host_name = االسم باستخدام العنوان Private host_ip As IPHostEntry = Dns.GetHostByName(Computer_Name) Private host_name As IPHostEntry = Dns.GetHostByAddress(IP_Address) الدالة Resolve وھي Overloaded Method حي ث ترج ع Host Name إذا أرس لت لھ ا في الIPHostEntry Host Name إذا أرسلت لھا Host Address وترجع IP Address وال يختلف استخدامھا عن استخدام الدوال السابقة وھذا المثال يبين طريقة استخدامھا : using System; using System.Net; class FMO_DNS public static void Main() IPHostEntry IPHost = Dns.Resolve(" Console.WriteLine(IPHost.HostName); IPAddress[] addr = IPHost.AddressList; for(int i= 0; i < addr.length ; i++) Console.WriteLine(addr[i]); Imports System Imports System.Net Class FMO_DNS Public Shared Sub Main() Dim IPHost As IPHostEntry = Dns.Resolve(" Console.WriteLine(IPHost.HostName) Dim addr As IPAddress() = IPHost.AddressList Dim i As Integer = 0 While i < addr.length Console.WriteLine(addr(i)) System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1) End While End Sub End Class ~196~
197 ثانيا الدوال الغير المتزامنة : Asynchronous Methods وتبدأ عادة بكلمة Begin أو End ومن األمثلة عليھا : و EndGetHostByName و BeginResolve و BeginGetHostByName EndResolve طبيعة عملھا كما ھو الحال في الدوال المتزامنة لكنھا تختلف بكون انه ال يشترط تنفيذھا إلكمال عمل البرنامج في حين المتزامن ال تسمح االنتقال إلى الخطوة الثانية في البرنامج إال في حالة انتھاء عملھا وقد تسبب ھذه السيئة بخفض األدائية بشكل عام في البرنامج لذلك ينصح باستخدام الطريقة الغير متزامنة وتستخدم كما يلي : Begin public static IAsyncResult BeginResolve(string hostname, AsyncCallback requestcallback, object stateobject) حي ث ي تم وض ع ال Host Name ف ي الب اروميتر األول و الب اروميتر الث اني يع رف في ه ال delegate وتس مح ل ك بتمري ر م دخالت إل ى delegate Method ويس تخدم End إلنھاء العملية في ال Back Result كما يلي : public static IPHostEntry EndResolve(IasyncResult ar) وھنا مثال شامل و بسيط يقوم بجلب جميع الIP s الموجودة على الشبكة حيث يعمل على جلب ال names host م ن ProcessStartInfo م ن خ الل الخاص ية StandardOutput بتنفي ذ األم ر Net View حي ث ي تم تحويل ه إل ى host name م ن خ الل الدال ة GetMachineNamesFromProcessOutput ثم تخزينھا في Collicaion ثم يتم تحوي ل األسماء إلى عناوين من خالل الدالة.. Dns.Resolve طبعا يتم استخدام الStreamReader لقراءة الcollection الخاص بالProcessStartInfo وھذا ھو المثال : 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()); ~197~
198 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(); ~198~
199 StringCollection names = _names.getnames(); foreach(string name in names) Console.WriteLine(name); Console.ReadLine(); Imports System Imports System.IO Imports System.Diagnostics Imports System.Net Imports System.Collections.Specialized Public Class Names Public Function GetNames() As StringCollection Dim _startinfo As ProcessStartInfo = New ProcessStartInfo("net", "view") _startinfo.createnowindow = True _startinfo.useshellexecute = False _startinfo.redirectstandardoutput = True Dim _process As Process = Process.Start(_startInfo) Dim _reader As StreamReader = _process.standardoutput Dim _machinenames As StringCollection = GetMachineNamesFromProcessOutput(_reader.ReadToEnd()) Dim _machineips As StringCollection = New StringCollection For Each machine As String In _machinenames _machineips.add(ipaddresses(machine)) Next machine Return _machineips End Function Private Shared Function IPAddresses(ByVal server As String) As String Try Dim ASCII As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding ' Get server related information. Dim heserver As IPHostEntry = Dns.Resolve(server) 'assumin the machine has only one IP address Return heserver.addresslist(0).tostring() Catch Return "Address Retrieval error for " & server End Try End Function 'string manipulations ~199~
200 Private Function GetMachineNamesFromProcessOutput(ByVal processoutput As String) As StringCollection Dim _allmachines As String = processoutput.substring(processoutput.indexof("\")) Dim _machines As StringCollection = New StringCollection Do 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)) Loop Return _machines End Function End Class Public Class Runner Shared Sub Main() Dim _names As Names = New Names Dim names As StringCollection = _names.getnames() For Each name As String In names Console.WriteLine(name) Next name Console.ReadLine() End Sub End Class وھكذا بينا في ھذه الفصل أھمي ة ال D S وط رق التعام ل مع ه ف ي بيئ ة ال دوت ني ت س يتم الحديث في الفصل التالي عن HTTP وطرق برمجته في بيئة الدوت نيت. ~200~
201 Chapter 13 HTTP Programming - The Concept of HTTP Protocol - Using HTTP in Dot Net - Advanced HTTP Programming - Using HttpWebRequest - Using HttpWebResponse ~201~
202 HTTP Hyper Text Transfer Protocol Programming :13 تتلخص وظيفة الHTTP بش كل ع ام عل ى ان ه البرتوك ول المس تخدم لتوص يل طل ب المس تخدم User Request إلى الويب Server ثم قيام الserver web ب الرد عل ى ال Request وال ذي يسمى ب Server Response وبتأكيد تستطيع نقل جميع أشكال (Multimedia) م ن ال نص وص ورة و ص وت و في ديو وغي ره.. م ن ال Server Web إل ى ال Application Client كobject.Byte يعمل برتوكول الHTTP على الLayer Application وھذا يعن ي اس تخدامه بش كل مباش ر من واجھة المستخدم كما ھو الحال في DNS,SMTP,POP3,FTP انظر إلى الشكل التالي: أوال : Server Downloading From Web نس تطيع التعام ل م ع ال Server Web ف ي ال دوت ني ت باس تخدام ال Class WebClient الموج ود ف ي System.Net Namespace إذ تق دم لن ا جمي ع اإلمكاني ات لتوص يل طل ب الزبون و الرد عليهResponse User Request & Server وتدعم الClass WebClient ثالثة Methods لتحميل البيانات من الServer Web وھي: Byte ف ي وتخزينھ ا Web ال Server م ن البيان ات ووظيفتھا جل ب DownloadData 1- Array وتعرض على شكل HTML Code وتستخدم كما يلي كمثال: using System; using System.Net; using System.Text; class DownloadData_Method public static void Main () WebClient wc = new WebClient(); byte[] response = wc.downloaddata(" ~202~
203 Console.WriteLine(Encoding.ASCII.GetString(response)); Imports System Imports System.Net Imports System.Text Class DownloadData_Method Public Shared Sub Main() Dim wc As WebClient = New WebClient Dim response As Byte() = wc.downloaddata(" Console.WriteLine(Encoding.ASCII.GetString(response)) End Sub End Class DownloadFile-2 ووظيفتھ ا نق ل مل ف م ا م ن ال Server Web وتخزينھ ا مباش رة ف ي Local Computer وھو سھل االس تخدام ج دا إذ م ا علي ك س وا تمري ر موق ع المل ف والمك ان الذي تريد تخزين الملف فيه ويستخدم كما يلي كمثال: 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(" filename); Console.WriteLine("file downloaded"); Imports System Imports System.Net ~203~
204 Imports System.Text Class DownloadData_Method Public Shared Sub Main() Dim wc As WebClient = New WebClient Dim response As Byte() = wc.downloaddata(" Console.WriteLine(Encoding.ASCII.GetString(response)) End Sub End Class 3- OpenRead ووظيفتھ ا إنش اء Read Only Stream ب ين الزب ون وال Server لجل ب بيانات من URL محدد وتخزينه في Stream Object بعد تمرير الURL للموقع الذي تري د عرض ه وباس تخدام الدال ة ReadLine نس تطيع ع رض البيان ات المخزن ة ف ي ال Stream. HTML Code على شكل Object using System; using System.IO; using System.Net; class OpenRead_Method public static void Main () WebClient wc = new WebClient(); string response; مالحظة : تستخدم الدالة Peek لمعرفة نھاية الObject. Stream Stream strm = wc.openread(" StreamReader sr = new StreamReader(strm); while(sr.peek() > -1) response = sr.readline(); Console.WriteLine(response); sr.close(); Imports System Imports System.IO Imports System.Net ~204~
205 Class OpenRead_Method Public Shared Sub Main() Dim wc As WebClient = New WebClient Dim response As String Dim strm As Stream = wc.openread(" Dim sr As StreamReader = New StreamReader(strm) While sr.peek > -1 response = sr.readline Console.WriteLine(response) End While sr.close() End Sub End Class ويحت وي ال Class WebClient عل ى مجموع ة م ن ال Properties والت ي تس تخدم لجل ب معلوم ات ع ن ال Host Web مث ل ResponseHeaders property وال ذي يس تخدم لجل ب معلوم ات ھام ة ع ن ال host web مث ل ع دد ال Headers ون وع ال control cash واس م الServer و نوع الEncoding المستخدم وغيرھا من المعلومات الھام ة ويس تخدم كم ا يل ي كمثال: using System; using System.Net; class ResponseHeaders_property public static void Main () WebClient wc = new WebClient(); byte[] response = wc.downloaddata(" 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)); Imports System Imports System.Net Class ResponseHeaders_property ~205~
206 Public Shared Sub Main() Dim wc As WebClient = New WebClient Dim response As Byte() = wc.downloaddata(" Dim whc As WebHeaderCollection = wc.responseheaders Console.WriteLine("header count = 0", whc.count) Dim i As Integer = 0 While i < whc.count Console.WriteLine(whc.GetKey(i) + " = " + whc.get(i)) System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1) End While End Sub End Class //Output: //header count = 6 //Cache-Control = private //Content-Type = text/html //Set-Cookie = PREF=ID=6ae22f44980c5d78 //7JRA; expires=sun, 17-Jan :14: //Server = GWS/2.1 //Transfer-Encoding = chunked //Date = Wed, 23 Nov :10:58 GMT ثانيا : Server Uploading to Web يدعم الWebClient أربعة Methods لتحميل البيانات إلى الServer Web وھي : 1- OpenWrite ويستخدم إلرسالData Stream إل ى ال Server Web وذل ك بع د تمري ر عن وان ال URL للمل ف وال نص ال ذي نري د كتابت ه عل ى ال Page Web طبع ا يج ب أن تمل ك الصالحيات لذلك ويستخدم كما يلي كمثال: using System; using System.IO; using System.Net; method_class OpenWrite 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(); ~206~
207 Imports System Imports System.IO Imports System.Net Class OpenWrite_method Public Shared Sub Main() Dim wc As WebClient = New WebClient Dim data As String = "<h1>welcome to My Page</h1>" Dim strm As Stream = wc.openwrite("c:\mypage.html") Dim sw As StreamWriter = New StreamWriter(strm) sw.writeline(data) sw.close() strm.close() End Sub End Class Web إلى الServer Byte ويستخدم لنقل محتويات مصفوفة من النوع UploadData 2 وھذا يعني انك تستطيع من خاللھا رفع أي نوع من البيانات مثل ال نص الص ور الفي ديو وغي ره إلى الserver web بعد تحويلھا إلى Byte Array ويستخدم كما يلي كمثال : using System; using System.Net; using System.Text; Method_class UploadData 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); Imports System Imports System.Net Imports System.Text Class UploadData_Method ~207~
208 Public Shared Sub Main() Dim wc As WebClient = New WebClient Dim data As String = "This is The Text Before Converted it to Byte" Dim dataarray As Byte() = Encoding.ASCII.GetBytes(data) wc.uploaddata("c:\mydata.txt", dataarray) End Sub End Class Web ال إل ى Local ال Computer م ن مل ف لرف ع الدال ة وتستخدم ھ ذه UploadFile 3- Host وھي بسطة االستخدام جدا وتستخدم كما يلي كمثال: using System; using System.Net; class UploadFile_Method public static void Main () WebClient wc = new WebClient(); wc.uploadfile(" "C:\\myfile.html"); Imports System Imports System.Net Class UploadFile_Method Public Shared Sub Main() Dim wc As WebClient = New WebClient wc.uploadfile(" "C:\myfile.html") End Sub End Class 4- UploadValues وتس تخدم لرف ع Collection م ن البيان ات وال values الخاص ة بھ ا إل ى الوي ب Server وذل ك بع د تحوي ل ال Collection إل ى Byte Array ولتعري ف Namespace ف ي الموج ود NameValueCollection الك الس نس تخدم Collection System.Collections.Specialized وبع د تعريف ه نس تخدم الدال ة add إلض افة الCollection جديد.. وتستخدم كما يلي كمثال: using System; using System.Collections.Specialized; using System.Net; using System.Text; class UploadValues_Method ~208~
209 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(" nvc); Console.WriteLine(Encoding.ASCII.GetString(response)); Imports System Imports System.Collections.Specialized Imports System.Net Imports System.Text Class UploadValues_Method Public Shared Sub Main() Dim wc As WebClient = New WebClient Dim nvc As NameValueCollection = New NameValueCollection nvc.add("firstname", "Fadi") nvc.add("lastname", "Abdel-qader") Dim response As Byte() = wc.uploadvalues(" nvc) Console.WriteLine(Encoding.ASCII.GetString(response)) End Sub End Class ثالثا :المواضيع األكثر تقدما في الProgramming :HTTP يعتبر ھذا الجزء من أھم األجزاء ف ي برمج ة تطبيق ات Web Client Applications وال ذي س وف نتح دث في ه ع ن اس تخدام ك ل م ن ال Class HttpWebRequest و الClass :HttpWebResponse -1 استخدام : HttpWebRequest Class يحت وي ھ ذا ال Class عل ى مجموع ة م ن ال Properties والت ي تس تخدم بش كل أساس ي ف ي تطبيقات الApplications Web Client إلنشاء مثل : 1- استخدام خاصية الProxy : Web والتي نمرر فيھا عنوان الServer Proxy ورقم الPort حتى نستطيع التعامل مع الRequests HTTPمن Web خلف Proxy Server أو Firewall ويتم تعريف الProsperity Proxy Server كما يلي كمثال: using System; using System.Net; ~209~
210 class ProxyServer_Property public static void Main () HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create( " WebProxy proxysrv = new WebProxy(" hwr.proxy = proxysrv; Imports System Imports System.Net Class ProxyServer_Property Public Shared Sub Main() Dim hwr As HttpWebRequest = CType(WebRequest.Create(" HttpWebRequest) Dim proxysrv As WebProxy = New WebProxy(" hwr.proxy = proxysrv End Sub End Class نع رف ف ي البداي ة ال Object HttpWebRequest ث م نع رف WebProxy Object م ن الClass webproxy ونسند له عنوان الServer Proxy ورقم ال Port وبعد ذلك نستطيع إس ناده إل ى أي Object باس تخدام الخاص ية Proxy الت ي تك ون موج ودة ع ادة ف ي جمي ع. HttpWebRequest Objects ~210~
211 2- استخدام الHttpWebrequest إلرسال بيانات إلى الويب Server باستخدام الStreams وتستخدم كما يلي كمثال: HttpWebrequest hwr = (HttpWebRequest)WebRequest.Create(" Stream strm = hwr.getrequeststream(); StreamWriter sw = new StreamWriter(strm); sw.writeline(data); Dim hwr As HttpWebrequest = CType(WebRequest.Create(" HttpWebRequest) Dim strm As Stream = hwr.getrequeststream Dim sw As StreamWriter = New StreamWriter(strm) sw.writeline(data) بع د تعري ف ال Object HttpWebRequest نق وم بتعري ف Stream Object ونس ند ل ه الStream Request من خالل الدالة. GetRequestStream - 2 استخدام :HttpWebResponse Class تس تخدم ال Object HttpWebResponse إلرج اع بيان ات م ن الوي ب Server إل ى ال Client حي ث نس تخدم الدال ة GetResponse و الدال ة BeginGetResponse لھ ذه العملية وال يوجد فرق في وظيفة ھ ذه ال Method س وى أن BeginGetResponse تعتب ر. asynchronous Method يحتوي ال HttpWebResponse Object على عدد من الProperties وھي : Character وتستخدم لتحديد نوع الSet : CharacterSet 1- وتستخدم لعملية الencoding : ContentEncoding 2-3- ContentLength : وتستخدم لمعرفة حجم الرد لتحديد نوع الResponse : ContentType 4-5- Cookies : لتعام ل م ع ال Cookies واس تخدامھا يج ب أوال إنش اء مل ف Cookie ف ارغ وتعريفه كما يلي كمثال: ~211~
212 HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create( hwr.cookiecontainer = new CookieContainer(); وذلك قبل الRequest HTTP ثم نسنده إليه كما يلي : HttpWebResponse hwrsp = (HttpWebResponse)hwr.GetResponse(); hwrsp.cookies = hwr.cookiecontainer.getcookies(hwr.requesturi); Dim hwr As HttpWebRequest = CType(WebRequest.Create(" HttpWebRequest) hwr.cookiecontainer = New CookieContainer Dim hwrsp As HttpWebResponse = CType(hwr.GetResponse, HttpWebResponse) hwrsp.cookies = hwr.cookiecontainer.getcookies(hwr.requesturi) HTTP لمعرفة الHeaders : Headers LastModified : يرجع فيه وقت وتاريخ أخر تعديل HTTP لمعرفة الدالة والتي تستخدم في الResponse : Method 8- HTTP لمعرفة الVersion : ProtocolVersion 9 بServer الخاص الURL : ResponseUri 10 لمعرفة اسم الServer : Server StatusCode : لمعرفة نوع الCoding المستخدم يحتوي على حالة الHTTP Text إلرجاع : StatusDescription 13 بينا ف ي ھ ذا الفص ل كيفي ة برمج ة ال HTTP ف ي بيئ ة ال دوت ني ت وط رق التعام ل م ع ال HttpWebRequest والHttpWebResponse في بيئ ة ال دوت ني ت س وف نتح دث في الفصل التالي عن Web Services والXML وطرق التعامل معه في بيئة الدوت نيت. ~212~
213 Chapter 14 Web Services & XML Programming -Introduction to Web services & XML -Create A Simple Web Service Application -Using ADO.NET With Web Services Create a Simple GIS System to Send Information About Countries Via SOAP & XML to Clients. ~213~
214 Web Services Programming :14 تحدثنا في الفصل السابق عن برمج ة ال HTTP وبين ا في ه كيفي ة التفاع ل ب ين ال server web والclient ويعتبر ھذا الفصل مكمل لما تحدثنا عنه في الفصل السابق. تتلخص وظيفة الservices web بإمكاني ة االس تفادة م ن ال Methods الموج ودة بال web Simple ل اختص ار وھ و SOAP ال داخل برنامج الزبون وباستخدام برتوك ول server Object Access Protocol ي تم نق ل ال Result م ن ال server web Services إل ى الClient بعد تحويلھا إلى الLanguage XML - extensible Markup حيث تنق ل عب ر برتوكول الHTTP إلى جھاز الزبون والھدف من اس تخدامه ھ و تس ھيل وص ول ال Data م ن الserver web إلى الClient من خالل ال firewalls والبيئ ات المختلف ة إذ أن جمي ع بيئ ات الشبكات تدعم برتوكول الHTTP والذي يعم ل عل ى ال Port. 80 وال تختل ف لغ ة ال XML ع ن ال HTML إذ تس تخدم نف س القواع د ف ي ال HTML وھ ي مجموع ة م ن ال Elements والAttributes مثل ال</> <> لكن تتميز بمرونة اكبر وكمثال عليھا : <MyStuff> <myname>fadi Abdel-qader</myName> <mytelephone> </mytelephone> <my >fadi822000@yahoo.com</my > <myage>25</myage> <mygender>m</mygender> </mystuff> ويمكن نقل أي شيء نريده باستخدام الXML س واء Text,Binary Data, Serialization Object أو أي شيء اخر وما مي ز ال XML ع ن غيرھ ا ھ و ق درتھا العالي ة عل ى نق ل جمي ع انواع البيانات بجميع البيئات... ويمكنن ا التعام ل م ع ال XML ف ي ال دوت ني ت باس تخدام ال System.xml Namespaces وھذا مثال يوضح كيفية قراءة ملف ال XML السابق باستخدام الXmlDocument : using System.Xml; XmlDocument xdoc = new XmlDocument(); xdoc.load(@"c:\myinfo.xml"); XmlNodeList name = xdoc.getelementsbytagname("myname"); XmlNodeList telephone = xdoc.getelementsbytagname("mytelephone"); XmlNodeList = xdoc.getelementsbytagname("my "); XmlNodeList age = xdoc.getelementsbytagname("myage"); XmlNodeList Gender = xdoc.getelementsbytagname("mygender"); MessageBox.Show( "Name: " + name[0].innertext +"\n"+ "Telephone: " + telephone[0].innertext +"\n"+ " "+ [0].innertext +"\n"+ "Age: "+ age[0].innertext +"\n"+ "Gender: "+ Gender[0].InnerText +"\n" ~214~
215 Dim xdoc As XmlDocument = New XmlDocument xdoc.load("c:\myinfo.xml") Dim name As XmlNodeList = xdoc.getelementsbytagname("myname") Dim telephone As XmlNodeList = xdoc.getelementsbytagname("mytelephone") Dim As XmlNodeList = xdoc.getelementsbytagname("my ") Dim age As XmlNodeList = xdoc.getelementsbytagname("myage") Dim Gender As XmlNodeList = xdoc.getelementsbytagname("mygender") Msgbox("Name: " + name(0).innertext + "" & Microsoft.VisualBasic.Chr(10) & "" + "Telephone: " + telephone(0).innertext + "" & Microsoft.VisualBasic.Chr(10) & "" + " " + (0).innertext + "" & Microsoft.VisualBasic.Chr(10) & "" + "Age: " + age(0).innertext + "" & Microsoft.VisualBasic.Chr(10) & "" + "Gender: " + Gender(0).InnerText + "" & Microsoft.VisualBasic.Chr(10) & "") ويمكن استخدام ال XmlTextWriter Class في المثال التالي: لخزين بيانات عل ى ھيئ ة XML Data وكم ا private void btnsave_click(object sender, System.EventArgs e) try XmlTextWriter XMLWriter = new XmlTextWriter ("AddressBook.XML", null); XMLWriter.Formatting = Formatting.Indented; ~215~
216 ;("العناوين ملف") XMLWriter.WriteComment XMLWriter.WriteStartElement("AddressBook"); XMLWriter.WriteStartElement("Name"); XMLWriter.WriteString(tx_Name.Text); XMLWriter.WriteEndElement(); XMLWriter.WriteStartElement("Address"); XMLWriter.WriteString(tx_Address.Text); XMLWriter.WriteEndElement(); XMLWriter.WriteEndElement(); XMLWriter.Flush(); XMLWriter.Close(); ;("تم") MessageBox.Show catch(exception ex) MessageBox.Show(ex.Message); private void btnviewxml_click(object sender, System.EventArgs e) try XmlDocument doc = new XmlDocument(); doc.preservewhitespace = true; doc.load("addressbook.xml"); ;("محتويات الملف", MessageBox.Show(doc.InnerXml catch(exception ex) MessageBox.Show(ex.Message); Private Sub btnsave_click(byval sender As Object, ByVal e As System.EventArgs) Try Dim XMLWriter As XmlTextWriter = New XmlTextWriter("AddressBook.XML", Nothing) XMLWriter.Formatting = Formatting.Indented ~216~
217 ("العناوين ملف") XMLWriter.WriteComment XMLWriter.WriteStartElement("AddressBook") XMLWriter.WriteStartElement("Name") XMLWriter.WriteString(tx_Name.Text) XMLWriter.WriteEndElement() XMLWriter.WriteStartElement("Address") XMLWriter.WriteString(tx_Address.Text) XMLWriter.WriteEndElement() XMLWriter.WriteEndElement() XMLWriter.Flush() XMLWriter.Close() ("تم") MessageBox.Show Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Private Sub btnviewxml_click(byval sender As Object, ByVal e As System.EventArgs) Try Dim doc As XmlDocument = New XmlDocument doc.preservewhitespace = True doc.load("addressbook.xml") ("الملف محتويات" MessageBox.Show(doc.InnerXml, Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub ~217~
218 تمر عملية استخدام الservices web بثالثة مراحل وھي : 1- server : The web service وال ذي ي تم م ن خالل ه إرس ال واس تقبال البيان ات عب ر برتوكول الSOAP باستخدام الIIS والASP.NET. 2- object : The proxy وال ذي يس مح لل Client بإرس ال و اس تقبال البيان ات م ن وإل ى الServer web Services حيث يتم تعريفه ف ي ال HttpWebRequest م ن خ الل الك الس WebProxy وھو ما بينته في الجزء السابق. Web بال ربطھ ا ي تم والت ي بزب ون الخاص ة الواجھ ة وھ و : The client application 3- Services Server كما في الشكل التالي : : Create a Simple Web Services Application :13.2 وإلنشاء web services server نقوم بعم ل مش روع ASP.NET Web Services جدي د ونس تدعي System.Web.Services Namespaces ث م نق وم بتوري ث الك الس WebService للClass الرئيسي للمشروع وكما يلي كمثال: using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = " [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; ~218~
219 Imports System Imports System.Web Imports System.Web.Services Imports System.Web.Services.Protocols <WebService(Namespace=" _ <WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)> _ Public Class Service Inherits System.Web.Services.WebService Public Sub New() End Sub <WebMethod()> _ Public Function Add(ByVal a As Integer, ByVal b As Integer) As Integer Return a + b End Function End Class حيث يتم استقبال قيمت ين A و B وبع د ذل ك يق وم بإرج اع ن اتج جم ع القيم ة األول ى م ع القيم ة الثانية إلى الClient على شكل XML باستخدام برتوكول ال SOAP وكم ا يظھ ر ف ي الش كل التالي : وإلنش اء برن امج ال Client يج ب أوال تحوي ل الك الس الس ابق إل ى Dll File و إرفاق ه بالResources Client ويتم استخدامه كما يلي : ~219~
220 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);. Class Client_side Public Shared Sub Main(ByVal argv As String()) Dim mm As My_main_class = New My_main_class Dim x As Integer = Convert.ToInt16(argv(0)) Dim y As Integer = Convert.ToInt16(argv(1)) Dim sum As Integer = mm.add(x, y) Console.WriteLine(sum) End Sub End Class كم ا يمك ن إنش اء Connection Object ب ين ال Client وال Web Services Server بشكل مباشر ويتم ذلك بإضافة Web Services Reference إلى المش روع وكم ا ف ي الش كل التالي: حيث يتم االختيار سواء كانت ال Web Services على نفس الجھاز أو على جھاز بعيد وذل ك بوضع ال URL للموقع وكما في الشكل التالي: ~220~
221 عندھا نستطيع استدعاء ال Methods السابقة في البرنامج كما وإنھا على نفس الجھاز سنبين في الجزء التالي من ھذا الفصل كيفية ربط ال ADO.NET مع ال Web Services إلرسال ال Result ك XML إلى الClient. ~221~
222 Using ADO. ET With Web Services :13.3 اس تخدمنا ف ي المث ال الس ابق ال Web Services إلرس ال بيان ات إل ى ال Client مس تخدما بروتوكول ال SOAP وفي ھ ذا المث ال س نقوم بإنش اء Web Services لنق ل بيان ات م ن ال SQL Server Database إلى ال Client ويمكن أن تكون ھذه البيانات عبارة ع ن Text أو Image أو غيره... وللبدء سنقوم أوال بتأكد من إعدادات الAuthentication في ال IIS وال SQL Server ويجب أن تك ون إع دادات ال Authentication ف ي ال IIS كم ا ف ي الش كل التالي: حيث نحدد User مع ين ونعط ي ل ه ص الحيات معين ة ل دخول عل ى قاع دة البيان ات والموج ودة عل ى ال SQL Server ونعط ي ل ه ھ ذه الص الحيات م ن ال Security ض من الManager Enterprise الخاص بال Microsoft SQL Server وكما في الشكل التالي: ~222~
223 ثم ندخل اسم المستخدم الذي حددناه في ال IIS ض من ال Users المس موح لھ م بال دخول عل ى قاعدة البيانات وكما في الشكل التالي: ولتحدي د الص الحيات نخت ار قاع دة البيان ات الت ي نري د اس تخدامھا ونح دد ص الحيات ال Database Access والRoles Server من ال SQL Server Login Properties وكما في الشكل التالي: وبتأكيد يمكنك تحديد الصالحيات التي تريدھا والتي تتناسب مع البرنامج الذي تريد إنشائه. وللب دء س نقوم بعم ل فك رة بس يطة إلنش اء نظ ام GIS بس يط يرس ل ال Client اس م البل د ال ذي يختاره من الخارطة إلى الServer Web Services ويرج ع ال Web Services معلوم ات ~223~
224 عن ھذا البلد من قاعدة البيانات إلى ال Client وسوف نقوم في البداية بعمل Table ف ي قاع دة البيانات وتحتوي على أسم البلد و معلومات عن ھذا البلد وكما في الشكل التالي: ث م س نقوم ب ربط قاع دة البيان ات م ع ال Web Services بالس حب واإلف الت م ن ال Server Explorer وكما في الشكل التالي: سيرسل ال Client اس م البل د ال ذي يق وم بض غط علي ه م ن الخريط ة إل ى ال Web Services وف ي ھ ذه الحال ة نح ن بحاج ة إل ى إنش اء Method تأخ ذ ب اروميتر واح د وترج ع String Return Value تحتوي على معلومات عن ھذا البلد وكما يلي: [WebMethod] public string GIS_Country(string country) try sqldataadapter1.selectcommand.commandtext = "select * from GIS where Country='"+ country+"'"; DataSet ds = new DataSet (); sqldataadapter1.fill (ds); return ds.tables[0].rows[0][1].tostring (); catch (Exception)return "I Can not Find Your Country! Please Select Another One"; <WebMethod()> _ Public Function GIS_Country(ByVal country As String) As String Try sqldataadapter1.selectcommand.commandtext = "select * from GIS where Country='" & country & "'" ~224~
225 Dim ds As DataSet = New DataSet sqldataadapter1.fill(ds) Return ds.tables(0).rows(0)(1).tostring() Catch e1 As Exception Return "I Can not Find Your Country! Please Select Another One" End Try End Function في طرف ال Client س نقوم بربط ه م ع ال Web Service الت ي ت م إنش ائھا وكم ا ف ي المث ال الس ابق وس يمرر ال Client اس م الدول ة إل ى ال Web Services Method ويرج ع لن ا معلومات عن الدولة وسيكون الشكل العام للClient كما يلي: نستطيع تحديد حدود كل بلد بعمل Areas حيث عند الضغط عليھا يرسل اسم البلد إلى ال Web Services ولكي ال ندخل بتعقيدات ال GDI سنحل الموض وع ب إدراج Panel عل ى ك ل بل د ونجعل لون الخلفية له من النوع الشفاف الTransparency وسيكون الكود التالي عند ح دث ال Mouse Down على ال Panel الموضوعة على كل بلد وكما يلي: ~225~
226 private void panel1_mousedown(object sender, System.Windows.Forms.MouseEventArgs e) localhost.service1 sr = new GIS.localhost.Service1 (); this.text = sr.gis_country ("Jordan"); VB. ET Private Sub panel1_mousedown(byval sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Dim sr As localhost.service1 = New GIS.localhost.Service1 Me.Text = sr.gis_country("jordan") End Sub ويمكن استخدام ال Web Services إلرج اع Binary Data كص ورة م ثال بع د إحض ارھا من قاعدة البيانات وھو ما تم شرحه ف ي الفص ل الخ اص بال Streaming ويمك ن تطبي ق كل ھذه المفاھيم على ال ASP. ET وبنفس الطريقة سيتم الحديث في الفص ل الت الي ع ن ال Remoting وتطبيقاتھا في الدوت نيت. ~226~
227 Chapter 15 Remoting & Distributed Systems Programming & Design - The Distributed Systems Concept & Design Design a Distributed ecommerce System by Using ASP.NET and Web Services. - Serialization Programming The Serialization (Classes & Members) Using BinaryFormatter & SoapFormatter to Serialize Objects & Images Through Network - Remoting Programming Remoting (Classes & Members) Using Remoting Applications in Dot Net Create an Advanced Distributed elearning System (Remote Class Room) Create an Advanced Remote Desktop Application With Remote (Mouse/Keyboard) Control Features ~227~
228 : 15 أوال - Design The Distributed Systems Concept & يعرف النظام الموزع على انه مجموعة من األجھزة التي تعمل مع بعضھا كنظام واحد بمعنى توزيع مھام البرنامج على مجموعة من األجھزة بحيث تعمل بشكل متوازي وھو ما يسمى بالBalance Load حيث تكون ھنالك نسخة من البرنامج على كل Server وتعمل مع بعضھا على أساس توزيع الحمل أو بشكل متسلسل بحيث تعمل مع بعضھا على أساس توزيع المھام ويفضل في برمجيات األعمال Business Applications تقسيم المھام التالية كل منھا على Server منفصل: 1- واجھ ة المس تخدم أو ال Presentation وھ ي الواجھ ة الت ي يتعام ل معھ ا الزب ون بش كل مباشر. 2- الجزء الذي له عالقة بطبيعة برنامج األعمالTier Business وجميع القواعد التي لھا عالقة بالعمل مثل طريقة حساب الخصومات Discounts أو طريقة الدفع أو طريقة توصيل السلعة لزبون أو ما شابه. 3- الج زء المخص ص لحف ظ البيان ات Data Source وھ و الج زء ال ذي يحت وي عل ى قواع د البيانات والتي تحفظ عليھا معلومات الزبائن أو حساباتھم وكل ما له عالقة بذلك. ويمكن أن يتم ربط كل من ھذه األجزاء مع بعضھا البعض مستخدما ال( Services (Web أو استخدامھا ك DLL Reference وھو ما بينته في الفصل السابق Web Services Programming وفي كال الحالتين يجب استخدام أسلوب ال Remoting لربط بين الServers المتعددة وسوف نبين في الجزء التالي من ھذا الفصل كيفية الربط باستخدام الRemoting وكيفية االستفادة من ال Serialization الستخدام مكتبات ال Dll والتي قد تكون موجودة على جھاز بعيد الحظ الشكل التالي: تعتبر ال Web Services من األمور الھامة وخاصة ببرمجة النظم الموزعة حيث نقوم بربط أجزاء البرنامج مع بعضھا البعض وكمثال سنقوم بتطبيق نظام لشركة تصنيع العاب الحاسوب تستخدم أسلوب البيع اإللكتروني (التجارة اإللكترونية) حيث سيقوم الزبون بالدخول على الSite Web الخاص بالشركة والمبني على ال ASP.NET ويحتوي ھذا الموقع على المنتجات الخاصة بالشركة واألسعار لكل منتج وتعتمد الشركة بنك ال ABC لدفع اإللكتروني و ال DHL لتوصيل المنتج إلى البلد الذي يقيم فيه الزبون كما وتقدم الشركة خصومات بنسبة % 20 لزبائن المقيمين في األردن و فلسطين والعراق وسوريا وخصومات تصل إلى % 50 لزبائن الذين يشترون 3 منتجات أو أكثر من منتجات الشركة. ~228~
229 و قبل البدء ببناء النظام سنقوم بتقسيم ھذه المھام على ثالثة أجزاء وكما يلي: 1- واجھة المستخدم ال Presentation ويمكن أن تكون موقع الكتروني مبني على الASP.NET يحتوي على صور المنتجات وشرح مختصر عن كل منتج باإلضافة إلى سلة المشتريات ال Shopping Cart والتي يجمع فيھا الزبون مشترياته من الموقع والقيمة اإلجمالية لھا. 2- ال Business Part وھو مقسم ھنا على ثالثة أجزاء ) البنك نظام الخصومات أو الضرائب نظام التوصيل DHL كمثال) 3- ال Data Source Part وھو ھنا قاعدة البيانات الخاصة بالشركة والتي تقسم إلى جزأين (جزء معلومات الزبائن جزء العروض واألسعار). تنويه: جميع المعلومات المتعلقة بالشركات المذكورة ھي معلومات وھمية وأسماء الش ركات والبنوك الموضوعة في المثال ھي أس ماء مس جلة ألص حابھا وال تعب ر المعلوم ات الموج ودة عن الطريقة المتبعة وإنما تم تبسيطھا قدر اإلمكان لغايات التعلم. سيعتمد أسلوب الربط بين ھذه األنظمة على ال Web Services حيث سيوفر بنك ال ABC ال Web Service الخاصة بأسلوب الدفع اإللكتروني وستوفر ال DHL ال Web Service الخاصة بتوصيل المنتج وسيتم ربط ھذه ال Web Services بالموقع اإللكتروني وسنفترض أن البنك سيحتاج المعلومات التالية إلتمام عملية الدفع: Data Type String String Integer String Float String Field ame اسم الزبون Name) (Full العنوان Address) (Full + رقم الھاتف والفاكس... رمز الدولة و المدينة Code) (Zip رقم بطاقة االئتمان سواء كان MasterCard, VISA, Discover, American Express أو غيره المبلغ المودع رقم الحساب الخاص بالشركة وستكون ال Method بال Web Services الخاصة بالبنك كما يلي كمثال: C# [WebMethod] public bool Bank_Tier(string Customer_Name,string Address,int zip_code,string payment_method,string ecard_number,float depositor,string acount_number) // Check if the ecard number is correct // Check if the Account is Available // Do The Transaction // Return if the Transaction Done Successfully or not ~229~
230 VB. ET <WebMethod()> _ Public Function Bank_Tier(ByVal Customer_Name As String, ByVal Address As String, ByVal zip_code As Integer, ByVal payment_method As String, ByVal ecard_number As String, ByVal depositor As Single, ByVal acount_number As String) As Boolean ' Check if the ecard number is correct ' Check if the Account is Available ' Do The Transaction ' Return if the Transaction Done Successfully or not End Function سنفترض أن الشركة قد تم تسجيلھا في ال DHL Customers Table حيث يملك ال DHL المعلومات الكاملة عن الشركة (مثل رقم الحساب وعنوانھا وما شابه)...اآلن سيطلب الDHL ھذه المعلومات لتوصيل السلعة إلى الزبون: Data Type String String Integer String String Float Field ame اسم الزبون Name) (Full العنوان Address) (Full + رقم الھاتف والفاكس... رمز الدولة و المدينة Code) (Zip اسم الشركة التي تم الشراء منھا البريد اإللكتروني (Primary Kay) صافي المبلغ المطلوب (المحول) (سيتم معرفته من methodأخرى تحسب القيمة المطلوبة لتوصيل السلعة إلى البلد الذي يقيم فيه الزبون) وستكون ال Method بال Web Services الخاصة بال DHL كما يلي كمثال: [WebMethod] public string DHL_Tier(string Customer_Name,string Address,int zip_code,string company_name,string ,float cost, int quantity) // Check the Company Account // Store all information about the Customer // Do The Transaction // if the Transaction Done Successfully // it Return The Number of Days that Need to Deliver the Product to Customer ~230~
231 VB. ET <WebMethod()> _ Public Function DHL_Tier(ByVal Customer_Name As String, ByVal Address As String, ByVal zip_code As Integer, ByVal company_name As String, ByVal As String, ByVal cost As Single, ByVal quantity As Integer) As String ' Check the Company Account ' Store all information about the Customer ' Do The Transaction ' if the Transaction Done Successfully ' it Return The Number of Days that Need to Deliver the Product to Customer End Function لذلك عندما يريد أي زبون التسجيل في الموقع سيتطلب منه إدخال المعلومات التالية: Data Type String String String Integer String Field ame اسم الزبون Name) (Full كلمة المرور (Password) البريد اإللكتروني (Primary Kay) العنوان Address) (Full + رقم الھاتف والفاكس... رمز الدولة و المدينة Code) (Zip وتسجل جميع عمليات الشراء (السلع التي تم شرائھا ( وغير المش ترى بع د (ف ي عرب ة التس وق (shopping Cart على قاعدة بيانات موجودة في ال Storage Tier وستحتوي عل ى الحق ول التالية: Data Type Field ame String البريد اإللكتروني (Foreign Kay) String أو Barcode Kay) (Foreign البار كود لسلعة Integer العدد المطلوب Date/Time تاريخ ووقت الطلب Date/Time تاريخ ووقت التسليم Float صافي المبلغ المطلوب String طريقة الدفع ) Bank Check or (Transfer.. String طريقة التسليم Example) (DHL For Boolean (True/False) ھل تم الدفع أم ال (Statues) ~231~
232 وسنفترض وجود Table آخر يحتوي على السلع المتوفرة والكميات باإلضافة إلى صورة السلعة: Data Type Field ame String أو Barcode Kay) (Primary البار كود لسلعة String اسم السلعة Integer العدد المتوفر Binary صورة السلعة وقاعدة بيانات أخرى لحساب الضريبة Tax حيث تحتوي على رمز الدولة والضريبة لكل دولة: Data Type Field ame Integer رمز الدولة و المدينة Code) (Zip Float الضريبة Tax وجدول آخر يحتوي على اسم الدولة والخصم Discount الممنوح لكل دولة: Data Type Field ame Integer رمز الدولة و المدينة Code) (Zip Float الخصم discount واآلن س نحتاج إل ى بن اء قاع دة البيان ات الت ي تحت وي عل ى معلوم ات العم الء وربطھ ا بص فحة ASP.NET وكما في الشكل التالي: بعد الضغط على ال Register Me Now يجب أن يتم أوال التحقق من صحة البيانات المدخلة ثم إدخال المعلومات إلى قاعدة البيانات : try // Check if All Information is Correct if Yes do: sqlconnection1.open(); sqlcommand1.commandtext = "insert into Clients_info values('"+ _textbox.text+"','"+pass_textbox.text+"','"+name_t extbox.text+"',"+zipcode_textbox.text + ",'"+address_textbox.text+"')"; ~232~
233 sqlcommand1.executenonquery(); Response.Redirect(" catch(exception ex)msg_txt.text = ex.message; finallysqlconnection1.close (); VB. ET Try Check if All Information is Correct if Yes do: sqlconnection1.open() sqlcommand1.commandtext = "insert into Clients_info values('" & _TextBox.Text & "','" & Pass_TextBox.Text & "','" & Name_TextBox.Text & "'," & Zipcode_TextBox.Text & ",'" & address_textbox.text & "')" sqlcommand1.executenonquery() Response.Redirect(" Catch ex As Exception msg_txt.text = ex.message Finally sqlconnection1.close () End Try وبعد ذلك سينتقل إلى الصفحة التي تحتوي على المنتجات الخاصة بالشركة حيث يمكنك اختي ار السلعة التي تريد شرائھا ويتم حفظھا في سلة المشتريات... ي تم ف ي األنظم ة الموزع ة فص ل ال Client Information Table بوص فھا ض من ال Tier Presentation ع ن بقي ة األم ور المتعلق ة بالش راء وم ا ش ابه Business Tire وي تم ربطھا جميعا باستخدام Web Services يربط مع مشروع ال ASP.NET الخ اص بالش ركة وترسل المعلومات ك Serialization Object من نظام إلى آخر ويفترض الفصل التام بين كل طبقة من طبقات النظ ام الم وزع حي ث س ترجع ك ل Remote Method قيم ة ص افية دون إظھار كيفية استخراج ھذه القيمة الحظ الشكل التالي: ~233~
234 في ال : Business Tier Web Services ترجع ھذه ال Web Services والتي تحتوي على (نظام البيع و الخصومات و الضرائب) إلى ال Presentation Tier القيم ة الص افية المطلوب ة م ن الزب ون بع د اختي اره ش راء س لعة م ن الموقع حيث ستأخذ أربعة باروميترات األول سيحتوي على رمز الدولة والثاني سيحتوي عل ى ال الخاص بالزبون والثالث على ال Barcode الخاص بالسلعة والرابع س يحتوي عل ى طريقة الدفع وترجع ھذه ال Method القيمة الصافية المطلوبة من الزبون لشراء الس لعة وي تم تصميمھا كما يلي: C# [WebMethod] public float Business_Tier_Get_Net_Cost (int zip_code,string ,string barcode,string payment_method,int quantity) float tax = Calculate_Tax( ,zip_code,barcode,quantity); float dicount = Calculate_Discount( ,zip_code,barcode,quantity); float DHL_Cost = DHL_Cost(Products_barcode,Product_weighing,Company_ID,quantity; float Product_Cost = Product(barcode,quantity); return (Product_Cost + tax + DHL_Cost) - dicount; VB. ET <WebMethod()> _ Public Function Business_Tier_Get_Net_Cost(ByVal zip_code As Integer, ByVal As String, ByVal barcode As String, ByVal payment_method As String, ByVal quantity As Integer) As Single Dim tax As Single = Calculate_Tax( , zip_code, barcode, quantity) Dim dicount As Single = Calculate_Discount( , zip_code, barcode, quantity) Dim DHL_Cost As Single = DHL_Cost(Products_barcode, Product_weighing, Company_ID, quantity) Dim Product_Cost As Single = Product(barcode, quantity) Return (Product_Cost + tax + DHL_Cost) - dicount End Function ~234~
235 وفي حالة موافقة الزبون على شراء الس لعة س ينتقل ب ه الموق ع إل ى الص فحة الت ي تحت وي عل ى معلوم ات البن ك حي ث ي تم تمري ر الق يم إل ى ال Server عب ر ال Web Service الخاص ة بالبنك وكما يلي: [WebMethod] public bool Payment (string Customer_Name,string Address,int zip_code,string payment_method,string ecard_number,string acount_number) Return Bank_Tier( Customer_Name, Address, zip_code, payment_method, ecard_number, Net_Cost, acount_number); <WebMethod()> _ Public Function Payment(ByVal Customer_Name As String, ByVal Address As String, ByVal zip_code As Integer, ByVal payment_method As String, ByVal ecard_number As String, ByVal acount_number As String) As Boolean Return Bank_Tier(Customer_Name, Address, zip_code, payment_method, ecard_number, Net_Cost, acount_number) End Function وكما الحظنا في النظم الموزعة فإن كل خدمة من الخدمات تعم ل بجھ ة منفص لة ع ن الجھ ة أو الواجھة التي يتعامل معھا الزبون وتعمل جميعا وكأنھا في نظ ام واح د... س نتحدث ف ي الج زء الت الي ع ن ال Serialization وال Remoting وتطبيقاتھ ا ف ي برمجي ات الش بكات وال نظم الموزعة. ~235~
236 ثانيا - Programming : The Serialization : The Serialization Classes & Members يمكننا م ن خ الل ال Serialization عم ل Stream ال باس تخدام المحلي ة جھاز إلى آخر سواء عبر الش بكة من لObject Serializing Socket أو عبر اإلنترنت باستخدام الWebServices والRemoting ويمكننا استخدام ال System.Runtime.Serialization ال خ الل م ن ني ت ال دوت ف ي Serialization Namespace حي ث يحت وي ھ ذا ال Namespace عل ى ع دد ض خم م ن ال Classes والت ي تساعد في عمل Serialization ألي Object عبر اإلنترنت أو الشبكة المحلية ويبين الجدول التالي أھم ھذه ال Classes والتي يمكننا االستفادة منھا في بناء النظم الموزعة: ويحتوي ھذا ال Class على كل الوظائف الرئيسية لعمل Serialize ومنھا يستخدم ال Object ألي Serialization Stream عبر ال Object Serializing إلرسال Method وال 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 والذي سيتم شرحه بالتفصيل في األمثلة القادمة في ھذا الفصل. حيث يحتوي على ال IFormatter Interface وال IConvertible Interface ألستخدمھما في عمليات تمثيل ال... Serializing Stream حتى يمكن إرساله عبر ال Object ويستخدم لتوليد رقم ID عشوائي ألي Object حيث يحتوي ھذا ال Class على Tow Methods األول يقوم بتوليد رقم تسلسلي لل Object يسمى GetID والثاني يرجع قيمة ال ID الخاص بال Object ويسمى HasId ويأخذ كل منھما اسم ال Object الذي نريد توليد رقم تسلسلي له وقيمة True أو False لتحديد فيما إذا كانت ھذه ھي المرة األولى التي تم فيھا توليد رقم تسلسلي لل Object أم ال... GetId ( object_name,out bool) to Set an ID HasId( object_name,out bool) to Return the ID ويحتوي على كل المعلومات التي يمكن أن نحتاج لھا لعملية ال Serialize و ال Deserialize ألي Object مثال AssemblyName و ال FullTypeName وال Objects لل Data Types وتحويالت ال MemberCount وغيرھا... Formatters, Formatter & FormatterServices FormatterConverter ObjectIDGenerator SerializationInfo إلنش اء أي Serializable Class يج ب أوال أن يع رف بال [Serializable] Attribute حيث يعرف أن ھ ذا ال Class م ن ال Classes الت ي يمك ن أن ي تم عم ل Serializing عليھ ا وكما يلي كمثال لعمل Serializable Class للBank_Tier الخاص بالمثال السابق: ~236~
237 [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(); <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 وإلنشاء البرنامج الخ اص بعملي ة اإلرس ال الب د م ن تحدي د طريق ة اإلرس ال س واء ك Binary Stream Data أو XML Data فف ي األول سنس تخدم ال BinaryFormatter والموج ود ض من ال Namespace System.Runtime.Serialization.Formatters.Binary أم ا الثاني فسيستخدم مع ال SOAP Protocol والمعرف ض من ال SOAPFormatter Class والموج ود ض من ال System.Runtime.Serialization.Formatters.Soap.Namespace ولعم ل Serialization لل Class الس ابق باس تخدام ال SOAP Formatter الب د أوال م ن تعريف الNamespaces التالية: System.Runtime.Serialization System.Runtime.Serialization.Formatters.Soap ث م نق وم بعم ل Instance م ن ال Bank Web Services حي ث نس تطيع فيم ا بع د إس ناد المعلوم ات اآلتي ة م ن ال Tier Presentation إلي ه ث م إرس الھا إل ى ال Bank Server باستخدام ال Remoting أو الNetworkStream أو حفظھا على الجھ از ك Binary Data أو XML File وكما يلي كمثال لتخ زين المخرج ات ب XML File باس تخدام بروتوك ول ال : SOAP ~237~
238 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(); 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() وسكون ال Output ملف XML يحتوي على البيانات التي تم إدخالھا وكما يلي: - <SOAP-ENV:Envelope xmlns:xsi=" xmlns:xsd=" xmlns:soap- ENC=" xmlns:soap- ENV=" xmlns:clr=" SOAP- ENV:encodingStyle=" "> - <SOAP-ENV:Body> - <a1:form1_x002b_bank_tier id="ref-1" xmlns:a1=" n/serialization%2c%20version%3d %2c%20c ulture%3dneutral%2c%20publickeytoken%3dnull"> ~238~
239 <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"> </ecard_number> <depositor>600</depositor> <acount_number id="ref-6"> </acount_number> </a1:form1_x002b_bank_tier> </SOAP-ENV:Body> </SOAP-ENV:Envelope> وبتأكيد نستطيع استخدام ھذا المثال إلرسال البيانات عبر ال Network Stream أو باس تخدام ال Remoting كما يمكننا االستفادة م ن ال Serialization لتمثي ل أي Object عل ى ش كل XML أو Binary Data الستخدامھا في أمور أخرى... سنبين في المثال التالي كيفية االستفادة من ال BinaryFormatter Class إلرس ال Object أو Binary Data من جھاز إلى آخر عبر الشبكة كما سنبين كيفي ة االس تفادة م ن ال SOAP Protocol إلرسال Binary Data كStream XML وكمثال نريد إرسال صورة من جھ از إلى آخر بعد تحويلھا إلى Binary Stream باستخدام الMemoryStream وكما يلي: أوال : باستخدام ال BinaryFormatter في برنامج اإلرسال: 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 (); ~239~
240 VB. ET 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 استخدام ال BinaryFormatter في برنامج االستقبال: والس تخدام ال BinarFormatter ف ي برن امج االس تقبال سنس تخدم الدال ة المعاكس ة للSerialize وھي Deserialize ثم نقوم بعمل Casting لل Object المس تقبل ونحول ه إل ى Picture box ال عل ى عرض ه نس تطيع عن دھا أخ رى م رة MemoryStream Object باستخدام ال FromStream Method والموجودة ضمن ال : Image Class 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 ~240~
241 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. ET 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 ~241~
242 .. 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 ثانيا : استخدام ال SOAP في برنامج اإلرسال: حيث سترسل الصورة ك XML Data ثم تحول ف ي الط رف المقاب ل إل ى ص ورة م رة أخ رى وتتم ھذه العملية باستخدام بروتوكول ال SOAP وكما يلي في برنامج اإلرسال: 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(); 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 ~242~
243 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 استخدام ال SoapFormatter في برنامج االستقبال: والستخدام بروتوكول ال SOAP في برنامج االستقبال سنستخدم الدالة المعاكسة للSerialize وھ ي Deserialize ث م نق وم بعم ل Casting لل Object المس تقبل ونحول ه إل ى Picture box ال عل ى عرض ه نس تطيع عن دھا أخ رى م رة MemoryStream Object باستخدام ال FromStream Method والموجودة ضمن ال : Image Class 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(); ~243~
244 . 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 (); 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 وھكذا بينا كيفية استخدام ال Serialization في بيئة الدوت نيت بنوعيھا ال Binary والData XML سيتم الحديث في الجزء التالي من ھذا الفصل عن ال Remoting واستخدامھا في برمجيات الشبكات والنظم الموزعة... ~244~
245 ثالثا: : Remoting Programming يعتب ر موض وع ال Remoting م ن المواض يع الھام ة ج دا ف ي برمج ة الش بكات إذ يق دم لن ا إمكانيات رائعة في مشاركة و استخدام ال Remote Methods والموجودة على ال Remote Server وتش به عملي ة التعام ل م ع ال Remoting عملي ة ال Web Services إل ى ح د كبي ر حيث يتطلب استخدامھا عمل Proxy Object في ط رف ال Client لك ن م ع إمكاني ات اكب ر حيث تقوم بإنشاء الServer بنفسك ولست مضطرا لتثبيت ال IIS أو غي ره م ن التطبيق ات الوس يطة لالس تفادة م ن خ دمات ال Remote Server وتس تطيع م ن خالل ه تنفي ذ أي عملي ة معالج ة عل ى ال Server مم ا يع زز م ن مب دأ ال Systems Distributed وال ذي ش رحناه ف ي الج زء األول م ن ھ ذا الفص ل حي ث تبق ى الmethods و عملية المعالجة الخاصة بھ ا عل ى ال Server ف ي ح ين ي تم إرس ال ال Result إل ى ال Clients ك XML Data أو Binary Data حس ب قن اة االتص ال المس تخدمة س واء HttpChannel أو TcpChannel وتمرر إلى ال Client عبر ال Proxy Object وال ذي ربط ال Remote Class الموجود على ال Server مع ال Client الحظ الشكل التالي: : Using Remoting in Dot et -1 يمكن استخدام ال Remoting بطريقتين األول ى عب ر بروتوك ول ال HTTP حي ث ت تم عملي ة التراسل ك XML Data بين ال Server وال Clients وتتم باستخدام بروتوكول ال SOAP أما الطريقة الثانية فتتم باستخدام ال TCP Protocol حي ث تك ون عملي ة التراس ل ك Binary Data ب ين ال Server وبقي ة ال Clients ويفض ل دائم ا اس تخدام ال TCP Channel في الحالتين التاليتين: األولى: إذا كانت قناة االتصال سريعة نسبيا الثاني ة: توافقي ة البيئ ات حي ث تس تخدم نظ ام التش غيل Microsoft Windows ف ي جمي ع الclients ويعتبر ھذه األمر من أھم عيوب استخدام ال TCP Channel وخاص ة ف ي حال ة الWeb حيث ال تضمن البيئ ة الت ي س يعمل عليھ ا ال Client ويفض ل ف ي ھ ذه الحال ة اس تخدام الChannel HTTP لكن تبقى أدائية ال TCP Channel أفضل من ال... HTTP وم ا يمي ز ال HTTP Channel ھ و اس تخدامه بروتوك ول ال SOAP وال ذي يتعام ل م ع الXML في عملية التراسل مما يضمن توافقيته مع جميع البيئات. يلزم استخدام ال Remoting في الدوت نيت ثالثة أمور : أوال تحديد طبيعة القناة المستخدمة سواء عبر ال HTTP كXML أو عبر ال TCP كFormatter Binary ودعمت الدوت نيت كال منھما في الClass HttpChannel والموجود ضمن System.Runtime.Remoting.Channels.Http Namespace والClass TcpChannel والموجود ضمن الNamespace System.Runtime.Remoting.Channels.Tcp (يجب إضافته إلى ~245~
246 الReferences في المشروع) حيث يجب تعريفھا في كال الطرفين ال Client وال Server وكما يلي: HttpChannel http_channel = new HttpChannel(Port_Number); Dim http_channel As HttpChannel = New HttpChannel(Port_Number) وفي حالة استخدام ال TcpChannel كما يلي: TcpChannel Tcp_Channel = new TcpChannel(Port_Number); Dim Tcp_Channel As TcpChannel = New TcpChannel(Port_Number) بعد ذلك يجب تسجيل القناة المستخدمة باستخدام الدالة RegisterChannel والموجودة ضمن الClass ChannelServices ضمن ال System.Runtime.Remoting.Channels Namespace ويتم ذلك في كال الطرفين أيضا الClient وال Server وكما يلي: ChannelServices.RegisterChannel(chan); ChannelServices.RegisterChannel(chan) بعد ذلك يجب تعريف ال Class الذي سيتم مشاركته على ال Server ويتم ذلك باستخدام الدالة RegisterWellKnownServiceType والموجودة ضمن الRemotingConfigurationClass والموجود ضمن الNamespace System.Runtime.Remoting ويتم ذلك كما يلي في طرف ال :Server RemotingConfiguration.RegisterWellKnownServiceType (Type.GetType ("Class_File_Name, Distributed_Class_Name"), "unique_service_name", WellKnownObjectMode.SingleCall); RemotingConfiguration.RegisterWellKnownServiceType (Type.GetType ("Class_File_Name, Distributed_Class_Name"), "unique_service_name", WellKnownObjectMode.SingleCall) وتأخ ذ ال RegisterWellKnownServiceType Method ثالث ة ب اروميترات األول الType الخاص باسم الClass Remote مع اسم ال Dll File ومس اره وال ذي نري د توزيع ه ويأخذ الباروميتر الثاني اسم ال URI الخاص بال Object الذي نريد توزيع ه ويج ب أن يك ون ال URI Object اس م فري د unique عل ى مس توى ال Port Application ويأخ ذ الب اروميتر الثال ث ن وع ال Object Remote Instance ف إذا ت م اختي ار SingleCall فھ ذا يعن ي إنش اء New Instance جدي د لك ل Client يق وم بإنش اء Instance م ن ال Remote Remote Instance ال نف س اس تخدام يعن ي فھ ذا Singleton اختي ار وإذا ت م Class ~246~
247 Object لك ل ال Clients وينص ح اس تخدام SingleCall ف ي حال ة ك ان النظ ام الم وزع سيستخدم Session لكل User وينصح باستخدام Singleton في حالة كان ال Server سيبث نفس المعلوم ات إل ى ك ل ال Clients عل ى الش بكة... أم ا ف ي ال Client فيج ب تعري ف ن وع ال Channel س واء TCP أو HTTP Channel حس ب ن وع القن اة الت ي ت م اس تخدمھا ف ي الServer وال يتم وضع رقم ال Port في ال Client Channel ونكتفي بوضعه في ال URI Object ويتم تعريف القناة في ال Client كما يلي: HttpChannel http_channel = new HttpChannel Dim http_channel As HttpChannel = New HttpChannel() وفي حالة استخدام ال TcpChannel كما يلي: TcpChannel Tcp_Channel = new TcpChannel(); Dim Tcp_Channel As TcpChannel = New TcpChannel() ويتم تسجيل القناةRegisterChannel في ال Client كما ھو الحال في ال Server وكما يلي: ChannelServices.RegisterChannel(chan); ChannelServices.RegisterChannel(chan) بع د ذل ك نق وم بتعري ف New Instance Object م ن ال Remote Client حي ث يج ب أن يحتوي الProject Client على ال Dll File الخ اص بال Distributed Class حي ث نق وم في البداية بتعريف ال URI والذي سيحتوي على ال Protocol المستخدم ويتبع بعنوان الجھاز أو ال DNS الخاص بال Server ومن ثم رقم الPort المستخدم و اسم الخدمة التي تم تعريفھ ا في ال Server ويتم ذلك كما يلي: في حالة استخدام : TCP Channel string URI = "Tcp://"+Remote_IP.Text+":Port/ unique_service_name "; ~247~
248 Dim URI As String = "Tcp://" & Remote_IP.Text & ": Port/ unique_service_name " في حالة استخدام : HTTP Channel string URI = " Port / unique_service_name"; Dim URI As String = " & Remote_IP.Text & ": Port / unique_service_name " وبعد ذلك نقوم بإنشاء New Instance Object من ال Remote Class ويتم ذلك باستخدام الMethod GetObject والموجود ضمن ال Activator Class ونمرر لھا الType Distributed Class و ال URI الذي عرفناه وكما يلي: Distributed_Class_Name obj = (Distributed_Class_Name) Activator.GetObject (typeof (Distributed_Class_Name), URI); Dim obj As Distributed_Class_Name = CType(Activator.GetObject(GetType(Distributed_Class_Name), URI), Distributed_Class_Name) مالحظة ھامة: يجب أن يتم توريث ال MarshalByRefObject Class إلى ال Distributed Class الذي نريد توزيعه والموجود ضمن System Namespace وعند توريث الMarshalByRefObject إلى ال Distributed Class سيتم تنفيذ كافة العمليات أو الProcess على ال Server وسيحصل ال Client على ال Result النھائي في حين إذا تم استخدام الMarshalByValueObject عندھا سيتم استخدام ال Remote Class و لكن ستتم عملية المعالجة على ال... Client Side وھكذا بينا كيفية استخدام ال Remoting في الدوت نيت سنقوم اآلن بتطبيق ھذه المفاھيم في مشروعين األول سيكون نظام تعليمي موزع حيث سيبث فيھا صورة الكاميرا للمحاضر وسطح المكتب الخاص به إلى الطلبة والموجودين في دول متعددة. ~248~
249 أوال: إنشاء نظام : Distributed elearning System إلنشاء ھذا النظام البد أوال من بإنشاء Distributed Class يقوم بعملية التقاط لصورة سطح المكتب الخاص بالServer وبثھا إلى ال Client مستخدما ال TcpChannel بين ال Server وال Client وسنفترض في ھذا المثال إنشاء Remote Classroom حيث يقوم المعلم بإلقاء محاضرة إلى طالبه ويتم بث صورة الكاميرا وسطح المكتب الخاص بالمعلم عبر اإلنترنت إلى الطالب في ال Classroom والموجودين في دول متعددة وكما في الشكل التالي: سنس تخدم ف ي ھ ذا المث ال ال TCP Channel وال HttpChannel وس نقارن األداء ف ي ك ل منھما سيكون الشكل العام للبرنامج شبيه بالشكل التالي: ~249~
250 أوال برنامج المحاضر Project) :(Server برنامج ال Client ويمكن أن يكون من خالل اإلنترنت في حالة كان لديك Real IP أو في الشبكة المحلية وكما ھو مبين في الشكل التالي: وإلنش اء ال Remote Class وال ذي س يقوم بجل ب ص ورة س طح المكت ب سنس تخدم دوال ال API ومنھ ا ال Method GetDesktopWindow والموج ودة ض من ال user32.dl وال Method BitBlt لرس م الص ورة ث م س نقوم بتحوي ل الص ورة إل ى Byte Array وحت ى نس تطيع إرس الھا إل ى ال Clients وبتأكي د سنس تخدم طريق ة MarshalByRefObject وحتى تتم عملية التقاط ومعالجة الصورة على ال Server Side ويتم ذلك كما يلي: ~250~
251 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(); ~251~
252 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. ET 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 ~252~
253 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 وبتأكي د يج ب تحوي ل ال Class الس ابق إل ى Dll File ث م وض عه بجان ب المل ف التنفي ذي للمش روع وأيض ا إض افته ض من ال References ف ي مش روع ال Client وحت ى نس تطيع عمل ال Casting على ال Object القادم من الSever. ~253~
254 أوال : إنشاء ال : Remoting Server سيحتوي برنامج ال Server على األمور التالية: Class picturebox mainmenu WebCamCapture External Dll File Object Name picturebox1 mainmenu1 WebCamCapture1 سنقوم اآلن بإنشاء وتسجيل TCP Remote Channel ثم إنشاء ال Server Object ويتم ذلك كما يلي: TcpChannel chan = new TcpChannel(6600); ChannelServices.RegisterChannel(chan); RemotingConfiguration.RegisterWellKnownServiceType(Type.GetTyp e("screencapture, ScreenCapture"), "MyCaptureScreenServer",WellKnownObjectMode.Singleton); VB. ET Dim chan As TcpChannel = New TcpChannel(6600) ChannelServices.RegisterChannel(chan) RemotingConfiguration.RegisterWellKnownServiceType(Type.GetTyp e("screencapture, ScreenCapture"), "MyCaptureScreenServer",WellKnownObjectMode.Singleton) قمن ا بتس مية ال Server Object ب MyCaptureScreenServer و طبيع ة ال Instance سيكون Singleton وھذا يعني استخدام نف س ال Instance Object لك ل ال Clients و ف ي حال ة إذا أردن ا إنش اء New Instance Object لك ل Client Request فيج ب اس تخدام ال ال Server عل ى Load وفي حالتنا ھذه ينصح باستخدام األول وحتى ال يزيد ال SingleCall ف ي حال ة ربط ه عل ى مجموع ة كبي رة م ن ال Clients إذ أن المعلوم ات الت ي ي تم بثھ ا إل ى ال Clients ھي نفسھا... ول ربط ال WebCamCapture Class ف ي ال Picturebox نض ع الك ود الت الي ف ي ح دث ImageCaptured الخاص بال WebCamCapture Class وكما يلي: private void webcamcapture1_imagecaptured(object source, WebCam_Capture.WebcamEventArgs e) picturebox1.image = e.webcamimage; ~254~
255 Private Sub webcamcapture1_imagecaptured(byval source As Object, ByVal e As WebCam_Capture.WebcamEventArgs) picturebox1.image = e.webcamimage End Sub واآلن نس تطيع تش غيل الك اميرا عن د الض غط عل ى ال Start Button الموج ود ف ي ال main Menu ونضع في الحدث الخاص بھا كود التش غيل ونم رر ل ه ال Period Time لك ل عملي ة التقاط وھو مثال 1 Milliseconds ويتم ذلك كما يلي: this.webcamcapture1.timetocapture_milliseconds = 1; this.webcamcapture1.start(0); Me.webCamCapture1.TimeToCapture_milliseconds = 1 Me.webCamCapture1.Start(0) ثانيا : إنشاء ال : Remoting Client ويحتوي أيضا على األمور التالية : Class picturebox mainmenu Timer TextBox ScreenCapture Class External Class in References Object Name picturebox1 mainmenu1 timer1 textbox1 ScreenCapture وسنقوم بتعريف المتغيرات وال Objects التالية في ال Global Declaration للبرنامج: ScreenCapture obj; TcpChannel chan; string URI; Dim obj As ScreenCapture Dim chan As TcpChannel Dim URI As String سنستخدم الObject ScreenCapture لعم ل ال Casting عل ى ال Incoming Remote Remoting ال إلنش اء TcpChannel Object ال وسنس تخدم Instance Object Server Object بال الخ اص URI ال URI String Variable وسنضع في ال Channel والذي تم تعريفه في ال. Server ث م س نقوم بوض ع التعريف ات األساس ية لل TCP Channel وال Remote Object ف ي الConstructer الخاص بالمشروع وكما يلي: ~255~
256 public Form1() URI = "Tcp://"+textBox1.Text+":6600/MyCaptureScreenServer"; chan = new TcpChannel(); ChannelServices.RegisterChannel(chan); obj = (ScreenCapture)Activator.GetObject(typeof(ScreenCapture), URI); URI = "Tcp://" & textbox1.text & ":6600/MyCaptureScreenServer" chan = New TcpChannel() ChannelServices.RegisterChannel(chan) obj = CType(Activator.GetObject(GetType(ScreenCapture), URI), ScreenCapture) حي ث س يتم تمري ر ال Remote IP أو ال DNS الخ اص بال Server م ن ال TextBox ويتبعه رقم ال Port وال Remote Object الذي تم تعريفه في ال...Client ولجلب الصورة سنضع الكود التالي في Timer حيث يجلب الصورة من ال Server ك ل فت رة محددة: 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); 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) ~256~
257 picturebox1.image = Image.FromStream(ms) Catch ex As Exception timer1.enabled = False MessageBox.Show(ex.Message) End Try End Sub ولتحوي ل قن اة االتص ال إل ى Http Channel فق ط ق م بتغيي ر ال TcpChannel إل ى Internet ال عب ر Remote Methods ال مش اھدة م ن س تتمكن وعن دھا HttpChannel WSDL Web Services Definition Language ال ولمشاھدتھا نض يف Browser :Remote Object الخاص بال URI التالي إلى ال Query وستظھر لنا ال Remote Interface Class بھيئة XML الحظ الشكل التالي: وتستطيع االستفادة من التركيب السابق لل Class في حالة لم تتمكن من الحصول على ال Dll Dll مل ف إل ى الس ابق XML ال تحوي ل تس تطيع حي ث Remote بال Class الخ اص File لوض عه م ع ال References ف ي برن امج ال Client وي تم ذل ك باس تخدام ال Metadata Namespace ومنھ ا ال w3cxsd2001 Standard حي ث يوض ع الج زء األول الخ اص بالNamespace XML في ال Serializable Attribute وكما يلي كمثال: using System; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Metadata; using System.Runtime.Remoting.Metadata.W3cXsd2001; ~257~
258 soft.com/clr/nsassem/screencapture/screencapture%2c%20version%3 D %2C%20Culture%3Dneutral%2C%20PublicKeyToke n%3dnull")] public class ScreenCapture : System.MarshalByRefObject // Your Methods with Return Values Only Imports System Imports System.Runtime.Remoting.Messaging Imports System.Runtime.Remoting.Metadata Imports System.Runtime.Remoting.Metadata.W3cXsd2001 <Serializable(), SoapTypeAttribute(XmlNamespace:=" m/clr/nsassem/screencapture/screencapture%2c%20version%3d %2C%20Culture%3Dneutral%2C%20PublicKeyToken%3 Dnull"), Serializable(), SoapTypeAttribute(XmlNamespace:=" m/clr/nsassem/screencapture/screencapture%2c%20version%3d %2C%20Culture%3Dneutral%2C%20PublicKeyToken%3 Dnull")> _ Public Class ScreenCapture : Inherits System.MarshalByRefObject Your Methods with Return Values Only End Class ولالختيار بين ال TCP أو ال HTTP Channel فيفض ل دائم ا ف ي حال ة ك ان ال Remote Object موجود على جھاز تتصل معه عب ر اإلنترن ت اس تخدام ال HTTP Channel بس بب محدودية سرعة االتصال باإلضافة إلى كون ه يتواف ق م ع أي نظ ام س واء Windows أو غي ره لكن يبقى أداء وسرعة ال TCP Channel أفضل فقط في الNetwork... Local وھكذا بينا كيفية استخدام ال Remoting في ال دوت ني ت وطبقن ا عملي ة إنش اء Distributed elearning System وبتأكيد تستطيع اآلن إضافة ميزة نقل الصوت إلى جانب نقل ص ورة الشاش ة والك اميرا الخاص ة بالمحاض ر (لمزي د م ن المعلوم ات ارج ع إل ى الفص ل الخ اص بال VOIP ) وس نبين ف ي الج زء الت الي م ن ھ ذا الفص ل كيفي ة إنش اء برن امج Remote Desktop Application مع خاصية التحكم. ~258~
259 ثاني ا : إنش اء برن امج ال تحكم ع ن بع د Create an Advanced Remote Desktop : Application With Remote (Mouse/Keyboard) Control Features تعتم د الفك رة األساس ية ف ي مث ل ھ ذه الب رامج عل ى إرس ال إح داثيات ال Mouse (X,Y) والEvent Kay Press إلى ال Server وبتم كل ذلك باستخدام دوال ال API والموجودة في ملف المستخدم الشھير user32.dll حيث يحتوي ھذا الملف على عدد ضخم م ن ال دوال ومنھ ا الدالة SendInput والتي ترسل من خاللھ ا ال input Button Type ال ذي ت م الض غط علي ه بال Keyboard أو ال Mouse والدالة SetCursorPos وتأخذ إحداثيات ال X وال Y لل Mouse حيث يتم وضع مؤشر الMouse على اإلحداثيات المرسلة ويمكن اس تخدام الدال ة GetSystemMetrics لمعرف ة حج م ال Desktop Screen لل Server Width) (Height & ويمكن استخدام ھذه الدوال لتحكم عن بعد بطريقتين: 1- إرس ال اإلح داثيات إل ى ال Server ك Serialization Object عب ر ال Socket ث م استقبالھا وتنفيذھا بتمرير اإلحداثيات المستقبلة إلى الدوال و لكن المشكلة في ھذه الطريقة ھي ال بطء ف ي عملي ة إرس ال اإلح داثيات حي ث يمك ن أن يح دث ت أخير إثن اء اإلرس ال ناھي ك ع ن الBandwidth الذي ستحاجه في عملية إرسال ال... Control Object 2- اس تخدام ال Remoting ف ي عملي ة ال تحكم حي ث يس تدعي ال Client ال Methods الموج ودة عل ى ال Server وم ن ث م وتج رى عملي ة معالجتھ ا عل ى ال Server Side ويم رر الClient اإلحداثيات الخاصة بالتحكم إلى الMethods Remote الموجودة عل ى ال Server وتعتبر ھذه الطريقة من أسرع الط رق إلرس ال معلوم ات ال تحكم إل ى ال Server حي ث ي تم استدعاء ال Methods الموجودة على ال Server وكأنھا على الClient و تنفذ بعد ذلك عل ى ال. Server Side وللبدء سنقوم بإنشاء ال Distributed Class والذي سيحتوي على كل الدوال الخاصة بالتحكم وسنس تخدم System.MarshalByRefObject ولك ي ي تم تنفي ذ ك ل ال Methods عل ى ال Side Server ف ي البداي ة س نعرف مجموع ة م ن ال Unsigned Variables ولك ي نستخدمھا الحقا لتمرير طبيعة العملية التي نريد التحكم بھا ونمرر لھا مجموعة القيم بال Hex Decimal والتي تخص كل عملية : const uint MOUSEEVENTF_MOVE = 0x0001; //mouse move const uint MOUSEEVENTF_LEFTDOWN = 0x0002; // left button down const uint MOUSEEVENTF_LEFTUP = 0x0004; // left button up const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; // right button down const uint MOUSEEVENTF_RIGHTUP = 0x0010; // right button up const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020; // middle button down const uint MOUSEEVENTF_MIDDLEUP = 0x0040; // middle button up const uint MOUSEEVENTF_WHEEL = 0x0800; // wheel button rolled const uint MOUSEEVENTF_ABSOLUTE = 0x8000; // absolute move const uint KEYEVENTF_EXTENDEDKEY = 0x0001; const uint KEYEVENTF_KEYUP = 0x0002; const uint INPUT_MOUSE = 0; const uint INPUT_KEYBOARD = 1; ~259~
260 Const MOUSEEVENTF_MOVE As Integer = &H1 'mouse move Const MOUSEEVENTF_LEFTDOWN As Integer = &H2 ' left button down Const MOUSEEVENTF_LEFTUP As Integer = &H4 ' left button up Const MOUSEEVENTF_RIGHTDOWN As Integer = &H8 ' right button down Const MOUSEEVENTF_RIGHTUP As Integer = &H10 ' right button up Const MOUSEEVENTF_MIDDLEDOWN As Integer= &H20 'middle button down Const MOUSEEVENTF_MIDDLEUP As Integer = &H40 ' middle button up Const MOUSEEVENTF_WHEEL As Integer = &H800 ' wheel button rolled Const MOUSEEVENTF_ABSOLUTE As Integer = &H8000 ' absolute move Const KEYEVENTF_EXTENDEDKEY As Integer = &H1 Const KEYEVENTF_KEYUP As Integer = &H2 Const INPUT_MOUSE As Integer = 0 Const INPUT_KEYBOARD As Integer = 1 ثم سنعرف مجموعة من ال Structs الستخدامھا في عملية إدخال ال Kay Press Value من قب ل ال Client إل ى ال Server وھ ي MOUSE_INPUT إلدخ ال Mouse Buttons Keyboard Button Press Value إلدخ ال وال KEYBD_INPUT Press Values وتستدعى كل منھا باستخدام ال INPUT Struct وكما يلي: struct MOUSE_INPUT public uint dx; public uint dy; public uint mousedata; public uint dwflags; public uint time; public uint dwextrainfo; struct KEYBD_INPUT public ushort wvk; public ushort wscan; public uint dwflags; public uint time; public uint dwextrainfo; ~260~
261 [StructLayout(LayoutKind.Explicit)] struct INPUT [FieldOffset(0)] public uint type; // union [FieldOffset(4)] public MOUSE_INPUT mi; [FieldOffset(4)] public KEYBD_INPUT ki; Friend Structure MOUSE_INPUT Public dx As System.UInt32 Public dy As System.UInt32 Public mousedata As System.UInt32 Public dwflags As System.UInt32 Public time As System.UInt32 Public dwextrainfo As System.UInt32 End Structure Friend Structure KEYBD_INPUT Public wvk As System.UInt16 Public wscan As System.UInt16 Public dwflags As System.UInt32 Public time As System.UInt32 Public dwextrainfo As System.UInt32 End Structure <StructLayout(LayoutKind.Explicit)> _ Friend Structure INPUT <FieldOffset(0)> _ Public type As System.UInt32 ' union <FieldOffset(4)> _ Public mi As MOUSE_INPUT <FieldOffset(4)> _ Public ki As KEYBD_INPUT End Structure وسوف نستخدم ال Methods التالية لتنفيذ عملية التحكم عن بعد: - الدال ة SetCursorPos وتأخ ذ إح داثيات ال X وال Y لل Mouse حي ث ي تم وض ع مؤش ر الMouse بناء على اإلحداثيات المرسلة م ن ال Client حي ث ستس تخدم لتحري ك مؤش ر ال. Server في ال Mouse ~261~
262 - الدالة SendInput وسنرسل فيھا ثالثة ب اروميترات األول ع دد اإلدخ االت ف ي ك ل عملي ة و Virtual ال تأخ ذ فإنھ ا Keyboard ال حال ة ف ي م ثال المدخل ة للعملي ة Reference Value SendInput Method ال والس تخدام علي ه الض غط ت م ال ذي Button لل Kay Code سننش ئ PressOrReleaseMouseButton Method وال Method SendKeystroke وسنمرر لك ل منھ ا مجموع ة م ن المتغي رات حي ث س نعرف Instance م ن ال Struct Input وال ذي عرفن اه ف ي بداي ة البرن امج وس نمرر ل ه ال Input Type س واء م ن ال Mouse أو الKeyboard فإذا كان من ال Mouse نم رر ل ه إح داثيات المؤش ر وال Button Kay س واء فسنمرر له الVirtualKeyCode Keyboard أما إذا كان المدخل من ال Right أو Left الخاص بال Button الذي تم الضغط عليه... [DllImport("user32.dll")] private static extern uint SendInput( uint ninputs, // count of input events ref INPUT input, int cbsize // size of structure ); public void PressOrReleaseMouseButton(bool Press, bool Left, int X, int Y) INPUT input = new INPUT(); input.type = INPUT_MOUSE; input.mi.dx = (uint) X; input.mi.dy = (uint) Y; input.mi.mousedata = 0; input.mi.dwflags = 0; input.mi.time = 0; input.mi.dwextrainfo = 0; if (Left) input.mi.dwflags = Press? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; else input.mi.dwflags = Press? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; SendInput(1, ref input, Marshal.SizeOf(input)); [DllImport("user32.dll")] private static extern void SetCursorPos(int x, int y); ~262~
263 public void MoveMouse(int x, int y) SetCursorPos(x, y); public void SendKeystroke(byte VirtualKeyCode, byte ScanCode, bool KeyDown, bool ExtendedKey) INPUT input = new INPUT(); input.type = INPUT_KEYBOARD; input.ki.wvk = VirtualKeyCode; input.ki.wscan = ScanCode; input.ki.dwextrainfo = 0; input.ki.time = 0; if (!KeyDown) input.ki.dwflags = KEYEVENTF_KEYUP; if (ExtendedKey) input.ki.dwflags = KEYEVENTF_EXTENDEDKEY; SendInput(1, ref input, Marshal.SizeOf(input)); <DllImport("user32.dll")> _ Private Shared Function SendInput(ByVal ninputs As System.UInt32, ByRef input As Input, ByVal cbsize As Integer) As System.UInt32 End Function Public Sub PressOrReleaseMouseButton(ByVal Press As Boolean, ByVal Left As Boolean, ByVal X As Integer, ByVal Y As Integer) Dim input As Input = New Input input.type = INPUT_MOUSE input.mi.dx = System.Convert.ToUInt32(X) input.mi.dy = System.Convert.ToUInt32(Y) input.mi.mousedata = 0 input.mi.dwflags = 0 input.mi.time = 0 input.mi.dwextrainfo = 0 If Left Then If Press Then ~263~
264 input.mi.dwflags = MOUSEEVENTF_LEFTDOWN Else input.mi.dwflags = MOUSEEVENTF_LEFTUP End If Else If Press Then input.mi.dwflags = MOUSEEVENTF_RIGHTDOWN Else input.mi.dwflags = MOUSEEVENTF_RIGHTUP End If End If SendInput(1, input, Marshal.SizeOf(input)) End Sub <DllImport("user32.dll")> _ Private Shared Sub SetCursorPos(ByVal x As Integer, ByVal y As Integer) End Sub Public Sub MoveMouse(ByVal x As Integer, ByVal y As Integer) SetCursorPos(x, y) End Sub Public Sub SendKeystroke(ByVal VirtualKeyCode As Byte, ByVal ScanCode As Byte, ByVal KeyDown As Boolean, ByVal ExtendedKey As Boolean) Dim input As Input = New Input input.type = INPUT_KEYBOARD input.ki.wvk = VirtualKeyCode input.ki.wscan = ScanCode input.ki.dwextrainfo = 0 input.ki.time = 0 If (Not KeyDown) Then input.ki.dwflags = input.ki.dwflags Or KEYEVENTF_KEYUP End If If ExtendedKey Then input.ki.dwflags = input.ki.dwflags Or KEYEVENTF_EXTENDEDKEY End If SendInput(1, input, Marshal.SizeOf(input)) End Sub ~264~
265 وأما فيما يتعلق بجلب ال Bitmap لصورة سطح المكتب الخاص بال Server فسنس تخدم نف س الخطوات التي عرفناھ ا ف ي المث ال الس ابق واآلن س نقوم بتص ميم شاش ات البرن امج وس نحول الClass السابق إل ى مل ف Dll حي ث س يرفق بال Client ك Reference وسيوض ع بجان ب الملف التنفيذي الخاص بطرف الServer : أوال ال : Server س يحتوي برن امج ال Server عل ى ال Remoting Registration Channel وال ذي س يقوم بتعريف قناة االتصال وتوزيع ال Control Class والذي تم إنشائه حيث سيمكننا من االتصال مع ال Remote Class عبر Port محدد ويتم ذلك كما يلي: TcpChannel chan = new TcpChannel(6600); ChannelServices.RegisterChannel(chan); RemotingConfiguration.RegisterWellKnownServiceType(Type.GetTyp e("screencapture, ScreenCapture"), "MyCaptureScreenServer",WellKnownObjectMode.Singleton); VB. ET Dim chan As TcpChannel = New TcpChannel(6600) ChannelServices.RegisterChannel(chan) RemotingConfiguration.RegisterWellKnownServiceType(Type.GetTyp e("screencapture, ScreenCapture"), "MyCaptureScreenServer",WellKnownObjectMode.Singleton) ثانيا ال : Client يشبه برنامج ال Client البرن امج ال ذي قمن ا بإنش ائه ف ي المث ال الس ابق لك ن س نقوم م ن خالل ه بتمري ر ق يم اإلح داثيات الخاص ة بال Mouse و ال Virtual Kay Code الخ اص بالButtons Keyboard وللبدء قم بإنشاء مشروع جديد وكما في الشكل التالي: ~265~
266 سنحتاج إلى استخدام ال Namespaces التالية: System.Runtime.Remoting System.Runtime.Remoting.Channels System.Runtime.Remoting.Channels.Tcp System.IO System.Runtime.InteropServices System.Threading بعد ذلك قم بإضافة التعاريف التالية إلى منطقة ال Global Declaration في البرنامج: string URI; ScreenCapture obj; TcpChannel chan; bool connected = false; Dim URI As String Dim obj As ScreenCapture Dim chan As TcpChannel Dim connected As Boolean = False وسوف نستخدم MapVirtualKey Method والتي سنس تدعيھا م ن ال user32.dll لجل ب ال Virtual Kay Code الخ اص بال Button ال ذي س يتم الض غط علي ه حي ث سنس تخدمه لمعرفة أزرار التحكم التي تم الضغط عليھا إثناء كتابة األح رف مث ل ال Shift أو ال Control أو غيره: [DllImport("")] private static extern uint MapVirtualKey( uint ucode, // virtual-key code or scan code uint umaptype // translation to perform ); <DllImport("user32.dll")> _ Private Shared Function MapVirtualKey(ByVal ucode As System.UInt32, ByVal umaptype As System.UInt32) As System.UInt32 End Function ثم سنقوم بكتابة الكود الخاص بتعريف قناة االتصال في Start Method جديدة وكما يلي: ~266~
267 void start() try URI = "Tcp://"+textBox1.Text+":6600/MyCaptureScreenServer"; chan = new TcpChannel(); ChannelServices.RegisterChannel(chan); obj = (ScreenCapture)Activator.GetObject(typeof(ScreenCapture), URI); connected = true; timer1.enabled = true; textbox1.readonly = true; this.formborderstyle = FormBorderStyle.None;// Full Size Mode this.windowstate = FormWindowState.Maximized; textbox1.visible = false; menuitem5.enabled = true; catch (Exception)stop();; Private Sub start() Try URI = "Tcp://" & textbox1.text & ":6600/MyCaptureScreenServer" chan = New TcpChannel ChannelServices.RegisterChannel(chan) obj = CType(Activator.GetObject(GetType(ScreenCapture), URI), ScreenCapture) connected = True timer1.enabled = True textbox1.readonly = True Me.FormBorderStyle = FormBorderStyle.None ' Full Size Mode Me.WindowState = FormWindowState.Maximized textbox1.visible = False menuitem5.enabled = True End Try وسنس تدعي ال Start Method الس ابقة عن د زر ال Start monitoring ف ي ح ين س نقوم بإنش اء Method أخ رى إلغ الق االتص ال وت دمير ال Remote Object ال ذي ت م إنش ائه و إليقاف ال Timer الذي يقوم بجلب صورة سطح المكتب الخاص بالServer : ~267~
268 void stop() try timer1.enabled = false; textbox1.readonly = false; connected = false; this.formborderstyle = FormBorderStyle.Sizable; // Normal Size Mode this.windowstate = FormWindowState.Normal; textbox1.visible = true; this.width = 584; this.height = 440; ChannelServices.UnregisterChannel(chan);//to Un Register chan Channel catch(exception) Private Sub Stop() Try timer1.enabled = False textbox1.readonly = False connected = False Me.FormBorderStyle = FormBorderStyle.Sizable ' Normal Size Mode Me.WindowState = FormWindowState.Normal textbox1.visible = True Me.Width = 584 Me.Height = 440 ChannelServices.UnregisterChannel(chan) 'to Un Register chan Channel End Try وتتم عملية جلب صورة س طح المكت ب م ن ال Remote Object كم ا يل ي حي ث سنض ع ھ ذا الكود في Timer لتكرير عملية الجلب وعرض الصورة على :Picture box try URI = "Tcp://"+textBox1.Text+":6600/MyCaptureScreenServer"; byte[] buffer = obj.getdesktopbitmapbytes(); MemoryStream ms = new MemoryStream(buffer); picturebox1.image = Image.FromStream(ms); catch (Exception)stop(); ~268~
269 VB. ET 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 e1 As Exception stop() End Try ولتمرير إحداثيات ال Mouse إلى ال Server سنقوم باستدعاء ال MoveMouse Method والت ي عرفناھ ا ف ي ال remote Class الس ابق ويوض ع ف ي Mouse Move Event للbox Picture وكما يلي: private void picturebox1_mousemove(object sender, System.Windows.Forms.MouseEventArgs e) if (connected == true) obj.movemouse(e.x, e.y); Private Sub picturebox1_mousemove(byval sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) If connected = True Then obj.movemouse(e.x, e.y) End If End Sub وس نمرر ال Mouse Button Event إل ى ال PressOrReleaseMouseButton Method باس تدعائھا م ن ال up Mouse وال Mouse Down Events وتأخ ذ ھ ذه ~269~
270 الMethod أربعة باروميترات األول يمرر له قيمة True أو False ف إذا ك ان ال Event ھ و Mouse up Event والعكس في حالة ال True عندھا يجب أن تكون قيمتھا Mouse Down ويأخذ الباروميتر الثاني ال Button الذي تم الضغط عليه بال Mouse سواء Left أو Right ويأخذ قيمة True أو False حيث تق ارن ال e.button م ع ال MouseButtons.Left ف إذا كان ت True ف إن ذل ك ي دل عل ى أن ال Mouse Button ال ذي ت م الض غط علي ه ھ و Left والعكس في حالة ال Right ويأخذ الباروميتر الثالث والرابع إحداثيات ال X وال Y للمؤشر: private void picturebox1_mousedown(object sender, System.Windows.Forms.MouseEventArgs e) if (connected == true) obj.pressorreleasemousebutton(true, e.button == MouseButtons.Left, e.x, e.y); private void picturebox1_mouseup(object sender, System.Windows.Forms.MouseEventArgs e) if (connected == true) obj.pressorreleasemousebutton(false, e.button == MouseButtons.Left, e.x, e.y); Private Sub picturebox1_mousedown(byval sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) If connected = True Then obj.pressorreleasemousebutton(true, e.button = MouseButtons.Left, e.x, e.y) End If End Sub Private Sub picturebox1_mouseup(byval sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) If connected = True Then obj.pressorreleasemousebutton(false, e.button = MouseButtons.Left, e.x, e.y) End If End Sub ولتمري ر ال Kay Code لل Buttons الخ اص بال Keyboard ال ذي ت م الض غط علي ه سنستخدم األحداث Kay Down والup Kay الخاصة بال Form وكما يلي: ~270~
271 private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) if (connected == true) e.handled = true; obj.sendkeystroke((byte) e.keycode, (byte) MapVirtualKey((uint) e.keycode, 0), true, false); private void Form1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) if (connected == true) e.handled = true; obj.sendkeystroke((byte) e.keycode, (byte) MapVirtualKey((uint) e.keycode, 0), false, false); Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) If connected = True Then e.handled = True obj.sendkeystroke(cbyte(e.keycode), CByte(MapVirtualKey(System.Convert.ToUInt32(e.KeyCode), 0)), True, False) ~271~
272 End If End Sub Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) If connected = True Then e.handled = True obj.sendkeystroke(cbyte(e.keycode), CByte(MapVirtualKey(System.Convert.ToUInt32(e.KeyCode), 0)), False, False) End If End Sub قمنا بالبداية بإيقاف فاعلية ال Buttons باستخدام الTrue e.handled = وبعد ذلك مررنا ال Kay code ال ذي س يتم الض غط علي ه إل ى ال SendKeystroke Method وتأخ ذ ھ ذه الMethod أربعة باروميترات على النحو الت الي األول ويأخ ذ ال Byte لل Virtual Kay Shift Kay س واء ال Keys لحال ة Scan Code الذي تم الضغط عليه ويأخذ الثاني ال code أو Control Kay أو إذا كن ت تح ت ال Caps look Mode أو غي ره م ن أزرار ال تحكم الخاصة بال Keyboard ويتم ذلك بعد تمري ر ق يم ال unassigned Integer Code الراج ع من الe.KayCode إلى ال MapVirtualKey التي عرفناھا في بداية البرنامج... أما الباروميتر الثالث فيأخ ذ قيم ة True ف ي حال ة ك ان الح دث ھ و KayDown و False ف ي حال ة ك ان الح دث ھ و KayUp ويأخ ذ الب اروميتر الراب ع قيم ة false حي ث ل ن تس تخدم الKeys Extended أي الضغط المطول... وھك ذا بين ا كيفي ة بن اء نظ ام ل تحكم ع ن بع د باس تخدام ال Remoting وط رق اس تخدام ال Serialization ف ي ال دوت ني ت وط رق بن اء وتص ميم األنظم ة الموزع ة س نتحدث ف ي الفصل التالي عن طرق استخدام ال SMTP إلرسال Emil s وال POP3 لقراءة ال Mail Box في الدوت نيت... ~272~
273 Chapter 16 SMTP & POP3 Programming - SMTP Protocol 1. SMTP Concept 2. Using SMTP in Dot Net 3. Advanced SMTP Programming - POP3 Protocol 1. POP3 Concept 2. Using POP3 in Dot Net ~273~
274 : SMTP & POP3 Programming :16 سوف نتحدث في ھذا الجزء عن برمجة الSMTP والمسئول عن إرس ال الرس ائل عب ر البري د اإللكتروني إلى الServer Mail و ال POP3 والمس ئول ع ن عملي ة ال Download لرس الة من الServer Mail إلى جھاز الزبون... أوال: SMTP Simple Mail Transfer Protocol Programming من المعروف أن الServer Mail يقوم بتجزئة عمليات إرس ال و اس تقبال البري د اإللكترون ي عبر اإلنترنت إلى ثالثة أجزاء وھي كما في الشكل التالي : Message Transfer Agent MTA والمس ئول ع ن اإلرس ال Outgoing والتوص يل Incoming للرسائل Message Delivery Agent -MDA و المس ئول ع ن عملي ات ال filtering والتأك د م ن وصول الرسالة Message User Agent -MUA والمس ئول ع ن عملي ة ق راءة و تخ زين الرس الة ف ي POP - Post بروتوك ول باس تخدام العملي ة ھ ذه وت تم Client المس تقبل ل دى Database Office Protocol انظر إلى الشكل التالي : و يس تخدم برتوك ول ال Protocol SMTP Simple Mail Transfer بش كل أساس ي ف ي الMTA أي عمليات إرسال Outgoing وتوصيل Incoming الرسائل. ~274~
275 لتطبيق يجب أوال التأكد من أنك تملك حساب SMTP من الProvider Internet الخاص بك تستطيع تجربة الAccount الخ اص ب ك م ن خ الل برن امج ال Express Outlook الموج ود مع الWindows إذا كنت ال تملك حساب SMTP تس تطيع تجرب ة البرن امج م ن خ الل إنش اء Control Panel >> : م ن بتثبيتھ ا وذل ك ال IIS طري ق ع ن Virtual SMTP Server Add/Remove Programs تأكد من تفعيل كل من الIIS والSMTP كما في الشكل التالي: ثم إعداد الServer من الIIS كما في الشكل التالي : ت دعم ال دوت ني ت اس تخدام بروتوك ول ال SMTP م ن خ الل Namespace System.Web.Mail و تحتوي على الكالس SmtpMail والتي من خاللھا نستخدم الدال ة Sendوالتي تستخدم إلرسال الرس الة عب ر ال 25 Port وھ و ال Port المخص ص لبروتوك ول SMTP و تعتبر الدالة " overloaded Method " Send حيث تأخذ عدة أشكال إذ بإمكانك ~275~
276 اس تخدامھا م ع ب اروميتر واح د إل ى أربع ة ب اروميترات وبش كل افتراض ي نس تخدم الباروميترات التالية : SmtpMail.Send(string from, string to, string subject, string body) الب اروميتر األول يوض ع في ه عن وان المرس ل والث اني يوض ع في ه عن وان المرس ل إلي ه و الباروميتر الثالث لعنوان الرسالة والرابع لنص الرسالة. ولعمل برنامج يقوم بإرسال البريد اإللكتروني قم بإنشاء New Form كما في الشكل التالي: ثم قم بإضافة System.Web.Mail Namespace ) إذا ل م تظھ ر ل ديك.Mail ق م ب إدراج System.Web Namespace إلى الReferences ( ثم قم بكتابة الكود التالي : using System.Web.Mail; imports 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); وتتم عملية إرسال الرسالة كما يلي: ~276~
277 catch (Exception ex) MessageBox.Show(ex.Message); Try Dim from As String = textbox1.text Dim to As String = textbox2.text Dim subject As String = textbox3.text Dim body As String = textbox4.text SmtpMail.SmtpServer = textbox5.text SmtpMail.Send(from, to, subject, body) Catch ex As Exception Msgbox(ex.Message) End Try مالحظة ھامة جدا : ھ ذا الك ود يعم ل بش كل جي د لك ن يج ب التأك د م ن تفعي ل ال SMTP م ن ال IIS كم ا ذك ر ف ي السابق وال IP الخاص بالSMTP (والذي ت م تعريف ه مس بقا ف ي (SMTP Virtual Server بال SMTP Server Textbox يج ب التأك د أيض ا م ن ال Server SMTP ل ديك ي دعم اس تخدام المكتب ة CDO2 - Microsoft Collaboration Data Objects Version 2 وإال سوف تحصل على Exception يخبرك بأنه ال يستطيع الوصول إلى CDO2 Object ف ي الع ادة ي تم اس تخدمھا م ع Windows XP و Windows 2000 وتعم ل بش كل افتراض ي عند تثبيت الServer SMTP Virtual أو مع Microsoft Exchange Server2003 أما إذا كن ت تس تخدم Exchange Version 5 أو 5.5 فس وف تحص ل عل ى ال Exception السابق الذكر. ~277~
278 الجزء األكثر تقدم: SMTP Advanced Programming يعتب ر المث ال الس ابق مث ال بس يط إلرس ال رس ائل عب ر ال SMTP باس تخدام CDO2 وف ي العادة عند إنشاء برامج مثل برنامج الOutlook ي تم اس تخدام ال Format HTML باإلض افة إال إمكانية إرسال ملحقات وطبع ا يعطي ك ع دة خي ارات إلرس ال و اس تقبال البري د اإللكترون ي ھل باستخدام الHTTP أو الPOP3... سوف نقوم بإنشاء برنامج بسيط يقوم بإرسال واستقبال البريد اإللكترون ي باس تخدام ال SMTP وال POP3 بنسبة الستخدام الPOP3 فيجب أن يتوفر لديك حساب POP3 أو أن تقوم بتثبي ت ال Service POP3 والت ي ت أتي م ع Windows Server أو أن تس تخدم Microsoft Exchange Server على جھازك وإع داده بحي ث يس تخدم ال POP3 إذ عن دھا س وف تحت اج لوج ود Domain Controller مثب ت عل ى الجھ از و Windows Server باإلض افة إل ى تثبيت الDirectory Active عليه. ق دمت ال دوت ني ت دع م ممت از الس تخدام ھ ذه الخ واص وذل ك م ن خ الل Namespace System.Web.Mail وباس تخدام الك الس MailMessage ل دعم ال Format HTML و الكالس MailAttachment لدعم إمكانية إرسال ملحقات مع الرسالة ولكن لبرمجة ال POP3 يل زم اس تخدام System.Net.Socket Namespace و System.Net و System.IO حيث يتم عمل Session خاص مع الServer للقيام بعملية تفح ص وج ود رس ائل جدي دة وف ي حال ة وجودھ ا يق وم بتعبئتھ ا ف ي List Box أو Treelist حس ب الحاج ة وعن د الض غط عل ى إحداھا يقوم الClient بعمل Download لرسالة من الServer Mail ولعم ل Advanced SMTP Sender قم بأخذ Object من الكالس MailMessage كما يلي : 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); imports System.Web.Mail; ~278~
279 Try Dim mm As MailMessage = New MailMessage mm.from = textbox1.text mm.to = textbox2.text 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 ex As Exception Msgbox(ex.Message) End Try الحظ أن جسم الرسالة يستخدم كود الHTML وھذا يمكنك من وض ع أي ل ون أو حج م أو أي ش يء يمك ن عمل ه باس تخدام ال HTML ولجع ل البرن امج ق ادر عل ى إرس ال ملحق ات يج ب استخدام الكالس MailAttachment وإدراج اسم الملف فيه وكما يلي بالكود : MailAttachment myattach = new MailAttachment("Your_Attached_File_path.extension", MailEncoding.Base64); Dim myattach As MailAttachment = New MailAttachment("Your_Attached_File_path.extension", MailEncoding.Base64) وھكذا قد انتھينا من برنامج الSMTP بشكل كامل طبعا عملية ال Design على حسب ذوق وذكاء وخبرة المبرمج. وغيرھا تعتم د ~279~
280 ثانيا : Programming POP3- Post Office Protocol Version 3 كم ا تح دثنا س ابقا ف إن وظيف ة برتوك ول ال POP3 وال ذي يعم ل ف ي ج زء ال MUA - Mail User Agent على 110 Port ضمن برتوكول الTCP تكمن في كونه المس ئول ع ن عملي ة توصيل الرسالة إلى الزبون Client من خالل عمل Download لھ ا م ن ال Server Mail حي ث تحف ظ الرس ائل ف ي ال Folder Mail والموج ود أساس ا ف ي جھ از ال Client أنظ ر إل ى الشكل التالي: ومن الب دائل لل POP3 برتوك ول Interactive Mail Access Protocol IMAP فم ن خالله يستطيع المستخدم إنشاء Mail Folder خاصة به ولكن ف ي ال server Mail ول يس في جھاز الزبون وتعتبر ھذه من ميزات الIMAP وسيئاته بنفس الوق ت إذ أن ق راءة الرس الة تتم مباشرة من خالل الServer حيث تستطيع قراءتھا من أكثر من Client ولكن المش كلة في ه ھي تحكم م دير خ ادم الرس ائل Mail Server Administrator بحج م ال Folder Mail إذ تكون في العادة سعتھا محدودة أنظر إلى الشكل التالي : الح ظ أن ال Folder Mail يق ع ض من Mail Server وي تم قراءت ه بع د التحق ق Authentication م ن اس م المس تخدم وكلم ة الم رور لك ن كم ا قلن ا ف إن مش كلته تكم ن ف ي محدودي ة س عة ال Folder Mail ل ذا ينص ح لش ركات الكبي رة اس تخدام ال POP3 كون ه غي ر مح دود الس عة فال ذي ي تحكم ف ي الس عة ھ و ال Client وال دخ ل ل Mail Server Administrator بھا. ~280~
281 وبم ا أنن ا قررن ا اعتم اد ال POP3 لعملي ة ق راءة الرس ائل س وف نب دأ ببرمجت ه إذ يل زم األم ر استخدام System.Net.Socket Namespace و System.Net و System.IO حي ث ي تم عمل Session خاص مع الServer باستخدام الSocket للقيام بعملي ة تفح ص وج ود رس ائل جدي دة وف ي حال ة وجودھ ا يق وم بتعبئ ة عناوينھ ا ف ي List Box أو Treelist خ اص حس ب الحاجة وعن د الض غط عل ى إح داھا يق وم ال Client بعم ل Download لرس الة م ن ال Mail.Textbox ثم عرضھا في Mail إلى الFolder Server ولتطبيق قم بإنشاء New Form جديد كما يظھر في الشكل التالي : ثم قم بإضافة Namespaces التالية : using System.Net; using System.Net.Socket; using System.IO; imports System.Net imports System.Net.Socket imports System.IO الحظ انه يتم التعامل مع الSocket والStream إلنشاء Session مع الServer باستخدام برتوكول الTCP وقراءة الرسالة من الServer POP3 ويستخدم ال Stream Socket السابق لتمرير ال Commands إلى الServer وھي: ~281~
282 USER (USER USER_NAME) PASS (PASS PASSWORD) RETR (RETR Message_Number) STAT QUIT إدخال ال User Name وال Password إلجراء عمليات التحقق ال Authentication وتستخدم لجلب الرسالة من ال POP3 وترجع ك... Byte Array لمعرفة وجود رسائل جديدة وعدد الرسائل الجديدة في ال inbox إغالق ال Session مع ال POP3 Server ثم قم بإضافة التعاريف التالية في بداية البرنامج (أي بعد تعريف الكالس الرئيسي ف ي منطق ة الDeclaration (Global : اشتقاق كائن من برتوكول التي سي بي وذلك بھدف إنشاء Server;// public TcpClient الجلسة سوف نستخدمه إلرسال معلومات المستخدم NetStrm;// public NetworkStream لقراءة المعلومات الواردة من البوب // 3 RdStrm; public StreamReader الستخدامھا في تمرير األوامر إلى السيرفر// Data; public string لتخزين البيانات الواردة من البوب // 3 szdata; public byte[] الستخدامھا في البرنامج لعمل سطر جديد.. "\r\n";// public string CRLF = Public Server As TcpClient Public NetStrm As NetworkStream Public RdStrm As StreamReader Public Data As String Public szdata As Byte() Public CRLF As String = "" & Microsoft.VisualBasic.Chr(13) & "" & Microsoft.VisualBasic.Chr(10) & "" // create server POP3 with port 110 Server = new TcpClient(POPServ.Text,110); try // initialization NetStrm = Server.GetStream(); RdStrm= new StreamReader(Server.GetStream()); Status.Items.Add(RdStrm.ReadLine()); في الButton Connect قم بإضافة الكود التالي : // Login Process Data = "USER "+ User.Text+CRLF; szdata = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); ~282~
283 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 لمعرفة عدد الرسائل الموجودة في POP3 Server باستخدام األمر STAT Data = "STAT"+CRLF; szdata = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData,0,szData.Length); Status.Items.Add(RdStrm.ReadLine()); قم بإضافة الكود التالي إلى الButton : Disconnect // 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(); Server = New TcpClient(POPServ.Text, 110) NetStrm = Server.GetStream RdStrm = New StreamReader(Server.GetStream) Status.Items.Add(RdStrm.ReadLine) 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) Data = "STAT" + CRLF szdata = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray) NetStrm.Write(szData, 0, szdata.length) Status.Items.Add(RdStrm.ReadLine) Data = "QUIT" + CRLF szdata = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray) ~283~
284 NetStrm.Write(szData, 0, szdata.length) Status.Items.Add(RdStrm.ReadLine) NetStrm.Close RdStrm.Close ولقراءة الرسائل من صندوق الوارد( بشكل افتراضي سيتم قراءة الرسالة األخيرة ( ق م بإض افة الكود التالي إلى الButton : Read Last Come string sztemp; Message.Clear(); try // retrieve mail with number mail parameter لتحديد رقم الرسالة المراد قراءتھا // 1"+CRLF; Data = "RETR szdata = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray()); NetStrm.Write(szData,0,szData.Length); تخزين الرسالة بشكل مؤقت حتى يتم طباعتھا // RdStrm.ReadLine(); sztemp = 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()); Dim sztemp As String Message.Clear Try Data = "RETR 1" + CRLF szdata = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray) NetStrm.Write(szData, 0, szdata.length) sztemp = RdStrm.ReadLine If Not (sztemp(0) = "-"C) Then While Not (sztemp = ".") Message.Text += sztemp + CRLF sztemp = RdStrm.ReadLine End While ~284~
285 Else Status.Items.Add(szTemp) End If Catch err As InvalidOperationException Status.Items.Add("Error: " + err.tostring) End Try وھكذا بينا كيفية عمل الPOP3 وبرمجته ف ي ال دوت ن ت وھ ذا مث ال بس يط تس تطيع الب دء من ه لعم ل مش روع كام ل ش بيه بال Outlook الخ اص بميكروس وفت حي ث تس تطيع اس تخدام مل ف الDLL الخ اص باإلنترن ت إكس بلورر لع رض الرس ائل ال واردة ب دال م ن عرض ھا عل ى ش كل HTML Code كما تستطيع عمل Tree List لوضع الرسائل الواردة حيث يكون لكل رسالة رقم تسلس لي ي تم وض عه ف ي الك ود الس ابق لقراءتھ ا حي ث اس تخدمت ال رقم 1 بش كل افتراض ي والذي يقوم بقراءة الرسالة األخيرة الواردة سيتم الحديث في الفصل التالي عن ال FTP وطرق التعامل معه في بيئة الدوت نيت. ~285~
286 Chapter 17 FTP Programming - Introduction to FTP File Transfer Protocol - Create a Simple Application to Transfer Files By Using COM Components - Create a Simple Application to Transfer Files By Using Web Classes Components - Create a Simple Application to Transfer Files By Using Socket Programming & Streaming Libraries ~286~
287 : FTP File Transfer Protocol Programming 17 سوف نبدأ ھنا بشرح برتوكول أخر من برتوك والت ال Layer Application وھ و برتوك ول الFTP والذي يستخدم بشكل أساسي في عملية ال downloading و ال uploading الملف ات من وإلى ال Server FTP وكالع ادة ف ي اغل ب برمجي ات الش بكات و الت ي تعتم د عل ى وج ود Client/Server حي ث يق وم ال Server بتص نت عل ى ال Port المخص ص لل FTP وھ و ال Port 21 باس تخدام ال Protocol TCPحي ث Connection Oriented يبق ى ال Server بوض ع االنتظ ار ل ورود طل ب م ن ال Client بإنش اء Session مع ه وبع د إج راء عملي ات التحقق Authentication والتأكد م ن الص الحيات ي تم الموافق ة عل ى الب دء بالجلس ة حي ث ي تم تحديد رقم الPort والذي سوف يتم استقبال البيانات من خالله ويتم اإلرسال إلى جھاز الزبون عبر الPort 20 في الServer وتتضح ھذه العملية كما في الشكل التالي : مالحظة: لتفعيل خدمة الFTP لديك بحي ث يعم ل جھ ازك ك FTP Server يج ب أوال التأك د من أن الServices FTP مثبتة لديك مع الIIS و كما يظھر في الشكل التالي : ~287~
288 ومن ثم التأكد من تفعيلھا ب Services م ن Control Panel ث م Administrative Tools ثم Services وكما يظھر في الشكل التالي : ثم التأكد منه في الIIS بحيث يظھر كما في الشكل التالي : ~288~
289 أوال : Commands FTP تشبه عملية االتصال و االستخدام لل FTP عملية الTelnet إلى حد كبير حيث يدعم برتوك ول ال FTP مجموع ة م ن األوام ر والت ي ي تم م ن خاللھ ا عملي ة التخاط ب م ع ال Server أو م ع الHost Remote وتضح ھذه العملية كما في الشكل التالي : وھنا شرح ألھم الCommands :FTP USER <username> & PASS مطلوبة لعملية التحقق إلنشاء الجلسة <password> <filename> RETR أو RECV ويستخدم لتنزيل ملف من الServer بعد تحديد اسم الملف <filename> STOR أو SEND ويستخدم لرفع الملف إلى الServer بعد تحديد اسم الملف لتحديد طبيعة أو ھيئة البيانات التي يتم نقلھا TYPE <type indicator> وكما يلي : -a ASCII e EBCDIC I for Binary Data - L<Byte < Sizeوالذي سيتم نقله لتحديد نوع الجلسة سواء Passive أو PASV ~289~
290 Active إذ انه في حالة الPassive يتم تفعيل االتصال فقط في حالة ورود أو رفع أي ملف من و إلى الServer. لفحص حالة االتصال و & uploading Downloading وھي كما ھو متعارف عليه في التعامل مع الملفات و المجلدات في نظام الDOS إلنھاء الجلسة مع الHost Remote Status أو STAT Delete, cd, mkdir, rename Close أو QUIT ثانيا : التعامل مع الFTP في الدوت نيت باستخدام : COM Components ت دعم ال دوت ني ت اس تخدام ال FTP عب ر ITC Internet Transfer Control وھ و ج زء م ن ال Controls COM Components وللب دء ق م بإنش اء New Windows Application كما في الشكل التالي : using System.IO; using System.Reflection; imports System.IO imports System.Reflection ~290~ ثم قم بإضافة Namespaces التالية : ثم إضافة الكود التالي إلى الButton : Upload 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;
291 ITC.InvokeMember("execute", BindingFlags.InvokeMethod,null, ITCObject, parameter); Private Sub button1_click(byval sender As Object, ByVal e As System.EventArgs) Dim thisfile As FileInfo = New FileInfo(tbFile.Text) Dim ITC As Type Dim parameter(2) As Object Dim ITCObject As Object ITC = Type.GetTypeFromProgID("InetCtls.Inet") ITCObject = Activator.CreateInstance(ITC) parameter(0) = CType(tbServer.Text, String) parameter(1) = CType("PUT ", String) + thisfile.fullname + " /" + thisfile.name ITC.InvokeMember("execute", BindingFlags.InvokeMethod, Nothing, ITCObject, parameter) End Sub ت م ف ي البداي ة تعري ف ال ITC م ن خ الل ال Type Class والموج ود ض من Namespace System.Reflection ثم عرفنا Array من النوع Object وذلك الستخدامھا في تمرير اس م الملف و الServer FTP إلى الدالة InvokeMember والموجودة ضمن ال ITC Control... Object سوف تجد الملف الذي سيتم رفعه في المجلد : C:\Inetpub\ftproot ~291~
292 ثالثا : التعامل مع الFTP في الدوت نيت باستخدام الClass : Web يمك ن برمج ة ال FTP باس تخدام web Class والموج ودة ض من Namespaces System.Net وتش به عملي ة التعام ل مع ه كم ا ف ي التعام ل م ع ال WebRequest و ال webresponse Classes و الت ي تعاملن ا معھ ا ف ي برمج ة ال HTTP حي ث يمكنن ا االستفادة منھا لتعامل مع الProtocol FTP وھي كما يلي : - WebClient إذ تم دعم dot net Framework 2 استخدام الكالس WebClient والذي يدعم التعامل مع الFTP والذي يتم استدعائه من System.Net Namespaces ويتم تعريف ه كما يلي : 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"); Imports System Imports System.Net Namespace Web_Client Class Program Public Shared Sub Main(ByVal args As String()) Dim filename As String = "ftp://ms.com/files/dotnetfx.exe" Dim client As WebClient = New WebClient client.downloadfile(filename, "dotnetfx.exe") End Sub End Class End Namespace ~292~
293 - FtpRequestCreator ويستخدم لتسجيل وبدأ العمل مع الFTP ويعرف كما يلي : 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); Imports System Imports System.Net Namespace FTP Public Class FtpRequestCreator Implements IWebRequestCreate Public Sub New() End Sub Public Function Create(ByVal uri As System.Uri) As System.Net.WebRequest Return New FtpWebRequest(uri) End Function End Class End Namespace download or upload a file on an FTP ويستخدم لعمل FtpWebRequest - server ويتم تعريفھا كما يلي : using System; using System.Net; namespace FTP ~293~
294 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; ~294~
295 Imports System Imports System.Net Namespace FTP Public Class FtpWebRequest Inherits WebRequest Private username As String = "Fadi" Friend password As String = "fff" Private uri As Uri Private binarymode As Boolean = True Private method As String = "GET" Friend Sub New(ByVal uri As Uri) Me.uri = uri End Sub Public Property Username() As String Get Return username End Get Set(ByVal value As String) username = value End Set End Property Public WriteOnly Property Password() As String Set(ByVal value As String) password = value End Set End Property Public Property BinaryMode() As Boolean Get Return binarymode End Get Set(ByVal value As Boolean) binarymode = value End Set End Property Public Overloads Overrides ReadOnly Property RequestUri() As System.Uri Get Return uri End Get End Property ~295~
296 Public Overloads Overrides Property Method() As String Get Return method End Get Set(ByVal value As String) method = value End Set End Property Public Overloads Overrides Function GetResponse() As System.Net.WebResponse Dim response As FtpWebResponse = New FtpWebResponse(Me) Return response End Function End Class End Namespace - FtpWebResponse ويستخدم لعملية الرد من قبل الServer ويتم تعريفھا كما يلي: using System; using System.IO; using System.Net; using System.Net.Socket; namespace FTP public class FtpWebResponse : WebResponse private FtpWebRequest request; private FtpClient client; internal FtpWebResponse(FtpWebRequest request) this.request = request; Imports System Imports System.IO Imports System.Net Imports System.Net.Socket Public Class FtpWebResponse Inherits WebResponse Private request As FtpWebRequest ~296~
297 Private client As FtpClient Friend Sub New(ByVal request As FtpWebRequest) Me.request = request End Sub End Class - FtpWebStream ويس تخدم لتعري ف ال Stream وال ذي س وف يس تخدم لعملي ة النق ل ويعرف بشكل مبدئي كما يلي: using System; using System.IO; using System.Net.Socket; namespace FTP internal class FtpWebStream : Stream private FtpWebResponse response; private NetworkStream datastream; public FtpWebStream(NetworkStream datastream, FtpWebResponse response) this.datastream = datastream; this.response = response; Imports System Imports System.IO Imports System.Net.Socket Namespace FTP Friend Class FtpWebStream Inherits Stream Private response As FtpWebResponse Private datastream As NetworkStream Public Sub New(ByVal datastream As NetworkStream, ByVal response As FtpWebResponse) Me.dataStream = datastream Me.response = response End Sub End Class End Namespace ~297~
298 رابعا : مثال تطبيقي لرفع ملف من جھاز Client إلى جھاز Server باستخدام الStream والSocket : ف ي ھ ذا الج زء س وف نق وم بإنش اء برن امجين Client / Server وبتعام ل م ع ال Stream Library سوف نقوم بتحوي ل المل ف إل ى Byte Array و إرس اله عب ر ال Stream باس تخدام الSocket وConnection TCP ولبرمجة الجزء الخاص باإلرسال أو الClient قم بإنشاء مشروع جديد كما في الشكل التالي : using System.IO; using System.Net; using System.Net.Socket; using System.Text; imports System.IO imports System.Net imports System.Net.Socket imports System.Text ~298~ سوف نستخدم Namespaces التالية : في الButton Send قم بكتابة الكود التالي : 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);
299 Try Dim filestream As Stream = File.OpenRead(textBox1.Text) Dim filebuffer(filestream.length) As Byte filestream.read(filebuffer, 0, CType(fileStream.Length, Integer)) Dim clientsocket As TcpClient = New TcpClient(textBox2.Text, 8880) Dim networkstream As NetworkStream = clientsocket.getstream networkstream.write(filebuffer, 0, filebuffer.getlength(0)) networkstream.close Catch ex As Exception Msgbox(ex.Message) End Try قمنا في البداية بق راءة المل ف ال ذي ن ود إرس اله وتخزين ه ب Stream Object وحت ى نس تطيع إرس اله عب ر ال Socket الب د م ن تحويل ه إل ى مص فوفة م ن الن وع Byte وقمن ا بتس ميته ب FileBuffer ثم تعبئته باستخدام الدالة Read والموجودة ضمن FileStream وبع د ذل ك قمن ا بإنش اء اتص ال م ع ال Server باس تخدام ال Connection TCP حي ث ت م إرس ال محتوي ات الFileBuffer إلى الServer باستخدام... NetworkStream Class ولبرمجة جزء Server وھو المسئول عن استقبال الملف وتخزينه قم بإنشاء مشروع جديد كم ا يظھر في الشكل التالي: using System.Threading; using System.Net; using System.Net.Socket; using System.Text; using System.IO; imports System.Threading imports System.Net imports System.Net.Socket imports System.Text imports System.IO سوف نستخدم ال Namespaces التالية : ~299~
300 ثم إضافة الMethod التالية وليكن اسمھا handlerthread وكما يلي : public void handlerthread() Socket handlersocket = (Socket)alSocket[alSocket.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; Public Sub handlerthread() Dim handlersocket As Socket = CType(alSocket(alSocket.Count - 1), Socket) Dim networkstream As NetworkStream = New NetworkStream(handlerSocket) Dim thisread As Integer = 0 Dim blocksize As Integer = 1024 Dim databyte(blocksize) As Byte SyncLock Me Dim filestream As Stream = File.OpenWrite("c:\upload") While True thisread = networkstream.read(databyte, 0, blocksize) filestream.write(databyte, 0, thisread) If thisread = 0 Then ' break End If filestream.close() End While ~300~
301 lbconnections.items.add("file Written") handlersocket = Nothing End SyncLock End Sub ثم قم بكتاب ة دال ة أخ رى جدي دة وذل ك لف تح TCP Connection عل ى ال 8880 Port وھ و افتراضي والتصنت عليھا وليكن اسمھا listenerthread وكما يلي : public void listenerthread() TcpListener tcplistener = new TcpListener(8880); tcplistener.start(); while(true) Socket handlersocket = tcplistener.acceptsocket(); if (handlersocket.connected) lbconnections.items.add(handlersocket.remoteendpoint.tostri ng() + " connected."); lock (this) alsocket.add(handlersocket); ThreadStart thdsthandler = new ThreadStart(handlerThread); Thread thdhandler = new Thread(thdstHandler); thdhandler.start(); Public Sub listenerthread() Dim tcplistener As TcpListener = New TcpListener(8880) tcplistener.start() While True Dim handlersocket As Socket = tcplistener.acceptsocket If handlersocket.connected Then lbconnections.items.add(handlersocket.remoteendpoint.tostring + " connected.") SyncLock Me alsocket.add(handlersocket) End SyncLock Dim thdsthandler As ThreadStart = New ThreadStart(handlerThread) ~301~
302 Dim thdhandler As Thread = New Thread(thdstHandler) thdhandler.start() End If End While End Sub ثم قم بإضافة الكود التالي إلى حدث بدأ تشغيل البرنامج : Form Load 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(); alsocket = new ArrayList(); Thread thdlistener = new Thread(new ThreadStart(listenerThread)); thdlistener.start(); Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim IPHost As IPHostEntry = Dns.GetHostByName(Dns.GetHostName) lbconnections.text = "My IP address is " + IPHost.AddressList(0).ToString alsocket = New ArrayList Dim thdlistener As Thread = New Thread(New ThreadStart(listenerThread)) thdlistener.start() End Sub باس تخدام ال Thread ت م تنفي ذ ال listenerthread Method والت ي قمن ا فيھ ا بتعري ف الTcpListener وتفعيله على ال 8880 Port حيث سيتم قبول أي طلب يأتي م ن ال Client عل ى ھ ذا ال Port وبع د ذل ك اس تدعاء الدال ة handlerthread والت ي س يتم فيھ ا اس تقبال ال Data Stream وتخزينھ ا ف ي Byte Array ث م قراءتھ ا وتخزينھ ا ف ي المك ان المح دد وباستخدام الfileStream.Write حيث مررنا له الStream وال ذي يحت وي عل ى اس م المل ف. DataByte والArray thisread ~302~
303 خامسا استخدام ال Serialization وال FileStream Class إلرسال ملف من جھ از إل ى آخر: يمكننا االستفادة من ميزة الSerialization إلرسال اسم الملف مع محتوياته إذ يتم تخزين الملف على الطرف اآلخر بناءا على اسم الملف األصلي وسيكون الشكل العام للبرنامج كما يلي كمثال: أوال برنامج اإلرسال: وسنستخدم فيه ال FileStream Class لتحويل الملف المراد إرساله إلى Byte Array كما وسنستخدم الClass FileInfo لجلب اسم الملف وحتى يتم إرساله ك Serialization Object باستخدام الClass BinaryFormatter وتتم ھذه العملية كما يلي: C# string FileName;.. openfiledialog1.showdialog(); textbox1.text = openfiledialog1.filename; FileInfo TheFile = new FileInfo(textBox1.Text); // Get The File Name FileName = TheFile.Name;.. FileStream fs = new FileStream(textBox1.Text,FileMode.Open); byte[] buffer = new byte[fs.length]; int len = (int)fs.length; fs.read(buffer,0,len); fs.close(); BinaryFormatter br = new BinaryFormatter (); TcpClient myclient = new TcpClient (text_ip.text,7000); NetworkStream myns = myclient.getstream (); br.serialize (myns,filename); BinaryWriter mysw = new BinaryWriter (myns); mysw.write(buffer); mysw.close (); myns.close (); myclient.close (); Private FileName As String.. ~303~
304 openfiledialog1.showdialog() textbox1.text = openfiledialog1.filename Dim TheFile As FileInfo = New FileInfo(textBox1.Text) ' Get The File Name FileName = TheFile.Name.. Dim fs As FileStream = New FileStream(textBox1.Text,FileMode.Open) Dim buffer As Byte() = New Byte(fs.Length - 1) Dim len As Integer = CInt(fs.Length) fs.read(buffer,0,len) fs.close() 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,filename) Dim mysw As BinaryWriter = New BinaryWriter (myns) mysw.write(buffer) mysw.close () myns.close () myclient.close () NetworkStream myns; TcpListener mytcpl; Socket mysocket; Thread myth; BinaryReader bb; ~304~ ثانيا برنامج االستقبال: void File_Receiver() mytcpl = new TcpListener (7000); mytcpl.start (); mysocket = mytcpl.acceptsocket (); myns = new NetworkStream (mysocket); BinaryFormatter br = new BinaryFormatter (); Object op= br.deserialize (myns); // Deserialize the Object from Stream bb = new BinaryReader (myns); byte[] buffer = bb.readbytes(buffer_size); FileStream fss = new FileStream(@textBox1.Text + (string) op, FileMode.CreateNew, FileAccess.Write); fss.write(buffer,0,buffer.length); fss.close();
305 mytcpl.stop(); listbox1.items.add ("Successfully Saved to: " + textbox1.text + (string) op); if (mysocket.connected ==true) while (true) File_Receiver(); Private myns As NetworkStream Private mytcpl As TcpListener Private mysocket As Socket Private myth As Thread Private bb As BinaryReader Private Sub File_Receiver() 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 bb = New BinaryReader (myns) Dim buffer As Byte() = bb.readbytes(buffer_size) Dim fss As FileStream = New FileStream(textBox1.Text + CStr(op), FileMode.CreateNew, FileAccess.Write) fss.write(buffer,0,buffer.length) fss.close() mytcpl.stop() listbox1.items.add ("Successfully Saved to: " & textbox1.text + CStr(op)) If mysocket.connected =True Then Do While True File_Receiver() Loop End If End Sub وھك ذا بين ا طريق ة عم ل بروتوك ول ال FTP وط رق برمجت ه ف ي بيئ ة ال دوت ني ت س يتم الح ديث ف ي الج زء الت الي ع ن ط رق وأن واع التش فير واس تخدامھا ف ي ال etwork. Security Programming ~305~
306 Part 5 Network Security Programming Chapter18 Cryptography & Network Security Programming Chapter19 Socket Permissions ~306~
307 Chapter 18 Cryptography & etwork Security Programming - Cryptography in Dot Net: Symmetric Encryption DES (Data Encryption Standard) Asymmetric Encryption RSA (Rivest Shamir Adleman) Digital Signature Algorithms Hashing Algorithms Using Security Encryption Standards With Network Applications Create an Advanced RSA Client Server Chat System. ~307~
308 : etwork Security Programming : 18 تتلخص الفكرة من األمن بحماية البيانات من الدخول غبر المخول unauthorized Access باستخدام عدة أساليب وأھمھا : Data Encryption & Decryption التشفير وفك التشفير Authentications التحقق من ھوية الشخص مرسل الرسالة Set Policies & Permissions تحديد وتنفيذ السياسات و الصالحيات دعم ت ف ي ال دوت ني ت جمي ع أس اليب الحماي ة الت ي ذكرناھ ا س ابقا باس تخدام ال Security Namespaces والتي تحتوي على مجموعة ضخمة من المكتبات الفرعية وھي كما في الشكل التالي أوال : Overview : Cryptography amespace :Cryptography in. ET وھي المكتب ة الت ي تھ تم بك ل م ا يخ ص عملي ات تش فير وف ك تشفير البيانات من Clear Text إلى Cipher Text وبالعكس وتستخدم بشكل أساس ي لتش فير البيانات قبل عملية اإلرسال وفك تشفيرھا عند االستالم ونستطيع تقسيم طرق التشفير فيھا إلى ثالثة أقسام رئيسية ھي: :Symmetric algorithms A- األسلوب المتماثل وفيه يستخدم المفتاح السري ذاته لعملي ة التشفير وفك التشفير وھي طريقة سريعة إلجراء عملية التشفير وفك التش فير لكنھ ا ليس ت آمن ة كطريق ة الغي ر المتماثل ة ودعم ت ال دوت ني ت التش فير المتماث ل بمجموع ة م ن ال Classes Algorithms وھي: - الكالس الذي يدعم التشفير باستخدام ال : DES-Data Encryption Standard DESCryptoServiceProvider - الكالس الذي يدعم RC2CryptoServiceProvider : RC2 Algorithms - الكالس الذي يدعم RijndaelManaged : Rijndael Managed Algorithms الطريقة المعتادة في التشفير باألسلوب المتماثل ھي تش فير الرس الة وإرس الھا عب ر الش بكة لك ن باستخدام ھذه الطريقة فإن نسبة الخطأ التي قد تكون عالية جدا وقد نفقد بعض ھذه البيان ات مم ا يؤدي إلى فقد الرسالة أو قد تسرق وتجرى عليھا عمليات لمحاولة فك الشفرة ناھيك ع ن الحج م الھائل الت ي ق د تحج زه م ن ال Bandwidth Network..وت م ح ل ھ ذه المش كلة بجع ل عملي ة التش فير ت تم عل ى مس توى ال Stream نفس ه ويس تخدم لھ ذه العملي ة ال CryptoStream Class حي ث ي تم اس تخدام مفت احين لتش فير مفت اح التش فير Encryption Kay ومفت اح لف ك التشفير IV Installation Victor Decryption ويشترط استخدام نفس المفتاحين في عملية التشفير وفك التشفير ويس تخدم الك الس الس ابق م ع ال MemoryStream أو FileStream حيث نمرر له الData Stream ون وع التش فير س واء DES أو TripleDES أو RC2 وم ن الحلول األخرى استخدام التشفير على مستوى ال Socket حيث يتم تشفير القناة نفس ھا ويس مى ~308~
309 ھذا النوع ال SSL Socket Secure Layer وھ و م ن أش ھر أن واع التش فير ال ذي يس تخدم ف ي اإلنترن ت بش كل خ اص وخاص ة ف ي إج راء العملي ات البنكي ة وكمث ال س وف نس تخدم ال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); Dim Key As Byte() = &H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16 Dim IV As Byte() = &H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16 Dim phrase As String = msg.text Dim ms As MemoryStream = New MemoryStream() Dim tdes As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider() Dim csw As CryptoStream = New CryptoStream(ms, tdes.createencryptor(key, IV), CryptoStreamMode.Write) csw.write(encoding.ascii.getbytes(phrase), 0, phrase.length) csw.flushfinalblock() Dim cryptdata As Byte() = ms.getbuffer() textbox1.text=encoding.ascii.getstring(cryptdata, 0, CInt(ms.Length)) ~309~
310 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; Dim Keyy As Byte() = &H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16 Dim IVv As Byte() = &H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16 ms.position = 0 Dim data As Byte() = New Byte(1023) Dim csr As CryptoStream = New CryptoStream(ms, tdes.createdecryptor(keyy, IVv), CryptoStreamMode.Read) Dim recv As Integer = csr.read(data, 0, data.length) Dim newphrase As String = Encoding.ASCII.GetString(data, 0, recv) textbox1.text=newphrase :Asymmetric algorithms B- األس لوب الغي ر متماث ل وھ و أكث ر أمان ا م ن األس لوب المتماث ل إذ تش فر البيان ات باس تخدام مفت اح ع ام Public Kay ولف ك التش فير يس تخدم مفت اح خ اص Private Kay ويك ون ھن اك عالق ة ب ين المفت احين ويس تخدم 128 Bits لتش فير وھ و أفضل أساليب التشفير للبيانات ودعم ت ال دوت ني ت التش فير الغي ر متماث ل وال ذي ي دعم تش فير المفتاح الخاص Private Kay باستخدام Tow Algorithms Classes وھي: 1- RSACryptoServiceProvider 2- DSACryptoServiceProvider for Digital Signature Algorithm أوال: :RSACryptoServiceProvider ويستخدم في إجراء التشفير وفك التشفير الغير متماثل وھو non inherited Class في البداية سوف ننشئ instance جدي د م ن ال RSACryptoServiceProvider وذل ك لتولي د المفت اح الع ام والخ اص ونرف ق المفت اح الع ام م ع الرس الة وم ن ث م يق وم المس تلم بف ك الرس الة باس تخدام المفتاح الخاص الحظ الشكل التالي: ~310~
311 سنقوم اآلن بإنشاء مشروع تشفير وفك تشفير يستخدم طريقة الAlgorithm RSA س يكون الشكل العام للبرنامج كما يلي: س نقوم بالبداي ة بإنش اء Tow Methods األول ى نم رر لھ ا ال Message String Plain والPrivateKay وذلك لتشفير الرسالة بناءا علي ه وأخ رى لف ك التش فير ونم رر لھ ا الرس الة المش فرة ك Byte Array والمفت اح الخ اص ك String وسنس تخدم ال Class RSACryptoServiceProvider لتش فير الرس الة باس تخدام ال RSAAlgorithms ونم رر ل ه ال Private Kay ك CspParameters Object وباس تخدام ال EncryptMethod وال DecryptMethod ض من الالClass RSACryptoServiceProvider نتمم عملي ة التش فير وف ك التش فير ونم رر لھ ا الرس الة الم راد تش فيرھا أو ف ك تش فيرھا باإلض افة إل ى قيم ة True أو False لتفعي ل طريق ة التش فير ك FOAEP وي دعم ھ ذا األس لوب إص دارات ال Windows XP وم ا بع دھا ل ذلك يفضل اختيار False دائما ولضمان التوافقية مع اإلصدارات األقدم من نظام التشغيل... ~311~
312 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; 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 والس تخدام ال Methods الس ابقة يج ب أوال إنش اء Instance Object م ن ال Class CspParameters ق م نم رر المفت اح الع ام إل ى ال KeyContainerName Proparity ضمن ال Instance Object الخاص بالClass CspParameters وكما يلي: public byte[] mymsg; لتشفير// Try CspParameters cp = new CspParameters(); cp.keycontainername = text_private.text; ~312~
313 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); 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 الحظ أن من الفروق بين استخدام أسلوب التشفير ال RSA والDES ھي إمكانية الRSA م ن استخدام مفتاحين كما يختلف مفتاح التشفير ع ن مفت اح ف ك التش فير وحت ى ل و اس تخدمنا نف س المفتاح لعملية التشفير فإن ناتج التشفير س يختلف عن د ك ل م رة نس تخدم فيھ ا نف س المفت اح ف ي حين يبقى الناتج في ال DES كما ھ و وم ن االس تخدامات األخ رى لل RSA Algorithms الSignature Digital وھو ما سنبينه في الجزء التالي من ھذا الفصل. ~313~
314 ثانيا: DSACryptoServiceProvider for Digital Signature Algorithm التواقيع الرقمية :والھدف منھا التحقق من ھوية الشخص مرس ل الرس الة وكمث ال يق وم المرس ل بتوليد ملخص لرسالة باس تخدام ال Function Hash وبع د ذل ك يق وم بتش فير ملخ ص الرس الة الذي تم توليده لتكوين المفتاح الخاص والذي سيستخدم كتوقيع رقمي للمرسل ث م يرس ل المفت اح العام م ع الرس الة أم ا بم ا يتعل ق بالمس تلم فيق وم بف ك تش فير الملخ ص باس تخدام المفت اح الع ام ويجب أن يتم ذلك باستخدام نفس الخوارزمية التي اتبعھا المرسل في تشفير الملخص فإذا ك ان ملخص الرسالة التي ولدھا المستلم ھي نفسھا التي ولدھا المرسل عندھا يتحقق من أن الش خص مرسل الرسالة ھو نفسه. ف ي البداي ة س وف ننش ئ instance م ن ال DSACryptoServiceProvider لتولي د المفت اح الع ام والخ اص ث م نك ون ال Value Hash sign ونخزن ه ف ي Byte Array ولفحص ه نول د hash sign value جدي د ونقارن ه بالس ابق ف إذا تش ابھا عن دھا نق رر أن الش خص ھ و نفس ه ص احب الرس الة المرس لة س نقوم اآلن بإنش اء مش روع نس تخدم في ه ال DSACryptoServiceProvider لتولي د تواقي ع رقمي ة ث م إج راء عملي ة التحق ق علي ه وسيكون الشكل العام للبرنامج كما في الشكل التالي: س نقوم بإنش اء Four Methods ال GetHash لتولي د ال Hash Code لتوقي ع الرقم ي وس يأخذ String Message وس يرجع ال Hash Code ك Byte Array وسيس تخدم ال Method ComputeHash م ن ال MD5CryptoServiceProvider Instance Object لتولي د ال Hash Code الس ابق ال method VerifyHash ونس تطيع م ن خاللھ ا المقارن ة ب ين ال Message المرس لة وال Hash Code المول د م ن الرس الة لتأك د م ن ص حة تطابق النص مع ال Hash المولد ال CreateSignature Method وستستخدم لتوليد توقيع رقمي من الCode Hash الممرر حيث سنستخدم ال RSAPKCS1SignatureFormatter Hash وال RSACryptoServiceProvider Instance ال Object ل ه ونم رر Class gorithm وباس تخدام ال Method CreateSignature س نولد التوقي ع الرقم ي الMethod VerifySignature وستستخدم للمقارنة ب ين ال Hash Code والتوقي ع الرقم ي المولد فإذا تطابق يرجع قيمة True والعكس يرجع False ويتم كل ذلك كما يلي: using System; using System.Security.Cryptography; using System.Text; public class MD5HashHelper public byte[] GetHash(string message) ~314~
315 byte[] data; data = UTF8Encoding.ASCII.GetBytes(message); MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); return md5.computehash(data, 0, data.length); public bool VerifyHash(string message, byte[] hash) byte[] data; data = UTF8Encoding.ASCII.GetBytes(message); MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); byte[] hashtemp = md5.computehash(data, 0, data.length); for (Int32 counter = 0; counter <= hash.length - 1; counter += 1) if (hash[counter]!= hashtemp[counter]) return false; return true; public class DigitalSignatureHelper private RSAParameters m_public; public byte[] CreateSignature(byte[] hash) RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(RSA); RSAFormatter.SetHashAlgorithm("MD5"); m_public = RSA.ExportParameters(false); return RSAFormatter.CreateSignature(hash); public bool VerifySignature(byte[] hash, byte[] signedhash) RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSAParameters RSAKeyInfo = new RSAParameters(); RSAKeyInfo.Modulus = m_public.modulus; RSAKeyInfo.Exponent = m_public.exponent; ~315~
316 RSA.ImportParameters(RSAKeyInfo); RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(RSA); RSADeformatter.SetHashAlgorithm("MD5"); return RSADeformatter.VerifySignature(hash, signedhash); Imports System Imports System.Security.Cryptography Imports System.Text Public Class MD5HashHelper Public Function GetHash(ByVal message As String) As Byte() Dim data As Byte() data = UTF8Encoding.ASCII.GetBytes(message) Dim md5 As MD5CryptoServiceProvider = New MD5CryptoServiceProvider Return md5.computehash(data, 0, data.length) End Function Public Function VerifyHash(ByVal message As String, ByVal hash As Byte()) As Boolean Dim data As Byte() data = UTF8Encoding.ASCII.GetBytes(message) Dim md5 As MD5CryptoServiceProvider = New MD5CryptoServiceProvider Dim hashtemp As Byte() = md5.computehash(data, 0, data.length) Dim counter As Int32 = 0 Do While counter <= hash.length - 1 If hash(counter) <> hashtemp(counter) Then Return False End If counter += 1 Loop Return True End Function End Class Public Class DigitalSignatureHelper Private m_public As RSAParameters Public Function CreateSignature(ByVal hash As Byte()) As Byte() Dim RSA As RSACryptoServiceProvider = New RSACryptoServiceProvider ~316~
317 Dim RSAFormatter As RSAPKCS1SignatureFormatter = New RSAPKCS1SignatureFormatter(RSA) RSAFormatter.SetHashAlgorithm("MD5") m_public = RSA.ExportParameters(False) Return RSAFormatter.CreateSignature(hash) End Function Public Function VerifySignature(ByVal hash As Byte(), ByVal signedhash As Byte()) As Boolean Dim RSA As RSACryptoServiceProvider = New RSACryptoServiceProvider Dim RSAKeyInfo As RSAParameters = New RSAParameters RSAKeyInfo.Modulus = m_public.modulus RSAKeyInfo.Exponent = m_public.exponent RSA.ImportParameters(RSAKeyInfo) Dim RSADeformatter As RSAPKCS1SignatureDeformatter = New RSAPKCS1SignatureDeformatter(RSA) RSADeformatter.SetHashAlgorithm("MD5") Return RSADeformatter.VerifySignature(hash, signedhash) End Function End Class وإلستخدام ال Methods السابقة: DigitalSignatureHelper ds = new DigitalSignatureHelper(); byte[] hash1; byte[] hash2; byte[] signedhash;... توليد التوقيع الرقمي // try MD5HashHelper md5 = new MD5HashHelper(); hash1 = md5.gethash(textbox1.text); signedhash = ds.createsignature(hash1); MessageBox.Show("Signature Created Successfully!"); catch(exception ex)messagebox.show(ex.message);... لتأكد من صحة التوقيع // try MD5HashHelper md5 = new MD5HashHelper(); ~317~
318 hash2 = md5.gethash(textbox2.text); if (ds.verifysignature(hash2, signedhash)) MessageBox.Show("Signatures verified Successfully!"); else MessageBox.Show("Signatures verification failed!"); catch(exception ex)messagebox.show(ex.message); Dim ds As DigitalSignatureHelper = New DigitalSignatureHelper() Dim hash1 As Byte() Dim hash2 As Byte() Dim signedhash As Byte()... توليد التوقيع الرقمي ' Try Dim md5 As MD5HashHelper = New MD5HashHelper() hash1 = md5.gethash(textbox1.text) signedhash = ds.createsignature(hash1) MessageBox.Show("Signature Created Successfully!") Catch ex As Exception MessageBox.Show(ex.Message) End Try... لتأكد من صحة التوقيع' Try Dim md5 As MD5HashHelper = New MD5HashHelper() hash2 = md5.gethash(textbox2.text) If ds.verifysignature(hash2, signedhash) Then MessageBox.Show("Signatures verified Successfully!") Else MessageBox.Show("Signatures verification failed!") End If Catch ex As Exception MessageBox.Show(ex.Message) End Try ~318~
319 وھك ذا بين ا كيفي ة إنش اء برن امج لتولي د ال Digital Signature Algorithms باس تخدام الRSA سنبين في الجزء التالي من ھذا الفص ل ان واع ال Hash Algorithms واس تخدامھا في بيئة الدوت نيت. ثالثا- :Hashing algorithms ويعتبر من األساليب القوية جدا لتشفير البيانات إذ يمكننا من استخدام algorithm تصل إلى 512 bits بدال من 128 bits وذلك باس تخدام ال Message MAC Digest Algorithms وھن ا ل ن تس تطيع ف ك تش فير الرس الة وإرجاعھ ا إل ى حالتھ ا السابقة ويس تخدم بش كل أساس ي لتولي د ال Passwords وف ي تولي د التواقي ع الرقمي ة Digital في ال Database Password وفي اغلب الحاالت تستخدم لتخزين كلمة المرور Signature بشكل امن. ويستخدم الSHA1Managed والSHA256ManagedوالSHA384Managed والSHA512Managed لتعريف Hash Object ومنه نستخدم ال ComputeHash Method لتوليد الcode hash وتخزينه في 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)); ~319~
320 Dim sham1 As SHA1Managed = New SHA1Managed Dim my_kay1 As Byte() = ASCIIEncoding.ASCII.GetBytes("convert this text to hash code") Dim hashed_kay1 As Byte() = sham1.computehash(my_kay1) Msgbox(ASCIIEncoding.ASCII.GetString(hashed_kay1)) Dim sham2 As SHA256Managed = New SHA256Managed Dim my_kay2 As Byte() = ASCIIEncoding.ASCII.GetBytes("convert this text to hash code") Dim hashed_kay2 As Byte() = sham2.computehash(my_kay2) Msgbox(ASCIIEncoding.ASCII.GetString(hashed_kay2)) Dim sham3 As SHA384Managed = New SHA384Managed Dim my_kay3 As Byte() = ASCIIEncoding.ASCII.GetBytes("convert this text to hash code") Dim hashed_kay3 As Byte() = sham3.computehash(my_kay3) Msgbox(ASCIIEncoding.ASCII.GetString(hashed_kay3)) Dim sham4 As SHA512Managed = New SHA512Managed Dim my_kay4 As Byte() = ASCIIEncoding.ASCII.GetBytes("convert this text to hash code") Dim hashed_kay4 As Byte() = sham4.computehash(my_kay4) Msgbox(ASCIIEncoding.ASCII.GetString(hashed_kay4)) ويمكن استخدام الطريقة السابقة للمقارنة بين ال... Hash Codes سنبين في الجزء التالي من ھذا الفصل كيفية استخدام معايير التشفير في برمجيات الشبكات... Using Security Encryption Standards With etwork - C :Applications ف ي برمجي ات الش بكات نق وم ف ي البداي ة بتش فير البيان ات المرس لة باس تخدام أي م ن األس اليب الس ابقة لتش فير ث م نح ول البيان ات المش فرة إل ى Stream إلرس الھا عب ر ال Socket باس تخدام ال Stream Network كمث ال ث م يق وم الط رف المس تقبل باس تقبال الرس الة باس تخدام ال Stream Network عب ر ال Socket ويج ب أن تك ون عملي ة ف ك التش فير كم ا ھ ي الخوارزمية المس تخدمة إثن اء التش فير س واء RSA أو DES أو التواقي ع الرقمي ة ث م نس تطيع تحم ل الرس الة إل ى ال stream Memory حي ث ستس تقبل الرس الة ك Data Stream وبع د ذلك يمكن تحويلھا إلى Byte Array لفك تش فيرھا لتحويلھ ا إل ى رس الة م رة أخ رى الح ظ الشكل التالي: ~320~
321 سنقوم اآلن بإنشاء برنامج بسيط Server) (Client / إلرسال نص من جھاز إلى آخر وسنخدم في ه ال RSA لتش فير ال نص المرس ل حي ث س يتفق الطرف ان عل ى ال Private Kay وال ذي سيستخدم لتشفير و فك تشفير الرسالة... و س يكون الش كل الع ام للبرن امج كم ا ف ي الش كل الت الي ويب ين طرف ان مرس ل ومس تقبل ويق وم المرسل بتشفير الرسالة باستخدام المفتاح العام ويتفق الطرفان على المفتاح الخاص والذي س يتم فك الرسالة من خالله: أوال المرسل أو ال : Client وسنستخدم فيه الطريقة المعروفة لتشفير الرسائل باستخدام ال RSA algorithms حي ث س يتم تحويل الرسالة المشفرة إلى Byte Array وسنستخدم ال Serialization إلرسالھا حيث س يتم إرسالھا ك Serialization Object ويتم كل ذلك كما يلي: ~321~
322 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); ~322~
323 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 ثانيا المستقبل أو ال : Server وفي طرف المستقبل ال Server يتم اس تقبال ال Encrypted Message as an Object ث م تحول إلى Byte Array بعد عمل ال Casting عليھا ومن ثم نمرر ال Byte Array المستلم إلى ال RSA Decryption Method لي تم ف ك تش فيرھا باس تخدام المفت اح الخ اص وال ذي ت م االتفاق عليه. ~323~
324 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(); ~324~
325 ... فك تشفير الرسالة // 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); 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... استقبال الرسالة بشكل مشفر ' RSA_Server() Private Sub mytcpl = New TcpListener(7000) ~325~
326 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 وھكذا بينا في ھذا الفصل كيفية التعامل م ع ال Cryptography إلج راء عملي ات التش فير على ال Data المرسلة عبر الشبكة كما بينا طرق استخدام معاير التشفير مثل ال DES و الHashing والRSA وال Digital Signature في بيئة الدوت نيت سيتم الح ديث ف ي الفصل التالي عن ال Socket Permission واس تخدامھا ف ي بيئ ة ال دوت ني ت وبرمجي ات الشبكات. ~326~
327 Chapter 19 Socket Permissions - Permission Namespace Overview - Security Action - Socket Access property - Socket Permissions ~327~
328 : Permission amespace Overview : 19 وتدعم الNamespace Permission في الدوت نيت ثالث ة أن واع م ن الص الحيات وھ ي ال Role- based وال Identity وال Permissions Code access permissions...permissions تطبق ال Code access permissions على كل من الClasses التالية: WebPermission: The ability to make/accept connection to/from the web. OleDbPermission: The ability to access databases with OLEDB. SQLClientPermission: The ability to access SQL databases. UIPermission: The ability to use User Interface. PrintingPermission: The ability to print. FileIOPermission: The ability to work with files. SocketPermission: The ability to make/accept TCP/IP connections on a transport address. SecurityPermission: The ability to execute, assert permissions, call into unmanaged code, skip verification and other rights. وتطبق الpermissions Identity على ال Classes التالية: PublisherIdentityPermission: Software publisher's digital signature Strong ameidentitypermission: Assembly's strong Name URLIdentityPermission: URL from which the code is originated ZoneIdentityPermission: Zone from which the assembly is originated SiteIdentityPermission: Location of web site from which the code is originated وتطبق ال Role- based permissions على ال PrincipalPermission Class فقط. :Socket Permission وتمكن ك م ن تحدي د ص الحيات اس تخدام ال Socket ف ي برمجي ات الش بكات باس تخدام SocketPermission و SocketPermissionAttribute ض من ال System.Net وال Namespaces System.Security.Permissions وكمث ال نس تطيع منع Client Host Address معين من االتصال مع الApplication Listener ويتم ذلك بتعري ف SocketPermission Attribute نح دد فيھ ا ن وع العملي ة وال Kind Access و عنوان الHost الذي سيطبق عليه الPermission ورقم ال Port ون وع ال Transport س واء موجه أو غير موجه TCP أو.UDP نريد في ھذا المثال منع اتصال الAddress loopback بالSocket عبر جميع الPorts وبغض النظر عن نوع الSocket المستخدم. [SocketPermission(SecurityAction.Deny, Access="Connect", Host=" ",Port="All", Transport="All")] ~328~
329 يمكننا الobject SecurityAction من تحديد نوع العملية التي نريدھا وكما يلي: :Assert وتعني السماح Client Host معين من إجراء عملية محددة ال Stack منطق ة ف ي تق ع التي وتعني تطبيق الصالحيات على جميع الClasses :Demand أعلى الAbstract Defined :Deny وتعني منع الHost Client من إجراء عملية معينة. ال Class س يرث ال ذي ال Class عل ى وفيھا تطبق الص الحيات : InheritanceDemand الحالي. :PermitOnly وفيه يمنع جميع الAccess عدا الUser Client المحدد... وفي الproperty Access نحدد نوع عملية المنع أو السماح وتأخذ خيارين ھما : Accept لمن ع أو الس ماح ل Client Socket م ن عم ل Binding م ع ال Address IP و الPort المحدد. Remote ال Host م ع connect عم ل م ن Client Socket لمنع أو السماح ل Connect المحدد. في الHost والPort نحدد عنوان الHost الذي سيطبق عليه الPermission و رقم الPort التي يتصل بھا ) في الproperty Port نستطيع تمرير كلمة all لداللة على تطبيق الصالحية على جميع الPorts ( وأخيرا نحدد الproperty Transport والتي سنعرف فيھ ا ن وع ال Socket المس تخدم وتأخ ذ الخيارات التالية: Socket ال جمي ع عل ى ال Permission ھ ذه تطب ق إذ ال Socket ن وع تحدي د ب دون All.Types Connectionless إذا كان ت ال Socket تس تخدم Datagram Protocols وكمث ال بروتوكول.UDP ConnectionOriented إذا كان ت ال Socket تس تخدم Oriented Protocols وكمث ال بروتوكول.TCP TCP إذ تستطيع تحديده مباشرة. UDP إذ تستطيع تحديده مباشرة. ويمكن أيض ا اس تخدام ال Socket Permission م ن خ الل اش تقاق Instance Object م ن ال Class SocketPermission ث م تحدي د ن وع ال Permission الم راد وض عه ويمكن ك أن تمرر له إما ال Permission State وذلك لسماح أو من ع ال Permission المح دد أو تمري ر ال Permission الذي تريد من خالل تحديد ال Network Access سواء اتصال Connect ~329~
330 Outgoing أو Accept Incoming ث م تحدي د ن وع البروتوك ول المس تخدم س واء TCP أو UDP أو االثن ين مع ا وبع د ذل ك نم رر ال IP Address لل Remote Machine ف ي حال ة الس ماح أو المن ع لل Access incoming أو ال IP لل Local Machine ف ي حال ة ال Connect Outgoing ويتم ذلك كما يلي: كما ويمك ن إس ناد ال Socket State لل Class SocketPermission إذ نح دد ل ه ال State سواء بسماح أو رفض االتصال وكما يلي: كما يمكن دمج أكثر من Socket Permission وذلك باستخدام ال Union Method وبع د ذلك تسند إلى SocketPermission Object جديد وكما يلي كمثال: SocketPermission mysocketpermission1= new SocketPermission(PermissionState.None); mysocketpermission1.addpermission(networkaccess.accept, TransportType.Tcp, IP, Port); SocketPermission mysocketpermission2 =new SocketPermission(NetworkAccess.Connect, TransportType.Tcp, IP, Port); SocketPermission mysocketpermissionunion = (SocketPermission)mySocketPermission1.Union(mySocketPermission2 ); Dim mysocketpermission1 As SocketPermission = New SocketPermission(PermissionState.None) mysocketpermission1.addpermission(networkaccess.accept, TransportType.Tcp, IP, Port) Dim mysocketpermission2 As SocketPermission = New SocketPermission(NetworkAccess.Connect, TransportType.Tcp, IP, Port) ~330~
331 Dim mysocketpermissionunion As SocketPermission = CType(mySocketPermission1.Union(mySocketPermission2), SocketPermission) كما يمكن أيضا دمج أكثر من Union Permission List وذلك باستخدام ال Intersect Method وكما يلي: SocketPermission mysocketpermissionintersect = (SocketPermission)mySocketPermission1.Intersect(mySocketPermissio nunion); Dim mysocketpermissionintersect As SocketPermission = CType(mySocketPermission1.Intersect(mySocketPermissionUnion), SocketPermission) ونس تطيع أيض ا نق ل ال Permission List الس ابقة إل ى XML Data ويمك ن تحويلھ ا م ن XML إلى Permission List مرة أخرى وذلك باستخدام ال FromXml Method للقراءة من XML وال ToXml Method لتحويل الPermission إلى XML وكما يلي كمثال: mysocketpermission1.fromxml(mysocketpermission1.toxml()); mysocketpermission1.fromxml(mysocketpermission1.toxml()); ونستطيع تطبيق ال Security Permissions باختيار واحدة من Deny) :(Assert,PermitOnly SocketPermission sp = new SocketPermission(PermissionState.None); sp.addpermission(networkaccess.accept,transporttype.tcp," ",0); sp.addpermission(networkaccess.connect,transporttype.tcp," ",0) المنع // sp.deny; // السماح//; sp.assert // sp.permitonly(); Dim sp As SocketPermission = New SocketPermission(PermissionState.None) sp.addpermission(networkaccess.accept,transporttype.tcp," ",0) sp.addpermission(networkaccess.connect,transporttype.tcp," ",0) ~331~
332 المنع // sp.deny; ' السماح//; sp.assert ' sp.permitonly() سنقوم اآلن بتطبيق مثال بسيط نستخدم فيه ال Socket Permissions لمنع االتص ال م ن قب ل بروتوكول ما أو السماح لل Client باالتصال أو منعه فك رة البرن امج تكم ن ف ي نق ل ص ورة الكاميرا من جھاز ال Client إلى الServer باستخدام ال Socket وم ن ث م وض ع ص الحيات لالتصال مع ال... Server أوال برنامج ال : Server ويحتوي على Picturebox كما في الشكل التالي: void StartMethod () TcpListener mytcpl; Socket mysocket; NetworkStream myns; SocketPermission sp = new SocketPermission(PermissionState.None); sp.addpermission(networkaccess.accept,transporttype.tcp," ",0); sp.addpermission(networkaccess.connect,transporttype.tcp," ",0); // الرفض // sp.deny; // السماح//; spassert sp.permitonly(); mytcpl = new TcpListener (5020); mytcpl.start (); mysocket = mytcpl.acceptsocket (); myns = new NetworkStream (mysocket); picturebox1.image = Image.FromStream(myns); mytcpl.stop(); ~332~
333 if (mysocket.connected ==true) while (true) StartMethod (); Private Sub StartMethod() Dim mytcpl As TcpListener Dim mysocket As Socket Dim myns As NetworkStream Dim sp As SocketPermission = New SocketPermission(PermissionState.None) sp.addpermission(networkaccess.accept, TransportType.Tcp, " ", 5020) sp.addpermission(networkaccess.connect, TransportType.Tcp, " ", 5020) الرفض // sp.deny; ' السماح//; spassert ' sp.permitonly() mytcpl = New TcpListener(5020) mytcpl.start() mysocket = mytcpl.acceptsocket() myns = New NetworkStream(mysocket) picturebox1.image = Image.FromStream(myns) mytcpl.stop() If mysocket.connected = True Then Do While True StartMethod() Loop End If End Sub ~333~
334 ثانيا برنامج ال : Client private void timer1_tick(object sender, System.EventArgs e) try MemoryStream ms = new MemoryStream();// Store it in Binary Array as Stream picturebox1.image.save(ms,system.drawing.imaging.imageformat.jp eg); byte[] arrimage = ms.getbuffer(); ms.close(); TcpClient myclient = new TcpClient (txt_host.text,int.parse(text_port.text));//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)timer1.enabled=false; listbox1.items.add(ex.message ); Private Sub timer1_tick(byval sender As Object, ByVal e As System.EventArgs) Try Dim ms As MemoryStream = New MemoryStream ' Store it in Binary Array as Stream picturebox1.image.save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) Dim arrimage As Byte() = ms.getbuffer() ms.close() Dim myclient As TcpClient = New TcpClient(txt_host.Text, Integer.Parse(text_Port.Text)) 'Connecting with server Dim myns As NetworkStream = myclient.getstream() ~334~
335 Dim mysw As BinaryWriter = New BinaryWriter(myns) mysw.write(arrimage) 'send the stream to above address mysw.close() myns.close() myclient.close() Catch ex As Exception timer1.enabled = False listbox1.items.add(ex.message) End Try الحظ أنه يمكنك االختيار بين وضع ال Permission Attribute أوالSocketPermission ويبقى الفرق بين استخدام أي منھا في حالة كنت تريد وضع الصالحيات إثناء التشغيل وتريد إمكانية تغيير ھذه الصالحيات إثناء Runtime فيفضل استخدام ال SocketPermission instance Object أما إذا أردت وضع الصالحيات بشكل دائم وبدون إمكانية تغيرھا وعلى مستوى ال Scope للبرنامج كامال عندھا يفضل استخدام الAttribute... وھكذا بينا طرق التعامل مع ال Socket Permission في بيئة الدوت ني ت س يتم الح ديث في الجزء التالي عن ال Multithreading واستخدامھا في بيئة الدوت نيت. ~335~
336 Part 6 Multithreading - Chapter 20 Multithreading (Using & Managing) ~336~
337 Chapter 20 Multithreading Using & Managing - Introduction to Threading in Dot Net - Threading Classes & Members - Multithreading & Network Applications ~337~
338 : The Concept of Threading : 20.1 عزز مفھوم ال Multithreading مفھوم ال Multitasking في أنظمة التشغيل بحي ث أن أي برنامج يمكنه أن يعمل على Thread منفص ل ع ن األخ ر باإلض افة إال إمكاني ة أن يعم ل نف س البرنامج على أكثر م ن Thread أت ى ھ ذا المفھ وم بع د تط وير فك رة ال Multitasking ف ي أنظمة التشغيل ويتم إدارة ھذه العمليات من قبل نظام التشغيل ال ذي يق وم بتقس يم المھ ام عل ى المعالج وفق األولويات لكل Thread وعلى فترات زمني ة ويمك ن مش اھدة ھ ذه العملي ات ف ي نظام التشغيل من خالل ال Task Manager وكما في الشكل التالي: الحظ أن كل برنامج يحجز مقدار معين من المعالج بناء على حاجته ويقوم نظام التشغيل بتقسيم المھام على المعالج وفق الحاجة و األولويات الحظ الشكل التالي: ~338~
339 وبتأكي د يمك ن ال تحكم ب أي Thread ف ي نظ ام التش غيل إذ يمكنن ا م ن عم ل Interrupt ل ه كم ا يمكنن ا إيقاف ه بش كل مؤق ت وأيض ا إلغائ ه بعم ل Abort ل ه ك ل ھ ذه العملي ات متاح ة ل دى الUser للقيام بھا وأيضا متاح استخدامھا برمجيا. : Threading in Dot et : 20.2 قمنا سابقا باستخدام ال Threading في برمجيات الش بكات والحظن ا ان ه ال يمك ن أن يس تقبل البرنامج أي شيء في حال ة كون ه يعم ل عل ى نف س ال Thread الخ اص بال Form مم ا يمن ع تنفيذ أي عملية أخرى إال بعد انتھاء العملي ة الجاري ة وھ و م ا ل ن يح دث أب دا إذ أنن ا اس تخدمنا Infinity Loop لبرن امج االس تقبال مم ا س يؤدي إل ى ع دم تنفي ذ أي أم ر آخ ر وس وف يتوق ف البرنامج عن االستجابة و الحل لھذه المشكلة االختيار بين أمرين : األول االبتع اد ع ن اس تخدام البرمج ة المتزامن ة Synchronous Programming و التوج ه نحو البرمجة غير المتزامنة Asynchronousوھو Programming ما تم ش رحه ف ي الج زء الخاص بال Streaming وال.Asynchronous Socket الث اني فص ل ال Infinity Loop ع ن ال Thread الخ اص بالبرن امج وجعل ه يعم ل عل ى Thread آخر منفصل وھذا ما يسمى بال Multithreading حيث سيتم تقسيم المعالجة على ال Thread الخاص بالبرنامج وال Thread الذي تم إنشائه الحظ الشكل التالي: وسيعمل في ھذه الحالة بشكل متوازي مع البرنامج وليس بشكل تسلسلي كما في السابق. ~339~
340 والس تخدام ال Threading ف ي ال دوت ني ت يج ب أوال تعري ف ال System.Threading Thread من ال Instance Object جديد نقوم باشتقاق Thread ولتعريف Namespaces Thread Start ال إل ى لھ ا Thread عم ل نري د الت ي Method ال اس م نم رر ث م Class Delegate يمكن عمل كل ذلك مباشرة وبخطوة واحدة كما يلي: Thread my_thread = new (new ThreadStart (my_method)); Dim my_thread As Thread = New (AddressOf my_method) الحظ انه يمكنك التحكم بجميع العمليات الت ي تخ ص ال Threading م ن خ الل ال Thread Object ال ذي ت م اش تقاقه وم ن أھ م ھ ذه العملي ات ال Start وال Stop والت ي تس تخدم لتفعي ل وإيقاف ال Thread وكما نستخدم ال Abort إللغاء ال Thread نھائيا من المعالجة. أوال : أھم ال Thread Class Methods Start وتستخدم لبدأ ال Thread في كل مرة يتم اس تدعائھا ي تم تنفي ذ Thread آخ ر ل نفس ال Method التي تم تمريرھا. Joinوتستخدم لتحكم بالفترة التي سيتم فيھا إنھاء ال Thread عند عمل Abort له. Suspend وتس تخدم إليق اف ال Thread الح الي بش كل مؤق ت وال نحص ل عل ى أي Exception في حالة كان الThread في وضع التوقف. Abort وتستخدم إليقاف ال Thread بشكل نھائي وإلغائه من الذاكرة ويفضل وض ع ھ ذه ال Method في الEvent Closing الخاص بالبرنامج لكي ال يبقى ال Thread في الذاكرة. Resume وتستخدم إلرجاع تنفيذ ال Thread بعد إيقافه بشكل مؤقت باستخدام ال. Suspend Sleep وتستخدم إليقاف ال Thread فترة زمنية معينة. ثانيا : أھم ال Thread Class Properties ame وتأخذ Get أو Set لتحديد أو معرفة اسم ال Thread ال ذي ت م انش ائھة والھ دف منھ ا تسھيل التعامل مع الMultithreads في البرنامج..Thread لتحديد أو معرفة اللغة المعرفة لھذا ال Set أو Get وتأخذ CurrentCulture CurrentUICulture وتأخذ Get لمعرفة اللغة المستخدمة في نظام التشغيل. IsAlive وتأخذ Get لمعرفة إذا كان ال Thread الحالي قيد التشغيل أم ال. ~340~
341 IsBackground وتأخذ Get أو Set لتحديد أو معرفة إذا كان ال Thread يعمل أو س يعمل في الProccess.Backgrount Pool queue يس تخدم Thread لمعرفة إذا كان ال Get وتأخذ IsThreadPoolThread لمجموعة من الThread أم ال. ManagedThreadId وتأخذ Get لمعرفة ال Unique ID الخاص بال Thread الحالي. Priority وتأخ ذ Get أو Set لتحدي د أو معرف ة األولوي ة لل Thread الح الي وف ي الوض ع الطبيعي تكون Normal ويمكن تغيرھا كما يلي: حيث يحدد فيھا مدى اھميتھا بالنسبة ألولوية المعالجة. ThreadState وتأخ ذ Get لمعرف ة حال ة ال Thread الح الي ھ ل ھ و يعم ل أم ال وترج ع. False أو True مثال بسيط ل Thread في الدوت نيت :First Thread Program in Dot Net سنقوم في البداية بتصميم New Form كما في الشكل التالي: إلنشاء Thread جديد : using System.Threading;.. Thread th;.. private void Start_New_Thread_Click(object sender, EventArgs e) th = new Thread(new ThreadStart(xx)); th.start(); Imports System.Threading.. Private th As Thread ~341~
342 .. Private Sub Start_New_Thread_Click(ByVal sender As Object, ByVal e As EventArgs) th = New Thread(AddressOf xx) th.start() End Sub th.suspend() th.abort() إليقاف ال Thread بشكل مؤقت: إليقاف ال Thread بشكل نھائي من الذاكرة: ويفض ل دائم ا وض ع ال Abort Method ع ن ال Closing Event للبرن امج بحي ث يق وم بإغالق ال Thread عند إطفاء البرنامج. listbox1.items.add(th.apartmentstate) listbox1.items.add(th.currentculture) listbox1.items.add(th.currentuiculture) listbox1.items.add(th.isalive) listbox1.items.add(th.isbackground) listbox1.items.add(th.isthreadpoolthread) listbox1.items.add(th.managedthreadid) listbox1.items.add(th.priority) listbox1.items.add(th.threadstate) لمعرفة كافة المعلومات عن ال Thread الحالي: وتحتوي ال Method على Infinity Loop يزيد ك ل م رة ال I بمق دار واح د ويطب ع النتيج ة على ال Form Text ويعتب ر اس تخدام ال Infinity Loop م ن أھ م م ا دعان ا إلس تخدام ال Thread في ھذه الحالة: void xx() int i = 0; while (true) i++; this.text = i.tostring(); Private Sub xx() Dim i As Integer = 0 Do While True i += 1 Me.Text = i.tostring() Loop End Sub ~342~
343 وسيكون ال Output للبرنامج كما في الشكل التالي: استخدام ال Multithreading في برمجيات الشبكات: ينصح باستخدام ال Multithreading ف ي برمجي ات الش بكات الت ي تعتم د البرمج ة المتزامن ة Synchronous Programming إذ أن طبيع ة التنفي ذ ف ي ھ ذه البرمجي ات متسلس لة وھ و م ا سوف يمنع من تنفيذ عمليات أخرى لحين االنتھ اء م ن العملي ة الجاري ة إذ أن ه وم ن المفض ل استخدام Thread منفصل لكل عملية قد تطرنا إل ى االنتظ ار فت رة طويل ة أو أن العملي ة س تبقى في وضع التنفيذ طيلة فترة تشغيل البرنامج. 1- استخدام ال Threading في برمجيات الزبون : Clients - اس تخدام دال ة ال ربط Connect ف ي االتص ال المت زامن: ف ي حال ة اس تخدام ال Connect Method وفي حالة كان الServer بطيء فإن عملية الموافقة ستأخذ بع ض الوق ت مم ا ي ؤدي إلى توقف البرنامج عن االس تجابة لح ين إتم ام عملي ة القب ول ويفض ل ف ي ھ ذه الحال ة اس تخدام Thread منفصل للقيام بعملية االتصال. - اس تخدام ال Client ف ي عملي ة اإلرس ال و االس تقبال المت زامن يفض ل ف ي حال ة اإلرس ال المت زامن ع دم اس تخدام Thread منفص ل لك ل عملي ة وخاص ة إذا ك ان الھ دف م ن البرن امج إرسال مجموع ة م ن التعليم ات المختلف ة إل ى نف س ال Server حي ث س يكون منش غل باس تقبال التعليمات التي تم يتم إرسالھا ويفضل في ھذه الحالة استخدام البرمجة غي ر المتزامن ة إذا ك ان اإلرسال ألكثر من تعليمة ولنفس الجھ ة أم ا ف ي حال ة االس تقبال المت زامن ف ال ب د م ن اس تخدام الThread ألن عدم استخدام ال Thread سيؤدي إلى توقف البرنامج عن االستجابة. ~343~
344 2- استخدام ال Threading في برمجيات الخادم : Server - استخدام دالة القبول AcceptSocket البد من استخدام Thread منفصل في حالة استخدام دالة القبول AcceptSocket في البرمجة المتزامنة إذ انه سيتوقف البرنامج عن اإلستجابة ف ي حال ة ع دم اس تخدام ال Thread م ع ال AcceptSocket حي ث توض ع ع ادة ف ي Infinity.Loop حالة خاصة: قد تضطر إلى اللجوء إلى البرمجة غير المتزامنة ف ي حال ة إذا ك ان ال Server سيس تقبل أكث ر من Client Reqouest في نفس الوقت مما سيؤدي إل ى قب ول أول طل ب ورف ض البقي ة وھ ذا امر غير فعال وخاصة إذا كان البرنامج سيعمل عل ى اإلنترن ت وأن ع دد ال Clients وأوق ات دخ ولھم غي ر معروف ة وف ي ھ ذه الحال ة الب د م ن اللج وء إل ى البرمج ة غي ر المتزامن ة asynchronous Programming إلتمام عملية القبول. مثال على استخدام ال Multithreading في برمجيات الشبكات المتزامنة: سوف ننشئ في ھذا المثال برنامجين Client/Server حيث يمكن لل Client إرسال Text و Tow Threads باستخدام Text الصور وال Server ال وسيستقبل إلى الServer Images يعمالن بشكل متوازي : أوال برنامج اإلرسال ال : Client void send(byte[] arrimage) try TcpClient myclient = new TcpClient (txt_host.text,5000); 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 ); void send(string msg) // overloading method ~344~
345 try TcpClient myclient = new TcpClient (txt_host.text,7000); NetworkStream myns = myclient.getstream (); StreamWriter mysw = new StreamWriter (myns); mysw.write(msg); mysw.close (); myns.close (); myclient.close (); catch (Exception ex)messagebox.show(ex.message ); Private Sub send(byval arrimage As Byte()) Try Dim myclient As TcpClient = New TcpClient (txt_host.text,5000) Dim myns As NetworkStream = myclient.getstream () Dim mysw As BinaryWriter = New BinaryWriter (myns) mysw.write(arrimage) mysw.close () myns.close () myclient.close () Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Private Sub send(byval msg As String) overloading method Try Dim myclient As TcpClient = New TcpClient (txt_host.text,7000) Dim myns As NetworkStream = myclient.getstream () Dim mysw As StreamWriter = New StreamWriter (myns) mysw.write(msg) mysw.close () myns.close () myclient.close () Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Thread myth1; ~345~ ثانيا برنامج اإلستقبال ال : Server
346 Thread myth2; private void Form1_Load(object sender, System.EventArgs e) myth1= new Thread (new System.Threading.ThreadStart(Image_Receiver)); myth1.start (); // Start Thread 1 myth2= new Thread (new System.Threading.ThreadStart(text_Receiver)); myth2.start ();// Start Thread 2 NetworkStream ns; TcpListener tcp; Socket sock; StreamReader sr; void text_receiver() tcp = new TcpListener (7000);// Open The Port tcp.start ();// Start Listening on That Port sock = tcp.acceptsocket ();// Accept Any Request From Client and Start a Session ns = new NetworkStream (sock);// Receives The Binary Data From Port sr = new StreamReader (ns);// Convert Received Data to String textbox1.text = sr.readline(); tcp.stop(); while (true) text_receiver();// Back to First Method NetworkStream myns; TcpListener mytcpl; Socket mysocket; void Image_Receiver() mytcpl = new TcpListener (5000);// Open The Port mytcpl.start ();// Start Listening on That Port mysocket = mytcpl.acceptsocket (); myns = new NetworkStream (mysocket); picturebox1.image = Image.FromStream(myns); mytcpl.stop(); if (mysocket.connected ==true)//if Connected Start Again ~346~
347 while (true) Image_Receiver();// Back to First Method Private myth1 As Thread Private myth2 As Thread Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) myth1 = New Thread(New System.Threading.ThreadStart(AddressOf Image_Receiver)) myth1.start() ' Start Thread 1 myth2 = New Thread(New System.Threading.ThreadStart(AddressOf text_receiver)) myth2.start() ' Start Thread 2 End Sub Private ns As NetworkStream Private tcp As TcpListener Private sock As Socket Private sr As StreamReader Private Sub text_receiver() tcp = New TcpListener(7000) ' Open The Port tcp.start() ' Start Listening on That Port sock = tcp.acceptsocket() ' Accept Any Request From Client and Start a Session ns = New NetworkStream(sock) ' Receives The Binary Data From Port sr = New StreamReader(ns) ' Convert Received Data to String textbox1.text = sr.readline() tcp.stop() Do While True text_receiver() ' Back to First Method Loop End Sub Private myns As NetworkStream Private mytcpl As TcpListener Private mysocket As Socket Private Sub Image_Receiver() mytcpl = New TcpListener(5000) ' Open The Port ~347~
348 mytcpl.start() ' Start Listening on That Port mysocket = mytcpl.acceptsocket() myns = New NetworkStream(mysocket) picturebox1.image = Image.FromStream(myns) mytcpl.stop() If mysocket.connected = True Then 'if Connected Start Again Do While True Image_Receiver() ' Back to First Method Loop End If End Sub ويجب اإلنتباه إلى أمر ھام في الAport Threading وھو إغالق كل ما له عالقة بالSocket مثل الTcplistener قبل إغالق الThread في حدث الClosing للForm... ~348~
349 Appendixes (A) - System. et amespace - System. et.socket amespace - Socket Option Members - System.Threading amespace - TAPI 2 Telephony Functions - Remoting TCP / HTTP Channels Members ~349~
350 1- System. et amespace Classes وتدعم ھذه ال amespace برمجة ال Application Layer و ال Transport Layer وال Web Protocols ومن اھم ھذه ال Classes واستخداماتھا: Class Authorization Cookie Dns EndPoint GlobalProxySelection HttpVersion HttpWebRequest HttpWebResponse IPAddress IPEndPoint IPHostEntry NetworkCredential SocketAddress SocketPermission WebClient WebException WebPermission Description Provides authentication messaging for a web server. Provides a set of properties and methods used to manage cookies. This class cannot be inherited. Simple domain name resolution functionality. Identifies a network address. This is an abstract class. Global default proxy instance for all HTTP requests. Defines the HTTP version numbers supported by the HttpWebRequest and HttpWebResponse classes. HTTP-specific implementation of the WebRequest class. HTTP-specific implementation of the WebResponse class. Internet Protocol (IP) address. A network endpoint consisting of an IP address and a port number. Container class for Internet host address information. Provides credentials for password-based authentication schemes such as basic, digest, NTLM, and Kerberos authentication. Stores serialized information from EndPointderived classes. Controls rights to make or accept socket connections. Provides common methods for sending data to and receiving data from a resource identified by a URI. The exception that is thrown when an error occurs while accessing resources via the HTTP protocol. Controls rights to access HTTP Internet ~350~
351 Class Description resources. WebPermissionAttribute Specifies permission to access Internet resources. WebProxy WebRequest WebResponse 2- System. et.socket amespace Classes Contains HTTP proxy settings for the WebRequest class. Makes a request to a Uniform Resource Identifier (URI). This class is abstract. Provides a response from a Uniform Resource Identifier (URI). This class is abstract. وتركز بشكل اساسي عل ى برمج ة ال Layer Transport وخاص ة TCP & UDP Socket Programming ومن اھم الClasses التي تدعمھا: Class LingerOption Description Contains information about the amount of time it will remain available after closing with the presence of pending data (the socket's linger time). MulticastOption Contains IP address values for IP multicast packets. NetworkStream Provides the underlying stream of data for network access. Socket Implements the Berkeley Socket interface. SocketException The exception that is thrown when a socket error occurs. TcpClient TcpListener UdpClient 3- Socket Options Class: Provides client connections for TCP network services. Listens for connections from TCP network clients. This is essentially the TCP server class. Provides User Datagram Protocol (UDP) network services. ويعتبر ھذا الكالس من ال Classes المھمة في برمجيات الشبكات وخاصة أنه يسمح لك بتعديل أي أمر له عالقة بعملية االتصال سواء على مستوى ال etwork Layer أو الLayer Transport أو حتى على مستوى ال Socket نفسه والصيغة العامة له كما يلي: ~351~
352 ويأخذ ثالثة باروميترات يحدد في األول مستوى ال Socket Option التي نريد إسناد ال Option إليھا ويحدد في الباروميتر الثاني نوعية ال Option التي نريد تفعيلھا أو منعھا أو تغيير في قيمھا ويأخذ الباروميتر األخير Object Value فإذا كانت العملية ھي السماح أو الرفض فتأخذ إما True أو False وإذا كانت تغيير أو تحديد قيم ما فتأخذ القيمة التي نريد تغييرھا ومن أھم ال Socket Option ame التالي: Member name AcceptConnection AddMembership AddSourceMembership BlockSource Broadcast BsdUrgent ChecksumCoverage Debug DontFragment DontLinger DontRoute DropMembership DropSourceMembership Error ExclusiveAddressUse Expedited Description Socket is listening. Add an IP group membership. Join a source group. Block data from a source. Permit sending broadcast messages on the socket. Use urgent data as defined in RFC This option can be set only once, and once set, cannot be turned off. Set or get UDP checksum coverage. Record debugging information. Do not fragment IP datagrams. Close socket gracefully without lingering. Do not route; send directly to interface addresses. Drop an IP group membership. Drop a source group. Get error status and clear. Enables a socket to be bound for exclusive access. Use expedited data as defined in ~352~
353 HeaderIncluded IPOptions IpTimeToLive KeepAlive Linger MaxConnections MulticastInterface MulticastLoopback MulticastTimeToLive ochecksum odelay OutOfBandInline PacketInformation ReceiveBuffer ReceiveLowWater ReceiveTimeout ReuseAddress SendBuffer SendLowWater RFC This option can be set only once, and once set, cannot be turned off. Indicates application is providing the IP header for outgoing datagrams. Specifies IP options to be inserted into outgoing datagrams. Set the IP header time-to-live field. Send keep-alives. Linger on close if unsent data is present. Maximum queue length that can be specified by Listen. Set the interface for outgoing multicast packets. IP multicast loopback. IP multicast time to live. Send UDP datagrams with checksum set to zero. Disables the Nagle algorithm for send coalescing. Receives out-of-band data in the normal data stream. Return information about received packets. Send low water mark. Receive low water mark. Receive time out. Allows the socket to be bound to an address that is already in use. Specifies the total per-socket buffer space reserved for sends. This is unrelated to the maximum message size or the size of a TCP window. Specifies the total per-socket buffer space reserved for receives. This is unrelated to the maximum message size or the size of a TCP window. ~353~
354 SendTimeout Type TypeOfService UnblockSource UseLoopback Send timeout. Get socket type. Change the IP header type of service field. Unblock a previously blocked source. Enable Or Disable a Loop Back Connection 4- System.Threading amespace Classes يستخدم الThreading لعمل Session منفصلة عن الsession المس تخدمة ف ي البرن امج وھ و أس لوب اخ ر لل Asynchronous وت دعم System.Threading مجموع ة م ن الClasses والتي تستخدم في ادارة عمليات الThreading وھي كما يلي: Class AutoResetEvent Interlocked ManualResetEvent Monitor Mutex ReaderWriterLock RegisteredWaitHandle Description This event notifies one or more waiting threads that an event has occurred. This class protects against errors by providing atomic operations for variables that are shared by multiple threads. This event occurs when notifying one or more waiting threads that an event has occurred. This class provides a mechanism that synchronizes access to objects. A synchronization primitive that grants exclusive access to a shared resource to only one thread. It can also be used for inter-process synchronization. This class defines a lock that allows single-writer and multiple-reader semantics. This class represents a handle that has been registered when calling the RegisterWaitForSingleObject() method. SynchronizationLockException This exception is thrown when a synchronized method is invoked from an unsynchronized block of code. Thread ThreadAbortException This class creates and controls a thread, sets its priority, and gets its status. This exception is thrown when a call is ~354~
355 Class ThreadExceptionEventArgs ThreadInterruptedException ThreadPool ThreadStateException Timeout Timer WaitHandle Description made to the Abort() method. This class provides data for the ThreadException event. This exception is thrown when a thread is interrupted while it is in a waiting state. This class provides a pool of threads that can be used to post work items, process asynchronous I/O, wait on behalf of other threads, and process timers. This is the exception that is thrown when a thread is in an invalid state for the method call. This class simply contains a constant integer used when we want to specify an infinite amount of time. This class provides a mechanism for executing methods at specified intervals. This class encapsulates operating system-specific objects that wait for exclusive access to shared resources. Public Method ame Abort() AllocateDataSlot() اھم الMethods التي تستخدم في ادارة الThreading في الدوت نيت : Description This overloaded method raises a ThreadAbortException in the thread on which it is invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread. This static method allocates an unnamed data slot on all the threads. AllocateNamedDataSlot() This static method allocates a named data slot on all threads. FreeNamedDataSlot() GetData() GetDomain() This static method frees a previously allocated named data slot. This static method retrieves the value from the specified slot on the current thread, within the current thread's current domain. This static method returns the current domain ~355~
356 Public Method ame GetDomainID() GetHashCode() GetNamedDataSlot() Interrupt() Join() ResetAbort() Resume() SetData() Sleep() SpinWait() Start() Suspend() Description in which the current thread is running. This static method returns a unique application domain identifier. This method serves as a hash function for a particular type, suitable for use in hashing algorithms and data structures like a hash table. This static method looks up a named data slot. This method interrupts a thread that is in the WaitSleepJoin thread state. This overloaded method blocks the calling thread until a thread terminates. This static method cancels an Abort() requested for the current thread. This method resumes a thread that has been suspended. This static method sets the data in the specified slot on the currently running thread, for that thread's current domain. This static and overloaded method blocks the current thread for the specified number of milliseconds. This static method causes a thread to wait the number of times defined by the iterations parameter. This method causes the operating system to change the state of the current instance to ThreadState.Running. This method will either suspend the thread, or if the thread is already suspended, has no effect. Public Property ame ApartmentState CurrentContext CurrentCulture Description ومن اھم الProperties الخاصة بالThreading : Sets or gets the apartment state of this thread. This static property gets the current context in which the thread is executing. Sets or gets the culture for the current thread. ~356~
357 Public Property ame CurrentPrincipal CurrentThread CurrentUICulture IsAlive IsBackground Description This static property sets or gets the thread's current principal. It is used for role-based security. This static property gets the currently running thread. Used at run time, this property sets or gets the current culture used by the Resource Manager to look up culture-specific resources. Gets a value that indicates the execution status of the current thread. Sets or gets a value that indicates whether a thread is a background thread or not. IsThreadPoolThread Gets a value indicating whether a thread is part of a thread pool. Name Priority ThreadState 5- TAPI 2 Telephony Functions: TAPI Initialization and Shutdown Sets or gets the name of the thread. Sets or gets a value that indicates the scheduling priority of a thread. Gets a value that contains the states of the current thread. Function lineinitializeex lineshutdown Description Initializes the TAPI line abstraction for use by the invoking application. Synchronous. API Example: public static extern int lineinitialize(ref int htapi, int hinst, LineCallBackDelegate fnptr,ref int szappname, ref int dwnumlines); Shuts down the application's use of TAPI's line abstraction. Synchronous. API Example: [DllImport("Tapi32.dll", SetLastError = true)] public static extern int lineshutdown(int hlineapp); Line Version egotiation Function Description ~357~
358 line egotiateapiversion Allows an application to negotiate a TAPI version to use. Synchronous. API Example: [DllImport("Tapi32.dll", SetLastError = true)]public static extern int linenegotiateapiversion(int htapi, int dwdeviceid, int dwapilowversion, int dwapihighversion, ref int lpdwapiversion, ref lineextensionid lpextensionid); Line Status and Capabilities Function linegetdevcaps linegetdevconfig linegetlinedevstatus linesetdevconfig Description Returns the capabilities of a given line device. Synchronous. API Example: [DllImport("Tapi32.dll", SetLastError = true)]public static extern int linegetdevcaps(int hlineapp, int dwdeviceid, int dwapiversion, int dwextversion,ref linedevcaps lplinedevcaps); Returns configuration of a media stream device. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetdevconfig(long dwdeviceid, ref VARSTRING lpdeviceconfig, string lpszdeviceclass); Returns current status of the specified open line device. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetlinedevstatus(long hline, ref LINEDEVSTATUS lplinedevstatus); Sets the configuration of the specified media stream device. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linesetdevconfig(long dwdeviceid, Any lpdeviceconfig, long dwsize, string lpszdeviceclass); ~358~
359 linesetstatusmessages linegetstatusmessages linegetid linegeticon lineconfigdialog Specifies the status changes for which the application needs to be notified. Synchronous. API Example: [DllImport("Tapi32.dll", SetLastError = true)] public static extern int linesetstatusmessages(int hline,int dwlinestates, int dwaddressstates); Returns the application's current line and address status message settings. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetstatusmessages(long hline, ref long lpdwlinestates, ref long lpdwaddressstates); Retrieves a device ID associated with the specified open line, address, or call. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetid(long hline, long dwaddressid, long hcall, long dwselect, ref VARSTRING lpdeviceid, string lpszdeviceclass); Allows an application to retrieve an icon for display to the user. Synchronous API Example: [DllImport("tapi32.dll")] static extern long linegeticon(long dwdeviceid, string lpszdeviceclass, ref long lphicon);. Causes the provider of the specified line device to display a dialog box that allows the user to configure parameters related to the line device. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long lineconfigdialog(long dwdeviceid, long hwndowner, string lpszdeviceclass); ~359~
360 lineconfigdialogedit Addresses Function linegetaddresscaps linegetaddressstatus linegetaddressid Displays a dialog box allowing the user to change configuration information for a line device. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long lineconfigdialogedit(long dwdeviceid, long hwndowner, string lpszdeviceclass, Any lpdeviceconfigin, long dwsize, ref VARSTRING lpdeviceconfigout); Description Returns the telephony capabilities of an address. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetaddresscaps(long hlineapp, long dwdeviceid, long dwaddressid, long dwapiversion, long dwextversion, ref LINEADDRESSCAPS lpaddresscaps); Returns current status of a specified address. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetaddressstatus(long hline, long dwaddressid, ref LINEADDRESSSTATUS lpaddressstatus); Retrieves the address ID of an address specified using an alternate format. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetaddressid(long hline, ref long lpdwaddressid, long dwaddressmode, string lpsaddress, long dwsize); Opening and Closing Line Devices Function lineopen Description Opens a specified line device for providing subsequent monitoring and/or control of the line. Synchronous. ~360~
361 API Example: [DllImport("Tapi32.dll", SetLastError = true)] public static extern int lineopen(int hlineapp, int dwdeviceid, ref int lphline, int dwapiversion,int dwextversion, ref int dwcallbackinstance,int dwprivileges, int dwmediamodes,ref int lpcallparams); lineclose Address Formats Function linetranslateaddress linesetcurrentlocation linesettolllist Closes a specified opened line device. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long lineclose(long hline); Description Translates between an address in canonical format and an address in dialable format. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linetranslateaddress(long hlineapp, long dwdeviceid, long dwapiversion, string lpszaddressin, long dwcard, long dwtranslateoptions, ref LINETRANSLATEOUTPUT lptranslateoutput); Sets the location used as the context for address translation. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linesetcurrentlocation (long hlineapp, long dwlocation); Manipulates the toll list. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linesettolllist(long hlineapp, long dwdeviceid, string lpszaddressin, long ~361~
362 dwtolllistoption); linegettranslatecaps Returns address translation capabilities. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegettranslatecaps(long hlineapp, long dwapiversion, ref LINETRANSLATECAPS lptranslatecaps); Call States and Events Function linegetcallinfo linegetcallstatus linesetappspecific Description Returns fixed information about a call. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetcallinfo(long hcall, ref LINECALLINFO lpcallinfo); Returns complete call status information for the specified call. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetcallstatus(long hcall, ref LINECALLSTATUS lpcallstatus); Sets the application-specific field of a call's information structure. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linesetappspecific(long hcall, long dwappspecific); Making Calls Function linemakecall Description Makes an outbound call and returns a call handle for it. Asynchronous. API Example: [DllImport("tapi32.dll")] static extern long linemakecall(long hline, ref long lphcall, string lpszdestaddress, long dwcountrycode, ref LINECALLPARAMS lpcallparams); ~362~
363 linedial Dials (parts of one or more) dialable addresses. Asynchronous. API Example: [DllImport("tapi32.dll")] static extern long linedial(long hcall, string lpszdestaddress, long dwcountrycode); Answering Incoming Calls Function lineanswer Description Answers an incoming call. Asynchronous. API Example: [DllImport("Tapi32.dll", SetLastError = true)] public static extern int lineanswer(int hcall, ref string lpsuseruserinfo, int dwsize); Toll Saver Support Function lineset umrings lineget umrings Description Indicates the number of rings after which incoming calls are to be answered. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linesetnumrings(long hline, long dwaddressid, long dwnumrings); Returns the minimum number of rings requested with linesetnumrings. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetnumrings(long hline, long dwaddressid, ref long lpdwnumrings); Call Privilege Control Function linesetcallprivilege Description Sets the application's privilege to the privilege specified. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linesetcallprivilege(long hcall, long dwcallprivilege); ~363~
364 Call Drop Functions Function linedrop linedeallocatecall Call Handle Manipulation Function linehandoff lineget ewcalls linegetconfrelated Calls Description Disconnects a call, or abandons a call attempt in progress. Asynchronous. API Example: [DllImport("Tapi32.dll", SetLastError = true)] public static extern int linedrop(int hcall, string lpsuseruserinfo, int dwsize); Deallocates the specified call handle. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linedeallocatecall(long hcall); Description Hands off call ownership and/or changes an application's privileges to a call. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linehandoff(long hcall, string lpszfilename, long dwmediamode); Returns call handles to calls on a specified line or address for which the application does not yet have handles. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetnewcalls(long hline, long dwaddressid, long dwselect, ref LINECALLLIST lpcalllist); Returns a list of call handles that are part of the same conference call as the call specified as a parameter. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetconfrelatedcalls(long hcall, ref LINECALLLIST lpcalllist); ~364~
365 Location and Country/Region Information Function linetranslatedialog linegetcountry Description Displays a dialog box allowing the user to change location and calling card information. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linetranslatedialog(long hlineapp, long dwdeviceid, long dwapiversion, long hwndowner, string lpszaddressin); Retrieves dialing rules and other information about a given country/region. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetcountry(long dwcountryid, long dwapiversion, ref LINECOUNTRYLIST lplinecountrylist); Request Recipient Services The following two functions are used only in support of Assisted Telephony. Function lineregisterrequestrecipient linegetrequest Description Registers or deregisters the application as a request recipient for the specified request mode. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long lineregisterrequestrecipient(long hlineapp, long dwregistrationinstance, long dwrequestmode, long benable); Gets the next request from the Telephony dynamic link library. Synchronous. API Example: [DllImport("tapi32.dll")] static extern long linegetrequest(long hlineapp, long dwrequestmode, Any lprequestbuffer); ~365~
366 6- Remoting TCP / HTTP Channels Members Member ame أوال ال HTTP Channel ومن أھم ال Members الخاصة بھا: Availability Description allowautoredirect Client A Boolean value that determines whether the client will handle HTTP redirects. bindto Server A string representing an IP address for the server to bind to. clientconnectionlimit Client connectiongroup ame Client An integer defining how many concurrent connections can be opened to the server. A string representing a group name if the unsafeauthenticatedconnectionsh aring property is set. credentials Client An ICredentials instance that allows a client to pass credentials for password- based authentication schemes such as Kerberos authentication. exclusiveaddressuse Server A Boolean value that forces the server to use the listening IP address and port exclusively so that another application cannot steal the listening TCP port. listen Server A Boolean value that determines whether to allow activation to hook into the outside listener service. name Client and server A string representing the name of the channel. port Server An integer value that specifies what TCP port the server will listen on or what port the client will send TCP packets from. If the value 0 is selected, the infrastructure will choose a port automatically. priority Client and server An integer value that defines the priority of the channel when multiple channels are available. proxy ame Client A string identifying a proxy if the client communication must pass through a proxy. proxyport Client An integer identifying the port on which a proxy is listening for ~366~
367 Member ame Availability Description communication from a client. suppresschanneldata Server A Boolean value that prevents the server channel from returning channel properties. timeout Client An integer that specifies how long the client channel will wait for a server response. unsafeauthenticatedc onnectionsharing useauthenticatedconn ectionsharing Client Client A Boolean value that indicates the client will supply credentials and a group name for the connection. A Boolean value that tells the server to reuse a connection from an authenticated user. useipaddress Server A Boolean value that forces the channel to use a specific IP address instead of using the machine ame property. machine ame Member ame Availability Client and server A string representing the machine name of the listening server. ثانيا ال TCP Channel ومن أھم ال Members الخاصة بھا: Description bindto Server A string representing an IP address for the server to bind to. exclusiveaddre ssuse Server A Boolean value that forces the server to use the listening IP address and port exclusively so that another application cannot steal the listening TCP port. machine ame Client and server A string representing the machine name of the listening server. ame Client and server A string representing the name Port Server An integer value that specifies what TCP port the server will listen on or what port the client will send TCP packets from. Priority rejectremoter equests Client and server An integer value that defines the priority of the channel when multiple channels are available. A larger value indicates greater priority. Server A Boolean value that determines whether the server will only accept requests from the local host. ~367~
368 Member ame Availability suppresschan neldata Server Description A Boolean value that prevents the server channel from returning channel properties. useipaddress Server A Boolean value that forces the channel to use a specific IP address rather than the machine ame property. ~368~
369 Appendixes (B) - ASCII Code Table - References - Useful Sites ~369~
370 ASCII Code Table: Table 1: ~370~
371 Table 2: ~371~
Microsoft Word - C#2
الفصل الا ول مفاهيم البرمجة بواسطة الا هداف معنى البرمجة بواسطة األھداف... 5 معنى الفصيلة 5...Class ما ھي دوال البناء و دوال الھدم...6 Construction & destruction ما ھي خاصية التوريث 7...inheritance ما
( IP Address ) العنوان الشبكي
اسم المقرر شبكات وامن المعلومات عنونة وتقس م الشبكات Network Addressing and Subnetting المحتو ات مقدمة العنوان الشبكى ) Address ( IP تقس مات العنوان الشبكى parts( )IP Network and Host قناع الشبكة Subnet
) NSB-AppStudio برمجة تطبيقات األجهزة الذكية باستخدام برنامج ( ) برمجة تطبيقات األجهزة الذكية باستخدام برنامج ( NSB-AppStudio الدرس األول ) 1 ( الدرس
) NSB-AppStudio ) 1 ( أهداف الدرس : بعد انتهاء هذا الدرس ستكون الطالبة قادرة على أن : )1 توضح مميزات برنامج ( NSB-AppStudio ) 2( تعدد لغات البرمجة المستخدمة في برنامج ( NSB-AppStudio ) 3( تذكر خطوات كتابة
Microsoft Word - moneybookers
الرحيم الرحمن االله بسم א א א ãããaewt{tuaçxà دليل المستخدم العربي في MONEYBOOKERS شرح بنك أوال عن البنك: :معلومات وقلربيزدنيعلما من بريطانيا. 1- البنك جنسيته المناسبة للعمل بھا. به تختار العملة -2 من 5
ورقة عمل الدرس الثاني تطبيقي اخلاص على هاتفي... برنامج App Inventor اعداد املعلمة : اماني ممدوح املصري مدرسة امحد شوقي الثانوية للبنات اختار اإلجابة ا
ورقة عمل الدرس الثاني تطبيقي اخلاص على هاتفي... برنامج App Inventor اعداد املعلمة اماني ممدوح املصري مدرسة امحد شوقي الثانوية للبنات اختار اإلجابة الصحيحة من بني االختيارات االتية - نضغط على االمر ببرنامج
Allomani Warehouse User Guide
المخزن warehouse.allomani.com دليل المستخدم اللوماني للخدمات البرمجية www.allomani.com / 11 اكتوبر / 2010 1 P a g e المحتويات اضافة و اعداد موقعك في المخزن... 3 اعداد بيانات ال...FTP 3 اعدادات بيانات حقوق
الموضوع الثالث تحليل التباين ANOVA) (Two Way الثنائي One Depended نلجأ الى ھذا القانون عند توفر متغيرين يتوقع بينھما تداخل او تفاعل (في تحليل التباين
الموضوع الثالث تحليل التباين ANOVA) (Two Way الثنائي One Depended نلجأ الى ھذا القانون عند توفر متغيرين يتوقع بينھما تداخل او تفاعل (في تحليل التباين االحادي كنا نقارن بين ثالث مجاميع في متغير واحد مثال
دولة فلسطين و ازرة التربية والتعليم العالي المبحث: تكنولوجيا المعلومات / النظري بسم هللا الرحمن الرحيم مدة االمتحان : ساعتان نموذج تجريبي مجموع العالم
دولة فلسطين و ازرة التربية والتعليم العالي المبحث: تكنولوجيا المعلومات / النظري بسم هللا الرحمن الرحيم مدة االمتحان : ساعتان نموذج تجريبي مجموع العالمات )70( عالمة مالحظة: عدد األسئلة خمسة أسئلة وعلى الطالب
التاريخ: االمتحان النهائي لمساق برمجة متقدمة תכנות מתקדם موعد أ الزمن: ساعتان فقط الخميس 2017/7/27 )10 عالمات( السؤال األول for او )while الالزمة لما
التاريخ: االمتحان النهائي لمساق برمجة متقدمة תכנות מתקדם موعد أ الزمن: ساعتان فقط الخميس 2017/7/27 )10 عالمات( السؤال األول for او )while الالزمة لما يلي )الجمل بصيغتين(: أ اكتب جمل التكرار بلغة البرمجة
الأول في السي شارب((c#للمبتدائين
شباب التنميه والبداع : امحد ياسني شلش ذ د الدرس األول: فتح فيوجل ستوديو وشرحه 2012 1 -هذا هوه البرنامج نقوم بفتحه نسخه 2012 فيوجل استوديو new )نضغط علي - 2 اي مشروع جديد( project المتبنأ هذه لغه فيوجل
اختر عنوان مناسب
1 كيفية الوصول الى البريد االلكتروني في الكلية 2 3 الهدف من المحاضرة.Webmail كيفية الدخول الى حساب البريد االلكتروني في الخادم الجديد باستخدام كيفية استعراض الرسائل االلكترونية في السيرفر القديم..Microsoft
The Global Language of Business دليل ارشادي الستخدام صفحة خدمات الشركات األعضاء Members Area 1
دليل ارشادي الستخدام صفحة خدمات الشركات األعضاء Members Area 1 للتسجيل في صفحة خدمات الشركات Area( )Members على الموقع االلكتروني لشركة هيئة الترقيم االردنية www.gs1jo.org.jo يرجى اتباع الخطوات التالية
كيفية تفعيل خدمة IIS ونشر موقع ويب على الشبكة احمللي السالم عليكم اصدقائي الكرام في هذا الكتاب سنتناول ما هي خدمة المعلومات وكيفية التفعيل ونشر الموقع
كيفية تفعيل خدمة IIS ونشر موقع ويب على الشبكة احمللي السالم عليكم اصدقائي الكرام في هذا الكتاب سنتناول ما هي خدمة المعلومات وكيفية التفعيل ونشر الموقع وتجربته وفي النهاية ستجدون روابط المثال مع شرح فيديو
Microsoft Word - 1-NURSE CALL SYSTEM
أنظمة التيار الخفيف 1 -نظام استدعاء الممرضات Eman.A (نظام استدعاء الممرضات) NURSE CALL SYSTEM الھدف من النظام : تسھيل عملية الرعاية الصحية للمرضي, مساعدته في حالة الطوارء. تسھيل التواصل بين فريق العالج
المحاضرة الثانية
المحاضرة الثان ة أنواع الب انات)المتغ رات و الثوابت( محتو ات المحاضرة أنواع الب انات اإلعالن عن المتغ رات الثوابت إسناد الق م إلى المتغ رات واجهة برنامج Visual Studio 2010 2 أنواع الب انات كلمات لغة ال
متطلبات النظام متطلبات جهاز الكمبيوتر الشخصي معالج Pentium 1 Intel غيغا هرتز أو أسرع نظام التشغيل Windows 2000 أوXP Windows مع Service Pack 2 أو Vista
متطلبات النظام متطلبات جهاز الكمبيوتر الشخصي معالج Pentium 1 Intel غيغا هرتز أو أسرع نظام التشغيل Windows 2000 أوXP Windows مع Service Pack 2 أو Vista Window أو Windows 7 Enterprise أو Ultimate أو Business
السالم عليكم و رحمة هللا شرح ربط قاعدة بيانات Access بال.. C# مذا ستستفيد من هذا الموضوع!! -معرفة طريقة صنع قاعدة بيانات بالAccess -ربط قاعدة البيانات
السالم عليكم و رحمة هللا شرح ربط قاعدة بيانات Access بال.. C# مذا ستستفيد من هذا الموضوع!! -معرفة طريقة صنع قاعدة بيانات بالAccess -ربط قاعدة البيانات هذه بالC # على بركة هللا.. * *إنجاز قاعدة بيانات ب*
التحكم في الجهاز عن بعد باستخدام نظام VNC
التحكم بالجهاز عن بعد باستخدام نظام VNC ا عداد : صالح عباس. w w w. a n a b i s h. c o m 2 هذا الملف من ا نتاج موقع ا نابيش وكافة حقوق التا ليف والنشر والتوزيع محفوظة للموقع ولا يجوز بيعه ا و تا جيره با
Banner – Hold Information SOAHOLD
1 Financial Aid System Documentation - eservice E-serviceخطوات التقديم لنظام المساعدات عبر ال 2 خطوات التقديم لنظام المساعدات Steps to apply for financial aid 1 Login to the portal http://my.uaeu.ac.ae
ABU DHABI EDUCATION COUNCIL Abu Dhabi Education Zone AL Mountaha Secondary School g-12 science section Mathematics Student Name:.. Section: How Long i
ABU DHABI EDUCATION COUNCIL Abu Dhabi Education Zone AL Mountaha Secondary School g-12 science section Mathematics Student Name:.. Section: How Long is the Average Chord of a Circle?/ 2009-2010 Second
Microsoft Word - Excel VBA
الفصل الا ول (البداية) قواعد البرمجة...4 مقارنة بين VB و...4 VBA ضبط بيي ة Excel للبرمجة...5 الماآرو فى برنامج...8 Excel أنواع الماآرو... 9 تنفيذ الماآرو... 11 شروط اسماء المتغيرات...18 الكاي ناتObjects...18
Microsoft Word - new.doc
الدرس الاول فى الماتلاب عنوان الدرس : ما هو الماتلاب الماتلاب هو لغة ذات مستوى عالى للحسابات والبرمجة و تمتاز بوجود برنامج يسهل عملية التعامل مع هذه اللغة. ويشمل البرنامج على: الحسابات الرياضية عمل الالجوريثمات
How To Make Connection Between Oracle DB Server 9i & Oracle Developer 6i
بسم االله الرحمن الرحيم How To Make Connection Between Oracle DB Server 9i & Oracle Developer 6i آيف تربط الا وراآل 9i مع الديفيلوبر 6i الا س م التخص ص المو ه ل العم ل البل د اله اتف البري د الص فحة يوسف
الفرق بين البرمجة الإجرائية و البرمجة المسيرة بالأحداث :
طرق كتابة HTML محرر النصوص Text Editor مثل Notepad محرر بطريقة واجهة المستخدم الرسومية GUI Editor وهو محرر يكتب كود بلغة Dream تلقائيا باستخدام القوائم الموجودة فيه مثل برنامج Weaver 8.0 HTML 2 انواع محررات
مختبر البرمجة والتحليل العددي قسم علوم الجو جمل التحكم والشرط والتكرار المرحلة الثانية PROGRAM CONTROL, CONDITION AND LOOP STATEMENTS الجمل الشرطية :-
جمل التحكم والشرط والتكرار PROGRAM CONTROL, CONDITION AND LOOP STATEMENTS الجمل الشرطية :- تقسم جمل الشرط الى نوعين وهي :- -1 جملة اذا الشرطية ) statement ( if -2 جملة التوزيع ) case ( switch -1 جملة اذا
Slide 1
تصميم السيرة الذاتية كصفحات الويب د. احمد عادل اسماعيل عمادة المركز الجامعي لخدمة المجتمع و التعليم المستمر. WWW.Dr-Ahmed.Info Info@Dr-Ahmed.Info -------------- المرجع: www.support.office.com اهداف المحاضرة
( اختبارات الفروق لعينتين مستقلتين Samples) 2) Independent مان- ويتني( U (Mann-Whitney ب( نحتاج الى ھذا القانون الغراض المقارنة بين مجموعتين او عينتين
( اختارات الفروق لعينتين مستقلتين Samples) 2) Independent مان ويتني( U (MannWhitney ( نحتاج الى ھذا القانون الغراض المقارنة ين مجموعتين او عينتين مستقلتين مثال المقارنة ين عينة للذكور م ع عينة لالناث او
Microsoft Word - SolutionOOPFinal2011.doc
صفحة 1 من 5 : : A : : 2010/ : : :. : (20/60) (2) ( 20) (10/20) : محاآاة الواقع على أنه مجموعة من الا شياء و أ ن آل شيء مكون من صفات و سلوك هو... التغليف التجرید البرمجة الشيي ية إخفاء طریقة تطبيق السلوك
Microsoft Word - Access VBA
الفصل الا ول (البداية) تصميم قاعدة بيانات بسيطة...4 الا وامر الا ساسية المتوفرة فى المعالجات...12 الفصل الثانى (برمجة ا كسيس (VBA برمجة أآسيس...18 VBA مقارنة بين VB وVBA...18 الدخول إلى صفحات آتابة برامج
SP-1101W/SP-2101W eciug niitallatini kciuq 1.0v /
SP-1101W/SP-2101W eciug niitallatini kciuq 1.0v / 1014-05 1 I. معلومات حول المنتج 1-1. محتويات العبوة مؤتمر نزع السالح مع دليل التثبيت السريع مفتاح القابس الذكي دليل التثبيت السريع 1-2. اللوحة األمامية
الفصل العاشر CHAPTER 10
الفصل العاشر CHAPTER 10 جدران النار FIREWALLS مبادئ تصميم جدران النار Firewall Design Principles خصاي ص جدار النار Firewall Characteristics أنواع جدران النار Types of تهيي ات جدار النار Firewall Configurations
الصف السادس االبتدائي الفصل الدراسي االول بسم هللا الرحمن الرحيم الصفحة محتويات الفصل الدراسي األول الموضو
بسم هللا الرحمن الرحيم الصفحة 2 3 4 5 6 7 9 11 11 13 14 16 16 17 11 19 22 محتويات الفصل الدراسي األول الموضوع اختيار دولة محددة تغيير نمط عرض التاريخ لالرقام تغيير نمط عرض التاريخ )هجري - ميالدي( تغيير
الدليل التدريبي لتسجيل منتج البوابة االلكترونية للمطابقة )سابر( الدليل التدريبي لتسجيل منتج 0
البوابة االلكترونية للمطابقة )سابر( 0 جدول المحتويات 2 2 4 6 7 8 9 11 وصف النظام تسجيل المنتج إضافة منتج عن طريق الرمز المنسق الجمركي HS code إضافة منتج عن طريق الكلمات الداللية إضافة منتج عن طريق البحث
حقيبة الدورة التدريبية التخزين السحابي Google Drive حقيبة المتدربة إعداد املدربة : عزة علي آل كباس Twitter 1438 ه
حقيبة الدورة التدريبية حقيبة المتدربة إعداد املدربة : عزة علي آل كباس Twitter : @azzahkabbas azzahkabbas@gmail.com 1438 ه الهدف العام : إكساب املتدربات املعرفة بأساسيات الحوسبة السحابية وتطبيقاتها بشكل
دليل المستخدم لبوابة اتحاد المالك التفاعلية
دليل المستخدم لبوابة اتحاد المالك التفاعلية الشاشة الرئيسية 3 إنشاء مستخدم جديد 4 أوال: التسجيل كفرد 5 - نوع الهوية «سعودي» : 5 - نوع الهوية «مقيم :» 6 - نوع الهوية «خليجي» : 7 : التسجيل كمنشأة : 9 ثانيا
اردوينو – الدرس الثامن – تغيير درجة الالوان لـ RGB LED
اردوينو الدرس الثامن تغيير درجة الالوان ل RGB LED في هذا الدرس ستقوم بتطبيق ماتعلمته بالدرس السابع والرابع وذلك لاستخدام الازرار في تغيير درجة الالوان في RGB Led القطع المطلوبة لاتمام هذا الدرس عليك توفير
Microsoft Word - Oracle1
360 Hòî b þa@âbè½ai Oracle Developer îôèm@æë í@áüèm pbíìn a@ ŠèÏ تعرف على ا وراكل تعرف على أوراكل... 4 مالمح ومزايا مجموعة التطوير 5...Oracle Developer Suite 10g أدوات تطوير التطبيقات...6 Oracle Developer
إيناس السيد محمد الشعراوى أستاذ مساعد قسم الحاسب كلية التربية - الجبيل المعلومات الشخصية الجنسية : مصرية تاريخ الميالد / 11 / م القسم علوم الحاس
إيناس السيد محمد الشعراوى أستاذ مساعد قسم الحاسب كلية التربية - الجبيل المعلومات الشخصية الجنسية : مصرية تاريخ الميالد 3 984/ / م القسم علوم الحاسب اآللى البريد الجامعي الرسمي eeelsharawy@iau.edu.sa الهاتف
Microsoft Word - CO_RT10
إعداد : تقديم الشكل أسفله يمثل مضخم يعتمد على ترانزيستور. فھو يحتوي على شبكة من المقاومات تمكن من تقطيب و مكثفات تعمل على ربط المضخم بأخر وذلك بتمرير اإلشارات المتناوبة. R1 100k 1µF 1µF (Load) Rc (charge)
السلطة الوطنيـة الفلسطينية
دولة فلسطني بسم هللا الرحمن الرحيم مدة االمتحان : ساعتان وزارة الرتبية والتعليم العايل اإلدارة العامة للقياس والتقويم واالمتحانات المبحث: تكنولوجيا المعلومات / النظري نموذج تجريبي 1/ الدورة: األولى اإلنجاز
جمعية زمزم للخدمات الصحية التطوعية بإشراف وزارة الشؤون االجتماعية تصريح رقم )411( نظام إدارة الجودة Quality Management System إجراءات الئحة تقنية املع
جمعية زمزم للخدمات الصحية التطوعية بإشراف وزارة الشؤون االجتماعية تصريح رقم )411( نظام إدارة الجودة Quality Management System إجراءات الئحة تقنية املعلومات زمزم 19 إعداد االسم : هاني عبدالعزيز فلمبان الوظيفة
خطـــــة المركــــــز التدريبيـــــة خلال شهر كانون ثاني من عام 2004
10 / 10 / 1 2 6/20 0 6 FRM-TC-T-01-01 تموز )7( التقييم العقاري Real Estate Appraisal 19/08/2019 /07/2019 Project Management - PMP Course 22/08/2019 31/07/2019 تصميم الشآت الخرسانية Concrete Structure Design
السالم عليكم ورحمة هللا وبركاتة كتاب تعلم برمجة االلعاب بأستخدام محرك االلعاب Unity 3D الكتاب مقدم من االستاذ : عماد عارف التوي موقع : Home OF Games ا
السالم عليكم ورحمة هللا وبركاتة كتاب تعلم برمجة االلعاب بأستخدام محرك االلعاب Unity 3D الكتاب مقدم من االستاذ : عماد عارف التوي موقع : Home OF Games الدورة تهتم فقط بتعلم البرمجة من االبتداء الى االحتراف
Basic Invoice Template for Word
قاموس المصطلحات أعزائي... ستجدون هنا جميع المصطلحات المستخدمة خالل مساق "أساسيات وأفضل ممارسات لغة ال "HTML5 مترجمة إلى اللغة العربية لمنفعتكم. 1 Accessibility 1 إمكانية الوصول 2 Animation (Animations)
عربي Sign-Code Website Guide فيما يلي دلي ا ل لطلب اسم مستخدم جديد لConnect Sell من خ لل موقع.Sign-Code يسمح لك الموقع بالدخول اإلداري على اسم المستخد
عربي فيما يلي دلي ا ل لطلب اسم مستخدم جديد لConnect Sell من خ لل موقع.Sign-Code يسمح لك الموقع بالدخول اإلداري على اسم المستخدم الخاص بك لID Office من خ لل طلب مستخدمين جدد وتحديثها وحتى حذفها:.1 ستتلقى
برمجة متقدمة -1-
برمجة متقدمة -1- السنة الثانية قسم برمجيات م. تغريد حرفوش 08 تشرين األول 1 18 اللكمة املفتاحية Base تستخدم هذه الكلمة المفتاحية لتحديد باني االب الذي سيتم استدعاؤه في الصف االبن ضمنيا الباني في الصف االبن
Slide 1
Ministry of Education Project# 10/2008-20009 Training Workshop Presented by: Eng. Mohamed Saleh Project Manager CCIE#25409 Agenda: 1- مقدمة: مفاهيم أساسية 2- ما هي الفوائد التي اضافتها أجهزة البلوكوت والراوتر
الفصل الثامن
المقرر: الفصل الثامن Chapter 8 سرية إدارة الشبكات Network Management Security 8.1 Basic concepts of SNMP 1.8 المفاهيم الا ساسية لبروتوآول إدارة الشبكات البسيط معمارية إدارة الشبكات Network Management Architecture
PowerPoint Presentation
API/iAPI Transmitting Challenges صعوبات وتحديات تطبيق برنامج تبادل المعلومات المسبقة للمسافرين Ali Al-athbi Qatar Civil Aviation Authority علي طالب العذبي الهيئة العامة للطيران قطر دولة المدني/ ICAO TRIP:
FS Future Series دليل البدء السريع الرجاء قراءة التعليمات التالية من أجل تثبيت وتنشيط 3D. Visualizer برنامج
FS Future Series دليل البدء السريع الرجاء قراءة التعليمات التالية من أجل تثبيت وتنشيط 3D. Visualizer برنامج 1. اتفاقية الترخيص والضمان المحدود الرجاء قراءة أحكام اتفاقية الترخيص قبل استخدام برنامج.Visualizer
عرض تقديمي في PowerPoint
كود التدريب KSH7TDB19 google يتم البحث عنه في متصفح sway يكون ضمن البرامج الموجودة من الموقع للتسجيل في hot mail او الدخول على البريد االلكتروني من : khulood.sairafi ضمن البرامج الموجودة hot mail للتسجيل
جامعة حضرموت
جاهعة حضرهوت التسجيل االلكتروني لمرحلة التنسيق بالجامعة عبر الموقع www.hu-registration.com الصفحة الرئيسية زر الدخول على النظام ف حالة التسج ل سابقا ولد ك اسم مستخدم وكلمة مرور زر تسج ل متقدم جد د اذا
New Microsoft Office Word Document
ا: أآ ات ا أي آ ة آ أم! ة و#" %" )'ى ازل أو ا+ت ا.ر, ه' ا 0 ادي.2 ا 3 ت ا 45. #6,8 ف ا 0 ادي : "#, ا ا;'ل ا> 8 ) = أ :3 '!'ل إ" ا ". و 3
شرح برنامج استعادة الملفات المحذوفة Recover my files من اعداد : رافاييل يوسف مقدمة: آلنا يعلم ان اجهزة الكومبيوتر قادرة على حفظ الملفات على قرصها الصل
شرح برنامج استعادة الملفات المحذوفة Recover my files من اعداد : رافاييل يوسف مقدمة: آلنا يعلم ان اجهزة الكومبيوتر قادرة على حفظ الملفات على قرصها الصلب على شكل موج ات آهرومغناطيسية و اننا نعلم باننا نستطيع
Microsoft Word - cover+contens
قسم : البرامج الفنية " تراسل" اساسيات االتصاالت الرقمية ١ المحتويات مقدمة عامة عن نظريات ونظم االتصاالت الصفحة ١) (١٥ التعديل النبضى المشفر الصفحة ١) (١٤ ٢ تجميع القنوات الھاتفية بالتقسيم الزمنى الصفحة
استمارة تحويل طالب يتعلم في الصف العادي لجنة التنسيب إلى )التقرير التربوي( استمارة لتركيز المعلومات حول العالج المسبق الذي حصل علية الطالب\ة الذي يتعل
استمارة تحويل طالب يتعلم في الصف العادي لجنة التنسيب إلى )التقرير التربوي( استمارة لتركيز المعلومات حول العالج المسبق الذي حصل علية الطالب\ة الذي يتعلم في صف عادي, قبل تحويله إلى لجنة التنسيب.يجب تعبئة
بسم هللا الرحمن الرحيم المادة: مقدمة في بحوث العمليات )100 بحث ) الفصل الدراسي األول للعام الدراسي 1439/1438 ه االختبار الفصلي الثاني اسم الطالب: الرق
بسم هللا الرحمن الرحيم المادة: مقدمة في بحوث العمليات ) بحث ) الفصل الدراسي األول للعام الدراسي 9/8 ه االختبار الفصلي الثاني اسم الطالب: الرقم الجامعي: أستاذ المقرر: الدرجة: أكتب اختيارك لرمز اإلجابة الصحيحة
ش ط TRANQUILITY ش ط Tranquility دومي ي ه منتج سك رائ ص ي ئ ب ت ست ى إق م م ا ر ا و. ا ط ط ا ع ة التصم د م ا ن س ا عم ري وأس ب ء ه ا ا م ا ي سي أجن سكن
ش ط TRANQUILITY ش ط Tranquility دومي ي ه منتج سك رائ ص ي ئ ب ت ست ى إق م م ا ر ا و. ا ط ط ا ع ة التصم د م ا ن س ا عم ري وأس ب ء ه ا ا م ا ي سي أجن سكني ح ي مك ن م غ ف ن م وا ة أو ا ت وأجن است دي وفي ت
نموذج السيرة الذاتية
بسم اهلل الرحمن الرحيم البيانات الشخصية االسم تاريخ ومكان الميالد الكلية القسم عمان العلوم التربوية المكتبات و المعلومات المؤهالت الد ارسية الدرجة العلمية التخصص الجهة المانحة لها 2012 دكتو اره علم المعلومات
دليل تدريبي : الحلول لما بعد اختراق الحسابات إعداد : محمد المسقطي Mohammed Al-Maskati بمساعدة : علي السباعي Ali Sibai
دليل تدريبي : الحلول لما بعد اختراق الحسابات إعداد : محمد المسقطي Mohammed Al-Maskati Twitter:@mohdmaskati بمساعدة : علي السباعي Ali Sibai Twitter:@alisibai المقدمة : العديد منكم يتعرض إلى حالة من الصدمة
Department of Computer Information Systems
Departmet of Computer Iformatio Systems CIS : Itroductio to Iformatio Techology Topic 5 Numberig Systems (Exteral Material) Chapter Outlie Numberig Systems Coversio Betwee Systems ملخص الفصل أنظمة الا
برنامج المساعدات المادية الذكي خطوات التقديم للمساعدة المادية...2 خطوات رفع المستندات المرفوضة...10 خطوات التاكد من حالة الطلب
برنامج المساعدات المادية الذكي خطوات التقديم للمساعدة المادية...2 خطوات رفع المستندات المرفوضة...10 خطوات التاكد من حالة الطلب... 13 1 خطوات التقديم للمساعدة المادية قبل البدء باستخدام البرنامج الرجاء:
عرض تقديمي في PowerPoint
Dr./ Ahmed Mohamed Rabie Sayed 1 2 Symbol Sprayer Tool -23 تستخدم األداة Symbol Sprayer Tool إلنشاء مجموعة من الرموز Symbols التصميم. لتنشيط األداة يتم الضغط على مفتاح Shift+S من لوحة المفاتيح. صفحة داخل
NUBIX for Information Technology
P a g e 1 NUBIX for Information Technology Document Management System. NUBIX for information technology is a software house located in Cairo Egypt, formed as limited company with Swiss and Egyptian capital.
Slide 1
10- تعريف البروتوكوالت Protocols:.1.2.3.4.5.6 ما هي شبكة اإلنترنت تطور شبكة اإلنترنت: أين تقع..شبكة االنترنت.....!!!! من الذي يمتلك شبكة االنترنت.....!!! من الذي يدير شبكة االنترنت.....!!! مجتمع االنترنت
دليل ملفات الــ Log
السلم عليكم ورحمة ال وبركاته... دليل ملفات ال Log موضوعي لهذا اليوم أجده مهم للمحترفين وللمستخدمين العاديين... ولم أجد أحد صراحة تكلم عنه سابقا... ول حتى فكر في السؤال عنه ولهذا ما سأتناول في هذا الموضوع
Certified Facility Management Professional WHO SHOULD ATTEND? As a Certified Facility Management Professional course, Muhtarif is the ideal next step
Certified Facility Management Professional WHO SHOULD ATTEND? As a Certified Facility Management Professional course, Muhtarif is the ideal next step for all those who have completed the Ta aseesy Foundation
Application-1st page
3 photos نموذج رقم ( A1) طلب قبول لدرجة البكالوريوس Application for Undergraduate Admission للعام الدراسي : 20 Academic Year 20 / الرقم الجامعي: Student ID: Application Number: Application Date: Student's
دائرة التسجيل والقبول فتح باب تقديم طلبات االلتحاق للفصل األول 2018/2017 " درجة البكالوريوس" من العام الدراسي جامعة بيرزيت تعلن 2018/2017 يعادلها ابتد
دائرة التسجيل والقبول فتح باب تقديم طلبات االلتحاق للفصل األول 2018/2017 " درجة البكالوريوس" من العام الدراسي جامعة بيرزيت تعلن 2018/2017 يعادلها ابتداء من عن فتح باب تقديم طلبات االلتحاق بإمكان الطلبة
???? ???????? ?????? ????? ...
1 of 13 5/10/2009 7:19 PM منتديات الفلوجة اإلسالمية اإلنترنت والبرامج تصفح اإلنترنت بتقنية تشفير Ssl 256 بروكسي < ::: المنتديات التقنية ::: < منتدى علوم الحاسب و مجانا - بدون برامج اسم العضو كلمة المرور
الفهرس: كيفية ضبط الموبايل/التابلت: خدمة االنترنت معرفة مسبقا على الجهاز. في حالة عدم تعريف خدمة االنترنت مسبقا على الجهاز يمكنك ضبطه يدويا ادخل على D
الفهرس: كيفية ضبط الموبايل/التابلت: خدمة االنترنت معرفة مسبقا على الجهاز. في حالة عدم تعريف خدمة االنترنت مسبقا على الجهاز يمكنك ضبطه يدويا ادخل على Data Cellular أو network«3g«ثم ادخل على Settings APN
الفصل الثاني
1 برنامج MINTAB 17 105 احص إعداد أ- ريم المبطي 2 الفصل الثاني ( اختبارات الفروض وفترات الثقة ) لمعالم مجتمع واحد أوال : اختبار المتوسط : لدينا حالتين : نستخدم اختبار Z عندما : N كبيرة و معلومة أو مجهولة
Zawiyathul Fassiyathush Shazuliya, Kazimar St, Madurai , Tamil Nadu, India. 1 حزب اللطف للشاذلي رضي االله عنھ وھذا حزب اللطف یدعى بھ في الشداي
1 حزب اللطف للشاذلي رضي االله عنھ وھذا حزب اللطف یدعى بھ في الشداي د والكربات فا ن لھ سر ا عجیبا لتفریج الكرب وازالة الھم وكل مو لم من امراض الظاھر والباطن ویصلح ان یكون على اسمھ تعالى لطیف وھو ھذا: بسم
الدليل التدريبي لطلب شهادة مطابقة إرسالية )للمنتجات المستوردة( البوابة االلكترونية للمطابقة )سابر( الدليل التدريبي لطلب شهادة مطابقة إرسالية )للمنتجات
البوابة االلكترونية للمطابقة )سابر( 0 جدول المحتويات 2 2 9 1 وصف النظام 2 طلب مطابقة إرسالية جديد 3 إصدار الشهادة 1 1 وصف النظام يهدف هذا النظام لتمكين ضابط اتصال المنشأة ومفوض المنشأة من استخراج شهادة
مدرسة هارون الرشيد الثانوية للبنين المهارات العملية / تكنولوجيا المعلومات ( الثاني عشر) إعداد/ أ. خالد الح
املهارات العملية / تكنولوجيا املعلومات )Appinventor )بزنامج :on line من خالل االنترنت مباشرة App inventor خطوات تشعيل برنامج الدخول إلى حساب ج م ل.Gmail ثم رابط الموقع App inventor عبر متصفح االنترنت http://appinventor.mit.edu/explore/
easy - translation
From: http://ar.miraath.net/audio/5030/01 Shaikh Ahmad Bazmool Http://ar.miraath.net/audio/download/5030/usool_us_sunnah_01.mp3 أما األمر األول فھو أنه يظن أن ھذا العلم ثقيل وال يفھمه فھذا خطأ فھذا خطأ
من نحن يف 2007 / 9 / 2 صدرت جريدة كصحيفة يومية وطنية شاملة تسعى إلى مواكبة التطورات احمللية و االقلميية والعاملية بشكل موضوعي ومبتكر إلى جانب تبني امل
من نحن يف 2007 / 9 / 2 صدرت جريدة كصحيفة يومية وطنية شاملة تسعى إلى مواكبة التطورات احمللية و االقلميية والعاملية بشكل موضوعي ومبتكر إلى جانب تبني املبادرات االبداعية وتستخدم يف سبيل الوصول إلى ذلك أحدث
مكثف الثالثة الوحدة البوابات املنطقية 1 هاتف : مدارس األكاد م ة العرب ة الحد ثة إعداد المعلم أحمد الصالح
مكثف الثالثة الوحدة البوابات املنطقية هاتف : 798226 النظ ري الج زء و الثاني األ ول للد رسين وضح ان قصىد ت ا يهي : انرعثير انعالئقي ج هح خثريح ذكى قي رها إيا صىاب )( و إيا خطأ )( ان عايم ان طقي راتط يسرخذو
حفظ واسترجاع الصور في قاعدة البيانات Sql Server بلغة سي شارب
بسم هللا الرحمن الرحيم ت ذ ذ هلل سج ت ؼث ١ صالذ عال ػ خ ١ ش ت شع ١ د ١ ث ذ ذ ػ آ صذد أج ؼ ١. ػض ٠ ض ت مثسئ خإر هللا عأشذذض ؼه ف زت ت ىص ١ ح ت ص تضغ ػ ض ع دفع ت ص سذ ف لثػذذ ت د ١ ث ثز Sql Server و ١ ف
riyadh-geeks-mobile-first
هذه الشريحة ت ركت فارغة عمد ا. رياض قيكس. لقاء شهر أغسطس ٢٠١٥. اجلو ال أوال *. تصميم صفحات الو يب ألجهزة اجلو ال. * مستلهم من http://www.youtube.com/watch?v=nje_or4vilu و غيره. ح سام الزغيبي. @hossamzee
عرض تقديمي في PowerPoint
Dr./ Ahmed Mohamed Rabie Sayed 1 2 صندوق االدوات صندوق االدوات Tools Box يحتوى اظهار وإخفاء Tools Box من قائمة على االدوات Window الرئيسية الالزمة النشاء واختيار.Tools وتعديل التصميم. ويمكن 3 Move Tool
د. ط در ءة ز ا ت ا دزة (درا ا ا ت) د. ط در را ر ا م م ا ا ا : ا ت ا ا ا م وا ا ي و إ ى ا ت ا ا ا دو إ و دة ا و أ اد ا. و ف ا ا إ وا ا ت ا دزة م ا أ ا
ءة ز ا ت ا دزة (درا ا ا ت) را ر ا م م ا ا ا : ا ت ا ا ا م وا ا ي و إ ى ا ت ا ا ا دو إ و دة ا و أ اد ا. و ف ا ا إ وا ا ت ا دزة م ا أ ا و ت وا ت ا دة أ ا ذ ا ا وا اءات ا ور ا و ن ا ءة و ا م ت ا. ا ا : ا
الخدمة العربية للكرازة باإلنجيل Arabic Bible Outreach Ministry بين العقل واإليمان الجزء األول بقلم د. ھيرمان بافينك ترجمة د. عبد ا
بين العقل واإليمان الجزء األول بقلم د. ھيرمان بافينك ترجمة د. عبد المسيح أسطفانوس All Rights Reserved جميع الحقوق محفوظة الرجاء التقيد جميع الحقوق محفوظة للمؤلف وال يجوز إعادة نشر أو طبع ھذا الكتاب بأي
دور ا ا ا ا ى ا ب ا رس ا ر م د إ ا أ أ در ن ا - ا دان ا ذ ا ا ر أ ا
دور ا ا ا ا ى ا ب ا رس ا ر م د إ ا أ أ در ن ا - ا دان ا ذ ا ا ر أ ا (١٧٠)... دور ا ا ا ا ى ا ب دور ا ا ا ا ى ا ب...( ١٧١ ) دور ا ا ا ا ى ا ب ا رس ا ر م د إ ا أ ا ذ ا ا ر أ ا أ در ن ا - ا دان ا ا ول ا اءات
<4D F736F F D20C7E1DDD5E120C7E1CBC7E1CB20E5E4CFD3C920C8D1E3CCEDC7CA2E646F6378>
CHAPTER 3 Software Requirement Engineering ھندسة المتطلبات البرمجية Topics: 3.1 Introduction 3.2 Requirement and its Problems 3.3 Software Requirement Engineering and its Objectives 3.4 Software Requirement
Metadata Applications in CrossRef linking in e-Journals(in Arabic)
تطبيقات الميتاداتا في الربط البيني للاستشهادات المرجعية بالدوريات الا لكترونية Metadata Applications in CrossRef linking in e-journals إعداد أماني محمد السيد مدرس المكتبات والمعلومات المساعد آلية الا داب
doc11
الجزء األول من الكتاب المدرسي (3 ع ت 3 ت ر ر ( التطورات الزمنية الرتيبة تطور جملة كيميائية نحو حالة التوازن الوحدة 4 DAHEL MT Lycée benalioui salah SETIF ***********************************************************
Do you like these sounds?
Good Vibrations االهتزازات الج دة االصوات LESSON 1 WHAT IS SOUND? ما هو الصوث إذا كنت سع دا وأنت تعرف ذلك صفق ب د ك 1-1 إذا إذا كنت سع دا وأنت تعرف ذلك صفق ب د ك كنت سع دا وأنت تعرف ذلك صفق ب د ك إذا كنت
فهرس المحتويات مقدمة...6 دوافع المشروع :...7 مراحل المشروع وأهدافه :...7 الفصل األول : Streaming مقدمة : : Media Streaming : St
فهرس المحتويات مقدمة...6 دوافع المشروع :...7 مراحل المشروع وأهدافه :...7 الفصل األول :...8 8...Streaming مقدمة :...8 8... : Media Streaming 10... : Streaming Methods 10... : - 1-1 - 1-2 1-3 Streaming Protocols
النشر في مجلات ال ISI
النشر في مجالت ال ISI د. ريم العبيكان 1440 ه /6 /20 املوافق 2019 م /2 /25 لماذا ين ر ش الباحث ي ف مجالت ال ISI نشر نتائج البحث على نطاق واسع.. ووصول البحث لعدد كبير من املهتمين باملجال )املؤشر: معامل تأثير
بسم هللا الرحمن الرحيم االسئلة المتوقعه لمادة الحاسوب م 3 شتوية 2016 االستاذ نور الدين بني عطا االسئلة المتوقعه على مادة الحفظ سؤال 1 : وضح
بسم هللا الرحمن الرحيم االسئلة المتوقعه لمادة الحاسوب م 3 شتوية 2016 االستاذ نور الدين بني عطا 0775226286 االسئلة المتوقعه على مادة الحفظ سؤال 1 : وضح المقصود بكل من : 1( االقتصاد المعرفي : هو االقتصاد
مشروع المكتبات الرقمية
قطاع الدراسات العليا والبحوث اإلدارة العامة للمكتبات قاعدة بيانات IEEE Electrical, Electronic Engineering and Computer Science إصدار رقم يونيه )6( 2016 قطاع الدراسات العليا والبحوث االدارة العامة للمكتبات
وزارة الترب ة بنك األسئلة لمادة علم النفس و الح اة التوج ه الفن العام لالجتماع ات الصف الحادي عشر أدب 0211 / 0212 األولى الدراس ة الفترة *************
وزارة الترب ة بنك األسئلة لمادة علم النفس و الح اة التوج ه الفن العام لالجتماع ات الصف الحادي عشر أدب 2 / 22 األولى الدراس ة الفترة ************************************************************************************
تحليل الانحــدار الخطي المتعدد
٥٦ تحليل الانحدار الخطي المتعدد Multple Regress Aalss الغرض من التحليل يهتم تحليل الانحدار الخطي المتعدد بدراسة وتحليل أثر عدة متغيرات مستقلة آمي ة عل ى متغي ر ت ابع آمي. نموذج الانحدار الخطي المتعدد بف