zoukankan      html  css  js  c++  java
  • 160429、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/');
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

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

    io.sockets.on('connection',function(socket){
        console.log('User connected');
        socket.on('disconnect',function(){
            console.log('User disconnected');
        });
    });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

    简单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');
        });
    });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    新建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>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    新建package.json

    新建package.json来引入模块。

    {
        "name":"socketio_example",
        "version":"4.13.2",
        "private":true,
        "dependencies":{
            "socket.io":"1.4.5"
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    运行

    如果大家没有安装Socket.IO,可以运行如下代码,如果安装了,自动跳过这一步。 
    npm install socket.io 
    从终端运行如下命令安装模块 
    npm install 
    运行如下命令启动服务器 
    node app.js 
    打开浏览器,输入http://127.0.0.1:3000/,多打开几个页签,都输入该网址,再任意关闭一个页签,然后看看我们的cmd命令窗口是不是如下: 
    这里写图片描述 
    这里会详细的记录又多少个用于连接了,也有多少个用户断开连接了,这样就能统计我们网页的访问量了。

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

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

    发送给单个用户

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

    发给所有用户

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

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

    客户端

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

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

    通过这些功能,我们就在第一个例子的基础上,实现用户数量的统计。这里只需要在服务端设置一个变量,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});  
        });
    });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    创建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>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    创建package.json文件

    {
        "name":"socketio_example",
        "version":"4.13.2",
        "private":true,
        "dependencies":{
            "socket.io":"1.4.5"
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    安装模块npm install 
    启动服务器node app.js 
    打开浏览器,输入http://127.0.0.1:3000,可以看到如下图片: 
    一个用户连接 
    再打开一个连接http://127.0.0.1:3000,可以看到如下结果: 
    第二个连接 
    可以看到如果我们打开两个连接,那么两个页签都会显示当前又两个用户在线,如果关闭其中一个,我们可以看到又显示只有一个用户在线。

    将数据广播给客户端

    接下来我们来看看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>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    实现的思想是,将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>');
          })
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    实例实现

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

    {
        "name":"socketio_example",
        "version":"4.13.2",
        "private":true,
        "dependencies":{
            "socket.io":"1.4.5"
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    创建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);
    
        });
    });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    创建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 
    可以看到我们再任何一个窗口输入内容,都会在其他的页面显示我们输入的内容,效果如下: 
    这里写图片描述 
    这里写图片描述

    小结

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

  • 相关阅读:
    关于下下载typora的相关说明
    Vue项目vscode 安装eslint插件的方法(代码自动修复)
    [0].Net开发者社区--您好大的官威啊!
    关于hadoop安装后无法访问web界面查看查看 NameNode 和 Datanode 信息
    C#(winform)记录阻止关闭页面方法
    Android开发:记录Cannot resolve symbol'R'问题解决记录
    C#Winform开发杂项记录
    C#Winform 使用NPOI导入、导出Excel
    C#记录一些用到的比对方法
    C#(Winform开发)Excel导出
  • 原文地址:https://www.cnblogs.com/zrbfree/p/5445783.html
Copyright © 2011-2022 走看看