`
biyeah
  • 浏览: 204838 次
  • 来自: ...
社区版块
存档分类
最新评论

nowjs和nodejs实现服务器端与客户端实时数据传输的例子

阅读更多
参考:http://www.bennadel.com/blog/2171-Realtime-Messaging-And-Synchronization-With-NowJS-And-Node-js.htm

    先说例子实现的功能。网页上有一图片,图片可以拖动。用浏览器打开多个同一网页,当图片移动时,其它页面的图片会同步移动。例子也展示了用jQuery实现图片的拖动。
测试环境window7,nodejs v0.6.5 分别用ie,firefox,chrome打开http://127.0.0.1:8080/client.html,所有该网页上的图片会同步移动。贴上代码。
server.js端:
需要用sock.io和nowjs第三包,推荐用npm方式安装。nowjs包在window的安装可参考:
http://blog.nowjs.com/running-nowjs-natively-on-windows
// Include the necessary modules.
var sys = require("util");
var http = require("http");
var url = require("url");
var path = require("path");
var fileSystem = require("fs");


// ---------------------------------------------------------- //
// ---------------------------------------------------------- //


// Create an instance of the HTTP server.
var server = http.createServer(
    function (request, response) {

// Get the requested "script_name". This is the part of the
// path after the server_name.
        var scriptName = request.url;

// Convert the script name (expand-path) to a physical file
// on the local file system.
        var requestdFilePath = path.join(process.cwd(), scriptName);

// Read in the requested file. Remember, since all File I/O
// (input and output) is asynchronous in Node.js, we need to
// ask for the file to be read and then provide a callback
// for when that file data is available.
//
// NOTE: You can check to see if the file exists *before* you
// try to read it; but for our demo purposes, I don't see an
// immediate benefit since the readFile() method provides an
// error object.
        fileSystem.readFile(
            requestdFilePath,
            "binary",
            function (error, fileBinary) {

// Check to see if there was a problem reading the
// file. If so, we'll **assume** it is a 404 error.
                if (error) {

// Send the file not found header.
                    response.writeHead(404);

// Close the response.
                    response.end();

// Return out of this guard statement.
                    return;

                }

// If we made it this far then the file was read in
// without a problem. Set a 200 status response.
                response.writeHead(200);

// Serve up the file binary data. When doing this, we
// have to set the encoding as binary (it defaults to
// UTF-8).
                response.write(fileBinary, "binary");

// End the response.
                response.end();

            }
        );

    }
);

// Point the server to listen to the given port for incoming
// requests.
server.listen(8080);


// ---------------------------------------------------------- //
// ---------------------------------------------------------- //


// Create a local memory space for further now-configuration.
(function () {

// Now that we have our HTTP server initialized, let's configure
// our NowJS connector.
    var nowjs = require("now");


// After we have set up our HTTP server to serve up "Static"
// files, we pass it off to the NowJS connector to have it
// augment the server object. This will prepare it to serve up
// the NowJS client module (including the appropriate port
// number and server name) and basically wire everything together
// for us.
//
// Everyone contains an object called "now" (ie. everyone.now) -
// this allows variables and functions to be shared between the
// server and the client.
    var everyone = nowjs.initialize(server);


// Create primary key to keep track of all the clients that
// connect. Each one will be assigned a unique ID.
    var primaryKey = 0;


// When a client has connected, assign it a UUID. In the
// context of this callback, "this" refers to the specific client
// that is communicating with the server.
//
// NOTE: This "uuid" value is NOT synced to the client; however,
// when the client connects to the server, this UUID will be
// available in the calling context.
    everyone.connected(
        function () {
            this.now.uuid = ++primaryKey;
        }
    );


// Add a broadcast function to *every* client that they can call
// when they want to sync the position of the draggable target.
// In the context of this callback, "this" refers to the
// specific client that is communicating with the server.
    everyone.now.syncPosition = function (position) {//syncPosition()在这里定义,在客户端调用

// Now that we have the new position, we want to broadcast
// this back to every client except the one that sent it in
// the first place! As such, we want to perform a server-side
// filtering of the clients. To do this, we will use a filter
// method which filters on the UUID we assigned at connection
// time.
        everyone.now.filterUpdateBroadcast(this.now.uuid, position);

    };


// We want the "update" messages to go to every client except
// the one that announced it (as it is taking care of that on
// its own site). As such, we need a way to filter our update
// broadcasts. By defining this filter method on the server, it
// allows us to cut down on some server-client communication.
    everyone.now.filterUpdateBroadcast = function (masterUUID, position) {

// Make sure this client is NOT the same client as the one
// that sent the original position broadcast.
        if (this.now.uuid == masterUUID) {

// Return out of guard statement - we don't want to
// send an update message back to the sender.
            return;

        }

// If we've made it this far, then this client is a slave
// client, not a master client.
        this.now.updatePosition(position);//updatePosition()为客户端定义的方法,在这里可调用,用this修饰now。

    };

})();


// ---------------------------------------------------------- //
// ---------------------------------------------------------- //


// Write debugging information to the console to indicate that
// the server has been configured and is up and running.
sys.puts("Server is running on 8080");


我把重要的东西摘录下来:
引用
Once the core HTTP server is configured and the NowJS module is initialized, we are given access to the "everyone" object. This everyone object then provides us with access to the server-side "now" scope. This "now" scope is shared between the server and every one of the clients. Anything added to or removed from the server-side "now" scope is also added to or removed from every client currently (or eventually) connected to the server.

This is true for both variables and functions! Notice that my server-side Node.js code defines two methods: syncPosition() and filterUpdateBroadcast(). By defining them in the "everyone.now" scope, I am making them available to both the server and to every single one of the connected clients.

But what about that, "everyone.now.updatePosition()", function? Where did that come from? Ah-ha! Here's the real, "there is no spoon" mind-screw - that function is defined on the client (which we'll see in a minute). And, since it's defined in the client's "now" scope, the server-side Javascript can then invoke it as if there were no separation between the server and client contexts.


client.html
<!DOCTYPE html>
<html>
<head>
    <title>NowJS And Node.js Realtime Communication</title>

    <style type="text/css">

        html,
        body {
            height: 100%;
            overflow: hidden;
            width: 100%;
        }

        img {
            left: 9px;
            position: absolute;
            top: 70px;
        }

    </style>

    <!-- We have this file stored explicitly. -->
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"/>
    </script>

    <!--
    The NowJS HTTP augmentation will take care of routing
    this - we don't actually have this physical file stored
    at this file path.
    -->
    <script type = "text/javascript" src = "/nowjs/now.js" ></script>
</head>
<body>

<h1>
    NowJS And Node.js Realtime Communication
</h1>

<!--
This will be draggable. When this image drags, we are
going to sync the position of it across browsers.
-->
<img
        id="myhead"
        src="./myhead.gif"
        width="100"
        height="100"
        alt="It's my head, do you like it?"
        />


<!-- Configure the client-side script. -->
<script type="text/javascript">

    // Get a reference to the target draggable.
    var myhead = $("#myhead");

    // Get a reference to the body - this is the element on which
    // we'll be tracking mouse movement once the draggable
    // tracking has been turned on.
    var body = $("body");


    // On mouse-down, turn on draggability.
    myhead.mousedown(
            function (event) {
// Prevent the default behavior.
                event.preventDefault();

// Get the current position of the mouse within the
// bounds of the target.
                var localOffset = {
                    x:(event.pageX - myhead.position().left),
                    y:(event.pageY - myhead.position().top)
                };

// Start tracking the mouse movement on the body.
// We're tracking on the body so that the mouse can
// move faster than the tracking.
                body.mousemove(
                        function (event) {
// Create a new position object.
                            var newPosition = {
                                left:(event.pageX - localOffset.x),
                                top:(event.pageY - localOffset.y)
                            };

// Update the target position locally.
                            myhead.css(newPosition);

// Announce the updated position so that we
// can sync accross all clients with NowJS.
                            now.syncPosition(newPosition);//syncPosition()是在服务器端定义的方法,可在客户端调用。
                        }
                );
            }
    );


    // On mouse-up, turn off draggability.
    myhead.mouseup(
            function (event) {
// Unbind the mousemove - no need to track movement
// once the mouse has been lifted.
                body.unbind("mousemove");
            }
    );


    // I allow the remove server to make a request to update the
    // position of the target.
    //
    // NOTE: By defining this function in the NOW scope, it gives
    // the server access to it as well.
    now.updatePosition = function (newPosition){
//updatePosition()这个方法在客户端定义,可在服务器端调用
// Check to see if this client is in master mode; if so,
// we won't update the position as this client is
// actively updating its own position.
        myhead.css(newPosition);

    };

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


引用
When the user moves the image on the client, the client broadcasts the new position using the "now.syncPosition()" function. This function, which was defined on the server, then pushes the updated position down to all the other clients using the "now.updatePosition()" function, which was defined on the client.

Even after coding this myself, it's still somewhat confusing; so, let's look at a quick rundown of the various functions to see where they were defined and where they were invoked:

syncPosition()
  • Defined: Server-side
  • Invoked: Client-side

filterUpdateBroadcast()
  • Defined: Server-side
  • Invoked: Server-side

updatePosition()
  • Defined: Client-side
  • Invoked: Server-side
分享到:
评论

相关推荐

    three7-html5:HTML5Canvas 落块游戏的灵感来自 YuYu Hakusho 动漫中的类似游戏

    如果一个块落下的值加上水平或垂直块序列的值等于 7,那么下落的块和该块序列将消失。 这些方块上方的任何方块都会掉落并且可能会触发连击。 7 的块本身不会清除,因为总和中必须涉及 2 个或更多块。 这个规则只有...

    vimrc-builder:ⓥvimrc文件生成器

    通过Web应用程序轻松构建vimrc为什么构建vimrc文件应该并不困难。 毕竟,您要配置的代码编辑器是1991年发明的。 没关系,您的经验水平是不变的,总有新的方法可以改变vim的经验,但是由于提示分散在Internet上,因此...

    毕业论文-安全跳转页面-整站商业源码.zip

    毕业论文-安全跳转页面-整站商业源码.zip

    实训商业源码-视频解析-毕业设计.zip

    实训商业源码-视频解析-毕业设计.zip

    实训商业源码-小小素材库V7.8.45 小程序前端+后端-毕业设计.zip

    实训商业源码-小小素材库V7.8.45 小程序前端+后端-毕业设计.zip

    毕业论文-二刺螈导航-整站商业源码.zip

    毕业论文-二刺螈导航-整站商业源码.zip

    AI在MES中的应用.pdf

    AI在MES中的应用.pdf

    基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例

    基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例,该项目是个人毕设项目,答辩评审分达到98分,代码都经过调试测试,确保可以运行!欢迎下载使用,可用于小白学习、进阶。该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了Cesium的一些基础示例基于Vue 3实现的Cesium大屏可视化项目源代码,展示了

    【跨境电商营销】亚马逊蓝牙音箱产品数据分析:市场表现与关键词影响研究

    内容概要:该报告由Co.media可美亚发布,基于Amazon平台上的蓝牙音箱产品数据,通过网页工具抓取并清理了772笔交易信息,最终分析了248笔有效数据。报告揭示了评论数高的产品通常售价较高,但低价并非获得高评级的有效手段。高频关键词如“Speaker”、“Bluetooth”、“Smart”、“Wireless”等能显著提升搜索匹配度和销售排名,尤其是前20名产品大多带有这些关键词。此外,价格较低的产品多归类为手机&配件,而价格较高的则归类为电子产品。前50名产品在金额、评论和星数方面具有明显优势,而新产品若想快速进入搜索排名前10,则需重点投入于产品定价和评论星数的提升。 适合人群:希望拓展北美市场的中国品牌企业、从事跨境电商的从业者以及对蓝牙音箱市场感兴趣的投资者。 使用场景及目标:①帮助企业了解蓝牙音箱在北美市场的竞争态势;②指导企业优化产品标题中的关键词选择,以提高搜索排名;③为制定产品定价策略和提升用户评价提供数据支持。 其他说明:Co.media可美亚是一家专注于为中国品牌提供跨境整合营销服务的公司,尤其擅长帮助企业在北美市场建立品牌知名度和竞争力。报告中涉及的数据分析方法包括统计回归分析,用于评估不同因素对搜索排名和销售排名的影响。

    基于Go+python实现的网络异常流量检测系统+源码+GUI界面(毕业设计&课程设计&项目开发)

    基于Go+python实现的网络异常流量检测系统+源码+GUI界面,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于Go+python实现的网络异常流量检测系统+源码+GUI界面,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于Go+python实现的网络异常流量检测系统+源码+GUI界面,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于Go+python实现的网络异常流量检测系统+源码+GUI界面,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于Go+python实现的网络异常流量检测系统+源码+GUI界面,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于Go+python实现的网络异常流量检测系统+源码+GUI界面,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用

    ANSYS SpaceClaim直接建模技术.pdf

    ANSYS SpaceClaim直接建模技术.pdf

    毕业论文-超人配送代驾跑腿小程序V1.5.10 前端+后端-整站商业源码.zip

    毕业论文-超人配送代驾跑腿小程序V1.5.10 前端+后端-整站商业源码.zip

    毕业论文-wx码支付-整站商业源码.zip

    毕业论文-wx码支付-整站商业源码.zip

    实训商业源码-智能AI雷达名片+1.6.7-毕业设计.zip

    实训商业源码-智能AI雷达名片+1.6.7-毕业设计.zip

    ANSYS网格划分.pdf

    ANSYS网格划分.pdf

    3D变形技术在汽车造型设计中的应用.pdf

    3D变形技术在汽车造型设计中的应用.pdf

    ANSYS高级流体动力学培训手册2.pdf

    ANSYS高级流体动力学培训手册2.pdf

    vosk-model-small-cn-022

    vosk-model-small-cn-022

    实训商业源码-视频小店V1.0.7 原版-毕业设计.zip

    实训商业源码-视频小店V1.0.7 原版-毕业设计.zip

    HR_S30-1800.hard

    HR_S30-1800.hard

Global site tag (gtag.js) - Google Analytics