เข้าใจ Socket.IO เบื้องต้น
เราจะทำระบบแชทแบบเรียลไทม์โดยการใช้ Socket io กัน
**การอธิบายจะมีการใช้ express ซึ่งเป็น web framework ในการเขียน AP
ขั้นตอนที่ 1 : สร้าง Server อย่างง่ายขึ้นมาตามลำดับตามนี้
สร้างไดเรกทอรีขึ้นมาชื่อ myapp
mkdir myapp
การ initial โปรเจคขึ้นมา
npm init
ติดตั้ง dependencies ชื่อ express ลงในโปรเจ็คสำหรับการเขียน server
npm install express --save
สร้างไฟล์ app.js เพื่อเขียน server อย่างง่ายดังนี้
const express = require('express');const app = express();const http = require('http');const server = http.createServer(app);app.get('/', (req, res) => { res.send('<h1>Hello world</h1>');});server.listen(3000, () => { console.log('listening on *:3000');});
รัน server
node app.js
Server จะรอรับ request อยู่ที่ port 3000 เราจึงสามารถเข้าไปใช้ service ได้ที่ port 3000 ผ่านเบราว์เซอร์ ดังนี้
อธิบาย ********
เมื่อเราเข้า URL ดังกล่าวผ่านเบราว์เซอร์จะเป็นการส่ง HTTP request ไปยัง server เพื่อขอใช้ service นี้
เมื่อเซิร์ฟเวอร์ได้รับ request จึงตอบกลับ( responde ) ไปให้ Client ซึ่งแพ็ค html element ไปด้วยทำให้เบราว์เซอร์สามารถอ่านข้อความนั้นได้เป็นดังที่แสดง
********
แทนที่เราจะส่งแบบนี้เราสามารถส่งเป็นไฟล์ html ไปได้เลยโดย
สร้างไฟล์ index.html ขึ้นมาในระดับเดียวกับ app.js ดังนี้
<!DOCTYPE html><html> <head> <title>Test</title> </head> <body> <h1>Hello world!!!</h1> </body></html>
เมื่อได้ไฟล์ index.html มาแล้วก็เปลี่ยนจากที่เคยส่ง html element ไปก็ส่งไปทั้งไฟล์ดังนี้
**เปลี่ยนแค่บรรทัดที่ 7 การเปลี่ยนโค้ดของ server ( app.js ) จะต้อง run server ขึ้นมาใหม่ ( node app.js ) หากไม่อยากรันใหม่ให้โหลด nodemon มาใช้แต่จะไม่ได้สอนในบทเรียนนี้
จะเมื่อรีหน้าเบราว์เซอร์จะได้หน้าตาคล้ายๆเดิมดังนี้
เราจะสร้างช่องแชทกัน
เปลี่ยนแปลง index.html เพื่อสร้าง field มารับค่าเพื่อที่จะสร้างระบบแชทระว่าง 2 client ขึ้นมาดังนี้
<!DOCTYPE html><html><head><title>Socket.IO chat</title><style>body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
sans-serif; }#form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }#input:focus { outline: none; }#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }#messages { list-style-type: none; margin: 0; padding: 0; }#messages > li { padding: 0.5rem 1rem; }#messages > li:nth-child(odd) { background: #efefef; }</style></head><body> <ul id="messages"></ul> <form id="form" action=""> <input id="input" autocomplete="off" /><button>Send</button> </form></body></html>
เมื่อเรารีโหลดหน้าเบราว์เซอร์เราจะได้หน้าตาที่ต่างออกไปโดยเราจะมีฟอร์มให้กรอกดังนี้
อธิบาย********
เราจะสร้างฟอร์มเพื่อรับเตรียมรับค่าเท่านั้นยังไม่ได้ทำอะไรต่อ
ดังนั้นจะยัง action บนเบราว์เซอร์ไม่ได้
**************
ขั้นตอนที่ 2 : เพิ่ม Socket.IO เข้าไป
ติดตั้ง Socket.IO ลงโปรเจ็ค
npm install socket.io
เราจะเพิ่ม socket io เข้าไปในเซิร์ฟเวอร์ดังนี้
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
มีโค้ดที่เพิ่มมาคือ บรรทัดที่ 5-6 และ 12-14
io.on('connection', (socket) => { console.log('a user connected');});
แก้ไข index.html ให้ client connect server ด้วย web socket ดังนี้
<script src="/socket.io/socket.io.js"></script><script> var socket = io();</script>
เมื่อมี Client connect( ตอนเรารีโหลดหน้าเว็บ / เข้ามาใหม่)เข้ามาที่ server จะแสดงข้อความ 1 ครั้งตามที่เราเขียนเอาไว้ใน app.js ดังนี้
เราจะเห็นได้ว่า Client สามารถ Connect กับ Server ได้ แต่เราอยากทำให้สื่อสารกับ Socket อื่นแบบเรียลไทม์
เขียนส่วนที่รับข้อความจาก Client และนำไปส่งต่อผ่าน Socket
io.on('connection', (socket) => { socket.on('chat message', (msg) => { io.emit('chat message', msg); });});
อธิบาย**********
ฟังก์ชันนี้จะทำงานเมื่อมี Socket connect เข้ามา และเมื่อ Client ส่ง message ผ่าน Socket จากนั้น Server จะนำ message ส่งไปหาทุก Socket ที่เปิดรับ Event ชื่อ chat message สามารถตั้งชื่อ Event อื่นได้
****************
เพิ่ม script ที่นำ message ที่รับมาจาก server มาแสดงและสามารถส่ง Message ให้กลับ Server เพื่อให้ Server ส่งต่อให้กับ Socket อื่นๆดังนี้
<script src="/socket.io/socket.io.js"></script><script>var socket = io();var messages = document.getElementById('messages');var form = document.getElementById('form');var input = document.getElementById('input');form.addEventListener('submit', function(e) { e.preventDefault(); if (input.value) { socket.emit('chat message', input.value); input.value = ''; }});socket.on('chat message', function(msg) { var item = document.createElement('li'); item.textContent = msg; messages.appendChild(item); window.scrollTo(0, document.body.scrollHeight);});</script>
อธิบาย*********
เมื่อ Form ถูก submit จะส่ง Message ไปที่ Event ชื่อ chat message เมื่อเซิร์ฟเวอร์ได้รับก็จะนำไปส่งให้ Socket อื่นๆต่อ
ในทางกลับกับกันถ้ามีผู้อื่นส่ง Message มาเราจะได้รับผ่าน Event chat message และนำไปแสดงผล
***************
เมื่อเราเปิดเบราว์เซอร์สองอันและพิมพ์แชทจะทำให้ message ถูกส่งโดยที่เราไม่ต้อง reload หน้าเบราว์เซอร์ดังนี้
เรารู้ได้อย่างไรว่าเป็น Socket คนละตัวกัน
ส่ง Socket id กลับมาด้วยดังนี้
*การเปลี่ยนแปลง API ต้องรันใหม่ถ้าไม่อยากรันใหม่ก็ต้องโหลด nodemon มาใช้นะจ๊ะ
ผลลัพธ์
****************************จบละ********************************
**********หากผิดพลาดประการใดขออภัยไว้นะที่นี่ด้วยนะครับ***********