基于Node.js的WebSocket通信

Websocket简介[维基百科]

WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection. The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011, and the WebSocket API in Web IDL is being standardized by the W3C.

node的依赖包

node中实现Websocket的依赖包有很多,websocket、ws均可,本文选取ws来实现,首先安装依赖

npm install ws

聊天室实例

假如A,B,C,D用户均通过客户端连接到Websocket服务,其中每个人发的消息都需要将其通过Websocket转发给其他人,此场景类似于服务端将A的消息广播给组内其他用户。

服务端实现

首先来看服务端程序,具体的工作流程分以下几步:

  1. 创建一个WebSocketServer的服务,同时监听8080端口的连接请求。
  2. 每当有新的客户端连接该WebSocket成功时,便将该连接push到连接池的数组中。
  3. 监听message事件,当该事件发生时,遍历连接池,以连接为单位将该消息转发到对应的客户端
  4. 监听close事件,当该事件发生时,将该连接移出连接池
# 服务端代码
var WebSocketServer = require('ws').Server,
    wss = new WebSocketServer({port: 8080});

// 连接池
var clients = [];

wss.on('connection', function(ws) {
    // 将该连接加入连接池
    clients.push(ws);
    ws.on('message', function(message) {
        // 广播消息
        clients.forEach(function(ws1){
            if(ws1 !== ws) {
                ws1.send(message);
            }
       })
    });

    ws.on('close', function(message) {
        // 连接关闭时,将其移出连接池
        clients = clients.filter(function(ws1){
            return ws1 !== ws
        })
    });
});

客户端实现

<html>
<input type="text" id="text">
<input type="button" onclick="sendMessage()" value="online">
<script>
    var ws = new WebSocket("ws://localhost:8080");

    ws.onopen = function (e) {
        console.log('Connection to server opened');
    }
    ws.onmessage = function(event) { 
        console.log('Client received a message', event); 
    }; 
    ws.onclose = function (e) {
        console.log('connection closed.');
    }
    function sendMessage() {
        ws.send(document.getElementById('text').value);
    }
</script>
</html>

如何发现用户?

通过上述的demo可以看到,WebSocket都是基于连接的,也就是说我们知道data是从那个connection发过来,但并不知道使用客户端的是李雷或者韩梅梅,这可如何是好?再想另一种场景,李雷只想给韩梅梅发消息,不想将消息广播给其他客户端,此时我们就需要在Server端能够标识用户身份和连接的对应关系。

于是,需要在客户端连接到WebSocket之后,紧接着再发一次请求,告诉Server我的user_id是多少,Server将此user_id与connection之间的关系存储在hashmap中,至此就建立了user_id与connection的对应关系。当需要发送消息给对应的客户端,从此hashmap中取出对应用户的connection信息,调用其send方法发出消息即可。

依赖包
npm install hashmap

服务端实现

var WebSocketServer = require('ws').Server, webSocketServer = new WebSocketServer({port: 8080});
var HashMap = require('hashmap');

// record the client
var userConnectionMap = new HashMap();
var connectNum = 0;

// connection
webSocketServer.on('connection', function(ws) {
    ++ connectNum;
    console.log('A client has connected. current connect num is : ' + connectNum);
    ws.on('message', function(message) {
        var objMessage = JSON.parse(message);
        var strType  = objMessage['type'];

        switch(strType) {
            case 'online' : 
                userConnectionMap.set(objMessage['from'], ws);
                break;
            default:
                var targetConnection = userConnectionMap.get(objMessage['to']);
                if (targetConnection) {
                    targetConnection.send(message);
                }
        }
    });

    ws.on('close', function(message) {
        var objMessage = JSON.parse(message);
        userConnectionMap.remove(objMessage['from']);
    });
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,234评论 19 139
  • 初涉IM,首先我有这么几个问题需要弄明白: Socket 和 WebSocket 有哪些区别和联系? WebSoc...
    夜幕青雨阅读 11,277评论 8 39
  • 昨天把2天的课程, 培训完之后, 早上花了两个小时做了一个全新的ppt, 用了这个方案之后, 立马传给好几个老总看...
    lilinjuan阅读 226评论 0 1
  • 这条路,从未来过。 走过了,才知道,它不是我想象中那么艰险、难走,但也不是其他人口中的那么轻松、易行..........
    文晓玲阅读 299评论 6 8
  • 希望 东方风格地方郭德纲的郭德纲到底是干啥地方郭德纲 这件事让我想起了苏格拉底的一句话 地方 发给他二哥哥哥个人个...
    王颖_b729阅读 196评论 1 0