<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://www.cellopoint.com/cn" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>Newest Blogs on Cellopoint</title>
 <link>http://www.cellopoint.com/cn/rss/blogs</link>
 <description>RSS for Blogs</description>
 <language>zh-hans</language>
<item>
 <title>使用 Facebook 登入并取得个人信息</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/11/fb</link>
 <description>&lt;p&gt;&lt;style type=&quot;text/css&quot;&gt;&lt;!--
.c1 {background: #FFCC66;}
.c2 {background: #CCFF99;}
.c3 {background: #99CCFF;}
--&gt;&lt;/style&gt;&lt;/p&gt;
&lt;p&gt;facebook，简称 fb，一个社群网络服务网站。许多网站结合了 fb， 来做营销活动，或是快速新增会员人数。如何将自家的网站与 fb 结合，以下做个简单的范例 ，让新加入的会员，可以使用fb的登入，就可以登入自家网站，并取得会员资料。&lt;br /&gt;
1.API 选择：&lt;br /&gt;
fb官方提供的 API，网页部份有 javascript、php，手机部份则有 iOS、Android，但由于 fb 好吃新奇又好玩 ，所以，其它语言也各自开发相关的api，如 silverlight、flash、.net、java 等，而本次则是选用 javascript 做为范例。&lt;br /&gt;
2.事前准备：&lt;br /&gt;
2.1.申请 fb 账号。&lt;br /&gt;
2.2.申请成为开发者人员，如何申请可参考如下网址&lt;br /&gt;
http://sofree.cc/fb-app-1/&lt;br /&gt;
3.开工&lt;br /&gt;
3.1.完成上述 2，进入新建立的应用程序，依序取得 App ID 与 App Secret ，如下图红框处，并设定相关数据，如下图蓝框处，本次的测试网站为me.cellopoint.com，故 App 网域与网站地址，分别填入 me.cellopoint.com 与http://me.cellopoint.com，设定好之后，按下储存钮&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/tw/files/image/blogs/fb_001.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;3.2.在 me.cellopoint.com 目录下，新增 channel.html 与 index.html 两个档案，首先开启 channel.html，里头只需加入一段 javascript code&lt;br /&gt;
&amp;lt;script src=&amp;quot;//connect.facebook.net/en_US/all.js&amp;quot;&gt;&amp;lt;/script&gt;&lt;br /&gt;
3.3.开启 index.html，贴上如下的 code，并做红框处的修改，需注意的是javascript code 必须贴于 &amp;lt;body&gt; 标签内。&lt;br /&gt;
&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD HTML 4.01 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/loose.dtd&amp;quot;&gt;&lt;br /&gt;
&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;br /&gt;
xmlns:fb=&amp;quot;http://www.facebook.com/2008/fbml&amp;quot;&gt;&lt;br /&gt;
&amp;lt;head&gt;&lt;br /&gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=UTF-8&amp;quot;&gt;&lt;br /&gt;
&amp;lt;title&gt;Login&amp;lt;/title&gt;&lt;br /&gt;
&amp;lt;/head&gt;&lt;br /&gt;
&amp;lt;body&gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;fb-root&amp;quot;&gt;&amp;lt;/div&gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;//connect.facebook.net/en_US/all.js&amp;quot;&gt;&amp;lt;/script&gt;&lt;br /&gt;
&amp;lt;script&gt;&lt;br /&gt;
window.fbAsyncInit = function() {&lt;br /&gt;
FB.init({&lt;br /&gt;
&lt;span class=&quot;c1&quot;&gt;appId      : &#039;xxxxxxxxxxx&#039;, // App ID，请输入 3.1 所又得的 App ID&lt;br /&gt;
channelURL : &#039;//me.cellopoint.com/channel.html&#039;, // 请输入 3.2 所新增的 channel.html 网址&lt;/span&gt;&lt;br /&gt;
status     : true, // check login status&lt;br /&gt;
cookie     : true, // enable cookies to allow the server to access the session&lt;br /&gt;
oauth      : true, // enable OAuth 2.0&lt;br /&gt;
xfbml      : true  // parse XFBML&lt;br /&gt;
});&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/script&gt;&lt;br /&gt;
&amp;lt;/body&gt;&lt;br /&gt;
&amp;lt;/html&gt;&lt;br /&gt;
3.4.登入并取得会员资料&lt;br /&gt;
新增如下 javascript code，说明如下&lt;br /&gt;
a.userID：为个人在 fb 的 id 值，取得如下红框处，如果个人网站利用fb登入，可以此判别会员。&lt;br /&gt;
b.如欲取得 email，则需设定如下绿框处&lt;br /&gt;
c.取得 name 与 email，使用 FB.api 的 me，如下蓝框处&lt;br /&gt;
function FBLogin(){&lt;br /&gt;
FB.login(function(response) {	  &lt;br /&gt;
if (response.authResponse) {&lt;br /&gt;
alert(&#039;登入成功&#039;);&lt;br /&gt;
&lt;span class=&quot;c1&quot;&gt;alert(&#039;UserID&#039; + response.authResponse.userID);&lt;/span&gt;&lt;br /&gt;
FB.api(&lt;span class=&quot;c3&quot;&gt;&#039;/me&#039;&lt;/span&gt;, function(response) {&lt;br /&gt;
alert(&#039;UserName&#039; + response.name);&lt;br /&gt;
alert(&#039;UserEmail&#039; + response.email);&lt;br /&gt;
});&lt;br /&gt;
} else {&lt;br /&gt;
alert(&#039;登入失败&#039;);&lt;br /&gt;
}&lt;br /&gt;
}, {&lt;span class=&quot;c2&quot;&gt;scope: &#039;email&#039;&lt;/span&gt;});&lt;br /&gt;
}&lt;br /&gt;
3.5.注销：新增如下 javascript code&lt;br /&gt;
function FBLoginOut(){&lt;br /&gt;
FB.logout(function(response) {&lt;br /&gt;
alert(&#039;Logged out.&#039;);&lt;br /&gt;
});&lt;br /&gt;
}&lt;br /&gt;
4.如果要移除掉该应用程序，于个人的 fb 页面的应用程序选项，找到该应用程序并移除掉即可。&lt;br /&gt;
5.以上参考出处自如下网址&lt;br /&gt;
&lt;a href=&quot;http://developers.facebook.com/docs/reference/javascript/&quot;&gt; http://developers.facebook.com/docs/reference/javascript/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/11/fb&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Wed, 09 Nov 2011 18:25:00 +0800</pubDate>
 <dc:creator>Hank Chen</dc:creator>
 <guid isPermaLink="false">380 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>Libgtop</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/10/libgtop</link>
 <description>&lt;p&gt;如何写一只程序来判断这只程序在执行阶段所占用的 linux 系统资源，例如 CPU 和内存使用率呢? 可以去查看系统中的 /proc/&amp;lt;process id&amp;gt;/stat，或是藉由系统 shell 的 top 指令，但是这两者都必须花费额外的功夫去分析档案或接口中的数据。在这边介绍一个 c 语言的开源函式库: libgtop，可以帮助我们获取系统或特定线程所占用的资源量。&lt;/p&gt;
&lt;p&gt;libgtop 是 GNOME 计划中的一个函式库，用来实现 GNOME 桌面环境中的&amp;rdquo;top&amp;rdquo;功能。它依赖于另一个GNOME 的函式库 glib。目前最新的版本是 2.28，在安装前必须先安装 glib 2.6.0 以上版本 以及 intltool 0.35.0 以上版本。&lt;/p&gt;
&lt;p&gt;一般来说，CPU 的使用率，是根据 CPU 花费在各种不同模式的时间所计算的。这些时间通常可分为 user mode, nice mode, system(kernel) mode 和 idle mode，而使用 libgtop 的 API 可以获取系统 boot 到目前为止，各种 mode 所占用的时间 (clock click 次数)。举例而言，可以利用下面的程序代码来计算出系统 CPU 的使用率:&lt;br /&gt;
#include &amp;lt;glibtop&amp;gt;&lt;br /&gt;
#include &amp;lt;glibtop/cpu.h&amp;gt;&lt;br /&gt;
double cpu_rate;&lt;br /&gt;
int dt, du, dn, ds;&lt;br /&gt;
glibtop_cpu cpu_begin,cpu_end;&lt;br /&gt;
glibtop_get_cpu(&amp;amp;cpu_begin);&lt;br /&gt;
sleep(1);&lt;br /&gt;
glibtop_get_cpu(&amp;amp;cpu_end);&lt;br /&gt;
dt = cpu_end.total - cpu.begin.total;&lt;br /&gt;
du = cpu_end.user - cpu.begin.user;&lt;br /&gt;
dn = cpu_end.nice - cpu.begin.nice;&lt;br /&gt;
ds = cpu_end.sys - cpu.begin.sys;&lt;br /&gt;
cpu_rate = 100.0 * (du+dn+ds) / dt&lt;/p&gt;
&lt;p&gt;注意 CPU 使用率的计算必须根据两个时间点的 click 次数的差，所以必须截取两次这个信息后再相减。而 memory 的观测就比较单纯，可以一次获得。例如:&lt;br /&gt;
#include &amp;lt;glibtop&amp;gt;&lt;br /&gt;
#include &amp;lt;glibtop/mem.h&amp;gt;&lt;br /&gt;
double mem_rate;&lt;br /&gt;
glibtop_mem memory;&lt;br /&gt;
glibtop_get_mem(&amp;amp;memory);&lt;br /&gt;
mem_rate = 100.0 * memory.used / memory.total;&lt;/p&gt;
&lt;p&gt;libgtop 可以观测的资源种类相当多，除了上例中介绍的系统 CPU 和内存以外，还包括特定线程的 CPU 和内存、swap、档案系统、网络接口等等。详细的 API 及数据结构可以参考 GNOME 的官方网站： &lt;a href=&quot;http://developer.gnome.org/libgtop/ &quot;&gt;http://developer.gnome.org/libgtop/&lt;/a&gt; &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/10/libgtop&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Mon, 03 Oct 2011 11:10:50 +0800</pubDate>
 <dc:creator>David Lee</dc:creator>
 <guid isPermaLink="false">379 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>Google File System 介绍</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/08/gfs</link>
 <description>&lt;p&gt;Google 之所以能独霸搜寻引擎市场，一方面是依靠 PageRank 技术所提供的优良搜寻排序，另一方面则仰赖其文件存储系统的优良效率。Google 设计了一套独特的分布式档案系统以满足其庞大的储存需求，也就是所谓的 Google File System (简称 GFS)。Google 并没有将 GFS 当做开源软件释出，不过还是公布了一些技术细节，包含一篇官方论文。&lt;/p&gt;
&lt;p&gt;与传统的分布式档案系统相比，GFS 有两个主要的不同点。首先，设备的失效被视为正常的现象而非意外。所谓的失效包括了应用程序的错误、操作系统的错误、人为操作的错误、乃至于硬件或网络的问题。既然连昂贵的硬盘设备也不可能百分之百排除发生错误的可能性，Google 干脆使用多个廉价的磁盘驱动器来组成他们的存储设备。而为了对抗设备的失效，GFS 包含了监视、错误侦测、容错以及自动修复的机制。&lt;/p&gt;
&lt;p&gt;其次，数据大多只会被追加到文件的末端，鲜少会修改或删除原本存在的档案。已写入的数据通常只需要可读 (readable) 不需要可写 (writable)，而且通常是按照顺序且大规模的读取，一次操作便可能读取数百 KB 甚至 MB 以上的数据。要特别注意到的是，GFS 预期所保存的档案通常都是数百 MB 甚至 GB 以上的文件，小型的文件会被支持但不会被优化。&lt;/p&gt;
&lt;p&gt;GFS 处理客户端所下要求的方式是采类似 supernode (Master) 与分布式结点 (Chunkserver) 的架构。真正的数据数据储存在 Chunkserver 上，并且定期将其状态报告给Master。当客户端需要读取某个档案时，要先向Master发出要求，Master 会考虑 Chunkserver 是否为闲置状态，若为闲置则将Chunkserver的位置回报给client，于是client就可以对 Chunkserver 中的档案进行操作。&lt;/p&gt;
&lt;p&gt;GFS支持了必需提供超大文件量与超大流量的 Google 搜寻引擎服务，同时建构于 GFS 之上的 BigTable 数据库技术也是 Gmail、Google Maps、Youtube 乃至于其它许多 Google 应用软件或云服务的基础，可以说是云时代的杀手级技术。&lt;/p&gt;
&lt;p&gt;碍于篇幅，更多的 GFS 细节可以参考: &lt;a href=&quot;http://labs.google.com/papers/gfs.html&quot;&gt;http://labs.google.com/papers/gfs.html&lt;/a&gt; &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/08/gfs&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Tue, 02 Aug 2011 10:38:42 +0800</pubDate>
 <dc:creator>David Lee</dc:creator>
 <guid isPermaLink="false">376 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>PHP 函数实作 Semaphore</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/07/php</link>
 <description>&lt;p&gt;Semaphore 是一个可变或抽象的数据型态，在并行计算环境中，若有多个行程对一个共享资源，将可提供简单有用的控制存取。&lt;/p&gt;
&lt;p&gt;可以把 semaphore 想成是一个记录，有多少单位的特殊资源是可使用的，加上操作安全地(即没有&amp;nbsp;race conditions)调整那个纪录，且那是有需要等待的直到一个单位的资源变得可使用。&lt;/p&gt;
&lt;p&gt;Semaphore是有用的工具来预防竞态条件和死锁; 然而，他们的用途绝不是保证程序可以从这些问题中解脱。资源允许任意数量的 semaphore 叫 counting semaphores；值只有 1 或 0 的 semaphore (或 locked/unlocked、unavailable/available)称 binary semaphores。&lt;/p&gt;
&lt;p&gt;下面为 PHP 的 semaphore 函数&lt;br /&gt;
int ftok (string $pathname, string $proj) &amp;ndash; 将可存取的路径和方案编号转换成 System V 可存取的 IPC key。&lt;/p&gt;
&lt;p&gt;bool sem_acquire (resource $sem_identifier) - 向信号机要求，信号机会减少一个资源数，并进入临界区。&lt;/p&gt;
&lt;p&gt;resource sem_get (int $key [, int $max_acquire = 1 [, int $perm = 0666 [, int $auto_release = 1 ]]]) - 取得一个新的信号机。&lt;/p&gt;
&lt;p&gt;bool sem_release (resource $sem_identifier) - 向信号机通知释放一个资源数，并离开临界区。&lt;/p&gt;
&lt;p&gt;bool sem_remove (resource $sem_identifier) - 移除一个信号机。&lt;/p&gt;
&lt;p&gt;resource shm_attach (int $key [, int $memsize [, int $perm ]]) - 回传一个可以存取 system V 共享内存的编号。&lt;/p&gt;
&lt;p&gt;bool shm_detach (resource $shm_identifier) - 中止对共享内存的链接。&lt;/p&gt;
&lt;p&gt;mixed shm_get_var (resource $shm_identifier, int $variable_key) - 取得共享内存中指定的变量值。&lt;br /&gt;
&lt;br /&gt;
bool shm_has_var (resource $shm_identifier, int $variable_key) - 检查共享内存里是否存在该键值。&lt;/p&gt;
&lt;p&gt;bool shm_put_var (resource $shm_identifier, int $variable_key, mixed $variable) - 增加或修改共享内存中的变量值。&lt;/p&gt;
&lt;p&gt;bool shm_remove_var (resource $shm_identifier, int $variable_key) - 移除指定的变量名称。&lt;/p&gt;
&lt;p&gt;bool shm_remove (resource $shm_identifier) &amp;ndash; 移除共享内存。 &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/07/php&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Fri, 15 Jul 2011 19:12:17 +0800</pubDate>
 <dc:creator>Ruby Lin</dc:creator>
 <guid isPermaLink="false">375 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>GNU libextractor</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/07/GNU</link>
 <description>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;GNU libextractor是一个种用来从 file 中提取 meta data 的 library。他的设计为以辅助链接库的方式来执行提取文件实际内容，Meta data 格式的数据有下列 (mime type, image dimensions, color depth, recording frequency)，GNU libextractor 主要是被我们用来提取 meta data 之用。目前，GNU libextractor 支持以下格式：HTML, PDF, PS, OLE2 (DOC, XLS, PPT), OpenOffice (sxw), StarOffice (sdw), DVI, MAN, FLAC, MP3 (ID3v1 and ID3v2), NSF(E) (NES music), SID (C64 music), OGG, WAV, EXIV2, JPEG, GIF, PNG, TIFF, DEB, RPM, TAR(.GZ), ZIP, ELF, S3M (Scream Tracker 3), XM (eXtended Module), IT (Impulse Tracker), FLV, REAL, RIFF (AVI), MPEG, QT and ASF. 此外，还有各种额外的 MIME 类型检测。&lt;/p&gt;
&lt;p&gt;GNU libextractor 是免费软件，可以下载下来修改以及发布。&lt;br /&gt;
GNU libextractor 使用 plugin 来处理各种文件格式。从技术上讲一个 plugin 可以支持多种文件格式，但大多数 plugin 只支持一个特定的格式。默认情况下，GNU libextractor 将使用所有在安装目录下发现的可用plugin。应用程序可以要求使用特定 plugin 或只有排除某些 plugin。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example for using dynamic library&lt;/strong&gt;&lt;/p&gt;
&lt;table width=&quot;350&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; align=&quot;center&quot;&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td class=&quot;rteleft&quot;&gt;// hello.c&lt;br /&gt;
            #include &amp;lt;extractor.h&amp;gt;&lt;br /&gt;
            int main()&lt;br /&gt;
            {&lt;br /&gt;
            struct EXTRACTOR_PluginList *el;&lt;br /&gt;
            el = EXTRACTOR_plugin_load_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);&lt;br /&gt;
            // ...&lt;br /&gt;
            EXTRACTOR_plugin_remove_all (el);&lt;br /&gt;
            return 0;&lt;br /&gt;
            }&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;执行以下指令 &lt;strong&gt;compile&lt;/strong&gt; &lt;br /&gt;
$ gcc \ -I/Library/Frameworks/Extractor.framework/Versions/Current/include \&lt;br /&gt;
-o hello hello.c \&lt;br /&gt;
-L/Library/Frameworks/Extractor.framework/Versions/Current/lib \&lt;br /&gt;
-lextractor&lt;/p&gt;
&lt;h3&gt;Plugin management&lt;/h3&gt;
&lt;p&gt;C Struct: EXTRACTOR_PluginList&lt;br /&gt;
&lt;span&gt;建立一组 plugin&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Function: void EXTRACTOR_plugin_remove_all (struct EXTRACTOR_PluginList *plugins)&lt;br /&gt;
&lt;span&gt;删除所有给定 plugin 列表&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Function: struct EXTRACTOR_PluginList * EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *plugins, const char*name)&lt;br /&gt;
&lt;span&gt;删除给定 plugin 列表例如 mime 中的 mpeg&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Function: struct EXTRACTOR_PluginList * EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *plugins, const char* name,const char* options, enum EXTRACTOR_Options flags)&lt;br /&gt;
&lt;span&gt;增加给定 plugin 列表&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Function: struct EXTRACTOR_PluginList * EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *plugins, const char* config, enum EXTRACTOR_Options flags)&lt;br /&gt;
&lt;span&gt;根据 config string load 或是 unload 或是修改已存在的列表&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Function: struct EXTRACTOR_PluginList * EXTRACTOR_plugin_add_defaults (enum EXTRACTOR_Options flags)&lt;br /&gt;
&lt;span&gt;加载所有在 plugin 数据夹下的预设 plugin 列表&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Example for a minimal extract method&lt;/h3&gt;
&lt;p&gt;以下范例告诉我们如何利用 plugin 解读出 MIME type&lt;/p&gt;
&lt;table width=&quot;350&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; align=&quot;center&quot;&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;
            &lt;p&gt;int&lt;br /&gt;
            EXTRACTOR_mymime_extract&lt;br /&gt;
            (const char *data,&lt;br /&gt;
            size_t data_size,&lt;br /&gt;
            EXTRACTOR_MetaDataProcessor proc,&lt;br /&gt;
            void *proc_cls,&lt;br /&gt;
            const char * options)&lt;br /&gt;
            {&lt;br /&gt;
            if (data_size &amp;lt; 4)&lt;br /&gt;
            return 0;&lt;br /&gt;
            if (0 != memcmp (data, &amp;quot;\177ELF&amp;quot;, 4))&lt;br /&gt;
            return 0;&lt;br /&gt;
            if (0 != proc (proc_cls, &lt;br /&gt;
            &amp;quot;mymime&amp;quot;,&lt;br /&gt;
            EXTRACTOR_METATYPE_MIMETYPE,&lt;br /&gt;
            EXTRACTOR_METAFORMAT_UTF8,&lt;br /&gt;
            &amp;quot;text/plain&amp;quot;,&lt;br /&gt;
            &amp;quot;application/x-executable&amp;quot;,&lt;br /&gt;
            1 + strlen(&amp;quot;application/x-executable&amp;quot;)))&lt;br /&gt;
            return 1;&lt;br /&gt;
            /* more calls to &#039;proc&#039; here as needed */&lt;br /&gt;
            return 0;&lt;br /&gt;
            }&lt;/p&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Internal utility functions&lt;/h3&gt;
&lt;p&gt;有些实用的内部开发 API &lt;br /&gt;
&amp;ldquo;convert_numeric.h&amp;rdquo; 定义了各种数字的转换功能（特别是转换为浮点数）。&lt;br /&gt;
&amp;ldquo;unzip.h&amp;rdquo; 定义了一个访问压缩文件的 API。&lt;br /&gt;
&amp;ldquo;pack.h&amp;rdquo; 可以把有 integer 的 struts 分解顺便也可以把 big/little endian 转成 host byte order。&lt;br /&gt;
&amp;ldquo;convert.h&amp;rdquo; 提供了一个函数进行所需之字符集转换。&lt;br /&gt;
Function: char * EXTRACTOR_common_convert_to_utf8 (const char *input, size_t len, const char * charset) 可以用来方便地从任何字符集转换为 UTF - 8 文本。&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;总之，对于讯息解析平凡的我们来说，GNU libextractor 不只帮助了我们找到档案的正确格式，还可以撰写各种 plugin 工具，分析各种文字格式，找到相对应的 MIME type。这对 email 这块领域而言，可说是不可或缺的一项工具。 &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/07/GNU&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Mon, 04 Jul 2011 14:18:34 +0800</pubDate>
 <dc:creator>Shawn Lin</dc:creator>
 <guid isPermaLink="false">372 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>What is memcache?</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/06/memcache</link>
 <description>&lt;p&gt;今天我要介绍一个对于存取数据库相当有用的技术 - Memcache.&lt;/p&gt;
&lt;p&gt;Memcache 是一种分布式内存快取系统，对于现在热门的云系统也是相当有用的。 它最基本的概念式用 key-based 的数据结构来存取数据到内存内部。 原先这个概念来自于 Brad Fitzpatrick，他最早用在一家叫做 LiveJournal.com(2003) 的公司，因为效果不错，而又加以发扬光大。 现在有更多的大公司有在用这项服务：LiveJournal、Wikipedia、Flickr、Twitter、Youtube、Digg、WordPress.com&amp;hellip;etc. 它的好处在，可以缩减大部分存取数据库的时间转而到存取内存上面，就算数据没有在内存上面对于要到后方存取数据库也是相当的容易设计。 虽然它有 key-based 快取还有分布式内存功能，但是对于存取限制这点必须由建构者自己决定。这项技术效果最好的地方当然就是把常用的数据写到内存内部，那么下次存取的时候就近乎不用等待时间。这概念有点像是当你上网的时候，网站会将网站大部分的图片数据先暂存到你计算机内，等你下次又再存取这个网站的时候，速度会大幅提升是一样道理。Memcache 也是用一样的概念，它拿你计算机的内存来加速存取，它可以拿整个网络的空闲内存来存取，让你可以在同一个网络架构下共同存取使用到， 另外一个特点就是你想要增加多少内存使用就可以增加多少(当然你需要充足的内存)，甚至它会将所有内存区块视为同一个内存，这就结合着前面所叙述着，网络上的内存只要你可以用你就可以将全体合并执行。而理论上它的设计这些行为应该都在 O(1) 可以完成。&lt;/p&gt;
&lt;p&gt;现在我来给一个简单的范例来叙说有 Memcache 使用上的差异 我们每天从一台计算机存取数据，如果我们想加入就会想要再加一台机器，但是要怎样才会有效率?&lt;/p&gt;
&lt;p class=&quot;rtecenter&quot;&gt;&lt;img width=&quot;500&quot; height=&quot;258&quot; alt=&quot;&quot; src=&quot;/cn/files/image/blogs/memcache.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;图片1，我们有两台机器两个分开的内存，为了确保两台数据相同不会有不一致情形发生，所以我们会让两台内存都存取一样的数据， 结果导致只是计算机 CPU 运作很快，但是内存没有有效率的使用，这种设置效率很差。&lt;/p&gt;
&lt;p&gt;图片2，我们有两台机器，但是透过 Memcache 来结合两边的内存，所以我们内存是共存使用的，不用担心不一致的情形， 而且空间还加倍使用，整个生活变得更美好了!!&lt;/p&gt;
&lt;p&gt;那我们到底该怎样使用 Memcache 比较好? 以目前较有意义的使用方式是，如果你的存取数据库充满着&amp;rdquo;SELECT * from XXX&amp;rdquo;， 表示你常常要所有的数据而且量不少，而且如果又是常常重复的数据，那你就可以使用Memcache使用的相当快乐。 这边给一个简单的分析，你如果要用 Memcache 必须要考虑几个要点：1. 搜寻的时间 2. 击中率 3. 档案存在时间，当然你需要花费额外的人力时间去写程序来增加这段效率，不过比较起结果，这算是常态时间 (Constant time) 的考虑吧?&lt;/p&gt;
&lt;p&gt;我再给予一个简单的流程来说明要如何建构你的系统跟 Memcache 还有数据库运作 假设你现在有很多台服务器，现在想要链接这几台服务器有更有效率的应用内存。 以下是一个简单的流程: 你的客户们来询问服务器数据，你的服务器一开始会先去询问 Memcache，如果数据不存在于 Memcache，这时候在去询问 Database，等到找到数据的时候，记得要将数据再写回去 Memcache，这就是一个简单的标准流程。系统刚开始跑 或许会有阵痛期，等只要时间久了，整体速度应该是向上提升才对。&lt;/p&gt;
&lt;p class=&quot;rtecenter&quot;&gt;&lt;img width=&quot;450&quot; height=&quot;529&quot; alt=&quot;&quot; src=&quot;/cn/files/image/blogs/flow.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;再上面的例子其实你可以看的出来 Memcache在实做上是一个网络的 daemon 大多数人会配合着 PHP或是 C/C++来跟 Memcache 沟通 我使用的 Linux 系统，如果你想要用 C/C++ 来建构，基本上你必须先安装几个程序：1. libevent 2.Memcache 3. libmemcache&lt;/p&gt;
&lt;p&gt;想要了解更详细的操作跟内容请参造 Memcache官网: http://memcached.org/ &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/06/memcache&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Thu, 23 Jun 2011 17:24:24 +0800</pubDate>
 <dc:creator>HH Tu</dc:creator>
 <guid isPermaLink="false">371 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>什么是 Node.js?</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/06/Node_js</link>
 <description>&lt;p&gt;传统上，JavaScript 只在网页浏览器执行，但由于 CommonJS 项目，最近已经有相当多的兴趣也把它拿到服务器端。其它服务器端 JavaScript 环境，包括 Jaxer 和 Narwhal。然而，Node.js 有点不同于这些解决方式，因为它是事件基础 (event-based) 而不是执行序基础(thread based)，像 Apache 这种被用来服务 PHP 和其它 CGI 语言的网页服务器是执行序基础，因为它们为每个近来的需求产生一个系统执行序。虽然这对很多应用程序是没问题，但执行序基础在很多诸如为了服务及时应用程序需要长久的 (long-lived) 联机，像 Friendfeed 或Google Wave，并没有很好地扩展。&lt;/p&gt;
&lt;p&gt;Node.js 使用事件循环取代执行序，且能够扩充到同时有上百万的联机，它利用服务器花最多的时间在等待读取与写入操作的事实，像从硬盘读取档案、存取额外的网页服务或等待档案上传完成，因为这些作业比内存作业慢很多。每个读取与写入操作在 Node.js 是非同期，意指当读取与写入操作发生时，服务器能够继续处理进来的需求。JavaScript 是非常适合事件基础的程序设计，因为它有匿名函数 (anonymous functions) 和封绝 (closure)，且 JavaScript 开发者已经知道如何以这种方式编程，这种事件基础模式让 Node.js 很快，且让扩充及时应用程序很容易。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://docs.pylonsproject.org/projects/pyramid/1.0/narr/introduction.html&quot;&gt;http://docs.pylonsproject.org/projects/pyramid/1.0/narr/introduction.html&lt;/a&gt; &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/06/Node_js&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Fri, 17 Jun 2011 10:33:48 +0800</pubDate>
 <dc:creator>Paul Chien</dc:creator>
 <guid isPermaLink="false">368 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>LDAP</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/06/LDAP</link>
 <description>&lt;p&gt;试想两个不同的问题：其一，一个上千人的庞大组织，拥有许多不同的部门与IT资源，要如何维护一个便于更新且组织成员们易于查询的在线通讯簿? 其二，一个必须同时维护多个不同系统(可能包含linux登入、apache、samba、mail service等等)的MIS人员，要如何维护多组不同的账号密码，甚至必须定期更新它们?  这两个问题看来毫不相干，可是都可以使用同一个方案来解决：LDAP (Lightweight Directory Access Protocol)。&lt;/p&gt;
&lt;p&gt;LDAP是一个参考在线目录服务(Directory Service)的协议，其经由X.500改造而来，省略了X.500许多繁琐的细节，成为了一个能够建构于IP网络上、弹性而方便的网络协议。对前文的问题一而言，LDAP充满弹性的设计让我们能够将组织资源整理成目录型式的数据库；而对于问题二而言，LDAP提供了一个标准化的接口供不同的应用程序参考，因而很容易整合多种不同应用服务的组态配置(configuration)。&lt;/p&gt;
&lt;p&gt;以宏观的角度来看，LDAP 将多笔数据以树状结构做存储，称为 DIT (Directory Information Tree)。整个 DIT 可以切割成许多子树，每个子树都可以储存在不同的 LDAP 服务器上，以达到分布式架构的目的。其中，每一笔数据都会有一个独一无二的 Distinguished Name (DN)，就像是一般档案系统中的「绝对路径」，用来标记这笔数据在 DIT 中的地址。&lt;/p&gt;
&lt;p&gt;以微观的角度来看，LDAP中每一笔数据都符合一种特殊的schema，并且可以转换成 LDIF (LDAP Data Interchange Format) 格式以便阅读 (注意实际上数据的储存方式可能是 binary的)。在 LDIF 格式中，每一笔数据都会拥有多个不同的「属性」，每种属性则会拥有一到多个不同的「值」。一笔数据可能拥有哪些属性，必须根据它所属的对象类别 (objectClass)。例如，类别为「员工」的数据可能会有「姓名」、「所属部门」、「邮件地址」等属性，而类别为「部门」的数据则可能有「主管」、「所属员工」等属性。其中，每一笔数据都一定会有 DN 和 objectClass 这两个属性，至于其它「应有」和「可有」的属性，则由其 objectClass 而定。&lt;/p&gt;
&lt;p&gt;要在 LDAP server 上查询数据时，可以把查询 (query) 包装成 LDAP URL 的格式:&lt;/p&gt;
&lt;p&gt;ldap://&amp;quot; [ &amp;lt;host&amp;gt; ]&amp;quot;/&amp;quot; &amp;lt;dn&amp;gt; [ &amp;quot;?&amp;quot; &amp;lt;attributes&amp;gt;[ &amp;quot;?&amp;quot; &amp;lt;scope&amp;gt; &amp;quot;?&amp;quot; &amp;lt;filter&amp;gt; ] ]&lt;br /&gt;
&amp;lt;host&amp;gt; ::= &amp;lt;hostname&amp;gt;[ &amp;quot;:&amp;quot; &amp;lt;port&amp;gt; ]					&lt;br /&gt;
&amp;lt;attributes&amp;gt; ::= NULL | &amp;lt;attributelist&amp;gt;		&lt;br /&gt;
&amp;lt;attributelist&amp;gt; ::= &amp;lt;attributetype&amp;gt;| &amp;lt;attributetype&amp;gt;[ &amp;quot;,&amp;quot; &amp;lt;attributelist&amp;gt; ]&lt;br /&gt;
&amp;lt;scope&amp;gt; ::= &amp;quot;base&amp;quot; | &amp;quot;one&amp;quot; | &amp;quot;sub&amp;quot;&lt;/p&gt;
&lt;p&gt;●	host: server的 IP 地址&lt;br /&gt;
●	dn: 搜寻起点的 dn&lt;br /&gt;
●	attributes: 希望回传的属性有哪些&lt;br /&gt;
●	scope: 搜寻的范围(单一节点、第一代的子节点、或是整个子树)&lt;br /&gt;
●	filter: 搜寻条件&lt;/p&gt;
&lt;p&gt;例如: ldap://cellopoint.com/ou=rd,ou=unit,ou=company,dc=cellopoint,dc=com?mail?sub?uid=david&lt;br /&gt;
会回传 cellopoint 公司中、rd 部门下、id 为 &amp;rdquo;david&amp;rdquo; 的员工的 email。&lt;/p&gt;
&lt;p&gt;目前最常被使用的两个 LDAP 软件为 openldap 和 Microsoft Active Directory。前者是 open source 的软件，对 LDAP 有兴趣者不妨测试看看，也许就会发现一些原本很繁琐的 MIS 工作顿时变得轻松不少喔！ &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/06/LDAP&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Thu, 09 Jun 2011 10:43:17 +0800</pubDate>
 <dc:creator>David Lee</dc:creator>
 <guid isPermaLink="false">369 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>Web Application Frameworks</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/05/Web_Application_Frameworks</link>
 <description>&lt;p&gt;&amp;nbsp;由于网络以及网络服务的使用率越来越大，网站在 Web 2.0 时代不再只支持静态内容。网站的内容已成为动态让使用者可以操作实时的工作，例如检查和发送邮件。我们的网络工程因为不断添加新功能让它的规模变的庞大和复杂。&lt;/p&gt;
&lt;p&gt;Web Application Frameworks 提供软件结构的模型，帮助我们分类和管理网络应用程序不同的组件。他们还提供一些有用的 libraries，例如：访问数据库，呈现模板和 session 管理。&lt;/p&gt;
&lt;p&gt;许多 Web Application Frameworks 使用 Model-View-Controller（MVC）的结构来定义网络应用程序逻辑上的组件。以下是 model，view 和 controller 的解释：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;br /&gt;
应用程序的 model 是用来处理系统的数据。换句话说，它包括数据和用来处理数据的函数。Controllers 和 views 会透过 model 获取和更改数据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;View &lt;/strong&gt;&lt;br /&gt;
View是呈现给使用者看到的应用程序组件，换句话说，使用者界面。使用者要使用这个接口与应用程序互动。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt; &lt;br /&gt;
Controller 是用来处理使用者的 request 并返回 response 给使用者。它会透过model获得所需要的数据，把数据准备成一个合适的格式，插入到 view 里和呈现 view 给使用者。&lt;/p&gt;
&lt;p&gt;一个典型的 request 到服务器的情况如下：使用者透过界面发送一个 request 到服务器。主 controller 会处理这个 request 将它委托给适当的 controller 和把控制传给这个 controller。被委托的 controller 会跟 model 互动来获取或更改数据，呈现 view，并将控制还给主 controller。主 controller 会返回呈现的 view。使用者与接口互动并发送新的请求时，这循环就会重复。&lt;/p&gt;
&lt;p&gt;References:&lt;br /&gt;
[1] Web application framework. (2011, May 28). In Wikipedia, The Free Encyclopedia. Retrieved 15:23, May 30, 2011, from http://en.wikipedia.org/w/index.php?title=Web_application_framework&amp;amp;oldid=431373642&lt;br /&gt;
[2] Model&amp;ndash;view&amp;ndash;controller. (2011, May 26). In Wikipedia, The Free Encyclopedia. Retrieved 17:12, May 30, 2011, from http://en.wikipedia.org/w/index.php?title=Model%E2%80%93view%E2%80%93controller&amp;amp;oldid=430946706 &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/05/Web_Application_Frameworks&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Tue, 31 May 2011 14:40:10 +0800</pubDate>
 <dc:creator>June Huang</dc:creator>
 <guid isPermaLink="false">366 at http://www.cellopoint.com/cn</guid>
</item>
<item>
 <title>Protocol Buffers (Google 专用的通讯协议)</title>
 <link>http://www.cellopoint.com/cn/media_resources/blogs/2011/05/Protocol_Buffers</link>
 <description>&lt;p&gt;&lt;strong&gt;&amp;nbsp;Introduction 简介&lt;/strong&gt;&lt;br /&gt;
Protocol buffers 是一个灵活的，高效的，有自动机制(可能指编解碼)工具用于序列化结构数据。&lt;br /&gt;
类似 XML，但是更小、更快、更简单。你定义你的结构化数据，然后就可以使用工具生成的特殊代码方便的使用各种语言 (c++ python java)&lt;br /&gt;
从各种数据流中读写你的结构化数据。你甚至可在不打断已经部署的程序的情况下重新更新你的数据结构（热部署）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why not just use XML? 为什么不使用XML?&lt;/strong&gt;&lt;br /&gt;
protocol buffer 有很多 XML 不具备的优点：&lt;br /&gt;
1.简单；&lt;br /&gt;
2.小巧：3-10倍&lt;br /&gt;
3.效率高：20-100倍&lt;br /&gt;
4.无双重义意&lt;br /&gt;
5.有自动工具生成&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do they work? 如何开始运作?&lt;/strong&gt;&lt;br /&gt;
你只需要安装 google 的 protocol buffer&lt;br /&gt;
编辑 .proto 檔&lt;br /&gt;
执行 protoc &amp;ndash;cpp_out=. 檔名&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;strong&gt;Example: 范例 1&lt;/strong&gt;&lt;br /&gt;
package tutorial;&lt;br /&gt;
message Person {&lt;br /&gt;
required string name = 1;&lt;br /&gt;
required int32 id = 2;&lt;br /&gt;
optional string email = 3;&lt;/p&gt;
&lt;p&gt;enum PhoneType {&lt;br /&gt;
MOBILE = 0;&lt;br /&gt;
HOME = 1;&lt;br /&gt;
WORK = 2;&lt;br /&gt;
}&lt;br /&gt;
message PhoneNumber {&lt;br /&gt;
required string number = 1;&lt;br /&gt;
optional PhoneType type = 2 [default = HOME];&lt;br /&gt;
}&lt;br /&gt;
repeated PhoneNumber phone = 4;&lt;br /&gt;
}&lt;br /&gt;
message AddressBook {&lt;br /&gt;
repeated Person person = 1;&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Three type 三种数据型态&lt;/strong&gt;&lt;br /&gt;
required：必须提供字段值，否则对应的 message 就会被认为是&amp;ldquo;未初始化的。&amp;ldquo;&lt;br /&gt;
optional：字段值指定与否都可以。如果没有指定一个可选的字段值，它就会使用默认值。&lt;br /&gt;
repeated：字段会重复 n 次（可以为 0）。重复的值的顺序将被保存在缓冲区中的协议。&lt;/p&gt;
&lt;p&gt;Required 是永久性的：在把一个字段标识为 Required 的时候，你应该特别小心。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Start working 开始&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这会产生以下文件&lt;br /&gt;
addressbook.pb.h：声明你生成的 class 的标头檔。&lt;br /&gt;
addressbook.pb.cc：你生成的 class 的实作档。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example: 范例 2&lt;/strong&gt;&lt;br /&gt;
Person person;&lt;br /&gt;
person.set_name(&amp;quot;John Doe&amp;quot;);&lt;br /&gt;
person.set_id(1234);&lt;br /&gt;
person.set_email(&amp;quot;jdoe@example.com&amp;quot;);&lt;br /&gt;
fstream output(&amp;quot;myfile&amp;quot;, ios::out | ios::binary);&lt;br /&gt;
person.SerializeToOstream(&amp;amp;output);&lt;/p&gt;
&lt;p&gt;fstream input(&amp;quot;myfile&amp;quot;, ios::in | ios::binary);&lt;br /&gt;
Person person;&lt;br /&gt;
person.ParseFromIstream(&amp;amp;input);&lt;br /&gt;
cout &amp;lt;&amp;lt; &amp;quot;Name: &amp;quot; &amp;lt;&amp;lt; person.name() &amp;lt;&amp;lt; endl;&lt;br /&gt;
cout &amp;lt;&amp;lt; &amp;quot;E-mail: &amp;quot; &amp;lt;&amp;lt; person.email() &amp;lt;&amp;lt; endl;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Entire message, including: 内部 API&lt;/strong&gt;&lt;br /&gt;
bool IsInitialized() const;：检查是否全部的 required 字段都被设置（set）了值。&lt;br /&gt;
string DebugString() const;：返回一个可读的讯息表示形式，对读取特别有用。&lt;br /&gt;
void CopyFrom(const Person&amp;amp; from);：用外部讯息的值，覆写调用者讯息内部的值。&lt;br /&gt;
void Clear();：将所有项回复到空状态（empty state）。&lt;br /&gt;
bool SerializeToString(string* output) const;：将消息序列化并储存在指定的字符串中。注意里面的内容是binary 的；我们只是使用字符串作为一个很方便的容器。&lt;br /&gt;
bool ParseFromString(const string&amp;amp; data);：从给定的 string 解析讯息。&lt;br /&gt;
bool SerializeToOstream(ostream* output) const;：将讯息写入到给定的 C++ ostream 中。&lt;br /&gt;
bool ParseFromIstream(istream* input);：从给定的 C++ istream 解析讯息。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://code.google.com/intl/zh-TW/apis/protocolbuffers/docs/overview.html&quot;&gt;http://code.google.com/intl/zh-TW/apis/protocolbuffers/docs/overview.html&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.cppprog.com/2010/0908/207_4.html&quot;&gt;http://www.cppprog.com/2010/0908/207_4.html&lt;/a&gt; &lt;span class=&#039;read-more&#039;&gt;&lt;a href=&quot;http://www.cellopoint.com/cn/media_resources/blogs/2011/05/Protocol_Buffers&quot;&gt;&amp;nbsp;read&amp;nbsp;more&amp;nbsp;&amp;raquo;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
 <pubDate>Thu, 19 May 2011 10:28:57 +0800</pubDate>
 <dc:creator>Shawn Lin</dc:creator>
 <guid isPermaLink="false">364 at http://www.cellopoint.com/cn</guid>
</item>
</channel>
</rss>

