1. مقدمة إلى TCP/IP
عائلة بروتوكول TCP/IP هي بروتوكول تستخدمه الإنترنت ويمكن أيضًا استخدامه في شبكات خاصة مستقلة.
تتضمن عائلة بروتوكول TCP/IP بروتوكول IP وبروتوكول TCP وبروتوكول UDP.
يستخدم بروتوكول IP عناوين IP لتوزيع الحزم ، ولكنه أفضل خدمة للجهد ، وقد تضيع الحزم أو خارج الترتيب أو تكرارها. تضيف بروتوكولات TCP و UDP أرقام المنافذ إلى بروتوكول IP ، وبالتالي إنشاء اتصال شفاف بين تطبيقات المضيفين.
الفرق هو أن بروتوكول TCP يعمل على إصلاح أخطاء طبقة IP ، والتي تنشئ اتصالات بين المضيفين من خلال رسائل المصافحة.
بعد ذلك ، تتم استعادة الأخطاء في الرسالة عن طريق إضافة رقم تسلسلي إلى الرسالة. UDP ببساطة يمتد بروتوكول IP.
تمكينه من العمل بين التطبيقات ، وليس بين المضيفين.
فيما يتعلق بعناوين IP ، يمكن أن يحتوي المضيف على واجهات شبكات متعددة ، ويمكن أن تحتوي واجهة واحدة على عناوين متعددة.
بعض عناوين IP لها استخدامات خاصة:
A. عنوان الاسترجاع: 127.0.0.1 ، يتم تعيينه دائمًا في واجهة الاسترجاع ، يستخدم بشكل رئيسي للاختبار.
B. العنوان الخاص: بدءًا من 10 ، 192.168 ، 172. (16-31) ، يستخدم للشبكات الخاصة. عندما يقوم جهاز NAT بإعادة توجيه رسالة ، يقوم بتعيين زوج منفذ العنوان الخاص للرسالة في واجهة واحدة في زوج منفذ العنوان العام في واجهة أخرى. يتيح ذلك مجموعة صغيرة من المضيفين من مشاركة زوج عنوان IP.
C. عنوان البث المتعدد: الرقم الأول يتراوح بين 224 و 239.
2. أساسيات المقبس
1. الحصول على العنوان
public static void main (string [] args) {try {enumeration <NetworkInterface> interfaces = networkInterface.getNetworkInterFaces () ؛ بينما (interfaces.hasmoreElements ()) {NetworkInterface iface = interfaces.nextElement () ؛ System.out.println ("واجهة:" + iface.getName ()) ؛ التعداد <InetAddress> addrlist = iface.getInetAddresses () ؛ if (! addrlist.hasmoreElements ()) system.out.println ("no address") ؛ بينما (addrlist.hasmoreElements ()) {inetaddress address = addrlist.nextElement () ؛ System.out.println ("العنوان:" + address.gethostaddress ()) ؛ }}} catch (socketException e) {e.printStackTrace () ؛ }}2. برنامج مثيل TCP
تجدر الإشارة إلى أنه على الرغم من استخدام طريقة واحدة فقط للكتابة () لإرسال سلاسل على جانب العميل ، فقد يتلقى جانب الخادم هذه المعلومات أيضًا من كتل متعددة. حتى إذا تم تخزين سلسلة التعليقات في كتلة عند إرجاع الخادم ، فقد يكون TCP
ينقسم البروتوكول إلى أجزاء متعددة.
tcpechoclienttest.java
static static void main (string [] args) يلقي ioException {String Server = args [0] ؛ byte [] data = args [1] .getBytes () ؛ منفذ int = 7 ؛ Socket Socket = مقبس جديد (خادم ، منفذ) ؛ System.out.println ("متصل بالخادم ...") ؛ inputStream في = socket.getInputStream () ؛ outputStream Out = socket.getOutputStream () ؛ out.write (البيانات) ؛ int totalBytesrcvd = 0 ؛ int bytesrcvd ؛ بينما (TotalByTesrcvd <data.length) {if ((bytesrcvd = in.read (data ، totalBytesrcvd ، data.length - TotalBytesrcvd)) == -1) رمي socketException ("connection مغلق") ؛ TotalBytesrcvd += bytesrcvd ؛ } system.out.println ("trab:" + new string (data)) ؛ socket.close () ؛ }tcpechoservertest.java
int bufsize int int static int = 32 ؛ الفراغ الثابت العام (سلسلة [] args) يلقي ioException {serversocket ServersOcket = new Serversocket (7) ؛ int recvmsgsize ؛ byte [] recebuf = new byte [bufsize] ؛ بينما (صواب) {socket Socket = serversOcket.accept () ؛ System.out.println ("Handling Client" + "من Remote" + Socket.getRemotesCetEntAddress () + "في محلي" + socketlocalsocketaddress ()) ؛ inputStream في = socket.getInputStream () ؛ outputStream Out = socket.getOutputStream () ؛ بينما ((recvmsgsize = in.read (recebuf))! = -1) {out.write (recebuf ، 0 ، recvmsgsize) ؛ } socket.close () ؛ }}لاحظ أن المقبس الجديد يحدد رقم المنفذ الذي يستمع إليه الخادم البعيد دون تحديد المنفذ المحلي ، وبالتالي سيتم استخدام العنوان الافتراضي ورقم المنفذ المتاح. على منفذ عميل الجهاز الخاص بي 4593 ، متصل بالمنفذ 7 من الخادم.
3. برنامج مثيل UDP
لماذا تستخدم بروتوكول UDP؟ إذا قام التطبيق بتبادل كمية صغيرة فقط من البيانات ، فستقوم مرحلة إنشاء اتصال TCP بنقل معلوماتها على الأقل (ومرضع وقت الرحلة ذهابًا وإيابًا).
udpechoclienttest.java
static static void main (string [] args) يلقي ioException {inetaddress serveraddress = inetaddress.getByName (args [0]) ؛ byte [] bytestosend = args [1] .getBytes () ؛ DataGramSocket Socket = datagramsocket () جديد ؛ Socket.SetSotimeout (3000) ؛ datagrampacket sendPacket = جديد datagrampacket (bytestosend ، bytestosend.length ، serveraddress ، 7) ؛ datagrampacket receptpacket = new datagrampacket (byte new [bytestosend.length] ، bytestosend.length) ؛ // قد تضيع الحزم ، لذلك يتعين علينا الاستمرار في محاولة محاولات int = 0 ؛ Boolean receedResponse = false ؛ do {socket.send (sendPacket) ؛ حاول {socket.receive (receptpacket) ؛ if (! recepacket.getAddress (). equals (serveraddress)) رمي ioException جديد ("استلام من مصدر غير معروف") ؛ استقبلت reSponse = صحيح ؛ } catch (ioException e) {tries ++ ؛ System.out.println ("timeout ، حاول مرة أخرى") ؛ }} بينما (! trauleResponse && tries <5) ؛ if (traucresponse) system.out.println ("receed:" + new string (receptpacket.getData ())) ؛ else system.out.println ("لا استجابة") ؛ socket.close () ؛ } udpechoservertest.java
int static int echomax = 255 ؛ kain static void main (string [] args) يلقي ioException {datagramsocket socket = datagramsocket (7) ؛ حزمة datagrampacket = datagrampacket جديد (بايت جديد [echomax] ، echomax) ؛ بينما (صواب) {socket.receive (حزمة) ؛ System.out.println ("مناولة العميل في" + packet.getaddress ()) ؛ Socket.send (حزمة) ؛ Packet.SetLength (Echomax) ؛ }}مقارنة هذا المثال مع مثيل TCP السابق ، هناك الاختلافات التالية:
لا تحتاج A.DatagramSocket إلى تحديد عنوان الوجهة عند إنشاءه ، لأن UDP لا يحتاج إلى إنشاء اتصال ، ويمكن إرسال كل حزمة بيانات أو استلامها من عنوان وجهة مختلف.
ب. إذا قمت بحظر وانتظرت القراءة () مثل TCP ، فقد يتم حظرها إلى الأبد ، لأن بروتوكول UDP يمتد ببساطة إلى بروتوكول IP ، وقد تضيع حزم UDP. لذلك ، يجب عليك تعيين وقت المهلة لحظر الانتظار.
يحتفظ بروتوكول C.UDP بالمعلومات الحدودية للرسالة ، ويمكن لكل مكالمة استلام () تلقي البيانات المرسلة فقط بواسطة استدعاء طريقة SEND () مرة واحدة.
D. البيانات القصوى التي يمكن أن تنقلها حزمة UDP هي 65507 بايت. سيتم تجاهل البايتات الزائدة تلقائيًا ، ولا يوجد موجه لبرنامج الاستلام. لذلك ، من الآمن ضبط مجموعة ذاكرة التخزين المؤقت على حوالي 65000 بايت.
E. إذا تم استدعاء طريقة Recet () مرارًا وتكرارًا مع مثيل Datagrampacket نفسه ، فيجب إعادة تعيين الطول الداخلي للرسالة بشكل صريح إلى الطول الفعلي للذاكرة التخزين المؤقت قبل كل مكالمة.