﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-&lt;font size=6 color=red&gt;Heart for communicating&lt;/font&gt;-文章分类-reprinting</title><link>http://www.cppblog.com/gnupython/category/723.html</link><description>&lt;font  color=blue&gt;......酒干倘卖无！......&lt;/font&gt;
&lt;img src=http://services.nexodyne.com/email/icon/dcyohY1Q.RaZMinI0A%3D%3D/7.703%2BQ%3D/R01haWw%3D/0/image.png&gt;&lt;/img&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 21:13:46 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 21:13:46 GMT</pubDate><ttl>60</ttl><item><title>如何编译，配置ACE</title><link>http://www.cppblog.com/gnupython/articles/3450.html</link><dc:creator>heart in the world</dc:creator><author>heart in the world</author><pubDate>Thu, 23 Feb 2006 11:53:00 GMT</pubDate><guid>http://www.cppblog.com/gnupython/articles/3450.html</guid><wfw:comment>http://www.cppblog.com/gnupython/comments/3450.html</wfw:comment><comments>http://www.cppblog.com/gnupython/articles/3450.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gnupython/comments/commentRss/3450.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gnupython/services/trackbacks/3450.html</trackback:ping><description><![CDATA[<P>ACE是个很有用的开放源代码的C++网络编程开发包，利用它比直接用API更有利于代码的健壮性，可移植性，并相对简单。<BR>估计大家刚接触ACE时，都有一定难度，说不定就半途放弃了，这是我学ACE两天中的总结，基本上不成文，但我想研究到ACE的你一定会明白下文的意思。<BR><BR>一、ACE官方主页：<A href="http://www.cs.wustl.edu/~schmidt/ACE.html">http://www.cs.wustl.edu/~schmidt/ACE.html</A><BR>&nbsp;&nbsp;&nbsp; 下载地址：<A href="http://deuce.doc.wustl.edu/Download.html">http://deuce.doc.wustl.edu/Download.html</A><BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 我下载的是Latest Beta Kit中的ACE.zip（Latest Release中的压缩包好像有问题，我有WinRAR3.30解压缩报错）</P>
<P>二、解压缩后放在D盘<BR>&nbsp;&nbsp;&nbsp; D:\ACE_wrappers</P>
<P>三、在D:\ACE_wrappers\ace目录下新建文件config.h加入一行<BR>&nbsp;&nbsp;&nbsp; #include "ace/config-win32.h"<BR>&nbsp;&nbsp;&nbsp; <BR>四、编译：用VC6.0打开D:\ACE_wrappers\ace\ace.dsw<BR>&nbsp;&nbsp;&nbsp; 左侧显示&nbsp;&nbsp;&nbsp; ACE DLL classes<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE LIB classes<BR>&nbsp;&nbsp;&nbsp; 或1、从菜单上选择“编译”，“放置可远行配置”，选择你需要的工程配置<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; “编译”，“重建全部”（或任一，如ACE DLL - Win32 MFC Debug）<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此过程可能持续半小时至一个小时不等<BR>&nbsp;&nbsp;&nbsp; 或2、从菜单上选择“编译”，“批构建”，选择你需要的工程配置<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此过程可能持续二至四个钟头<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 产生的.lib文件位于D:\ACE_wrappers\ace\下，<BR>&nbsp;&nbsp;&nbsp; 产生的.dll文件位于D:\ACE_wrappers\bin\下<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 同样打开ace_static.dsw<BR>&nbsp;&nbsp;&nbsp; 编译<BR>&nbsp;&nbsp;&nbsp; ACEs.lib<BR>&nbsp;&nbsp;&nbsp; ACEsd.lib<BR>&nbsp;&nbsp;&nbsp; ACE_RMCasts.lib<BR>&nbsp;&nbsp;&nbsp; ACE_RMCastsd.lib<BR>&nbsp;&nbsp;&nbsp; TMCasts.lib<BR>&nbsp;&nbsp;&nbsp; TMCastsd.lib</P>
<P>&nbsp;&nbsp;&nbsp; ACE生成的dll和lib文件的命名规则：（d = debug，s&nbsp;= static）<BR><BR>&nbsp;&nbsp;&nbsp; debug - aced.lib、debug+static - acesd.lib、release - ace.lib、 release+static - aces.lib<BR><BR><BR>五、样例程序的编译<BR>&nbsp;&nbsp;&nbsp; 用VC打开D:\ACE_wrappers\tests\tests.dsw<BR>&nbsp;&nbsp;&nbsp; “编译”，“批构建”<BR>&nbsp;&nbsp;&nbsp; <BR>六、自写程序的工程配置<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 中篇：ACE程序员教程.pdf中的样例程序：<BR>&nbsp;&nbsp;&nbsp; 网址：<A href="http://www.cs.wustl.edu/~schmidt/ACE_wrappers/docs/tutorials/guide-tutorials.html">http://www.cs.wustl.edu/~schmidt/ACE_wrappers/docs/tutorials/guide-tutorials.html</A><BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 将网页上的原代码复制到一新建文件，并命名为server.cpp<BR>&nbsp;&nbsp;&nbsp; 用ＶＣ打开，编译，重建全部，弹出对话框，“This build command require ...“，点”是“<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 会出现以下错误<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 如果有“Cannot open include file: 'ace/SOCK_Acceptor.h': No such file or directory”<BR>&nbsp;&nbsp;&nbsp; 工程-设置-C/C++: Preprocessor,附加包含路径：D:/ACE_wrappers<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 如果有“ You must link against multi-threaded libraries when using ACE (check your project settings)”<BR>&nbsp;&nbsp;&nbsp; 工程-设置-C/C++: Code Generation - Use run-time library : Debug Multithreaded Dll<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 如果有“error C2065: 'ACE_ERROR' : undeclared identifier”<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error C2065: 'ACE_DEBUG' : undeclared identifier<BR>&nbsp;&nbsp;&nbsp; #include "ace/Log_Msg.h"</P>
<P>&nbsp;&nbsp;&nbsp; error C4716: 'ace_main_i' : must return a value<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在main中加入<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; “error LNK2001: unresolved external symbol "__declspec(dllimport) int __cdecl”<BR>&nbsp;&nbsp;&nbsp; 工程-设置-Link-Input: 对象/库模块：添加aced.lib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 附加库路径：D:\ACE_wrappers\ace<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 编译client中遇到的问题<BR>&nbsp;&nbsp;&nbsp; 1、error C2039: 'sprintf' : is not a member of 'ACE_OS'<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include "ace/OS_NS_stdio.h"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 2、error C2039: 'strlen' : is not a member of 'ACE_OS'<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include "ace/OS_NS_string.h"<BR>&nbsp;&nbsp;&nbsp; 3、error C2059: syntax error : '?'<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 错误在这一句：&nbsp; ACE_DEBUG((LM_DEBUG,?Usage egX &lt;hostname&gt; &lt;port_number&gt;\n?)); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将?改为"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 4、无法找到动态链接库aced.dll于指定的路径<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为系统变量PATH加上D:\ACE_wrappers\bin<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp; 静态包含：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 工程-设置-C/C++-预处理程序定义中加入 ,ACE_AS_STATIC_LIBS<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>例１server编译后生成<BR>&nbsp;&nbsp;&nbsp; server.exe 16K&nbsp; serverd.exe 97K&nbsp;&nbsp;&nbsp;&nbsp; servers.exe 124K serversd.exe 669K<BR>&nbsp;&nbsp;&nbsp; （servers.exe较适合发布）<BR>&nbsp;&nbsp;&nbsp; <BR>例2 client编译后生成<BR>&nbsp;&nbsp;&nbsp; client.exe 16K&nbsp; clientd.exe 97K&nbsp;&nbsp;&nbsp;&nbsp; clients.exe 124K clientsd.exe 669K<BR>&nbsp;&nbsp; （clients.exe较适合发布）<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 测试 clients 127.0.0.1 1919<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servers 1919<BR><BR><BR>下面是马维达老师写的：(转自huihoo)<BR><BR>
<TABLE cellSpacing=1 cellPadding=6 width="100%" border=0>
<TBODY>
<TR bgColor=#dededf>
<TD class=tablerow vAlign=top>发表于： 3/31/2003 - 04:24</TD></TR>
<TR bgColor=#dededf>
<TD vAlign=top height=120>翻译的一点小东西，希望能对大家有帮助。<BR>其实也不敢称为是翻译的，水平太烂了，大家将就着看吧 ：）<BR><BR>使用Microsoft Visual C++ 在win32平台上生成和安装ACE：<BR><BR>注意：关于MSVC5.0和Service Pack 3的使用有一些问题，过去一些用户在sp2中使用良好的代码在sp3种却会引发一些问题。感谢Bill 的细心查找，这一神秘的问题被解决了。答案？（哦，这儿有一个好答案。。。）这可能是因为有多个版本的sp3较早版本的sp3有一些bug，而后来的版本修正了这些错误，从微软网站上下载的1998年6月16日版本的sp3是一个良好的版本。如果X03-50158是那些拥有sp3的光盘序列号的一部分，那么这些版本也是良好的。但是不管任何版本的sp3，其STL的实现都有错误，详细情况请浏览http://www.dinkumware.com/vc_fixes.html。感谢Ben Eng对这些错误的修正。<BR>现在的SP4(希望只有一个版本)已经修正了STL中的死锁问题。<BR>我们现在将不再积极的支持MSVC 4.X以及以前的版本，ACE可和这些编译器一起工作但是可能会丢失一些好处。<BR>1. 将ACE分发包界压缩到一个目录中，这将在那个目录中生成一个包含ACE的目录ACE_wrappers。接下来的步骤中假设ACE分发包被解压缩到ACE_ROOT=C:\ACE_wrappers中，因此ACE将会存在于ACE_ROOT\ace目录中。<BR>2. 在ACE_ROOT\ace目录中创建一个文件，命名为config.h，其内容为：<BR>#include "ace/config-win32.h"<BR>3. 在VC++中加载ACE的工程文件（ACE_ROOT\ace\ace.dsw）<BR>4. 每个工程都会包含多个配置，这些配置是Debug/Release, MFC/Non-MFCh和Static/Dynamic库版本等选项的混合。确定你所需要的构造(例如，调试代码需要ACE的调试版本)。所有这些不同的配置可以为你提供一些便利，你可以或者采用不同的模式以构造不同配置的应用，或者通过改变ace\config.h来改变在NT上的不同配置。<BR>注意：如果你使用动态连接，请保证ACE_ROOT\bin被添加到你的path环境变量中，否则你将在运行程序的时候碰到寻找ace.dll或者aced.dll的问题。<BR>5. 如果你在Windows NT或者Windows 2k上构建ACE，你可以马上开始构造她而不需任何改变，如果你在Windows 9x/me上构建，那么你必须在<BR>ACE_ROOT\ace\config.h.的#include块之前添加一行：<BR>#define ACE_HAS_WINNT4 0<BR>这将在ACE中移掉一些WinNT/Win2K中特有的代码。<BR>6. 如果你希望使用MSVC自带的标准C++头文件（C++ Standard Draft 2种定义的iostream,cstdio…..）,则应该在<BR>ACE_ROOT\ace\config.h.的#include块之前添加一行：<BR>#define ACE_HAS_STANDARD_CPP_LIBRARY 1<BR>7. 如果需要和MFC一起使用，增加如下定义到你的config.h文件中，注意，如果你想使用spawn一个新的线程，则必须保证使用THR_USE_AFX标志来spawn线程。<BR>#define ACE_HAS_MFC 1<BR>缺省的，ACE工程使用MSVC运行时的动态DLL版本，你也可以选择使用ACE的不关心运行时库的静态（LIB）版本。我们选择仅与动态运行时库连接的原因在于基本上所有的NT机器上都会安装这些库，而我们则可以因此而减小代码的大小。如果你希望ACE与MFC的静态版本连接，则可以在config.h中定义ACE_USES_STATIC_MFC。然而，如果你希望静态的连接所有的库（包括MSVC运行时库），就需要自己修改工程文件了。<BR>8. 如果要构建ACE的静态版本，则需要在config.h中定义ACE_AS_STATIC_LIBS，此宏在那些希望使用ACE的静态版本的应用工程中也必须定义。<BR>作为一个可选项，你可以在<BR>#include statement in ACE_ROOT\ace\config.h.之前添加一行：<BR>#define ACE_NO_INLINE<BR>来取消函数内联从而减小静态库（和你的运行码）的大小。<BR>9. ACE DLL和LIB库的命名规则：<BR>我们使用如下的规则明明使用MSVC的ACE的DLL和LIB文件。<BR>"Library/DLL name" + (是静态库吗 ? "s" : "") + (包含调试信息 ? "d" : "") + {".dll"|".lib"}<BR>在MSVC环境中使用ACE的更多信息可以在这里找到。<BR><BR></TD></TR></TBODY></TABLE><BR><BR>-----------------------------------------------------------------------<BR>一、安装TAO，需要先编译并安装ACE。<BR><BR>二、ACE的编译和安装步骤见http://www.cs.wustl.edu/~schmidt/ACE_wrappers/ACE-INSTALL.html。TAO的编译和安装步骤见http://www.cs.wustl.edu/~schmidt/ACE_wrappers/TAO/TAO-INSTALL.html。如果你英文程度还可以的话，最好直接阅读这两篇文档。说到底，中文文档只是“权宜之计”；汉语并不太适合进行逻辑性的表述。<BR><BR>但我还是把其中的一些段落编译如下（VC 6.0 + ACE-5.2.1 + TAO-1.2.1）：<BR><BR>ACE的编译与安装<BR><BR>一般规则<BR><BR>ACE中的许多特性可以通过在$ACE_ROOT/ace/config.h中定义一些宏来进行修改。这些宏应该总是在包括针对你的平台的配置文件之前出现。<BR><BR>但是，如果你想要取消/重定义在针对特定平台的配置文件中定义的宏，#undef应该在配置文件之后出现。<BR><BR>如果你计划在多种平台上编译ACE，你也许需要考虑克隆源码树。<BR><BR>步骤：<BR><BR>1. 将ACE发布文件解压缩到某个目录中，在其中将会创建含有所有文件的ACE_wrappers目录。在下面的步骤中，ACE_wrappers目录将以ACE_ROOT为名来指称。<BR><BR>2. 在ACE_ROOT\ace目录中创建一个名为config.h的文件，在其中包含：<BR><BR>#include “ace/config-win32.h”<BR><BR>3. 现在加载ACE的项目文件（ACE_ROOT\ace\ace.dsw）。<BR><BR>4. 其中的每个项目都含有若干不同的配置（可混合Debug/Release、MFC/Non-MFC、Static/Dynamic library版本）。你可以从中选择你所需的配置，或是使用ace/config.h来进行调整。<BR>注意：如果你使用动态链接库，在运行使用ACE的程序时，确定你在PATH中包括了ACE_ROOT\bin。<BR><BR>5. 如果你的系统平台是WinNT或2000，那么无需任何改动你就可以开始编译了。如果是Windows 9x/Me，你需要在ACE_ROOT\ace\config.h中的#include语句之前增加：<BR><BR>#define ACE_HAS_WINNT4 0<BR><BR>6. 如果你想要使用MSVC标准C++头（iostream、cstdio……），在ACE_ROOT\ace\config.h中的#include语句之前增加：<BR><BR>#define ACE_HAS_STANDARD_CPP_LIBRARY 1<BR><BR>7. 要与MFC一起使用ACE，再增加下面的定义：<BR><BR>#define ACE_HAS_MFC 1<BR><BR>注意如果你想要通过CWinThread派生新线程，一定要设置THR_USE_AFX。在缺省情况下，所有的ACE项目都使用DLL版本的MSVC运行时库。尽管如此，你仍然可以选择使用static（LIB）版本的ACE库。如果你想要将MFC作为静态库链接进ACE，你可以在config.h文件中定义ACE_USES_STATIC_MFC。但如果你想要静态链接所有的东西（包括MSVC运行时库），你就需要自己修改ACE的项目文件。<BR><BR>8. ACE的静态版本是通过定义ACE_AS_STATIC_LIBS来编译的。在链接静态ACE库的应用项目中也应该使用这个宏。<BR>你也可以在config.h文件中增加<BR><BR>#define ACE_NO_INLINE<BR><BR>来取消函数内联并减小静态库（和你的可执行程序）的大小。<BR><BR>9. ACE DLL和LIB的命名方案：<BR><BR>"Library/DLL名" + (是否为静态库 ? "s" : "") + (是否启用了Debugging ? "d" : "") + {".dll"|".lib"}<BR><BR>10. 配置完毕后编译即可。选择dll版本，编译生成的dll文件在ACE_ROOT\bin中，相应的lib文件在ACE_ROOT\ace中。<BR><BR>ACE测试<BR><BR>各测试程序在ACE_ROOT\tests中。在其中也有一个工作空间文件可用来编译所有的测试程序（tests.dsw）。<BR>一旦你编译了所有测试程序（可使用批编译），你可以运行tests目录中的perl脚本run_test.pl或批处理文件run_tests.bat来进行所有测试。<BR><BR>TAO的编译与安装<BR><BR>确定VC的CL.EXE在你的访问路径上。设置ACE_ROOT或TAO_ROOT环境变量。例如：<BR><BR>set ACE_ROOT=C:\ACE_wrappers<BR><BR>TAO最好放置在ACE_wrappers（这也是缺省情况）。<BR><BR>1.确定ACE已经编译和安装。<BR><BR>2.确定ACE_wrappers\bin已在“Tools|Options”中的“Executable Directories”中列出。如果在MSVC下使用TAO_IDL编译器就需要进行此设置。<BR><BR>3.加载tao\TAO.dsw，并编译TAO库。<BR><BR>4.要编译Cubit测试，加载performance-tests\Cubit\TAO\IDL_Cubit\IDL_Cubit.dsw，并编译客户和服务器。<BR><BR>TAOACE.dsw<BR><BR>TAOACE.dsw是一个Visual C++ 5.0/6.0工作空间文件，它加载的项目包括ACE、TAO、TAO_IDL（编译器）、gperf、orb服务库，以及一些单独的可执行程序（比如Naming Service，等等）。它可以用于编译所有的用于编译/运行TAO应用的文件。<BR><BR>三、我选择编译的是dll版本（Release），并在ACE的config.h文件中定义了“#define ACE_HAS_STANDARD_CPP_LIBRARY 1”。编译后我所得到的ace.dll的大小是1.13MB，相应的ace.lib的大小是1.77MB；TAO.dll的大小是1.47MB，相应的TAO.lib的大小是2.74MB。所有文件约有 MB，包括源程序、编译生成的中间文件，等等，但有些例子及服务我没有编译。<BR><BR>祝学有所成！<BR><BR>马维达<BR><BR>-------------------------------------<BR>将ACE与VC6集成在一起<BR><BR>一.打开 Tools&gt;Options&gt;Directories <BR>加入以下内容:<BR>Executable File:<BR>C:\ACE_wrappers\bin<BR><BR>Include File:<BR>C:\ACE_wrappers\<BR>C:\ACE_wrappers\TAO<BR>C:\ACE_wrappers\TAO\orbsvcs<BR><BR>Library Files:<BR>C:\ACE_wrappers\ace<BR>C:\ACE_wrappers\TAO\tao<BR>C:\ACE_wrappers\TAO\orbsvcs\orbsvcs<BR><BR>Source Files:<BR>C:\ACE_wrappers\ace<BR>C:\ACE_wrappers\TAO\tao<BR>C:\ACE_wrappers\TAO\orbsvcs\orbsvcs<BR><BR>二.加入 C:\ACE_wrappers\bin 到系统环境变量 path中<BR><BR>三.设置系统变量<BR>ACE_ROOT=C:\ACE_wrappers<BR>TAO_ROOT=C:\ACE_wrappers\TAO<BR></P></SPAN><img src ="http://www.cppblog.com/gnupython/aggbug/3450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gnupython/" target="_blank">heart in the world</a> 2006-02-23 19:53 <a href="http://www.cppblog.com/gnupython/articles/3450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计不受传统网络限制的 P2P 系统</title><link>http://www.cppblog.com/gnupython/articles/2405.html</link><dc:creator>heart in the world</dc:creator><author>heart in the world</author><pubDate>Tue, 03 Jan 2006 12:02:00 GMT</pubDate><guid>http://www.cppblog.com/gnupython/articles/2405.html</guid><wfw:comment>http://www.cppblog.com/gnupython/comments/2405.html</wfw:comment><comments>http://www.cppblog.com/gnupython/articles/2405.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gnupython/comments/commentRss/2405.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gnupython/services/trackbacks/2405.html</trackback:ping><description><![CDATA[<font color="#ff1493">声明一下：在reprinting栏目中的文章完全是转载，来自互联网，本人完全是学习之用，如果，转载侵犯了您的版权，请给我联系一下，我会作相应处理。Email:gaoyuanxue118@gmail.com </font><br><dl class="ReadArticle"><dt>
							<span id="LblTitle">设计不受传统网络限制的 P2P 系统</span>
							</dt><dd class="ArticleInfo">
								作者：
								<a id="HyperAuthor" href="http://kb.csdn.net/ArticleAuthor.aspx?author=chris">chris</a>∣来源：<a id="HyFromWhere" href="http://www.matrix.org.cn/article.shtml" target="_blank">Matrix</a>∣<a id="HyHistoryUrl" title="http://www.matrix.org.cn/resource/article/77.html" href="http://www.matrix.org.cn/resource/article/77.html" target="_blank">原文地址</a>∣<span id="LblUpdateDate">2003-6-11</span>
								</dd></dl><br><span id="LblContent">随着移动计算的普及和嵌入式可联网微处理器的无处不在的应用，TCP/IP
终于显露出它已经显得过时。设计 Jxta 的初衷就是要突破当今基于 TCP/IP 的网络的限制，从而扩展因特网所能触及的范围。在
developerWorks 的讨论 Jxta 的系列的这最后一篇文章中，Sing Li
举例说明了体现这种扩展的系统，并解决了一个实际问题。您将看到 Jxta
不受客户机／服务器网络的典型约束的限制。请单击本文顶部或底部的讨论，在讨论论坛与作者及其他读者共享关于本文的心得。<br><br>到本系列文章的
这里为止，我们仔细考察了 Jxta，一个 Java 参考实现的新 P2P 平台，是如何工作的。在第一部分中，我们了解了 Jxta
的互操作特征。Jxta 被定义为一组互操作协议，可以跨硬件平台、操作系统和编程语言实现。我们也讨论了 Jxta
的操作模型和包括对等机、对等组、服务和管道在内的许多重要概念。在第二部分中，我们的着眼点是建立和运行 Jxta。我们探讨了一个 Jxta
应用程序 — Jxta shell — 并经历了创建管道并从一个对等机发送消息到另一个对等机的情形。在我们编写 Jxta shell
扩展时，我们第一次获得了用 Jxta API 编程的经验。迄今为止，我们讨论 Jxta
的方式都是从下到上的。对于像我们这样具有系统编程和网络工程背景的人来说，这是再自然不过的。<br><br>在本系列的这第三篇也即最后一篇文章中，我们要把事情颠倒过来。从那些从事应用级设计和体系结构的人的角度来说，本文是自上而下看待 Jxta 的。我们从一个特定的示例问题开始，对这个问题进行分析并设计出一个解决方案，从而展示 Jxta 是如何自然地解决该问题的。<br><br>随着本文的进行，我们讨论 Jxta 如何通过并列（juxtaposition）改变联网的前景展望，我们还提供一个 Jxta 服务和客户机的设计和代码。<br><br>解决一个分布式数据收集问题<br>设
想一下我们需要创建一个大规模的气象数据收集和分析系统。在这个系统中，我们有数百个气象数据收集点；每个收集点配备一个微型气象站，这些气象站将当前温
度（和其它大气状态）提供给一组数据集中器。收集器遍布世界各地；这些收集器并不是都直接连接到因特网，任何时候都可能有新的数据收集器连接上来或脱开连
接。在这个项目中，参与进来的收集器的确切数量经常在变化；数据分析和处理基于区域平均值。 <br><br>开始时只有 10
个集中器。每个集中器监视来自许多个收集器的数据，这些数据被实时提供给关系数据库。随后，来自关系数据库的数据被提供给运行气象分析和预测的仿真模型的
超级计算机并由它处理。集中器的数量和位置会发生变化，但它们的行为则大多更稳定。一旦安装后，集中器就会保持运转，除非碰到系统失效。 <br><br>我们必须解决的问题：我们的系统如何能够持续运转，并能考虑到在几乎不影响整体性能的条件下，允许动态添加或除去收集器和集中器。<br><br>初始分析：特定网络的复杂性<br>系
统中的某些收集器可直接访问因特网；其它的通过无线电传输技术进行连接，它们处在恶劣的外部环境中。事实上，在这些基于无线电的收集器中，许多都被设计成
了节能的，以延长电池寿命；收集器的有效范围仅够与下一个最近的收集器或基站联系。这些收集器中许多都不支持
TCP/IP，而是使用基本的分组无线技术。一些更独立的收集器仅仅靠其太阳能电池板获得能量，并使用卫星传输进行通信。还有另外一些收集器则连接到标准
蜂窝电话上，用 SMS（short message service，短消息服务）消息传递来发送消息。 <br><br>在项目的整个生命周期中，
可用的收集器的数量会发生变化；在项目开始时，我们无法预测将会构建到未来收集器中的连接类型，也无法预测收集器将使用的技术。例如，在项目的某个阶段，
在一个超级计算机群集内使用软件仿真来仿真数量巨大的收集器。我们的解决方案必须能适应所有收集器，不管是真正的还是仿真的，现在的还是将来的。 <br><br>解决方案：并列（Juxtaposition）<br>图 1 显示用来解决这个问题的高层次设计。 <br><br>图 1. 解决数据收集问题<br><br><img src="http://www-900.ibm.com/developerWorks/cn/java/j-p2pint/part3/fig1.gif" alt="image" style="display: inline;" border="0">请
注意，并列 P2P 网络用来适应网络的多种不同情况，而集中器提供 P2P
网络和传统的客户机／服务器网络之间的连接，数据库服务器和超级计算机驻留在客户机／服务器网络。集中器充当两个网络之间的网桥 — 每个集中器在
P2P 网络上具有动态特性，在客户机／服务器网络具有静态特性。 <br><br>这个体系结构反映了 Jxta 对传统系统的补充作用和提供并行于这些传统系统的增值的能力 — 通过并列（juxtaposition），Jxta 的名称就源于这个词语。 <br><br>我们不想深入讨论这里的客户机／服务器网络的细节，因为其中并没有什么独特之处；我们甚至可以使用 VPN 技术在因特网上运行它。有趣的部分在 P2P 网络。图 2 显示了它的组成，它可随将来的变化而变化。请注意其中用到的多种不同技术。 <br><br>图 2. 数据收集器网络的组成<br><br><br><img src="http://www-900.ibm.com/developerWorks/cn/java/j-p2pint/part3/fig2.gif" alt="image" style="display: inline;" border="0">在实现这个 P2P 网络时，我们可以利用 Jxta，从而获得以下优点： <br><br>容易地添加或除去新的收集器或集中器，这得益于 Jxta 的统一分散寻址<br><br><br>设计简单性，这得益于 Jxta 的网络虚拟化<br><br><br>持续运转，这得益于 Jxta 支持故障弹性<br><br><br>免维护运转，这得益于 Jxta 支持动态自我组织网络<br><br><br>支持跨越许多硬件平台和编程语言的多种不同实现，支持所用的各种不同通信协议<br>让我们来更详细地研究一下其中几个益处，并看看 Jxta 如何为体系结构的各个方面作出独特的贡献。<br><br>统一分散寻址<br>统一分散寻址的字面意思是，对等机可以为自己生成一个 ID 并立即加入到网络，而不必与任何注册人或中央认证机构联系，而当今的 DNS 则必须这样。这一特征使我们任何时候都可以向网络添加收集器和集中器。 <br><br>在
本文附带的代码包中（您可以从参考资料下载它），我们提供了名为 mdidgen 的实用程序，它可以用来为新的 Jxta
服务和管道生成地址。（要更多了解 mdidgen，请参阅旁注 mdidgen 实用程序。）您可以阅读本系列的第一篇文章，了解 Jxta ID
是如何用来对 Jxta 对象（例如：对等机、对等组、服务和管道）进行统一寻址的。 <br><br>请注意，Jxta
网络中的对等机不一定要有一个独立的物理存在。在我们的示例中，我们用一个超级计算机群集来仿真数量巨大的收集器，每个收集器有它自己的统一地址。这些仿
真收集器的每一个在 P2P 网络的其它部分看来都是一个与那些具有物理存在的对等机没有什么差别的对等机。 <br><br>网络虚拟化<br>通过分散寻址为所有收集器和集中器赋予网络中唯一的标识后，它们立即就成为网络中的对等机并开始彼此通信。尽管它们可能通过许多种不同的消息传递机制进行相互联系，但在 Jxta 级别上，它们都只是一个虚拟网状网络中的节点，如图 3 所示。 <br><br>图 3. 网络虚拟化<br><br><br><img src="http://www-900.ibm.com/developerWorks/cn/java/j-p2pint/part3/fig3.gif" alt="image" style="display: inline;" border="0">请
注意，将收集器和对等机实际相互连接起来的所有不同的传输和寻址模式都被虚拟化了，只留下一个网状网络，其中的每个对等机都与其它每一个对等机相连接。
Jxta 通过使用统一寻址模式和极迟绑定（very late
binding），在多个端点协议上添加一个智能消息路由层做到这一点。从本质上说，每一个端点协议或传输协议栈都成为虚拟 Jxta
网络的一个驱动程序，将虚拟网络映射到物理网络上。图 4 显示了这种设置。 <br><br>图 4. 端点协议作为驱动程序<br><br><br><img src="http://www-900.ibm.com/developerWorks/cn/java/j-p2pint/part3/fig4.gif" alt="image" style="display: inline;" border="0">通
信协议要成为合格的端点协议，只需要它能够在两个物理节点之间发送或接收 XML
消息。对传输可靠性或消息广播支持没有什么要求。因而，最简单的分组无线协议也可以用作端点协议驱动程序，与像 TCP/IP
这样的复杂多层协议并列。这也解释了为什么 HTTP 和 TCP/IP 在 Jxta
协议栈内都是同一级别的端点协议，尽管它们的物理级别非常不同。HTTP
是一个受支持的端点协议，因为只要有必要，它就能够穿越尽可能多的防火墙，从而获取从一个 Jxta 对等机传送到另一个的消息。 <br><br>Jxta
网络中的每个对等机可以同时支持多个端点协议，Jxta 虚拟网络机制会以一种尽可能迟的方式将虚拟化的统一网络地址映射到物理网络地址（在 Jxta
中称为网络端点）。从本质上说，一个对等机对应于一组物理端点，其中的每个物理端点可以在完全不同的物理通信协议上实现。较高级别的虚拟化和路由服务隐藏
了这一点。许多人或许能看出这就是多协议路由器的一个非常高级的形式 —
正是这相同的设备使当今的因特网成为现实。这一概念的发展将把我们带向一个更加普遍的因特网，这是再自然不过的了。 <br><br>让我们更详细地研究一下图 5 所示的示例。对等机 A 是网络中的一个收集器，它试图通过一系列中介收集器（对等机 B、C 和 D）将其数据发送到集中器（对等机 E）。在图中每个对等机的下面是该对等机所支持的一组协议。 <br><br>图 5. Jxta 路由示例<br><br><br><img src="http://www-900.ibm.com/developerWorks/cn/java/j-p2pint/part3/fig5.gif" alt="image" style="display: inline;" border="0">因为对等机 A 不直接连接到对等机 E，所以它的消息必须通过中介对等机 B、C 和 D 进行路由。Jxta 将自动对消息进行路由： <br><br>使用 TCP/IP 从对等机 A 到对等机 B<br><br><br>使用分组无线协议从对等机 B 到对等机 C<br><br><br>使用 SMS 从对等机 C 到对等机 D<br><br><br>使用 HTTP 从对等机 D 到对等机 E<br>对
等机 E 将在它创建的管道上接收来自对等机 A 的消息，完全未觉察 Jxta 为它所执行的复杂工作。请注意，对等机 C 到对等机 D
的路径是非对称的；Jxta 就是专门设计来处理这种状况的。如果有条消息要从对等机 E 发送回对等机 A，则 Jxta 将使用拨号调制解调器
PPP 自动地从对等机 D 路由到对等机 C。 <br><br>故障弹性<br>尽管上面所描述的路由功能已经令人非常惊奇，但更为重要的是，
Jxta 必须能够适合 P2P 网络不断变化的拓扑结构。特别是它必须能够处理充当消息路由代理的 P2P
对等机与生俱来的不可靠性。在我们的例子中，如果中继收集器不可用，那么，依赖另一个收集器来路由它的消息的收集器将不能进行通信。 <br><br>当
有对等机加入或离开网络时，Jxta 要能够实时对消息进行重路由。再考虑一下图 5 中的路由示例。请设想一下，由于某些原因，就在对等机 A
已经发送出消息（现在正在传输）而尚未到达对等机 C 时，对等机 C 和对等机 D 之间的卫星链路却断了。Jxta
必须能够动态地通过某些替代路径（可能是通过另一组中间节点）将该消息重路由到对等机
E。这种动态重路由是基于最大努力（best-effort）完成的；偶而有这样的情况，如果没有可能的路由（除非中介传输支持持久队列），则消息可能会
被丢失。由于这种重路由能够改换实际用来到达对等机 E 的端点协议（例如：从 HTTP 到
TCP/IP），所以，要一直达到路由的最后一个跳数时，对等机到物理端点的绑定才会发生。这就是 Jxta 的极迟绑定的本质。 <br><br>在对等组级别上（请参阅本系列的第一篇文章了解有关对等组的更多知识），Jxta 通过支持对等组服务 — 在对等组内总是可用的、冗余地实现的服务 — 支持故障弹性。 <br><br>动态自我组织网络<br>当具有统一虚拟网络 ID 的对等机插入到 Jxta 网络中时，它必须这样来自我引导： <br><br>定位本地对等机并发现它们的功能<br><br><br>发现可用的对等组并加入其中一个<br><br><br>发现对等组中可用的服务并开始使用它们<br>我
们从本系列的第二篇文章中了解到，这一切都是在消息级别上通过发布、中继、中介高速缓存和搜索称为广告的不同类型的消息完成的。Jxta 的 Java
参考实现有一个解析器和使发布-高速缓存-搜索（publish-cache-search）过程简便的集中服务层。 <br><br>Jxta 中的对等组的作用是作为网络分区（network-partitioning）机制，确保广告只被中继到能够使用这些广告的组成员。不同的对等组可以包含对等机和对等组服务的不同组合，充当功能性的捆束机制。对等组也可以起到特定应用程序的认证域的作用。 <br><br>mdidgen 实用程序<br><br><br>实
用类 com.ibm.jxta.mdidgen 可以用来以分散方式为 Jxta 对象生成统一地址。它生成一个新的
ModuleClassID、一个相应的 ModuleSpecID 和一个与某个组（在启动时被读取的配置文件中指定）关联的新
PipeID。所生成的这些 ID 是立即可以使用的 Java 声明形式，并且立即可以插入到您的代码中。这就是我们为
ModuleSpecAdvertisement 和集中器服务管道生成 ID 的方式。<br> <br>设计 Jxta 服务和 Jxta 客户机<br>让我们回到气象站示例上来。从概念上说，集中器实现必须：<br><br>读取并处理适当的配置文件，这个文件告诉集中器加入到哪个 Jxta 组。（样本代码包中包含有我们示例的配置文件。）<br><br><br>启动 Jxta。<br><br><br>加入到配置文件所指定的组。<br><br><br>进行搜索，以判断集中器服务的服务广告是否存在；如果不存在，就创建一个并发布它。<br><br><br>创建一条相应于该服务的输入管道。<br><br><br>在管道等待来自收集器的消息。<br><br><br>一旦消息到达，就处理它并存储到 RDBMS 中。<br><br><br>回到第 6 步。<br>这个逻辑在 com.ibm.jxta.Concentrator 类中实现。您可以从参考资料部分下载这个类及所有来自本文的代码。 <br><br>收集器实现必须：<br><br>读取并处理上述配置文件。<br><br><br>启动 Jxta。<br><br><br>加入到配置文件所指定的组。<br><br><br>发现集中器服务的服务广告；如果服务广告不可用，我们就无法继续。<br><br><br>从服务广告抽取管道信息。<br><br><br>每隔一段时间收集数据。<br><br><br>创建包含收集器位置和数据的消息。<br><br><br>通过管道将消息发送到集中器服务。<br><br><br>回到第 6 步。<br>上述逻辑在 com.ibm.jxta.Collector 类中实现。 <br><br>将公共任务分解到 DwJxtaPeer 超类<br>有很多任务对收集器和集中器角色都是公共的。为了消除不必要的代码重复并使将来的维护更简单，让我们把这些公共任务分解出来放入名为 com.ibm.jxta.DWJxtaPeer 的超类。 <br><br>其中一个公共任务是执行 ModuleSpecAdvertisement 的发现（请参阅旁注 JXTA 中的服务广告了解关于这个广告的更多知识）。这由清单 1 中的 findModuleSpecAdv() 方法执行： <br><br>清单 1. findModuleSpecAdv() <br>protected ModuleSpecAdvertisement findModuleSpecAdv()  {<br>   return (ModuleSpecAdvertisement) findAdv("ModuleSpecAdvertisement",<br>      "Name",ModuleSpecName,  new ModuleSpecAdvValidator(), false );<br>}<br><br> <br><br>请注意，findModuleSpecAdv() 调用另一个名为 findAdv() 的通用方法，我们用这个方法发现广告。findAdv() 的参数是： <br><br>参数 描述 <br>AdvType 广告类型的字符串描述 — 例如，PipeAdvertisement。 <br>Attr 搜索广告时要匹配的标记 — 例如，Name。 <br>Value 与所指定的属性匹配的值。 <br>Validator 一个实现 FindValidate 接口的对象。这个接口有一个方法 checkAdv()，当找到一条广告时，这个方法就被用来立即对这条广告进行验证。 <br>LocalOnly 一个布尔标志，表明该发现是否只应在本地执行，还是跨网络在远程执行。 <br><br>如清单 2 所示，该方法的第一部分通过使用组的发现服务的 getLocalAdvertisement() 方法，仅根据本地广告高速缓存执行对广告的发现。请注意对 validator.checkAdv() 调用，用来对所找到的任何广告进行验证。 <br><br>清单 2. findAdv()，第 1 部分 <br>  protected  Advertisement findAdv(String advType, String attr, String val,<br>       FindValidate validator, boolean localOnly) {<br>        Enumeration enum = null;<br>        System.out.println("Looking for " + advType + ", please wait...");<br>        // First look in the local storage<br>         try {<br>            enum = discovery.getLocalAdvertisements(DiscoveryService.ADV,<br>           attr, val);<br><br>          } catch (Exception e) {<br>          }<br><br><br><br>         if ((enum != null) &amp;&amp; (enum.hasMoreElements())) {<br>                Advertisement adv = null;<br>                while (enum.hasMoreElements()) {<br>                    try {<br>                        adv = (Advertisement) enum.nextElement();<br>                        if( validator.checkAdv(adv))<br>                                return adv;<br>                        } catch(Exception e) {<br>                        continue;<br>                           }<br>                       } // while<br>              } // if<br><br> <br><br>如果该发现是本地的，则逻辑就在这里停止。否则，我们就发送一条查询到网络，执行远程发现。发现服务将把所找到的任何广告都存储到本地高速缓存。我们只要给点时间就可以让远程发现发生。在清单 3 中，循环大约持续了五秒钟： <br><br>清单 3. findAdv()，第 2 部分 <br>        if (localOnly)<br>           return null;<br><br>        System.out.println("   cannot find it locally, trying remote");<br>        // Now, search remote<br>        discovery.getRemoteAdvertisements(null, DiscoveryService.ADV,<br>                attr, val, 2, null);<br><br>        // Wait a bit in order to get an answer.<br>         int i=0;<br>         while (true) {<br>         try {<br>               if (i&gt;MAXRETRIES){<br>                System.out.print(".");<br>                break;<br>            }<br>            Thread.sleep(WaitingTime);<br>            i++;<br>        } catch (Exception e) {<br>        }<br>        System.out.println("");<br><br> <br><br>此时，已发现的任何广告都应可在本地高速缓存中找到。在清单 4 中，我们再次执行一个本地检查。 <br><br>清单 4. findadv()，第 3 部分 <br>      // Look in the local storage again<br>        try {<br>            enum = discovery.getLocalAdvertisements(DiscoveryService.ADV,<br>                    attr, val);<br><br>            if ((enum != null) &amp;&amp; (enum.hasMoreElements())) {<br>                Advertisement adv = null;<br><br>                while (enum.hasMoreElements()) {<br>                    try {<br>                        adv = (Advertisement) enum.nextElement();<br>                          if( validator.checkAdv(adv))<br>                                return adv;<br>                        } catch(Exception e) {<br>                        continue;<br>                    }<br>                } // while<br>            }<br>        } catch (Exception e) {<br>        }<br>       }<br>        return null;<br>    }<br><br> <br><br>超类中的另两个公共方法的描述在下表中；您可以作为练习完成对它们的分析。 <br><br>方法 描述 <br>PublishModuleSpecAdv()
如果发现过程没有为服务找到现有的
ModuleSpecAdvertsiement，则这个方法被集中器调用。这个方法将创建一个服务（根据我们所生成的、固定的服务
ID）。这条广告将在本地和远程发布。仅在集中器第一次启动时，当配置改变时，或者在本地高速缓存被清除后，才有创建广告的必要。 <br>JoinGroupIfExists() 这个方法为收集器和集中器所调用；它尝试加入到一个已命名的子组（subgroup），这个子组是全局 NetPeerGroup（缺省情况下大家都在这个组）的子（child）组。 <br><br>请看一下清单 5，它是 DwJxtaPeer 类的常数声明部分的一部分： <br><br>清单 5. 模块 ID 定义 <br>public static final String ClassID = <br>"urn:jxta:uuid-EE99266A1DE84E3DB34D9CC842EC889105";<br>public static final String SpecID = <br>"urn:jxta:uuid-EE99266A1DE84E3DB34D9CC842EC8891B9EB13ECA6FE44DDA112B5F5E357763006";<br><br> <br>Jxta 中的服务广告<br><br><br>服务广告概念分解成一组相互联系的广告（共三条）： <br>ModuleClassAdvertiseent<br>ModuleSpecAdvertisement<br>MdouleImplAdvertisement<br><br>为了减小在系统中循环的广告的大小，也为了将服务的通用类（例如：银行）、该类的特定规范（例如：存款和提款 API）和该服务（例如：API 基于 Java 的实现）的实现之间的关系规格化，这样做都是必要的。 <br><br>应用程序或 Jxta 服务不必使用所有这些广告，只要使用它所需要的就行了。在我们的系统中，我们只需要ModuleSpecAdvertisement，我们用它将服务连到管道上，并使这条广告是远程可发现的。 <br> <br>ModuleClassID
和 ModuleSpecID 用 mdidgen 实用程序生成并以硬编码方式置于模块中；它们与一个集中器服务的 ID
相对应。所有的集中器都知道这个服务的 ID，而且这个 ID 一旦生成就一直保持不变，所以组中的收集器肯定能够找到这个集中器服务。因为生成
ModuleSpecID 时需要 ModuleClassID，所以这里有 ModuleClassID。为了轻松生成这些 ID，我们使用一个名为
AdvCooker 的库，它是 W.R. Bauer（vasha@jxta.org）创建的名为 jxta-wire 的 Jxta
项目的一部分。 <br><br>网络中运行的所有集中器实例将对同一个集中器对等组服务（通过使用相同的 ModuleSpecID 和侦听广播管道的同一个逻辑实例）作出应答。这种冗余实现将确保集中器服务在对等组中始终可用。 <br><br>集中器：一个 Jxta 对等组服务<br>我们来看一下 com.ibm.jxta.Concentrator 实现。我们已经提到过，它继承（扩展）自 DwJxtaPeer 类。这里是逐个方法地对 Concentrator 进行的描述： <br><br>方法 描述 <br>init() 它应该是该类被调用的第一个方法。这个方法调用私有 jxtaInit() 方法，然后创建输入集中器服务管道的一个实例。 <br>process() 这个方法进入一个无限循环。它在输入集中器服务管道上侦听传入的收集器数据提交。对每一个提交，它都调用 processData() 对数据进行处理。 <br>findPipeAdv() 这个方法对服务管道广告执行本地发现（也就是说，它检查本地高速缓存）。 <br>jxtaInit()
这个方法首先读取配置文件并设定我们想要加入到的组。接着，它启动 Jxta 和 NetPeerGroup 网络，然后调用超类的
joinGroupIfExist()
加入到指定的组。接着，如果能够，它就从本地高速缓存检索服务管道广告；否则，它将创建一个新的服务管道广告（通过使用
createInputPipeAdvIfNotExist()）。最后，它执行发现，看看是否可以找到
ModuleSpecAdvertisement；如果不能找到，它就创建一个并发布它。 <br>processData() 这个方法是占位符。在实际的项目中，它将使用后端客户机／服务器网络将所收集到的数据提交给 RDBMS（可能使用 JDBC）。 <br>createInputPipeAdvIfNotExist() 这个助手方法首先检查高速缓存，看看服务管道广告是否可用。如果不可用，它将创建该广告并将它存储到高速缓存中。在任一种情况下都返回正确的广告。 <br><br>静态类型定义如下： <br><br><br>public static String servicePipeID = <br>"urn:jxta:uuid-969610EE8945417CA56F9771197EE3965207E4C303154E7EB5878751AE22761804";<br><br> <br><br><br>这
是由 mdidgen 实用程序生成的管道
ID。它是该服务管道的统一地址，被所有集中器使用。它是一条广播管道，因而侦听消息的所有集中器都应接收到那些来自收集器的消息。收集器从作为
ModuleSpecAdvertisement 的一部分的管道广告中获得这个管道 ID；收集器通过发现过程找到该广告。 <br><br>收集器：编写 Jxta 客户机逻辑的代码<br>最后，我们来看一下 com.ibm.jxta.Collector 类的本地方法。 <br><br>方法 描述 <br>init() 它应该是从这个类中调用的第一个方法。这个方法调用私有 jxtaInit()，然后创建用来将所收集到的数据发送到集中器服务的输出管道。 <br>process() 这个方法有一个无限循环，这个循环首先调用 collectData() 获得测量的数据，接着，创建一条 Jxta 消息并沿集中器服务管道将它发送到正在等待的集中器。循环内每次采样都延迟一段固定时间。 <br>jxtaInit()
这个方法首先读取配置文件并对我们想要加入到的组进行设置，接着确定收集器的位置。接着，它启动 Jxta 和 NetPeerGroup
网络，然后调用超类的 joinGroupIfExist() 加入到指定的组。接着，它执行发现，看看是否可以找到相应于众所周知的集中器服务的
ModuleSpecAdvertisement；如果找不到，则退出。一旦找到了
ModuleSpecAdvertisment，它就将抽取集中器服务管道广告并为输出管道的创建做好准备。 <br>collectData() 这个方法是一个占位符，用于实际的数据收集。在实际的项目中，这个方法将访问各种数据输入通道（可能使用输入／输出端口或本机代码）并将所收集到的数据返回给调用者。 <br><br>实际运转 Jxta：在您自己的机器上测试这个动态网络<br>本文附带的源代码包中有一个便于您实验的目录结构。下面的目录在 code 子目录下： <br><br>目录 描述 <br>lib
来自 Jxta 核心最新稳定版的所有 jar 文件，用于 Jxta shell 的所有 jar 文件以及来自 jxta-wire 项目的
jxta-wire.jar 文件都放在这里。（请参阅参考资料了解关于 Jxta shell 和 jxta-wire 的更多信息。） <br>src 包含我们系统的源代码。 <br>classes 包含我们系统的编译好的类文件。 <br>shell1 第一个实验目录。我们将在这个目录创建一个带有一个集中器的 shell。我们还将在这里充分考查 mdidgen 实用程序。 <br>shell2 设置为网络中的第二个对等机。这将运行另一个集中器。 <br>shell3 设置为网络中的第三个对等机。这将运行一个收集器。 <br><br>要编译这些代码，您需要安装 JDK 1.3 或更新版本。在 code 目录时，执行 MAKEIT.BAT 批处理文件。这将编译代码并在 classes 目录中创建类文件。 <br><br>接着，运行 MAKEJAR.BAT 批处理文件。这将创建一个包含所有代码的 dwjxta.jar 文件；将它放到 lib 目录，为实验做好准备。 <br><br>现在，请启动三个不同的命令窗口。将它们的目录分别改到 shell1、shell2 和 shell3。 <br><br>在 shell1 目录中编辑 runshell.bat 文件，将您在配置期间用来设置安全性的用户标识和密码反映出来（密码必须至少八个字符长）。编辑 runconc.bat 和 mdidgen.bat 文件，同样要有这个用户标识和密码。 <br><br>使用 runshell.bat 运行这个 shell，并按以下所示配置这个对等机： <br><br>对等机名： node1 <br>传输： TCP/IP 启用，HTTP 禁用，选中作为集中点，无中继 <br>所用 TCP 端口： 9701 <br>安全性用户名和密码： 如在批处理文件中所定制 <br><br>因为我们的系统假设已经创建了一个用于操作的组，所以我们需要在该 shell 中创建这个组。在这个 shell 中时，使用以下命令创建 dwtest 组： <br><br><br>Jxta&gt; myadv = mkadv -g dwtest<br>Jxta&gt; mygrp = mkpgrp -d myadv dwtest<br><br> <br><br>这将创建我们将使用的 dwtest 组。您可以这样来确认它已经被创建： <br><br><br>Jxta&gt;groups<br>group0: name = dwtest<br><br> <br><br>现在您可以退出该 shell。 <br><br>现在，请使用 mdidgen.bat 文件试验统一地址（ID）的分散生成。当您运行这个文件时，应得到类似这样的输出： <br><br>清单 6. mdidgen.bat 的输出 <br>remote group discovery message sent<br>group joined successfully<br>public static final String ClassID = <br>"urn:jxta:uuid-DCDD418FCC194040AA13A52A334B967105";<br>public static final String SpecID = <br>"urn:jxta:uuid-DCDD418FCC194040AA13A52A334B96716C515B975C2941AD9FBC90178B6918A806";<br>public static final String PipeID = <br>"urn:jxta:uuid-2184CACA259B42E0A866AEA788A923054C519D304E07415195B0917C81238FD004";<br><br> <br><br>请注意所生成的 ModuleClassID、ModuleSpecID 和 PipeID。这就是我们获得在集中器服务用到的 ID 的办法。 <br><br>通过执行 runconc.bat 文件启动集中器。这将读取 dwConfig 文件，这个文件告诉集中器加入到 dwtest 组。您的输出应与此有些相似： <br><br>清单 7. 1 号集中器（runconc.bat）的输出 <br>Starting Jxta...<br>Joining default NetPeerGroup...<br>Attempting to join group: dwtest<br>remote group discovery message sent<br>group joined successfully<br>group dwtest joined successfully<br>Look for previously created Pipe Adv, create one if not exist<br>Looking for PipeAdvertisement, please wait...<br>Previously published pipe advertisement not found, creating a new one.<br>Locally caching the new pipe advertisement...<br>Checking to see if MSA previously published...<br>Looking for ModuleSpecAdvertisement, please wait...<br>   cannot find it locally, trying remote<br>... MSA not found, need to create it<br>Creating new MSA<br>Locally and remotely publish the MSA<br>Creating pipe for data collection...<br>pipe created successfully<br>Waiting for data from collector...<br><br> <br><br>到这里，集中器实例就建立好了，并且为接收来自收集器的数据做好了准备。 <br><br>现在，到 shell2 命令窗口中编辑 runconc.bat 文件，将您的安全性用户标识和密码反映出来。接着，使用 runconc.bat 文件运行集中器实例。在配置过程中设置以下参数： <br><br>对等机名： node2 <br>传输： TCP/IP 启用，HTTP 禁用，无集中点，无中继 <br>所用 TCP 端口： 9702 <br>安全性用户名和密码： 如在批处理文件中所定制 <br><br>如果一切都正确运行，则您应看到与此相似的输出： <br><br>清单 8. 2 号集中器（来自 Shell2 的 runconc.bat 输出） <br>Starting Jxta...<br>Joining default NetPeerGroup...<br>Attempting to join group: dwtest<br>remote group discovery message sent<br>group joined successfully<br>group dwtest joined successfully<br>Look for previously created Pipe Adv, create one if not exist<br>Looking for PipeAdvertisement, please wait...<br>Checking to see if MSA previously published...<br>Looking for ModuleSpecAdvertisement, please wait...<br>.. found previously published MSA<br>Creating pipe for data collection...<br>pipe created successfully<br>Waiting for data from collector...<br><br> <br><br>请注意，集中器的 ModuleSpecAdvertisement 被找到了，所以这个集中器实例不必另外创建一个 ModuleSpecAdvertisement。现在它也在等待来自收集器的输入。 <br><br>最
后，到 shell3 命令窗口中编辑 runcoll.bat 文件，将您的安全性用户标识和密码反映出来。接着，使用 runcoll.bat
文件运行收集器实例。这个实例将使用 shell3 目录中的 dwColConfig 文件，该文件告诉收集器应加入到 dwtest
组，这个组的位置是“Timbuktu North”。在配置过程中设置以下参数： <br><br>对等机名： node3 <br>传输： TCP/IP 启用，HTTP 禁用，无集中点，无中继 <br>所用 TCP 端口： 9703 <br>安全性用户名和密码： 如在批处理文件中所定制 <br><br>这个收集器实例将开始查找 ModuleSpecAdvertisement 并且应该能找到。然后，它将创建一条管道与已经运行的集中器通信。您应看到与此相似的输出： <br><br>清单 9. 收集器（来自 Shell3 的 runcoll.bat 的输出） <br>Reading config file, dwColConfig, and processing...<br>   group to join will be dwtest<br>   collector location is  Timbuktu North<br>Starting Jxta...<br>Joining default NetPeerGroup...<br>Attempting to join group: dwtest<br>remote group discovery message sent<br>group joined successfully<br>group dwtest joined successfully<br>Searching for collector's MSA...<br>Looking for ModuleSpecAdvertisement, please wait...<br>   cannot find it locally, trying remote<br>.. found collector's MSA<br>Extracting pipe adv from MSA...<br>Connecting to concentrator network...<br>pipe created successfully<br>... collecting data....<br>... data collected, sending to concentrator<br>waiting until next sample...<br>... collecting data....<br>... data collected, sending to concentrator<br>waiting until next sample...<br><br> <br><br>请注意，数据被收集起来并定期发送到集中器服务。当数据穿过 P2P 网络以及两个集中器接收这些数据并进行处理时，请注意观察。 <br><br>高难度的应用模式<br>我
们的气象收集示例说明了这样一个应用模式：在一般的方面，它使用普遍流行的应用 P2P 系统；从特定的方面，它使用
Jxta。这个模式包含两个耦合极其松散的群体：消费者和生产者。当消费者想要生产者所生产的产品时，消费者不愿作出坚定的许诺，也不愿受限于特定生产
者。在这种想法背后可能有几个现实动机。消费者可能想： <br><br>可以在任意时间进行选择，以选择最佳的可用生产者<br><br><br>降低对某个生产者的成功或失败的依赖风险<br><br><br>从非常庞大的动态社区中选择，这种社区的大小和拓扑结构在物理上是难于管理的<br>当
消费者群体和生产者群体出现交迭时，这种模式变得十分有趣，当前可用的、流行的、世界范围内的文件共享系统就例证了这一点。与传统的联网技术不同，P2P
系统从一开始就是设计来适应这种应用模式的。特别地，与使用传统的客户机／服务器技术进行设计时，必须提供的复杂的解决方案不同，Jxta
使得创建这些系统既容易又轻松。 <br><br>超越 TCP/IP 的联网<br>为了真正突出 Jxta
带来的价值，我选择了全球气象信息收集系统作为一个示例。然而，这个问题及解决方案具有许多业务模式（business
scenario）的典型特征，这些业务情形如移动销售队伍自动化、商品贸易、内容分发和企业到企业电子商务等等，可以列出很多。您可以同时使用
P2P 网络和传统的客户机／服务器网络，从而构建大大超出当今静态边界的新型网络解决方案。开放源代码的 Jxta
平台将是这些新型解决方案的实现工具。我希望本系列已经激起您探索 Jxta 提供的可能性的愿望。 <br><br>from-ibm developer</span><br><img src ="http://www.cppblog.com/gnupython/aggbug/2405.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gnupython/" target="_blank">heart in the world</a> 2006-01-03 20:02 <a href="http://www.cppblog.com/gnupython/articles/2405.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>