使用nodejs-websocket实现网页上面的即时通讯!

websocket
在没有websocket技术之前,我们想要在网页上面进行长时间的通讯聊天,一般都用的是AJAX轮循,直到现在AJAX轮循依然被很多网站广泛使用,这种传统的绑定交互模式虽然有比较良好的兼容性,但其性能问题令人堪忧,并且延时调用并不能实现真正意义上面的“即时通讯”,比如有高质量链接效率的游戏、聊天、股票等等,这种将交互频率精确于毫秒之间的是不可能通过ajax轮循实现的,本篇文章就为大家来介绍一下websocket在nodeJs下面的使用场景。
本次demo的源码:https://github.com/renjianfeng/nodejs/tree/master/gamesocket
关于nodejs-websocket
nodejs-websocketnodejs的一个框架,用于实现基于nodeJSwebsocket模块封装。
它的优点是可以利用js的事件驱动模型进行更加友好、简单的进行websocket握手链接。
关于websocket
WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。
浏览器支持情况
IE 9以上,chrome/firefox
在nodeJS环境下使用npm安装nodejs-websocket

npm install nodejs-websocket 

这个例子中,我们实现一个很简单的交互游戏;
现在有两个页面test.html和test2.html,
我们在test.html里面可以通过监听按键的w、s、a、d或方向键可以让test.html里面的方块进行上下左右的移动,同时可以在test2.html里面看到一个方块和test.html里面的方块同步移动。
别小看这些,也许这个是你开发网络游戏的关键。

首先创建服务器端代码index.js

//引入nodejs-websocket
var ws = require("nodejs-websocket");

console.log("开始建立连接...")

//game1为test.html传过来的websocket链接对象
//game2为test2.html传过来的websocket链接对象
//game1Ready game2Ready为两个页面的链接状态
var game1 = null,game2 = null , game1Ready = false , game2Ready = false;
var server = ws.createServer(function(conn){
    conn.on("text", function (str) {
        console.log("收到的信息为:"+str)
        if(str==="game1"){
            game1 = conn;
            game1Ready = true;
            conn.sendText("success");
        }
        if(str==="game2"){
            game2 = conn;
            game2Ready = true;
        }
        if(game1Ready&&game2Ready){
            //把str推送给game2
            game2.sendText(str);
        }
        conn.sendText(str)
    })
    conn.on("close", function (code, reason) {
        console.log("关闭连接")
    });
    conn.on("error", function (code, reason) {
        console.log("异常关闭")
    });
}).listen(8001,'127.0.0.1')
console.log("WebSocket建立完毕")

客户端test.html页面

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>操作端</title>
    <style>
        .value{width: 200px;height:200px;border:1px solid;text-align: center; margin-top:200px;margin-left:200px;line-height: 200px;display: block;position: absolute;}
    </style>
</head>
<body>
<div id="mess">正在连接...</div>
<div class="kuang">
    <div class="value" id="value1">盒子的位置</div>
</div>
<script>
   // !(function(){})()



    var mess = document.getElementById("mess");
    //向127.0.0.1:8001发起WebSocket请求
    var ws = new WebSocket('ws://127.0.0.1:8001');
    if(window.WebSocket){
        ws.onopen = function(e){
            console.log("连接服务器成功");
            //请求的对象名为game1
            ws.send("game1");
        }
        ws.onclose = function(e){
            console.log("服务器关闭");
        }
        ws.onerror = function(){
            console.log("连接出错");
        }
        ws.onmessage = function(e){
            mess.innerHTML = "连接成功,按住“w,s,a,d或方向键,test2.html中的div位置会跟随test.html中的位置!"
            document.onkeydown = test;
        }
    }


   var _top=200;
   var _left=200;

   var positionXY=[]
   var moveForward,moveLeft,moveBackward,moveRight
   function test(){

       //监听按键状态
       var onKeyDown = function ( event ) {

           switch ( event.keyCode ) {

               case 38: // up
               case 87: // w
                   moveForward = true;
                   break;

               case 37: // left
               case 65: // a
                   moveLeft = true; break;

               case 40: // down
               case 83: // s
                   moveBackward = true;
                   break;

               case 39: // right
               case 68: // d
                   moveRight = true;
                   break;
           }
       };

       var onKeyUp = function ( event ) {

           switch( event.keyCode ) {

               case 38: // up
               case 87: // w
                   moveForward = false;
                   break;

               case 37: // left
               case 65: // a
                   moveLeft = false;
                   break;

               case 40: // down
               case 83: // s
                   moveBackward = false;
                   break;

               case 39: // right
               case 68: // d
                   moveRight = false;
                   break;

           }

       };

       document.addEventListener( 'keydown', onKeyDown, false );
       document.addEventListener( 'keyup', onKeyUp, false );


       if(moveForward){
           //w
           _top=_top-3;
           document.getElementById("value1").style.marginTop="+"+_top+"px";
           console.log(_top)
           
           //将盒子个坐标赋值给一个数组
           positionXY=[_top,_left]
           //将当前位置的数组positionXY推送到服务器
           ws.send(positionXY);
       }
       if(moveBackward){
           //s
           _top=_top+3;
           document.getElementById("value1").style.marginTop="+"+_top+"px";
           console.log(_top)
           positionXY=[_top,_left]
           ws.send(positionXY);
       }
       if(moveLeft){
           //a
           _left=_left-3;
           document.getElementById("value1").style.marginLeft="+"+_left+"px";
           positionXY=[_top,_left]
           ws.send(positionXY);
       }
       if(moveRight){
           //d
           _left=_left+3;
           document.getElementById("value1").style.marginLeft="+"+_left+"px";
           positionXY=[_top,_left]
           ws.send(positionXY);
       }

   }
</script>
</body>
</html>

客户端test2.html页面

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>接收端</title>
    <style>
        .value{width: 200px;height:200px;border:1px solid;text-align: center; margin-top:200px;margin-left:200px;line-height: 200px;display: block;position: absolute;}
    </style>
</head>
<body>
<div id="mess">websocket练习:注意这是一个群组接收端,div的位置会被当前服务中的多人操作影响!网络不流畅时会有延迟。</div>
<div class="kuang">
    <div class="value" id="value1">盒子的位置</div>
</div>
<script>
    var mess = document.getElementById("mess");
    if(window.WebSocket){
        var ws = new WebSocket('ws://127.0.0.1:8001');
        ws.onopen = function(e){
            console.log("连接服务器成功");
            ws.send("game2");
        }
        ws.onclose = function(e){
            console.log("服务器关闭");
        }
        ws.onerror = function(){
            console.log("连接出错");
        }
        ws.onmessage = function(e){
            //获取服务器发送过来的值
            var string = e.data;
            //转化为数组
            var ss = string.split(",");
            //绑定到状态
            document.getElementById("value1").style.marginTop="+"+ss[0]+"px";
            document.getElementById("value1").style.marginLeft="+"+ss[1]+"px";
            console.log(e.data)
        }
    }
</script>
</body>
</html>

运行 index.js

然后分别在两个窗口打开test.html和test2.html 如果链接成功则会有下面的效果
test.html中的方块按w、a、s、d或方向键会有移动效果,同时test2.html中的方块会跟随其移动。同时nodejs的控制台会输出方块的坐标

Top