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 URL模块操作URL相关方法介绍
Mar 03 NodeJs
详解nodejs 文本操作模块-fs模块(二)
Dec 22 NodeJs
Express与NodeJs创建服务器的两种方法
Feb 06 NodeJs
nodejs+express实现文件上传下载管理网站
Mar 15 NodeJs
Nodejs读取文件时相对路径的正确写法(使用fs模块)
Apr 27 NodeJs
详解nodejs通过响应回写的方式渲染页面资源
Apr 07 NodeJs
Nodejs中的JWT和Session的使用
Aug 21 NodeJs
nodejs中express入门和基础知识点学习
Sep 13 NodeJs
NodeJS服务器实现gzip压缩的示例代码
Oct 12 NodeJs
NodeJs 模仿SIP话机注册的方法
Jun 21 NodeJs
nodejs使用socket5进行代理请求的实现
Feb 21 NodeJs
浅谈JS和Nodejs中的事件驱动
May 05 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
php中使用addslashes函数报错问题的解决方法
2013/02/06 PHP
使用PHP生成二维码的两种方法(带logo图像)
2014/03/14 PHP
Thinkphp实现自动验证和自动完成
2015/12/19 PHP
jquery学习笔记二 实现可编辑的表格
2010/04/09 Javascript
JS面向对象编程 for Cookie
2010/09/19 Javascript
jQuery下通过$.browser来判断浏览器.
2011/04/05 Javascript
JS预览图像将本地图片显示到浏览器上
2013/08/25 Javascript
JS操作数据库的实例代码
2013/10/17 Javascript
jquery ui resize 中border-box的bug修正
2015/04/26 Javascript
JavaScript添加随滚动条滚动窗体的方法
2016/02/23 Javascript
JS组件Bootstrap dropdown组件扩展hover事件
2016/04/17 Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
2016/12/08 Javascript
React创建组件的三种方式及其区别
2017/01/12 Javascript
JS简单验证上传文件类型的方法
2017/04/17 Javascript
Angular.Js中ng-include指令的使用与实现
2017/05/07 Javascript
VUE 更好的 ajax 上传处理 axios.js实现代码
2017/05/10 Javascript
vue中element-ui表格缩略图悬浮放大功能的实例代码
2018/06/26 Javascript
Element-ui自定义table表头、修改列标题样式、添加tooltip、:render-header使用
2019/04/11 Javascript
[02:32]DOTA2亚洲邀请赛 VG战队巡礼
2015/02/03 DOTA
python实现从字符串中找出字符1的位置以及个数的方法
2014/08/25 Python
黑科技 Python脚本帮你找出微信上删除你好友的人
2016/01/07 Python
Python-嵌套列表list的全面解析
2016/06/08 Python
Python常见格式化字符串方法小结【百分号与format方法】
2016/09/18 Python
使用python的pexpect模块,实现远程免密登录的示例
2019/02/14 Python
关于Python形参打包与解包小技巧分享
2019/08/24 Python
使用pandas的box_plot去除异常值
2019/12/10 Python
Python3 ID3决策树判断申请贷款是否成功的实现代码
2020/05/21 Python
python FTP编程基础入门
2021/02/27 Python
Guess美国官网:美国知名服装品牌
2019/04/08 全球购物
中专生学习生活的自我评价分享
2013/10/27 职场文书
优秀教师事迹简介
2014/02/02 职场文书
入党积极分子批评与自我批评思想汇报
2014/09/14 职场文书
装修公司工程部经理岗位职责
2015/04/09 职场文书
教师读书笔记
2015/06/29 职场文书
《中彩那天》教学反思
2016/02/24 职场文书
怎样评估创业计划书是否有可行性?
2019/08/07 职场文书