English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
برمجة الشبكة هي كتابة برامج تعمل على أجهزة متعددة (كمبيوترات) مرتبطة عبر اتصال شبكة.
تتضمن حزمة java.net API الخاصة بـ J2SE أنواعًا وواجهات توفر تفاصيل اتصال سطحية. يمكنك استخدام هذه الأنواع والواجهات مباشرة للتركيز على حل المشكلة وليس تفاصيل الاتصال.
يقدم حزمة java.net دعمًا لبروتوكولي الشبكة الشائعين:
TCPTCP (باللغة الإنجليزية: Transmission Control Protocol، بروتوكول التحكم في النقل) هو بروتوكول اتصال، موثوق، يعتمد على تدفق البيانات في طبقة الترانزيت من نماذج OSI، يقع طبقة TCP فوق طبقة IP، تحت طبقة التطبيق. يضمن TCP التواصل المتبادل بين تطبيقين. يستخدم عادة في بروتوكول الإنترنت، ويُسمى TCP / IP.
UDPUDP (باللغة الإنجليزية: User Datagram Protocol، بروتوكول نقل البيانات الخاص بالمستخدم)، يقع في طبقة الترانزيت في نموذج OSI. بروتوكول غير مرتبط. يوفر بيانات جاءت للاستخدام من تطبيقات. بسبب عدم وجود الثقة في UDP وكونه بروتوكول غير مرتبط، فإن التطبيقات يجب أن تسمح ببعض فقدان أو تكرار أو بيانات خاطئة.
يشرح هذا الدرس موضوعين رئيسيين.
برمجة Socket:هذا هو المفهوم الشبكي الأكثر استخدامًا، وتم شرحه بشكل مفصل للغاية.
معالجة URL:سيتم شرح هذا الجزء في نطاق آخر، انقر هنا للحصول على مزيد من التفاصيل حول معالجة URL بلغة Java.
استخدمت Socket في TCP تقديم آلية اتصال بين جهازين كمبيوتر. يصنع برنامج العميل كائنة Socket ويحاول الاتصال بكائنة Socket الخاصة بالخادم.
عند إقامة الاتصال، يصنع الخادم كائنة Socket. يمكن للعميل والخادم الآن التواصل من خلال كتابة وقراءة كائنة Socket.
تمثل كلاس java.net.Socket socket، وكلاس java.net.ServerSocket يوفر ميكانيكية لبرنامج الخادم لمراقبة العملاء، وبناء الاتصالات معهم.
تظهر هذه الخطوات عند إنشاء اتصال TCP بين جهازين باستخدام socket:
يصنع الخادم كائن ServerSocket يمثل الاتصال عبر الميناء على الخادم.
يطلب الخادم من كلاس ServerSocket طريقة accept()، والتي تنتظر إلى أن يتصل العميل بالخادم على الميناء المحدد.
عندما يكون الخادم في حالة الإنتظار، يصنع العميل كائن Socket ويحدد اسم الخادم وميناء الطلب للاتصال.
يحاول بناء كلاس Socket ربط العملاء بالخادم المحدد والميناء. إذا تم إنشاء الاتصال، يتم إنشاء كائن Socket في العميل يمكنه التواصل مع الخادم.
في الخادم، يعود طريقة accept() إلى مرجع socket جديد على الخادم، والذي يتصل بsocket للعميل.
بعد إنشاء الاتصال، يتم إجراء الاتصال من خلال استخدام تيارات I/O، وكل socket يحتوي على تيار إدخال وتيار خروج، ويتصل تيار الإدخال للعميل بتيار الخروج للخادم، وتيار الإدخال للخادم بتيار الخروج للعميل.
TCP هو بروتوكول اتصال ثنائي الاتجاه، لذا يمكن إرسال البيانات من خلال اثنين من تيارات البيانات في نفس الوقت. يقدم بعض هذه الكلاسات مجموعة كاملة من الطرق المفيدة لتحقيق socket.
يستخدم تطبيق الخادم كلاس java.net.ServerSocket للحصول على ميناء ومراقبة طلبات العملاء.
يملك كلاس ServerSocket أربعة طرق بناء:
الرقم | وصف الطريقة |
1 | public ServerSocket(int port) throws IOException إنشاء وصلات خادم مرتبطة بميناء معين. |
2 | public ServerSocket(int port, int backlog) throws IOException استخدام backlog المحدد لإنشاء وصلات套كتك والربط إلى الميناء المحلي المحدد. |
3 | public ServerSocket(int port, int backlog, InetAddress address) throws IOException استخدام الميناء المحدد، الاستماع إلى backlog وال عنوان IP المحلي المحدد لإنشاء خادم. |
4 | public ServerSocket() throws IOException يُنشئ جهاز الاتصال الخادم غير المُرتبط. |
يُنشئ جهاز الاتصال الخادم غير المُرتبط. إذا لم يُلقي بناء ServerSocket استثناءً، فإن هذا يعني أن تطبيقك قد تم بناؤه بنجاح على الميناء المحدد وأنه يُستمع إلى طلبات العملاء.
هناك بعض الطرق الشائعة لفئة ServerSocket:
الرقم | وصف الطريقة |
1 | public int getLocalPort() يُرجع هذا الميناء الذي يُستمع إليه هذا جهاز الاتصال. |
2 | public Socket accept() throws IOException يُستمع ويُقبل الاتصال إلى هذا جهاز الاتصال. |
3 | public void setSoTimeout(int timeout) يُفعّل/يُلغي SO_TIMEOUT عبر تحديد قيمة الزمن المحدد بالأمثلة، بالأمثلة. |
4 | public void bind(SocketAddress host, int backlog) يُربط ServerSocket إلى عنوان معين (عنوان IP وميناء) |
فئة java.net.Socket تمثل جهاز الاتصال الذي يستخدمه كل من العملاء والخوادم للتواصل مع بعضهم البعض. يجب على العملاء الحصول على جهاز الاتصال من خلال التمثيل، بينما يتم الحصول على جهاز الاتصال من قبل الخوادم من خلال مُعادلة accept().
يُمتلك فئة Socket خمس طرق بناء.
الرقم | وصف الطريقة |
1 | public Socket(String host, int port) throws UnknownHostException, IOException. يُنشئ جهاز الاتصال السلس ويُربط إلى المضيف المحدد على الميناء المحدد. |
2 | public Socket(InetAddress host, int port) throws IOException يُنشئ جهاز الاتصال السلس ويُربط إلى عنوان IP المحدد على الميناء المحدد. |
3 | public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. يُنشئ جهاز الاتصال ويُربط إلى المضيف المحدد على الميناء المحدد في المضيف البعيد. |
4 | public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. إنشاء مُقبس وربطه بالمنفذ المحدد في العنوان المرجعي البعيد. |
5 | public Socket() إنشاء مُقبس غير متصل من خلال SocketImpl النوعي المحدد من النظام. |
عندما يعود طريقة Socket بناءً على عدم وجود مثال بسيط لإنشاء مُعادلة Socket، فهي في الواقع تحاول الاتصال بالخادم المحدد والمنفذ.
إليك بعض الطرق المثيرة للاهتمام، يُلاحظ أن لديك Socket على جانب العميل والخادم، لذا يمكن للعميل والخادم استدعاء هذه الطرق.
الرقم | وصف الطريقة |
1 | public void connect(SocketAddress host, int timeout) throws IOException إعادة الاتصال هذا المقبس بالخادم وتحديد قيمة زمن الإنتظار. |
2 | public InetAddress getInetAddress() يُرجع عنوان الاتصال هذا المقبس. |
3 | public int getPort() يُرجع المنفذ النهائي الذي يُتصل به هذا المقبس. |
4 | public int getLocalPort() يُرجع المُرتبطة هذا المقبس بالمنفذ المحلي. |
5 | public SocketAddress getRemoteSocketAddress() يُرجع عنوان النقطة النهائية للاتصال هذا المقبس، إذا لم يكن متصلاً فيُرجع null. |
6 | public InputStream getInputStream() throws IOException يُرجع مدخل هذا المقبس. |
7 | public OutputStream getOutputStream() throws IOException يُرجع流出 هذا المقبس. |
8 | public void close() throws IOException إغلاق هذا المقبس. |
هذه الفئة تمثل عنوان Protocal الإنترنت (IP). إليك قائمة بالطرق المفيدة في برمجة Socket:
الرقم | وصف الطريقة |
1 | static InetAddress getByAddress(byte[] addr) يُرجع مُعادلة InetAddress عند تقديم عنوان IP الأصلي. |
2 | static InetAddress getByAddress(String host, byte[] addr) يُنشأ InetAddress بناءً على اسم المضيف ومسار IP. |
3 | static InetAddress getByName(String host) يحدد عنوان IP للمضيف في حالة اسم المضيف المعطى. |
4 | String getHostAddress() يعود إلى عنوان IP كـ String (بشكل نصي). |
5 | String getHostName() يستخرج اسم المضيف الذي يحتوي على هذا العنوان IP. |
6 | static InetAddress getLocalHost() يعود إلى المضيف المحلي. |
7 | String toString() تحويل هذا العنوان IP إلى String. |
GreetingClient التالية هي برنامج عميل، يربط هذا البرنامج بخدمة Socket على الخادم ويرسل طلبًا ثم ينتظر استجابة.
// اسم الملف GreetingClient.java import java.net.*; import java.io.*; public class GreetingClient { public static void main(String [] args) { String serverName = args[0]; int port = Integer.parseInt(args[1]); try { System.out.println("اتصال بالمضيف: " + serverName + "، عدد المنفذ: " + port); Socket client = new Socket(serverName, port); System.out.println("عنوان المضيف البعيد: " + client.getRemoteSocketAddress()); OutputStream outToServer = client.getOutputStream(); DataOutputStream out = new DataOutputStream(outToServer); out.writeUTF("مرحبًا من " + client.getLocalSocketAddress()); InputStream inFromServer = client.getInputStream(); DataInputStream in = new DataInputStream(inFromServer); System.out.println("استجابة الخادم: " + in.readUTF()); client.close(); catch(IOException e) { e.printStackTrace(); } } }
如下的GreetingServer 程序是一个服务器端应用程序,使用 Socket 来监听一个指定的端口。
// 文件名 GreetingServer.java import java.net.*; import java.io.*; public class GreetingServer extends Thread { private ServerSocket serverSocket; public GreetingServer(int port) throws IOException { serverSocket = new ServerSocket(port); serverSocket.setSoTimeout(10000); } public void run() { while(true) { try { System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "..."); Socket server = serverSocket.accept(); System.out.println("远程主机地址:" + server.getRemoteSocketAddress()); DataInputStream in = new DataInputStream(server.getInputStream()); System.out.println(in.readUTF()); DataOutputStream out = new DataOutputStream(server.getOutputStream()); out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!"); server.close(); }catch(SocketTimeoutException s) { System.out.println("Socket timed out!"); break; catch(IOException e) { e.printStackTrace(); break; } } } public static void main(String [] args) { int port = Integer.parseInt(args[0]); try { Thread t = new GreetingServer(port); t.run(); catch(IOException e) { e.printStackTrace(); } } }
أعد كتابة الكود في ملفي Java التاليين، وأecute الأوامر التالية لبدء الخدمة، باستخدام ميناء 6066:
$ javac GreetingServer.java $ java GreetingServer 6066 الانتظار للاتصال البعيد، ميناء: 6066...
افتح نافذة أوامر جديدة، وأecute الأوامر التالية لفتح العميل:
$ javac GreetingClient.java $ java GreetingClient localhost 6066 الاتصال بالمضيف: localhost، ميناء: 6066 عنوان المستضيف البعيد: localhost/127.0.0.1:6066 استجابة الخادم: شكراً على الاتصال بي: /127.0.0.1:6066 وداعاً!