วันอังคารที่ 3 ธันวาคม พ.ศ. 2556

เขียนโปรแกรมเครือข่ายด้วย Socket ตอนที่ 3: TCP Server ด้วยภาษา Java

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

คลาสในภาษา Java ที่ใช้สร้าง Server Socket ก็ตรงตัวเลยครับคือ ServerSocket ส่วนคลาสที่ใช้ในการสร้าง Connection Socket ก็คือ ConnectionSocket นั่นเอง เอาล่ะครับเพื่อให้เข้าใจการทำงานมาดูตัวอย่างกันดีกว่า สำหรับโปรแกรมเซิร์ฟเวอร์ที่จะเขียนขึ้นมาก็คือเซิร์ฟเวอร์ที่ใช้ในการแปลงข้อความภาษาอังกฤษที่รับเข้ามาจากไคลเอนต์ ให้เป็นตัวอักษรตัวใหญ่ทั้งหมดแล้วส่งกลับไปให้ไคลเอนต์ สำหรับโค้คภาษา Java ของโปรแกรมแสดงได้ดังนี้ครับ

1. import java.io.*;
2. import java.net.*;
3. import java.util.*;
4. class TCPServer {

5. public static void main(String argv[]) throws Exception
6.    {
7.      String clientSentence;
8.     String capitalizedSentence;
9.      ServerSocket welcomeSocket = new ServerSocket(49152);
10.  while(true) {
11.              System.out.println("The server is waiting ");
12. Socket connectionSocket = welcomeSocket.accept();
13. Scanner inFromClient = new Scanner(connectionSocket.getInputStream());
14. DataOutputStream  outToClient =
15.              new DataOutputStream(connectionSocket.getOutputStream());
16.            clientSentence = inFromClient.nextLine();
17. capitalizedSentence = clientSentence.toUpperCase() + '\n';
18.             outToClient.writeBytes(capitalizedSentence);
19. }
 20.     }
21.  }

สำหรับโปรแกรมนี้ก็มีส่วนที่จะอธิบายดังนี้ครับ บรรทัดที่ 9 เป็นการสร้าง Server Socket โดยใช้หมายเลขพอร์ต 49152 ในการรอรับการติดต่อกับไคลเอนต์  บรรทัดที่ 12 จะเห็นว่ามีการเรียกใช้เมท็อด accept() เมท็อดนี้จะมีผลทำให้โปรแกรมเซิร์ฟเวอร์หยุดรอรับการติดต่อจากไคลเอนต์ เมื่อไคลเอนต์ติดต่อเข้ามาก็จะสร้าง Connection Socket เพื่อใช้ในการแลกเปลี่ยนข้อมูล บรรทัดที่ 13 สร้างสตรีมข้อมูลเข้า(input stream) เพื่ออ่านข้อมูลจากซ็อกเก็ต บรรทัดที่ 14, 15 สร้างสตรีมผลลัพธ์ (output stream) เพื่อเขียนข้อมูลลงซ็อกเก็ต บรรทัดที่ 16 หยุดเพื่อรออ่านข้อมูลที่ไคลเอนต์จะส่งผ่านซ็อกเก็ตมา บรรทัดที่ 17 แปลงสตริงที่รับมาให้เป็นตัวอักษรตัวใหญ่ และบรรทัดที่ 18 เขียนข้อมูลผ่านซ็อกเก็ตกลับไปให้ไคลเอนต์ ข้อสังเกตที่น่าสนใจก็คือจะเห็นว่าเราให้โปรแกรมนี้ทำงานอยู่ในลูปไม่รู้จบ ซึ่งเป็นธรรมชาติของโปรแกรมเซิร์ฟเวอร์ที่จะทำงานไปเรื่อย ๆ  เมื่อโปรแกรมเซิร์ฟเวอร์ตัวนี้ให้บริการไคลเอนต์ตัวหนึ่งเสร็จ จึงจะไปให้บริการไคลเอนต์ตัวอื่นที่ติดต่อเข้ามาได้ ลักษณะของโปรแกรมเซิร์ฟเวอร์แบบนี้เราจะเรียกว่า iterative server ซึ่งก็คือเซิร์ฟเวอร์ที่ให้บริการไคลเอนต์ได้ครั้งละหนึ่งตัว ถ้ามีไคลเอนต์ตัวอื่นติดต่อเข้ามาขณะที่เซิร์ฟเวอร์กำลังให้บริการไคลเอนต์ตัวอื่นอยู่ ไคลเอนต์ตัวดังกล่าวก็จะถูกเข้าคิวไว้ เมื่อเซิร์ฟเวอร์ให้บริการไคลเอนต์ตัวนี้เสร็จก็จะกลับไปให้บริการไคลเอนต์ในคิว สำหรับเซิร์เวอร์ที่ให้บริการไคลเอนต์ได้ทีละหลายตัวพร้อมกันที่เรียกว่า concurrent server นั้น ทำได้โดยใช้ Thread ซึ่งจะกล่าวถึงในตอนต่อ ๆ ไป

1 ความคิดเห็น: