这是什么?websocket?用一下

           

发布于 2023-02-01  642 人经过了这里


哈喽大家好呀,咱自己的博客一转眼都快拖更1年了实在抱歉(被打x
实际上这一年里喵喵折腾的很多东西(x只是没有在这写出文章来罢了,回头有兴趣的话我可以再写几篇qwq
如果你好奇喵喵的某些项目是如何实现的,欢迎来找咱qwq咱说不定再写一篇文章放这

很久很久以前,喵喵在本站点(qwq.re)整了个聊天室插件,因为当时不会写(x
后来呢,写过了在线摸摸啊、像素绘板啊...其实也能用AJAX来写一个实时聊天室

但是为什么我没有这么做呢?因为AJAX本质上还是HTTP/HTTPS协议
这个协议的坏处就是:只能是客户端发出请求,不能主动接受服务端的请求
这就导致了什么呢?导致了每个用户都得一直对着服务器发出HTTPS请求,服务器很累!
比如我们定的刷新时间是1s,那假如有10个人在聊天室,那么服务器每秒需要处理10个请求
如果刷新时间更短比如0.5s,那就是每秒20个请求!!!

为什么说这不好呢?因为每秒这么多请求不就跟"CC攻击"似的(当然没那么严重
啊,这时候可能有人站出来说:我为什么不用AJAX长轮询呢?
可以是可以,但是不还是只能客户端发出请求吗,这还是太low了

实际上服务器负载并不是AJAX写聊天室的最大问题,最大问题是:
一个人发送完消息,其他用户不能同时且第一时间收到消息

就不说为什么会这样了,相信大家都能很容易理解上面这一点,这在聊天中是很致命的坏处

那怎么办呢?这时候喵喵就使用了:当当当当!

websocket

什么是websocket?实际上,这就不是我们平常访问网页的常见HTTP/HTTPS协议了
它是这个协议:WS://或WSS://(和HTTP/HTTPS一样,后面加个S是带证书的)

这个协议客户端可以接收服务端的请求!
这不就完美的解决了这个问题吗,那我们废话不多说,直接开干~

喵喵在这里使用NodeJS来讲解,实际运用中多种语言都可以哦(比如喵喵的Raccon聊天室就是PHP干出来的x)
(为什么用NodeJS讲呢,是因为喵喵是先学习NodeJS写WS连接再后学PHP那边的x)

首先,因为是NodeJS,所以服务端我们使用.js文件,客户端.html即可,我们先说服务端:

首先是这几行:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

这些是加载需要用到的包和扩展,需要事先在NJS中配置好

然后是主体部分:

users = [];    //将用户存到数组中
io.on('connection', function(socket) { socket.on('setUsername', function(data) { users.push(data); io.sockets.emit('join', data); io.sockets.emit('fresh','Now online: ' + users.toString()); console.log(users); } }); socket.on('msg', function(data) { io.sockets.emit('newmsg', data); }) socket.on('disconnect', function() { if(socket.name){ io.sockets.emit('left', socket.name); users.splice(users.indexOf(socket.name),1); } io.sockets.emit('fresh','Now online: ' + users.toString()); }) });

这是一个大体的模型,实际中肯定是比这个复杂的,喵喵也是简化了这些代码希望能让大家看懂(x

然后是客户端的Script部分,其他部分随便写一下就好啦~

    var socket = io();
//起名相关,,,想怎么写怎么写x socket.on('userSet', function(data) { user = data.username; document.body.innerHTML = '这里写相关的html元素'; function sendMessage() { var msg = document.getElementById('message').value; if(msg) { socket.emit('msg', {message: msg, user: user}); document.getElementById('message').value = ""; //发送完消息后清空输入框 } } socket.on('newmsg', function(data) { if(user) { document.getElementById('message-container').innerHTML += '收到的信息内容'; } }) socket.on('join', function(data) { document.getElementById('message-container').innerHTML += 'xxx进入聊天室'; }) socket.on('left', function(data) { document.getElementById('message-container').innerHTML += 'xxx退出聊天室'; }) socket.on('fresh', function(data) { document.getElementById("now").innerHTML = data; })

当然实际中可能代码量至少是上面的2 3倍,这样简化模型只是为了方便理解
里面的对应关系弄懂后你想怎么写就怎么写~比如喵喵现在还在这个NJS项目中写了个小圈圈移动x
所以上面便有了:起名,进入提醒,退出提醒,聊天,显示当前在线人员 这些非常实用的功能

最后就完成啦~项目地址:chat.qwq.re(以后可能就关停掉了,因为现在喵喵还是喜欢PHPx)

放张截图(?不过放的是Raccon聊天室x没关系,虽然后端不一样,但是功能实现的是一样的x