RMI之所以使用的范围受限制主要有两方面原因,其一:必须要是java,平台的异构性受到限制;其二:穿越防火墙不方便。这里主要谈谈RMI如何通过固定分配端口来穿越防火墙。 RMI穿越防火墙不方便主要是因为除了RMI服务注册的端口(默认1099)外,与RMI的通讯还需要另外的端口来传送数据,而另外的端口是随机分配的,所以要想RMI的客户能通过防火墙来与RMI服务通讯,则需要能让随机分配的端口固定下来,具体做法如下:
1、增加一个文件SMRMISocket.java
import java.rmi.server.*;
import java.io.*;
import java.net.*;
public class SMRMISocket extends RMISocketFactory {
public Socket createSocket(String host, int port) throws IOException{
return new Socket(host,port);
}
public ServerSocket createServerSocket(int port) throws IOException {
if (port == 0)
port = 10990; //不指定就随机分配了
return new ServerSocket(port);
}
}
2、在实例化UnicastRemoteObject的子类前加入一下代码:
[java] view plaincopyprint?
try {
RMISocketFactory.setSocketFactory(new SMRMISocket());
} catch (Exception ex) {
}
这样的话RMI分配的端口就被固定了,防火墙只需要打开1099和10990端口即可。
---------------------------------------------------------------------------------------------------------------------------------
在用RMI做服务监控的时候碰到两个问题:
1. InetAddress.getLocalHost().getHostAddress(); 报错UnknowHost
linux /etc/hosts 加主机名以及映射
hostname hostname -i 能正确获取到就ok
----------------------------------------------------------------------------------------------------------------------------------
2. 先记录问题
1) 服务端重启客户端报错的问题
http://forum.springsource.org/showthread.php?t=61575
at monitor.SendHeartBeatThread.run(SendHeartBeatThread.java:32)
Caused by: java.rmi.NoSuchObjectException: no such object in table
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:275)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:252)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:161)
at org.springframework.remoting.rmi.RmiInvocationWrapper_Stub.invoke(Unknown Source)
at org.springframework.remoting.rmi.RmiClientInterceptor.doInvoke(RmiClientInterceptor.java:397)
at org.springframework.remoting.rmi.RmiClientInterceptor.doInvoke(RmiClientInterceptor.java:343)
... 5 more
<bean id="beanId" class="org.springframework.remoting.rmi.RmiProxyFa ctoryBean">
<property name="serviceUrl" value="rmi://127.0.0.1:6666/appName"/>
<property name="serviceInterface" value="test.HelloI"/>
<!--property name="cacheStub" value="false"/-->
<property name="lookupStubOnStartup" value="false"/>
<property name="refreshStubOnConnectFailure" value="true"/>
</bean>
因为RMI stub被连接到特定的端点,不仅仅是为每个调用打开一个给定的目标地址的连接,所以如果重新启动RMI端点主机的服务器,那么就需要重新注册这些stub,并且客户端需要再次查询它们。
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl">
<value>${showcasewiz.report.serviceurl}</value>
</property>
<property name="serviceInterface">
<value>com.meetexpo.showcase.backend.service.ReportService</value>
</property>
</bean>
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl">
<value>${showcasewiz.report.serviceurl}</value>
</property>
<property name="serviceInterface">
<value>com.meetexpo.showcase.backend.service.ReportService</value>
</property>
</bean>
----------------------------------------------------------------------------------------------------------------------------------
2) 内网(局域网)间访问明明指定一个ip确变成另一个ip的情况)
Exception in thread "main" org.springframework.remoting.RemoteConnectFailureException: Cannot connect to remote service [rmi://218.206.203.3:9902/cmpayNotice]; nested exception is java.rmi.ConnectException: Connection refused to host: 10.97.164.26; nested exception is:
java.net.ConnectException: Connection timed out: connect
Caused by: java.rmi.ConnectException: Connection refused to host: 10.97.164.26; nested exception is:
java.net.ConnectException: Connection timed out: connect
以下from:http://dd2086.iteye.com/blog/362995
出错堆栈:
org.springframework.remoting.RemoteConnectFailureException: Cannot connect to remote service [rmi://192.168.2.61/Service]; nested exception is java.rmi.ConnectException: Connection refused to host: 192.168.7.11; nested exception is:
java.net.ConnectException: Connection timed out: connect
很奇怪,rmi访问的url是对的,但是后续的访问得到的IP却是双网卡中的另外一个无法访问的。
在本机做个简单试验:
System.out.println(UnicastRemoteObject.exportObject(new Remote(){},0));
输出:
Proxy[Remote,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:[192.168.2.3:2339](local),objID:[0]]]]]
说明对象在没有注册出去的时候其IP就已经决定,绑定出去以后客户端就按照这个IP按图索骥。Server端有两个网卡,乱找一个就Over了。
这种方式对分布式对象注册很有用,但是碰到多IP的情况下就比较弱智了。sun的faq上给出一个简单答案:
http://java.sun.com/j2se/1.5.0/docs/guide/rmi/faq.html#netmultihomed
一句话:
System.setProperty("java.rmi.server.hostname","192.168.2.3");//建议从配置文件加载。
或
java -Djava.rmi.server.hostname=xxx -jar xxx.jar
http://yangwencan2002.iteye.com/blog/284249
http://hi.baidu.com/wolf55/item/1676aa0b41184417cd34ea52
相关推荐
rmi技术客户端调用服务器的函数解决问题 刚刚开始准备这个rmi作业的时候,我都有点无从下手。于是我先开始一起找资料,看书,经过不断的尝试编码,以及总结错误,为后期的工作奠定了基础。 在基础知识基本搞定的...
- **异常处理**:RMI调用可能遇到网络中断、远程对象不存在等问题,因此客户端需要适当地捕获和处理`java.rmi`包下的异常,如`RemoteException`。 3. **RMI通信机制**: - **marshalling**与**unmarshalling**:...
在 ServerCSPDataSwitch 类中,我们使用 Properties 对象来读取 RMI 绑定 URL 的 IP 地址和端口,然后使用这些信息来绑定 RMI 服务。 RMI 接口实现可以帮助我们实现远程方法调用,提高系统的可扩展性和灵活性。同时...
本项目使用socket直接发送数据包来攻击rmi,通过反序列化攻击rmi,双击直接运行,对1099端口的rmi服务直接进行漏洞检测。
- **端口冲突**:RMI默认使用1099端口,可能与其他应用冲突,可更改RMI注册表端口。 - **安全性**:RMI默认使用匿名连接,可能需要配置SSL或特定的安全策略文件。 - **异常处理**:处理`RemoteException`,特别是...
- **安全性**:RMI通信可能会暴露于网络攻击,因此需要考虑使用SSL/TLS加密通信,以及限制RMI端口的访问权限。 - **数据一致性**:虽然RMI提供了近乎实时的数据同步,但不保证完全的一致性。在设计系统时,需要考虑...
在Spring Boot应用中,可以通过配置文件(application.properties或application.yml)设置RMI端口和服务,自动暴露RMI接口。 ### 7. 示例代码 创建远程接口: ```java public interface MyRemoteService extends ...
- 客户端需要知道服务器的IP地址和端口号,然后使用相同的`SslRMIClientSocketFactory`创建连接,以确保安全的RMI通信。客户端将通过调用服务器上的Service来建立连接。 以下是一个简单的例子,展示了如何在同一台...
在实际应用中,还需要配置JVM的RMI端口和其他网络参数。 在“www.pudn.com.txt”和“rmi”这两个文件中,可能包含了关于RMI的详细教程、代码示例或配置说明。例如,“www.pudn.com.txt”可能是一个文档,详细解释了...
对象注册表通常运行在一个已知端口上(默认为1099)。服务器启动后,会将对象以文本形式注册到对象注册表中。客户端在调用远程方法之前,必须首先联系对象注册表以获取对远程对象的访问权限。 #### 三、RMI中的对象...
-- RMI注册表的端口号 --> ``` 4. 启动RMI服务器:运行包含上述配置的Spring应用,RMI服务将自动注册到RMI注册表。 在"springmvcclient"文件中,我们有客户端代码。客户端通过Spring的`RmiProxyFactoryBean`来获取...
默认情况下,RMI注册表监听1099端口。`rebind()`方法的参数`//localhost/MyServer`指定了注册表的位置以及要绑定的名称。 4. **安全性**: - RMI支持安全特性,如SSL/TLS加密,以及通过JAAS(Java Authentication ...
-- RMI服务器端口 --> <bean id="rmiServiceExporter" class="org.springframework.remoting.rmi.RmiServiceExporter"> <property name="service" ref="myService" /> <!-- 引用要发布的服务 --> ...
5. 配置:可能需要配置JVM的RMI端口(默认1099),以及防火墙设置,确保通信不受阻碍。 6. 运行:启动客户端,查找并调用远程对象。 四、RMI优点 1. 简化分布式编程:RMI提供了透明的远程调用,开发者无需关注网络...
为了使这些批处理文件正常工作,需要确保JRE环境已安装,RMI相关的端口(默认为1099)未被占用,且服务器端和客户端之间的网络通信畅通。同时,由于RMI依赖于Java的序列化机制,所以远程对象及其返回值必须是可序列...
10. **部署与配置**:RMI应用需要正确配置JVM的RMI服务,包括设置RMIREGISTRY端口、JDK的`.policy`文件以指定安全策略,以及可能的防火墙或安全组规则。 在“基于RMI的远程控制”项目中,开发者可能创建了一个包含...
在`Naming.bind()`中,传入的RMI协议字符串会被解析,然后基于主机和端口创建Registry实例。在Client端执行`bind()`操作时,调用的是Stub的`bind()`,这个过程中可能涉及反序列化。因此,理解这一流程可以帮助我们...
2. **安全**: RMI调用可能涉及跨网络的安全问题,因此需要配置合适的权限控制和认证机制。 3. **异常处理**: 需要适当地处理网络中断、服务器不可达等异常情况。 4. **性能优化**: 考虑缓存远程对象的引用,减少不必...
日志管理对于分布式系统来说至关重要,因为它可以帮助开发者追踪和调试系统中的问题。通常,日志管理器会提供记录、存储、检索和分析日志信息的功能。 在实际应用中,RMI还可以与其他技术结合,比如EJB(Enterprise...
在实验过程中,可能遇到的问题包括网络配置、权限问题、序列化异常(`RemoteException`)等,这些都是学习RMI时常见的挑战。 通过RMI,我们可以构建分布式系统,比如分布式数据库、负载均衡服务、分布式计算等。RMI...