发给网络服务器constinput=document

lxf2023-03-10 17:19:01

文中先发于我的公众号:前面西瓜哥

小伙伴们好,我就是前面西瓜哥,现在我们用 WebSocket 来达到一个简单的在线聊天室

WebSocket 是一个网络层协议,有点类似于 HTTP。但跟 HTTP 不一样的是,它适用真正意义上的双工,即不但手机客户端能够积极发信息给服务器端,服务器端还可以积极发信息给手机客户端。

特别是后面一种,使我们也不用再根据 HTTP 长轮询或短轮循的低效能方法来完成服务器端通告。对比 HTTP,WebSocket 的服务器端消息推送更轻巧,并可以减少服务器端压力。

服务器端

nodejs 并没给予原生的 WebSocket 控制模块。假如想要实现,必须根据 net 控制模块,依据 WebSocket 规范去干完成。

由于完成非常复杂,因此西瓜哥我选择直接使用第三库 ws。

yarnaddws

相近 nodejs 原生的 http 等控制模块,ws 库适用 WebSocket 的服务器端或手机客户端, 给予偏最底层的 API。

我们首先完成服务器端编码:

import{WebSocketServer}from"ws";

//创建一个 ws 服务项目
constwsSever=newWebSocketServer({
port:6060,
});

//每每一个手机客户端展开了 ws 联接,便会创建一个 ws 目标
wsSever.on("connection",(ws)=>{
//新手机客户端连接时,广播节目
wsSever.clients.forEach((client)=>{
client.send(`有些人进到在线聊天室,现阶段在线聊天室总数:${wsSever.clients.size}`);
});

//广播节目一切手机客户端上传的信息
ws.on("message",(data)=>{
constmsg=data.toString();
wsSever.clients.forEach((client)=>{
client.send(msg);
});
});

//若有手机客户端撤出时,广播节目
ws.on("close",()=>{
wsSever.clients.forEach((client)=>{
client.send(`有些人退出在线聊天室,现阶段在线聊天室总数:${wsSever.clients.size}`);
});
});
});

每每一个手机客户端展开了 websocket 联接,都是会开启 wsServer 的 connection 事情,随后拿到一个 ws 目标。

这一 ws 目标代表着某一手机客户端和服务器端连接,我们通过它去接受相匹配客户端的信息,然后让服务器端对特定手机客户端开展积极消息提醒。

创好的 ws 目标会到建立联系时保存到 wsServer.clients 结合下,并且在关掉联接后退除。因此我们可以利用这一 wsServer.clients 去进行广播节目,完成在线聊天室作用。

手机客户端

手机客户端应用原生的 WebSocket 目标,来跟服务器端开展 WebSocket 联接。

constws=newWebSocket('ws://localhost:6060');

ws.addEventListener('message',(event)=>{
constdiv=document.createElement('div');
div.innerText=event.data;
document.body.append(div);
})

//点一下推送按键,将文本框里面的内容发给网络服务器
constinput=document.querySelector('input');
constbtn=document.querySelector('button');
btn.onclick=()=>{
ws.send(input.value);
input.value='';
}

实际效果

发给网络服务器constinput=document

简单在线聊天室

改成应用 Socket.IO

ws 库是偏最底层的完成,非常简单。

另一个库 Socket.IO 的底层用了 ws,并进行作用里的提高,提供更好的水平。

对比 ws,Socket.IO 可以做到:

  1. 假如浏览器不支持 WebSocket,返回为 HTTP 长轮询计划方案来模拟 WebSocket( WebSocket 于 2011 年完成 RFC,很久了,目前来看主流浏览器都已适用 WebSocket 了,还没适用 WebSocket 浏览器是屑);

  2. 应用心跳包体制完成了全自动重新连接。

  3. 包缓存文件。断连时传送数据,会把信息存储出来,等重连之后再推送;

  4. 自定义事件适用;

  5. 广播节目;

对比自己去一个个完成,应用最流行的车轮子有可能是最佳的选择。

我们将要前面的作用用 Socket.IO 完成一下。

服务器端:

import{Server}from"socket.io";

//socket.io v3.x 逐渐默认设置不可以跨域请求,必须在配置显式设为容许跨域请求
constio=newServer(6060,{cors:{origin:"*"}});

io.on("connection",(socket)=>{
//新手机客户端连接时,广播节目
io.emit("chat",`有些人进到在线聊天室,现阶段在线聊天室总数:${io.engine.clientsCount}`);

//广播节目一切手机客户端上传的信息
socket.on("chat",(data)=>{
io.emit("chat",data);
});

//若有手机客户端撤出时,广播节目
socket.on("disconnect",()=>{
io.emit("chat",`有些人退出在线聊天室,现阶段在线聊天室总数:${io.engine.clientsCount}`);
});
});

必须特别注意的是,Socket.IO 的 v3.x 版本号逐渐,默认设置不可以跨域请求,必须在配置显式设为容许跨域请求。

手机客户端:

constsocket=io('ws://localhost:6060');

socket.on('chat',(data)=>{
constdiv=document.createElement('div');
div.innerText=data;
document.body.append(div);
})

//点一下推送按键,将文本框里面的内容发给网络服务器
constinput=document.querySelector('input');
constbtn=document.querySelector('button');
btn.onclick=()=>{
console.log('推送');
socket.emit('chat',input.value);
input.value='';
}

Socket.IO 特点是完成了工作环境必须的底层非业务水平,让我们可以更心无杂念的去撰写业务代码

主要缺点丢了协调能力。由于进行了个性化,因此需要配套使用 Socket.IO 的服务端和服务器端库的包,某种程度远离了网络层协议规范。当出现跨语言表达(例如前面是 JS,后端是 Java)的画面时,需要提供相对应的语言的表达 Socket.IO 完成。

demo

demo 早已放进 github 上,操作方法在 README.md 含有表明。

github.com/F-star/webs…

末尾

文中演示了 WebSocket 简单的在线聊天室作用是如何做到的,希望对大家有帮助。

我就是前面西瓜哥,请关注我,了解更多的前端知识。