ภาษาจาวามี Java API ที่ช่วยให้เราสามารถเชื่อมต่อกับเครือข่าย (network) เพื่อสื่อสารกับคอมพิวเตอร์เครื่องอื่นหรือบางครั้งก็ใช้ในการสื่อสารกับแอพพลิเคชั่นในเครื่องตนเอง โดยเครือข่ายแบ่งออกเป็นเครือข่ายภายนอกองค์กรเรียกว่าอินเตอร์เนต (Internet) ส่วนเครือข่ายในองค์กรเรียกว่าอินตราเนต (Intranet) และเราจะเรียกเครื่องคอมพิวเตอร์แต่ละเครื่องว่าโฮสต์ (host) 

     การสื่อสารกันระหว่างโฮสต์แต่ละเครื่องผ่านเครือข่ายจะต้องเป็นไปตามข้อตกลงในการสื่อสารที่กำหนดไว้เรียกว่าโปรโตคอล (protocal) โดยโปรโตคอลที่ใช้ประกอบด้วย internet protocal (IP) ซึ่งทำหน้าที่ในการกำหนดเส้นทางและจุดหมาย และ transport protocal (TP) ซึ่งทำหน้าที่ควบคุมการรับ/ส่งข้อมูลซึ่งแบ่งออกเป็น transmission control protocal (TCP) และ user datagram protocal  (UDP) การใช้ TCP จะรับประกันว่าข้อมูลจะถูกรับ/ส่งครบถ้วนและถูกต้องตามลำดับแต่ความเร็วในการส่งข้อมูลจะช้ากว่า UDP เพราะจะมีส่วนของข้อมูลที่ใช้ในการการจัดการเพิ่มเข้ามา ส่วนการใช้ UDP จะส่งข้อมูลได้เร็วกว่าเพราะไม่มีส่วนของข้อมูลที่ใช้ในการการจัดการ แต่ไม่รับประกันว่าข้อมูลจะถึงปลายทางหรือลำดับการรับ/ส่งจะถูกต้อง เมื่อกล่าวถึงโปรโตคอลในการสื่อสารผ่านเครือข่ายเรามักจะเรียกว่า TCP/IP หรือ UDP/IP 

     ในการเชื่อมต่อโฮสต์กับเครือข่าย โฮสต์แต่ละเครื่องจะต้องมีหมายเลขประจำตัวเรียกว่า ip address ในปัจจุบัน ip address จะมี 2 เวอร์ชั่นคือ เวอร์ชั่น4 (IPV4) ซึ่งมีรูปแบบเป็น ตัวเลข.ตัวเลข.ตัวเลข.ตัวเลข โดยตัวเลขจะเป็นเลขฐาน 10 และแต่ละตำแหน่งสูงสุดไม่เกิน 255 เช่น 129.45.66.123 และเวอร์ชั่น 6 (IPV6) ซึ่งมีรูปแบบเป็น ตัวเลข:ตัวเลข:ตัวเลข:ตัวเลข:ตัวเลข:

ตัวเลข:ตัวเลข:ตัวเลข โดยตัวเลขจะเป็นเลขฐาน 16 เช่น 2001:db8:3333:4444:5555:6666:7777:8888 IPV6 ถูกพัฒนาขึ้นมาเนื่องจากการมีอุปกรณ์ใหม่ๆรวมถึงอุปกรณ์ IoT ถูกพัฒนาขึ้นมามากมาย ทำให้จำนวนของ IPV4 ไม่เพียงพอต่อการใช้งาน 

     ในการเชื่อมต่อกับโฮสต์ เราต้องระบุ ip address ของโฮสต์ หรืออาจจะเป็นรูปแบบชื่อที่เราอ่านรู้เรื่อง เช่น www.google.com ซึ่งจะมีโฮสต์ที่มีโปรแกรมแปลงจากชื่อไปเป็น ip address ให้เราอีกทีหนึ่ง (ส่วนนี้เป็นหน้าที่ของโปรแกรมเครือข่ายในส่วนของระบบปฏิบัติการในการจัดการให้กับเราอีกทีหนึ่งจึงจะไม่กล่าวถึงในที่นี้) เนื่องจากโฮสต์สามารถมีได้หลายแอพพลิชั่น ดังนั้นจึงมีการกำหนดพอร์ต (Port) เพื่อใช้เป็นตัวระบุว่าเราต้องการติดต่อกับแอพพลิชั่นใดในโฮสต์ มาตรฐานของพอร์ตที่กำหนดไว้มีทั้งหมด 65535 พอร์ตและมีการกำหนดเป็นมาตรฐานไว้ว่าหมายเลขพอร์ตใดสำหรับใช้งานอะไร เช่น หมายเลขพอร์ต 80 ใช้สำหรับการสื่อสารด้วยโปรโตคอล HTTP ดังนั้นการติดต่อกับโฮสต์ด้วยหมายเลขพอร์ต 80 ก็คือการเข้าใช้งานเว็บเพจนั่นเอง

     ในการเชื่อมต่อระหว่างโฮสต์โดยมากจะเป็นการขอใช้บริการและการให้บริการในรูปแบบไคลเอนท์/เซอร์ฟเวอร์ (Client/Server) โดยโฮสต์ที่ขอใช้บริการเรียกว่าไคลเอนท์ และโฮสต์ที่ให้บริการเรียกว่าเซอร์ฟเวอร์ แต่เนื่องจากเซอร์ฟเวอร์สามารถให้บริการได้หลายไคลเอนท์พร้อมๆกัน จึงมีการใช้ซอกเก็ต (Socket) เพื่อกำหนดจุดปลายทางของการสื่อสารทั้ง 2 ฝั่งระหว่างเซอร์ฟเวอร์และไคลเอนท์แต่ละตัว โดยซอกเก็ดจะเป็นตัวบอก ip address และพอร์ตที่ต้องการเชื่อมต่อ

    Java API ที่เราใช้ในการเชื่อมต่อกับเครือข่ายคือแพคเกจ java.net ซึ่งจะมี API อยู่ 2 แบบคือ low-level API ซึ่งจะเป็นการใช้งาน Addresses, Sockets, Interfaces โดยคลาสที่เกี่ยวข้องจะมีคลาส Socket คลาส ServerSocket และคลาส DatagramSocket  และ high-level API ซึ่งจะเป็นการใช้งาน Universal Resource Identifiers (URIs), Universal Resource Locators (URLs), Connections โดยคลาสที่เกี่ยวข้องจะมีคลาส URI คลาส URL คลาส URLConnection และคลาส HttpURLConnection

การเชื่อมต่อในแบบ Low-Level API ด้วย TCP/IP

     การเชื่อมต่อในแบบ low-level API ด้วย tcp/ip เป็นการใช้งานคลาส Socket และคลาส ServerSocket เราสามารถจำลองการสื่อสารกันระหว่างไคลเอนท์/เซอร์ฟเวอร์ด้วย tcp/ip แบบง่ายๆโดยสร้างโครงงานขึ้นมา 2 โครงงานเพื่อเป็นไคลเอนท์และเซอร์ฟเวอร์ เมื่อเริ่มการเชื่อมต่อทั้งไคลเอนท์และเซอร์ฟเวอร์จะกำหนดข้อตกลงในการเชื่อมต่อระหว่างกัน (handshake) และเปิดซอกเก็ตเพื่อติดต่อสื่อสารกันซึ่งซอกเก็ตจะมีข้อมูลเพื่อการเชื่อมต่อ เช่น internet address และ port เพื่อให้ไคลเอนท์และเซอร์ฟเวอร์สามารถสื่อสารโต้ตอบกันได้ จากนั้นจึงเริ่มการสื่อสารโดยไคลเอนท์จะเป็นผู้ส่งคำขอ (request) และเซอร์ฟเวอร์จะเป็นผู้ตอบสนอง (response) การมีข้อตกลงในการเชื่อมต่อจึงเป็นการรับประกันว่าข้อมูลจะถูกรับ/ส่งครบถ้วนและถูกต้องตามลำดับการรับ/ส่ง

     จากตัวอย่างด้านล่างเป็นโครงงานที่เป็นเซอร์ฟเวอร์ โดยบรรทัดที่ 12 เราสร้างออบเจกต์ ServerSocket ขึ้นมาโดยกำหนดให้เป็นพอร์ต 5000 ออบเจกต์ ServerSocket จะทำหน้าที่เป็นช่องทางในการรับการติดต่อจากไคลเอนท์  บรรทัดที่ 13 เราสร้างออบเจกต์ Socket ขึ้นมาโดยใช้เมธอด ServerSocket.accept() ซึ่งการทำงานจะถูกบล๊อกไว้เพื่อรอการติดต่อจนกว่าจะได้รับการติดต่อจากไคลเอนท์ซอกเก็ตจึงจะถูกสร้างขึ้นมาสังเกตุได้จากบรรทัดที่ 14 จะไม่ถูกพิมพ์จนกว่าจะมีการติดต่อเข้ามา บรรทัดที่ 15 เป็นการสร้างออบเจกต์ InputStreamReader ขึ้นมาเพื่อรับสตรีมของข้อมูลจากเมธอด Socket.getInputStream() และหุุ้มด้วยออบเจกต์  BufferReader เพื่อช่วยในการบัฟเฟอร์ข้อมูลและกำหนดให้กับตัวแปร input บรรทัดที่ 17 สร้างออบเจกต์ PrintWriter เพื่อส่งข้อมูลออกด้วยเมธอด Socket.getOutputStream() บรรทัดที่ 18 – 31 เราสร้างการวนรอบที่ไม่มีวันจบโดยกำหนดเงื่อนไขของ while เป็น true เพื่อรอรับการติดต่อจากไคลเอนท์ไปเรื่อยๆ ส่วนการออกจากการวนรอบ เราจะตรวจสอบว่าเมื่อไคลเอนท์ส่งข้อความ exit เข้ามา เราจะ break การวนรอบทันที แต่ถ้าเป็นข้อมูลอื่น เราจะส่งข้อความกลับไปดังบรรทัดที่ 26

     สำหรับโครงงานที่เป็นไคลเอนท์จะคล้ายๆกันต่างกันเพียงแค่ไม่มีการสร้าง ServerSocket ขึ้นมา จากตัวอย่างด้านล่าง บรรทัดที่ 11 เราสร้างออบเจกต์ Socket ของไคลเอนท์เพื่อใช้ในการติดต่อกับเซอร์ฟเวอร์ บรรทัดที่ 12 – 14 เป็นการรับ/ส่งข้อมูลซึ่งจะเหมือนกัน บรรทัดที่ 16 และ 18 เป็นการแสดงข้อมูลที่ได้รับจากเซอร์ฟเวอร์ บรรทัดที่ 15 และ 17 และ 19 เป็นการส่งข้อมูลให้เซอร์ฟเวอร์

     เมื่อลองใช้งานโดย run เซอร์ฟเวอร์ก่อน จะขึ้นเพียงข้อความ Host Server จนกระทั่งเรา run ไคลเอนท์จึงเกิดการส่ง/รับข้อมูลตามที่กำหนด ลำดับการส่ง/รับข้อมูลสังเกตุได้จากเวลาที่แสดงโดยดูในส่วนมิลลิวินาที

การสร้างซอกเก็ตเธรดเพื่อรองรับหลายไคลเอนท์พร้อมกัน

     จากตัวอย่างก่อนหน้า เซอร์ฟเวอร์ของเราสามารถรองรับได้เพียงไคลเอนท์เดียว หากเราต้องการให้เซอร์ฟเวอร์รองรับการเชื่อมต่อจากหลายไคลเอนท์ได้พร้อมกันและไม่รบกวนกัน เราจะต้องสร้างเธรดสำหรับแต่ละซอกเก็ตที่เป็นการเชื่อมต่อระหว่างแต่ละไคลเอนท์และเซอร์ฟเวอร์แยกกัน

    จากตัวอย่างด้านล่างที่โครงการของเซอร์ฟเวอร์ ในบรรทัดที่ 10 เราสร้างคลาสที่เป็นเธรด (thread) เพื่อจัดการกับซอกเก็ตขึ้นมา บรรทัดที่ 11 กำหนดตัวแปรชนิด Socket เพื่อเอาไว้รับออบเจกต์ Socket ที่ได้รับมาผ่านเมธอดคอนสตรัคเตอร์ในบรรทัดที่ 13 – 15 และย้ายการอ่านและเขียนข้อมูลมาไว้ที่เมธอด run() ซึ่งเกิดจากโอเวอร์ไรด์

     สำหรับคลาส  Main เรากำหนดการวนรอบแบบไม่รู้จบเพื่อรอรับการติดต่อจากไคลเอนท์ในบรรทัดที่ 10 – 12 ซึ่งเมื่อมีการติดต่อจากไคลเอนท์ คำสั่งในบรรทัดที่ 11 จะทำงานโดยสร้างออบเจกต์ SocketThread ซึ่งจะรับซอกเก็ตจากเมธอด ServerSocket.accept() และเริ่มทำงานด้วยเมธอด start() เกิดเป็นเธรดเฉพาะสำหรับแต่ละซอกเก็ตที่เป็นการเชื่อมต่อระหว่างแต่ละไคลเอนท์และเซอร์ฟเวอร์ 

     เราสามารถทำการทดสอบได้โดยแก้ไขเพิ่มการหน่วงเวลาในโครงงานไคลเอนท์ด้านบน และสร้างโครงงานไคลเอนท์เพิ่มอีกหนึ่งโครงงาน 

     เมื่อเรา run โครงงานไคลเอนท์อันแรกโดยในช่วงหน่วงเวลาเรา run โครงงานไคลเอนท์อันที่สอง จะเห็นว่าแต่ละโครงงานไคลเอนท์ทำงานได้โดยไม่รบกวนกัน และเมื่อหมดเวลาที่หน่วงไว้ต่างก็ทำงานต่อจนจบ ซึ่งถ้ามาดูที่ผลลัพธ์ที่โครงงานเซอร์ฟเวอร์จะเห็นว่ามีการติดต่อเข้ามาจากทั้ง 2 ไคลเอนท์

การเชื่อมต่อในแบบ Low-Level API ด้วย UDP/IP

     การเชื่อมต่อแบบ low-level API ด้วย udp/ip เป็นการใช้คลาส Socket และคลาส DatagramSocket เราใช้การเชื่อมต่อด้วย udp/ip เมื่อเราต้องการความเร็วในการส่งข้อมูล ไม่ต้องการการตอบสนอง (response) จากปลายทาง และการที่ปลายทางไม่ได้รับข้อมูลบางส่วนไม่ใช่เรื่องสำคัญนัก เช่น การส่งสตรีมมิ่งของภาพและเสียง เป็นต้น ข้อมูลที่ส่งผ่านเครือข่ายทั้งแบบ tcp/ip และ udp/ip จะถูกแบ่งออกเป็นส่วนย่อยมากๆแล้วส่งออกโดยมีข้อมูลเกี่ยวกับการสื่อสารปิดหัว/ท้ายของข้อมูลเรียกว่าแพกเก็ต – packet – ดังนั้นการไม่ได้รับบางแพกเก็ตในการสื่อสารด้วย udp/ip จึงไม่ส่งผลกระทบอย่างมีนัยสำคัญกับปลายทาง 

     การเชื่อมต่อแบบ udp/ip ไม่มีการทำ handshake ดังนั้นซอกเก็ตของ udp จะไม่มีข้อมูล เช่น internet address และ port สำหรับการสื่อสารโต้ตอบกัน  แพกเก็ตของ udp สามารถไปถึงปลายทางได้ด้วยข้อมูล เช่น internet address และ port ที่มีในแพกเก็ตเอง เราจึงเรียกว่าแพกเก็ตของ udp เป็นแพกเก็ตที่สมบูรณ์ในตัวมันเอง

     จากตัวอย่างโครงงานเซอร์ฟเวอร์ด้านล่าง บรรทัดที่ 9 เป็นการสร้างออบเจกต์ DatagramSocket ซึ่งเป็น udp ซอกเก็ตเพื่อรับการติดต่อจากไคลเอนท์โดยระบุพอร์ตที่รอรับการเชื่อมต่อเป็น 5000 บรรทัดที่ 11 สร้างอาเรย์ของไบต์เพื่อเอาไว้รับข้อมูลที่เข้ามา บรรทัดที่ 12 สร้างออบเจกต์  DatagramPacket หุ้มอาเรย์ของไบต์ไว้เพื่อสร้างแพคเก็ตเปล่าไว้รองรับข้อมูลที่เข้ามา บรรทัดที่ 13 รับข้อมูลจากแพตเก็ตขาเข้ามาเก็บไว้ด้วยเมธอด DatagramSocket.receive()  บรรทัดที่ 14 พิมพ์สิ่งที่ได้รับมาโดยแปลงอาเรย์เป็น String ก่อนพิมพ์

     สำหรับโครงงานไคลเอนท์ บรรทัดที่ 9 สร้างออบเจกต์ InetAddress เพื่อเก็บที่อยู่ที่ต้องการส่งข้อมูลไปซึ่งในที่นี้เป็นเครื่องตนเองจึงใช้เมธอด getLocalHost() บรรทัดที่ 10 สร้างออบเจกต์  DatagramSocket ซึ่งเป็น udp ซอกเก็ตเพื่อใช้ในการติดต่อกับเซอร์ฟเวอร์ บรรทัดที่ 11 แปลงข้อมูลที่ต้องการส่งไปเป็นอาเรย์ไบต์ บรรทัดที่ 12 สร้างออบเจกต์ DatagramPacket หุ้มอาเรย์เพื่อสร้างเป็นแพกเก็ตที่จะส่งออกไปโดยระบุ InetAddress และพอร์ตด้วยทำให้ udp แพกเก็ตสมบูรณ์ในตัวเองสำหรับส่งไปในเครือข่าย

          สังเกตว่าการสร้างออบเจกต์ DatagramPacket ของเซอร์ฟเวอร์ไม่มีการกำหนด ip address และพอร์ตเพราะแพกเก็ตถูกสร้างขึ้นมาเพื่อรับข้อมูล ในขณะที่การสร้างออบเจกต์ DatagramPacket ของไคลเอนท์จะมีการกำหนดip address และพอร์ตเพราะแพกเก็ตถูกสร้างขึ้นมาเพื่อส่องออก

     หากเราต้องการให้เซอร์ฟเวอร์ส่งข้อมูลกลับ เราจะต้องอ่านข้อมูลของ address และ port ของไคลเอนท์จากแพกเก็ตที่ไคลเอนท์ส่งมา ดังตัวอย่างด้านล่างในโครงงานเซอร์ฟเวอร์ เราเพิ่มส่วนของโปรแกรมเพื่อส่งข้อความกลับไปยังไคลเอนท์ โดยบรรทัดที่ 16 เราสร้างอาเรย์ไบต์ขึ้นมาใหม่เพื่อเก็บข้อความที่จะส่งไปยังไคลเอนท์ บรรทัดที่ 17 อ่าน ip address ของไคลเอนท์จากแพกเก็ตที่รับเข้ามา บรรทัดที่ 18 อ่านพอร์ตของไคลเอนท์จากแพกเก็ตที่รับเข้ามา บรรทัดที่ 19 สร้างแพกเก็ตขึ้นมาใหม่เพื่อส่งกลับไปยังไคลเอนท์ และบรรทัดที่ 20 เป็นการส่งออกไป

     สำหรับโครงงานไคลเอนท์ เราเพิ่มส่วนที่รับข้อมูลเข้ามาและแสดงผลดังตัวอย่างด้านล่าง โดยในบรรทัดที่ 14 – 15  สร้างแพกเก็ตอาเรย์ไบต์ขึ้นมาเพื่อรอรับข้อมูล บรรทัดที่ 16 รับแพกเก็ตเข้ามา บรรทัดที่ 17 พิมพ์สิ่งที่ได้รับมา

การเชื่อมต่อด้วย high-level API

     แอพพลิเคชั่นรุ่นใหม่มักจะใช้ high-level API ในการเชื่อมต่อกับเครือข่าย การใช้ high-level API ทำให้ เราไม่ต้องสนใจซอกเก็ตหรือพอร์ตแต่จะใช้ Universal Resource Identifiers (URIs) และ Universal Resource Locators (URLs) แทน 

     URI ประกอบด้วย URN (Uniform Resource Name) ซึ่งจะแสดงชื่อของทรัพยากร และ URL ซึ่งจะแสดงที่อยู่ของทรัพยากร ดังนั้นเราบอกได้ว่า URL และ URN เป็น URI แต่ URI ไม่ใช่ URL และ URN

     URI เป็นรูปแบบในการอธิบายถึงทรัพยากรที่เชื่อมต่อกับเครือข่าย ข้อมูลของ URI ประกอบด้วย scheme, scheme specific-path, authority, user-info, host, port, path, query และ fragment โดยมีรูปแบบดังนี้

     URI สามารถระบุได้ทั้งแบบ absolute path คือมีการระบุ scheme และแบบ relative path คือไม่มีการระบุ scheme ตัวอย่างของการใช้ URI เช่น

     URL เป็นรูปแบบในการอธิบายที่อยู่ของทรัพยากร โดยจะมีข้อมูลและรูปแบบเหมือนกับ URI แต่ต้องระบุแบบ absolute path เท่านั้น

     คลาสที่เกี่ยวข้องในการใช้ high-level API จะมีคลาส URI คลาส URL และ  คลาส URLConnection 

     ในการดำเนินการกับข้อมูลของทรัพยากรเรามักจะใช้ URI ซึ่งจะช่วยให้เราดำเนินการกับข้อมูลของทรัพยากรได้ง่ายกว่า จนกระทั่งเมื่อเราต้องการระบุที่อยู่ของทรัพยากรเราจึงแปลงจาก URI ไปเป็น URL แต่ถ้าเราแค่ต้องการเชื่อมต่อกับโฮสต์เราอาจจะใช้ URL ตรงๆเลยก็ได้ จากตัวอย่างด้านล่างเป็นการดึงเอาข้อมูลส่วนต่างๆของ URI ออกมาและแปลงจาก URI เป็น URL โดยในบรรทัดที่ 8 เราสร้างออบเจกต์ URI เพื่อเก็บข้อมูล URI ตามที่กำหนด บรรทัดที่ 9 – 17 พิมพ์ข้อมูลแต่ส่วนออกมา บรรทัดที่ 18 แปลงจาก URI ไปเป็น URL จะเห็นว่าเราสามารถเข้าถึงและระบุข้อมูลในแต่ละส่วนของ URI ได้ และแปลงจาก URI ไปเป็น URL ได้

     การใช้ URI ช่วยให้เราจัดการข้อมูลของทรัพยากรได้ง่ายกว่า เช่น เราต้องเขียนโปรแกรมเพื่อจัดการเรื่องการเก็บข้อมูลจากแต่ละแผนกในองค์กรไปยัง FTP Server ในพาธที่แตกต่างกันไป แทนที่เราจะต้องระบุ absolute path ในทุกๆที่ในโปรแกรม เราสามารถใช้ relative path แทนได้ และหากมีการเปลี่ยนที่อยู่ของ FTP Server เราสามารถแก้ไขเพียงที่เดียวได้ จากตัวอย่างด้านล่าง  บรรทัดที่ 8 เราสร้างออบเจกต์ URI ที่เก็บเฉพาะข้อมูลส่วนที่เป็นโฮสต์ บรรทัดที่ 10 และ 12 สร้างออบเจกต์ URI ที่เก็บเฉพาะข้อมูลส่วนที่เป็นพาธ บรรทัดที่ 13 – 14 ใช้เมธอด resolve() เพื่อสร้าง absolute path ของแต่ละแผนก  และเมธอด toURL() เพื่อแปลงจาก URI เป็น URL

     เราสามารถเชื่อมต่อกับโฮสต์ได้ด้วยออบเจกต์ URLจากตัวอย่างด้านล่างจะเป็นการเชื่อมต่อไปยัง http://www.example.org โดยบรรทัดที่ 10 เป็นการสร้างออบเจกต์ URL เพื่อเก็บที่อยู่ของเว็บที่ต้องการเชื่อมต่อ ในบรรทัดที่ 11 เป็นการเปิดการเชื่อมต่อพร้อมกับอ่านข้อมูลโดยใช้เมธอด URL.openStream โดยข้อมูลจะถูกเก็บในออบเจกต์ InputStreamReader ซึ่งหุ้มด้วยออบเจกต์ BufferedReader อีกทีหนึ่งเพื่อเป็นบัฟเฟอร์รองรับข้อมูลที่เข้ามา บรรทัดที่ 13 สร้างออบเจกต์ String ว่างๆขึ้นมาเพื่อรอรับข้อมูลที่จะอ่านจากออบเจกต์ InputStreamReader ด้วยเมธอด readLine() ในบรรทัดที่ 15 และแสดงข้อความด้วยบรรทัดที่ 16 โดยในบรรทัดที่ 14 เราวนรอบเพื่ออ่านข้อมูลจนกว่าจะได้ค่า null คือหมดข้อมูลแล้ว

     ผลลัพธ์ที่ได้คือข้อมูลในรูปแบบ html

     แต่การเชื่อมต่อโดยใช้เมธอด URL.openStream ทำได้แค่รับข้อมูล (http get) เท่านั้น หากเราต้องการส่งข้อมูล (http post) ด้วยเราจะใช้คลาส URLConnection 

     คลาส URLConnection มีคลาสลูกคือคลาส HttpUrlConnection ซึ่งรองรับข้อกำหนดของ http โดยเฉพาะสำหรับการเชื่อมต่อกับเซอร์ฟเวอร์ http ดังนั้นเราจะใช้คลาส HttpURLConnection เพื่ออ่านข้อมูลจากเว็บเซอร์เวอร์เช่นเดียวกับตัวอย่างด้านบน

     จากตัวอย่างด้านล่างในบรรทัดที่ 10 เราสร้างออบเจกต์ url ซึ่งจะถือ url ของเว็บเซอร์ฟเวอร์ไว้ บรรทัดที่ 11 เราสร้างออบเจกต์ HttpURLConnection ด้วยเมธอด URL.openConnection ซึ่งจะได้ผลลัพธ์เป็นออบเจกต์ URLConnection เราจึงต้อง cast ด้วย HttpURLConnection เพื่อให้ได้ออบเจกต์ HttpURLConnection บรรทัดที่ 12 ใช้เมธอด HttpURLConnection.connect() เพื่อเชื่อมต่อกับเซอร์ฟเวอร์ บรรทัดที่ 13 รับข้อมูลจากเว็บเซอร์ฟเวอร์มาเกห็บไว้ที่ออบเจกต์ InputStream บรรทัดที่ 14 แปลงข้อมูลใน InputStream มาใส่ในอาเรย์ของ byte และบรรทัดที่ 15 -16 พิมพ์ข้อมูลในอาเรย์ออกมา

     จะเห็นว่าได้ผลลัพธ์เช่นเดียวกับตัวอย่างก่อนหน้า

     ในการส่งข้อมูลไปยังเว็บเซอร์ฟเวอร์ เราต้องเรียกเมธอด URLConnection.setDoOutput() เพื่อกำหนดให้ออบเจกต์ URLConnection สามารถส่งข้อมูลได้ และเราต้องมีเซอร์ฟเวอร์เพื่อรองรับการทดสอบซึ่งในที่นี้จะใช้ https://httpbin.org/ ซึ่งเป็นเซอร์ฟเวอร์ที่มีไว้ให้ทดสอบโหมดต่างๆของ http เนื่องจากเว็บไซต์ดังกล่าวเป็น https ดังนั้นเราจะใช้คลาส HttpsURLConnection ซึ่งเป็นคลาสลูกของ HttpURLConmnection แต่อยู่ในแพคเกจ javax.net.ssl ในการเชื่อมต่อกับเซอร์ฟเวอร์

     จากตัวอย่างด้านล่างซึ่งเป็นการแก้ไขตัวอย่างที่ผ่านมาโดยเพิ่มการส่งข้อมูลและใช้ http get ของเดิมในการรับข้อมูลตอบกลับจากเซอร์ฟเวอร์ โดยบรรทัดที่ 11 เปลี่ยนเซอร์ฟเวอร์เป็น https://httpbin.org/post บรรทัดที่ 13 เรียกเมธอด setDoOutput() และกำหนดค่าเป็น true เพื่อกำหนดให้ออบเจกต์ HttpsURLConnection สามารถส่งข้อมูลได้ โดยต้องกำหนดก่อนการเรียกเมธอด connect() บรรทัดที่ 15 สร้างออบเจกต์ OutputStream ด้วยเมธอด getOutputStream() เพื่อเป็นตัวส่งออกข้อมูล บรรทัดที่ 16 สร้างอาเรย์ byte ของข้อความที่ต้องการส่งออก บรรทัดที่ 17 ใช้เมธอด OutputStream.write() อ่านข้อมูลจากอาเรย์แล้วส่งออก ส่วนที่เหลือของโปรแกรมเป็นการรับข้อความตอบกลับจากเซอร์ฟเวอร์เหมือนในตัวอย่างก่อนหน้า

     ตัวอย่างด้านล่างเป็นผลลัพธ์ที่ได้จากเซอร์ฟเวอร์ สังเกตุการข้อความที่ส่งไปถูกนำมาใช้ในการตอบกลับมาเพื่อยืนยันการทำงาน

      https://httpbin.org เป็นเว็บที่เราสามารถใช้ทดสอบได้หลายๆเรื่อง เช่น ทดสอบกิจกรรมต่างๆของ http ทดสอบการลงชื่อเข้าใช้งาน ทดสอบการรับไฟล์ขากลับในรูปแบบต่างๆ ทดสอบการรองรับการปลี่ยนเส้นทางของเว็บ (redirect) ทดสอบการอ่านข้อมูล cookie เป็นต้น

     เราเรียนรู้การเชื่อมต่อเครือข่ายด้วยแพคเกจ java.net เพื่อให้เห็นภาพการเชื่อมต่อว่าทำงานอย่างไร แต่แพคเกจ java.net มักจะไม่ถูกเลือกใช้จากนักพัฒนาเนื่องจากมันมีมาตั้งแต่ภาษาจาวาเวอร์ชั่น 1.0 และไม่มีการพัฒนาอะไรเพิ่มเติมมากนักทำให้ไม่รองรับเทคโนโลยีใหม่ๆ เช่น http/2 หรือ http/3 และบางครั้งก็ให้ผลลัพธ์ที่ไม่ถูกต้องนัก นักพัฒนาส่วนใหญ่จะเลือกใช้ไลบรารี่จากที่อื่น (3rd party library) ซึ่งไลบรารี่ยอดนิยมจะเป็น Jetty (https://www.eclipse.org/jetty/) และ Apache HTTP Client (https://hc.apache.org/httpcomponents-client-5.1.x/)