24 ม.ค. 2021 เวลา 07:31 • วิทยาศาสตร์ & เทคโนโลยี
การเขียนโปรแกรมเครือข่ายด้วยซ็อกเก็ต ตอนที่ 7: Java UDP
หมายเหตู: สามารถโหลดโค้ดของโปรแกรมได้ที่นี่ครับ https://github.com/ajsarun/basicUDPSocket
จากตอนที่ 6 ก็คงเข้าใจความแตกต่างระหว่างทีซีพี (TCP) กับยูดีพี (UDP) กันแล้วนะครับ คราวนี้เราจะมาเขียนโปรแกรมฝั่งเซิร์ฟเวอร์กัน โดยโปรแกรมเซิร์ฟเวอร์นี้จะทำงานเหมือน TCPServer คือรับข้อมูลสตริงจากไคลเอนต์ เอามาแปลงเป็นตัวอักษรตัวใหญ่ แล้วส่งกลับไปให้ไคลเอนต์ มาดูโค้ดกันเลยครับ
01: import java.io.*;
02: import java.net.*;
03:
04: class UDPServer {
05: public static void main(String args[]) throws Exception
06: {
07:
08: DatagramSocket serverSocket = new DatagramSocket(9876);
09: byte[] receiveData = new byte[1024];
10: byte[] sendData = new byte[1024];
11: while(true)
12: {
13: System.out.println("The server is waiting ");
14: DatagramPacket receivePacket =
15: new DatagramPacket(receiveData, receiveData.length);
16: serverSocket.receive(receivePacket);
17: String sentence = new String(receivePacket.getData());
18: InetAddress IPAddress = receivePacket.getAddress();
19: int port = receivePacket.getPort();
20: String capitalizedSentence = sentence.toUpperCase();
21: sendData = capitalizedSentence.getBytes();
22: DatagramPacket sendPacket =
23: new DatagramPacket(sendData, sendData.length, IPAddress, port);
24: serverSocket.send(sendPacket);
25: }
26: }
27: }
การสร้างซ็อกเก็ตจะใช้คลาส DatagramSocket ตามที่เขียนไว้ในบรรทัดที่ 8 ในที่นี้โปรแกรมเซิร์ฟเวอร์จะรอรับการติดต่ออยู่ที่พอร์ตหมายเลข 9876 บรรทัดที่ึ 9 และ 10 จะสร้างบัฟเฟอร์สำหรับรับและส่งข้อมูลตามลำดับ โดยในโปรแกรมนี้ระบุขนาดของการรับส่งข้อมูลไว้ที่ไม่เกิน 1024 ไบต์ บรรทัดที่ 14-15 สร้างแพ็กเก็ตรับข้อมูล โดยระบุว่าให้เอาข้อมูลมาเก็บไว้ในบัฟเฟอร์คือ receiveData ด้วยความยาวตามขนาดของบัฟเฟอร์ที่ประกาศไว้ ในตัวอย่างนี้คือ 1024 ไบต์ บรรทัดที่ 16 รออ่านข้อมูลที่ไคลเอนต์จะส่งมา โดยข้อมูลจะถูกเก็บลงแพ็กเก็ตที่ประกาศไว้ในบรรทัดที่ 9
บรรทัดที่ 17-19 ดึงข้อมูลออกมาจากแพ็กเก็ต โดยบรรทัดที่ 17 เป็นการดึงตัวข้อมูลคือ บรรทัดที่ 18 และ 19 ดึงไอพีแอสเดรสและหมายเลขพอร์ตของไคลเอนต์ที่ส่งข้อมูลมาตามลำดับ สองบรรทัดนี้มีความจำเป็นเพราะการใช้โปรโตคอลยูดีพีไม่มีการสร้างการติดต่อไว้ก่อน ข้อมูลของผู้ส่งอย่างไอพีแอสเดรสและหมายเลขพอร์ตจะถูกส่งมาเป็นส่วนหนึ่งของแพกเก็ตด้วย
บรรทัดที่ 21 สร้างแพ็กเก็ตสำหรับส่งข้อมูลกลับ โดยระบุว่าจะส่งกลับไปที่ไหนโดยใช้ค่าหมายเลขไอพี และหมายเลขพอร์ตที่ดึงมาจากบรรทัดที่ 18 และ 19 ข้อสังเกตก็คือถึงแม้เราจะไม่ได้ระบุหมายเลขไอพีและหมายเลขพอร์ตของเซิร์ฟเวอร์ ซึ่งในจุดนี้คือผู้ส่ง แต่ข้อมูลทั้งสองนี้จะถูกใส่เข้าไปในแพ็กเก็ตโดยอัตโนมัติ บรรทัดที่ 24 เป็นการส่งแพ็กเก็ตผ่านซ็อกเก็ตกลับไปให้ไคลเอนต์
ต่อไปมาดูโปรแกรมฝั่ง Client กันครับ
01: import java.io.*;
02: import java.net.*;
03: import java.util.*;
04: class UDPClient {
05: public static void main(String args[]) throws Exception {
06: Scanner inFromUser = new Scanner(System.in);
07: DatagramSocket clientSocket = new DatagramSocket();
08: InetAddress IPAddress = InetAddress.getByName("localhost");
09: byte[] sendData = new byte[1024];
10: byte[] receiveData = new byte[1024];
11: System.out.print("Please enter words: ");
12: String sentence = inFromUser.nextLine();
13: sendData = sentence.getBytes();
14: DatagramPacket sendPacket =
15: new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
16: clientSocket.send(sendPacket);
17: DatagramPacket receivePacket =
18: new DatagramPacket(receiveData, receiveData.length);
19: clientSocket.receive(receivePacket);
20: String modifiedSentence = new String(receivePacket.getData());
21: System.out.println("FROM SERVER:" + modifiedSentence.trim());
22: clientSocket.close();
23: }
24: }
บรรทัดที่ 7 สร้างซ็อกเก็ตเพื่อใช้ในการแลกเปลี่ยนข้อมูลกับเซิร์ฟเวอร์ บรรทัดที่ 8 แปลงชื่อโดเมนของเซิร์ฟเวอร์เป็นหมายเลขไอพี ในที่นี้เรารันโปรแกรมไคลเอนต์และเซิร์ฟเวอร์บนเครื่องเดียวกันชื่อโดเมนจึงเป็น localhost บรรทัดที่ 14-15 เตรียมแพ็กเก็ตที่ใช้ส่งข้อมูล โดยนอกจากข้อมูลที่จะส่งไปแล้ว ก็ต้องระบุหมายเลขไอพี และหมายเลขพอร์ตของโปรแกรมเซิร์ฟเวอร์
ถึงแม้เราจะไม่ได้ระบุหมายเลขไอพี และหมายเลขพอร์ตของไคลเอนต์ที่เป็นผู้ส่ง ข้อมูลนี้จะถูกใส่ลงไปในแพ็กเก็ตโดยอัตโนมัติ บรรทัดที่ 19 ส่งข้อมูลผ่านซ็อกเก็ตไปให้เซิร์ฟเวอร์ บรรทัดที่ 20 รอรับข้อมูลที่เซิร์ฟเวอร์จะตอบกลับมา บรรทัดที่ 21 พิมพ์ผลลัพธ์ที่เซิร์ฟเวอร์ส่งกลับมา บรรรทัดที่ 22 ปิดซ็อกเก็ต ก็คือจบการเชื่อมต่อกับเซิร์ฟเวอร์
คราวนี้มารันโปรแกรมกันดูครับ เราก็จะเริ่มจากคอมไพล์โปรแกรมกันก่อนนะครับ
คอมไพล์เซิร์ฟเวอร์และไคลเอนต์โปรแกรม
จากนัั้นก็รันโปรแกรมเซิร์ฟเวอร์ครับ
การรันโปรแกรม UDPServer
การใช้ start นำหน้าคำสั่งก็เพื่อให้มีการเปิดหน้าตางใหม่ขึ้นมาสำหรับเซิร์ฟเวอร์นะครับ เราจะได้ใช้หน้าต่างเดิมในการรันไคลเอนต์ จะเห็นว่าเซิร์ฟเวอร์รันอยู่อีกหน้าต่างหนึ่ง ที่มีคำว่า The server is waiting นะครับ
จากนั้นไปรันโปรแกรมไคลเอนต์กันครับ
การรันโปรแกรม UDPClient
จะเห็นว่าเมื่อรันโปรแกรมไคลเอนต์แล้ว เมื่อเราป้อนข้อความไป ฝั่งเซิร์ฟเวอร์ก็จะตอบกลับมา โดยแปลงข้อความที่เราป้อนเป็นตัวอักษรตัวใหญ่ทั้งหมด เหมือนกับในเวอร์ชันที่เป็น TCP และให้สังเกตว่าที่หน้าจอของเซิร์ฟเวอร์จะพิมพ์คำว่า The server is waiting ขึ้นมาอีกหนึ่งครั้ง นั่นก็แสดงว่าเทื่อเซิร์ฟเวอร์ให้บริการไคลเอนต์ตัวนี้เสร็จแล้ว มันก็พร้อมให้บริการไคลเอนต์ตัวถัดไป
มีอีกจุดหนึ่งที่อยากแสดงให้ดูก็คือ UDP เป็นโปรโตคอบแบบ connectionless ดังนั้นจะเกิดอะไรขึ้น ถ้าไคลเอนต์รันติดต่อเข้าไปโดยเซิร์ฟเวอร์ไม่ได้รันอยู่ ดังนั้นก่อนรันโปรแกรมต่อไปขอให้ไปปิดหน้าต่างของตัวเซิร์ฟเวอร์ก่อนนะครับ จากนั้นรันโปรแกรมไคลเอนต์
การรัน UDPClient โดยไม่ได้รัน UDPServer ไว้ก่อน
จะเห็นว่าโปรแกรมให้ผู้ใช้ป้อนข้อความไปตามปกติ และเมื่อผู้ใช้ป้อนข้อมูลไปและกดปุ่ม Enter โปรแกรมก็จะหยุดค้างรอการตอบรับอยู่ตรงนี้ ซึ่งเกิดจากการเรียกใช้คำสั่งในบรรทัดที่ 19 ของโปรแกรม UDPClient และจะรออยู่อย่างนี้ไปตลอด จนกว่าผู้ใช้จะปิดโปรแกรมเอง
หลายคนอาจถามว่าถ้ารันโปรแกรมเซิร์ฟเวอร์หลังจากนี้ก็จะไม่มีการเชื่อต่อหรือ คำตอบคือใช่ครับ ถ้ารันโปรแกรมเซิร์ฟเวอร์หลังจากนี้ โปรแกรมเซิร์ฟเวอร์ก็จะรอรับการติดต่อจากโปรแกรมไคลเอนต์ตัวใหม่ที่จะติดต่อเข้ามา เนื่องจากมันไม่มีข้อมูลของไคลเอนต์ตัวนี้
ถึงตรงนี้ก็หวังว่าจะทำให้เห็นภาพการทำงานแบบ connection-oriented กับ connectionless ได้ชัดเจนขึ้นนะครับ
หมายเหตุ:
1. ในกรณีที่รันโปรแกรมเซิร์ฟเวอร์ไม่ได้ส่วนใหญ่ปัญหาจะเกิดจากการที่ใช้หมายเลขพอร์ตซ้ำกับโปรแกรมอื่นที่รันอยู่ ให้แก้หมายเลขพอร์ตในโค้ดโปรแกรมของทั้งเซิร์ฟเวอร์และไคลเอนต์ จากนั้นคอมไพล์โปรแกรมและรันใหม่
ถ้าสนใจบทความอื่น ๆ ทางด้านวิทยาการคอมพิวเตอร์ และการพัฒนาโปรแกรมของผมสามารถอ่านเพิ่มเติมได้ที่ https://computingblog.intakosum.net/

ดูเพิ่มเติมในซีรีส์

โฆษณา