`
tcxiang
  • 浏览: 85063 次
  • 性别: 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作业的时候,我都有点无从下手。于是我先开始一起找资料,看书,经过不断的尝试编码,以及总结错误,为后期的工作奠定了基础。 在基础知识基本搞定的...

    java_rmi漏洞利用工具

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

    RMI接口实现

    java rmi 接口,使用WEB工程外的类访问WEB工程中的类,客户端的类访问远程服务端的类

    Rmi组件

    java的Rmi组件,在服务端部署RmiServer.jar 以: java -jar RmiServer.jar 1199(端口号) 启动 &lt;br&gt;在客户端部署RmiClient.jar 直接调用其API即可完成对服务端后台程序的远程调用

    RMI 的全套使用

    // 数据端口,0表示端口由RMI服务器动态生成. private Remote stub; public RMIServer() { } /* * 使用默认端口,默认服务器名称,服务路径构造函数 use the default port,server name and the url */ public...

    serialRMI:java rmi服务注册表串行端口通信

    串行RMI 该程序将创建一个RMI服务,该服务可让您与串行端口进行通信。 RXTX库( )用作串行端口的连接器。 到现在为止,RMI服务实现了以下功能: String read() void write(String str) void writeLine(String str) ...

    RMI-IIOP Java 源码实例.rar

    RMI-IIOP Java 源码实例,附有BAT批处理命令,Java EJB初学者可参考学习,EJB的例子。

    Java RMI实例

    简单实现了Java RMI实例,需手动更改IP和端口~

    基于RMI分布计算实例

    可以单机模拟多台电脑的环境。当然也可以在Eclipse中配置运行时程序的参数来运行程序(运行时参数主要负责传递端口号,服务器地址等)。

    Java开发基于rmi的数据库中间件设计源码,并利用中间件建立一个数据库应用(Java web项目),分布式对象技术课程实践

    Java开发基于rmi的数据库中间件设计源码,并利用中间件建立一个数据库应(Java web项目),...绑定Rmi服务端口和主机(如果Rmi服务放在远程主机需要注意避开防火墙,并绑定主机,更有甚者需要指定另外一个通信端口)

    Java RMI 远程调用实例.rar

     PERFECTTIME.JAVA:向RMI注册服务,以便客户端查找,创建提供注册服务的本地对象,参数为端口号,也可以在Dos窗口下,执行start rmiregistry port启动此服务,注册把PerfectTime注册到机器192.8.200.27,端口2005,名为...

    java rmi示例

    该项目是maven工程,由三个子模块,一个定义api和model实体,一个是远程服务(provider),...需要先build api, 然后再运行远程服务,最后运行调用方,在打包完成后,两者可以运行在不同服务器上,注意:需要修改ip和端口

    jmx监控activeMQ监控

    activeMQ开启jmx固定rmi端口,穿透防火墙,用了一天的时间,踩了无数的坑,拿出来共享.

    启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法

    问题描述  今天一来公司,在IntelliJ IDEA 中启动Tomcat服务器时就出现了如下图所示的错误:  错误: 代理抛出异常错误: java.rmi.server.ExportException: Port already in use: 1099; nested exception is: java...

    RMIDeserialize:RMI 反序列化环境 一步步

    RMIDeserialize RMI反序列化学习环境,细节请参考博客、 java -cp RMIDeserialize.jar com.lala.ServerAndRegister :起一个包含CC链...本地JRMP服务端口&gt;:攻击目标8u231版本以下的RMI服务。 其他功能可以从源码运行。

    java rmi demo2 N个客户端,N个P2P节点,一个服务端

    java rmi demo2 N个客户端,N个P2P节点,一个服务端,客户端连接P2P节点,服务端保存当前所有在线的客户端的IP和端口,客户端相当于我们的电脑。用户上传文件,都从客户端传到P2P节点中,然后每个P2P节点互相传输,...

    state-machine-model

    基于RMI的服务器作者: Divya Nairy(5589575... 如果未提供端口,则使用默认的RMI端口1099。 java BankServerImpl 运行BankClient java BankClient &lt;serverHostname&gt; &lt;severPortnumber&gt; &lt;threadCount&gt; &lt;iterationCo

    rmiscout:RMIScout使用单词列表和蛮力策略来枚举Java RMI函数并利用RMI参数解组漏洞

    通常为端口1099):远程对象注册表服务(rmiregistry) IIOP要求使用JRE 1.8。由于在以后的运行时中已弃用。 RMI SSL 多种操作模式 单词表模式:使用签名的单词表测试远程方法(请参阅随附的list / prototypes.txt...

    JMeter分布式原理,远程启动配置,jmeter在Linux上分布式压测环境搭建配置,命令行运行+问题集合,修改jvm值

    1 slave机器的自定义端口号配置; 2 负载机(Slave)找不到参数文; 3 无数据,依赖文件报错的问题; 4 Server failed to start: java.rmi.server.ExportException: Listen failed on port…找不到指定文件; 5 ...

    Java RMI(Remote Method Invocation)远程方法调用 详解

    编写一个RMI的步骤 定义一个远程接口,此接口需要继承java.rmi.Remote 开发远程接口的实现类 创建一个server并把远程对象注册到端口 创建一个client查找远程对象,调用远程方法 实例 定义一个远程接口 public ...

Global site tag (gtag.js) - Google Analytics