تكتب Java خادمًا وعميلًا يمكنه تحميل الملفات. المحتوى المحدد كما يلي
جانب الخادم
Class Server {public static void main (string [] args) يلقي الاستثناء {// إنشاء خادم Socket Socket STERSOCKET SS = NEW SERVESSOCTING (10005) ؛ // استقبال مقبس العميل fileLoadersOcket = ss.accept () ؛ // اطبع سلسلة معلومات الاتصال IP = fileLoadersocket.getInetAddress (). gethostaddress () ؛ System.out.println (IP + "... conceed") ؛ // تلقي الملف وحفظ inputStream في = fileLoadersocket.getInputStream () ؛ // instantiate الكائن filesave outputStream filemave = جديد fileOutputStream ("e: //3.mp3") ؛ // إنشاء صفيف buf byte [] buf = new byte [1024] ؛ int len = 0 ؛ // الدفاع عما إذا كانت نهاية الملف تتم قراءة بينما ((len = in.read (buf))! = -1) {filesave.write (buf ، 0 ، len) ؛ // refresh filesave.flush () ؛ }. Out.write ("تحميل الملف الناجح") ؛ // refresh.flush () ؛ // Resource Close Ss.Close () ؛ fileLoadersocket.close () ؛ filesave.close () ؛ }}عميل:
Class Client {public static void main (string [] args) يلقي الاستثناء {// إنشاء مقبس Socket Socket FileLoadersOcket = New Socket ("168.168.168.94" ، 10005) ؛ // اقرأ الملف محليًا من العميل واكتب إلى إخراج إخراج المقبس OutputStream Out = fileLoadersOcket.getOutputStream () ؛ // instantiate الكائن fileReader inputStream fileRead = جديد fileInputStream ("g: //2.mp3") ؛ // إنشاء بايت صفيف [] buf = new byte [1024] ؛ int len = 0 ؛ // ugns ما إذا كان يتم قراءة نهاية الملف بينما ((len = fileRead.Read (buf))! = -1) {out.write (buf ، 0 ، len) ؛ } // أخبر الخادم أن الملف قد تم نقله fileLoadersOcket.shutdownoutput () ؛ // احصل على ملاحظات المعلومات من الخادم BufferedReader في = جديد Bufferreader (New InputStreamReader (fileLoadersocket.getInputStream ())) ؛ String serverback = in.ReadLine () ؛ system.out.println (serverback) ؛ // Resource Close fileLoadersocket.close () ؛ fileread.close () ؛ }}يتم نسخ البرنامج التالي مباشرة من مكان آخر للتعلم المرجع:
جافا مقبس البرمجة
بالنسبة لبرمجة Socket Java ، هناك مفهومين ، أحدهما هو ServerSocket والآخر هو المقبس. يتم توصيل الخادم والعميل من خلال المقبس ، ثم يمكنهم التواصل. أولاً ، سوف يستمع Serversocket إلى منفذ على الخادم. عندما يتم العثور على أن العميل لديه مقبس لمحاولة الاتصال به ، فإنه سيقبل طلب اتصال المقبس ، وفي الوقت نفسه ، قم بإنشاء مأخذ توصيل مقابل على الخادم للتواصل معه. وبهذه الطريقة ، هناك مآخذان ، أحدهما على العميل وواحد على الخادم.
التواصل بين المقابس بسيط للغاية. عندما يكتب الخادم شيئًا ما في دفق إخراج المقبس ، يمكن للعميل قراءة المحتوى المقابل من خلال دفق إدخال المقبس. يتم توصيل المقبس والمقبس في اتجاهين ، بحيث يمكن للعميل أيضًا كتابة الأشياء في دفق إخراج المقبس المقابل ، ثم يمكن لدفق إدخال المقبس المقابل للخادم قراءة المحتوى المقابل. فيما يلي بعض الأمثلة على التواصل من جانب الخادم مع العملاء:
1. كتابة العميل وقراءة الخادم
خادم رمز Java
خادم الفئة العامة {public static void main (string args []) يلقي ioException {// for simplicity ، يتم طرح جميع معلومات الاستثناء من منفذ int = 8899 ؛ // تحديد Serversocke الاستماع على المنفذ 8899 ServerSocket Server = New ServersOcept (PORT) ؛ // يحاول الخادم تلقي طلبات الاتصال من مآخذ أخرى. طريقة قبول الخادم هي مقبس مقبس الحظر = server.accept () ؛ // بعد إنشاء اتصال مع العميل ، يمكننا الحصول على إدخال المقبس وقراءة المعلومات التي أرسلها العميل. reader reader = new inputStreamReader (socket.getInputStream ()) ؛ char chars [] = New Char [64] ؛ int len ؛ StringBuilder sb = new StringBuilder () ؛ بينما ((len = reader.read (chars))! = -1) {sb.append (سلسلة جديدة (chars ، 0 ، len)) ؛ } system.out.println ("من العميل:" + sb) ؛ reader.close () ؛ socket.close () ؛ server.close () ؛ }}يتم تشغيل تشغيل الخادم لقراءة البيانات من مقبس inputStream أيضًا. إذا لم تتم قراءة البيانات من دفق الإدخال ، فسيبقى البرنامج هناك حتى يكتب العميل البيانات في دفق إخراج المقبس أو يغلق دفق إخراج المقبس. بالطبع ، وينطبق الشيء نفسه على مآخذ العميل. بعد اكتمال العملية ، تذكر إغلاق الموارد المقابلة قبل انتهاء البرنامج بأكمله ، أي إغلاق دفق IO المقابل والمقبس.
كود العميل Java
عميل الفئة العامة {public static void main (String args []) يرمي الاستثناء {// للبساطة ، يتم طرح جميع الاستثناءات مباشرة string stox = "127.0.0.1" ؛ // عنوان IP للخادم المراد توصيله هو منفذ int = 8899 ؛ // منفذ الاستماع المقابل للخادم المراد توصيله // يتم إنشاء الاتصال باستخدام عميل Server Socket = مقبس جديد (مضيف ، منفذ) ؛ // بعد إنشاء الاتصال ، يمكنك كتابة البيانات إلى كاتب الخادم = New OutputStreamWriter (client.getOutputStream ()) ؛ Writer.write ("Hello Server.") ؛ الكاتب. client.close () ؛ }}عند كتابة البيانات إلى دفق إخراج المقبس ، يجب أن تنتبه إلى شيء واحد. إذا كان البرنامج لا يتوافق مع إيقاف تشغيل دفق الإخراج بعد عملية الكتابة ، ولكنه يقوم بعمليات حظر أخرى (مثل قراءة البيانات من دفق الإدخال) ، تذكر أن تتغلب عليها. وبهذه الطريقة ، يمكن للخادم تلقي البيانات التي يرسلها العميل ، وإلا فقد يتسبب في انتظار بعضها البعض. سيتم ذكر هذه المشكلة لاحقًا عند الحديث عن قراءة العميل والخادم والكتابة في نفس الوقت.
2. العميل والخادم يقرأ ويكتبان في نفس الوقت
كما ذكرنا سابقًا ، تتواصل Sockets بطرق ثنائية الاتجاه ، والتي يمكن أن تتلقى البيانات وإرسال البيانات.
خادم رمز Java
خادم الفئة العامة {public static void main (string args []) يلقي ioException {// for simplicity ، يتم طرح جميع معلومات الاستثناء من منفذ int = 8899 ؛ // تحديد Serversocke الاستماع على المنفذ 8899 ServerSocket Server = New ServersOcept (PORT) ؛ // يحاول الخادم تلقي طلبات الاتصال من مآخذ أخرى. طريقة قبول الخادم هي مقبس مقبس الحظر = server.accept () ؛ // بعد إنشاء اتصال مع العميل ، يمكننا الحصول على إدخال المقبس وقراءة المعلومات التي أرسلها العميل. reader reader = new inputStreamReader (socket.getInputStream ()) ؛ char chars [] = New Char [64] ؛ int len ؛ StringBuilder sb = new StringBuilder () ؛ بينما ((len = reader.read (chars))! = -1) {sb.append (سلسلة جديدة (chars ، 0 ، len)) ؛ } system.out.println ("من العميل:" + sb) ؛ // اكتب جملة بعد قراءة كاتب تكنولوجيا المعلومات = New OutputStreamWriter (socket.getOutputStream ()) ؛ Writer.write ("Hello Client.") ؛ الكاتب. flush () ؛ الكاتب. reader.close () ؛ socket.close () ؛ server.close () ؛ }}في الكود أعلاه ، قرأنا أولاً البيانات المرسلة من قبل العميل من دفق الإدخال ، ثم اكتب البيانات في دفق الإخراج إلى العميل ، ثم أغلق ملف المورد المقابل. في الواقع ، قد لا يتم تشغيل الكود أعلاه بالطريقة التي افترضناها مقدمًا ، لأن قراءة البيانات من دفق الإدخال هي عملية حظر. عندما تتم قراءة البيانات في ما ورد أعلاه أثناء الحلقة ، سيتم تنفيذ هيئة الحلقة ، وإلا سيتم حظرها ، بحيث لن يتم تنفيذ عمليات الكتابة اللاحقة. ستتوقف حلقة بينما ما لم يتم إغلاق المقبس المقابل للعميل وحظره. إن حل هذا الموقف حيث قد لا يتم تنفيذه هو أن الحلقة يجب أن يتم القفز بشكل مشروط. عند النظر إلى الكود أعلاه ، فإن الشيء الوحيد الذي يتغير هو طول LEN والبيانات التي يتم قراءتها. لم يعد لين قابلاً للاستخدام ، والشيء الوحيد الذي يمكن استخدامه هو البيانات التي تتم قراءتها. في هذه الحالة ، نتفق عادة على علامة نهاية. عندما تحتوي البيانات التي يرسلها العميل على علامة نهاية معينة ، فهذا يعني أنه تم إرسال البيانات الحالية ، وفي هذا الوقت يمكننا الخروج. ثم سيبدو الرمز المحسن هكذا:
كود جافا
خادم الفئة العامة {public static void main (string args []) يلقي ioException {// for simplicity ، يتم طرح جميع معلومات الاستثناء من منفذ int = 8899 ؛ // تحديد Serversocke الاستماع على المنفذ 8899 ServerSocket Server = New ServersOcept (PORT) ؛ // يحاول الخادم تلقي طلبات الاتصال من مآخذ أخرى. طريقة قبول الخادم هي مقبس مقبس الحظر = server.accept () ؛ // بعد إنشاء اتصال مع العميل ، يمكننا الحصول على إدخال المقبس وقراءة المعلومات التي أرسلها العميل. reader reader = new inputStreamReader (socket.getInputStream ()) ؛ char chars [] = New Char [64] ؛ int len ؛ StringBuilder sb = new StringBuilder () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ بينما ((len = reader.read (chars))! = -1) {temp = new string (chars ، 0 ، len) ؛ if ((index = temp.indexof ("eof"))! = -1) {// يتم إنهاء الاستقبال عند مواجهة eof sb.append (temp.substring (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ } system.out.println ("من العميل:" + sb) ؛ // اكتب جملة بعد قراءة الكاتب = New OutputStreamWriter (socket.getOutputStream ()) ؛ Writer.write ("Hello Client.") ؛ الكاتب. flush () ؛ الكاتب. reader.close () ؛ socket.close () ؛ server.close () ؛ }}في الرمز أعلاه ، عندما يقرأ الخادم علامة النهاية التي يرسلها العميل ، أي "EOF" ، سيتم إنهاء استقبال البيانات وسيتم إنهاء الحلقة ، بحيث يمكن الاستمرار في الكود اللاحق.
كود العميل Java
عميل الفئة العامة {public static void main (String args []) يرمي الاستثناء {// للبساطة ، يتم طرح جميع الاستثناءات مباشرة string stox = "127.0.0.1" ؛ // عنوان IP للخادم المراد توصيله منفذ int = 8899 ؛ // منفذ الاستماع المقابل للخادم المراد توصيله // يتم إنشاء الاتصال باستخدام عميل Server Socket = مقبس جديد (مضيف ، منفذ) ؛ // بعد إنشاء الاتصال ، يمكنك كتابة البيانات إلى كاتب الخادم = New OutputStreamWriter (client.getOutputStream ()) ؛ Writer.write ("Hello Server.") ؛ الكاتب. flush () ؛ // اقرأ بعد كتابة قارئ القارئ = جديد inputStreamReader (client.getInputStream ()) ؛ char chars [] = New Char [64] ؛ int len ؛ StringBuffer SB = New StringBuffer () ؛ بينما ((len = reader.read (chars))! = -1) {sb.append (سلسلة جديدة (chars ، 0 ، len)) ؛ } system.out.println ("من الخادم:" + sb) ؛ الكاتب. reader.close () ؛ client.close () ؛ }}في الكود أعلاه ، أرسلنا أولاً قطعة من البيانات إلى الخادم ، ثم نقرأ البيانات التي يتم إرجاعها بواسطة الخادم. مثل الخادم السابق ، قد يتسبب ذلك في تعليق البرنامج هناك طوال الوقت ولا يقفز أبدًا من الحلقة. يتم دمج هذا الرمز مع الكود الأول للخادم ، فقط دعنا نحلل أن الخادم سيتلقى دائمًا البيانات هناك ، ولن يقفز أبدًا من الحلقة ، لذلك لن يكون هناك خادم لاحق لإرجاع البيانات إلى العميل ، ولن يتمكن العميل من تلقي البيانات التي يتم إرجاعها بواسطة الخادم. يظهر الحل في الكود الثاني للخادم. بعد أن يرسل العميل البيانات ، اكتب علامة نهائية في دفق الإخراج لإخبار الخادم بأنه قد تم إرسال البيانات. يرسل الخادم أيضًا علامة لإخبار العميل بعد إرجاع البيانات. ثم يجب أن يبدو رمز العميل المعدل هكذا:
كود جافا
عميل الفئة العامة {public static void main (String args []) يرمي الاستثناء {// للبساطة ، يتم طرح جميع الاستثناءات مباشرة string stox = "127.0.0.1" ؛ // عنوان IP للخادم المراد توصيله هو منفذ int = 8899 ؛ // منفذ الاستماع المقابل للخادم المراد توصيله // يتم إنشاء الاتصال باستخدام عميل Server Socket = مقبس جديد (مضيف ، منفذ) ؛ // بعد إنشاء الاتصال ، يمكنك كتابة البيانات إلى كاتب الخادم = New OutputStreamWriter (client.getOutputStream ()) ؛ Writer.write ("Hello Server.") ؛ Writer.Write ("EOF") ؛ الكاتب. flush () ؛ // اقرأ بعد كتابة قارئ القارئ = جديد inputStreamReader (client.getInputStream ()) ؛ char chars [] = New Char [64] ؛ int len ؛ StringBuffer SB = New StringBuffer () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ بينما ((len = reader.read (chars))! = -1) {temp = new string (chars ، 0 ، len) ؛ if ((index = temp.indexof ("eof"))! = -1) {sb.append (temp.substring (0 ، index)) ؛ استراحة؛ } sb.append (سلسلة جديدة (chars ، 0 ، len)) ؛ } system.out.println ("من الخادم:" + sb) ؛ الكاتب. reader.close () ؛ client.close () ؛ }}النموذج الأكثر شيوعًا الذي نستخدمه في الحياة اليومية هو أن العميل يرسل البيانات إلى الخادم ، ويتلقى الخادم البيانات ويعيد النتائج المقابلة إلى العميل. ومع ذلك ، لم تعد هناك علاقة فردية بين العميل والخادم ، ولكن الموقف الذي يتوافق فيه العديد من العملاء مع نفس الخادم كما هو مذكور أدناه.
3. العديد من العملاء يتصلون بنفس الخادم
بالنسبة إلى الأمثلة المذكورة أعلاه ، ينتهي الخادم بعد تلقي طلب العميل ولا يمكنه تلقي طلبات من عملاء آخرين ، والتي لا يمكن في كثير من الأحيان تلبية متطلباتنا. عادة ما نفعل هذا:
كود جافا
خادم الفئة العامة {public static void main (string args []) يلقي ioException {// for simplicity ، يتم طرح جميع معلومات الاستثناء من منفذ int = 8899 ؛ // تحديد Serversocke الاستماع على المنفذ 8899 ServerSocket Server = New ServersOcept (PORT) ؛ بينما (صحيح) {// يحاول الخادم تلقي طلبات الاتصال من مآخذ أخرى. طريقة قبول الخادم هي مقبس مقبس الحظر = server.accept () ؛ // بعد إنشاء اتصال مع العميل ، يمكننا الحصول على إدخال المقبس وقراءة المعلومات التي أرسلها العميل. reader reader = new inputStreamReader (socket.getInputStream ()) ؛ char chars [] = New Char [64] ؛ int len ؛ StringBuilder sb = new StringBuilder () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ بينما ((len = reader.read (chars))! = -1) {temp = new string (chars ، 0 ، len) ؛ if ((index = temp.indexof ("eof"))! = -1) {// يتم إنهاء الاستقبال عند مواجهة eof sb.append (temp.substring (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ } system.out.println ("من العميل:" + sb) ؛ // اكتب جملة بعد قراءة الكاتب = New OutputStreamWriter (socket.getOutputStream ()) ؛ Writer.write ("Hello Client.") ؛ الكاتب. flush () ؛ الكاتب. reader.close () ؛ socket.close () ؛ }}} في الكود أعلاه ، استخدمنا حلقة ميتة ، حيث يستدعي Serversocket طريقة قبولها لمحاولة تلقي طلب اتصال من العميل. عند عدم استلام الطلب ، سيتم حظر البرنامج هنا حتى يتلقى طلب الاتصال من العميل ، ثم التواصل مع العميل الذي أنشأ الاتصال. بعد ذلك ، سيقوم بعد ذلك بتنفيذ جسم الحلقة ومحاولة تلقي طلب اتصال جديد مرة أخرى. وبهذه الطريقة ، يمكن لـ ServersOcept تلقي طلبات الاتصال من جميع العملاء والتواصل معهم. هذا ينفذ طريقة بسيطة للاتصال مع عملاء متعددين على خادم واحد.
في المثال أعلاه ، على الرغم من أنه يتم تنفيذ خادم واحد للتواصل مع عملاء متعددين ، لا تزال هناك مشكلة. في المثال أعلاه ، يتعامل خادمنا مع طلب اتصال العميل بشكل متزامن. في كل مرة نتلقى فيها طلب اتصال من العميل ، يجب علينا أولاً التواصل مع العميل الحالي قبل أن نتمكن من معالجة طلب الاتصال التالي. سيؤثر هذا بشكل خطير على أداء البرنامج عندما يكون هناك المزيد من التزامن. لهذا السبب ، يمكننا تغييره إلى معالجة التواصل غير المتزامنة التالية مع العميل:
كود جافا
خادم الفئة العامة {public static void main (string args []) يلقي ioException {// for simplicity ، يتم طرح جميع معلومات الاستثناء من منفذ int = 8899 ؛ // تحديد Serversocke الاستماع على المنفذ 8899 ServerSocket Server = New ServersOcept (PORT) ؛ بينما (صحيح) {// يحاول الخادم تلقي طلبات الاتصال من مآخذ أخرى. طريقة قبول الخادم هي مقبس مقبس الحظر = server.accept () ؛ // في كل مرة يتم استلام مقبس ، يتم إنشاء مؤشر ترابط جديد للتعامل معه مؤشر ترابط جديد (مهمة جديدة (مقبس)). start () ؛ }} / ** * * / static Class Task تنفذ Runnable {Socket Socket ؛ المهمة العامة (مقبس المقبس) {this.socket = socket ؛ } public void run () {try {standlesocket () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ }} / *** التواصل مع مقبس العميل* athrows استثناء* / private void مقابض () يلقي استثناء {reader reader = new inputStreamReader (socket.getInputStream ()) ؛ char chars [] = New Char [64] ؛ int len ؛ StringBuilder sb = new StringBuilder () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ بينما ((len = reader.read (chars))! = -1) {temp = new string (chars ، 0 ، len) ؛ if ((index = temp.indexof ("eof"))! = -1) {// يتم إنهاء الاستقبال عند مواجهة eof sb.append (temp.substring (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ } system.out.println ("من العميل:" + sb) ؛ // اكتب جملة بعد قراءة الكاتب = New OutputStreamWriter (socket.getOutputStream ()) ؛ Writer.write ("Hello Client.") ؛ الكاتب. flush () ؛ الكاتب. reader.close () ؛ socket.close () ؛ }}} في الكود أعلاه ، في كل مرة يتلقى ServersOcept طلبًا جديدًا لاتصال المقبس ، سيتم إنشاء مؤشر ترابط جديد للتواصل مع المقبس الحالي ، والذي سيحقق المعالجة غير المتزامنة للاتصال مع مقبس العميل.
عند استلام البيانات من مقبس الإدخال ، فإن القراءة قليلاً مثل ما سبق معقدة للغاية. في بعض الأحيان ، سنستخدم BufferedReader لقراءة سطر واحد في كل مرة ، مثل:
كود جافا
خادم الفئة العامة {public static void main (string args []) يلقي ioException {// for simplicity ، يتم طرح جميع معلومات الاستثناء من منفذ int = 8899 ؛ // تحديد Serversocke الاستماع على المنفذ 8899 ServerSocket Server = New ServersOcept (PORT) ؛ بينما (صحيح) {// يحاول الخادم تلقي طلبات الاتصال من مآخذ أخرى. طريقة قبول الخادم هي مقبس مقبس الحظر = server.accept () ؛ // في كل مرة يتم استلام مقبس ، يتم إنشاء مؤشر ترابط جديد للتعامل معه مؤشر ترابط جديد (مهمة جديدة (مقبس)). start () ؛ }} / ** * * / static Class Task تنفذ Runnable {Socket Socket ؛ المهمة العامة (مقبس المقبس) {this.socket = socket ؛ } public void run () {try {standlesocket () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ }} / *** التواصل مع مقبس العميل* athrows استثناء* / private void مقابض () يلقي الاستثناء {bufferedreader br = جديد bufferedreader (new inputStreamReader (socket.getInputStream ())) ؛ StringBuilder sb = new StringBuilder () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ بينما ((temp = br.readline ())! = null) {system.out.println (temp) ؛ if ((index = temp.indexof ("eof"))! = -1) {// إنهاء الاستقبال عند مواجهة eof sb.append (temp.substring (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ } system.out.println ("من العميل:" + sb) ؛ // اكتب جملة بعد قراءة الكاتب = New OutputStreamWriter (socket.getOutputStream ()) ؛ Writer.write ("Hello Client.") ؛ Writer.Write ("EOF/N") ؛ الكاتب. flush () ؛ الكاتب. br.close () ؛ socket.close () ؛ }}}في هذا الوقت ، تجدر الإشارة إلى أن طريقة القراءة لـ BufferedReader تقرأ سطرًا واحدًا في وقت واحد. تم حظر هذه الطريقة. لن يستمر البرنامج في التنفيذ حتى يقرأ سطر واحد من البيانات. إذن متى ستقرأ READLINE خطًا؟ لن تعتقد طريقة ReadLine أنه تم قراءة سطر حتى يواجه البرنامج سطرًا جديدًا أو حرفًا نهائيًا للتيار المقابل. سوف ينهي انسداده ويسمح للبرنامج باستمرار التنفيذ. لذلك ، عندما نستخدم خط القراءة BufferredReader لقراءة البيانات ، يجب أن نتذكر أن تكتب فواصل الأسطر في دفق الإخراج المقابل (سيتم تمييزه تلقائيًا كنهاية بعد انتهاء الدفق ، ويمكن التعرف على خط القراءة). بعد كتابة فواصل الخط ، يجب أن نتذكر التدفق إذا لم يتم إغلاق دفق الإخراج على الفور ، بحيث يتم كتابة البيانات حقًا من المخزن المؤقت. المقابلة للرمز أعلاه ، يجب كتابة برنامج عميلنا مثل هذا:
كود جافا
عميل الفئة العامة {public static void main (String args []) يرمي الاستثناء {// للبساطة ، يتم طرح جميع الاستثناءات مباشرة string stox = "127.0.0.1" ؛ // عنوان IP للخادم المراد توصيله هو منفذ int = 8899 ؛ // منفذ الاستماع المقابل للخادم المراد توصيله // يتم إنشاء الاتصال باستخدام عميل Server Socket = مقبس جديد (مضيف ، منفذ) ؛ // بعد إنشاء الاتصال ، يمكنك كتابة البيانات إلى كاتب الخادم = New OutputStreamWriter (client.getOutputStream ()) ؛ Writer.write ("Hello Server.") ؛ Writer.Write ("EOF/N") ؛ الكاتب. flush () ؛ // اقرأ بعد كتابة BufferedReader BR = جديد BufferedReader (New InputStreamReader (client.getInputStream ())) ؛ StringBuffer SB = New StringBuffer () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ بينما ((temp = br.readline ())! = null) {if ((index = temp.indexof ("eof")! = -1) {sb.append (temp.subString (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ } system.out.println ("من الخادم:" + sb) ؛ الكاتب. br.close () ؛ client.close () ؛ }}4. اضبط وقت المهلة
لنفترض أن هناك شرطًا لدرجة أن عميلنا يحتاج إلى الحصول على معلومات XX من الخادم من خلال المقبس ثم عرضها على المستخدم على الصفحة. نحن نعلم أن Socket يحظر عند قراءة البيانات ، وإذا لم تقرأ البيانات ، فسيستمر البرنامج في الحجب هناك. عند مزامنة الطلب ، يجب ألا نسمح بحدوث مثل هذا الموقف. هذا يتطلب منا التحكم في مقاطعة الحظر بعد أن يصل الطلب إلى وقت معين حتى يتمكن البرنامج من الاستمرار في التشغيل. يوفر لنا Socket طريقة SetSotimeOut () لتعيين الوقت المهلة للبيانات المستلمة بالميلي ثانية. عندما يكون وقت المهلة المحدد أكبر من 0 ، وبعد هذا الوقت لم يتلق المقبس البيانات التي تم إرجاعها ، فإن المقبس سوف يرمي SockettimeOutException.
لنفترض أننا بحاجة إلى التحكم في عميلنا لمقاطعة وحظرها قبل قراءة البيانات لمدة 10 ثوانٍ بعد البدء في قراءة البيانات ، يمكننا القيام بذلك:
كود جافا
عميل الفئة العامة {public static void main (String args []) يرمي الاستثناء {// للبساطة ، يتم طرح جميع الاستثناءات مباشرة string stox = "127.0.0.1" ؛ // عنوان IP للخادم المراد توصيله هو منفذ int = 8899 ؛ // منفذ الاستماع المقابل للخادم المراد توصيله // يتم إنشاء الاتصال باستخدام عميل Server Socket = مقبس جديد (مضيف ، منفذ) ؛ // بعد إنشاء الاتصال ، يمكنك كتابة البيانات إلى كاتب الخادم = New OutputStreamWriter (client.getOutputStream ()) ؛ Writer.write ("Hello Server.") ؛ Writer.Write ("EOF/N") ؛ الكاتب. flush () ؛ // اقرأ بعد كتابة BufferedReader BR = جديد BufferedReader (New InputStreamReader (client.getInputStream ())) ؛ // قم بتعيين المهلة على 10 ثوان عميل. setsotimeout (10*1000) ؛ StringBuffer SB = New StringBuffer () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ حاول {بينما ((temp = br.readline ())! = null) {if ((index = temp.indexof ("eof")! = -1) {sb.append (temp.substring (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ }} catch (SockettimeOutException e) {system.out.println ("timeout timeout.") ؛ } system.out.println ("من الخادم:" + sb) ؛ الكاتب. br.close () ؛ client.close () ؛ }}5. استلام رمز مشجعة البيانات
في مثل هذه الحالات عندما يتلقى الخادم أو العميل رمزًا صينيًا مشوهًا ، يكون ذلك عادةً لأن الترميز المستخدم عند إرسال البيانات غير متسق مع الترميز المستخدم عند استلام البيانات. على سبيل المثال ، هناك رمز خادم مثل هذا:
كود جافا
خادم الفئة العامة {public static void main (string args []) يلقي ioException {// for simplicity ، يتم طرح جميع معلومات الاستثناء من منفذ int = 8899 ؛ // تحديد Serversocke الاستماع على المنفذ 8899 ServerSocket Server = New ServersOcept (PORT) ؛ بينما (صحيح) {// يحاول الخادم تلقي طلبات الاتصال من مآخذ أخرى. طريقة قبول الخادم هي مقبس مقبس الحظر = server.accept () ؛ // في كل مرة يتم استلام مقبس ، يتم إنشاء مؤشر ترابط جديد للتعامل معه مؤشر ترابط جديد (مهمة جديدة (مقبس)). start () ؛ }} / ** * * / static Class Task تنفذ Runnable {Socket Socket ؛ المهمة العامة (مقبس المقبس) {this.socket = socket ؛ } public void run () {try {standlesocket () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ }} / *** التواصل مع مقبس العميل* athrows استثناء* / private void مقابض () يلقي الاستثناء {bufferedReader br = new BufferedReader (inputStreamReader جديد (socket.getInputStream () ، "GBK")) ؛ StringBuilder sb = new StringBuilder () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ بينما ((temp = br.readline ())! = null) {system.out.println (temp) ؛ if ((index = temp.indexof ("eof"))! = -1) {// end undept at in eof eof sb.append (temp.SubString (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ } system.out.println ("العميل:" + sb) ؛ // اكتب جملة بعد قراءة كاتب الكاتب = جديد outputStreamWriter (socket.getOutputStream () ، "UTF-8") ؛ Writer.write ("مرحبًا ، عميل.") ؛ Writer.Write ("EOF/N") ؛ الكاتب. flush () ؛ الكاتب. br.close () ؛ socket.close () ؛ }}}أنا مرتبك قليلاً عندما استخدمته هنا للاختبار. في رمز الخادم أعلاه ، نحدد بوضوح استخدام ترميز GBK لقراءة البيانات عند تحديد دفق الإدخال ، ونحدد بوضوح أن استخدام ترميز UTF-8 لإرسال البيانات عند تحديد دفق الإخراج. إذا لم يرسل العميل بيانات في ترميز GBK عند إرسال بيانات على العميل ، فمن المحتمل أن يتم تشويه البيانات التي يتلقاها الخادم ؛ وبالمثل ، إذا لم يرسل العميل ترميز البيانات عند إرسال بيانات على الخادم ، أي ترميز UTF-8 لتلقي البيانات ، فمن المحتمل جدًا أن تحدث البيانات المشوهة. لذلك ، بالنسبة لرمز الخادم أعلاه ، من أجل تمكين برنامجنا من قراءة البيانات التي يرسلها الطرف الآخر بدون رمز مشوه ، يجب أن يكون عميلنا هكذا:
كود جافا
عميل الفئة العامة {public static void main (String args []) يرمي الاستثناء {// للبساطة ، يتم طرح جميع الاستثناءات مباشرة string stox = "127.0.0.1" ؛ // عنوان IP للخادم المراد توصيله منفذ int = 8899 ؛ // منفذ الاستماع المقابل للخادم المراد توصيله // يتم إنشاء الاتصال باستخدام عميل Server Socket = مقبس جديد (مضيف ، منفذ) ؛ // بعد إنشاء الاتصال ، يمكنك كتابة البيانات إلى كاتب الخادم = New OutputStreamWriter (client.getOutputStream () ، "GBK") ؛ Writer.write ("Hello ، Server.") ؛ Writer.Write ("EOF/N") ؛ الكاتب. flush () ؛ // اقرأ بعد كتابة BufferedReader BR = جديد BufferEdReader (New InputStreamReader (client.getInputStream () ، "UTF-8")) ؛ // قم بتعيين المهلة على 10 ثوان عميل. setsotimeout (10*1000) ؛ StringBuffer SB = New StringBuffer () ؛ سلسلة درجة الحرارة ؛ مؤشر int ؛ حاول {بينما ((temp = br.readline ())! = null) {if ((index = temp.indexof ("eof")! = -1) {sb.append (temp.substring (0 ، index)) ؛ استراحة؛ } sb.append (temp) ؛ }} catch (SockettimeOutException e) {system.out.println ("timeout timeout.") ؛ } system.out.println ("server:" + sb) ؛ الكاتب. br.close () ؛ client.close () ؛ }}تم تجميع هذه المقالة في "ملخص لتقنيات تشغيل Java Upload" ، وكل شخص مرحب به للتعلم والقراءة.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.