1、几十行代码实现一个聊天室
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、一对一对话功能实现
服务端 通过io.to(socketId).to(socketId).emit('my message') 发送给客户端 socketId是每个客户端登陆后都会生成的独一无二的标识, to就是向哪个人发送 服务端代码
服务端代码
// 发送消息给某人
socket.on("say to someone", (myId, userId, msg) => {
let { sockedId, username } = users.find((el) => el.sockedId === myId);
io.to(myId).to(userId).emit("my message", username, msg);
});
客户端代码
// 4、点击enter发送消息给单个的人
function clickEnter(e) {
let myId = socket.id;
let userId = event.path[0].getAttribute("sockedId");
let msg = event.path[0].value;
var evt = window.event || e;
if (evt.keyCode == 13) {
event.path[0].value = "";
socket.emit("say to someone", myId, userId, msg);
}
}
// 5、接收消息 展示出来
socket.on("my message", (username, msg) => {
let date = new Date().toLocaleString();
message(`${username}: ${msg}---------${date}`, 3);
});
8、完整代码
1、客户端
Title #btn, #info { display: none; }简易聊天室
当前用户列表账号: 登陆 退出登陆
发送 ```
2、服务端
const app = require("express")();
const server = require("http").Server(app);
const io = require("socket.io")(server);
server.listen("8080", 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, id) => {
users.push({
username: username,
sockedId: id,
});
socket.username = username;
// 推送登陆成功
socket.emit("loginSuccess");
//广播事件 io.emi 加入通知
io.emit("notify", username);
io.emit("updateUserList", users);
});
// 退出连接
const disconnect = () => {
if (socket.username) io.emit("loginOut", socket.username);
users = users.filter((item) => item.username !== socket.username);
socket.username = "";
io.emit("updateUserList", users, socket.username);
};
//监听用户断开连接 和用户主动退出
socket.on("disconnect", disconnect);
socket.on("loginOut", disconnect);
// 消息处理
socket.on("message", (people) => {
let { username, message } = people;
io.emit("recevied", username, message);
});
// 断开连接
socket.on("error", (reason) => {
console.log(reason + "发生错误");
});
// 发送消息给某人
socket.on("say to someone", (myId, userId, msg) => {
let { sockedId, username } = users.find((el) => el.sockedId === myId);
io.to(myId).to(userId).emit("my message", username, msg);
});
});