認識 socket.io

前言

此筆記主要紀錄如何使用 socket.io。
內容根據官方文件撰寫,做出一個簡易的即時訊息。

安裝套件

會使用到 expresssocket.ionodemon

新增 server.js

  1. 使用 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. 更改讀取檔案的位置
1
2
3
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
  1. 新增一個簡易 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>
  1. 修改 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);
// 新增 socket.io 用法
const { Server } = require("socket.io");
const io = new Server(server);

// 修改檔案讀取位置
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});

// 新增 connection
io.on('connection', (socket) => {
console.log('a user connected');
});

server.listen(3000, () => {
console.log('listening on *:3000');
});
  1. 在 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>
  1. 處理 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>
  1. 確認 server.js 是否有接收到 client 端的訊息
1
2
3
4
5
io.on('connection', (socket) => {
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
});
});
  1. 完整 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');
});

// 使用 socket.io 開啟 connection
io.on("connection", (socket) => {
socket.on('chat message', (msg) => {
// 發送給 client 端
io.emit('chat message', msg);
});
})

// 在 4000 port 開啟一個 http server
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>
// 使用 io 裡面的方法
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) {
// 接收 server 端傳來的 msg
socket.emit('chat message', input.value);
input.value = '';
}
})

socket.on("chat message",function(msg){
// 新增 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 之間的區別(譯) - 知乎


認識 socket.io
https://phoebeho.com/Web/20220331/2809986606/
作者
Phoebe
發布於
2022年3月31日
許可協議