เข้าใจ Socket.IO เบื้องต้น

Pongsathon Chodchoi
4 min readJul 6, 2021

--

เราจะทำระบบแชทแบบเรียลไทม์โดยการใช้ Socket io กัน

**การอธิบายจะมีการใช้ express ซึ่งเป็น web framework ในการเขียน AP

ขั้นตอนที่ 1 : สร้าง Server อย่างง่ายขึ้นมาตามลำดับตามนี้

สร้างไดเรกทอรีขึ้นมาชื่อ myapp

mkdir myapp

การ initial โปรเจคขึ้นมา

npm init
ไฟล์ที่ได้จากการ initial

ติดตั้ง 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 มาใช้นะจ๊ะ

ผลลัพธ์

****************************จบละ********************************

**********หากผิดพลาดประการใดขออภัยไว้นะที่นี่ด้วยนะครับ***********

--

--

No responses yet