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

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

จากโปรแกรมเซิร์ฟเวอร์ในตอนที่ 3 จัดเป็นเซิร์ฟเวอร์แบบ iterative นั่นคือให้บริการไคลเอนต์ได้ครั้งละหนึ่งตัว ถ้ามีมากกว่าหนึ่งตัวตัวที่เข้ามาทีหลังจะต้องเข้าคิวรอจนกว่าจะถึงคิวตัวเอง ซึ่งเซิร์ฟเวอร์แบบนี้ไม่เหมาะสมกับงานที่ไคลเอนต์และเซิร์ฟเวอร์ต้องติดต่อกันเป็นเวลานาน ลองนึกภาพว่าถ้า Gmail ให้บริการแบบนี้ดูนะครับว่ามันจะเป็นยังไง ดังนั้นงานแบบนี้จะต้องเขียนเซิร์ฟเวอร์ที่ทำงานแบบพร้อมกัน (Concurrent) ครับ

ซึ่งการเขียนก็ไม่ได้ยากอะไร แนวคิดที่ผ่านมาในตอนต่าง ๆ ยังใช้ได้หมด แต่สิ่งที่เราจะเพิ่มเข้ามาคือเราจะนำเธรด (Thread) มาใช้ครับ หลักการก็คือหลังจากที่เซิร์ฟเวอร์รับการติดต่อจากไคลเอนต์เข้ามาแล้วแทนที่จะไปให้บริการไคลเอนต์เองเหมือนที่ผ่านมา ก็จะสร้างเธรด ขึ้นมาให้บริการไคลเอนต์แต่ละตัว ไปลองดูโค้ดกันครับ
  1. //TCPConcurrentServer.java
  2. import java.io.*; 
  3. import java.net.*; 
  4. import java.util.*;
  5. public class TCPConcurrentServer { 
  6.    public static void main(String argv[])  { 
  7.       String clientSentence; 
  8.       String capitalizedSentence; 
  9.       ServerSocket welcomeSocket = null;
  10.       try {
  11.          welcomeSocket = new ServerSocket(6789);
  12.       }
  13.       catch (IOException e) {
  14.          System.out.println("Cannot create a welcome socket");
  15.          System.exit(1);
  16.       }
  17.       while(true) {
  18.          try {  
  19.             System.out.println("The server is waiting ");
  20.             Socket connectionSocket = welcomeSocket.accept(); 
  21.    EchoThread echoThread = new EchoThread(connectionSocket);
  22.             echoThread.start();
  23.          }
  24.          catch (IOException e) {
  25.             System.out.println("Cannot create this connection");
  26.          }
  27.       }
  28.    } 
  29. //EchoThread.java
  30. import java.io.*; 
  31. import java.net.*; 
  32. import java.util.*;
  33. public class EchoThread extends Thread {
  34.     private Socket connectionSocket;
  35.     public EchoThread(Socket connectionSocket) {
  36.         this.connectionSocket = connectionSocket;
  37.     }
  38.     public void run() {
  39.          Scanner inFromClient = null;
  40.          DataOutputStream outToClient = null;
  41.          try {
  42.             inFromClient = new Scanner(connectionSocket.getInputStream());
  43.    outToClient = 
  44.               new DataOutputStream(connectionSocket.getOutputStream()); 
  45.    String clientSentence = inFromClient.nextLine(); 
  46.          String capitalizedSentence = clientSentence.toUpperCase() + '\n'; 
  47.          outToClient.writeBytes(capitalizedSentence);         
  48.             
  49.    }
  50.         catch (IOException e) {
  51.             System.err.println("Closing Socket connection");
  52.         }
  53.         finally {
  54.             try {
  55.                if (inFromClient != null)
  56.                   inFromClient.close();
  57.                if (outToClient != null)
  58.                   outToClient.close();
  59.                if (connectionSocket != null)
  60.                   connectionSocket.close();
  61.                }
  62.             catch (IOException e) {
  63.                e.printStackTrace();
  64.             }
  65.         }
  66.     }
  67. }

สิ่งที่แตกต่างจากโปรแกรม iterative server ก็คือ คลาส EchoThread ในบรรทัดที่ 30-68 ซึ่งเป็นคลาสที่เขียนขึ้นเพื่อเป็นส่วนของการให้บริการไคลเอนต์ในการแปลงตัวอักษรตัวเล็กเป็นตัวใหญ่ จะเห็นว่างานบริการไคลเอนต์ที่เคยอยู่ในตัวโปรแกรม TCPServer จะถูกนำมาเขียนในคลาสนี้ บรรทัดที่ 21 และ 22 ในคลาส TCPConcurrent  จะสร้างออบเจกต์ของ EchoThread และสั่งให้เทรดเริ่มทำงาน ให้สังเกตว่ามีการส่งซ็อกเก็ตเชื่อมต่อที่สร้างขึ้นมาให้ออบเจกต์ของคลาส EchoThread ผ่านทางคอนสตรักเตอร์ หลังจากสร้างออบเจกต์ และสั่งให้เธรดเริ่มทำงานในการบริการไคลเอนต์แล้ว โปรแกรมเซิร์ฟเวอร์ก็สามารถกลับไปรับการติดต่อจากไคลเอนต์ตัวถัดไปได้ โดยตอนนี้การบริการไคลเอนต์จะเป็นหน้าที่ของเธรดที่ถูกสร้างขึ้น และถ้ามีการติดต่อเข้ามาก็ทำแบบเดียวกันคือสร้างเธรดอีกตัวหนึ่งไปให้บริการไคลเอนต์

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

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

สำหรับใครที่ยังไม่เข้าใจว่าจะรันโปรแกรมยังไงดูได้จากวีดีโอนี้ครับ



สุดท้ายสำหรับวันนี้ก็ขอสุขสันต์วันคริสต์มาสมายังทุกคนครับ...

วันเสาร์ที่ 7 ธันวาคม พ.ศ. 2556

เขียนโปรแกรมเครือข่ายด้วยซ็อกเก็ต (Socket) ตอนที่ 5: การรันโปรแกรมเพื่อทดสอบการทำงาน

หลังจากที่เราเขียนโปรแกรมเซิร์ฟเวอร์และไคลเอนต์เรียบร้อยแล้ว ในตอนนี้เราจะมาลองรันโปรแกรมเพื่อทดสอบการทำงานกันดู  โดยจะขอยกตัวอย่างการรันโปรแกรมบนระบบปฏิบัติการไมโครซอฟท์วินโดวส์ นะครับ โดยเราจะรันทั้งสองโปรแกรมบนเครื่องเดียวกัน หลังจากคอมไฟล์ทั้งโปรแกรมเซิร์ฟเวอร์และไคลเอนต์แล้ว เราจะเริ่มจากรันโปรแกรมเซิร์ฟเวอร์ดังนี้ start java TCPServer

เราใช้คำสั่ง start นำหน้าคำสั่งที่ใช้รันโปรแกรมเซิร์ฟเวอร์เพราะเราต้องการจะเปิดหน้าจอ command prompt ชึ้นมาใหม่เพื่อใช้รันโปรแกรมเซิร์ฟเวอร์ โดนหน้าจอ command prompt เดิมจะได้ใช้สำหรับรันโปรแกรมไคลเอนต์ต่อไป

การรันไคลเอนต์ใช้คำสั่งดังนี้ java TCPClient

หลังจากนั้นเราสามารถป้อนข้อความอะไรก็ได้ จากนั้นโปรแกรมฝั่งเซิร์ฟเวอร์จะส่งข้อความที่เราป้อนเข้าไปกลับมาเป็นตัวอักษรภาษาอังกฤษตัวใหญ่ หลังจากรันโปรแกรมแล้วโปรแกรมฝั่งไคลเอนต์จะจบการทำงาน ส่วนโปรแกรมฝั่งเซิร์ฟเวอร์จะรอรับการติดต่อจากไคลเอนต์ต่อไป นั่นคือเราสามารถรันโปรแกรมฝั่งไคลเอนต์เพื่อติดต่อเข้าไปอีกกี่รอบก็ได้ ถ้าต้องการจบการทำงานของโปรแกรมฝั่งเซิร์ฟเวอร์ให้ไปที่หน้าต่างของโปรแกรมเซิร์ฟเวอร์และกด Ctrl-C

อีกหนึ่งจุดที่อยากให้ทดลองคือ เซิร์ฟเวอร์ที่เราเขียนขึ้นจากตัวอย่างที่แล้วเป็น iterative server คือจะให้บริการไคลเอนต์ได้ทีละหนึ่งตัว ตัวที่ติดต่อเข้ามาภายหลังจะต้องเข้าคิวรอไว้ ดังนั้นเพื่อให้เห็นภาพให้ลองรันไคลเอนต์สักสองตัว โดยเปิดหน้าต่าง command prompt ขึ้นมาสองหน้าต่าง แต่ละหน้าต่างก็รันโปรแกรมไคลเอนต์  จากนั้นให้ลองดูว่าถ้าป้อนสตริงจากไคลเอนต์ที่รันเป็นตัวที่สองก่อนที่จะป้อนสตริงจากไคลเอนต์ตัวที่หนึ่งจะเกิดอะไรขึ้น

สำหรับใครที่อ่านบทความแล้วยังไม่เข้าใจว่าจะรันโปรแกรมยังไง สามารถดูได้จากวีดีโอต่อไปนี้ครับ



หมายเหตุ:
1. ในกรณีที่รันโปรแกรมเซิร์ฟเวอร์ไม่ได้ส่วนใหญ่ปัญหาจะเกิดจากการที่ใช้หมายเลขพอร์ตซ้ำกับโปรแกรมอื่นที่รันอยู่ ให้แก้หมายเลขพอร์ตในโค้ดโปรแกรมของทั้งเซิร์ฟเวอร์และไคลเอนต์ จากนั้นคอมไพล์โปรแกรมและรันใหม่


เขียนโปรแกรมเครือข่ายด้วยซ็อกเก็ต (Socket) ตอนที่ 4: TCP Client ด้วยภาษาจาวา (Java)

หลังจากเขียนโปรแกรมฝั่งเซิร์ฟเวอร์ไปเมื่อตอนที่แล้วคราวนี้มาดูโปรแกรมฝั่งไคลเอนต์บ้าง สำหรับโปรแกรมก็เป็นดังนี้ครับ


  1. import java.io.*; 
  2. import java.net.*;
  3. import java.util.*; 
  4. class TCPClient { 
  5.     public static void main(String argv[]) throws Exception 
  6.     { 
  7.          String sentence; 
  8.          String modifiedSentence;
  9.          Scanner inFromUser = null;
  10.          Socket clientSocket = null;
  11.          DataOutputStream outToServer = null;
  12.          Scanner inFromServer = null;
  13.          try { 
  14.             inFromUser = new Scanner(System.in);
  15.             clientSocket = new Socket("localhost", 6789); 
  16.             outToServer = 
  17.                new DataOutputStream(clientSocket.getOutputStream()); 
  18.            inFromServer = new Scanner(clientSocket.getInputStream());
  19.            System.out.print("Please enter words: ");
  20.            sentence = inFromUser.nextLine(); 
  21.            outToServer.writeBytes(sentence + '\n');
  22.            modifiedSentence = inFromServer.nextLine(); 
  23.            System.out.println("FROM SERVER: " + modifiedSentence);
  24.          }
  25.          catch (IOException e) {
  26.              System.out.println("Error occurred: Closing the connection");
  27.          }
  28.          finally {
  29.             try {
  30.                 if (inFromServer != null)
  31.                     inFromServer.close();
  32.                 if (outToServer != null)
  33.                     outToServer.close();
  34.                 if (clientSocket != null)
  35.                     clientSocket.close();
  36.             }
  37.             catch (IOException e) {
  38.                e.printStackTrace();
  39.             }
  40.          } 
  41.     } 


บรรทัดที่ 15 เป็นการสร้างซ็อกเก็ตเชื่อมต่อ (Connection Socket) ให้สังเกตว่าเราใช้ชื่อโฮสต์คือ localhost เพราะโปรแกรมตัวอย่างของเราเราจะรันโปรแกรมเซิร์ฟเวอร์และไคลเอนต์บนเครื่องเดียวกัน ในกรณีที่รันโปรแกรมเซิร์ฟเวอร์บนเครื่องอื่น ให้ระบุชื่อหรือหมายเลขไอพีของเครื่องดังกล่าว หมายเลขพอร์ตใช้หมายเลขที่โปรแกรมเซิร์ฟเวอร์รอรับการติดต่ออยู่ ในที่นี้ใช้ 6789 เพราะโปรแกรมเซิร์ฟเวอร์ที่เราเขียนขึ้นในบทความที่แล้วใช้หมายเลขพอร์ตนี้  บรรทัดที่ 16-17 สร้างสตรีมผลลัพธ์สำหรับเขียนข้อมูลลงซ็อกเก็ต บรรทัดที่ 18 สร้างสตรีมเพื่อรับข้อมูลจากซ็อกเก็ต บรรทัดที่ 21 เขียนข้อมูลลงซ็อกเก็ตเพื่อส่งให้เซิร์ฟเวอร์ บรรทัดที่ 22 รอรับข้อมูลที่เซิร์ฟเวอร์จะส่งกลับมา finally clause บรรทัดที่ 28-35 ปิดสตรีมทุกตัว และซ็อกเก็ตเชื่อมต่อ

สำหรับโปรแกรมต้นฉบับ (source code) สามารถโหลดได้จากลิงก์นี้ครับ ถ้าใครโหลดจาก gitlab ไปเมื่อบทความที่แล้ว ก็จะได้โค้ดโปรแกรมไปแล้วนะครับ ไม่ต้องโหลดใหม่ครับ

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

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

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

สำหรับแนวคิดของการอ่านและเขียนข้อมูลกับซ็อกเก็ตนั้นจะใช้แนวคิดของสตรีม (Stream) ซึ่งก็คือแนวคิดที่จาวา (Java) ใช้ในการรับส่งข้อมูลระหว่างโปรแกรมที่เขียนด้วยภาษาจาวา กับอุปกรณ์รอบข้าง หรือกับไฟล์ ตัวอย่างเช่น เวลาจะพิมพ์ข้อมูลออกมาทางจอภาพเราจะใช้คำสั่ง System.out.println("string"); ประโยคนี้ out คือสตรีมผลลัพธ์ (output stream) ซึ่งอ้างถึงตัวแสดงผลลัพธ์มาตรฐาน ซึ่งก็คือจอภาพนั่นเอง การเขียนโปรแกรมซ็อกเก็ตของภาษาจาวา (Java) ก็จะใช้แนวคิดนี้ เพียงแต่สตรีมที่เราสร้างขึ้น จะเชื่อมโยงกับซ็อกเก็ตแทนที่จะเป็นอุปกรณ์หรือไฟล์

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


  1. import java.io.*; 
  2. import java.net.*; 
  3. import java.util.*;
  4. class TCPServer { 
  5.    public static void main(String argv[])  { 
  6.       String clientSentence; 
  7.       String capitalizedSentence; 
  8.       ServerSocket welcomeSocket = null;
  9.       Socket connectionSocket = null;
  10.       Scanner inFromClient = null;
  11.    DataOutputStream outToClient = null;
  12.       try {
  13.          welcomeSocket = new ServerSocket(6789);
  14.       }
  15.       catch (IOException e) {
  16.          System.out.println("Cannot create a welcome socket");
  17.          System.exit(1);
  18.       }
  19.       while(true) {
  20.          try {
  21.             System.out.println("The server is waiting ");
  22.              connectionSocket = welcomeSocket.accept(); 
  23.              inFromClient = new Scanner(connectionSocket.getInputStream());
  24.              outToClient = 
  25.               new DataOutputStream(connectionSocket.getOutputStream()); 
  26.              clientSentence = inFromClient.nextLine(); 
  27.             capitalizedSentence = clientSentence.toUpperCase() + '\n'; 
  28.             outToClient.writeBytes(capitalizedSentence);
  29.          }
  30.          catch (IOException e) {
  31.             System.out.println("Error cannot create this connection");
  32.          }
  33.          finally {
  34.             try {
  35.                if (inFromClient != null)
  36.                   inFromClient.close();
  37.                if (outToClient != null)
  38.                   outToClient.close();
  39.                if (connectionSocket != null)
  40.                   connectionSocket.close();
  41.             }
  42.             catch (IOException e) {
  43.                e.printStackTrace();
  44.             }
  45.          }
  46.       }
  47.    } 

สำหรับโปรแกรมนี้ก็มีส่วนที่จะอธิบายดังนี้ครับ บรรทัดที่ 13 เป็นการสร้างเซิร์ฟเวอร์ซ็อกเก็ตโดยใช้หมายเลขพอร์ต 6789 ในการรอรับการติดต่อกับไคลเอนต์  บรรทัดที่ 22 จะเห็นว่ามีการเรียกใช้เมท็อด accept() เมท็อดนี้จะมีผลทำให้โปรแกรมเซิร์ฟเวอร์หยุดรอรับการติดต่อจากไคลเอนต์ เมื่อไคลเอนต์ติดต่อเข้ามาก็จะสร้างซ็อกเก็ตเชื่อมต่อเพื่อใช้ในการแลกเปลี่ยนข้อมูล บรรทัดที่ 23 สร้างสตรีมข้อมูลเข้า (input stream) เพื่ออ่านข้อมูลจากซ็อกเก็ต บรรทัดที่ 24-25 สร้างสตรีมผลลัพธ์ (output stream) เพื่อเขียนข้อมูลลงซ็อกเก็ต บรรทัดที่ 26 หยุดเพื่อรออ่านข้อมูลที่ไคลเอนต์จะส่งผ่านซ็อกเก็ตมา บรรทัดที่ 27 แปลงสตริงที่รับมาให้เป็นตัวอักษรตัวใหญ่ และบรรทัดที่ 28 เขียนข้อมูลผ่านซ็อกเก็ตกลับไปให้ไคลเอนต์ ใน finally clause จะปิด stream ที่สร้างขึ้นมาทั้งหมด และซ็อกเก็ตเชื่อมต่อตัวนี้ เนื่องจากในตัวอย่างนี้เซิฟร์เวอร์จะแปลงสตริงที่ไคลเอนต์ส่งเข้ามา ส่งสตริงที่แปลงกลับไป และตัดการเชื่อมต่อกับไคลเอนต์ทันที  และข้อสังเกตที่น่าสนใจก็คือจะเห็นว่าเราให้โปรแกรมนี้ทำงานอยู่ในลูปไม่รู้จบ ซึ่งเป็นธรรมชาติของโปรแกรมเซิร์ฟเวอร์ที่จะทำงานไปเรื่อย ๆ

โปรแกรมเซิร์ฟเวอร์ตัวนี้ให้บริการไคลเอนต์ครั้งละหนึ่งตัว เมื่อให้บริการไคลเอนต์ตัวหนึ่งเสร็จจึงจะไปให้บริการไคลเอนต์ตัวอื่นที่ติดต่อเข้ามาได้ ลักษณะของโปรแกรมเซิร์ฟเวอร์แบบนี้เราจะเรียกว่า iterative server ซึ่งก็คือเซิร์ฟเวอร์ที่ให้บริการไคลเอนต์ได้ครั้งละหนึ่งตัว ถ้ามีไคลเอนต์ตัวอื่นติดต่อเข้ามาขณะที่เซิร์ฟเวอร์กำลังให้บริการไคลเอนต์ตัวอื่นอยู่ ไคลเอนต์ที่ติดต่อเข้ามาก็จะถูกเข้าคิวไว้ เมื่อเซิร์ฟเวอร์ให้บริการไคลเอนต์ตัวนี้เสร็จก็จะกลับไปให้บริการไคลเอนต์ในคิว สำหรับเซิร์เวอร์ที่ให้บริการไคลเอนต์ได้ทีละหลายตัวพร้อมกันที่เรียกว่า concurrent server นั้น ทำได้โดยใช้เธรด (thread) ซึ่งจะกล่าวถึงในตอนต่อ ๆ ไป

สำหรับโปรแกรมต้นฉบับ (source code) สามารถโหลดได้จากลิงก์นี้ครับ  ซึ่งจะได้โปรแกรมทั้งฝั่งเซิร์ฟเวอร์และไคลเอนต์เลย แต่บล็อกเกี่ยวกับไคลเอนต์โปรแกรมจะอยู่ในตอนหน้านะครับ

เมื่อรันโปรแกรมนี้ โปรแกรมจะแสดงสถานะว่าโปรแกรมเซิร์ฟเวอร์กำลังทำงานอยู่ ซึ่งในโปรแกรมเซิร์ฟเวอร์จริง ๆ ไม่จำเป็นต้องมีการทำงานส่วนนี้นะครับ

วันพฤหัสบดีที่ 28 พฤศจิกายน พ.ศ. 2556

การเขียนเว็บแอพพลิเคชันด้วย Servlet และ JSP ด้วย NetBeans

วันนี้จะนำเสนอการสร้างเว็บแอพพลิเคชันง่าย ๆ โดยใช้ Servlet และ JSP โดยใช้ NetBeans เป็นตัวสร้างนะครับ สำหรับ NetBeans ที่จะใช้นี้ต้องเป็น NetBeans ที่รองรับ Java EE นะครับ ถ้าใครจะดาวน์โหลดก็ใช้อันนี้นะครับ

 

ส่วนเวอร์ชันที่ใช้ไม่ต้องเป็นเวิร์ชันล่าสุดก็ได้นะครับ เอาเป็นสัก 7 ขึ้นมาก็ได้ 6 ดูจะเก่าไป หลังจากดาวน์โหลดแล้วติดตั้งแล้วก็มาเริ่มกันเลยครับ วันนี้เราจะมาสร้างแอพลิเคชั้นง่าย ๆ ตามคอนเซ็ปของบล็อกกันครับ นั่นคือโปรแกรมแปลงอุณหภูมิจากฟาเรนต์ไฮต์เป็นเซลเซียส โปรแกรมของเราจะมีการทำงานดังนี้ครับเริ่มจากมีหน้าจอให้ผู้ใช้ป้อนอุณภูมิเป็นฟาเรนต์ไฮต์ ดังรูป



เมื่อผู้ใช้ป้อนอุณหภูมิและกดปุ่ม Submit จะแแสดงหน้าจอดังรูปถัดไป


มาเริ่มสร้างกันเลยครับ เริ่มจากสร้างโปรเจกต์กันก่อนดังรูป โดยให้เลือกเป็น Java Web -> Web Application ดังรูป





จากนั้นให้เลือก Server เป็น GlassFish หรือจะเลือกเป็น Tomcat ก็ได้

จะได้โปรเจกต์ ซึ่ง NetBeans จะมีไฟล์ HTML ชื่อ index.html ไว้ให้ ซึ่งให้เราเขียนโค้ดสำหรับฟอร์มรับค่าอุณหภูมิเป็นฟาเรนต์ไฮต์ดังรูป


   ถ้าดูโค้ดในรูปไม่ชัดก็ดูได้จากด้านล่างนี้


<html>
    <head>
        <title>Fahrenheit to Celcius </title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
    </head>
    <body>
        <form name="main" action="FahrenheitToCelcius">
            Fahrenheit: <input type="text" name="fahrenheit" value="" size="10" />
            <br/>
            <input type="submit" value="Submit" name="submit" />
        </form>
    </body>
</html>

ให้สังเกตุค่าที่กำหนดให้กับแอททริบิวต์ action ของแท็ก form ไว้ให้ดี เพราะนี่จะเป็นชื่อของ Servlet ที่เราจะสร้าง และขอให้สังเกตุที่กำหนดให้กับแอทริบิวต์ name ของแท็ก input ไว้ด้วยเพราะเราจะต้องใช้เพื่อนำค่าที่ผู้ใช้ป้อนไปประมวลผล

ขั้นต่อไปจะสร้าง Servlet โดยคลิกขวาที่ Source Package ในตัวโปรเจกต์เลือก New -> Servlet



ตั้งชื่อคลาสให้ตรงกับค่าที่อยู่ใน แอททริบิวต์ action ของแท็ก form แล้วคลิก Next ย้ำนะครับว่า Next อย่าเพิ่ง Finish เพราะเราควรจะกำหนดค่านี้ให้อยู่ใน deployment descriptor ด้วย

ให้เลือก Add Information to deployment descriptor (web.xml) ด้วยแล้วจึงคลิก Finish (ขอไม่อธิบายนะครับว่าคืออะไร เพราะมันจะยาวเกินขอบเขตของ Tutorial)

NetBeans จะสร้างคลาสให้ ซึ่งส่วนที่เราจะเขียนโค้ดให้ Servlet คือเมท็อด ProcessRequest() ดังรูป


ถ้าดูไม่ชัดสามารถดูได้จากโค้ดข้างล่างนี้ครับ

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
           response.setContentType("text/html;charset=UTF-8");
          String fahrenheitStr = request.getParameter("fahrenheit");
         double fahrenheit = Double.parseDouble(fahrenheitStr);
         DecimalFormat twoDigits = new DecimalFormat("0.00");
        double celcius = (5.0 / 9 ) * (fahrenheit - 32);
        String celciusStr = twoDigits.format(celcius);
        fahrenheitStr = twoDigits.format(fahrenheit);
        request.setAttribute("fahrenheit", fahrenheitStr);
        request.setAttribute("celcius", celciusStr);
        request.getRequestDispatcher("result.jsp").forward(request, response);
     
    }

ตรงนี้ขอขยายความเล็กน้อยครับ ว่าจริง ๆ แล้วตามหลักการจริง ๆ ในคลาส Servlet ที่สร้างขึ้นนี้เราจะต้อง Override เมท็อด doGet() หรือ doPost() ขึ้นอยู่กับว่าตอนที่ส่ง HTTP Request มาใช้เมท็อด Get หรือ Post แต่ NetBeans เลือก Override ทั้งสองเมท็อดนี้ให้มาเรียกเมท็อด processRequest() นั่นคือไม่ว่า HTTP Request ที่ส่งมาจะเป็นเมท็อด Get หรือ Post เราก็จะเขียนโปรแกรมที่เมท็อด ProcessRequest()

ในส่วนของโค้ดที่เราเขียนขออธิบายเป็นบรรทัดต่อบรรทัดดังนี้ครับ

String fahrenheitStr = request.getParameter("Fahrenheit"); รับค่าที่ผู้ใช้ป้อนเข้ามา ซึ่งในพารามิเตอร์ของเมท็อด getParamater() เราจะระบุชื่อให้ตรงกับที่เราตั้งไว้ใน Form และให้เข้าใจนะครับว่าสิ่งที่ผู้ใช้ป้อนเข้ามาจะอยู่ในรูปแบบสตริง

double fahrenheit = Double.parseDouble(fahrenheitStr);  แปลงสตริงให้เป็นตัวเลข
double celcius = (5.0 / 9) * (fahrenheit -32); แปลงฟาเรนต์ไฮต์เป็นเซลเซียส

DecimalFormat twoDigits = new DecimalFormat("0.00"); เป็นการสร้างออบเจ็กต์ที่จะใช้ในการจัดรูปแบบการแสดงผลตัวเลขให้เป็นทศนิยมสองตำแหน่ง

String celciusStr = twoDigits.format(celcius);
fahrenheitStr = twoDigits.format(fahrenheit);
สองบรรทัดข้างบนก็คือการจัดรูปแบบผลลัพธ์ครับทั้งฟาห์เรน"ฮต์และเซลเซียส

request.setAttribute("fahrenheit", fahrenheitStr);
request.setAttribute("celcius", celciusStr);  

สร้างแอททริบิวต์เพื่อส่งต่ออุณหภูมิไปแสดงผลในหน้า JSP ที่เราจะสร้างต่อไป

 request.getRequestDispatcher("/result.jsp").forward(request, response); ส่งต่อการทำงานไปยังหน้า JSP ชื่อ result.jsp

ขั้นสุดท้ายซะทีครับ สร้าง result.jsp เริ่มจากคลิกขวาที่ โฟลเดอร์ Web Pages เลือก New -> JSP  ดังรูป




ในช่อง File Name ให้ใส่ชื่อ result ไม่ต้องใส่ .jsp นะครับ แล้วกดปุ่ม Finish จากนั้น NetBeans จะสร้างไฟล์ชื่อ result.jsp ให้เราเขียนโค้ดดังนี้





<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <% out.print(request.getAttribute("fahrenheit") + " Fahrenheit is " + request.getAttribute("celcius") + " Celcius"); %>
    </body>
</html>


ให้สังเกตุวิธีการเรียกใช้ค่าพารามิเตอร์และแอทริบิวต์ที่ถูกส่งมาจาก Servlet ในขั้นตอนก่อนหน้า และจะเห็นว่าเราสามารถใช้ ตัวแปร request ได้เลย เพราะ request เป็นหนึ่งใน implicit object ของ JSP ครับ

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

วันศุกร์ที่ 22 พฤศจิกายน พ.ศ. 2556

การสร้างและใช้งาน Stateless Session Bean ด้วย NetBeans ตอนที่ 2

ในตอนที่ 1 เราได้สร้างส่วนของ Session Bean กันไปแล้ว ในตอนนี้มาดูส่วนของ Client บ้าง เริ่มเลยนะครับ

1. สร้างโปรเจกต์ใหม่ให้เลือกเป็น Enterprise Application Client ตามรูป





ในรูปสุดท้ายของขั้นตอนนี้ขอให้สังเกตุว่าเราเลือกใส่ Client ที่เรากำลังสร้างขึ้นลงไปใน Enterprise Application ที่เราสร้างจากตอนที่แล้ว (จริง ๆ จะไม่ใส่ลงไปก็ได้) จากนั้นกด Finish 

2. จากโครงของโค้ดในส่วนที่ NetBeans สร้างให้ ให้คลิกขวาในบริเวณของ Editor เลือก insert code แล้วตามด้วย Call Enterprise Bean



3. เลือก Enterprise Bean ที่ได้สร้างไว้แล้วในตอนที่ 1



4. NetBeans จะ inject ส่วนของ Object Reference ของ Session Bean เข้ามาให้เรา ซึ่งเราก็สามารถเขียนโปรแกรมเพื่อเรียกเมท็อดของ Session Bean ได้เลยดังรูป


5. ทดลองรันโปรแกรมโดยคลิกขวาที่โปรเจกต์ที่เป็น Enterprise Application ที่เราสร้างขึ้นแล้วเลือก run (ถ้าใครไม่แน่ใจว่าจะมีที่ผิดในโปรแกรมบ้างไหมอาจจลองเลือก build ดูก่อนก็ได้ ถ้าผ่านแล้วค่อยเลือก run)


6. ดูผลลัพธ์ที่ได้ในหน้าต่าง output ของ NetBeans ซึ่งก็จะเห็นคำว่า Hello World!




เรียบร้อยครับ เฮ้อกว่าจะเสร็จ แค่ Hello World! นี่ทำไมมันวุ่นวายจัง



การสร้างและใช้งาน Stateless Session Bean ด้วย NetBeans ตอนที่ 1

วันนี้เราจะมาสร้างเอนเทอร์ไพรส์แอพพลิเคชันอย่างง่าย ๆ โดยใช้ NetBeans กันครับ โดยวันนี้เราจะสร้าง Stateless Session Bean และเรียกใช้งานกัน และก็คงเดาได้นะครับว่าโปรแกรมที่เราจะสร้างก็คือ Hello World นั่นเอง :) ก่อนจะทำตามขั้นตอนใน Tutorial นี้ผมก็ให้ดาวน์โหลดและติดตั้ง NetBeans กันก่อนนะครับ โดยขอให้ดาวน์โหลด NetBeans ที่รองรับ Java EE สำหรับเวอร์ขันที่ผมใช้ตอนนี้คือล่าสุด 7.4 แต่จริง ๆ ตั้งแต่เวอร์ชัน 6 กว่า ๆ ก็ใช้ได้แล้วนะครับ เมื่อติดตั้งแล้วมาเริ่มกันเลยครับ

1. รัน NetBeans สร้างโปรเจกต์ใหม่โดยเลือกเป็น Enterprise Application ตามรูป 


2. .ใส่ชื่อโปรเจกต์ และคลิกที่ปุ่ม Next


3. เลือกออปชันตามรูปครับ 


สิ่งที่เรากำหนดในส่วนนี้คือ Application Server ท่ี่เราต้องการใช้ ในที่นี้คือ GlassFish และให้สร้าง EJB Module ให้เรา ซึ่งเราจะสร้าง Session Bean ใน EJB Module นี้ต่อไป และเราไม่ต้องการให้สร้าง Web Application Module ก็เพราะเราจะสร้าง Client ที่เป็น Application Client สำหรับตอนนี้ก็กดปุ่ม Finish ได้เลยครับ

4. เราจะได้รายการโปรเจกต์ดังรูป 


5. ในขั้นนี้เราจะสร้างโปรเจกต์เอาไว้เก็บ Remote Interface เรื่องจากในตัวอย่่างนี้เราจะสร้าง Remote Session Bean ซึ่งเราจะต้องสร้างโปรเจกต์ใหม่โดยเลือกเป็น Java Class Library ดังรูป 





หลังจากกดปุ่ม Finish เราจะได้รายการของโปรเจกต์เพิ่มขึ้นดังรูป 


6. เริ่มสร้าง Session Bean โดยเข้าไปที่โปรเจกต์ที่เป็น EJB Module แล้วคลิกขวาที่ Source Package เลือก New เลือก Session Bean ดังรูป


 7. เลือกประเภทของ Session Bean และทางเลือกต่าง ๆ ตามรูป


จะเห็นว่าเราเลือก Stateless และเลือก create interface เป็นแบบ remote ซึ่งเราจะต้องใส่ชื่อโปรเจกต์ที่เราเตรียมไว้ในขั้นตอนที่ 5 เพื่อใช้เก็บ remote interface ที่ NetBeans จะสร้างให้อัตโนมัติ จากนั้นคลิกปุ่ม Finish เราจะได้ รายการของโปรเจกต์ดังรูป



จากรูปจะเห็นว่า NetBeans จะสร้าง interface ให้เราโดยเติมคำว่า Remote ต่อท้ายชื่อของ Session Bean ที่เราระบุ และจะสร้างโครงของคลาสสำหรับ Session Bean เพื่อให้เราใส่เมท็อดเพิ่มเติมลงไป

8. ขั้นนี้เราจะเขียนเมท็อดให้ Session Bean โดยให้คลิกขวาในบริเวณ editor ของ NetBeans เลือก insert code และเลือก Add Business Method 





9. ใส่รายละเอียดของเมท็อดดังรูป


แล้วกดปุ่ม OK หลังจากนั้น NetBeans จะสร้างโครงของเมท็อดให้ 

10. จากโค้ดที่ NetBeans สร้างให้ ให้แก้ไขให้เป็นดังนี้ 


เรียบร้อยครับ ตอนนี้เราก็ได้ Session Bean พร้อมใช้งานแล้ว ในตอนหน้าเราจะมาเขียน Client กัน


วันพฤหัสบดีที่ 14 พฤศจิกายน พ.ศ. 2556

เขียนโปรแกรมเครือข่ายด้วยซ็อกเก็ต (Socket) ตอนที่ 2: รู้จักกับหมายเลขพอร์ต

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

ในส่วนของหมายเลขพอร์ตนั้นโปรแกรมเซิร์ฟเวอร์จะมีหมายเลขพอร์ตที่แน่นอนเพื่อที่ให้โปรแกรมไคลเอนต์ติดต่อเข้ามาได้ ส่วนโปรแกรมไคลเอนต์นั้นระบบปฏิบัติการจะเลือกหมายเลขพอร์ตที่ว่าง ณ ตอนนั้นมาให้ นั่นหมายความว่าโปรแกรมไคลเอนต์โปรแกรมเดียวกัน ในการทำงานแต่ละครั้งอาจมีหมายเลขพอร์ตไม่เหมือนกัน เช่นถ้าเราใช้เว็บเบราว์เซอร์เช่น Chrome ติดต่อเข้าไปยังเว็บเซิร์ฟเวอร์หมายเลขพอร์ตที่เว็บเซิร์ฟเวอร์จะมีค่าเดิมทุกครั้งเช่นหมายเลข 80 แต่โปรแกรม Chrome ในการทำงานครั้งแรกระบบปฏิบัติการอาจให้หมายเลข 1234 หลังจากนั้นถ้าปิดไปแล้วเปิดโปรแกรมขึ้นมาใหม่อาจจะได้หมายเลข 2000 ก็ได้

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

ดังนั้นในการเลือกหมายเลขพอร์ตให้กับโปรแกรมเซิร์ฟเวอร์ นักเขียนโปรแกรมควรจะมีความเข้าใจในเรื่องการจัดการหมายเลขพอร์ต โดยหน่วยงานที่มีหน้าที่ในการจัดการหมายเลขพอร์ตก็คือ Internet Assigned Numbers Authority (IANA)  ซึ่งเป็นแผนกหนึ่งของ Internet Corporation for Assigned Names and Numbers (ICANN)

การจัดการหมายเลขพอร์ตจะมีการแบ่งหมายเลขพอร์ตออกเป็นช่วง ช่วงแรกคืออ 0-1,023 จะไม่นำมานำมาใช้กับโปรแกรมเรา และระบบปฎิบัติการหลายตัวก็จะไม่ให้เราลงทะเบียนโปรแกรมเราโดยใช้พอร์ตในช่วงนี้นี้ เพราะหมายเลขพอร์ตในช่วงนี้จะเป็นส่วนที่โปรแกรมเซิร์ฟเวอร์ที่เป็นมาตรฐานใช้ เช่นเว็บเซิร์ฟเวอร์ใช้หมายเลข 80 อีเมลเซิร์ฟเวอร์ใช้พอร์ตหมายเลข 25 เป็นต้น 

หมายเลข 1,024-49,151 เป็นช่วงหมายเลขพอร์ตที่ IANA กำหนดให้เป็นพอร์ตจดทะเบียน (registered port)  คือถ้าหน่วยงานใดที่ต้องการจะจดทะเบียนหมายเลขพอร์ตให้กับโปรแกรมของตัวเอง IANA ก็สามารถนำหมายเลขพอร์ตในช่วงนี้มาจดทะเบียนให้ได้ โปรแกรมเซิร์เวอร์ที่เราเขียนอาจจะใช้หมายเลขพอร์ตในช่วงนี้ก็ได้ แต่ก็ไม่ได้มีการบังคับหรือควบคุมใด ๆ ถ้าเราอยากเขียนโปรแกรมโดยใช้พอร์ตในช่วงนี้  

ส่วนช่วงที่เหลือคือ 49,152 ถึง 65,535 เรียกว่าเป็นไดนามิกพอร์ต (dynamic port) เป็นหมายเลขพอร์ตที่ IANA ไม่รับจดทะเบียน และไม่ได้มีการควบคุมใด ๆ คือตั้งใจให้หมายเลขในช่วงนี้ใช้เป็นหมายเลขพอร์ตชั่วคราว หรือใช้สำหรับโปรแกรมหรือบริการที่ใช้ภายในเครื่อง หรือเป็นช่วงหมายเลขพอร์ตที่สุ่มให้โปรแกรมฝั่งไคลเอนต์ได้ใช้   

ข้อมูลเพิ่มเติมของพอร์ตต่าง ๆ ที่มีการใช้งานจริงสามารถดูเพิ่มเติมได้จากลิงก์นี้ http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers

ก็หวังว่าจะเข้าใจเรื่องหมายเลขพอร์ตมากขึ้นนะครับ แต่ไม่ต้องซีเรียสมาก เอาเป็นว่าโปรแกรมเซิร์ฟเวอร์ที่เราจะเขียนขึ้นต่อไปจะใช้พอร์ตตั้งแต่หมายเลข 1,024 ขึ้นไป ที่ว่างในเครื่องเราแล้วกันนะครับ โดยผมจะเลือกหมายเลขพอร์ตในช่วงของพอร์ตจดทะเบียน (1,024 - 49,151) เป็นหลักนะครับ พบกันต่อไปบทความหน้าครับ  

วันเสาร์ที่ 9 พฤศจิกายน พ.ศ. 2556

เขียนโปรแกรมเครือข่ายด้วยซ็อกเก็ต (Socket) ตอนที่ 1 รู้จักกับซ็อกเก็ต

แม้ว่าในปัจจุบันการพัฒนาโปรแกรมบนเครือข่ายเราจะพัฒนาในลักษณะที่เป็นเว็บแอพลิเคชัน หรือใช้มิดเดิลแวร์อย่างจาวาอีอี (Java EE) หรือ ไมโครซอฟท์ดอตเน็ต (Microsoft .Net) เป็นหลัก แต่พื้นฐานของโปรแกรมที่ทำงานบนเครือข่ายจะอยู่บนแนวคิดของซ็อกเก็ต (Socket) ยิ่งไปกว่านั้นแอพพลิเคชันหลัก ๆ บนอินเทอร์เน็ตที่เราใช้กันอยู่ในปัจจุบันนี้เช่นการติดต่อเพื่อขอหน้าเว็บระหว่างเว็บเบราว์เซอร์หรือเว็บเซิร์ฟเวอร์ หรือการรับส่งไฟล์โดยใช้โปรโตคอลเอฟทีพี (FTP)  ก็ใช้เพียงแค่แนวคิดของซ็อกเก็ต ในการทำงาน ดังนั้นการรู้จักและเข้าใจการเขียนโปรแกรมเครือข่ายโดยใช้ซ็อคเก็ต จึงยังจัดว่ามีประโยชน์อยู่ ในบทความตอนแรกนี้ผมจะกล่าวถึงว่า  ซ็อกเก็ตคืออะไร และในตอนต่อ ๆ ไป จะแสดงตัวอย่างของการเขียนโปรแกรมในภาษาต่าง ๆ อย่างเช่นภาษาจาวา (Java) ภาษาไพธอน (python) และอาจมีภาษาอื่น ๆ ด้วย ตามความขยันของผม แต่จริง ๆ แล้วถ้าเข้าใจแนวคิดในบทความนี้ผมคิดว่าก็สามารถที่จะนำไปประยุกต์กับภาษาอะไรก็ได้ครับ  

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

Photo by Greg Rosenke on Unsplash


ในปัจจุบันระบบปฏิบัติการแทบทุกตัวจะรองรับแนวคิดของการติดต่อสื่อสารผ่านเครือข่ายโดยใช้ซ็อกเก็ต  และภาษาเขียนโปรแกรมแทบทุกภาษาก็จะมี ซ็อกเก็ตเอพีไอ (Socket API) ให้นักเขียนโปรแกรมเรียกใช้ ข้อดีของการใช้ซ็อกเก็ตเอพีไอ ก็คือนักเขียนโปรแกรมไม่จำเป็นต้องลงไปรู้รายละเอียดของโปรโตคอลในระดับชั้นทรานส์ปอร์ตอย่างเช่น ทีซีพี (TCP) ) และระดับชั้นเน็ตเวิร์คอย่างเช่นไอพี ( IP)  

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

สำหรับบนอินเทอร์เน็ตเลขที่อยู่ของเครื่องคอมพิวเตอร์เราจะระบุโดยใช้หมายเลขไอพี (IP Address) ซึ่งพวกเราอาจเคยเห็นผ่านตามาบ้างในรูปแบบเช่น  192.168.1.2 อันนี้เป็นหมายเลขไอพีในเวอร์ชัน 4 นะครับ ปัจจุบันในเครือข่ายอินเทอร์เน็ตเราใช้ทั้งเวอร์ชัน 4 และเวอร์ชัน 6 ซึ่งจะเป็นเลขฐานสิบหก (อันนี้ขอละไว้ให้ค้นคว้าเพิ่มเติมเอานะครับว่าเวอร์ชัน 4 กับ 6 ต่างกันยังไง และทำไมเราใช้อยู่สองเวอร์ชัน) 

ส่วนหมายเลขที่อยู่ของโปรแกรมเราจะใช้หมายเลขพอร์ต (port number) ครับ ซึ่งหมายเลขพอร์ตนี้ก็คือเลขจำนวนเต็มธรรมดานี่เองครับ โดยจะเป็นเลขจำนวนเต็มที่เริ่มจาก 0 ถึง 65,535 ซึ่งก็เท่ากับจำนวน 65,536 หรือพูดง่าย ๆ ก็คือ ตามทฤษฎีแล้ว คอมพิวเตอร์หนึ่งเครื่องสามารถมีโปรแกรมเครือข่ายทำงานอยู่ได้พร้อมกัน 65,536 โปรแกรม ถ้าจะเทียบกับตัวอย่างคอนโด ก็คือคอนโดมีจำนวนห้อง 65,536 ห้อง 

ช่วงของตัวเลขที่ได้นี้ก็มาจากจำนวนบิตในฟิลด์ที่ใช้เก็บหมายเลขพอร์ตในโปรโตคอลระดับชั้นทรานส์ปอร์ตอย่าง ทีซีพี (TCP) หรือ ยูดีพี (UDP) ที่มีจำนวน 16 บิตนั่นเองครับ 2 ยกกำลัง 16 มีค่าเท่ากับ 65,536 นั่นเอง  (ไม่รู้เรื่องก็ข้ามไปก่อนครับ ไปทำความเข้าใจเพิ่มเอาทีหลัง) รายละเอียดมากกว่านี้ของหมายเลขพอร์ตจะพูดถึงในตอนต่อไปครับ เอาเป็นว่าจะขอยกตัวอย่างหมายเลขพอร์ตตัวหนึ่งที่เป็นมาตรฐานสำหรับโปรแกรมเว็บเซิร์ฟเวอร์ก็แล้วกันนะครับนั่นก็คือพอร์ตหมายเลข 80  ดังนั้นสมมติว่าถ้าเว็บเบราว์เซอร์ต้องการติดต่อกับโปรแกรมเว็บเซิร์ฟเวอร์ที่ทำงานอยู่บนเครื่องที่มีหมายเลข IP 161.246.123.123 ก็ต้องระบุทั้งหมายเลขไอพีดังกล่าว และหมายเลขพอร์ตซึ่งคือ 80

Photo by Kevin Horvat on Unsplash
 

ถึงตอนนี้หลายคนอาจบอกว่าไม่เคยเห็นต้องใส่เลขไอพีและเลขพอร์ตเลยเวลาเข้าถึงเว็บไซต์ เหตุผลก็คือในอินเทอร์เน็ตจะใช้ DNS (Doamin Name Server) เป็นกลไกในการแปลง URL ของเว็บไซต์ที่เราป้อนเป็นหมายเลขไอพีของเครื่องเซิร์ฟเวอร์ให้เราครับ ส่วนพอร์ต 80 เป็นพอร์ตมาตรฐาน ซึ่งถ้าเว็บเซิร์ฟเวอร์ใช้พอร์ตนี้อยู่แล้วก็ไม่จำเป็นต้องระบุ 

สำหรับการใช้งานซ็อกเก็ตเอพีไอนั้นแต่ละโปรแกรมก็ต้องระบุที่อยู่ทั้งสองตัวเพื่อสร้างเต้ารับของตัวเอง ซึ่งในการใช้งานซ็อกเก็ตเอพีไอจะเรียกเลขที่อยู่ทั้งสองว่าที่อยู่ซ็อกเก็ต (Socket Address) หรือจะแปลว่าที่อยู่เต้ารับดี :)  พูดง่าย ๆ ก็คือ 

Socket Address = IP Address + Port Number นั่นเองครับ 

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

วันเสาร์ที่ 9 กุมภาพันธ์ พ.ศ. 2556

การลิงก์เว็บแอพของเราให้เป็นเฟซบุ๊คแอพ

เริ่มบทความแรกของบล็อกนี้ ด้วยเรื่องที่หลายคนอาจจะอยากทำแต่ยังหาทางเริ่มต้นไม่ถูกนะครับ ก็คือการเชื่อมต่อเว็บแอพของเราให้เป็นเฟซบุ๊คแอพ สำหรับสิ่งที่จะต้องเตรียมตัวก่อนที่จะทำตามขั้นตอนในบทเรียนนี้ก็คือ 1. คุณต้องมีเฟซบุ๊คครับ ใครไม่มี (ล้อเล่นหรือเปล่า) ก็ไปสมัครซะนะครับ 2อันที่สองคุณต้องมี Web Hosting ครับ และถ้าคุณไม่มี Domain Name ของตัวเอง ก็ควรหา Web Hosting ที่ให้คุณสร้าง Sub domain ได้นะครับ ซึ่งผมขอแนะนำตัวฟรีตัวหนึ่งคือ http://www.awardspace.com/ ไปสมัครให้เรียบร้อยนะครับ อย่างไรก็ตามเนื่องจากตอนนี้เฟซบุ๊ค ระบุให้เว็บแอพที่จะลิงก์เข้ามาเป็นเฟซบุ๊คแอพต้องมีการเชื่อมต่อแบบปลอดภัยโดยใช้ SSL พูดง่าย ๆ ต้องใช้ https แทน http ธรรมดา และฟรีเว็บโฮสติงส่วนใหญ่มักไม่มีคุณสมบัตินี้ หรือถ้ามีก็ต้องจ่ายเงิน ดังนั้นเฟซบุ๊คแอพที่พัฒนาขึ้นตามบทความนี้ ก็จะใช้งานได้เฉพาะเราที่เป็นคนพัฒนามันขึ้นมาเท่านั้น ซึ่งถ้าใครอยากให้คนอื่นใช้ด้วยอาจต้องเสียเงินหาเว็บโฮสติงที่รองรับ SSL นะครับ ซึ่งผมจะอธิบายเรื่องนี้ต่อไปนะครับ

เรียบร้อยแล้วใช่ไหมครับ เอาล่ะมาเริ่มต้นกัน เราจะเริ่มจากการพัฒนาเว็บแอพง่าย ๆ ครับ   หลายคนอาจคิดว่า Hello World ละซิ มันง่ายไปใช่ไหมครับ ถ้างั้นเอาโปรแกรมยากขึ้นมาหน่อย Hello Facebook แล้วกัน :) จริง ๆ ความยากง่ายของเว็บแอพของเราไม่เกี่ยวกับบทความนี้นะครับ ดังนั้นเพื่อให้สอดคล้องกับจุดมุ่งหมายของบล็อกนี้คือให้ทำตามได้ง่าย ๆ อย่างเข้าใจ ก็เอา Hello นี่ละนะครับ จะ Hello อะไรก็ตามสะดวก ผมเอา Hello Facebook แล้วกัน ดังนั้นเว็บแอพเราจะมีโค้ดตามนี้ครับ

<HTML>
<BODY>
<H1> Hello Facebook </H1>
</BODY>
</HTML>

เพื่อความง่ายให้จัดเก็บไฟล์นี้ในชื่อ index.html นะครับ โหลดขึ้น Web Hosting ของคุณครับ จากนั้นทดลองดูครับว่าเว็บแอพของเราทำงานได้โดยพิมพ์ชื่อ Sub domain ที่เราสร้างไว้ครับ อย่างของผมใช้ Award Space และผมสร้าง Sub Domain ชื่อ hellofb.atwebpages.com เมื่อป้อน URL แล้วเราควรได้ผลลัพธ์ตามรูปดังนี้ครับ


ถ้าทุกอย่างเรียบร้อยเรามาเริ่มลิงก์เว็บแอพของเรากันเลยครับ โดยทำตามขั้นตอนดังนี้ครับ
  1. ให้ล็อกอินเข้าเฟซบุ๊คแล้วไปที่หน้านี้ครับ  https://developers.facebook.com/apps ซึ่งถ้าใครยังไม่เคยลงทะเบียนเป็นนักพัฒนา (Developer) ก็ลงทะเบียนนะครับ จากนั้นควรจะได้จอภาพแบบนี้ครับและให้คลิกที่ปุ่ม Create New App 
  2. จากนั้นให้ป้อนApp Name และ App Namespace โดย App name ความยาวตั้งแต่สามตัวขึ้นไปแต่ไม่เกิน 32 ตัว และต้องไม่มีคำอะไรที่มีชื่อคล้าย ๆ หรือสื่อไปถึง Facebook ส่วน App Namespace ให้ตั้งชื่อ URL ของ App เราภายใต้ Facebook เช่นถ้าเราใส่ App NameSpace เป็น hellohellofb เราจะอ้างถึงโปรแกรมของเราได้จาก URL นี้ http://apps.facebook.com/hellohellofb จากนั้นคลิกปุ่ม Continue และป้อนรหัสตรวจสอบให้เรียบร้อย
  3.  ป้อนข้อมูลต่อไปนี้ 
  4. App Domains : ชื่อโดเมนของเว็บโฮสต์ติง 
    Sandbox Mode: ให้เลือก Enable จุดประสงค์ของการเลือกโหมดนี้ก็คือเราต้องการจะทดลองแอพของเรา ยังไม่ต้องการให้คนอื่นใช้ และการเลือกข้อนี้ ทำให้เราไม่ต้องไปกำหนด URL ที่เป็น https ในหัวข้อถัดไป แต่ถ้าคุณต้องการให้คนอื่นใช้ App นี้ด้วยต้องเลือก Enable และคุณต้องมี  URL แบบ https อีกด้วย
    canvas URL: ตรงนี้ให้ป้อน URL ของเว็บแอพคุณครับ เช่นของผม hellofb.atwebpages.com/ ต้องใส่ / หลังสุดนะครับ ไม่งั้นเฟซบุ๊คไม่ยอม
    secure canvas URL: ใส่ค่า URLแบบ https ของเว็บแอพ ค่านี้ต้องใส่ถ้าคุณเลือก Sandbox Mode เป็น disabled

    จากนั้นกดปุ่ม save changes 

  5. ทดลองใช้งานโปรแกรมโดยป้อน URL  ในรูปแบบ apps.facebook.com/AppNamespaces สำหรับค่า AppNamespaces ให้ใช้ค่าที่ป้อนไว้ในขั้นที่สอง ซึ่งถ้าไม่มีอะไรผิดพลาดก็ควรจะได้ผลลัพธ์ดังนี้ 



  6. เป็นอันว่าเรียบร้อยครับสำหรับบทความแรกนี้ ก็หวังว่าจะเป็นแนวทางเบื้องต้นให้กับคนที่ต้องการสร้างเฟซบุ๊คแอพนะครับ