مقبس Java: إنشاء تطبيق دردشة عميل / خادم
في هذا البرنامج التعليمي ، ستتعلم كيفية إنشاء تطبيق دردشة جافا بين جهازين باستخدام المقابس. قبل البدء في جزء البرمجة ، تحتاج إلى تكوين شبكتك لجعل هذين الجهازين يتفاعلان على الشبكة المحلية لمنزلك على سبيل المثال. سنقوم بتنفيذ ما رأيناه من الناحية النظرية: نموذج العميل / الخادم المعروف.بنهاية هذا البرنامج التعليمي ، ستعرف كيف يمكن للمقابس تبادل الرسائل.
الخادم< / span >< / h2>يقوم javaserver> بتهيئة الاتصال، ويستمع إلى منفذ، وينتظر قبول الاتصالات الواردة. على سبيل المثال ، رقم المنفذ هو 5000 ، يرسل العميل طلبا إلى الخادم برقم المنفذ هذا 5000. يقبل الخادم الطلب وينقل معلوماته (عنوان IP) إلى العميل. الآن تم إنشاء الاتصال ويمكن أن يتم تبادل الرسائل.
< / span >< span style = "عائلة الخط: وراثة ؛" توفر >Java حزمة java.net< / i> تتعامل مع كل شيء عن الشبكات ، ما عليك سوى فئتين: < / span >< / span >
- java.net.ServerSocket: تقبل هذه الفئة الاتصالات من clients.
- java.net.Socket: يتصل هذا الفصل بالجهاز البعيد.
تحتاج أيضا إلى أداة لإدخال وإرسال واستقبال الدفق: < / span>
- مسح: قراءة مدخلات لوحة المفاتيح.< / span >< / li>
- BufferedReader: قراءة النص المستلم من المرسل.
- PrintWriter: أرسل النص المكتوب.< / span>< / li>< / ul>
ServerSocket socketserver ؛
مقبس مقبس الخادم ؛
النهائي BufferedReader في ؛
كاتب الطباعة النهائي ؛
final الماسح الضوئي sc = ماسح ضوئي جديد (System.in) ؛
try {
socketserver = ServerSocket الجديد (5000) ؛
serversocket = socketserver.accept ();
out = PrintWriter الجديد (serversocket.getOutputStream ()) ؛
in = BufferedReader جديد (InputStreamReader جديد (serversocket.getInputStream ())) ؛
سلسلة ق ؛
s = sc.next ();
out.println (s) ؛
out.flush ();
سلسلة message_client ؛
message_client = in.readLine ();
System.out.println ("العميل: "+message_client);
}
catch (IOException e) {
e.printStackTrace();
}
بعد إنشاء مقبس الخادم ، الذي يحتوي على رقم المنفذ 5000 ، ينتظر الخادم الاتصالات الواردة ، وبمجرد اكتشاف أحدها ، فإنه يقبلها. المتغيران اللذان يتعاملان مع تدفق القراءة والكتابة in و out< / span> ليتم ربطها مباشرة بدفق الإرسال والاستقبال.
المتغير ق < / سبان> يخزن النص المكتوب باستخدام نمط next() ، ثم يتم إرسالها بنمط println (s) < / span>.
نمط flush () < / span> مهم لأنه يمسح المخزن المؤقت للكتابة إلى الإخراج وإلا فإن نمط null< / span> بواسطة الجهاز الآخر.
المتغير message_client< / span > يخزن الرسالة الإيصال الذي يتم عرضه مع نمط println().
يتمثل قيد هذا الرمز في أنه قادر على إرسال واستقبال رسالة مرة واحدة فقط. سيكون لديك فكرة في الاعتبار: إضافة حلقة بينما (صحيح) < / امتداد>. هذا صحيح ، ولكن إذا ، على سبيل المثال ، يرسل الخادم رسالة إلى العميل ، فلن يتمكن العميل من استرداد الرسالة حتى يرسلها أيضا. الحل الأمثل هو إنشاء خيطين: أحدهما للإرسال والآخر للاستقبال. تسمح كلتا العمليتين بحدوث الإرسال والاستقبال في وقت واحد.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/ * < br / > * www.codeurjava.com
* /
خادم الفئة العامة {
الفراغ الثابت العام الرئيسي (اختبار السلسلة [] ) {
النهائي ServerSocket serverSocket ؛
عميل المقبس النهائي ؛
النهائي BufferedReader في ؛
كاتب الطباعة النهائي ؛
الماسح الضوئي sc = الماسح الضوئي الجديد (System.in) ؛
try {
serverSocket = ServerSocket الجديد (5000) ؛
clientSocket = serverSocket.accept ();
out = PrintWriter جديد (clientSocket.getOutputStream ()) ؛
in = BufferedReader جديد (InputStreamReader جديد (clientSocket.getInputStream()));
إرسال مؤشر الترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
بينما (صحيح) {
msg = sc.nextLine ();
out.println (رسالة) ؛
out.flush ();
}
}
}) ؛
send.start ();
تلقي مؤشر الترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
try {
msg = in.readLine ();
//طالما أن العميل متصل
بينما(msg!=null){
System.out.println("العميل: "+msg);
msg = in.readLine ();
}
//exit from the loop إذا كان العميل قد قام بفك
System.out.println ("العميل deconected") ؛
// إغلاق الدفق ومقبس الجلسة
out.close () ؛
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}) ؛
receive.start();
}catch (IOException e) {
e.printStackTrace();
}
}
}
< / pre>
الفصل بين العمليتين واضح ، يمكن للخادم والعميل تبادل البيانات في أي وقت وبلا حدود. تختبر حلقة التشغيل أثناء التشغيل ما إذا كان الاتصال لا يزال قائما أم لا. تذكر إغلاق تدفقات القراءة والكتابة بالإضافة إلى الاتصال بعد الخروج من الحلقة باستخدام إغلاق () < / امتداد>.
Client< / h2>يحتاج العميل فقط إلى نمط المقبس < / الامتداد> لإنشاء اتصال server، على يأخذ المنشئ عنوان IP الخاص بالخادم ورقم المنفذ كمدخلات. بقية الكود هو نفس الكود الخاص ب server.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
/ * < br / > * www.codeurjava.com
* /
عميل الفئة العامة {
الفراغ العام الثابت الرئيسي (سلسلة [] args) {
النهائي Socket clientSocket ؛
النهائي BufferedReader في ؛
كاتب الطباعة النهائي ؛
الماسح الضوئي النهائي sc = ماسح ضوئي جديد (System.in) ؛// للقراءة من لوحة المفاتيح
try {
/*
* معلومات الخادم (المنفذ وعنوان IP أو اسم المضيف
* 127.0.0.1 هو العنوان المحلي للجهاز
* /
clientSocket = مقبس جديد ("127.0.0.1" ، 5000);
// stream لإرسال
out = PrintWriter جديد (clientSocket.getOutputStream ()) ؛
// stream لتلقي
in = BufferedReader جديد (جديد InputStreamReader (clientSocket.getInputStream ())) ؛
إرسال مؤشر ترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
بينما (صحيح) {
msg = sc.nextLine ();
out.println (رسالة) ؛
out.flush ();
}
}
}) ؛
send.start ();
تلقي مؤشر ترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
try {
msg = in.readLine ();
while(msg!=null){
System.out.println("Server: "+msg);
msg = in.readLine ();
}
System.out.println ("خادم Deconected");
out.close ();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}) ؛
receive.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
< / pre>
ServerSocket socketserver ؛بعد إنشاء مقبس الخادم ، الذي يحتوي على رقم المنفذ 5000 ، ينتظر الخادم الاتصالات الواردة ، وبمجرد اكتشاف أحدها ، فإنه يقبلها. المتغيران اللذان يتعاملان مع تدفق القراءة والكتابة in و out< / span> ليتم ربطها مباشرة بدفق الإرسال والاستقبال.
مقبس مقبس الخادم ؛
النهائي BufferedReader في ؛
كاتب الطباعة النهائي ؛
final الماسح الضوئي sc = ماسح ضوئي جديد (System.in) ؛
try {
socketserver = ServerSocket الجديد (5000) ؛
serversocket = socketserver.accept ();
out = PrintWriter الجديد (serversocket.getOutputStream ()) ؛
in = BufferedReader جديد (InputStreamReader جديد (serversocket.getInputStream ())) ؛
سلسلة ق ؛
s = sc.next ();
out.println (s) ؛
out.flush ();
سلسلة message_client ؛
message_client = in.readLine ();
System.out.println ("العميل: "+message_client);
}
catch (IOException e) {
e.printStackTrace();
}
المتغير ق < / سبان> يخزن النص المكتوب باستخدام نمط next() ، ثم يتم إرسالها بنمط println (s) < / span>.
نمط flush () < / span> مهم لأنه يمسح المخزن المؤقت للكتابة إلى الإخراج وإلا فإن نمط null< / span> بواسطة الجهاز الآخر.
المتغير message_client< / span > يخزن الرسالة الإيصال الذي يتم عرضه مع نمط println().
يتمثل قيد هذا الرمز في أنه قادر على إرسال واستقبال رسالة مرة واحدة فقط. سيكون لديك فكرة في الاعتبار: إضافة حلقة بينما (صحيح) < / امتداد>. هذا صحيح ، ولكن إذا ، على سبيل المثال ، يرسل الخادم رسالة إلى العميل ، فلن يتمكن العميل من استرداد الرسالة حتى يرسلها أيضا. الحل الأمثل هو إنشاء خيطين: أحدهما للإرسال والآخر للاستقبال. تسمح كلتا العمليتين بحدوث الإرسال والاستقبال في وقت واحد.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/ * < br / > * www.codeurjava.com
* /
خادم الفئة العامة {
الفراغ الثابت العام الرئيسي (اختبار السلسلة [] ) {
النهائي ServerSocket serverSocket ؛
عميل المقبس النهائي ؛
النهائي BufferedReader في ؛
كاتب الطباعة النهائي ؛
الماسح الضوئي sc = الماسح الضوئي الجديد (System.in) ؛
try {
serverSocket = ServerSocket الجديد (5000) ؛
clientSocket = serverSocket.accept ();
out = PrintWriter جديد (clientSocket.getOutputStream ()) ؛
in = BufferedReader جديد (InputStreamReader جديد (clientSocket.getInputStream()));
إرسال مؤشر الترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
بينما (صحيح) {
msg = sc.nextLine ();
out.println (رسالة) ؛
out.flush ();
}
}
}) ؛
send.start ();
تلقي مؤشر الترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
try {
msg = in.readLine ();
//طالما أن العميل متصل
بينما(msg!=null){
System.out.println("العميل: "+msg);
msg = in.readLine ();
}
//exit from the loop إذا كان العميل قد قام بفك
System.out.println ("العميل deconected") ؛
// إغلاق الدفق ومقبس الجلسة
out.close () ؛
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}) ؛
receive.start();
}catch (IOException e) {
e.printStackTrace();
}
}
}
< / pre>
الفصل بين العمليتين واضح ، يمكن للخادم والعميل تبادل البيانات في أي وقت وبلا حدود. تختبر حلقة التشغيل أثناء التشغيل ما إذا كان الاتصال لا يزال قائما أم لا. تذكر إغلاق تدفقات القراءة والكتابة بالإضافة إلى الاتصال بعد الخروج من الحلقة باستخدام إغلاق () < / امتداد>.Client< / h2>
يحتاج العميل فقط إلى نمط المقبس < / الامتداد> لإنشاء اتصال server، على يأخذ المنشئ عنوان IP الخاص بالخادم ورقم المنفذ كمدخلات. بقية الكود هو نفس الكود الخاص ب server.import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
/ * < br / > * www.codeurjava.com
* /
عميل الفئة العامة {
الفراغ العام الثابت الرئيسي (سلسلة [] args) {
النهائي Socket clientSocket ؛
النهائي BufferedReader في ؛
كاتب الطباعة النهائي ؛
الماسح الضوئي النهائي sc = ماسح ضوئي جديد (System.in) ؛// للقراءة من لوحة المفاتيح
try {
/*
* معلومات الخادم (المنفذ وعنوان IP أو اسم المضيف
* 127.0.0.1 هو العنوان المحلي للجهاز
* /
clientSocket = مقبس جديد ("127.0.0.1" ، 5000);
// stream لإرسال
out = PrintWriter جديد (clientSocket.getOutputStream ()) ؛
// stream لتلقي
in = BufferedReader جديد (جديد InputStreamReader (clientSocket.getInputStream ())) ؛
إرسال مؤشر ترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
بينما (صحيح) {
msg = sc.nextLine ();
out.println (رسالة) ؛
out.flush ();
}
}
}) ؛
send.start ();
تلقي مؤشر ترابط = مؤشر ترابط جديد (جديد Runnable () {
سلسلة msg ؛
@Override
تشغيل الفراغ العام () {
try {
msg = in.readLine ();
while(msg!=null){
System.out.println("Server: "+msg);
msg = in.readLine ();
}
System.out.println ("خادم Deconected");
out.close ();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}) ؛
receive.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
< / pre>