जावा में नेटवर्क प्रोग्रामिंग एक सुपरपावर क्यों है?
\n\nकल्पना करें: आप कोड लिख रहे हैं, और अचानक आपका प्रोग्राम दुनिया के दूसरे छोर पर किसी दूसरे प्रोग्राम से संवाद करना शुरू कर देता है। यह अनुरोध भेजता है, प्रतिक्रिया प्राप्त करता है, डेटा सिंक्रोनाइज़ करता है - और यह सब मिलीसेकंड में। यह जादू नहीं है, यह जावा में नेटवर्क प्रोग्रामिंग है। यदि आप केवल स्थानीय उपयोगिताएँ नहीं, बल्कि वास्तविक वितरित सिस्टम, चैट, ऑनलाइन गेम या REST सेवाएँ बनाना चाहते हैं - तो नेटवर्क प्रोग्रामिंग के बिना काम नहीं चलेगा।
\n\nJava इसके लिए एक शक्तिशाली टूलकिट प्रदान करता है: क्लासिक Socket और ServerSocket से लेकर उच्च-प्रदर्शन Java NIO (नॉन-ब्लॉकिंग I/O) और आधुनिक WebSockets तक। इस लेख में, हम तीनों दृष्टिकोणों का विश्लेषण करेंगे, लाइव कोड लिखेंगे और समझेंगे कि अपने कार्य के लिए सही उपकरण कैसे चुनें। चलिए शुरू करते हैं!
1. क्लासिक सॉकेट: "जल्दी से" TCP चैट
\n\nआइए मूल बातों से शुरू करें। जावा में सॉकेट TCP/IP की दुनिया का प्रवेश द्वार है। सर्वर एक ServerSocket बनाता है, एक पोर्ट सुनता है, कनेक्शन स्वीकार करता है। क्लाइंट एक Socket बनाता है और सर्वर से जुड़ता है। यह उतना ही सरल है जितना दो और दो का जोड़।
एक सरल इको सर्वर लिखना
\n\nसर्वर क्लाइंट से एक संदेश प्राप्त करता है और उसे वापस भेजता है (इको)। कोड न्यूनतम है, लेकिन पूरे सार को दर्शाता है:
\n\nimport java.io.*;\nimport java.net.*;\n\npublic class EchoServer {\n public static void main(String[] args) {\n try (ServerSocket serverSocket = new ServerSocket(12345)) {\n System.out.println("सर्वर पोर्ट 12345 पर शुरू हुआ...");\n Socket clientSocket = serverSocket.accept(); // कनेक्शन तक ब्लॉक रहता है\n System.out.println("क्लाइंट जुड़ा: " + clientSocket.getInetAddress());\n\n BufferedReader in = new BufferedReader(\n new InputStreamReader(clientSocket.getInputStream()));\n PrintWriter out = new PrintWriter(\n clientSocket.getOutputStream(), true);\n\n String inputLine;\n while ((inputLine = in.readLine()) != null) {\n System.out.println("प्राप्त: " + inputLine);\n out.println("इको: " + inputLine);\n if (inputLine.equalsIgnoreCase("exit")) break;\n }\n } catch (IOException e) {\n e.printStackTrace();\n }\n }\n}\n\n\nऔर यहाँ एक क्लाइंट है जो संदेश भेजता है:
\n\nimport java.io.*;\nimport java.net.*;\n\npublic class EchoClient {\n public static void main(String[] args) throws IOException {\n Socket socket = new Socket("localhost", 12345);\n PrintWriter out = new PrintWriter(socket.getOutputStream(), true);\n BufferedReader in = new BufferedReader(\n new InputStreamReader(socket.getInputStream()));\n BufferedReader stdIn = new BufferedReader(\n new InputStreamReader(System.in));\n\n String userInput;\n System.out.println("संदेश दर्ज करें (बाहर निकलने के लिए exit):");\n while ((userInput = stdIn.readLine()) != null) {\n out.println(userInput);\n System.out.println("सर्वर का उत्तर: " + in.readLine());\n if (userInput.equalsIgnoreCase("exit")) break;\n }\n socket.close();\n }\n}\n\n\nयहाँ क्या महत्वपूर्ण है? विधि accept() और readLine() थ्रेड को ब्लॉक करती हैं। इसका मतलब है कि जब तक एक क्लाइंट संवाद कर रहा है, अन्य प्रतीक्षा करते हैं। समाधान - मल्टीथ्रेडिंग।
मल्टीथ्रेडेड सर्वर: कई क्लाइंट को संभालना
\n\nप्रत्येक नए कनेक्शन के लिए, हम एक अलग थ्रेड बनाते हैं। हम ExecutorService थ्रेड पूल का उपयोग करते हैं ताकि व्यर्थ में हजारों थ्रेड न बनाएँ:
import java.io.*;\nimport java.net.*;\nimport java.util.concurrent.*;\n\npublic class MultiThreadedServer {\n private static final int PORT = 12345;\n private static final ExecutorService threadPool = Executors.newFixe