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

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上,因此...

    python入门-30.寻找列表中只出现一次的数字-寻找单身狗.py

    python入门-30.寻找列表中只出现一次的数字——寻找单身狗.py

    布尔教育linux优化笔记

    linux优化笔记,配套视频:https://www.bilibili.com/list/474327672?sid=4496133&spm_id_from=333.999.0.0&desc=1

    知识付费系统-直播+讲师入驻+课程售卖+商城系统-v2.1.9版本搭建以及资源分享下载

    知识付费系统-直播+讲师入驻+课程售卖+商城系统-v2.1.9版本搭建以及资源分享下载,CRMEB知识付费分销与直播营销系统是由西安众邦科技自主开发的一款在线教育平台,该系统不仅拥有独立的知识产权,还采用了先进的ThinkPhp5.0框架和Vue前端技术栈,集成了在线直播教学及课程分销等多种功能,旨在为用户提供全方位的学习体验,默认解压密码youyacaocom

    美妆神域-JAVA-基于springBoot美妆神域设计与实现

    美妆神域-JAVA-基于springBoot美妆神域设计与实现

    原生js制作Google粘土logo动画涂鸦代码.zip

    原生js制作Google粘土logo动画涂鸦代码.zip

    golin 扫描工具使用, 检查系统漏洞、web程序漏洞

    golin 扫描工具使用, 检查系统漏洞、web程序漏洞

    原生态纯js图片网格鼠标悬停放大显示特效代码下载.zip

    原生态纯js图片网格鼠标悬停放大显示特效代码下载.zip

    用AWLUM进行灰色编码2^2n-QAM调制的精确率Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    去水印web端独立版web

    去水印web端独立版web

    原生js制作左侧浮动可折叠在线客服代码.zip

    原生js制作左侧浮动可折叠在线客服代码.zip

    Chrome 谷歌浏览器下载

    Chrome 谷歌浏览器下载

    亲测全新完整版H5商城系统源码 附教程

    全新完整版H5商城系统源码 自己花钱买的,亲测可用,需要自行下载 H5商城系统设置是实现商城基本功能的核心部分,涵盖了从网站配置、短信和支付配置,到商品、工单、订单、分站和提现管理等多个模块的设置。以下是详细的设置指南,帮助您快速上手并高效管理商城系统。 测试环境:Nginx+PHP7.0+MySQL5.6 1. 网站配置 设置商城名称、LOGO、标题、联系方式和SEO关键词等,确保商城专业和易于搜索。 2. 短信配置 配置短信接口和模板,用于发送订单通知、验证码等,提升用户体验。 3. 支付接口配置 配置微信、支付宝等支付接口,填写API密钥和回调地址,确保支付流畅。 4. 商品分类管理 对商品进行分类和排序,设置分类名称和图标,便于用户查找商品。 5. 商品管理 添加和管理商品信息、规格、图片等,确保商品信息准确丰富。 6. 工单管理 查看和回复用户工单,记录售后问题,提升用户服务质量。 7. 订单管理 查看订单详情,更新订单状态,支持批量导出,方便订单跟踪。 8. 分站管理 创建不同区域分站,设置权限,统一管理各区域市场。 9. 提现管理

    短信3.141592672893982398674234

    apk安装包

    原生js选项卡插件自定义图片滑动选项卡切换.zip

    原生js选项卡插件自定义图片滑动选项卡切换.zip

    1-宗教信息佛教佛寺寺庙庵堂相关数据-社科数据.zip

    宗教信息佛教佛寺寺庙庵堂相关数据集提供了全国各个地区省市县各个佛教寺庙的详细信息。这些数据不仅包括寺庙的名称和负责人姓名,还涵盖了所属省份、地级市、区县、具体地址、建立日期以及支派类别等关键信息。该数据集整理了超过3万条样本,为研究中国佛教寺庙的分布、历史和文化提供了丰富的第一手资料。这些信息有助于了解佛教在中国的传播和发展,以及寺庙在社会和文化中的作用。数据的整理和提供,对于宗教学、社会学、历史学和文化研究等领域的学者来说,是一个宝贵的资源。

    线性电阻网络的等效电阻计算Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    简单的 Python 版本管理.zip

    简单的 Python 版本管理pyenvpyenv 可让您轻松在多个 Python 版本之间切换。它简单、不引人注目,并遵循 UNIX 传统,即使用单一用途的工具来做好一件事。该项目由rbenv和 ruby​​-build分叉而来,并针对 Python 进行了修改。pyenv 的作用是什么......允许您根据每个用户更改全局 Python 版本。为每个项目的 Python 版本提供支持。允许您使用环境变量覆盖 Python 版本。一次搜索多个 Python 版本的命令。这可能有助于使用tox跨 Python 版本进行测试。与 pythonbrew 和 pythonz 相比,pyenv没有……依赖于Python本身。pyenv由纯shell脚本制作。不存在Python的引导问题。需要加载到你的 shell 中。相反,pyenv 的 shim 方法通过向你的 中添加目录来工作PATH。管理虚拟环境。当然,你可以自己创建虚拟环境 ,或者使用pyenv-virtualenv 来自动化该过程。目录安装获取 PyenvLinux/UNIX自动安装程序基本

    Notepad-v2.20工具,是替代Notepad++的首选工具

    Notepad-v2.20工具,是替代Notepad++的首选工具

Global site tag (gtag.js) - Google Analytics