nodejs结合Socket.IO实现的即时通讯功能详解


Posted in NodeJs onJanuary 12, 2018

本文实例讲述了nodejs结合Socket.IO实现的即时通讯功能。分享给大家供大家参考,具体如下:

动态web

在html5以前,web的设计上并没有考虑过动态,他一直是围绕着文档设计的,我们看以前比较老的网站,基本上都是某一刻用来显示单一的文档的,用户请求一次web页面,获取一个页面,但是随着时间的推移,人们想要web做更多的事情了,而不是简单的要显示文档,而javaScript一直处于开发人员推动web页面功能的发展中心。

Ajax无疑是动态Web页面的一个重大发展,他不再需要我们即使更新一点内容,也需要刷新整个页面了,但是有些方面,又体现了他的不足。如果从服务器请求数据,他固然号,但是如果服务器想要将数据推送到浏览器呢。Ajax技术无法很容易的支持将数据推送到客户,虽然可以,但是需要跨国很多的障碍才行,而且不同的浏览器工作方式也不同,例如IE和FireBox他们的内核就不一样,从而工作方式也不一样。

WebSocket是在对服务器和客户端之间实现双向通信问题的相应。他的思想是,从头开始,设计一个开发人员可以使用的标准以便以一直的方式创建应用程序,而不是通过复杂的,并不总能设置所有浏览器的工作。他的思想是Web服务器和浏览器之间保持持久打开,这就使得不管是服务器还是浏览器都可以在想要的时候推送数据。因为连接是持久的,所以数据的交换非常的快,也就成了实时的了。

Socket.IO

说了那么多,我们介绍一下正主,Socket.IO是Node.js的一个模块,他提供通过WebSocket进行通信的一种简单方式,WebSocket协议很复杂,但是Socket.IO提供了服务器和客户端双方的组件,所以只需要一个模块就可以给应用程序加入对WebSocket的支持。而且还能支持不同的浏览器。

基础的Socket.IO

Socket.IO既能在服务端也能在客户端工作,要使用它,必须将其添加到服务器端的JavaScript(Node.js)和客户端的JavaScript(JQuery)中,这是以为内通信通常是双向的,所以Sokcet.IO需要能在两边工作。

var server = http.createServer(function (req,res){
  fs.readFile('./index.html',function(error,data){
    res.writeHead(200,{'Content-Type':'text/html'});
    res.end(data,'utf-8');
  });
}).listen(3000,"127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

而且必须将Socket.IO库包含起来,才能加入Socket.IO的功能。

var io = require('socket.io').listen(server);

然后加入一个事件来响应客户端到底是连接了,还是断开了。事件如下:

io.sockets.on('connection',function(socket){
  console.log('User connected');
  socket.on('disconnect',function(){
    console.log('User disconnected');
  });
});

是不是觉得非常的简单,下面我们看一下完整的代码实现是如何实现的吧:

简单Socket.IO应用

新建app.js

新建文件夹socket.io,在该文件夹下新建app.js,写如下代码:

var http = require('http');
var fs = require('fs');
var server = http.createServer(function (req,res){
  fs.readFile('./index.html',function(error,data){
    res.writeHead(200,{'Content-Type':'text/html'});
    res.end(data,'utf-8');
  });
}).listen(3000,"127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');
var io = require('socket.io').listen(server);
io.sockets.on('connection',function(socket){
  console.log('User connected');
  socket.on('disconnect',function(){
    console.log('User disconnected');
  });
});

新建index.html

新建index.html文件,代码如下:

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>Socket.IO Example</title>
 </head>
 <body>
  <h1>Socket.IO Example</h1>
  <script src="/socket.io/socket.io.js"></script>
  <script>
   var socket = io.connect('http://127.0.0.1:3000');
  </script>
 </body>
</html>

新建package.json

新建package.json来引入模块。

{
  "name":"socketio_example",
  "version":"4.13.2",
  "private":true,
  "dependencies":{
    "socket.io":"1.4.5"
  }
}

版本号大家可以输入自己的nodejs -V,或者socket.io -v来查看自己的版本号。

运行

如果大家没有安装Socket.IO,可以运行如下代码,如果安装了,自动跳过这一步。

npm install socket.io

从终端运行如下命令安装模块

npm install

运行如下命令启动服务器

node app.js

打开浏览器,输入http://127.0.0.1:3000/,多打开几个页签,都输入该网址,再任意关闭一个页签,然后看看我们的cmd命令窗口是不是如下:

nodejs结合Socket.IO实现的即时通讯功能详解

这里会详细的记录又多少个用于连接了,也有多少个用户断开连接了,这样就能统计我们网页的访问量了。

从服务器发送数据到客户端

上边的实例我们已经实现了连接或者断开服务器做记录了,但是我们要是想要推送消息怎么办,例如我们好友的QQ上线了,腾讯都会咳嗽一下来提醒我们有好友上线。下面我们来做一下这个功能功能。

发送给单个用户

io.sockets.on('connection',function(socket){
    socket.emit('message',{text:'你上线了'});
});

发给所有用户

io.sockets.on('connection',function(socket){
    socket.broadcast.emit('message',{'你的好某XXX上线了'});
});

无论是发送给单个用户还是所有用户,这个message是自己写的,但是要在客户端用,所以命名要注意。

客户端

在客户端我们可以添加侦听事件来接收数据。

var socket = io.connect('http://127.0.0.1:3000');
socket.on('message',function(data){
  alert(data.text);
})

通过这些功能,我们就在第一个例子的基础上,实现用户数量的统计。这里只需要在服务端设置一个变量,count,如果有一个上线,那么就数量+1,并通知所有用户,最新的在线人数。

新建app.js

var http = require('http');
var fs = require('fs');
var count = 0;
var server = http.createServer(function (req,res){
  fs.readFile('./index.html',function(error,data){
    res.writeHead(200,{'Content-Type':'text/html'});
    res.end(data,'utf-8');
  });
}).listen(3000,"127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');
var io = require('socket.io').listen(server);
io.sockets.on('connection',function(socket){
  count++;
  console.log('User connected' + count + 'user(s) present');
  socket.emit('users',{number:count});
  socket.broadcast.emit('users',{number:count});
  socket.on('disconnect',function(){
    count--;
    console.log('User disconnected');
    socket.broadcast.emit('users',{number:count});
  });
});

创建index.html文件

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>Socket.IO Example</title>
 </head>
 <body>
  <h1>Socket.IO Example</h1>
  <h2>How many users are here?</h2>
  <p id="count"></p>
   <script src="http://***.***.**.***:9001/jquery.min.js"></script>
  <script src="/socket.io/socket.io.js"></script>
  <script>
   var socket = io.connect('http://127.0.0.1:3000');
   var count = document.getElementById('count');
   socket.on('users',function(data){
    console.log('Got update from the server');
    console.log('There are ' + data.number + 'users');
    count.innerHTML = data.number
   });
  </script>
 </body>
</html>

创建package.json文件

{
  "name":"socketio_example",
  "version":"4.13.2",
  "private":true,
  "dependencies":{
    "socket.io":"1.4.5"
  }
}

安装模块npm install

启动服务器node app.js

打开浏览器,输入http://127.0.0.1:3000,可以看到如下图片:

nodejs结合Socket.IO实现的即时通讯功能详解

再打开一个连接http://127.0.0.1:3000,可以看到如下结果:

nodejs结合Socket.IO实现的即时通讯功能详解

可以看到如果我们打开两个连接,那么两个页签都会显示当前又两个用户在线,如果关闭其中一个,我们可以看到又显示只有一个用户在线。

将数据广播给客户端

接下来我们来看看Socket.IO是如何实现客户端与客户端的通信呢。
要想实现该功能,首先需要客户端将消息发送到服务端,·然后服务端发送给除自己之外的其他客户。服务器将消息发送给客户端的方法在上一个例子中我们已经实现了,那么我们需要的是客户端把接收到的消息发送给服务器。

下边的代码思想是利用表单来实现的。

<form id="message-form" action="#">
   <textarea id="message" rows="4" cols="30"></textarea>
   <input type="submit" value="Send message" />
</form>
<script src="http://***.***.***.**:9001/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
   var socket = io.connect('http://127.0.0.1:3000');
   var message = document.getElementById('message');
   $(message.form).submit(function() {
    socket.emit('message', { text: message.value });
    return false;
   });
   socket.on('push message', function (data) {
    $('form').after('<p>' + data.text + '</p>');
   });
</script>

实现的思想是,将JQuery和SocketIO库包含进来,只是浏览器拦截127.0.0.1:3000的服务,使用Jquery的submit方法加入侦听期,等候用户提交表单。

发送消息给Socket>IO服务器,文本区域的内容位消息发送。

添加return false ,防止表单在浏览器窗口提交。

在上边已经说过服务器如何广播消息,下边我们说一下客户端如何显示客户端发送的消息。

socket.on('push message', function (data) {
  $('form').after('<p>' + data.text + '</p>');
})

实例实现

创建messaging的新文件夹

在文件夹下创建package.json文件,代码如下:

{
  "name":"socketio_example",
  "version":"4.13.2",
  "private":true,
  "dependencies":{
    "socket.io":"1.4.5"
  }
}

创建app.js文件,代码如下:

var http = require('http');
var fs = require('fs');
var server = http.createServer(function (req,res){
  fs.readFile('./index.html',function(error,data){
    res.writeHead(200,{'Content-Type':'text/html'});
    res.end(data,'utf-8');
  });
}).listen(3000,"127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');
var io = require('socket.io').listen(server);
io.sockets.on('connection',function(socket){
  socket.on('message',function(data){
    socket.broadcast.emit('push message',data);
  });
});

创建index.html

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="utf-8" />
  <title>Socket.IO Example</title>
 </head>
 <body>
  <h1>Socket.IO Example</h1>
  <form id="message-form" action="#">
   <textarea id="message" rows="4" cols="30"></textarea>
   <input type="submit" value="Send message" />
  </form>
  <script src="http://222.222.124.77:9001/jquery.min.js"></script>
  <script src="/socket.io/socket.io.js"></script>
  <script>
   var socket = io.connect('http://127.0.0.1:3000');
   var message = document.getElementById('message');
   $(message.form).submit(function() {
    socket.emit('message', { text: message.value });
    return false;
   });
   socket.on('push message', function (data) {
    $('form').after('<p>' + data.text + '</p>');
   });
  </script>
 </body>
</html>

加载模块npm install

启动服务器node app.js

然后打开浏览器的多个页签,都输入http://127.0.0.1:3000

可以看到我们再任何一个窗口输入内容,都会在其他的页面显示我们输入的内容,效果如下:

nodejs结合Socket.IO实现的即时通讯功能详解

nodejs结合Socket.IO实现的即时通讯功能详解

小结

这篇博客好长,其实说了这么多,还是有很多的东西没有说,但是我们还是讨论了Socket.IO如何实现动态的,通过服务端能显示用户的连接,和统计链接次数统计,到最后的消息的通知和聊天功能的实现。在我们的生活中这种例子比比解释,例如QQ,例如淘宝的抢购,都是可以通过这种方式实现的,这样我们就能实时的实现动态的功能了。尤其是12306这个网站,我得和他们说说了,哈哈。

希望本文所述对大家nodejs程序设计有所帮助。

NodeJs 相关文章推荐
nodejs教程 安装express及配置app.js文件的详细步骤
May 11 NodeJs
nodejs npm包管理的配置方法及常用命令介绍
Jun 05 NodeJs
Nodejs极简入门教程(三):进程
Oct 27 NodeJs
nodejs 中模拟实现 emmiter 自定义事件
Feb 22 NodeJs
Nodejs抓取html页面内容(推荐)
Aug 11 NodeJs
实例分析nodejs模块xml2js解析xml过程中遇到的坑
Mar 18 NodeJs
NodeJs通过async/await处理异步的方法
Oct 09 NodeJs
nodejs结合Socket.IO实现的即时通讯功能详解
Jan 12 NodeJs
nodeJs爬虫的技术点总结
May 13 NodeJs
NodeJS加密解密及node-rsa加密解密用法详解
Oct 12 NodeJs
用Electron写个带界面的nodejs爬虫的实现方法
Jan 29 NodeJs
如何利用nodejs实现命令行游戏
Nov 24 NodeJs
nodejs基于WS模块实现WebSocket聊天功能的方法
Jan 12 #NodeJs
nodejs使用http模块发送get与post请求的方法示例
Jan 08 #NodeJs
nodejs基于mssql模块连接sqlserver数据库的简单封装操作示例
Jan 05 #NodeJs
Nodejs连接mysql并实现增、删、改、查操作的方法详解
Jan 04 #NodeJs
nodejs简单实现TCP服务器端和客户端的聊天功能示例
Jan 04 #NodeJs
详解NODEJS的http实现
Jan 04 #NodeJs
Nodejs中crypto模块的安全知识讲解
Jan 03 #NodeJs
You might like
解决dede生成静态页和动态页转换的一些问题,及火车采集入库生成动态的办法
2007/03/29 PHP
php下使用SimpleXML 处理XML 文件
2010/02/27 PHP
for循环连续求和、九九乘法表代码
2012/02/20 PHP
深入理解PHP之数组(遍历顺序)  Laruence原创
2012/06/13 PHP
PHP数组无限分级数据的层级化处理代码
2012/12/29 PHP
Laravel5中contracts详解
2015/03/02 PHP
PHP数组操作类实例
2015/07/11 PHP
thinkPHP使用post方式查询时分页失效的解决方法
2015/12/09 PHP
必须收藏的23个php实用代码片段
2016/02/02 PHP
密码强度检测效果实现原理与代码
2013/01/04 Javascript
js数组Array sort方法使用深入分析
2013/02/21 Javascript
高效率JavaScript编写技巧整理
2013/08/23 Javascript
jquery实现弹出层完美居中效果
2014/03/03 Javascript
js中document.write使用过程中的一点疑问解答
2014/03/20 Javascript
Javascript学习笔记之相等符号与严格相等符号
2014/11/23 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
2015/06/01 Javascript
JS去掉字符串中所有的逗号
2017/10/18 Javascript
利用Node.js检测端口是否被占用的方法
2017/12/07 Javascript
Vue组件库发布到npm详解
2018/02/17 Javascript
Babel 入门教程学习笔记
2018/06/13 Javascript
详解nuxt路由鉴权(express模板)
2018/11/21 Javascript
一篇文章带你从零快速上手Rollup
2020/09/07 Javascript
[01:24]DOTA2上海特锦赛OG战队抵达 专车接机入驻总统套房
2016/02/23 DOTA
[41:56]Spirit vs Liquid Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
[01:09:01]完美世界DOTA2联赛循环赛 Magma vs PXG BO2第一场 10.28
2020/10/28 DOTA
python字典多条件排序方法实例
2014/06/30 Python
教大家玩转Python字符串处理的七种技巧
2017/03/31 Python
python中requests库session对象的妙用详解
2017/10/30 Python
Python实现的用户登录系统功能示例
2018/02/05 Python
在python中画正态分布图像的实例
2019/07/08 Python
opencv 实现特定颜色线条提取与定位操作
2020/06/02 Python
澳大利亚便宜隐形眼镜购买网站:QUICKLENS Australia
2018/10/06 全球购物
科级干部群众路线教育实践活动对照检查材料思想汇报
2014/09/20 职场文书
建筑横幅标语
2014/10/09 职场文书
四年级作文之植物
2019/09/20 职场文书
浅谈redis的过期时间设置和过期删除机制
2022/03/18 MySQL