zoukankan      html  css  js  c++  java
  • Silverlight应用程序的本地通讯

     

    Silverlight应用程序的本地通讯

     

           在实际开发中,可能会在同一个网页上放置多个Silverlight应用程序,而这些应用程序之间可能需要互相通讯,比如实现两个Silverlight应用程序之间的同步。

             Silverlight 3开始,我们可以使用“System.Windows.Messaging”命名空间中的两个类——LocalMessageSenderLocalMessageReceiver,在运行于同一台计算机上的两个Silverlight应用程序间相互交换信息。

             顾名思义,LocalMessageSender类用于发送消息,而LocalMessageReceiver则用于接收消息。

             当一个Silverlight应用程序需要发送消息时,实例化一个LocalMessageSender对象,类似地,如果它需要接收消息,实例化一个LocalMessageReceiver对象。

             消息发送与接收的“配对”关系通过消息接收者的“域名+接收对象名字”来确定。只要“域名+接收对象名字”一致,多个LocalMessageSender对象就可以向同一个LocalMessageReceiver对象发送消息。

             了解了上述知识,开发能相互通讯的Silverlight应用程序就有了章法。

             请看文后所附之示例解决方案LocalCommunication

     

     

    图1 在同一个网页上相互通讯的Silverlight程序

            

             1所示,示例解决方案LocalCommunication在同一个ASP.NET网页上承载了两个Silverlight应用程序。用户在发送端应用程序输入一个消息字串,并从下拉框中选择一个命令(“椭圆”或“矩形”)之后,发送端应用程序会将这两个信息以“;”作为间隔符组合成一个复合信息发送出去。

             接收端应用程序在收到信息之后,解析收到的信息,将字串显示出来,并依据接收到命令显示一个“椭圆”或“矩形”。

             下面剖析一下示例程序,以帮助大家掌握相关的技术要点。

    1 消息发送方

    在发送端示例程序,需要实例化一个LocalMessageSender对象:

        LocalMessageSender Sender = new LocalMessageSender(

                        "LocalCommunication.Receiver");

              特别注意一下构造函数中的参数指定了接收者的名字。此名字将用于定义消息的接收者。

             实例化LocalMessageSender对象之后,就可以调用其SendAsync()方法“异步”发送信息:

        Sender.SendAsync("要发送的信息");

             如果需要接收消息接收方发回的“消息已接收”通知,通常会给LocalMessageSender对象的SendCompleted方法挂接一个事件响应函数,在此函数中可以通过其参数e(类型为SendCompletedEventArgs)的Response属性获取用户发回的“回执”。

        Sender.SendCompleted += new        

            EventHandler<SendCompletedEventArgs>(Sender_SendCompleted);

    2 消息接收方

             类似地,消息接收方示例程序实例化一个LocalMessageReceiver对象,注意其名字一定要与消息发送方一致。

        LocalMessageReceiver Receiver = new

            LocalMessageReceiver("LocalCommunication.Receiver");

             然后,为其挂接事件响应函数,在此函数中处理接收到的消息。

        Receiver.MessageReceived += new

            EventHandler<MessageReceivedEventArgs>(Receiver_MessageReceived);

             从事件参数e(其类型为MessageReceivedEventArgs)的Message属性可以读取发送方传过来的消息。

             最后,调用Listen()方法监听消息:

        Receiver.Listen();

             最关键的地方就是这么多了。是不是很简单?

             但还是有一些东西需要交代的。

             1)在消息发送方,LocalMessageSender对象有一个ReceiverDomain属性,默认值为null,这意味着,消息的发送方与接收方必须位于同一个域(Domain)中

          注意:

           域(Domain)”和“应用程序域(AppDomain)”不是一回事。域表明了Silverlight应用程序的位置信息,诸如:“www.myuniversity.edu.cn”之类,而应用程序域则代表了Silverlight应用程序的运行环境,Silverlight插件在装载一个Silverlight应用程序时,会为其创建一个应用程序域作为其运行环境。

           假设某网页使用多个<object>元素承载了多个Silverlight应用程序,则Silverlight插件会为每个Silverlight应用程序创建相互独立的应用程序域,这些Silverlight应用程序的“域”可以相同(只要来源于同一个网站),也可以不同(如果来源于不同的网站)。

             如果将发送方的ReceiverDomain属性设置为LocalMessageSender.Global值(其实就是一个仅包容单个“*”字符的字串),则发送方可以向另一个域的Silverlight应用程序发送信息。

             2)在消息接收方,LocalMessageReceiver对象的名字决定了其是否能接收到消息。因此,在同一个域中绝对不要创建拥有相同名字的LocalMessageReceiver对象!

             如果你硬要这么做,当调用LocalMessageReceiver.Listen()方法开始监听时,你会得到一个ListenFailedException,不能接收消息。

             为了处理“名字”问题,LocalMessageReceiver类提供了一个NameScope属性,其默认值为“ReceiverNameScope.Domain”,表示这个名字必须在当前域中唯一。它的另一个可选值是“ReceiverNameScope.Global”,表示在当前计算机上运行的所有Silverlight应用程序所涉及到的域中,这个名字都必须是独一无二的。

             ReceiverNameScope.Global”值是一个非常强的约束条件,你可以保证在“自己的”域中名字唯一,但你无法保证来源于其他网站的Silverlight应用程序在给LocalMessageReceiver对象取名时一定不会与你“英雄所见略同”。

             为了解决这一问题,笔者的建议是给LocalMessageReceiver对象的名字中加上一个GUID值,这样,同名的机会就很少了。

             另外,还要注意消息接收方与消息发送方的设置必须一致,比如消息发送方的ReceiverDomain属性设置为“LocalMessageSender.Global”,则接收方的NameScope属性也必须设置为“ReceiverNameScope.Global”。

             3)由于消息接收方可能会接收多个消息发送方发来的消息,因此有可能某个“不速之客”(指某个在本机上加载的Silverlight应用程序)“恰巧”地“蒙”对了消息接收对象的名字,这将导致消息接收方应用程序可能会接收到“非法”的,有可能是“恶意”的指令,因此,LocalMessageReceiver类还设计了另一个AllowedSenderDomains属性来限制可以发送消息的域,这个属性是一个“有资格发送消息的”Silverlight应用程序所在域名字串的集合:

     

        public IEnumerable<string> AllowedSenderDomains { get; }

     

             域名不在此集合范围内的Silverlight应用程序发送的消息,将被接收方所拒绝。

             可以使用LocalMessageReceiver的另一个构造函数一次性地为上述介绍过的属性进行赋值:

        Receiver = new LocalMessageReceiver("LocalCommunication.Receiver",

            ReceiverNameScope.Global,

            new string[] {"www.myFriend.com","www.myHost.com"});

             上述代码指定只有来自于“www.myFriend.com”和“www.myHost.com”的Silverlight应用程序可以“跨域”向“我”发送信息。

             如果允许接收任何一个域的消息,可以将AllowedSenderDomains属性设置为“LocalMessageReceiver.AnyDomain”值,此值引用仅包容了一个“*”字串的数组对象。

             再次警告,这是个“危险”的值,使用时要慎重!

             另外,属于同一域内的多个Silverlight应用程序间通讯总是许可的。

             4)如果允许Silverlight应用程序脱离浏览器运行,那么,默认情况下运行于浏览器中的Silverlight应用程序是不能与浏览器外的“兄弟”通讯的。如果需要启用这个功能,必须在创建LocalMessageReceiver对象时,将其DisableSenderTrustCheck属性设置为true(其默认值为false:

     

        Receiver.DisableSenderTrustCheck = true;

     

        下面做个小结:

        可以使用LocalMessageSenderLocalMessageReceiver方便地在运行于同一台计算机上的多个Silverlight应用程序间相互通讯,其中的关键在于要正确地匹配名字和给相关的属性赋与有效的值。

             在实际开发中,要特别注意安全性问题。

             此外,每次能传送的信息大小是有限制的,最大上限为40K。信息的格式是由程序员决定的,由于Silverlight对序列化XMLJSON格式的数据提供了支持,因此,使用它们会比较方便,只要注意消息大小别越限就好了。

     

    ==============================

    下载本文示例源码

    注:示例运行环境为VS2010 RC + Silverlight4 RC。

  • 相关阅读:
    第十八课 顺序存储线性表的分析
    第十七课 StaticList和DynamicList实现
    第十六课 顺序存储结构的抽象实现
    第十五课 线性表的顺序存储结构
    第十四课 线性表的本质和操作
    第十三课 类族结构的进化
    第十二课 顶层父类的创建
    第十一课 异常类构建
    HDU 5773The All-purpose Zero
    HDU 5755 Gambler Bo
  • 原文地址:https://www.cnblogs.com/bitfan/p/1698873.html
Copyright © 2011-2022 走看看