最近用了java的rmi还是不错的,遇到的问题参考网上的文章解决的,做个记录
引自 http://hi.baidu.com/wangdefu/blog/item/4e1e041f8d5bdacaa7866987.html
可以参考Sun的资料去理解rmi http://java.sun.com/developer/onlineTraining/rmi/RMI.html
写一个rmi客户端程序,你可能会收到如标题这样的异常。这个问题其实是由rmi服务器端程序造成的。
客户端程序向服务端请求一个对象的时候,返回的stub对象里面包含了服务器的hostname,客户端的后续操作根据这个hostname来连接服务器端。要想知道这个hostname具体是什么值可以在服务器端bash中打入指令:
hostname -i
如果返回的是127.0.0.1,那么你的客户端肯定会抛如标题的异常了。
解决这个问题有两个方式:
1 修改/etc/hosts
找到127.0.0.1 hostxxxxx这样的字样。把127.0.0.1改成真实的,可供其他机器连接的ip。
这样客户端就能得到真实的ip了。
2 在rmi服务器端程序启动脚本中加上两行,显式指定hostname。我的脚本:
hostname=`hostname`
java -cp $CLASSPATH -Djava.rmi.server.codebase=$codebase -Djava.security.policy=$PROJECT_HOME/se_server/conf/se_server.policy -Djava.rmi.server.hostname=$hostname com.abc.server.StartServer > $PROJECT_HOME/se_server/logs/init.log 2>&1 &
不过该方式有个局限,其他机器肯定能识别ip,但是可能无法识别hostname。
当然,你也可以直接写死这个hostname,比如:-Djava.rmi.server.hostname=xxx.xxx.xxx.xxx。 这样最省力,就是少点灵活性.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cnhome/archive/2009/09/02/4512191.aspx
----------------------------------------------------------------------------------------------------------------------------------------------------------
RMI invocation attempts connecting to 127.0.0.1
Hi
I've exported a bean by using the RmiServiceExporter, and tries to access this bean through the RmiProxyFactoryBean. This works fine when client and server is on the same host, but fails with the following exception when client is set up on a different host. I have ofcourse set the RmiProxyFactoryBean.serviceUrl correctly, and the remote object is found, but as the exception shows it is the invocation of a method on the remote object that fails with a connect failure to 127.0.0.1. Why is the loopback address being used? I found from the javadocs of RmiServiceExporter a suggestion to set -Djava.rmi.server.host , but this does not seem to help. [using spring 2.0]
Exception in thread "main" org.springframework.remoting.RemoteConnectFailureE xception: Cannot connect to remote service [rmi://bernt:2000/Admin]; nested exception is java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused
Caused by: java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEnd point.java:574)
at sun.rmi.transport.tcp.TCPChannel.createConnection( TCPChannel.java:185)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCP Channel.java:171)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:9 4)
at org.springframework.remoting.rmi.RmiInvocationWrap per_Stub.invoke(Unknown Source)
at org.springframework.remoting.rmi.RmiClientIntercep tor.doInvoke(RmiClientInterceptor.java:400)
at org.springframework.remoting.rmi.RmiClientIntercep tor.doInvoke(RmiClientInterceptor.java:344)
at org.springframework.remoting.rmi.RmiClientIntercep tor.invoke(RmiClientInterceptor.java:259)
at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :185)
at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:209)
at $Proxy0.settle(Unknown Source)
[CUT]
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl .java:333)
at java.net.PlainSocketImpl.connectToAddress(PlainSoc ketImpl.java:195)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.j ava:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.j ava:366)
at java.net.Socket.connect(Socket.java:519)
at java.net.Socket.connect(Socket.java:469)
at java.net.Socket.<init>(Socket.java:366)
at java.net.Socket.<init>(Socket.java:179)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.cre ateSocket(RMIDirectSocketFactory.java:22)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.cre ateSocket(RMIMasterSocketFactory.java:128)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEnd point.java:569)
... 24 more
---------
Finally figured this out. RMI uses the following method to obtain a server hostname:
http://java.sun.com/j2se/1.4.2/docs/...ml#nethostname
In my case the IP returned was 127.0.0.1 due to the setup on my linux box
(see http://www.jguru.com/faq/view.jsp?EID=790132).
By changing the OS setup i got the correct external IP address returned.
Strange though that neither -Djava.rmi.server.host=$HOSTNAME nor -Djava.rmi.server.useLocalHostname=true did the job.
Well, since I didn't have time to wait for a reply, I went ahead and banged my head against it for a little while and figured out what to do. After re-reading the links from thosmas' posts, I realized that it was the hosts file on the server that needed to be fixed. If your hosts file has the first line as: Code: 127.0.0.1 localhost {hostname} you must remove the {hostname} from that first line and add another line like: Code: {actual ip address} {hostname} That worked for me. |
---------------------------------------------------------------------------------------------------------------------------------------------------------
其他参考:
==============================================================================================
==============================================================================================
How does RMI obtain a server hostname in each of the versions of the JDK?
Methods that RMI uses to obtain a server hostname in each of the versions of the JDK:
JDK v1.1
RMI relied upon
java.net.InetAddress.getLocalHost()
to return a fully qualified domain name.
InetAddress
objects initialized local hostnames in a static block of code, performing a reverse lookup on the local IP address to retrieve a local hostname. However, on machines that were not connected to the network, this behavior caused the program to hang while
InetAddress
looked for a hostname that could not be found.
JDK v1.1.1-1.1.6
To work around the JDK v1.1 problem on stand-alone systems,
InetAddress
was modified in JDK v1.1.1 to only retrieve the [potentially unqualified] hostname returned from a native system call, which did not attempt to consult a name service. RMI was not modified to compensate for this change since the property
java.rmi.server.hostname
allowed users to override incorrect hostnames provided by
InetAddress
. RMI made no attempt to consult a name service and could default to using unqualified hostnames.
Later versions
To compensate for the many problems that were generated by the v1.1.1 change in functionality of
InetAddress
, the following behavior has been integrated into the most recent versions of the JDK:
RMI will use an IP address or a fully qualified domain name to identify a machine that serves a remote object. Server hostnames are initialized to the value obtained by performing the following actions:
By default, RMI uses the IP address of the server host as the server name for remote references.
If the property
java.rmi.server.hostname
is set, RMI will use its value as the server hostname, and will not attempt to find a fully qualified domain name through any other method. This property takes precedence over all other means of finding an RMI server name.
If the property
java.rmi.server.useLocalHostname
is set to
true
(by default, the value of this property is
false
), RMI applies the following routine to obtain a hostname for the RMI server:
If the value returned by the
InetAddress.getLocalHost().getHostName()
method contains a "." character, then RMI will assume that this value is the server's fully qualified domain name and will use it as the server hostname.
Otherwise, RMI will spawn a thread to query the local name service for the fully qualified domain name of the RMI server. If the name service takes too long to return, or the name service returns but its response does not contain a "." then RMI will use the server's IP address obtained from
InetAddress.getLocalHost().getHostAddress()
.
Users can override the default time (10 seconds or 10000 milliseconds) that RMI will look for a fully qualified domain name by setting the following property:
sun.rmi.transport.tcp.localHostnameTimeOut
=timeOutMillis
where timeOutMillis is the time that RMI will wait in milliseconds. For example:
java -Dsun.rmi.transport.tcp.localHostnameTimeOut=2000 MyServerApp
When using activatable remote objects, it is recommended that RMI servers set the value of the
java.rmi.server.useLocalHostname
property to
true
. In general, hostnames are more stable than IP addresses. Activatable remote objects tend to last longer than transient remote objects (for example, surviving a reboot). An RMI client will be more likely to locate a remote object over a long period of time if it uses a qualified hostname rather than an explicit IP address.