基于nodejs+websocket搭建即时通讯应⽤
如果说AJAX是像⼿机发短信⼀样,发送信息,获取信息,那么websocket技术则是打电话这样。Web领域的实时推送技术,也被称作Realtime技术。这种技术要达到的⽬的是让⽤户不需要刷新浏览器就可以获得实时更新。在以前你可能会使⽤AJAX进⾏轮询,这造成了服务器的多重压⼒,使⽤websocket,既可实现⼀次连接,保持通话的作⽤。⽽它有着⼴泛的应⽤场景,⽐如室、系统、评论系统、WebIM等。
WebSocket简介
要做到WEB实时推送,就让⼈想到WebSocket。在WebSocket出现之前,很多⽹站为了实现实时推送技术,通常采⽤的⽅案是轮询(Polling)和Comet技术,Comet⼜可细分为两种实现⽅式,⼀种是长轮询机制,⼀种称为流技术,这两种⽅式实际上是对轮询技术的改进,这些⽅案带来很明显的缺点,需要由浏览器对服务器发出HTTP request,⼤量消耗服务器带宽和资源。
⾯对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并实现真正意义上的实时推送。
WebSocket协议本质上是⼀个基于TCP的协议,它由通信协议和编程API组成,WebSocket能够在浏览器
和服务器之间建⽴双向连接,以基于事件的⽅式,赋予浏览器实时通信能⼒。既然是双向通信,就意味着服务器端和客户端可以同时发送并响应请求,⽽不再像HTTP的请求和响应。
为了建⽴⼀个WebSocket连接,客户端浏览器⾸先要向服务器发起⼀个HTTP请求,这个请求和通常的HTTP请求不同,包含了⼀些附加头信息,其中附加头信息”Upgrade: WebSocket”表明这是⼀个申请协议升级的HTTP请求,服务器端解析这些附加的头信息然后产⽣应答信息返回给客户端,客户端和服务器端的WebSocket连接就建⽴起来了,双⽅就可以通过这个连接通道⾃由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某⼀⽅主动的关闭连接。
⼀个典型WebSocket客户端请求头:
前⾯讲到WebSocket是HTML5中新增的⼀种通信协议,这意味着⼀部分⽼版本浏览器(主要是IE10以下
版本)并不具备这个功能,,IE8⽬前仍以33%的市场份额占据榜⾸,好在chrome浏览器市场份额逐年上升,现在以超过26%的市场份额位居第⼆,同时微软前不久宣布停⽌对IE6的技术⽀持并提⽰⽤户更新到新版本浏览器,这个曾经让⽆数前端⼯程师为之头疼的浏览器有望退出历史舞台,再加上⼏乎所有的智能⼿机浏览器都⽀持HTML5,所以使得WebSocket的实战意义⼤增,但是⽆论如何,我们实际的项⽬中,仍然要考虑低版本浏览器的兼容⽅案:在⽀持WebSocket的浏览器中采⽤新技术,⽽在不⽀持WebSocket的浏览器⾥启⽤Comet来接收发送消息。
WebSocket实战
我们将实现⼀个nodejs + websocket的聊天室
需求分析
1、兼容不⽀持WebSocket的低版本浏览器。
2、允许客户端有相同的⽤户名。
3、进⼊聊天室后可以看到当前在线的⽤户和在线⼈数。
4、⽤户上线或退出,所有在线的客户端应该实时更新。
5、⽤户发送消息,所有客户端实时收取。
在实际的开发过程中,为了使⽤WebSocket接⼝构建Web应⽤,我们⾸先需要构建⼀个实现了 WebSocket规范的服务端,服务端的实现不受平台和开发语⾔的限制,只需要遵从WebSocket规范即可,⽬前已经出现了⼀些⽐较成熟的 WebSocket服务端实现,⽐如本⽂使⽤的Node.js+Socket.IO。为什么选⽤这个⽅案呢?先来简单介绍下他们两。
Node.js
Node.js采⽤C++语⾔编写⽽成,它不是Javascript应⽤,⽽是⼀个Javascript的运⾏环境,据Node.js创始⼈ Ryan Dahl回忆,他最初希望采⽤Ruby来写Node.js,但是后来发现Ruby虚拟机的性能不能满⾜他的要求,后来他尝试采⽤V8引擎,所以选择了 C++语⾔。
Node.js⽀持的系统包括*nux、Windows,这意味着程序员可以编写系统级或者服务器端的Javascript代码,交给 Node.js来解释执⾏。Node.js的Web开发框架Express,可以帮助程序员快速建⽴web站点,从2009年诞⽣⾄今,Node.js的成长的速度有⽬共睹,其发展前景获得了技术社区的充分肯定。
Socket.IO
Socket.IO是⼀个开源的WebSocket库,它通过Node.js实现WebSocket服务端,同时也提供客户端JS库。
Socket.IO⽀持以事件为基础的实时双向通讯,它可以⼯作在任何平台、浏览器或移动设备。
Socket.IO⽀持4种协议:WebSocket、htmlfile、xhr-polling、jsonp-polling,它会⾃动根据浏览器选择适合的通讯⽅式,从⽽让开发者可以聚焦到功能的实现⽽不是平台的兼容性,同时Soc ket.IO具有不错的稳定性和性能。
编码实现
安装Node.js
在此不做过多的说明,可以查⼀下,⽹上很多。
搭建WebSocket服务端
在项⽬根⽬录配置⼀个package.json
{
"name": "realtime-server",
"version": "0.0.1",
"description": "my first realtime server",
"dependencies": {}
}
接下来使⽤npm命令安装express和socket.io
npm install --save express
npm install --save socket.io
npm包安装完后,⼯作⽬录下⽣成了⼀个名为node_modules的⽂件夹,⾥⾯分别是express和socket.io,可能还有⼀些相关的依赖包。
先看⼀下项⽬结构:socket_io是服务端的代码,public是客户端的代码(博主在客户端编码,node_modules在服务器端,所以下列项⽬结构没有)
服务端
我们先看⼀下服务端的编码(此处需要了解⼀下express的基础)
index.js是⽀持ws通信的代码(服务端代码),监听3000端⼝(此端⼝在客户端脚本要使⽤,可以⽤ip:3000访问);app.js是搭建客户端访问⽹页的代码,监听8080端⼝index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
<('/', function(req, res){
res.send('<h1>Welcome Realtime Server</h1>');
});
//在线⽤户
var onlineUsers = {};
//当前在线⼈数
var onlineCount = 0;
<('connection', function(socket){
console.log('a user connected');
//监听新⽤户加⼊
<('login', function(obj){
//将新加⼊⽤户的唯⼀标识当作socket的名称,后⾯退出的时候会⽤到
socket.name = obj.userid;
//检查在线列表,如果不在⾥⾯就加⼊
if(!onlineUsers.hasOwnProperty(obj.userid)) {
onlineUsers[obj.userid] = obj.username;
/
/在线⼈数+1
onlineCount++;
}
//向所有客户端⼴播⽤户加⼊
console.log(obj.username+'加⼊了聊天室');
});
//监听⽤户退出
<('disconnect', function(){
//将退出的⽤户从在线列表中删除
if(onlineUsers.hasOwnProperty(socket.name)) {
/
/退出⽤户的信息
var obj = {userid:socket.name, username:onlineUsers[socket.name]};
//删除
delete onlineUsers[socket.name];
//在线⼈数-1
onlineCount--;
//向所有客户端⼴播⽤户退出
}
});
//监听⽤户发布聊天内容
<('message', function(obj){
//向所有客户端⼴播发布的消息
console.log(obj.username+'说:'+t);
});
});
http.listen(3000, function(){
websocket和socketconsole.log('listening on *:3000');
});
app.js
const express = require('express')
const path = require('path')
const app = express()
//使⽤静态资源访问,public为根⽬录
app.use(express.static(path.join(__dirname, 'public')))
app.listen(8080, () => {
console.log(`App listening at port 8080`)
})
客户端
<script src="cdn.bootcss/socket.io/2.0.4/socket.io.js"></script>
)
index.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论