JavaRush /جاوا بلاگ /Random-SD /ساکٽ ۽ سرور ساڪٽ ڪلاس، يا "هيلو، سرور؟ ڇا تون مونکي ٻڌي س...
Sergey Simonov
سطح
Санкт-Петербург

ساکٽ ۽ سرور ساڪٽ ڪلاس، يا "هيلو، سرور؟ ڇا تون مونکي ٻڌي سگهين ٿو؟"

گروپ ۾ شايع ٿيل
تعارف: ”ٽيبل تي هڪ ڪمپيوٽر هو، ان جي پويان هڪ انڪوڊر هو...“ ساکٽ ۽ سرور ساڪٽ ڪلاس، يا "هيلو، سرور؟  ڇا تون مونکي ٻڌي سگهين ٿو؟"  - 1 هڪ دفعي، منهنجي هڪ هم جماعت پنهنجي جاوا جي مطالعي جو ٻيو نتيجو پوسٽ ڪيو، هڪ نئين پروگرام جي اسڪرين شاٽ جي صورت ۾. هي پروگرام هڪ گهڻ استعمال ڪندڙ چيٽ هو. ان وقت مان صرف هن ٻوليءَ ۾ پروگرامنگ جي مهارت حاصل ڪرڻ ۾ پنهنجو سفر شروع ڪري رهيو هوس، پر مون پنهنجي لاءِ ضرور نوٽ ڪيو ته ”مان اهو چاهيان ٿو! وقت گذري ويو ۽، منهنجي پروگرامنگ جي ڄاڻ کي وڌيڪ مضبوط ڪرڻ جي حصي جي طور تي ايندڙ منصوبي تي ڪم ختم ڪرڻ، مون کي اهو واقعو ياد آيو ۽ فيصلو ڪيو ته اهو وقت آهي. ڪنهن نه ڪنهن طرح مون اڳ ۾ ئي هن موضوع کي مڪمل طور تي تجسس کان ٻاهر ڳولڻ شروع ڪيو، پر منهنجي مکيه جاوا درسي ڪتاب ۾ (اهو Schildt جو مڪمل دستور هو) صرف 20 صفحا java.net پيڪيج لاءِ مهيا ڪيا ويا. اهو سمجھڻ وارو آهي - ڪتاب اڳ ۾ ئي تمام وڏو آهي. مکيه طبقن جي طريقن ۽ تعمير ڪندڙن جا جدول هئا، پر اهو سڀ ڪجهه آهي. ايندڙ قدم آهي، يقينا، غالب گوگل: مختلف مضمونن جا هزارين، جتي ساڳي شيء پيش ڪئي وئي آهي - ساکٽ بابت ٻه يا ٽي لفظ، ۽ هڪ تيار ڪيل مثال. ڪلاسيڪي انداز (گهٽ ۾ گهٽ منهنجي مطالعي جي انداز ۾) پهرين اهو سمجهڻ آهي ته مون کي ڪم لاءِ ڪهڙن اوزارن جي ضرورت آهي، اهي ڇا آهن، انهن جي ضرورت ڇو آهي، ۽ صرف پوءِ، جيڪڏهن مسئلي جو حل واضح نه هجي، تياري سان ٽڪرائجي. - ٺهيل لسٽون، نٽ ۽ بولٽ کي ختم ڪرڻ. پر مون سمجهيو ته ڇا هو ۽ آخرڪار هڪ ملٽي يوزر چيٽ لکيو. ٻاهران، اهو ڪجهه هن طرح نڪتو: ساکٽ ۽ سرور ساڪٽ ڪلاس، يا "هيلو، سرور؟  ڇا تون مونکي ٻڌي سگهين ٿو؟"  - 2هتي آئون توهان کي سمجهڻ جي ڪوشش ڪندس ڪلائنٽ-سرور ايپليڪيشنن جي بنيادي ڳالهين جي بنياد تي جاوا ساکٽ استعمال ڪندي چيٽ ڊيزائن جو مثال. جاوارش ڪورس ۾ توهان چيٽ ڪندا. اهو هڪ مڪمل طور تي مختلف سطح تي هوندو، خوبصورت، وڏي، گھڻائي. پر سڀ کان پهريان، توهان کي هميشه بنياد رکڻ جي ضرورت آهي، تنهنڪري هتي اسان کي اهو ڄاڻڻ جي ضرورت آهي ته اهڙي حصي کي ڇا آهي. (جيڪڏهن توهان کي ڪا نقص يا غلطي ملي ٿي، PM ۾ يا آرٽيڪل هيٺ ڏنل تبصرو ۾ لکو). اچو ته شروع ڪريون. هيڊ ون: ”اهو گهر جيڪو...“ وضاحت ڪرڻ لاءِ ته ڪيئن هڪ نيٽ ورڪ ڪنيڪشن هڪ سرور ۽ هڪ ڪلائنٽ جي وچ ۾ ٿئي ٿو، اچو ته هڪ اپارٽمنٽ بلڊنگ جو هاڻوڪو مثال وٺون. اچو ته چوندا آهن هڪ ڪلائنٽ ڪنهن به طرح سان هڪ مخصوص سرور سان ڪنيڪشن قائم ڪرڻ جي ضرورت آهي. ڳولا ڪندڙ کي ڳولا واري اعتراض بابت ڇا ڄاڻڻ جي ضرورت آهي؟ ها، پتو. سرور بادل تي هڪ جادو ادارو نه آهي، ۽ تنهنڪري اهو هڪ مخصوص مشين تي واقع هجڻ گهرجي. ھڪڙي گھر سان مشابھت سان، جتي ٻنھي پارٽين تي اتفاق ٿيل گڏجاڻي ٿيڻ گھرجي. ۽ هڪ اپارٽمنٽ بلڊنگ ۾ هڪ ٻئي کي ڳولڻ لاء، عمارت جو هڪ پتو ڪافي ناهي؛ توهان کي لازمي طور تي اپارٽمنٽ جو تعداد ظاهر ڪرڻ گهرجي جنهن ۾ ملاقات ٿيندي. ساڳئي طرح، هڪ ڪمپيوٽر تي هڪ ئي وقت ۾ ڪيترائي سرور ٿي سگهن ٿا، ۽ ڪلائنٽ لاء هڪ مخصوص سان رابطو ڪرڻ لاء، هن کي پڻ پورٽ نمبر بيان ڪرڻ جي ضرورت آهي جنهن جي ذريعي ڪنيڪشن ٿيندي. تنهن ڪري، پتو ۽ پورٽ نمبر. هڪ پتو جو مطلب آهي هڪ مشين جي سڃاڻپ ڪندڙ انٽرنيٽ اسپيس ۾. اهو ڊومين نالو ٿي سگهي ٿو، مثال طور، "javarush.ru" ، يا هڪ باقاعده IP. بندرگاهه- هڪ منفرد نمبر جنهن سان هڪ مخصوص ساکٽ جڙيل آهي (هي اصطلاح بعد ۾ بحث ڪيو ويندو)، ٻين لفظن ۾، اهو هڪ خاص خدمت تي قبضو ڪيو ويو آهي ته جيئن ان سان رابطو ڪرڻ لاء استعمال ڪري سگهجي. تنهن ڪري، گهٽ ۾ گهٽ ٻه شيون هڪ (سرور) جي علائقي تي ملڻ لاء، علائقي جي مالڪ (سرور) کي ان (ڪار) تي هڪ مخصوص اپارٽمنٽ (پورٽ) تي قبضو ڪرڻ گهرجي، ۽ ٻئي کي ملڻ جي جڳهه کي ڄاڻڻ گهرجي. گھر جو پتو (ڊومين يا ip)، ۽ اپارٽمينٽ نمبر (پورٽ). هيڊ ٻه: Meet Socket نيٽ ورڪ تي ڪم ڪرڻ سان لاڳاپيل تصورن ۽ اصطلاحن مان، هڪ تمام اهم ساکٽ آهي. اهو نقطو ظاهر ڪري ٿو جنهن جي ذريعي ڪنيڪشن ٿئي ٿي. بس ڪر، هڪ ساکٽ نيٽ ورڪ تي ٻن پروگرامن کي ڳنڍيندو آهي. ڪلاس Socketهڪ ساکٽ جي خيال کي لاڳو ڪري ٿو. ڪلائنٽ ۽ سرور ان جي ان پٽ/آئوٽ پٽ چينلز ذريعي رابطو ڪندا: ساکٽ ۽ سرور ساڪٽ ڪلاس، يا "هيلو، سرور؟  ڇا تون مونکي ٻڌي سگهين ٿو؟"  - 3 هي ڪلاس ڪلائنٽ جي پاسي تي اعلان ڪيو ويو آهي، ۽ سرور ان کي ٻيهر ٺاهي ٿو، ڪنيڪشن سگنل وصول ڪندي. اهو ڪيئن آن لائن ڪميونيڪيشن ڪم ڪندو آهي. شروع ڪرڻ لاء، هتي ممڪن طبقي تعمير ڪندڙ آهن Socket:
Socket(String Name_хоста, int порт) throws UnknownHostException, IOException
Socket(InetAddress IP-address, int порт) throws UnknownHostException
"host_name" - مطلب آهي هڪ مخصوص نيٽ ورڪ نوڊ، IP پتو. جيڪڏهن ساکٽ ڪلاس ان کي حقيقي، موجوده پتي ۾ تبديل نه ڪري سگهيو، پوء هڪ استثنا اڇلايو ويندو UnknownHostException. بندرگاهه هڪ بندرگاهه آهي. جيڪڏهن 0 پورٽ نمبر جي طور تي بيان ڪيو ويو آهي، سسٽم پاڻ کي هڪ مفت بندرگاهه مختص ڪندو. هڪ استثنا پڻ ٿي سگهي ٿو جيڪڏهن ڪنيڪشن گم ٿي وڃي IOException. اهو ياد رکڻ گهرجي ته ايڊريس جو قسم ٻئي تعمير ڪندڙ ۾ آهي InetAddress. اهو بچاء لاء اچي ٿو، مثال طور، جڏهن توهان کي پتو ڏيڻ جي ضرورت آهي ڊومين جو نالو ايڊريس طور. انهي سان گڏ، جڏهن هڪ ڊومين جو مطلب آهي ڪيترن ئي IP پتي، InetAddressتوهان انهن کي استعمال ڪري سگهو ٿا انهن جي هڪ صف حاصل ڪرڻ لاء. بهرحال، اهو پڻ IP سان ڪم ڪري ٿو. توھان پڻ حاصل ڪري سگھو ٿا ھوسٽ جو نالو، بائيٽ ايري جيڪا ٺاھي ٿي IP پتي وغيره. اسان ان تي ٿورو اڳتي هلنداسين، پر توهان کي مڪمل تفصيلن لاءِ سرڪاري دستاويزن ڏانهن وڃڻو پوندو. جڏهن هڪ قسم جو اعتراض شروع ڪيو ويندو آهي Socket، ڪلائنٽ جنهن سان تعلق رکي ٿو نيٽ ورڪ تي اعلان ڪري ٿو ته اهو سرور سان ڳنڍڻ چاهي ٿو مخصوص ايڊريس ۽ پورٽ نمبر تي. هيٺ ڏنل ڪلاس جا سڀ کان وڌيڪ استعمال ٿيل طريقا آهن Socket: InetAddress getInetAddress()- ساکٽ بابت ڊيٽا تي مشتمل هڪ اعتراض ڏي ٿو. جيڪڏهن ساکٽ ڳنڍيل نه آهي - null int getPort()- بندرگاهن کي واپس ڏئي ٿو جنهن تي سرور سان ڪنيڪشن ٿئي ٿي int getLocalPort()- بندرگاهن کي واپس ڏئي ٿو جنهن سان ساکٽ پابند آهي. حقيقت اها آهي ته ڪلائنٽ ۽ سرور هڪ بندرگاهه تي "ڳالهائيندي" ڪري سگهن ٿا، پر اهي بندرگاهن جن تي اهي پابند آهن مڪمل طور تي مختلف ٿي سگهن ٿيون boolean isConnected()- واپسي صحيح آهي جيڪڏهن ڪنيڪشن قائم ٿئي void connect(SocketAddress address)- هڪ نئون ڪنيڪشن ظاهر ڪري boolean isClosed()- واپسي صحيح آهي، جيڪڏهن ساکٽ بند آهي. boolean isBound()- واپسي صحيح، جيڪڏهن ساکٽ اصل ۾ هڪ ايڊريس تي پابند آهي، ڪلاس Socketانٽرفيس کي لاڳو ڪري ٿو AutoCloseable، تنهنڪري اهو استعمال ڪري سگهجي ٿو try-with-resources. تنهن هوندي، توهان بند ڪري سگهو ٿا هڪ ساکٽ کلاسک طريقي سان، بند () استعمال ڪندي. هيڊ ٽي: ۽ هي هڪ سرور ساڪٽ آهي اچو ته چئو ته اسان اعلان ڪيو، هڪ طبقي جي صورت ۾ Socket، ڪلائنٽ جي پاسي تي ڪنيڪشن جي درخواست. سرور اسان جي خواهش جو اندازو ڪيئن لڳائيندو؟ ان لاءِ، سرور وٽ ھڪڙو طبقو آھي جھڙوڪ ServerSocket، ۽ ان ۾ قبول () طريقو آھي. ان جي تعمير ڪندڙ ھيٺ ڏنل آھن:
ServerSocket() throws IOException
ServerSocket(int порт) throws IOException
ServerSocket(int порт, int максимум_подключений) throws IOException
ServerSocket(int порт, int максимум_подключений, InetAddress локальный_address) throws IOException
جڏهن اعلان ڪيو وڃي، ServerSocket توهان کي ڪنيڪشن ايڊريس بيان ڪرڻ جي ضرورت ناهي، ڇاڪاڻ ته مواصلات سرور مشين تي ٿيندي آهي. صرف هڪ ملٽي چينل ميزبان سان توهان کي وضاحت ڪرڻ جي ضرورت آهي ته ڪهڙي IP سرور ساکٽ پابند آهي. Head Three.One: سرور جيڪو چوي ٿو نه، ڇاڪاڻ ته هڪ پروگرام مهيا ڪرڻ کان وڌيڪ وسيلن سان گڏ ان جي ضرورت کان وڌيڪ قيمتي ۽ غير معقول آهي، تنهنڪري تعمير ڪندڙ ۾ ServerSocketتوهان کي چيو ويندو آهي ته آپريشن دوران سرور پاران قبول ڪيل وڌ کان وڌ ڪنيڪشن جو اعلان ڪريو. جيڪڏهن اها وضاحت نه ڪئي وئي آهي، ته پوءِ ڊفالٽ طور هن نمبر کي 50 جي برابر سمجهيو ويندو. ها، نظريي ۾ اسان فرض ڪري سگهون ٿا ته ServerSocketاهو ساڳيو ساکٽ آهي، صرف سرور لاءِ. پر اهو ڪلاس کان بلڪل مختلف ڪردار ادا ڪري ٿو Socket. اهو صرف ڪنيڪشن ٺاهڻ جي اسٽيج تي گهربل آهي. هڪ قسم جو اعتراض ٺاهي، ServerSocketتوهان کي اهو ڳولڻ جي ضرورت آهي ته ڪو ماڻهو سرور سان ڳنڍڻ چاهي ٿو. قبول () طريقو هتي ڳنڍيل آهي. ھدف ان وقت تائين انتظار ڪري ٿو جيستائين ڪو ماڻھو ان سان ڳنڍڻ چاھي ٿو، ۽ جڏھن اھو ٿئي ٿو ته اھو ھڪڙي قسم جي اعتراض کي واپس ڪري ٿو Socket، اھو آھي، ھڪڙي ٺاھيل ڪلائنٽ ساکٽ. ۽ هاڻي ته ڪلائنٽ ساکٽ سرور جي پاسي تي ٺاهي وئي آهي، ٻه طرفي رابطي شروع ٿي سگهي ٿي. ڪلائنٽ جي پاسي تي هڪ قسم جو اعتراض ٺاهڻ Socket۽ ان کي سرور سائڊ استعمال ڪندي ٻيهر ٺاهڻ ServerSocketڪنيڪشن لاءِ گهٽ ۾ گهٽ گهربل آهي. هيڊ فور: سانتا کلاز ڏانهن خط Вопрос: ڪلائنٽ ۽ سرور ڪيئن ڳالهائيندا آهن؟ Ответ:I / O اسٽريمز ذريعي. اسان وٽ اڳ ۾ ئي ڇا آهي؟ سرور ايڊريس ۽ ڪلائنٽ جي پورٽ نمبر سان هڪ ساکٽ، ۽ ساڳئي شيء، قبول ڪرڻ جي مهرباني ()، سرور جي پاسي تي. تنهنڪري اهو سمجهڻ مناسب آهي ته اهي هڪ ساکٽ ذريعي گفتگو ڪندا. هن کي ڪرڻ لاء، اتي ٻه طريقا آهن جيڪي اسٽريم InputStream۽ OutputStreamشين جي قسم تائين رسائي ڏين ٿيون Socket. هتي اهي آهن:
InputStream getInputStream()
OutputStream getOutputStream()
جيئن ته بيئر بائيٽ پڙهڻ ۽ لکڻ ايترو ڪارائتو نه آهي، اسٽريم کي اڊاپٽر ڪلاس ۾ لپي سگهجي ٿو، بفر ٿيل يا نه. مثال طور:
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
رابطي لاء ٻه طرفي هجڻ لاء، اهڙيون آپريشنون ٻنهي طرفن تي ٿيڻ گهرجن. ھاڻي توھان ڪجھ موڪلي سگھو ٿا اندر استعمال ڪندي، ۽ ڪجھ حاصل ڪري سگھو ٿا ٻاھر استعمال ڪندي، ۽ ان جي برعڪس. دراصل، اهو عملي طور تي طبقي جو واحد ڪم آهي Socket. ۽ ها، فلش() طريقي جي باري ۾ نه وساريو BufferedWriter- اهو بفر جي مواد کي فلش ڪري ٿو. جيڪڏهن اهو نه ڪيو ويو آهي، معلومات منتقل نه ڪئي ويندي ۽ تنهن ڪري، وصول نه ڪيو ويندو. وصول ڪندڙ ٿريڊ پڻ انتظار ڪري ٿو پڄاڻي واري انڊيڪيٽر – “\n”، ٻي صورت ۾ پيغام قبول نه ڪيو ويندو، ڇاڪاڻ ته حقيقت ۾ پيغام مڪمل نه ٿيو آهي ۽ مڪمل ناهي. جيڪڏهن اهو توهان لاءِ تڪليف ڏيندڙ لڳي ٿو، پريشان نه ٿيو، توهان هميشه استعمال ڪري سگهو ٿا ڪلاس PrintWriter، جنهن کي ختم ڪرڻ جي ضرورت آهي، ٻئي دليل جي طور تي صحيح بيان ڪريو، ۽ پوء بفر مان پاپنگ خودڪار ٿي ويندي:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
انهي سان گڏ، لائن جي آخر کي ظاهر ڪرڻ جي ڪا ضرورت ناهي؛ هي طبقو اهو توهان لاء ڪندو آهي. پر ڇا اسٽرنگ I/O جي حد آهي جيڪو ساکٽ ڪري سگهي ٿو؟ نه، ڇا توھان شيون موڪلڻ چاھيو ٿا ساڪٽ اسٽريمز ذريعي؟ خدا جي واسطي. انهن کي ترتيب ڏيو ۽ توهان وڃڻ لاءِ سٺو آهيو:
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
هيڊ پنج: انٽرنيٽ ذريعي حقيقي ڪميونيڪيشن جيئن ته حقيقي نيٽ ورڪ ذريعي حقيقي IP پتي سان ڳنڍڻ لاءِ توهان کي هڪ مڪمل سرور جي ضرورت آهي، ۽ پوءِ:
  1. اسان جي مستقبل جي چيٽ، هڪ افاديت جي طور تي، اهڙيون صلاحيتون نه آهن. اهو صرف هڪ ڪنيڪشن قائم ڪري سگهي ٿو ۽ وصول ڪري سگهي ٿو / پيغام موڪليو. اهو آهي، ان ۾ حقيقي سرور صلاحيتون نه آهن.
  2. اسان جو سرور، جنهن ۾ صرف ساکٽ ڊيٽا ۽ I/O اسٽريم شامل آهن، حقيقي ويب يا ايف ٽي پي سرور طور ڪم نٿو ڪري سگهي، پوءِ صرف ان سان اسان انٽرنيٽ تي ڳنڍجي نه سگهنداسين.
۽ ان کان علاوه، اسان صرف پروگرام کي ترقي ڪرڻ شروع ڪري رهيا آهيون، جنهن جو مطلب آهي ته اهو ڪافي مستحڪم ناهي ته فوري طور تي حقيقي نيٽ ورڪ سان ڪم ڪري، تنهنڪري اسان مقامي ميزبان کي ڪنيڪشن ايڊريس طور استعمال ڪنداسين. اهو آهي، نظريي ۾، ڪلائنٽ ۽ سرور اڃا تائين ڪنهن به طريقي سان ڳنڍيل نه هوندا، سواء ساکٽ جي ذريعي، پر پروگرام کي ڊيبگ ڪرڻ لاء اهي ساڳيا مشين تي هوندا، نيٽ ورڪ تي حقيقي رابطي کان سواء. تعمير ڪندڙ ۾ ظاهر ڪرڻ لاء Socketته پتو مقامي آهي، اتي 2 طريقا آهن:
  1. ايڊريس جي دليل طور ”لوڪل هوسٽ“ لکو، معنيٰ مقامي اسٽب. "127.0.0.1" پڻ هن لاءِ موزون آهي - اهو صرف هڪ اسٽب جو هڪ ڊجيٽل فارم آهي.
  2. InetAddress استعمال ڪندي:
    1. InetAddress.getByName(null)- null پوائنٽون localhost ڏانهن
    2. InetAddress.getByName("localhost")
    3. InetAddress.getByName("127.0.0.1")
سادگي لاءِ، اسان استعمال ڪنداسين "لوڪل هوسٽ" قسم جو String. پر ٻيا سڀئي اختيار پڻ قابل عمل آهن. هيڊ ڇهون: اهو وقت آهي گفتگو جو، تنهن ڪري، اسان وٽ اڳ ۾ ئي سڀ ڪجهه آهي جيڪو اسان کي سرور سان گفتگو واري سيشن کي لاڳو ڪرڻ جي ضرورت آهي. اهو سڀ ڪجهه رهي ٿو ان کي گڏ ڪرڻ لاءِ: هيٺ ڏنل لسٽ ڏيکاري ٿي ته ڪلائنٽ ڪيئن سرور سان ڳنڍي ٿو، ان کي هڪ پيغام موڪلي ٿو، ۽ سرور، موڙ ۾، تصديق ڪري ٿو ته اهو پيغام حاصل ڪيو ويو آهي ان کي استعمال ڪندي ان ۾ دليل طور استعمال ڪندي: "سرور. جاوا"
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    private static Socket clientSocket; // socket for communication
    private static ServerSocket server; // server socket
    private static BufferedReader in; // socket read stream
    private static BufferedWriter out; // socket write stream

    public static void main(String[] args) {
        try {
            try  {
                server = new ServerSocket(4004); // server socket listening on port 4004
                System.out.println("Server is running!"); // server would be nice
                // announce your launch
                clientSocket = server.accept(); // accept() will wait until
                //someone won't want to connect
                try { // after establishing a connection and recreating the socket for communication with the client, you can go
                    // to create I/O streams.
                    // now we can receive messages
                    in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                    // and send
                    out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

                    String word = in.readLine(); // wait for the client to write something to us
                    System.out.println(word);
                    // without hesitation responds to the client
                    out.write("Hi, this is the Server! I confirm you wrote: " + word + "\n");
                    out.flush(); // push everything out of the buffer

                } finally { // in any case, the socket will be closed
                    clientSocket.close();
                    // streams would also be nice to close
                    in.close();
                    out.close();
                }
            } finally {
                System.out.println("Server closed!");
                    server.close();
            }
        } catch (IOException e) {
            System.err.println(e);
        }
    }
"Client.java"
import java.io.*;
import java.net.Socket;

public class Client {

    private static Socket clientSocket; // socket for communication
    private static BufferedReader reader; // we need a reader that reads from the console, otherwise
    // do we know what the client wants to say?
    private static BufferedReader in; // socket read stream
    private static BufferedWriter out; // socket write stream

    public static void main(String[] args) {
        try {
            try {
                // address - local host, port - 4004, same as the server
                clientSocket = new Socket("localhost", 4004); // with this line we request
                // the server has access to the connection
                reader = new BufferedReader(new InputStreamReader(System.in));
                // read messages from the server
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                // write there
                out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

                System.out.println("Did you have something to say? Enter it here:");
                // if the connection happened and the threads were successfully created - we can
                // work further and offer the client something to enter
                // if not, an exception will be thrown
                String word = reader.readLine(); // wait for the client to do something
                // will not write to the console
                out.write(word + "\n"); // send a message to the server
                out.flush();
                String serverWord = in.readLine(); // wait for the server to say
                System.out.println(serverWord); // received - display
            } finally { // in any case, you need to close the socket and streams
                System.out.println("The client has been closed...");
                clientSocket.close();
                in.close();
                out.close();
            }
        } catch (IOException e) {
            System.err.println(e);
        }

    }
}
يقينن، توهان کي پهريان سرور شروع ڪرڻ گهرجي، ڇو ته ڪلائنٽ شروع ٿيڻ تي ڇا سان ڳنڍيندو جيڪڏهن اتي ڪا شيء ناهي جيڪا ان کي ڳنڍيندي؟ :) آئوٽ پٽ هن طرح ٿيندو: /* ڇا توهان ڪجهه چوڻ چاهيو ٿا؟ ان کي هتي داخل ڪريو: هيلو، سرور؟ ڇا تون مونکي ٻڌي سگھين ٿو؟ هيلو، هي سرور آهي! مان تصديق ڪريان ٿو، توهان لکيو آهي: هيلو، سرور؟ ڇا تون مونکي ٻڌي سگھين ٿو؟ ڪلائنٽ بند ٿي ويو... */ هري! اسان سرور کي ڪلائنٽ سان گفتگو ڪرڻ سيکاريو! تنهن ڪري اهو ڪميونيڪيشن ٻن نقلن ۾ نه ٿي ٿئي، پر جيترو توهان چاهيو ٿا، صرف ٿريڊن جي پڙهڻ ۽ لکڻ کي ٿوري دير (سچو) لوپ ۾ لپيٽيو ۽ ٻاهر نڪرڻ لاءِ اشارو ڪيو ته، هڪ خاص پيغام جي مطابق، مثال طور، ”exit“. ، چڪر روڪيو ويو، ۽ پروگرام ختم ٿي ويندو. هيڊ سيون: ملٽي يوزر بهتر آهي. حقيقت اها آهي ته سرور اسان کي ٻڌي سگهي ٿو، پر اهو گهڻو بهتر ٿيندو جيڪڏهن اسان پنهنجي قسم جي ڪنهن سان رابطو ڪري سگهون ٿا. آئون آرٽيڪل جي آخر ۾ سڀني ذريعن کي ڳنڍيندس، تنهنڪري هتي آئون هميشه نه ڏيکاريندس وڏو، پر ڪوڊ جا اهم ٽڪرا جيڪي اهو ممڪن بڻائي سگهندا، جيڪڏهن صحيح طريقي سان استعمال ڪيو وڃي، هڪ گهڻن صارف جي چيٽ کي ترتيب ڏيڻ لاء. تنهن ڪري، اسان چاهيون ٿا ته سرور ذريعي ڪنهن ٻئي ڪلائنٽ سان گفتگو ڪرڻ جي قابل ٿي. اهو ڪيئن ڪجي؟ ظاهر آهي، ڇاڪاڻ ته ڪلائنٽ پروگرام جو پنهنجو طريقو آهي main، ان جو مطلب آهي ته اهو سرور کان الڳ ٿي سگهي ٿو ۽ ٻين مراجعين سان متوازي طور تي. هي اسان کي ڇا ڏئي ٿو؟ ڪنهن به صورت ۾، اهو ضروري آهي ته هر نئين ڪنيڪشن سان سرور فوري طور تي رابطي ۾ نه وڃي، پر هن ڪنيڪشن کي ڪنهن قسم جي فهرست ۾ لکي ۽ نئين ڪنيڪشن جو انتظار ڪرڻ لاء اڳتي وڌو، ۽ ڪنهن قسم جي معاون خدمت هڪ مخصوص رابطي سان رابطي ۾ مصروف آهي. گراهڪ. ۽ گراهڪن کي لازمي طور تي سرور ڏانهن لکڻو پوندو ۽ هڪ ٻئي جي آزاديءَ سان جواب جو انتظار ڪرڻ گهرجي. موضوع بچاء لاء ايندا. اچو ته چئو ته اسان وٽ ھڪڙو طبقو آھي جيڪو نون ڪنيڪشن کي ياد ڪرڻ لاء ذميوار آھي: اھو ھيٺ ڏنل بيان ڪيو وڃي.
  1. پورٽ نمبر.
  2. لسٽ جنهن ۾ اهو نئون ڪنيڪشن لکي ٿو.
  3. ۽ ServerSocket، ھڪڙي ھڪڙي (!) ڪاپي ۾.
public class Server {

    public static final int PORT = 8080;
    public static LinkedList<ServerSomthing> serverList = new LinkedList<>(); // list of all threads

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(PORT);
            try {
            while (true) {
                // Blocks until a new connection is made:
                Socket socket = server.accept();
                try {
                    serverList.add(new ServerSomthing(socket)); // add a new connection to the list
                } catch (IOException e) {
                    // If it fails, the socket is closed,
                    // otherwise, the thread will close it when it exits:
                    socket.close();
                }
            }
        } finally {
            server.close();
        }
    }
}
ٺيڪ، هاڻي هر ٺهيل ساکٽ گم نه ٿيندو، پر سرور تي ذخيرو ڪيو ويندو. اڳتي. هر گراهڪ کي ٻڌڻ جي ضرورت آهي. اچو ته آخري باب کان سرور جي ڪمن سان هڪ ٿريڊ ٺاهيون.
class ServerSomthing extends Thread {

    private Socket socket; // socket through which the server communicates with the client,
    // except for it - the client and server are not connected in any way
    private BufferedReader in; // socket read stream
    private BufferedWriter out; // socket write stream

    public ServerSomthing(Socket socket) throws IOException {
        this.socket = socket;
        // если потоку ввода/вывода приведут к генерированию исключения, оно пробросится дальше
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        start(); // call run()
    }
    @Override
    public void run() {
        String word;
        try {

            while (true) {
                word = in.readLine();
                if(word.equals("stop")) {
                    break;                }
                for (ServerSomthing vr : Server.serverList) {
                    vr.send(word); // send the received message with
                   // bound client to everyone else including him
                }
            }

        } catch (IOException e) {
        }
    }

    private void send(String msg) {
        try {
            out.write(msg + "\n");
            out.flush();
        } catch (IOException ignored) {}
    }
}
تنهن ڪري، سرور جي سلسلي جي تعمير ڪندڙ ۾، هڪ ساکٽ کي شروعات ڪرڻ گهرجي جنهن جي ذريعي موضوع هڪ مخصوص ڪلائنٽ سان رابطو ڪندو. انهي سان گڏ I/O موضوع، ۽ ٻيو سڀ ڪجهه توهان کي سڌو سنئون تعمير ڪندڙ کان هڪ موضوع شروع ڪرڻ جي ضرورت آهي. ٺيڪ آهي، پر ڇا ٿيندو جڏهن سرور ٿريڊ ڪلائنٽ مان هڪ پيغام پڙهي؟ صرف پنهنجي ڪلائنٽ ڏانهن واپس موڪليو؟ تمام گهڻو اثرائتو ناهي. اسان هڪ گھڻائي استعمال ڪندڙ چيٽ ٺاهي رهيا آهيون، تنهنڪري اسان کي هر هڪ ڳنڍيل ڪلائنٽ جي ضرورت آهي جيڪو هڪ شخص لکيو آهي. توهان کي انهن جي ڪلائنٽ سان لاڳاپيل سڀني سرور جي سلسلي جي فهرست استعمال ڪرڻ جي ضرورت آهي ۽ هر پيغام موڪليو هڪ مخصوص سلسلي ڏانهن موڪليو ته جيئن اهو ان کي پنهنجي ڪلائنٽ ڏانهن موڪلي:
for (ServerSomthing vr : Server.serverList) {
    vr.send(word); // send the received message
    // from the linked client to everyone else, including him
}
private void send(String msg) {
    try {
        out.write(msg + "\n");
        out.flush();
    } catch (IOException ignored) {}
}
هاڻي سڀني گراهڪن کي خبر پوندي ته انهن مان هڪ ڇا چيو! جيڪڏهن توهان نٿا چاهيو ته پيغام ان شخص ڏانهن موڪليو وڃي جنهن ان کي موڪليو آهي (هو اڳ ۾ ئي ڄاڻي ٿو ته هن ڇا لکيو آهي!)، بس جڏهن ٿريڊن ذريعي ورجائيندي، بيان ڪريو ته جڏهن ڪنهن شئي کي پروسيس ڪيو وڃي، لوپ thisبغير ڪارڪردگي جي ايندڙ عنصر ڏانهن منتقل ٿيندو. ان تي ڪو به عمل. يا، جيڪڏھن توھان چاھيو ٿا، ڪلائنٽ ڏانھن ھڪڙو پيغام موڪليو ته پيغام ڪاميابيء سان ملي ويو ۽ موڪليو ويو. هاڻي سرور سان سڀ ڪجهه واضح آهي. اچو ته ڪلائنٽ ڏانهن وڃو، يا بلڪه گراهڪن ڏانهن! اتي سڀ ڪجھ ساڳيو آھي، آخري باب کان ڪلائنٽ سان قياس ڪندي، صرف جڏھن توھان کي ضرورت آھي ھڪڙو مثال ٺاھيو، جيئن سرور سان ھن باب ۾ ڏيکاريو ويو آھي، ٺاھيندڙ ۾ سڀ ڪجھ ضروري ٺاھيو. پر ڇا ٿيندو، جڏهن هڪ گراهڪ ٺاهي، هن وٽ اڃا تائين ڪجهه داخل ڪرڻ جو وقت نه آهي، پر ڪجهه اڳ ۾ ئي موڪليو ويو آهي؟ (مثال طور، انهن جي correspondence جي تاريخ جيڪي اڳ ۾ ئي هن کان اڳ چيٽ سان ڳنڍيل آهن). تنهن ڪري اهي چڪر جن ۾ موڪليل پيغامن تي عمل ڪيو ويندو انهن کان الڳ ٿيڻ گهرجي جن ۾ پيغام ڪنسول مان پڙهيا ويندا آهن ۽ ٻين ڏانهن اڳتي وڌڻ لاءِ سرور ڏانهن موڪليا ويندا آهن. موضوع ٻيهر بچاء لاء ايندا. هڪ موضوع جي طور تي ڪلائنٽ ٺاهڻ ۾ ڪو به مقصد ناهي. اهو وڌيڪ آسان آهي ته هڪ لوپ سان ٿريڊ کي هلائڻ واري طريقي سان جيڪو پيغام پڙهي ٿو، ۽ پڻ، قياس سان، لکي ٿو:
// thread reading messages from the server
private class ReadMsg extends Thread {
    @Override
    public void run() {

        String str;
        try {
            while (true) {
                str = in.readLine(); // waiting for a message from the server
                if (str.equals("stop")) {

                    break; // exit the loop if it's "stop"
                }
                            }
        } catch (IOException e) {

        }
    }
}
// thread sending messages coming from the console to the server
public class WriteMsg extends Thread {

    @Override
    public void run() {
        while (true) {
            String userWord;
            try {
               userWord = inputUser.readLine(); // messages from the console
                if (userWord.equals("stop")) {
                    out.write("stop" + "\n");
                    break; // exit the loop if it's "stop"
                } else {
                    out.write(userWord + "\n"); // send to the server
                }
                out.flush(); // clean up
            } catch (IOException e) {

            }

        }
    }
}
ڪلائنٽ تعمير ڪندڙ ۾ توهان کي صرف انهن موضوعن کي شروع ڪرڻ جي ضرورت آهي. جيڪڏهن هو ڇڏڻ چاهي ٿو ته ڪلائنٽ جي وسيلن کي صحيح طريقي سان ڪيئن بند ڪيو وڃي؟ ڇا مون کي سرور جي سلسلي جا وسيلا بند ڪرڻ گهرجن؟ هن کي ڪرڻ لاء، توهان کي گهڻو ڪري هڪ الڳ طريقو ٺاهڻ جي ضرورت پوندي جنهن کي سڏيو ويندو آهي جڏهن پيغام لوپ مان نڪرڻ. اتي توهان کي ساکٽ ۽ I/O اسٽريمز کي بند ڪرڻ جي ضرورت پوندي. هڪ خاص ڪلائنٽ لاءِ ساڳيو سيشن آخر سگنل لازمي طور تي ان جي سرور واري سلسلي ڏانهن موڪليو وڃي، جيڪو لازمي طور تي ان جي ساکٽ سان ڪرڻ گهرجي ۽ پاڻ کي مکيه سرور ڪلاس ۾ موضوعن جي فهرست مان هٽائڻ گهرجي. هيڊ اٺ: تڪميل جي ڪا به حد ناهي توهان پنهنجي پروجيڪٽ کي بهتر ڪرڻ لاءِ لامحدود نيون خاصيتون ايجاد ڪري سگهو ٿا. پر ڇا واقعي هڪ نئين ڳنڍيل ڪلائنٽ ڏانهن منتقل ڪيو وڃي؟ مان سمجهان ٿو ته آخري ڏهه واقعا هن جي اچڻ کان اڳ ٿي ويا. هن کي ڪرڻ لاء، توهان کي هڪ ڪلاس ٺاهڻ جي ضرورت آهي جنهن ۾ ڪنهن به سرور جي سلسلي سان آخري عمل کي اعلان ڪيل فهرست ۾ داخل ڪيو ويندو، ۽ جيڪڏهن فهرست اڳ ۾ ئي ڀريل آهي (يعني 10 اڳ ۾ ئي آهن)، پهرين کي حذف ڪريو ۽ شامل ڪريو. آخري جيڪو آيو. هن لسٽ جي مواد کي نئين ڪنيڪشن ذريعي حاصل ڪرڻ لاء، جڏهن سرور ٿريڊ ٺاهي، آئوٽ اسٽريم ۾، توهان کي انهن کي ڪلائنٽ ڏانهن موڪلڻ جي ضرورت آهي. اهو ڪيئن ڪجي؟ مثال طور، هن طرح:
public void printStory(BufferedWriter writer) {
// ...
}
سرور ٿريڊ اڳ ۾ ئي اسٽريم ٺاهي چڪو آهي ۽ آئوٽ پٽ اسٽريم کي دليل طور پاس ڪري سگھي ٿو. اڳيون، توهان کي صرف هر شي کي منتقل ڪرڻ جي ضرورت آهي جيڪا نئين ڪلائنٽ ڏانهن منتقل ٿيڻ جي ضرورت آهي ڳولا جي چڪر ۾. نتيجو: هي صرف بنياديات آهي، ۽ گهڻو ڪري هي چيٽ آرڪيٽيڪچر ڪم نه ڪندو جڏهن حقيقي ايپليڪيشن ٺاهيندي. اهو پروگرام تعليمي مقصدن لاءِ ٺاهيو ويو هو ۽ ان جي بنياد تي مون ڏيکاريو ته توهان ڪيئن ڪري سگهو ٿا ڪلائنٽ سان رابطو سرور سان (۽ ان جي برعڪس)، ڪيترن ئي ڪنيڪشن لاءِ اهو ڪيئن ڪجي، ۽ يقيناً، ساکٽس تي اهو ڪيئن منظم ڪيو وڃي. ذريعا هيٺ ترتيب ڏنل آهن، ۽ پروگرام جو سورس ڪوڊ پڻ ڳنڍيو ويو آهي. هي منهنجو مضمون لکڻ جو پهريون تجربو آهي) توهان جي توجه لاء مهرباني :)
  1. جاوا انٽرپرائز ۾ سوچڻ، بروس ايڪيل ايٽ پاران. ال. 2003
  2. جاوا 8، مڪمل گائيڊ، هربرٽ شيلڊٽ، 9 ايڊيشن، 2017 (باب 22)
  3. ساکٽ پروگرامنگ جاوا مضمون ۾ ساکٽس بابت
  4. سرڪاري دستاويز ۾ ساکٽ
  5. سرور ساکٽ سرڪاري دستاويزن ۾
  6. GitHub تي ذريعن
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION