เริ่มศึกษา node.js ด้วยการสร้าง chat room

เริ่มศึกษา node.js ด้วยการสร้าง chat room

chat room ไม่ใช่เรื่องใหม่เลย รวมทั้งการใช้งาน PHP, HTML , javascript ปกติก็ทำได้อยู่แล้ว แต่... ถ้าผมจะยังทำแบบเดิม ก็แปลว่า ผมก็ย่ำอยู่ที่เดิม จริงๆแล้วคนที่อยู่ในสายงานนี้ ไม่มีคำว่าอยู่ที่เดิมครับ มีแต่ ก้าวหน้า กับถอยหลังเท่านั้นเอง เพราะว่าโลกของ technology นั้นไม่เคยหยุดนิ่ง มีสิ่งใหม่ให้เราต้องเรียนรู้มันตลอดครับ ถ้าคุณแค่หยุดการเรียนรู้ นั่นคือคุณกำลังถอยหลัง เพราะคนอื่นเค้าก้าวล้ำไปข้างหน้าอย่างตลอดเวลานั่นเอง

ผมไม่ได้คาดหวังว่า chat room ที่สร้างนี้ จะทำให้สามารถเอามาใช้งานเป็น public production ได้ เพราะว่าแค่ต้องการทำเพื่อเรียนรู้ environment ต่างๆของ node.js กับองค์ประกอบที่เกี่ยวข้องเพื่อให้มันตอบสนองงานเราในลักษณะนี้ได้เท่านั้นเอง ตอนนี้ผมยังประสบการณ์น้อย ผมไม่สามารถตอบได้ครับ ว่า chat room เหมาะจะเป็นบทเรียนสำหรับมือใหม่หรือเปล่า ไว้สักวัน ที่ผมมีประสบการณ์มากพอ ผมก็จะกลับมาบอกเล่าคนรุ่นต่อๆไปอีกทีนะครับ

สำหรับ เนื้อหานี้ ผมจะอ้างอิงจาก https://code.google.com/p/nodejs-win/wiki/SimpleChatSystem เนื่องด้วย ลองโค้ดมาหลายชุด จากหลายเว็บ แต่ไม่ work ทำงานไม่ได้ มีแต่ตัวนี้ ที่ทำงานได้ แต่ว่าเว็บดังกล่าว ปัจจุบันไม่ได้ update ต่อแล้ว เพราะว่าย้ายไปทำงานที่ nodejs.org นั่นเอง (แต่ script ยังใช้งานได้อยู่ครับ)

node.js คืออะไร ทำหน้าที่อะไร

เล่าเรื่องของ node.js เพิ่มอีกนิด หากใครเข้าใจแล้ว ข้ามย่อหน้าที่ไปได้เลย node.js คือ platform ตัวหนึ่ง (platform มองภาพให้เข้าใจได้ก็คล้ายๆกับ android นั่นแหล่ะครับ ที่มันจะรองรับการติดตั้ง program ข้างใน android ได้ เราก็เขียน programใส่ให้มันรัน โดยเราต้องเขียนตาม pattern ที่ platform นั้นๆกำหนดเท่านั้นเอง) ที่เราจะเขียน software ใส่ให้มันทำงานตามที่ต้องการได้ โดยเราจะใช้ภาษา JavaScript เหมือนที่เราใช้เขียนเว็บนี่แหล่ะ เป็นภาษาที่ใช้เขียน ดังนั้น การศึกษาภาษานี้ ถือว่าไม่ยาก คนที่เขียนเว็บมาเยอะๆ แล้วใช้ javascript เยอะๆก็ถือว่าหมูเลยล่ะ(สำหรับผมเองยังไม่ถือว่าหมูนะ เอิ้กๆ) โดย node.js จะให้ประโยชน์เรา ที่มากกว่า php + apache นั่นก็คือ มันจะไม่ได้ทำงานแบบ บนลงล่างเหมือน php ยกตัวอย่าง เวลาเราเขียน php มันจะทำงานจากบรรทัดบนลงล่าง ถ้าบรรทัดบนทำไม่เสร็จ บรรทัดล่างก็ยังไม่ทำ แบบนี้เค้าจึงเรียกว่า PHP มันมี blocking I/O เพราะลองนึกถึงงานที่ประมวลผลครั้งละ 5 นาที แล้วเรียกพร้อมกัน 100000 ครั้ง เครื่องก็ไม่ต้องทำอะไรกันแล้วครับ โดยการทำงานแบบ node.js เค้าจะเรียกว่า event-driven นั่นก็คือ เราจะควบคุมการทำงานของมันด้วยการ เขียนให้ ตัวหนึ่งไปกระตุ้นอีกตัวหนึ่ง เหมือนกับ นักกีฬาวิ่งผลัด หลายลู่วิ่ง ที่วิ่งออกไปพร้อมกัน ใครไปถึงคนถัดไปแล้วส่งไม้ก่อน คนต่อไปก็ถึงจะออกวิ่งต่อไปได้ (แต่อย่าลืมว่าขณะนั้น มีอีกหลายลู่วิ่งก็วิ่งพร้อมๆกัน) รวมๆกันสองสิ่งนี้ เป็นประโยชน์มหาศาลที่ apache + php ไม่สามารถทำให้ได้ เพราะว่าการทำงานแบบนี้ ทำให้มันรองรับการใช้งานจากคน และ จากจำนวนที่มากกว่า php + apache เป็นพันๆเท่านั่นเอง 

ปัจจุบันนี้เราใช้อะไรกันอยู่

การสร้าง chat room ในแบบที่ง่ายๆ นั่นก็คือ เราเขียน javascript แล้วตั้งเวลาให้มันทำงานตามที่เรากำหนด (interval) เช่นทุกๆ ครึ่งนาที ก็ให้เรียกไปที่ URL นึง เพื่อให้ URL นั้น อ่านข้อมูลที่เก็บใน database หรือว่า text file ที่บรรจุดข้อความ chat ของทุกคนแล้วเอามาแสดงที่หน้าเว็บ โดยเรียงลำดับได้ดังนี้

  1. เรียก URL ที่จะ provide ข้อมูล
  2. ส่งค่าสิ่งที่เราต้องการเรียกเข้าไป (เช่น ชื่อห้อง)
  3. รับค่ามาจาก URL ข้อที่ 1 แล้วมาแสดงผล (เช่น ข้อความ, ชื่อเจ้าของข้อความ, เวลาของข้อความ)
  4. ไปเริ่มทำข้อ 1 ใหม่อีกครั้ง ตามจังหวะเวลาที่ตั้งเวลาหน่วงเอาไว้ เช่นทุก 1 นาที

แบบนี้เค้าจะเรียกว่า การ pulling นั่นเอง 

ที่เรากำลังจะเปลี่ยนมาใช้

แบบใหม่ที่เรากำลังจะใช้งานนี้ เราจะไม่ใช้การ pulling จาก client แต่ว่าเราจะใช้การ push ข้อมูลที่ออกมาจาก server ไปหา client แทน(ทำกลับฝั่งกัน) โดยปัจจุบัน มีหลายตัวที่ทำแบบนี้ได้เช่น WebSockets โดยเนื้อหาตอนนี้ เราก็จะมาใช้งาน node.js, socket.io และ jQuery เพื่อทำงานในแบบ push กัน 

เริ่มต้นทำ chat room ด้วย node.js

ที่ผมเขียน ผมเขียนพร้อมกับศึกษามันไปด้วย ไม่ได้เขียนจากมุมมองที่เป็นผู้มีประสบการณ์ขั้นสูงใน node.js นะครับ learning by doing ครับ ดังนั้น ขั้นตอนไหนดูแปลกๆสามารถชี้แนะได้ทันทีครับ ยินดีรับฟังครับผม และจะเป็นพระคุณด้วย 

ขั้นตอนนี้ ผมถือว่า ทุกท่านทำการติดตั้ง node.js เรียบร้อยแล้วนะครับ ถ้ายัง ลองอ่านบทความติดตั้ง ถือว่าได้ทดสอบ script แล้ว work แล้วนะครับ ก็จะได้เริ่มไปพร้อมๆกันเลย

ติดตั้ง socket.io

เนื่องจากการทำ web application real time หรือ chat room ที่เรากำลังทำเนี่ย เราจะใช้ push technology ซึ่งจะต้องทำงานด้วยการเปิด socket เอาไว้นั่นเอง โดย node เดิมๆทำไม่ได้ เราต้องติดตั้ง socket.io เพื่อมาช่วยงานนี้ โดย socket.io นั้นมี module ใน node ให้เราใช้งานได้ง่าย การติดตั้ง module ใน node ให้เราเข้าไปในแฟ้มที่เรากำลังทำงานอยู่ก่อน แล้วค่อยติดตั้ง module นะครับ โดยเมื่อเราเข้ามาอยู่ในแฟ้มที่เราใช้งานแล้ว(แฟ้มที่เก็บไฟล์ .js) ให้เราติดตั้ง module socket.io ด้วยคำสั่ง

npm install socket.io

ต้องไม่มี error อะไรนะครับ ถือว่าผ่าน พร้อมใช้ครับ

ให้สร้างไฟล์ node.js ขึ้นมา ตั้งชื่ออะไรก็ได้ ผมตั้งชื่อว่า chat4.js นะครับ แล้วใส่โค้ดดังนี้

var io = require('socket.io').listen(8000); // open the socket connection io.sockets.on('connection', function (socket) {        // listen for the chat even. and will recieve    // data from the sender.    socket.on('chat', function (data) {           // default value of the name of the sender.       var sender = 'unregistered';              // get the name of the sender       socket.get('nickname', function (err, name) {          console.log('Chat message by ', name);          console.log('error ', err);          sender = name;       });          // broadcast data recieved from the sender       // to others who are connected, but not       // from the original sender.       socket.broadcast.emit('chat', {          msg : data,          msgr : sender       });    });        // listen for user registrations    // then set the socket nickname to    socket.on('register', function (name) {           // make a nickname paramater for this socket       // and then set its value to the name recieved       // from the register even above. and then run       // the function that follows inside it.       socket.set('nickname', name, function () {                 // this kind of emit will send to all! :D          io.sockets.emit('chat', {             msg : "naay nag apil2! si " + name + '!',             msgr : "mr. server"          });       });    }); }); });

จากนั้น ให้เราเอาไปวางไว้ที่ server node ของเราเลย แล้วสั่งรัน node ด้วย

node test4.js

อย่า งง นะครับ เพราะว่าผมตั้งชื่อไฟล์ว่า test4.js ครับ

จากนั้น ให้เราสร้างไฟล์หน้าเว็บ ผมตั้งชื่อว่า chat.html อันนี้ เราจะใช้ในเครื่องเราเองครับ เป็นเหมือนหน้าเว็บ ให้เปิดเข้าไป chat กันได้กันคนอื่นๆ ถ้าทุกคนเปิดหน้านี้กันหมด ก็จะสามารถร่วม chat กันได้เลยใส่โค้ดดังนี้ครับ 

<html>
   <head>
      <script src="http://192.168.1.47:8000/socket.io/socket.io.js"></script>
      <script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
      <script>
         var name = '';
         var socket = io.connect('http://192.168.1.47:8000');
         
         // at document read (runs only ones).
         $(document).ready(function(){
            // on click of the button (jquery thing)
            // the things inside this clause happen only when
            // the button is clicked.
            $("button").click(function(){
            
               // just some simple logging
               $("p#log").html('sent message: ' + $("input#msg").val());
               
               // send message on inputbox to server
               socket.emit('chat', $("input#msg").val() );
               
               // the server will recieve the message,
               // then maybe do some processing, then it will
               // broadcast it again. however, it will not
               // send it to the original sender. the sender
               // will be the browser that sends the msg.
               // other browsers listening to the server will
               // recieve the emitted message. therefore we will
               // need to manually print this msg for the sender.
               $("p#data_recieved").append("<br />\r\n" + name + ': ' + $("input#msg").val());
               
               // then we empty the text on the input box.
               $("input#msg").val('');
            });
            
            // ask for the name of the user, ask again if no name.
            while (name == '') {
               name = prompt("What's your name?","");
            }
            
            // send the name to the server, and the server's
            // register wait will recieve this.
            socket.emit('register', name );
         });
         
         // listen for chat event and recieve data
         socket.on('chat', function (data) {
         
            // print data (jquery thing)
            $("p#data_recieved").append("<br />\r\n" + data.msgr + ': ' + data.msg);
            
            // we log this event for fun :D
            $("p#log").html('got message: ' + data.msg);
            
         });
      </script>
   </head>
   <body>
      <input type="text" id="msg"><button>Click me</button>
      <p id="log"></p>
      <p id="data_recieved"></p>
   </body>
</html>

เท่านี้ครับ แต่มีข้อสังเกตุคือ http://localhost:8000 เนี่ย ให้เปลี่ยนเป็น ip ของเครื่อง server ที่รัน node อยู่นะครับ ถ้าเครื่องเดียวกัน ก็ใช้แบบนี้ได้ แต่ถ้าเป็น VM หรือ server จริงก็ต้องใส่ ip ให้ตรงตามนั้นครับ เมื่อเปิดหน้าเว็บแล้ว จะมีให้ใส่ชื่อ เมื่อใส่ชื่อแล้วก็จะเข้าห้อง chat เลย พิมพ์ข้อความส่งหากันได้ทันทีครับ

สำหรับการทดสอบก็ง่ายๆด้วยการเปิด chat.html ในหลายๆ browser แล้วลองใส่ชื่อให้ต่างกัน แล้วทดสอบด้วยการ chat กันเอง ก็จะพบว่า สามารถ chat แบบ real time ได้เลย โดยที่ไม่ต้องรอ refresh อะไรใดๆทั้งสิ้นครับ (เหมือน facebook chat เลยล่ะ ต่างกันตรงหน้าตาเท่านั้น)

chat room ไม่ทำงาน

แน่นอนครับ ว่าทุกสิ่งอย่างบนโลก ล้วนต้องมีอุปสรรค แต่เราจะมาหาทางออกร่วมกัน หาก chat room ไม่ทำงาน ต้องไล่ตรวจสอบไปเรื่อยๆครับ อาศัยทักษะพอสมควร 

  • โค้ดถูกต้อง - แน่นอนครับ ถ้าโค้ดผิด ก็จบตั้งแต่เริ่มเลย
  • เปิดหน้าเว็บ ไม่ได้ - ถ้าเปิดไม่ได้ลองดูว่า รันอะไรผิดหรือเปล่า เพราะปกติควรเปิด html ในเครื่องตัวเองดูได้
  • เปิดได้แต่หมุนอยู่นานมาก แล้วไม่มีช่องให้ใส่ชื่อ - กรณีนี้น่าเชื่อได้ว่า หน้าเว็บ connect เข้าไปที่ node ไม่ได้ ให้ตรวจสอบ ค่า http://localhost:8000 ว่าถูกต้องหรือเปล่า port ผิดมั้ย ตรงกับในไฟล์ test4.js หรือเปล่า แล้วเวลารัน node.js มีอะไรแสดง error หรือเปล่า ถ้าทุกอย่างถูกต้องแล้ว ให้เช็ค firewall, iptables ใน linux  ว่าได้เปิด port 8000 หรือยัง (เดิมๆจะไม่ได้เปิดไว้ ทดสอบได้ด้วยการปิด firewall ก่อน ถ้าปิดแล้วยังรันไม่ได้ แสดงว่า ไม่น่าจะเป็นที่ firewall)
  • ทดสอบว่า node ทำงานถูกต้องหรือเปล่า - ใน server ที่รัน node เอง ให้รันทิ้งเอาไว้ แล้วทดสอบด้วยคำสั่ง curl http://localhost:8000 จะต้องได้ Welcome to socket.io. ถือว่าถูกต้อง node ทำงานได้
  • ตรวจสอบว่า เวลาเปิดหน้าเว็บ connect ไปที่ url node ได้โดยไม่มี error - ใช้ firebug ใน firefox ก็ได้ครับ ดูที่ tab console จะต้องมี response เป็น 200 OK

ถ้าทั้งหมดนี้ถูกต้อง แล้วยังทำงานไม่ได้ ก็เผ่นเถอะครับ เพราะไม่น่าจะมีข้อผิดพลาดแล้วล่ะครับ

สำหรับเรื่องที่เราได้เรียนรู้ก็คือ ตัวอย่าง code node.js และหน้าเว็บ ที่ทำงานร่วมกับ node.js server ถ้าทำสำเร็จแล้วลองอ่านโค้ดดู ก็จะเห็นได้ว่า เข้าใจไม่ยาก แม้ว่ามีหลายๆอย่างที่ชวนให้ งง ต่างจาก PHP บ้างก็ตาม แต่ก็ไม่ยากจนเกินไปมากครับ เพียงแค่ ต้องไปทำความรู้จักและเข้าใจ function เพิ่มเติมอีก อย่างเช่น socket.on, socket.get, socket.set, socket.emit เพื่อให้เราเอามันมาใช้ได้อย่างถูกต้องต่อไปครับ

ขอให้สนุกกับ node.js นะครับ

Create: Modify : 2013-04-02 08:56:10 Read : 13921 URL :