存档
RMI和Socket的比较及区别
本文的测试数据来自国外专家文档,详细介绍如下:
一般来说,基于CS(client-server)软件架构的开发技术有很多种。比较常用的有:基于socket的网络编程、RPC、基于Java技术的RMI(当然C#也有类似技术)、CORBA等。在这里我们只是对基于socket的网络编程与RMI作个对比,有助于我们了解它们各自的应用领域,帮助我们在面对一个具体问题的时候选用适合的技术。另外,本文所做的讨论可以认为是脱离了语言层面的东西,只是对技术的本身做一个讨论,无关乎你是用C++、C#或Java 在开发。
一、RMI技术简介
本文就以Java为例,简单介绍一下RMI技术。
从Java1.1开始,远程方法调用作为Java分布式对象技术成为Java核心的API之一(在java.rmi.* 包)。RMI的引入,使得Java程序之间能够实现灵活的,可扩展的分布式通信。RMI允许Java对象存在于多个不同的地址空间,分布在不同的Java虚拟机上。每一个地址空间可以在同一台主机上或者网络上不同的计算机上。由于远程方法调用跨越不同的虚拟机边界到不同的指定的地址空间,所以没有对象共享的全局变量,这就需要对象序列化(Object Serialization)API,它使得Java对象能够在不同的JVM之间传递。对象序列化是特别为Java的对象设计的,这就意味着Java程序中的对象可以作为对象参数存取(可序列化的对象必须实现Serializable接口)。结合RMI和对象序列化机制,就可以访问越过本地Java虚拟机边界的对象以及数据。通过RMI,可以调用远程对象的远程方法,而通过Java对象序列化机制可以将对象传递给这些方法。
最基本的Java模型并没有提供将远程主机上的Java对象看作本地Java程序地址空间一部分的能力,而RMI祢补了这一不足。另外,由于Java与硬件平台无关的特性,无论是同构的系统还是异构的系统,RMI不需移植就可以顺利运行。
RMI为Java平台的分布式计算提供了一个简单而直接的模型。因为Java的RMI技术是基于Java平台的,所以它将Java平台的安全性和可移植性等优点带到了分布式计算中。RMI大大扩展Java的网络计算能力,它为编写基于分布式对象技术的企业级Internet/Intranet应用提供了强大的系统平台支持。
二、基于socket的网络编程
当你使用socket进行网络应用开发的时候,一般的思路是“消息驱动逻辑”,即这样的软件系统一般具有以下特点:
(1) 客户端与服务器端依靠消息进行通讯。
(2) 客户端或者服务器端都需要一个消息派遣器,将消息投递给具体的massage handler
(3) 客户端或者服务器端利用massage handler进行逻辑事务处理
三、RMI Vs Sochet
RMI技术比较socket的网络编程主要有以下几个方面:
第一、.RMI是面向对象的,而后者不是。
第二、.RMI是与语言相绑定的。比如当你使用Java RMI技术的时候,客户端与服务器端都必须使用Java开发。而socket的网络编程是使用独立于开发语言的,甚至独立于平台。基于socket的网络编程,客户端与服务器端可以使用不同开发语言和不同的平台。
第三、从网络协议栈的观点来看,RMI与socket的网络编程处于不同层次上。基于socket的网络编程位于TCP协议之上,而RMI在TCP协议之上,又定义了自己的应用协议,其传输层采用的是Java远程方法协议(JRMP)。可见,在网络协议栈上,基于RMI的应用位置更高一些,这也决定了,与socket的网络编程相比,RMI会丧失一些灵活性和可控性,但是好处是它带给了应用开发者更多的简洁,方便和易用。比如:如果你用的是RMI,你不需要关心消息是怎么序列化的,你只需要像本地方法调用一样,使用RMI。代价是:应用开发者无法很好地控制消息的序列化机制。
第四、这是最后一点不同,我认为也是比较重要的一点,就是两种方法的性能比较,其往往决定着你将使用那种技术来开发你的应用。以下引用Adrian Reber在Network-programming with RMI文中对TCP和RMI所做的一个比较,其做的实验主要是对两者在网络传输的带宽上作的对比: 在网络上传输2 byte的有效数据,对于TCP而言,总共有478 byte被额外传输,而对于RMI, 1645byte被额外传输。
以下是两者的trace结果:
TCP:
46037 > 12345 [SYN] Seq=801611567 Ack=0 Win=5840 Len=0
12345 > 46037 [SYN, ACK] Seq=266515894 Ack=801611568 Win=10136 Len=0
46037 > 12345 [ACK] Seq=801611568 Ack=266515895 Win=5840 Len=0
12345 > 46037 [PSH, ACK] Seq=266515895 Ack=801611568 Win=10136 Len=1
46037 > 12345 [ACK] Seq=801611568 Ack=266515896 Win=5840 Len=0
12345 > 46037 [FIN, PSH, ACK] Seq=266515896 Ack=801611568 Win=10136 Len=1
46037 > 12345 [RST, ACK] Seq=801611568 Ack=266515898 Win=5840 Len=0
RMI:
42749 > rmiregistry [SYN, ECN, CWR]
Seq=3740552479 Ack=0 Win=32767 Len=0
rmiregistry > 42749 [SYN, ACK, ECN]
Seq=3749262223 Ack=3740552480 Win=32767 Len=0
42749 > rmiregistry [ACK] Seq=3740552480 Ack=3749262224 Win=32767 Len=0
JRMI, Version: 2, StreamProtocol
rmiregistry > 42749 [ACK] Seq=3749262224 Ack=3740552487 Win=32767 Len=0
JRMI, ProtocolAck
42749 > rmiregistry [ACK] Seq=3740552487 Ack=3749262240 Win=32767 Len=0
Continuation
rmiregistry > 42749 [ACK] Seq=3749262240 Ack=3740552506 Win=32767 Len=0
JRMI, Call
rmiregistry > 42749 [ACK] Seq=3749262240 Ack=3740552556 Win=32767 Len=0
JRMI, ReturnData
42749 > rmiregistry [ACK] Seq=3740552556 Ack=3749262442 Win=32767 Len=0
JRMI, Ping
JRMI, PingAck
42749 > rmiregistry [ACK] Seq=3740552557 Ack=3749262443 Win=32767 Len=0
JRMI, DgcAck
42749 > rmiregistry [FIN, ACK]
Seq=3740552572 Ack=3749262443 Win=32767 Len=0
rmiregistry > 42749 [FIN, ACK]
Seq=3749262443 Ack=3740552573 Win=32767 Len=0
42749 > rmiregistry [ACK] Seq=3740552573 Ack=3749262444 Win=32767 Len=0
实验的结果是:RMI与TCP based socket相比,传输相同的有效数据,RMI需要占用更多的网络带宽(protocol overhead)。从这里,我们可以得出一个一般性的结论:RMI主要是用于远程方法的”调用“(RMI是多么的名符其实:)),其技术内涵强调的是“调用”,基于此,我能想到的是:移动计算,和远程控制,当你的应用不需要在client与server之间传输大量的数据时,RMI是较好的选择,它简洁、易于开发。但是,一旦你的应用需要在client与server之间传输大量的数据,极端的,比如FTP应用,则RMI是不适合的,我们应该使用socket。
四、参考资料:
Network-programming with RMI, by Adrian Reber, URL:
http://42.fht-esslingen.de/~adrian/master/rmi.pdf
Popularity: unranked [?]
游戏多服务器的用户身份认证方案
这篇文章转载 云风大哥的优秀博文,内容如下:
当游戏服务器群达到一定规模后,让用户只从一个入口连入会给这个入口带来很大的压 力。这样,我们就需要让服务器群中的多台机器都允许用户直接连接。
当服务器开放给用户直接登陆后,必须面临的一个问题就是用户身份认证的问题。
大多数提供网络服务的公司都做了一套统一的用户认证系统,比如微软的 passport ,网易的通行证,等等。为了避免重复验证用户身份而给用户认证系统带来过大的负担,云风在这里给出一个参考解决方案。
登陆服务器可以只有一台,专门用于用户第一次登陆的身份认证。它认证完用户的身份 后,则发放一个游戏系统内部用的临时通行证给用户,用户可以拿着这个临时通行证到指定的地点玩游戏。
我们需要讨论的是,以上流程中的安全问题,以及如何加强安全性。
用户认证过程自然不能传送用户密码的全部信息,这跟密码是否加密无关。简单的安全措施是先由登陆服务器发送一个随机串给用户,用户把这个字符串同自 己的密码连接起来,并 md5 以后传回服务器做验证。(这里用 md5 指代一种特定的不可逆 hash 算法)
临时通行证的生成可以是这样: 登陆服务器从数据库中取得用户所属的服务器 id (通常是他最后一次登陆的位置,或者游戏逻辑认为他所在位置)、用户的游戏 id (往往不同于他的用户名)、一个约定字符串、一个顺序版本号、一些随机字节、把它们连在作一次 des 加密(这里用 des 指代一种特定的可逆密匙加密算法)。每生成一次临时通行证,版本号递增。加密临时通行证的密码由登陆服务器与每个可以接受用户直接连接的服务器约定,永远 不传送给用户。
用户拿到这个临时通行证后,可以用之一次性登陆指定服务器。直到从服务器正常登出,若需切入新服务器,可由老服务器生成下一份临时通行证。临时通行 证由于被服务器加密,所以对用户来说是一串无意义字符串,故而无法伪造。
临时通行证传送给用户时,可用用户自己的密码之 md5 值(或者连接一个约定串增加安全性)做密匙加密。这样不知道密匙的人截获数据包也不能获得临时身份证。而临时身份证总是一次有效,且只针对特定服务器(服 务器会检查临时通行证中包含的版本号、服务器 id ),企图用临时身份证多次登陆也会失败。
Popularity: unranked [?]
JodConverter(Openoffice)支持的格式
JODConverter automates conversions that are actually performed by OpenOffice.org. This means that if you can convert from format ABC to format XYZ from OpenOffice.org (by opening ABC and saving/exporting to XYZ) then you can do the same with JODConverter. You just have to discover the magic string used by OpenOffice.org as the export filter name. A useful list can be found in the OpenOffice.org Wiki.
That said, JODConverter maintains a registry of the most common formats, their associated file extensions, mime types, and OpenOffice.org filter names to simplify your life. These predefined conversions are shown in the following table:
| From (any of) | To (any of) |
| Text Formats | |
| OpenDocument Text (*.odt) OpenOffice.org 1.0 Text (*.sxw) Rich Text Format (*.rtf) Microsoft Word (*.doc) WordPerfect (*.wpd) Plain Text (*.txt) HTML1 (*.html) |
Portable Document Format (*.pdf) OpenDocument Text (*.odt) OpenOffice.org 1.0 Text (*.sxw) Rich Text Format (*.rtf) Microsoft Word (*.doc) Plain Text (*.txt) HTML2 (*.html) MediaWiki wikitext (*.wiki) |
| Spreadsheet Formats | |
| OpenDocument Spreadsheet (*.ods) OpenOffice.org 1.0 Spreadsheet (*.sxc) Microsoft Excel (*.xls) Comma-Separated Values (*.csv) Tab-Separated Values (*.tsv) |
Portable Document Format (*.pdf) OpenDocument Spreadsheet (*.ods) OpenOffice.org 1.0 Spreadsheet (*.sxc) Microsoft Excel (*.xls) Comma-Separated Values (*.csv) Tab-Separated Values (*.tsv) HTML2 (*.html) |
| Presentation Formats | |
| OpenDocument Presentation (*.odp) OpenOffice.org 1.0 Presentation (*.sxi) Microsoft PowerPoint (*.ppt) |
Portable Document Format (*.pdf) Macromedia Flash (*.swf) OpenDocument Presentation (*.odp) OpenOffice.org 1.0 Presentation (*.sxi) Microsoft PowerPoint (*.ppt) HTML2 (*.html) |
| Drawing Formats | |
| OpenDocument Drawing (*.odg) | Scalable Vector Graphics (*.svg) Macromedia Flash (*.swf) |
1 HTML can be used as an input format but you should not expect OpenOffice.org to properly render complex web pages as Firefox or IE7 do. Works reasonably well for simple and “printer friendly” web pages only.
2 HTML can be used as an output format but while all other formats always generate a single output file, HTML can produce multiple files. In addition to the HTML file in fact, any images contained in the input document will also be saved in the same directory. This requires extra care in your code, especially in a web environment.
Openoffice官方的說明如下:
http://wiki.services.openoffice.org/wiki/Framework/Article/Filter
Popularity: unranked [?]
为Openoffice.org创建服务
官方的说明如下:
Windows系统:
Creating a Windows Service lets you have an OpenOffice.org instance always running as a service and listening for connections. That’s what you usually want to do on a server machine. Here is one way to create a Windows Service: use the SRVANY utility that you can download for free as part of the Resource Kit. (This was done on an XP SP2, YMMV.)
- I assume you already installed OpenOffice.org and started at least once under the current user
- Download and install the Windows Server 2003 Resource Kit Tools
- Read How To Create a User-Defined Service
- Create a service named OpenOfficeUnoServer following the instructions above; as the Application registry value use C:\Program Files\OpenOffice.org 2.0\program\soffice.exe
- Add another value to the Parameters key named AppParameters and set it to -headless -accept=socket,port=8100;urp;
- From Control Panel / Administrative Tools / Services open the Properties for the new service and change the Log On account to be Local Service which is a more secure option than SYSTEM
- If we stop here the service will start but not actually work. That’s because the service runs as a special account and OpenOffice.org will try to show the license agreement dialog as if it was a new user instead of starting the application. To avoid this, you need to edit share\registry\data\org\openoffice\Setup.xcu (it’s an XML file) inside the OpenOffice.org installation directory and replace this bit
<prop oor:name="ooSetupInstCompleted"> <value>false</value> </prop> <prop oor:name="ooSetupShowIntro"> <value>true</value> </prop>
with this other one (replace the date with today’s date; it must be later than the OOo installation time)
<prop oor:name="ooSetupInstCompleted" oor:type="xs:boolean"> <value>true</value> </prop> <prop oor:name="LicenseAcceptDate" oor:type="xs:string"> <value>2006-07-25T17:34:04</value> </prop> <prop oor:name="FirstStartWizardCompleted" oor:type="xs:boolean"> <value>true</value> </prop>
- Start your new service (e.g. from Control Panel / Administrative Tools / Services)
- You may need to unblock the new service at the firewall level
- From a command prompt do
> netstat -anp tcp
this should show a listening on port 8100. Chances are that the service will only listen on the 127.0.0.1 interface; this means you can only connect from the same machine and it’s good from a security point of view. However, if you want to be able to connect from other machines as well you need to change the accept string to "socket,host=0.0.0.0,port=8100;urp;" in the AppParameters registry value
Linux/UNIX系统
Creating a SysV-style init script for starting OpenOffice.org is not difficult but the details depend on your particular OS flavour/distribution.
The tricky part is that OpenOffice.org requires an X server to work. On a headless server, you can use Xvfb as a dummy display for OpenOffice.org.
However since OpenOffice.org 2.3 an X server server is no longer needed; it is now possible to start OpenOffice.org in “true” headless mode simply by making sure the DISPLAY environment variable is not defined:
$ unset DISPLAY $ soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
Popularity: unranked [?]
JodConverter实现Office转化PDF格式
使用SUN公司的Openoffice完成office(Word,Excel,Powerpoint)向pdf文档转化
1,将目录下的所有DOC格式的文件转化成PDF格式的文件
java -jar lib/jodconverter-cli-2.2.0.jar -f pdf *.doc
java -jar JConverterCommand.jar -f pdf F:\*.doc
2,转换制定的文件
java -jar lib/jodconverter-cli-2.2.0.jar document.doc document.pdf
java -jar JConverterCommand.jar c:\aaa.doc c:\aaa.pdf
介绍如下:
OpenOffice.org具有一个鲜为人知的特性就是其能够作为一个服务来运行,而这种能力具有一定的妙用。举例来说,你可以把openoffice.og变成一个转换引擎,利用这种转换引擎你可以通过网络接口或命令行工具对文件的格式进行转换,JODConverter可以帮助你实现OpenOffice.org的这种文件转换功能。
为了将OpenOffice.org作为一个转换引擎,你必须以服务的方式将它启动,使它在某个特定的端口监听连接,在Linux平台你可以用如下的命令启动openoffice.org:
soffice -headless -accept=”socket,port=8100;urp;”
在Windows平台, 使用如下命令:
“C:\Program Files\OpenOffice.org 2.2\program\soffice” -accept=”socket,port=8100;urp;”
JODConverter是基于java,你需要安装1.4或更高版本的java运行环境。下载最新版本的jodconverter-tomcat-x.x.x.zip,解压到某个目录,就可以启动 JODConverter
sh jodconverter-tomcat-2.1.1/bin/startup.sh
在浏览器打开http://localhost:8080/converter,你就可以看见一个简单的Web界面,选中需要转换的文件并确定格式,点击按钮就可以转换。也可以通过命令行对文件进行转换,如:
java -jar jodconverter-2.1.1/lib/jodconverter-2.1.1.jar loremipsum.odt loremipsum.pdf
Popularity: unranked [?]
解决 This function has none of DETERMINISTIC
今天遇到了这个问题,很郁闷,只需要在 MSYQL中执行一行命令就搞定了,代码如下:
SET GLOBAL log_bin_trust_function_creators = 1;
官方解释如下:
In general, the issues described here result from the fact that binary logging occurs at the SQL statement level. A future MySQL release is expected to implement row-level binary logging, which specifies the changes to make to individual rows as a result of executing SQL statements.
Unless noted otherwise, the remarks here assume that you have enabled binary logging by starting the server with the --log-bin option. (See Section 5.2.3, “The Binary Log”.) If the binary log is not enabled, replication is not possible, nor is the binary log available for data recovery.
The development of stored routine logging in MySQL 5.0 can be summarized as follows:
- Before MySQL 5.0.6: In the initial implementation of stored routine logging, statements that create stored routines and
CALLstatements are not logged. These omissions can cause problems for replication and data recovery. - MySQL 5.0.6: Statements that create stored routines and
CALLstatements are logged. Stored function invocations are logged when they occur in statements that update data (because those statements are logged). However, function invocations are not logged when they occur in statements such asSELECTthat do not change data, even if a data change occurs within a function itself; this can cause problems. Under some circumstances, functions and procedures can have different effects if executed at different times or on different (master and slave) machines, and thus can be unsafe for data recovery or replication. To handle this, measures are implemented to allow identification of safe routines and to prevent creation of unsafe routines except by users with sufficient privileges. - MySQL 5.0.12: For stored functions, when a function invocation that changes data occurs within a non-logged statement such as
SELECT, the server logs aDOstatement that invokes the function so that the function gets executed during data recovery or replication to slave servers. For stored procedures, the server does not logfunc_name()CALLstatements. Instead, it logs individual statements within a procedure that are executed as a result of aCALL. This eliminates problems that may occur when a procedure would follow a different execution path on a slave than on the master. - MySQL 5.0.16: The procedure logging changes made in 5.0.12 allow the conditions on unsafe routines to be relaxed for stored procedures. Consequently, the user interface for controlling these conditions is revised to apply only to functions. Procedure creators are no longer bound by them.
- MySQL 5.0.17: Logging of stored functions as
DOstatements (per the changes made in 5.0.12) are logged asfunc_name()SELECTstatements instead for better control over error checking.func_name()
As a consequence of the preceding changes, the following conditions currently apply to stored function creation when binary logging is enabled. These conditions do not apply to stored procedure creation.
- To create or alter a stored function, you must have the
SUPERprivilege, in addition to theCREATE ROUTINEorALTER ROUTINEprivilege that is normally required. - When you create a stored function, you must declare either that it is deterministic or that it does not modify data. Otherwise, it may be unsafe for data recovery or replication. Two sets of function characteristics apply here:
- The
DETERMINISTICandNOT DETERMINISTICcharacteristics indicate whether a function always produces the same result for given inputs. The default isNOT DETERMINISTICif neither characteristic is given, so you must specifyDETERMINISTICexplicitly to declare that a function is deterministic.Use of the
NOW()function (or its synonyms) orRAND()does not necessarily make a function non-deterministic. ForNOW(), the binary log includes the timestamp and replicates correctly.RAND()also replicates correctly as long as it is invoked only once within a function. (You can consider the function execution timestamp and random number seed as implicit inputs that are identical on the master and slave.)SYSDATE()is not affected by the timestamps in the binary log, so it causes stored routines to be non-deterministic if statement-based logging is used. This does not occur if the server is started with the--sysdate-is-nowoption to causeSYSDATE()to be an alias forNOW(). - The
CONTAINS SQL,NO SQL,READS SQL DATA, andMODIFIES SQL DATAcharacteristics provide information about whether the function reads or writes data. EitherNO SQLorREADS SQL DATAindicates that a function does not change data, but you must specify one of these explicitly because the default isCONTAINS SQLif no characteristic is given.
By default, for a
CREATE FUNCTIONstatement to be accepted,DETERMINISTICor one ofNO SQLandREADS SQL DATAmust be specified explicitly. Otherwise an error occurs:ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
Assessment of the nature of a function is based on the “honesty” of the creator: MySQL does not check that a function declared
DETERMINISTICis free of statements that produce non-deterministic results. - The
- To relax the preceding conditions on function creation (that you must have the
SUPERprivilege and that a function must be declared deterministic or to not modify data), set the globallog_bin_trust_function_creatorssystem variable to 1. By default, this variable has a value of 0, but you can change it like this:mysql>
SET GLOBAL log_bin_trust_function_creators = 1;You can also set this variable by using the
--log-bin-trust-function-creators=1option when starting the server.If binary logging is not enabled,
log_bin_trust_function_creatorsdoes not apply andSUPERis not required for routine creation.
Popularity: unranked [?]
Linux查看某个端口是否被占用
查看 5038 是否被占用 :
方法一: lsof -i tcp:5038
方法二:netstat -ae |grep 5038
Popularity: unranked [?]
解决Java打包成Jar找不到文件问题
使用这个就可以了 getClass().getResourceAsStream(”/source/config.xml”)
例:
Element root = dombuilder.parse(getClass().getResourceAsStream(”/config.xml”)).getDocumentElement();
Popularity: unranked [?]
最近评论