`
tcxiang
  • 浏览: 89523 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

rmi端口问题

 
阅读更多

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,并且客户端需要再次查询它们。

     虽然目标服务的重新注册在重新启动时通常会自动发生,不过此时客户端保持的stub将会变的陈旧,且客户端不会注意这些,除非他们再次尝试调用stub上的方法,而这也将throw一个连接失败的异常。
      为了避免这种情形,Spring的RmiProxyFactoryBean提供了一个refreshStubOnConnectFailure的bean属性,如果调用失败,并且连接异常的话,将它设定为true来强制重新自动查询stub。
<bean id="reportService"
  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>
  <property name="refreshStubOnConnectFailure">
    <value>true</value>
  </property>
 </bean>
      stub查询的另一个问题是,目标RMI服务器和RMI注册项在查询时要为可用的。如果客户端在服务器启动之前,尝试查询和缓存该服务stub,那么客户端的启动将会失败(即使还不需要该服务)。
     为了能够惰性查询服务stub,设定RmiProxyFactoryBean的lookupStubOnStarup标志为false。然后在第一次访问时查询该stub,也就是说,当代理上的第一个方法被调用的时候去主动查询stub,同时被缓存。这也有一个缺点,就是直到第一次调用,否则无法确认目标服务是否实际存在。
<bean id="reportService"
  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>
  <property name="lookupStubOnStartup">
     <value>false</value>
  </property>
  <property name="refreshStubOnConnectFailure">
    <value>true</value>
  </property>
 </bean>
还有一个属性就是cacheStub,当它设置为false的时候,就完全避免了stub的缓存,但影响了性能。需要的时候还是可以试试。

 ----------------------------------------------------------------------------------------------------------------------------------

 

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

分享到:
评论
3 楼 Lstoryc 2014-07-09  
tcxiang 写道
java.rmi.server.RMISocketFactory
jdk里面的

恩, 解决了 thx
2 楼 tcxiang 2014-07-05  
java.rmi.server.RMISocketFactory
jdk里面的
1 楼 Lstoryc 2014-06-17  
能提供 RMISocketFactory 这个类具体代码么  谢谢~

相关推荐

    rmi技术客户端调用服务器的函数解决问题

    rmi技术客户端调用服务器的函数解决问题 刚刚开始准备这个rmi作业的时候,我都有点无从下手。于是我先开始一起找资料,看书,经过不断的尝试编码,以及总结错误,为后期的工作奠定了基础。 在基础知识基本搞定的...

    Rmi示例 Rmi代码示例

    - **异常处理**:RMI调用可能遇到网络中断、远程对象不存在等问题,因此客户端需要适当地捕获和处理`java.rmi`包下的异常,如`RemoteException`。 3. **RMI通信机制**: - **marshalling**与**unmarshalling**:...

    RMI接口实现

    在 ServerCSPDataSwitch 类中,我们使用 Properties 对象来读取 RMI 绑定 URL 的 IP 地址和端口,然后使用这些信息来绑定 RMI 服务。 RMI 接口实现可以帮助我们实现远程方法调用,提高系统的可扩展性和灵活性。同时...

    java_rmi漏洞利用工具

    本项目使用socket直接发送数据包来攻击rmi,通过反序列化攻击rmi,双击直接运行,对1099端口的rmi服务直接进行漏洞检测。

    Java RMI 例子 和一些常见问题

    - **端口冲突**:RMI默认使用1099端口,可能与其他应用冲突,可更改RMI注册表端口。 - **安全性**:RMI默认使用匿名连接,可能需要配置SSL或特定的安全策略文件。 - **异常处理**:处理`RemoteException`,特别是...

    Ehcache RMI Replicated Cluster(RMI集群)

    - **安全性**:RMI通信可能会暴露于网络攻击,因此需要考虑使用SSL/TLS加密通信,以及限制RMI端口的访问权限。 - **数据一致性**:虽然RMI提供了近乎实时的数据同步,但不保证完全的一致性。在设计系统时,需要考虑...

    Spring RMI

    在Spring Boot应用中,可以通过配置文件(application.properties或application.yml)设置RMI端口和服务,自动暴露RMI接口。 ### 7. 示例代码 创建远程接口: ```java public interface MyRemoteService extends ...

    JAVA RMI 传输 SSL加密

    - 客户端需要知道服务器的IP地址和端口号,然后使用相同的`SslRMIClientSocketFactory`创建连接,以确保安全的RMI通信。客户端将通过调用服务器上的Service来建立连接。 以下是一个简单的例子,展示了如何在同一台...

    rmi.rar_Java RMI_RMI java_RMI policy.all_rmi

    在实际应用中,还需要配置JVM的RMI端口和其他网络参数。 在“www.pudn.com.txt”和“rmi”这两个文件中,可能包含了关于RMI的详细教程、代码示例或配置说明。例如,“www.pudn.com.txt”可能是一个文档,详细解释了...

    java rmi 参考文档

    对象注册表通常运行在一个已知端口上(默认为1099)。服务器启动后,会将对象以文本形式注册到对象注册表中。客户端在调用远程方法之前,必须首先联系对象注册表以获取对远程对象的访问权限。 #### 三、RMI中的对象...

    SpringRMI小例子

    -- RMI注册表的端口号 --&gt; ``` 4. 启动RMI服务器:运行包含上述配置的Spring应用,RMI服务将自动注册到RMI注册表。 在"springmvcclient"文件中,我们有客户端代码。客户端通过Spring的`RmiProxyFactoryBean`来获取...

    对 RMI 的简单理解

    默认情况下,RMI注册表监听1099端口。`rebind()`方法的参数`//localhost/MyServer`指定了注册表的位置以及要绑定的名称。 4. **安全性**: - RMI支持安全特性,如SSL/TLS加密,以及通过JAAS(Java Authentication ...

    spring RMI 服务(自动把service发布为RMI服务)

    -- RMI服务器端口 --&gt; &lt;bean id="rmiServiceExporter" class="org.springframework.remoting.rmi.RmiServiceExporter"&gt; &lt;property name="service" ref="myService" /&gt; &lt;!-- 引用要发布的服务 --&gt; ...

    关于java RMI分布式程序开发实例

    5. 配置:可能需要配置JVM的RMI端口(默认1099),以及防火墙设置,确保通信不受阻碍。 6. 运行:启动客户端,查找并调用远程对象。 四、RMI优点 1. 简化分布式编程:RMI提供了透明的远程调用,开发者无需关注网络...

    RMI分布式议程服务

    为了使这些批处理文件正常工作,需要确保JRE环境已安装,RMI相关的端口(默认为1099)未被占用,且服务器端和客户端之间的网络通信畅通。同时,由于RMI依赖于Java的序列化机制,所以远程对象及其返回值必须是可序列...

    基于rmi的远程控制

    10. **部署与配置**:RMI应用需要正确配置JVM的RMI服务,包括设置RMIREGISTRY端口、JDK的`.policy`文件以指定安全策略,以及可能的防火墙或安全组规则。 在“基于RMI的远程控制”项目中,开发者可能创建了一个包含...

    RMI反序列化及相关工具反制浅析1

    在`Naming.bind()`中,传入的RMI协议字符串会被解析,然后基于主机和端口创建Registry实例。在Client端执行`bind()`操作时,调用的是Stub的`bind()`,这个过程中可能涉及反序列化。因此,理解这一流程可以帮助我们...

    rmi接口技术详细介绍文档

    2. **安全**: RMI调用可能涉及跨网络的安全问题,因此需要配置合适的权限控制和认证机制。 3. **异常处理**: 需要适当地处理网络中断、服务器不可达等异常情况。 4. **性能优化**: 考虑缓存远程对象的引用,减少不必...

    RMI例子

    日志管理对于分布式系统来说至关重要,因为它可以帮助开发者追踪和调试系统中的问题。通常,日志管理器会提供记录、存储、检索和分析日志信息的功能。 在实际应用中,RMI还可以与其他技术结合,比如EJB(Enterprise...

    RMI应用实例及实验报告

    在实验过程中,可能遇到的问题包括网络配置、权限问题、序列化异常(`RemoteException`)等,这些都是学习RMI时常见的挑战。 通过RMI,我们可以构建分布式系统,比如分布式数据库、负载均衡服务、分布式计算等。RMI...

Global site tag (gtag.js) - Google Analytics