Node.js Websocket Socket.io的介绍和使用

 

Websocket是什么?

websockets是web和移动应用程序中一种新的通信方式,这个协议最终在2011年由IETF标准化,为广泛使用铺平了道路。

这个新协议为客户机打开了一条更快、更有效的通信线路。和HTTP一样,websockets在TCP连接上运行,但是速度要快得多,因为我们不必每次发送消息时都打开一个新连接,因为只要服务器或客户端需要,连接就会一直保持活动状态。

更好的是,由于连接永远不会终止,我们终于可以使用全双工通信,这意味着我们可以将数据推送到客户机,而不必等待客户机从服务器请求数据。这使得数据可以来回通信,这对于实时聊天应用程序甚至游戏来说都是非常理想的。

Node.js Websocket Socket.io的介绍和使用 - 豆豆网

 

Node.js Websocket Socket.io的介绍和使用

Websockets是如何工作的?

websocket核心只是一个TCP连接,它支持全双工通信,这意味在同一时间连接的任何一方都可以向另一方发送数据。

为了建立这个连接,协议实际上将握手作为一个普通的HTTP请求发起,但随后使用升级请求HTTP头进行“upgrade request”,如下所示:

GET /ws/chat HTTP/1.1  
Host: chat.example.com  
Upgrade: websocket  
Connection: Upgrade  
Sec-WebSocket-Key: q1PZLMeDL4EwLkw4GGhADm==  
Sec-WebSocket-Protocol: chat, superchat  
Sec-WebSocket-Version: 15  
Origin: http://example.com

然后服务器返回一个HTTP 101“Switching Protocols交换协议)响应,确认连接将被升级。一旦建立了这个连接,它就切换到双向二进制协议,此时就可以发送应用程序数据了

所有的协议所要做的就是保持连接的打开,发送一些ping/pong数据包,这告诉彼此连接在线。要关闭连接,发送一个简单的“close connection关闭连接)包

 

Websocket示例

许多不同Node.js的websocket节点库对于我们是可用的,本篇介绍 socket.io 的使用,因为它目前似乎是最流行的,而且是最容易使用的。虽然每个库都有自己独特的API,但是它们也有许多相似之处,因为它们都构建在相同的协议之上,所以可以的话你能够将下面的代码转换为想要使用的任何库

对于HTTP服务器,我将使用Express,这是最流行的Node服务器。可以只使用普通的http模块,如果你不需要Express的所有模块的话

 

建立连接

为了在客户端和服务器之间建立连接,服务器必须做两件事:

  1. 连接到HTTP服务器来处理websocket连接
  2. socket.io.js客户端库作为静态资源提供

在下面的代码中,你可以在第三行看到上面的第1项被完成。在路径/socket.io/socket.io.js上由socket.io库完成(默认情况下)第2项。默认情况下,所有websocket连接和资源都在/socket.io路径中提供

服务器端

var app = require('express')();  
var server = require('http').Server(app);  
var io = require('socket.io')(server);

app.get('/', function(req, res) {  
    res.sendFile(__dirname + '/index.html');
});

server.listen(8080);

客户还需要做两件事:

  1. 从服务器加载库
  2. 调用.connect()到服务器地址和websocket路径

客户端

<script src="/socket.io/socket.io.js"></script>  
<script>  
    var socket = io.connect('/');
</script>

如果将浏览器导航到http://localhost:8080并使用浏览器的开发人员工具在后台检查HTTP请求,应该能够看到正在执行的握手(会话),包括GET请求和由此产生的HTTP 101交换协议响应

 

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

下面是展示从服务器端向客户端发送数据的最常见方式。在这种情况下,我们将向一个通道发送消息,该通道可以被客户端订阅和接收。例如,客户端应用程序可能正在监听“announcements”通道,该通道将包含关于系统范围内事件的通知,例如用户加入聊天室时的通知

在服务器上,这是通过等待建立新连接来完成的,然后调用socket.emit()方法向所有连接的客户机发送消息

服务器端

io.on('connection', function(socket) {  
    socket.emit('announcements', { message: '一个新用户加入!' });
});

客户端

<script src="/socket.io/socket.io.js"></script>  
<script>  
    var socket = io.connect('/');
    socket.on('announcements', function(data) {
        console.log('Got announcement:', data.message);
    });
</script>

 

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

它与上一个示例非常相似,使用socket.emit()和socket.on()方法

服务器端

io.on('connection', function(socket) {  
    socket.on('event', function(data) {
        console.log('一个客户端给我们发送了一些信息:', data.message);
    });
});

客户端

<script src="/socket.io/socket.io.js"></script>  
<script>  
    var socket = io.connect('/');
    socket.emit('event', { message: '我有个重要事情!' });
</script>

 

计算连接用户数

这是一个好的示例因为它展示了socket.io的更多特性(比如disconnect事件),它易于实现,并且适用于许多web应用程序。我们将使用connection和disconnect事件来计算站点上活动用户的数量,并使用当前的数量更新所有用户

服务器端

var numClients = 0;

io.on('connection', function(socket) {  
    numClients++;
    io.emit('stats', { numClients: numClients });

    console.log('已连接客户端:', numClients);

    socket.on('disconnect', function() {
        numClients--;
        io.emit('stats', { numClients: numClients });

        console.log('已连接客户端:', numClients);
    });
});

客户端

<script src="/socket.io/socket.io.js"></script>  
<script>  
    var socket = io.connect('/');
    socket.on('stats', function(data) {
        console.log('已连接客户端:', data.numClients);
    });
</script>

跟踪服务器上的用户数量的一种简单得多的方法是:

var numClients = io.sockets.clients().length;

但很明显,这方面存在一些问题,因此你可能需要自己跟踪客户的数量

 

Rooms 和 Namespaces

随着应用程序变得越来越复杂,你可能需要使用websockets进行更多的定制,比如向特定的用户或一组用户发送消息。或者你需要在应用程序的不同部分之间严格分离逻辑。这就是用Rooms 和 Namespaces的地方

注意:这些特性不是websocket协议的一部分,而是由socket.io添加的

默认情况下,socket.io使用根名称空间(/)发送和接收数据。通过编程,你可以通过io.sockets访问这个命名空间,尽管它的许多方法在io上都有快捷方式。所以这两个调用是等价的:

io.sockets.emit('stats', { data: '一些数据' });  
io.emit('stats', { data: '一些数据' });

要创建自己的名称空间,只需执行以下操作:

var iosa = io.of('/stackabuse');  
iosa.on('connection', function(socket){  
    console.log('连接到stackabuse名称空间'):
});
iosa.emit('stats', { data: '一些数据' });

此外,客户端必须显式连接到你的命名空间:

<script src="/socket.io/socket.io.js"></script>  
<script>  
    var socket = io('/stackabuse');
</script>

现在,无论使用哪个通道,在这个名称空间中发送的任何数据都将与默认/名称空间分离

更进一步,在每个名称空间中,您可以加入和离开“rooms”。这些房间在名称空间之上提供了另一层分隔,而且由于客户端只能添加到服务器端的房间中,因此它们还提供了一些额外的安全性。因此,如果你想确保用户不会窥探某些数据,可以使用一个room来隐藏它

要添加到房间中,您必须调用.join():

io.on('connection', function(socket){  
    socket.join('private-message-room');
});

然后,你可以发送信息给每个属于给定房间的人:

io.to('private-message-room').emit('some event');

最后,调用.leave()停止从房间获取事件消息:

socket.leave('private-message-room');

 

结论

这只是实现websockets协议的一个库,还有很多其他库,它们都有自己独特的特性和优势。

我建议你尝试一下其他的一些(比如 node-websockets),这样就会对其中的内容有所了解

在短短几行代码中,就可以创建一些非常强大的应用程序~

 

转载请注明出处豆豆网

欢迎分享至:

版权声明:原创文章自由转载-非商用-非衍生-保持署名及文章出处(创意共享3.0许可证
转载说明:转载请注明出处豆豆网
部分文章选自网络(文首、末未标明豆豆网的均来自网络),我们对文中观点保持中立,本站涉及软件下载,仅供参考学习、交流之目的,涉及版权请告知删除,邮箱地址:豆豆网博客


发表评论

电子邮件地址不会被公开。 必填项已用*标注