1、前言
Socket.io將資料傳輸部分獨立出來形成engine.io,engine.io對WebSocket和AJAX輪詢進行了封裝,形成了一套API,遮蔽了細節差異和相容性問題,實現了跨瀏覽器/跨裝置進行雙向資料通訊。 WebSocket是一種**雙向通訊協議,**WebSocket與HTTP協議一樣都是基於TCP的
2、功能與效果
- 登陸、登出
- 多使用者聊天
- 效果如下
3、目錄結構
4、Node端服務
socket.io 服務需要依賴http服務,通過安裝express,起一個http服務,然後安裝socket.io
npm i socket.io express -S
複製程式碼
通過訪問localhost:3000 訪問頁面
// app.js
const app = require("express")();
const server = require("http").Server(app);
const io = require("socket.io")(server);
app.get("/", function (req, res, next) {
res.sendFile(__dirname + "/index.html");
});
server.listen("3000", function () {
console.log("服務啟動在3000");
});
複製程式碼
服務端用到的socket.io的api
const io = require("socket.io")(server);
// 連線socket.io
io.on("connect", (socket) => {
// socket.emit 代表著向客戶端傳送訊息,客戶端通過 socket.on("receive", params); 接收
socket.emit("receive",params);
// socket.on('send') 代表著接收客戶端發來的訊息, 客戶端通過 socket.emit("send", params); 傳送
socket.on("send",params);
// io.emit("all") 代表廣播,給每個客戶端發訊息
io.emit("all",params)
})
複製程式碼
5、客戶端socket的使用
客戶端主要是使用socket.io的 emit 傳送訊息和on接收訊息,和服務端的api相同 index.html
// 客戶端需要引入包
<script src="/socket.io/socket.io.js"></script>
<script>
// 使用
let socket = io("http://localhost:3000");
// 1、等待服務端的訊息通知
socket.on("notify", (username) => {
message(`${username}加入進來了!`, 1);
});
// 2、傳送訊息給服務端
function send() {
if (!info.value) message("請輸入訊息", 0);
socket.emit("message", people);
}
</script>
複製程式碼
6、使用者登陸和列表展示流程
- 客戶端登陸通過sock.emit 將賬號名稱發給服務端
- 服務端通過socket.emit 傳送給客戶端登陸成功, 通過 io.emit 廣播給所有客戶端
- 服務端儲存使用者資訊到user中,廣播給客戶端
- 客戶端通過拿到的資料展示
7、完成程式碼
1、客戶端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<style>
#btn,
#info {
display: none;
}
</style>
<body>
<h4>簡易聊天室</h4>
<div>
當前使用者列表
<ul id="userList"></ul>
</div>
<input type="text" id="account" />
<button onclick="login()">登陸</button>
<button onclick="loginOut()">退出登陸</button>
<input type="text" id="info" />
<button id="btn" onclick="send()">傳送</button>
<div id="text"></div>
<script src="/socket.io/socket.io.js"></script>
<script>
let account = document.querySelector("#account");
let info = document.querySelector("#info");
let text = document.querySelector("#text");
let btn = document.querySelector("#btn");
let userList = document.querySelector("#userList");
let socket = io("http://localhost:3000");
let SUCCESS = "#4d834d",
ERROR = "#f00",
OTHER = "orange";
let people = {
username: "",
message: "",
};
// 1、 登陸成功,通知服務端,廣播訊息
function login() {
let accountName = account.value;
if (!accountName) return message("請輸入賬號!", 0);
if (people.username) return message("您已登陸!", 0);
people.username = accountName;
socket.emit("login", accountName);
}
socket.on("loginSuccess", (users) => {
message(people.username + "登陸成功!", 1);
info.style.display = "inline-block";
btn.style.display = "inline-block";
});
socket.on("updateUserList", (users) => {
// 更新使用者列表
let liTxt = "";
users.map((item) => {
let txt =
item.username === people.username
? item.username + "(本人)"
: item.username;
liTxt += "<li style='color:blue;'>" + txt + "</li>";
});
userList.innerHTML = liTxt;
});
// 2、傳送訊息,廣播訊息
function send() {
if (!info.value) message("請輸入訊息", 0);
people.message = info.value;
info.value = "";
socket.emit("message", people);
}
// 3、退出操作
function loginOut() {
socket.emit("loginOut");
info.style.display = "none";
btn.style.display = "none";
account.value = "";
people = {};
}
socket.on("loginOut", (username) => {
if (username) {
message(username + "退出了群聊!", 0);
return;
}
message("您未登陸!", 0);
});
// 處理加入通知
socket.on("notify", (username) => {
message(`${username}加入進來了!`, 1);
});
// 接收處理訊息
socket.on("recevied", (username, msg) => {
let date = new Date().toLocaleString();
message(`${username}: ${msg}---------${date}`, 3);
});
// 統一處理訊息
function message(message, status) {
let color = { 1: SUCCESS, 0: ERROR, 3: OTHER };
text.innerHTML += `<span style='color:${color[status]};'>${message}</span><br/>`;
}
</script>
</body>
</html>
複製程式碼
2、服務端
const app = require("express")();
const server = require("http").Server(app);
const io = require("socket.io")(server);
server.listen("3000", function () {
console.log("服務啟動在3000");
});
app.get("/", function (req, res, next) {
res.sendFile(__dirname + "/index.html");
});
let users = []; // 記錄當前所有使用者資訊
// 連線
io.on("connect", (socket) => {
// 登陸處理
socket.on("login", (username) => {
users.push({
username: username,
});
socket.username = username;
name = username;
// 推送登陸成功
socket.emit("loginSuccess");
//廣播事件 io.emi 加入通知
io.emit("notify", username);
io.emit("updateUserList", users);
});
// 訊息處理
socket.on("message", (people) => {
let { username, message } = people;
io.emit("recevied", username, message);
});
// 退出連線
socket.on("loginOut", () => {
// 退出的時候廣播,退出處理
io.emit("loginOut", socket.username);
users = users.filter((item) => item.username !== socket.username);
socket.username = "";
io.emit("updateUserList", users, socket.username);
});
});
複製程式碼