前言
此筆記主要紀錄如何使用 socket.io。
內容根據官方文件撰寫,做出一個簡易的即時訊息。
安裝套件
會使用到 express,socket.io,nodemon
新增 server.js
- 使用 express 開啟一個在 3000 port 的 server
1 2 3 4 5 6 7 8 9 10 11 12
| 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'); });
|
然後就可以在 http://localhost:3000
開啟網頁。
- 更改讀取檔案的位置
1 2 3
| app.get('/', (req, res) => { res.sendFile(__dirname + '/index.html'); });
|
- 新增一個簡易 html 檔案 (index.html)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <!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>
|
- 修改 server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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'); });
|
- 在 index.html 檔案中,新增
<script>
。將 /socket.io/socket.io.js
的方法引入 html 中。
1 2 3 4
| <script src="/socket.io/socket.io.js"></script> <script> const socket = io(); </script>
|
- 處理 client 端的發送訊息功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script src="/socket.io/socket.io.js"></script> <script> var socket = io();
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 = ''; } }); </script>
|
- 確認 server.js 是否有接收到 client 端的訊息
1 2 3 4 5
| io.on('connection', (socket) => { socket.on('chat message', (msg) => { console.log('message: ' + msg); }); });
|
- 完整 Code
server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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) => { socket.on('chat message', (msg) => { io.emit('chat message', msg); }); })
server.listen(4000, () => { console.log('Not listening on port 4000'); })
|
index.js
接收訊息後,新增一個 li
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| ... <ul id="messages"></ul> <form id="form" action=""> <input id="input" autocomplete="off" /><button>Send</button> </form> <script src="/socket.io/socket.io.js"></script> <script> const socket = io();
const form = document.getElementById("form"); const input = document.getElementById("input") const messages = document.getElementById("messages")
form.addEventListener("submit",function(e){ e.preventDefault(); if (input.value) { socket.emit('chat message', input.value); input.value = ''; } })
socket.on("chat message",function(msg){ const item = document.createElement('li'); item.textContent = msg; messages.appendChild(item); window.scrollTo(0, document.body.scrollHeight); }) </script>
|
Socket io 與 Websocket 的差別
websocket
websocket 是一種通信協定,它透過TCP去連接用戶與伺服器,使他們之間產生雙向通信。
而 websocket 會保持開啟的狀態,所以它允許即時的數據傳輸。當用戶向伺服器發送請求時,它不會接收到回應後關閉連結(TCP/IP 三向交握、四次揮手結束連線),而是會持續存在,並等待用戶或是伺服器停止請求。
主要功能:
- WebSocket 在用戶端和 Web 伺服器之間建立即時通信。
- 該協議有助於在伺服器和客戶端之間的建立一個跨平臺的即時通訊環境。
- 它的主要優點是可以提供全雙工通信的 HTTP 連接。
socket.io
socket.io 是一個面向即時 web 應用的 JavaScript library。
比較
websocket |
socket io |
協議建立在 TCP 連接的基礎上 |
此 Library 在 websocket 上工作 |
在 TCP 上創建雙向通訊 |
在瀏覽器和服務器之間創建事件通訊 |
不支持代理與負載均衡 |
支持代理與負載均衡 |
不支持廣播 |
支持廣播 |
參考連結
WebSocket和 Socket.io 之間的區別(譯) - 知乎