Application Domains 应用程序域
和安全域一样,不同安全沙箱下的SWF有着自己独立的类定义。这种在安全域下面进行划分和管理类定义(函数、接口和命名空间的定义也类似)的子域就是应用程序域。应用程序域只存在于安全域内,并且只能属于唯一的一个安全域。但是安全域可以包含多个应用程序域。
安全域内的应用程序域
虽然安全域沙箱用于保护数据安全,应用程序沙箱域用于划分定义。但是他们都用于解决定义的冲突和判断代码的继承关系。
安全域彼此之间是相互独立的,相比之下,应用程序域之间的关系则较为复杂。应用程序域通过类似于Flash中的显示列表那样的层级关系链接在一起。应用程序域可以包含任意的子域,而子域只能有一个父域。子域继承了来自父域中的定义,就像是显示列表中父对象的位置和缩放属性被子对象继承一样。
应用程序域的根节点是一个系统域,这个域包含了Flash Player API的原生定义(Array,XML,flash.display.Sprite等等)。系统域与安全域是一一对应的关系,当安全域初始化的时候这个唯一的系统域也被建立。
当一个Flash Player的实例初始化的时候,SWF文件加到它对应的安全域内。同时也创建了一个包含了这个文件中所有编译过的ActionScript定义的应用程序域。这个应用程序域就成为安全域下的系统域的第一个子域。Flash Player API的原生定义就通过这种继承关系对所有子域开放。
在系统域下新建了一个SWF应用程序域
我们将在应用程序域的继承章节中进行更多关于继承的讨论。
Application Domain Placement 应用程序域的位置
第一个实例化Flash Player的SWF文件所包含的定义总是被加载为系统域的直接子域。父SWF去加载子SWF的时候,可以控制子SWF内的定义所要放置的位置。可选的位置共有以下4种:
- 父SWF的应用程序域的新建子域 (默认方式)
- 子SWF 与父SWF的应用程序域合并
- 作为父域的系统域下的新建子域
- 在其他安全域下的系统域的新建子域
前三种情况都是把子SWF加载到父域所处的安全域下,只有第四种是唯一一种把SWF加载到其他安全域下的方法。
加载子SWF时放置应用程序域的4种选择
还有一种没提到的方式,是你为某个已加载的SWF创建了应用程序域,再把其他子SWF中的定义合并到(或者继承)这个域的情况。这种特殊的放置方式需要复杂的应用程序域层级管理,你需要掌握ApplicationDomain.parentDomain的用法,在此提醒读者小心:这种方法通常在不同的安全沙箱下(本地或者网络)会有不同的行为。这种方式很不常见,所以在此不进行更深的探讨。
LoaderContext对象的applicationDomain属性定义了放置应用程序域的方式。你可以用ApplicationDomain.currentDomain(类似于安全域的SecurityDomain.currentDomain)或者用new关键字新建一个ApplicationDomain实例来作为参数。在ApplicationDomain的构造函数里可以为新建的域指定父域,如果这个参数没有指定,则表示将该域直接作为系统域的子域。
// 将定义放置到父SWF所在的应用程序域(当前应用程序域)
var current:ApplicationDomain = ApplicationDomain.currentDomain;
// 将定义放置到父SWF所在的应用程序域的的子域
var currentChild:ApplicationDomain = new ApplicationDomain(current);<em>?</em>
// 将定义放置到父SWF所在的应用程序域的系统域
var systemChild:ApplicationDomain = new ApplicationDomain();
下面的代码演示了使用LoaderContext对象传递ApplicationDomain实例给Loader.load方法,把一个子SWF加载到父SWF所处的应用程序域的子域下的例子。这种方式也是默认的加载行为。
var context:LoaderContext = new LoaderContext();
// 把子应用程序域作为当前应用程序域的子域
var current:ApplicationDomain = ApplicationDomain.currentDomain;
context.applicationDomain = new ApplicationDomain(current);
var loader:Loader = new Loader();
var url:String = "child.swf";
loader.load(new URLRequest(url), context);
ApplicationDomain实例在内部包含了不对ActionScript开放的层级位置信息。每个ApplicationDomain实例都是一个唯一引用,彼此之间不能相互比较。
var current1:ApplicationDomain = ApplicationDomain.currentDomain;
var current2:ApplicationDomain = ApplicationDomain.currentDomain;
trace(current1 == current2); // false
你也不能通过parentDomain属性得到系统域的引用,只有通过new ApplicationDomain()才可以。
Application Domain Inheritance 应用程序域的继承
定义的继承和类继承有点类似,两者都是子级可以访问父级的定义,而反之则不行。
区别在于,应用程序域的继承不允许子级覆盖父级的定义。如果子域中包含有与父域一样的定义(指的是完全限定名称一致,包括包路径)。那么父域中的定义会取代掉子域。
子域中的定义被父域覆盖
这是因为你不能改变一个已经存在的实例的类定义。如果新的定义在被加载进来以前就已经用旧的定义生成过实例,那么这个实例原先的类定义和新的类定义之间就会产生冲突。所以Flash Player保护原先的类定义不被重写来避免冲突。
这也意味着开发者不可能覆盖ActionScript API的原生定义。因为SWF所处的应用程序域肯定是系统域的子域,而系统域包含了所有原生的定义。所以就算子SWF中包含了同名的定义,也会被系统域中的定义所覆盖。
当向一个已经存在的应用程序域合并定义时,上述规则同样适用。只有与原先的域里的定义无冲突的定义才会被合并。
新增到应用程序域里的定义不会覆盖现有的定义
这种情况下,那些发生冲突但却被覆盖的定义就完全获取不到了。但是如果是继承的方式,就算子域中的那些冲突定义被父域中的定义覆盖掉,还是可以通过getDefinition方法从子域中提取出来,关于这点将在动态获取定义章节中讨论。
加载到应用程序域中的定义在应用程序域的生命期里一直存在。在SWF卸载后,用于保存这个SWF内的定义的应用程序域也会从内存中卸载。但如果该SWF的定义是放在其他某个已经存在的应用程序域内的话,那么这些定义将一直存在于内存中,除非目标应用程序域所关联的那个SWF被卸载。如果一直把新的定义加载到一个已经存在的域内,比如为第一个被加载的SWF创建的域,那么定义所占用的内存就会一直增加。如果是一个不停加载子SWF的滚动广告应用的话,持续增加定义到相同的应用程序域内引起的内存增长问题显然不是预期的结果。
而且,用这种方式加载的定义不会随着子SWF的卸载而卸载,而是在第二次加载相同的子SWF的时候重用第一次加载时创建的定义。这通常不会有什么问题,但是这意味着再次加载相同SWF的时候静态类的状态不会重置。静态变量有可能是上次使用过的值,一定会和第一次加载进来的时候保持一致。
所以,不同的情况需要不同的解决方法。
Child Domains: Definition Versioning 子域:定义的版本管理
定义的继承机制使得子域可以很方便的共享父域内的定义。也由于子域中的重名定义会被父域所覆盖的原因,父应用程序域拥有控制在子域中使用哪个版本的定义的权力。
子应用程序域继承自父域
考虑以下情形:一个基于SWF的网站使用不同的SWF文件来代表不同的页面。主SWF负责加载这些子页面。每个页面SWF基于一个相同的类库开发,具有相似的行为。比如都有一个PageTitle类来表示页面的标题文本。
假如在相同域下有另一个SWF也用到这些相同的子页面,但是需要把子页面的标题文本变为不可选(假设原先的属性是可选择)。要实现这个例子里的目的,在PageTitle类中,我们需要把TextField的selectable属性改为false。但这样改动的问题是会影响原先的SWF文件保持其本来的行为。
为了解决这个问题,我们可以把每个子页面都复制一份并重新编译。但这么做的话会占用更多的空间和网站流量。更好的办法是只编译第二个主SWF,把更新过的PageTitle类定义一起编译进去。然后在子页面在加载到子应用程序域的时候,这个类的定义就会被父域里的定义给覆盖。
原先所有子页面用的PageTitle类如下:
package {
import flash.display.Sprite;
import flash.text.TextField;
public class PageTitle extends Sprite {
private var title:TextField;
public function PageTitle(titleText:String){
title = new TextField();
title.text = titleText;
addChild(title);
}
}
}
编译到第二个主文件里的更新版本的PageTitle类:
package {
import flash.display.Sprite;
import flash.text.TextField;
public class PageTitle extends Sprite {
private var title:TextField;
public function PageTitle(titleText:String){
title = new TextField();
title.text = titleText;
<strong>title.selectable = false;</strong> // changed
addChild(title);
}
}
}
把更新过的PageTitle类定义编译到新的主文件里面,并加载所有子页面到它们自己的子应用程序域中。
PageTitle; // 虽然没有直接用到PageTitle,但我们可以包含一个引用,让它被一同编译进来
// 加载子页面到它们自己的子应用程序域中
// 加载的SWF将会用父域里的PageTitle定义取代掉它们自带的
function addChildPage(url:String):void {
var context:LoaderContext = new LoaderContext();
var current:ApplicationDomain = ApplicationDomain.currentDomain;
context.applicationDomain = new ApplicationDomain(current);
var loader:Loader = new Loader();
addChild(loader);
loader.load(new URLRequest(url), context);
}
这种方法可以在不用重新编译子内容的前提下改变其中的类行为,这都是由于父应用程序域中的定义会覆盖子域中的定义的原因。
注意在上面的例子也可以省略LoaderContext的使用,效果是一样的。
即便子SWF无需用作多重使用目的,更新主文件中的定义也比更新所有子文件的更加简单。实际上,子文件中甚至可以完全不用包含这些定义,只依赖于主文件提供。这就是我们将在相同的域:运行时共享库章节里将展开讨论的。
Separate Domains: Preventing Conflicts 域分离:避免冲突
某些情形下,你可能不希望加载的子SWF内容被父应用程序域里的定义继承关系所影响。因为有可能你甚至不知道父域中存在哪些定义。不论哪种情况,最好都要避免主SWF和子SWF中的定义共享。在这种情况下,应该把子SWF的定义放到新的系统域的子域下。
系统域下的不同子应用程序域
由于父SWF和子SWF的定义之间没有继承关系,所以这时候即使存在相同的定义也不会引起冲突,因为二者属于不同的沙箱。
举个例子:比如你有个培训程序,通过加载外部SWF来代表不同的培训模块。这个程序已经有些年头了,许多开发者开发了成百上千个培训模块。这些模块,甚至培训主程序自身都是基于不同版本的基础代码库进行开发。所以主程序要保证自己使用的基础代码库不会对其他模块造成不兼容的情况。这就必须把这些培训模块加载到他们独立的系统域下的子域,而不是把他们加载到主应用程序域的子域下面。
trainingapplication.swf:
var moduleLoader:Loader = new Loader();
addChild(moduleLoader);
// 把模块加载到系统域的子域下,与当前的应用程序域区分开
function loadModule(url:String):void {
var context:LoaderContext = new LoaderContext();
context.applicationDomain = new ApplicationDomain();
moduleLoader.load(new URLRequest(url), context);
}
不足的是,这种定义的划分方式还不是完全隔离的。由于在同一个安全域下的内容都处于一个相同的系统域下,任何对系统域内定义的修改都将影响同一个安全域下的所有应用程序域。即使是将子SWF加载到一个单独的系统域的子域下,父SWF对系统域的更改还是会对其造成影响。
我们可以通过改动XML.prettyIndent属性来验证这一点:不管处于应用程序域层级的哪个SWF对系统域里的定义作出改变,都会影响到相同安全域下的所有文件。
parent.swf:
trace(XML.prettyIndent); // 2
XML.prettyIndent = 5;
trace(XML.prettyIndent); // 5
var loader:Loader = new Loader();
var context:LoaderContext = new LoaderContext();
// 新建一个独立的应用程序域
context.applicationDomain = new ApplicationDomain();
var url:String = "child.swf";
loader.load(new URLRequest(url), context);
child.swf:
trace(XML.prettyIndent); // 5
所以最佳实践是对定义做的改动应该在使用后及时还原,这样可以避免对其他文件的影响。
var originalPrettyIndent:int = XML.prettyIndent;
XML.prettyIndent = 5;
trace(myXML.toXMLString());
XML.prettyIndent = originalPrettyIndent;
同样的,你也必须留心类似这样的值有可能在你的程序之外被人所改动。
Same Domain: Runtime Shared Libraries 相同的域:运行时共享库
把新增的定义增加到现有的应用程序域下可能是应用程序域最大的用处。因为继承只能把父域内的定义对子域共享,而合并定义到相同的应用程序域内则可以对所有使用这个域的SWF共享,包括父级和子级。
父应用程序域包括了子SWF的定义
运行时共享库(RSLs)正是运用了这种机制。RSLs是可以在运行时被加载的独立的代码库。通过RSLs,其他SWF可以共用其中的代码而不需要编译到自身,从而排除了冗余,减小了文件量,也让代码更容易维护。我们在主应用程序域中加载RSL,从而可以在整个程序中共享定义。
使用RSLs之前需要做些准备工作。首先,ActionScript编译器需要在发布SWF文件的时候知道哪些定义不需要被编译。
原生的Flash Player API定义就不需要编译。虽然每个SWF都需要用到原生的定义(Array,XML,Sprite等),但是这些定义只存在于Flash Player的可执行文件中,不需要也不会被编译到SWF文件中。编译器使用一个叫做playerglobal.swc的特殊SWC(预先编译的SWF类库)来识别原生定义。它包含了原生定义的接口,包括定义的名字和数据类型等。编译器通过它来编译SWF,而且不会把这些定义编译到最终的SWF中。
编译器还可以引用其他类似playerglobal.swc一样的SWC库。这些库作为“外部”类库,其中包含的定义只是用于编译,不会包含到SWF内部。
这里不详细讨论在编辑工具中如何进行库链接的设置。不同版本的编辑器的设置有些不同,具体方法请参考Flash文档。
虽然我们用SWCs来编译SWF,但实际上他们本身就是SWF文件,和其他被加载的SWF内容类似。在进行库编译的时候,同时生成了SWF和SWC文件。SWF用于运行时加载,而SWC在编译时用做外部库。
编译器使用SWCs共享库,SWF共享库在运行时加载
另一个准备工作需要编写代码。使用外部库的时候,发布的SWF中不包含库中的定义。如果Flash Player尝试运行其中代码,就会产生核查错误,整个SWF基本上就瘫痪了。
Flash Player会在类第一次使用的时候校验其定义。如果应用程序域中不包括该定义,那么校验错误就会产生。
实际上缺少定义产生的错误有两种。校验错误是两种之中最糟的,表示类无法正常工作的灾难性失败。另一种是引用错误,当某种数据类型被引用但是却不可用的情况下发生。虽然缺失定义也会造成引用错误,但这种错误只会在已经经过核查的类内部打断代码执行的正常过程。
var instance:DoesNotExist;
// VerifyError: Error #1014: Class DoesNotExist could not be found.
// 当Flash Player校验包含该定义的类时发生校验错误
var instance:Object = new DoesNotExist();
// ReferenceError: Error #1065: Variable DoesNotExist is not defined.
// 当代码执行到这一行的时候发生引用错误
主要的区别在于校验错误与类定义有关,而引用错误与代码执行相关。在类内部的代码要执行之前,必须要先通过校验。上面的例子中instance对象声明为Object类型,校验可以正常通过(只是在执行的时候就会遇到引用错误)。
Note: Strict Mode 注意:严格模式
外部库是引用定义而不需将其编译到SWF中的一种方法。另一种方法是关闭严格模式,这将大大放宽了对变量使用的检查。对于类的使用来说,你可以引用一个不存在的类而不会引起编译器报错。你不能直接把不存在的类用作变量类型(这样做会在运行时产生校验错误),但是你可以像上面的“引用错误”例子中那样去引用。在非严格模式下,编译器也许会检测不到一些可能发生的错误,所以通常不建议用这种模式。
使用了RSLs的SWF文件必须保证先加载好RSLs,才能使用这些外部定义。我们应该在主应用程序开始执行之前用一个预加载器来加载RSLs。
下面演示了一个SWF加载包含Doughnut类的外部RSL的例子。虽然在SWF中直接引用了这个类,但是它却是编译在外部库中,并通过SWC的方式来引用的。RSL在Doughnut类第一次使用之前就被加载进来,所以不会造成校验错误。
Doughnut.as (编译为doughnutLibrary.swc 和doughnutLibrary.swf):
package {
import flash.display.Sprite;
public class Doughnut extends Sprite {
public function Doughnut(){
// draw a doughnut shape
graphics.beginFill(0xFF99AA);
graphics.drawCircle(0, 0, 50);
graphics.drawCircle(0, 0, 25);
}
}
}
ShapesMain.as (Shapes.swf的主类):
package {
import flash.display.Sprite;
public class ShapesMain extends Sprite {
public function ShapesMain(){
// 虽然并没有编译到Shapes.swf中,
// 但是我们通过doughnutLibrary.swc外部库
// 可以获得对Doughnut类的引用
var donut:Doughnut = new Doughnut();
donut.x = 100;
donut.y = 100;
addChild(donut);
}
}
}
Shapes.swf (RSL loader):
var rslLoader:Loader = new Loader();
rslLoader.contentLoaderInfo.addEventListener(Event.INIT, rslInit);
// 把RSL中的定义加载到当前应用程序域中
var context:LoaderContext = new LoaderContext();
context.applicationDomain = ApplicationDomain.currentDomain;
var url:String = "doughnutLibrary.swf";
rslLoader.load(new URLRequest(url), context);
function rslInit(event:Event):void {
// 只有当RSL中的定义导入到当前应用程序域以后
// 我们才能用其中的Doughnut定义通过ShapesMain类的校验
addChild(new ShapesMain());
}
在这个例子中,Shapes.swf是主程序,当RSL加载完毕后实例化主类ShapesMain。如果没有导入RSL中的定义,创建ShapesMain实例的时候就会因为在应用程序域中找不到对应的类而发生校验错误。
注意:Flex中的RSL
这里讨论的方法是最底层的方法,不应该用于Flex开发。Flex框架中有自己的一套RSLs处理机制,更多关于RSL在Flex中的应用,请参考Flex Runtime Shared Libraries (Flex 4)。
Getting Definitions Dynamically 动态获取定义
我们可以用Application.getDefinition方法获取不在应用程序域内的定义,或者被父域覆盖的定义。这个方法返回应用程序域及其任意父域内的定义引用。在当前应用程序域内使用getDefinition方法的效果等同于全局函数getDefinitionByName。
我们也可以通过SWF的LoaderInfo.applicationDomain来获得在ApplicationDomain.currentDomain以外的应用程序域。在下面的例子中我们用Loader加载了一个SWF文件,然后在加载的那个应用程序域中提取com.example.Box类的定义。
try {
var domain:ApplicationDomain = loader.contentLoaderInfo.applicationDomain;
var boxClass:Class = domain.getDefinition("com.example.Box") as Class;
var boxInstance:Object = new boxClass();
}catch(err:Error){
trace(err.message);
}
以上的例子中包含了两个知识点。首先,getDefinition方法的返回值被显式的转换为Class类型,这是因为getDefinition默认返回的是Object类型,有可能代表了除了类类型以外的其他类型(函数,命名空间,接口)。其次,这个操作应该要放在try-catch函数体内,因为如果getDefinition查找定义失败将会抛出错误。或者你也可以在使用getDefinition之前用ApplicationDomain.hasDefinition方法检测是否能够成功找到某个定义。
用动态方式去获取的定义,而不是那些在当前应用程序域(及继承的程序域内)的定义,是不能用作变量类型的。就像RSL一样,在应用程序域内找不到的类定义会在校验的时候报错。所以上面的例子中boxInstance变量声明为Object类型而不是Box类型,就是因为Box类的定义在应用程序域内不存在。
Same-definition Collisions 相同定义的冲突
有些时候可能会发生你引用的定义匹配到另外的应用程序域里的定义的交叉情况。这种情况将会产生如下强制转换类型错误:
TypeError: Error #1034: Type Coercion failed: cannot convert
com.example::MyClass@51e1101 to com.example.MyClass.
你可以看到在不同内存空间里的定义用@符号进行了区分。虽然它们内部的代码可能是完全相同的(或不同),但是由于它们存在不同的应用程序域(或安全域)内,所以它们是两个不同的定义。
只有像Object那样的原生Flash Player定义才可以将位于不同域(甚至是跨安全域的)的定义关联起来。实际上,大多数时候声明一个跨域的变量类型的时候都需要用Object类型。
虽然我们可以用Object这种通用类型来解决定义冲突错误,实际上我们更应该合理安排应用程序域的位置来消除这种不匹配的情况。
Conclusion 总结
这篇教程包含了很多方面的信息。前半部分讨论了什么是安全域,以及它如何影响来自不同域的内容。Flash Player用这种安全沙箱机制保护用户的数据。Flash开发者应该了解并合理利用这种限制。
第二部分讨论了应用程序域——另一种用于在安全沙箱内划分ActionScript定义的沙箱类型。应用程序域的层级机制提供了在不同的SWF直接共享和重用定义的方法。
在安全域和应用程序域的概念上有很多容易犯的错误。希望这篇教程能够帮你对此有所准备。你不仅应当了解他们的运作方式,还要知道如何正确运用它们以达成你想要的效果。
译者注:
通过这篇文章的翻译,我才真正体会了翻译工作的难做。虽然平时看英文资料的速度还挺快,但是用中文详细复述一遍需要多花好几十倍的时间。在这篇教程的翻译中,我没有使用全文翻译等辅助工具,完全靠手打,一边翻译一遍领会作者的意图。感觉收获还是比单纯看一遍要来得更多一些。
本文介绍的知识相当重要,特别是从AS2时代成长起来的开发者很容易就掉进文中提到的一些陷阱。完全掌握这部分知识对设计模块架构,管理内存等方面都有很大的帮助。在此要再次感谢原作者senocular为我们带来这么精彩的教程。
请大家尊重版权,转载请注明出处。
相关推荐
首先,让我们深入了解一下 Flash 的安全沙箱模型。Flash 分为三个主要的安全沙箱:浏览器沙箱、本地-with-网络沙箱和本地-without-网络沙箱。浏览器沙箱是最严格的,只允许 Flash 内容与同一域名的资源交互;本地-...
通过以上内容,你应该对AS3中的安全沙箱有了更深入的理解。如果你在实际项目中遇到沙箱问题,可以参考提供的文件集合,寻找解决方案。这些资料很可能包含了多种处理方法,以应对各种情况。记住,解决这类问题可能...
本篇文章将详细探讨“Flash加载SWF文件的沙箱问题”,并结合标签“源码”和“工具”来深入理解这个问题。 Flash Player为了确保用户的安全,采用了沙箱模型,这个模型将不同的运行环境分隔开来,防止恶意代码对用户...
本文将深入探讨如何实现这两种语言间的Socket通信,并解决在Flash Player的安全沙箱问题。 首先,让我们理解什么是Socket通信。Socket是网络编程中的一个概念,它允许两个程序通过TCP/IP协议进行双向通信。在Java中...
《深入解析Flash安全文档:构建安全的Flash应用环境》 一、引言 在数字时代,Flash技术作为网络媒体和互动应用的重要组成部分,其安全性问题备受关注。《Flash安全文档》是一份由Adobe公司发布的白皮书,详细阐述...
Flex安全沙箱问题是一个在开发基于...总的来说,解决Flex安全沙箱问题需要深入理解沙箱机制、跨域策略和`crossdomain.xml`文件的配置,同时关注服务器端的实现细节,以确保应用程序既能正常运行,又能保障用户的安全。
2. "浅谈Flash_Player的沙箱机制.ppt" - 这是一个PowerPoint演示文稿,标题明确指出它将深入探讨Flash Player的“沙箱机制”。沙箱机制是Flash Player为了安全而采用的一种隔离策略,它将Flash内容分割到不同的安全...
本文将深入探讨如何使用C#作为服务器端,Flash作为客户端,通过Socket进行安全通信,并利用Flash的沙箱机制来保障数据传输的安全性。 首先,让我们了解Socket通信的基本概念。Socket是网络编程中的一个接口,它允许...
为了深入学习这个示例,你应该下载并研究`FlashPlayer`源码包,查看其中的类和方法,了解它们如何与Flash内容交互,并尝试在自己的项目中集成。同时,阅读博客文章...
Flex沙箱是Flex应用程序运行时的一个核心组件,它模仿了Adobe Flash Player的安全模型。沙箱主要分为两种类型:本地沙箱和网络沙箱。本地沙箱允许应用程序访问用户的本地文件系统和硬件设备,而网络沙箱则限制了这些...
在深入探讨Flash应用程序域之前,我们先明确一点:Flash是一款由Adobe Systems开发的多媒体平台,广泛应用于网页动画、游戏以及桌面应用程序等领域。Flash的核心在于其强大的脚本语言——ActionScript,它允许开发者...
### 深入理解ApplicationDomain和SecurityDomain #### 安全域(Security Domain)与应用程序域(Application Domain)概述 安全域与应用程序域是Flash Player中两种重要的沙箱概念,它们帮助开发者理解如何管理和...
本话题将深入探讨“Flash与C#通信”的技术细节。Flash,作为一种曾经广泛应用于网页动画和交互设计的平台,常常需要与后端或宿主环境进行数据交换。C#,作为.NET框架的一部分,提供强大的开发能力,特别是在Windows...
在Flash开发中,加载特效是用户体验的重要组成部分,它在内容加载期间提供视觉反馈,使得用户知道应用程序正在...通过深入理解和实践这些概念,开发者可以创建出更加吸引人的加载特效,提升用户对应用程序的满意度。
本文将深入探讨如何使用Socket进行Xcode与Flash之间的通信,以及解决通过网页调用时遇到的两次连接问题。 首先,Socket是网络编程中的基本概念,它提供了一种端到端的数据通信方式,允许两个应用程序通过TCP或UDP...
这个经典的Flash播放器源码提供了深入理解其工作原理和技术实现的机会,对于开发者来说,是提升技能和学习新知识的宝贵资源。 Flash播放器的核心技术基于ActionScript,这是一种面向对象的编程语言,用于控制和驱动...
本书开篇便引领读者了解并掌握PHP for Flash FMS开发所需的基础环境设置。这包括了PHP、Flash Media Server及相关开发工具的安装与配置流程,确保开发者能在最短的时间内搭建起一个适合开发的环境。这一章节的重要性...
首先,让我们深入了解VC和Flash的基本概念。VC,全称Visual C++,是微软公司开发的一款集成开发环境,主要用于编写C++语言的应用程序。它提供了强大的调试工具和丰富的库支持,如MFC(Microsoft Foundation Classes...