关于Socket.IO

好吧,四月的第一篇学习笔记,我知道我是偷懒了,<摊手>,一些整理参考《nodejs入门经典》,仅供个人学习。

一 动态web的简史

    从历史上说,web在设计上并没有考录动态,它是围绕着文档设计的可以在一个时刻阅读单一的文档。用户从浏览器请求一个web页面,获得响应,然后浏览器显示页面——这样的循环是许多为web提供力量的技术的设计基础。随着时间的推移,开发人员更多的想法,不只是显示文档,而JavaScript就是推动web页面功能发展的中心。在20世纪90年代后期,DHTML这个术语出现了,它描述的是使用JavaScript,css和html更改页面的某些部分的能力,从而让web页面更有交互性,也就是动态性。它引入了诸如ticker,显示页面的隐藏部分以及简单的动画等内容。DHTML原本是个行为术语,它讲解的是用户与web页面交互的方法以及当交互发生时会发生什么。web标准社区后来采用DOM脚本,以可响应的方式来描述对web页面的操纵,这样当浏览器的某些插件不可用时,浏览器可以优雅的降级。

   Ajax是动态web页面的下一个巨大进步,它和DHTMl一样,描述了一组包括js,XML,html和css在内的技术。它让开发人员可以无需刷新web页面就能从服务器请求数据。这意味着可以在诸如用户单击按钮这样的特定事件发生的时候,从服务器请求新的数据。由于整个web页面无需刷新,就带来了更具有交互性,动态的体验。

   不可否认,在创建动态web页面上,ajax将继续发挥极大的作用;但在某些领域,它却极为不足。如果从服务器请求数据,Ajax可以工作的很好;但如果服务器想将数据推送到浏览器呢?Ajax技术无法很容易地将数据推送到客户端,虽然诸如Comet这样的一些技术已经让其成为了可能。使用ajax技术可以实现双向数据流,但需要跨过许多障碍才行,而且不同的浏览器工作方式也不同。

  WebSocket 是对在服务器和客户端之间实现双向实时通信问题的响应。它的思想是,从头开始,设计一个开发人员可以使用的标准以便以一致的方式创建应用程序;而不是通过复杂的,并不总能在所有浏览器中都正常工作的设置来使用现有技术完成这一任务。WebSocket的基本思想是在web服务器和浏览器之间保持连接持久打开。这就使得不管是服务器还是浏览器都可以在需要的时候推送数据。由于连接是持久的,所以数据的交换就非常快,也就成就了‘实时’这个术语。WebSocket 不支持诸如重新连接处理(reconnetion handling)或者心跳(heartbeat)这样的功能,但诸如Socket.IO这样的库提供了这些功能,同时还对某些跨浏览器的问题做了抽象。

二Socket.IO是什么?

   Socket.IO是node.js的一个模块,它是通过WebSocket进行通信的一种简单方式。WebSocket协议很复杂,从头开始斌写一个支持WebSocket的应用程序将需要花费很多时间。Socket.IO提供服务器和客户端双方的组件,所以只需一个模块就可以给应用程序加入对WebSocket的支持。Socket.IO也解决了各浏览器的支持问题(不是所有浏览器都支持WebSocket)并让实时通信可以跨几乎所有常用的浏览器实现。Socket.IO的设计非常好,将实时通信带入应用程序的过程便得非常简单。如果想做任何涉及在web服务器和浏览器之间通信的事情,那么nodejs和Socket.IO是极好的选择哦!。

三Socket.IO示例

1.新建一个文件夹,我取名叫mySocket

2.在文件夹中创建一个名为package.json的文件并加入以下内容来声明依赖模块,输入如下内容

{
    "name":"socket.io",
    "version":"0.0.1",
    "dependencies":{
        "socket.io":"0.8.7"
    }
}

3.在文件夹中再创建一个名为app.js的文件,输入如下内容

var http=require('http');
var fs=require('fs');
var sever=http.createServer(function(req,res){
	fs.readFile('./index.html',function(err,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(sever);//为了在服务器上加入Socket.IO的功能,必须将Socket.IO库包括进来,而后附加到服务器上。
io.socket.on('connection',function(socket){//在启动了服务器的Socket.io之后,用于初始化,需要一些代码来让Socket.io对特定事件作出响应,Socket.io侦听许多事件,这里只是示例
	console.log('user conneted');
	socket.on('disconnect',function(){
		console.log('user disconnet');
	});
});

 4.在文件夹中,创建一个名为index.html的文件,输入如下内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Socket.io</title>
</head>
<body>
    <h1>I Am Socket.IO</h1>
    <script src="https://cdn.bootcss.com/socket.io/1.7.3/socket.io.js"></script>
    <script>
        var socket=io.connect('http://127.0.0.1:3000');
    </script>
</body>
</html>

5.在终端运行如下命令安装依赖模块:
npm install

6.从终端运行如下命令启动服务器:

node app.js(注意是在mysocket的文件路径下运行)

7.打开浏览器访问http://127.0.0.1:3000.

8.可看到显示‘I Am socket.IO’的页面。

9.检查服务器记录在终端的日志,可以看到‘user connected’。

10.打开另一个浏览器,浏览http://127.0.0.1:3000

11.可在服务器日志上看到另一条‘ user connected’。

12.关闭浏览器。

13.在服务器日志上看到‘user disconnected’。

 

这个示例仅仅是演示了当客户端做诸如连接和断开连接这样的事情时,socket.io对特定事件的侦听。

 

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

看以下代码

io.sockets.on('connection',function(socket){
    socket.emit('message',{text:"you have connected"});//向客户端发送消息
});

注意到这个示例中,Socket.IO发送的是一个JavaScript对象,也可以使用更复杂的数据结构。
这段代码需要添加到应用程序的服务器端。只要客户端连接,它就将数据发送给每一个新的客户端,而如果想给当前所有的客户端都发送消息,则需要发送广播消息

io.sockets.on('connection',function(socket){
socket.emit('message',{text:'A new user has connected"});
socket.broadcast.emit('massage',{text:'A new user has connected'});
});

这是相似的,不同的只是消息发送给所有已连接的客户端而不仅仅是刚刚连接的客户端。注意broadcast的发送不包括自己。还有一点,示例中,消息以JavaScript对象在‘message’事件下发送。‘message’这个词可以是任何东西,但它是重要的,因为接收到数据时需要设置客户端侦听‘message’事件。不一定必须以JavaScript对象来发送数据,如果需要的话也可以发送文本,但使用JavaScript对象可以让客户端更容易使用数据。
接下来需要做的就是客户端要包含如下js以便首先连接Socket.io服务器然后侦听在''message’事件上接收的数据,然后做出响应。

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

通过使用这些功能以及客户端js,就可以创建实时的计数器来计算已启用Socket.io的服务器上所连接的客户端数量。其思想是:当服务器启动后,计数器从0开始。当客户端连接到服务器时它递增1.当客户端断开连接时,它递减1.Socket.IO的消息机制可用以实时地随着客户端连接与断开连接将服务器上客户端的数量信息更新给所有的客户端。考虑一下,这就是站点访问者的实时统计数据了!

那么开始动手吧

1 创建一个名为realtime_socket的文件夹

2.在文件夹中,创建一个名为package.json文件,并输入如下代码来声明依赖模块

{
    "name":"realtime_socket",
    "version":"0.0.1",
    "private":true,
    "dependencies":{
        "socket.io":"0.8.7"
    }
}

3.在文件夹中,创建一个名为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(err,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 conneted'+count+'users present');
    socket.emit('users',{number:count});
    socket.broadcast.emit('users',{number:count});

    socket.on('disconnect',function(){
        count--;
      console.log('user disconnected'+count+'users present');
      socket.broadcast.emit('users',{number:count});
    });
});

4.在文件夹中,创建index.html文件,并输入如下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> Realtime Socket.io</title>
</head>
<body>
    <h1>Realtime Socket.IO</h1>
    <h2> how many users are connect?</h2>
    <p id="count"></p>
     <script src="http://localhost:3000/socket.io/socket.io.js "/>
    <script>
        var socket=io.connect('http://127.0.0.1:3000');
        var count =document.getElementById('count');
        socket.on('users',function(data){ //侦听users事件
            console.log('Got update from the server');
            console.log('there are'+data.number+'users');
            count.innerHtml=data.number;
        })
    </script>
</body>
</html>

5.从终端运行如下命令安装依赖模块
npm install

6.从终端运行如下命令启动服务器

node app.js(注意是在realtime_Socket.IO的文件路径下)

7.打开浏览器浏览:http://127.0.0.1:3000。

8.可以看到一个页面,显示“Realtime Socket.IO”等等页面信息

9.打开拎一个浏览器访问:http://127.0.0.1:3000。

10.服务器更新信息,浏览器更新信息。

 五 进阶:将数据广播给客户端

    实时计数器展示了客户端数量数据如何实时往外推送给客户端。但是如果想让客户端之间做通信呢?有可能需要添加聊天功能的场合,或者有需要在客户端之间发送消息的游戏。为了让客户端可以互相通信,首先需要从客户端发送一条消息给服务器然后从服务器将消息推送给客户端。过程如下:

1客户端连接到Socket.IO Node.js服务器。

2一个客户端发送消息给服务器。

3服务器接受此消息

4.服务器将消息广播给所有其他客户端。

我们已经在上一个示例中看到,可以从Socket.IO服务器将消息广播给客户端:

socket.broadcast.emit('message',{text:' this goes to everyone'});

我们还看到,可以从服务器给单个客户端发送消息:

socket.emit('message',{text:' this goes to single client'});

从客户端发送消息给服务器代码完全相同!与实时计数器示例不同的是,消息是在客户端原发的,而且来自客户端的JavaScript。于是,在客户端上,必须要有能让用户添加消息并提交给服务器的方法。一种实现这个功能的方法是创建一个表单然后使用一些JavaScript来捕获用户输入到表单中的内容并将其发送给服务器。

好吧,原理说这么多,开始实干吧

1.创建一个名为Socket.IO node.js的文件夹

2在文件夹中创建一个名为package.json的文件,并输入如下内容:

{
    "name":"socket_nodejs",
    "version":"0.0.1",
    "private":true,
    "dependencies":{
        "socket.io":"0.8.7"
    }
}

3.在文件夹中创建一个名为app.js文件,并输入如下内容:

var http = require('http');
var fs = require('fs');


var server = http.createServer(function(req, res) {
    fs.readFile('./index.html', function(err, 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) {//侦听客户端的message事件
        socket.broadcast.emit('push message', data);
    });
});

4.在文件夹中创建一个名为index.html的文件,并输入如下内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>  Socket.io  Nodejs</title>
</head>
<body>
    <h1> Socket.IO Nodejs</h1>
    <form action="#" id="message_form">
        <textarea  id="message" cols="30" rows="10"></textarea>
        <input type="submit" value="Send message"/>
    </form>
    <!-- 将jquery和Socket.IO库包含进来 -->
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
     <script src="http://localhost:3000/socket.io/socket.io.js "/>
    <script>

        var socket=io.connect('http://127.0.0.1:3000');//指示浏览器连接位于http://127.0.0.1:3000的Socket.IO服务器
    var message=document.getElementById('message');
    $('#message_form').submit(function(){//将jquery的submit()方法加入侦听器,等候用户提交表单
        socket.emit('message',{text:message.value});//发送消息给服务器,文本区域的内容作为消息发送
        return false;//防止表单在浏览器窗口中提交。
    });
        socket.on('push message',function(data){ //侦听push message事件
            $('form').after('<p>'+data.text+'</p>');//捕捉接收的数据,写入dom
            
        });
    </script>
</body>
</html>

5.在终端输入:
npm install

6.从终端启动服务器:

node app.js(在文件夹路径下)

7.打开浏览器浏览:http://127.0.0.1:3000

8打开另一个浏览器访问:http://127.0.0.1:3000

9在文本框中输入内容并单击submit。

10在另一个浏览器中可看到消息出现

扩展:

ajax和socket.io之间有什么区别?
Socket.IO提供的功能比ajax要多得多,比如很容易就能实时地将数据推送给客户端。如果可以使用WebSocket,那么客户端和服务器之间的连接就会是持久的。而对于ajax而言,每次都需要重新连接

另外,WebSocket和ajax的服务目标不同,所以不好说使用哪个不使用哪个。ajax适合浏览器需要时不时请求数据并且数据有可能需要缓冲的场景。如果经常需要在客户端之间接收发送数据,而且有很多客户端,那么应该使用WebSocket。如果要构建一个客户端能互相通信的联网应用程序,那么WebSocket是更好的选择

推送和拉取消息之间有何不同?

推送消息意味着新的消息通过持久连接推送到客户端。这意味着客户端无需请求获得新消息。作为对比,拉取消息意味着客户端必须检查服务器上的内容,看看是否有新的消息可用。

WebSocket当前对浏览器的支持如何?

访问http://canuuse.com并输入WebSocket,就会看到WebSocket的支持情况。在移动设备上,对websocket的支持不是很好于是这就增加了使用Socket.IO的筹码了。

使用socket.io比起单纯使用websock有何优势?

如果不能使用websocket,socket.io会使用其他传输方法,来处理并不完全支持websocket的浏览器问题,(Socket.IO会尝试使用Adobe flash socket,ajax长轮询,ajax多部分流,forever iframe 或者jsonp轮询)。这就意味着无需编写更多的代码就可以让应用程序支持更多浏览器。

posted @ 2017-04-14 21:06  小爱想偷懒  阅读(4075)  评论(0编辑  收藏  举报