西西河

主题:【原创】新时代新潮流WebOS 【1】 -- 邓侃

共:💬594 🌺1902
全看树展主题 · 分页首页 上页
/ 40
下页 末页
家园 Yeah, it works very well for

Nokia, especially the N-series.

家园 【原创】【12】解剖Adobe Flash

【12】解剖Adobe Flash

前文说到,Adobe Flash系统,包括三个方面,1. 制作工具,2. 播放器,Flash Player,3. 数据传输协议。理解Adobe Flash系统,或许可以从数据传输协议入手。数据传输协议体现在Flash的文件格式,Flash的文件格式很多,其中最重要的有三个,SWF,FLV 和AS。理解了这三个文件格式,Adobe Flash制作工具和播放器,就不难理解了。

1. SWF,传输动画的文件格式。用户一边下载.swf文件,一边使用Flash Player播放。

2. FLV,传输视频的文件格式,Flash制作者可以把FLV作为一个独立的文件,用户一边下载.flv文件,一边用Flash Player播放。也可以把FLV插入到SWF文件中去,作为一个片段。

3. AS,ActionScript的缩写。ActionScript类似于JavaScript,解决与用户交互的问题。

[1] SWF 动画格式

1. 整个SWF由若干frames按顺序串联组成,每个frame的结尾处有特殊的tag(ShowFrame)作为标识。

2. 每段frame的内容分成两部分,一部分定义该frame中出现的角色(character),譬如形体,图像,按钮,文字等等。另一部分控制这些角色显现的位置,移动和变形,以及配音的播放等等。

3. Flash Player开始播放一段SWF前,它先处理几段frames。处理的结果,主要是把每一段frame的内容绘制在一幅bitmap上,把这幅 bitmap缓存在内存中。当完成了若干幅bitmaps以后,就可以开始播放,播放过程中,逐步处理后续的frames。

4. 假如整个SWF中总共出现N个角色,不需要在文件初始一揽子把它们全部定义清楚,而是可以在后续的frames中,陆续添加角色。Flash player开始播放前,会准备一份空白的角色名单。每出现一个新角色,就把它添加到名单中。

5. 每段frame可以调用先前frames中已经定义过了的角色,但是不可以调用后续frames中定义的角色。这样做的好处,是flash player不需要下载完整的SWF文件,而是在下载了一部分数据后,就可以开始播放。一边播放,一边继续下载后续的数据。

6. SWF采用分段压缩,也就是把每段frame的数据分别压缩,而不是把SWF文件作为一个整体压缩。这样做的好处,是支持一边播放一边下载的功能。但是也有代价,因为分段压缩的压缩比,显然不如整体压缩比。

7. Frame中出现的角色和控制键,都是以tag的形式来定义。Flash的制作者,可以自行定义特殊类型的tags,以便扩充现有flash的功能。但是每增加一个新类型的tag,不要忘记给flash player提供相应的插件。

8. 如果flash player在播放某一个SWF文件的过程中,遇到不能识别的tags,它会自动跳过,而不至于因为个别陌生的tags,影响整个SWF文件的播放。这样设计的好处,是既方便用户扩展flash的功能,又保证flash player播放的稳定。

点看全图

外链图片需谨慎,可能会被源头改

Figure 1. Illustration of Flash Animation

Courtesy http://www.dedecms.com/upimg/20070117/11E00M5bF43427.gif

[2] FLV 视频格式

FLV是Flash Video的文件格式。其实FLV本身并不是一个视频格式,而是一个容器。容器里面可以装H.263,H.264, VP6或者其它格式的视频,同时可以装MP3格式的音乐。2007年8月推出的新版Flash Player 9,更是强大到,能够支持MPEG-4旗下诸多格式的解码,包括H.264(MPEG-4, P10),音频压缩格式AAC(MPEG-4,P3),MP4(MPEG-4,P14),屏幕下方文字走马格式3GPP(MPEG-4, P17)等等。

在Flash Player播放一段.flv文件时,Player知道,它将播放的是一段视频或者音乐,然后它进一步识别这段视频或者音乐用的是什么编码格式,根据不同格式,选择相应的解码器。这里有两个问题,

1. 譬如说有一段MP3的音乐,为什么不直接传输MP3,而要在外卖裹一层FLV的包装,而FLV的包装并没有实际功能。

如果直接下载MP3音乐,那么播放时需要启动识别MP3的播放器。直接使用MP3播放器,播放.mp3文件,比用Flash Player,播放.flv文件的效率高。因为.flv文件里实际包括的就是那个.mp3文件,丝毫不差。但是识别编码格式,选择相应解码器,这些都是中间环节,中间环节多了,效率自然低。

让MP3成为音乐的标准格式,这是很多人的愿望。但是视频的标准是什么,众说纷纭,莫衷一是。不同网页使用不同的视频格式,用户浏览这些网页,需要事先下载并安装各种各样的视频播放器,烦不胜烦。

如果Flash Player能包含所有常用的视频播放器,那么无论用户浏览哪个网页,他只需要预先下载并安装Flash Player一套软件,就可以包打天下。更何况,反正Flash Player已经无所不在了,现在要做的,是扩充Flash Player的功能,使它能够播放更多格式的视频。

2. 既然FLV支持MPEG-4旗下所有格式,为什么林立山头,把文件后缀定为.flv,不如干脆把文件后缀定为.mpeg4好了。

实际上,Adobe公司的确有意向,今后取消.flv文件格式,而使用标准的.mpeg4格式。

点看全图

外链图片需谨慎,可能会被源头改

Figure 2. The video format H.264 and audio format AAC wrapped inside FLV

Courtesy http://farm4.static.flickr.com/3587/3372083431_f9b0a9e5d9_o.gif

关键词(Tags): #硅谷评论
家园 质感
家园 FLASH包含的元素很多吗?ADOBE自己就做不出来?

非得收购那个Macromedia?还是微软厉害,模仿能力强:)

家园 本节沙发
家园 【原创】【13】Adobe Flash,向何处去?

【13】Adobe Flash,向何处去?

前文说到,Adobe Flash的文件格式很多,其中最重要的有三个,SWF,FLV 和AS。前文介绍了SWF和FLV,这一篇谈谈ActionScript。

[3] ActionScript 与 Adobe Flex

虽然Adobe Flash的初衷是制作和播放动画,但是有没有可能利用这个技术,让网页“活”起来?譬如有个网页讲解建筑装修。网页中央反复播放一段动画,显示建筑的各个立面,下方划出一块区域,显示文字注释。当用户把鼠标移动到动画中某一个位置时,注释区就显示相应文字说明。

针对这样的需求,Adobe推出了Adobe Flex。Adobe Flex是Asynchronous Flash and XML的简称。明眼人一看就明白,这个命名方式,与Ajax非常类似。Ajax是以下几个单词的首字母的缩写,Asynchronous JavaScript And XML。比较一下Ajax和Adobe Flex,两者都有Asynchronous,都有XML。Asynchronous指的是,通过异步响应的方式,改善用户体验。问题是,1. 为什么XML这么重要?2. Adobe Flash支持不支持JavaScript?

1. 先说XML为什么重要,借用一段S兄的文字。

如果浏览器的核心是Rendering Engine,那么Rendering Engine的核心就是“DOM”。譬如浏览器从某个网站下载了某个网页,网页不仅包括HTML文件,还包括CSS文件,还有JavaScript,还有 HTML文件中链接的图片,音乐和视频等等。所有这些,统称为网页内容,所有内容中最重要的,是HTML。HTML之所以重要,是因为HTML描述了一个 XML DOM Tree,这棵XML DOM Tree是个框架,是个脉络,是个纲。

纲举目张,Rendering Engine的主要任务就是围绕着这棵XML DOM Tree的生成,表现,维护与撤销。譬如CSS,它定义了DOM树中各个节点,尤其是叶子们的字体,大小,颜色,渲染方式等等。又譬如 JavaScript,它的任务之一是捕捉用户的行为,例如在文本框中输入的文字,点击的按钮,鼠标的位置等等,改变XML DOM Tree的某一些节点的内容,甚至部分改变Tree的结构。

点看全图

外链图片需谨慎,可能会被源头改

Figure 1. The internal workflow of a rendering engine.

Courtesy https://developer.mozilla.org/@api/deki/files/189/=EmbeddingBasicsa.gif

从上图可以看出DOM的重要性。虽然这个图这是Rendering过程的大致流程图,但是DOM模型并没有在这个过程结束时被销毁,而是一直在当前网页的“ 生命期”生存。可以这样说,任何于网页的交互操作都伴随着DOM树的“部分遍历”。 如果能掌握住Render Engine中关于DOM的代码就等于抓住了Render Engine的纲。

问题是,HTML的解析,CSS风格的渲染,这些工作由谁来做,是WebKit还是Flash Player?或者换一句话说,是在WebKit框架内,插入Flash Player,还是在Adobe Flash体系内,插入WebKit的某些功能。这个问题,各个厂家目前各行其道,没有统一规范。Palm WebOS的解决方案,是把Flash Player插入到WebKit框架中去,插入的手段是NPAPI。

点看全图

外链图片需谨慎,可能会被源头改

Figure 2. Palm WebOS architecture

Courtesy http://developer.palm.com/assets/images/book/palm_0112.png

2. Adobe Flash支持不支持JavaScript?

HTML+CSS+JavaScript,人称网页三剑客。JavaScript的专长是解决用户交互的问题。所谓与用户的交互,体现在两个方面,1. 捕捉事件,譬如用户移动鼠标,在文本框里输入文字,点击按钮等等。2. 响应动作,主要是改变页面的内容,以及显示的方式。

Adobe Flash提供了ActionScript。ActionScript与JavaScript相比,无论是功能还是语法,都非常相似。这不奇怪,因为 ActionScript与JavaScript一样,使命都是解决与用户交互的问题。奇怪的是,为什么Adobe Flash不直接使用JavaScript。

点看全图

外链图片需谨慎,可能会被源头改

Figure 3. A not-blessed prophet

Courtesy http://www.creationism.org/images/DoreBibleIllus/h1Ki1324Dore_TheDisobedientProphetSlainByA_Lion.jpg

95% 以上的PC装载了Adobe Flash,这意味着Adobe有可能在Rich Internet Application领域,形成垄断。有垄断的威胁,就有开源的反制。开源项目Gnash致力于取代Flash Player,而开源项目Ajax Animator的目标主要是提供制作SWF的工具。

玩味一下Ajax Animator这个名字,想到一个问题,是不是可以拓展Ajax,来提供所有Adobe Flash的功能?

1. ActionScript与JavaScript,功能和语法都相似,长远来讲,势必合流。

2. SWF格式,是不是可以归并到XML范畴中?SWF以tag作为标示,XML以marker作为标示,两者很容易统一,当然也有代价,marker比tag占用更多空间。

3. 支持Ajax的是浏览器,播放SWF的是Adobe Flash Player。浏览器是否可以与Flash Player融为一体?目前Flash Player作为插件插入浏览器,但是两者功能上有很多重叠。如果把两者融合在一起,重新实现,运行效率必然比插件方式高很多。

总之,Ajax和Adobe Flash有可能合流。技术上的确存在一些障碍,但是主要是优化系统,提高效率,而不是致命的差别。Ajax和Adobe Flash的合流,困难主要来自于商务。

目前在Rich Internet Application领域,是三足鼎立的局面,其中Adobe Flash份额最大,其次是Microsoft SilverLight,最弱的是Sun Microsystems的JavaFX。JavaFX之所以没有受到用户的青睐,一是制作工具不直观,难掌握,二是JavaFX播放器启动时间太长,运行期间也太占用内存。

照这个趋势发展下去,JavaFX前途堪忧。但是也有改变命运的机会,譬如,JavaFX摇身一变,着力于拓展现有Ajax技术,去支持动画和视频。这样一来,JavaFX就有可能蜕变成Ajax的领跑者,而不是RIA的淘汰生。

关键词(Tags): #硅谷评论
家园 ActionScript源自JavaScript

在ECMA-262 specification将JS标准化后,ActionScript的演进也遵照这个标准。按照ECMA规范,这种脚本语言应该叫ECMAScript——"JavaScript"仅指Netscape和Mozilla Foundation的实现。不妨把JS和ActionScript看作ECMAScript的两种方言好了。

家园 未必那么简单

JavaScript和JScript是ECMAScript的两种方言,但是ActionScript短期内是不是能统一到ECMAScript规范内,情况可能会复杂一点。

尤其是ECMAScript的事件的捕捉和传递,是基于DOM Event 机制来处理的,但是Adobe Flash不一定需要DOM。

当然,如果Adobe Flex从Flash独立出来,分道扬镳,那就有可能遵循ECMAScript规范。

家园 得宝

恭喜:你意外获得【通宝】一枚

鲜花已经成功送出。

此次送花为【有效送花赞扬,涨乐善、声望】

家园 Silverlight跟开源社区眉来眼去

Silverlight 3开始对第三方音视频解码器进行支持,Flash还是不行的,在这一点上Microsoft比Adobe采取了更开放的态度,呵呵。

http://tirania.org/blog/archive/2009/Mar-23-1.html

家园 从技术指标看

从技术指标看,貌似SilverLight至少不比Adobe Flash差。

家园 【原创】【14】AJAX适合手机吗?

【14】AJAX 适合手机吗?

有人问,“为什么要长篇累牍地讨论Palm WebOS?这个系列写到现在,并没有明确地指出Palm WebOS好在什么地方”。这个问题问得好。Palm WebOS的价值在于提出了若干值得深思的问题,至于Palm WebOS的解决方案,却具有很大争议。

Palm WebOS首先提出的问题是,手机OS是否应当有别于PC OS?对于这个问题,笔者认为手机OS的设计的确应当有别于PC OS的设计。原因并不在于手机的CPU处理能力比PC的CPU弱,并不在于Memory和Disk空间比PC的小。虽然从目前看,手机在 CPU,Memory和Disk方面的确与PC存在差距,但是这个差距正在很快缩小。手机的问题来自三个方面,

1. 电池寿命,导致手机不能像PC那样持续地高负荷地工作。即便手机的CPU很强大,也只适合短时间内高强度地工作,而不能打持久战。

2. 不能假设手机一直在线,即便3G和LTE全面普及以后,这个局面也不会改变。3G和LTE全面普及,导致的是带宽的增加,而不能保障无线网络的永久畅通。

3. 手机输入不便,以及显示屏尺寸小,导致用户行为不同于PC。PC便于阅读大量文字信息,也便于输入大量文字信息,也支持生成复杂的图像。但是手机不适合大量的文字阅读,更不要说输入大量文字。手机展示的内容应当是图像多于文字。手机更适合信息的消费,而不是信息的生成,除非信息的生成是通过摄影摄像和录音这两种途径。

针对这三个特点,手机OS的设计或许需要强调三个方面。

1. 手机OS的设计,应当与云计算平台做一体化考虑,而不是设计一个支持手机独立工作的OS。把数据量大计算量大的逻辑,分配给云计算平台处理。然后把半成品发送给手机,手机做简单的最后处理以后,呈现给用户。这就是大纵深的前店后厂模式。这样做的好处,是最大限度地减少手机电池的消耗。

2. 手机OS的文件系统的设计,难点在于当无线网络时有时无的情况下,如何保证手机文件系统与云计算文件系统最大限度地同步,同时最小限度地占用无线网络带宽。不仅数据需要同步,而且手机装载的应用程序的版本也需要与云计算平台相应业务逻辑的版本保持一致。

3. 如何简化应用程序的开发,尤其是简化以图像为主的UI工作流程的开发。

Palm WebOS是如何解决这三个方面问题的呢?到目前为止,我们只分析了第三个方面,如何简化以图像为主的UI工作流程的开发。第一个和第二个方面,我们在后续章节中逐个讨论。

为了达到简化UI工作流程这个目标,Palm WebOS的解决方案是让手机应用的开发,尽可能逼近Web的开发。换句话说,手机应用开发商,以Ajax为基本工具,即HTML/XML + CSS + JavaScript三驾马车,实现UI工作流程以及业务处理逻辑。基于Ajax的应用程序下载到手机上并开始运行时,UI的渲染由WebKit Rendering Engine处理,业务逻辑的处理由JavaScript Engine负责。

猛一看,觉得似乎有理。用Ajax为工具进行Web开发的工程师为数众多。他们不需要做技术转型就可以为手机开发应用程序。但是仔细想一想,有一些问题需要进一步梳理。

点看全图

外链图片需谨慎,可能会被源头改

Figure 1. Google map UI workflow for Android

Courtesy http://farm4.static.flickr.com/3554/3385778443_b90139f91c_o.jpg

Web页面以HTML/XML为格式,HTML/XML格式的意义在于规定了网页内容的结构。结构的重要性体现在两个方面,

1. 有了结构就可以区别各段内容的性质,哪些是标题,哪些是正文,哪些是图片,哪些是链接。另外再用CSS(Cascading Style Sheets),来规定各段不同性质的内容的渲染风格,譬如标题的字体,大小和颜色,表格的宽度,表格框的宽窄和风格,视频界面的大小,音量等等。

2. 通过JavaScript对页面进行部分修改,并重新渲染修改过的那一部分时,内部操作是修改相应的XML DOM tree,然后渲染相应的子树,而不需要重新生成整个DOM Tree,不需要重新渲染整个页面。

Figure 1 显示的是Google Android 手机地图应用的部分页面截图,从中可以感悟到手机应用UI工作流程的两个特点,1. 每个单幅页面的结构并不复杂,2. 工作流程包括多幅页面。

HTML/XML + CSS + JavaScript专注于定义单幅页面的结构和渲染风格,但是并没有充分关注多幅页面组成的工作流程的结构和渲染风格。有没有必要重新定义一套专门供手机应用使用的类似与HTML/XML + CSS那样的结构化语言?

工作流程的结构大体包括三个方面,1. 明确页面与页面之间的前后顺序,2. 登记不同页面共享的构件,仔细看Google 手机地图的截图,虽然整个工作流程包括很多页面,但是很多页面共用同一幅地图作为底图。所谓共享的构件,不仅包括文字和图片,也包括代码,例如日期选择或者树展那样的,HTML,CSS和JavaScript的部分组合)3. 状态机(state machine),譬如当用户在某一页面放大了地图,后续页面里的地图底图也应当随之放大。状态机的功能在于记忆用户行为的历史和现状,以及根据现状决定未来流程。

HTML/XML + CSS + JavaScript是否可以用来定义手机本地工作流程,而不是WEB网页+WEB服务器的工作流程?如果不考虑运行效率,基本上是可以满足需要的。1. 页面与页面之间的前后顺序可以通过HTML里面HREF实现。2. 共享的构件可以单独存放,当页面引用这些共享构件时,用诸如IMG之类的TAG来实现。3. 状态机可以通过JavaScript来实现。

虽然HTML/XML + CSS + JavaScript基本可以满足定义工作流程的结构的需求,但是并不意味着这是最优解决方案,实际上,三驾马车如果原封不动地照搬到手机上去,虽然能工作,但是CPU消耗高,占用内存大,工作环节多,总之,效率不高。原因出在XML DOM Tree 和 JavaScript。

所以,一个比较激进的观点是,的确有必要另起炉灶,重新制订一套专供手机应用使用的三驾马车,这三驾马车虽然脱胎于HTML/XML + CSS + JavaScript,但是与后者有显著不同。同时,WebKit也不能原封不动地照搬到手机上去,有必要另起炉灶,重新设计一个专供手机应用使用的 Rendering Engine。当然,所谓有必要,确切地说,是技术上有必要重起炉灶,但是商务上是否合算,传统的惯性是否允许,是另一个问题。

关键词(Tags): #硅谷评论

本帖一共被 1 帖 引用 (帖内工具实现)
家园 一花双宝……

恭喜:你意外获得【通宝】一枚

谢谢:作者意外获得【通宝】一枚

家园 这个不是AJAX特有的问题

任何需要在手机上运行的web应用,都有这个问题,flash也不例外。

重启炉灶的风险很大,一来那么多应用要重写,这个不是任何一家公司敢于承受的;二来电池的发展也很快,很可能新标准还没流行,电池容量就赶上了。

前店后厂的方式固然有其优势,但是响应速度也是不可忽略的,用户宁可用一个使用时间只有半天的smart phone,也不会去用一个很慢,还要随时依赖网络连接的smart phone。把合适的计算和数据放在合适的地方,很重要。

我个人对电池容量不是很担心,主要是电池容量这块的投入很大,发展很快。如果容量真的成了瓶颈,或许用云生成某种手机可以高效执行的中间格式是个方向。

btw,手机可以生成的数据输入远非照片和视频。

家园 花,很有启发性

不过关于文中工作流程的结构的需求,现在业界不是这么干的。

HTML/XML + CSS + JavaScript基本可以满足定义工作流程的结构的需求。1. 页面与页面之间的前后顺序可以通过HTML里面HREF实现,加上JavaScript来控制在不同状态下,谁是后续的页面。2. 共享的构件,可以单独存放,当页面引用这些共享构件时,用诸如IMG之类的tag来实现。3. 状态机可以通过JavaScript来实现。http://www.ccthere.com/article/2098571

一般来说,大家现在认可的web开发的最佳实践并不是由三驾马车包办工作流程,而是MVC的架构,就客户端而言,处理的是视图的渲染工作,而关于模型和控制器的分工,尽管现在还有争执,比如业务逻辑究竟应该放在模型层还是控制器层,但是这两部分的工作地点应该是在服务器端是没有异议的,大家都认可客户端不应该负担更多的计算工作。

具体到老邓提到的那三点,现在大伙儿的玩儿法是:

首先,后续页面的问题:后续页面用超链体现,超链的目标由服务器端根据客户端操作状态决定,而不是由js的计算结果决定。

其次,状态机:js在操作状态上确实有工作要做,操作状态的传递有URL参数,cookie,session三种方法,url参数(get)对应小于254个字符长度的短参数传递,比如google的搜索查询关键字传递,url参数(post)一般应用于应用程序类型的参数提交,比如注册,登录,填写订单;cookie存储在客户端,用来表述用户的状态,比如google分析大量使用了cookie存储用户数据;session则完全是服务器端维护,在服务器端,可以存储在db中,也可以表现成file形式,也可以放在内存里面。

因为http协议的无状态特点,用户状态的传递必须分门别类的使用这三种方式实现,实事求是的说,现有的解决方案并不令人满意,比如网站大了,需要水平延展了,那麻烦就来了,无共享架构说起来就是五个字,实现起来,在参数传递方面就会遇到比较大的问题,这是不少架构师安身立命的本钱,也是羽羊到处忽悠赚取不义之财的路子

js在计算方面的低效是个头疼的事情,所以js在状态传递的工作中,一般现在倾向于仅仅让他作获取、发送(存储)两项工作,而不是完整的实现状态机,响应事件的活儿js干了,然后把当前状态扔给服务器,事件对应的节点处理函数以及终态判断的事儿由服务器端撑着,不劳js费神,服务器处理完了传给客户端,再次渲染页面,然后打完收工。当然,现在的web应用越来越复杂,比如googlemap,js的工作也愈加繁重,ajax的短板就在js上,各种浏览器都在js解释器方面做出努力就可见一斑。

最后,关于共享组件,老邓的文章一笔带过,我还没看的太明白,如果指的是图片,js代码,或者css代码之类的(比较复杂的例如日期选择或者treeview那样的可以看作图片、html和css的组合),那么存储和复用的工作是浏览器来做的,这一块展开说,缓存什么?何时过期,又得是一大篇,webkit的代码里头,这一块好像就挺复杂的,当然webkit的代码我看的不深,半瓶子水,就不多扯了,所以共享组件说错了大伙尽管拍砖。也请老邓指正。

上面拉拉杂杂扯这么多,都是web开发行里头的事情,webOS肯定和现在的web开发有不同,这一点同意老邓的看法,palm用三驾马车的路子,肯定对与现在web程序员是个巨大的吸引力,不过我也觉得这就好像vb->vb.net的过渡一样,看起来很美,因为web加上OS之后,就我看至少有如下几个方面超出了传统web开发的论域。

1、离线应用,仅仅从省电来说,同样性质功能的在线应用应该拼不过离线应用,信号的发射和接收是耗电大户。更极端一点说,internet掉线了,我连个通讯录就查不了了?另外还有个离线应用对应的本地数据存储问题,html5标准倒是有这一说,但是,就凭w3c?肯定赶不上pre的进度。

2、本地硬件的控制以及相关的安全问题,之前说过,需要点亮键盘灯怎么办?三驾马车做不到。

综上,web开发走到今天,基本上是飘在天上的级别,和本地没啥大关系,如果想要在pre上应用,那么就必须解决好落地的问题。对palm来说,铁了心用三驾马车,那么落地的问题就非常有看点,拭目以待,对于传统的web开发人员来说,这些都超出了他们传统的技术领域,palm给出的方案在学习难度上的把握直接决定了未来开发人员群落的规模,对于一个新的平台,这足够成为决定生死的重要原因了(想了想,还是加上之一吧

全看树展主题 · 分页首页 上页
/ 40
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河