Java RMI:在特定的网络地址和端口上创建服务器
我想在我以编程方式选择的端口和网络接口上创建rmi服务器(无jvm设置)。例如,我需要rmi服务器侦听接口127.0.0.1和端口2525。我读过互联网上的信息,这就是我最终找到的解决方案Java RMI:在特定的网络地址和端口上创建服务器,java,rmi,Java,Rmi,我想在我以编程方式选择的端口和网络接口上创建rmi服务器(无jvm设置)。例如,我需要rmi服务器侦听接口127.0.0.1和端口2525。我读过互联网上的信息,这就是我最终找到的解决方案 class ServerSocketFactory implements RMIServerSocketFactory, Serializable { public ServerSocket createServerSocket(int port) throws IOException {
class ServerSocketFactory implements RMIServerSocketFactory, Serializable {
public ServerSocket createServerSocket(int port) throws IOException
{
ServerSocket server = new ServerSocket(2525, 0, InetAddress.getByName("127.0.0.1"));
return server;
}
}
这就是我创建注册表的方式
registry = LocateRegistry.createRegistry(2525,null,new ServerSocketFactory());
然而,我有一个例外:
java.rmi.server.ExportException: Port already in use: 2525; nested exception is:
java.net.BindException: Address already in use
at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:341)
我不明白为什么如果在createRegistry中使用ServerSocketFactory,还会有一个端口参数。我犯了什么错
注意:这不是重复的,因为它是关于选择网络接口而不是端口。即
BindException
表示端口已在使用中。因此,您正在两次运行此代码,或者其他内容正在端口上侦听
您不必两次指定端口号。只需使用作为参数提供给createServerSocket()
的端口号即可。它将是导出时指定的端口号,或为零
如果要使用此套接字工厂的多个实例,则需要在套接字工厂类中实现equals()
,以便该类的所有实例都返回true
注意:RMIServerSocketFactory实现不需要是可序列化的。事实上,除了绑定到127.0.0.1之外,您根本不需要RMIServerSocketFactory
实现类。不清楚您为什么要这样做,因为这意味着您在同一个主机中执行所有RMI,这是非常徒劳的
总之,您需要:
registry = LocateRegistry.createRegistry(2525);
及
及
如果您需要远程对象(包括注册表)只在一个本地IP地址而不是所有IP地址上侦听,则此时您需要一个RMIServerSocketFactory
:
public class MyRMIServerSocketFactory implements RMIServerSocketFactory
{
private InetAddress address;
public MyRMIServerSocketFactory(InetAddress address)
{
this.address = address;
}
@Override
public ServerSocket createServerSocket(int port) throws IOException
{
return new ServerSocket(port, 0, address);
}
@Override
public boolean equals(Object that)
{
return that != null && this.getClass() == that.getClass() && this.address.equals((MyServerSocketFactory)that).address);
}
}
要使用它:
Registry registry = LocateRegistry.createRegistry(2525, null, new MyServerSocketFactory(address));
及
此游戏的规则是,当且仅当满足以下条件时,从同一JVM(可以包括注册表)导出的远程对象之间共享端口:
equals()下相等的服务器套接字工厂。
@如果您认为这里有问题,请说明问题所在。但是,这里不允许随机向下投票给人留下正确答案是错误的印象,从而误导OP。正如我发现的那样,我在创建注册表后执行UnicastRemoteObject.export(obj,2525)时遇到了这个异常。您能告诉我如何将对象导出到我用createRegistry()创建的套接字吗?老实说,糟糕的API。你做到了。不清楚你在问什么。当然,如果想要端口共享,注册表和远程对象必须在同一个JVM中,而且它们也必须使用相同的套接字工厂。不清楚您认为API有什么问题。我有rmi服务器-我们只谈论服务器,让我们完全忘记客户端。现在我有以下任务:1)为RMI创建所需的套接字2)在该套接字上创建注册表3)将远程导出到该套接字。我完成了任务1和任务2。但是我不知道怎么做3.我只是回答了这个问题。你做到了。正如我在回答中所建议的那样,我将去掉套接字工厂,只需在端口上导出注册表和远程对象。您也不需要第(1)步。@关闭投票者不是该问题的重复。。
public class MyRMIServerSocketFactory implements RMIServerSocketFactory
{
private InetAddress address;
public MyRMIServerSocketFactory(InetAddress address)
{
this.address = address;
}
@Override
public ServerSocket createServerSocket(int port) throws IOException
{
return new ServerSocket(port, 0, address);
}
@Override
public boolean equals(Object that)
{
return that != null && this.getClass() == that.getClass() && this.address.equals((MyServerSocketFactory)that).address);
}
}
Registry registry = LocateRegistry.createRegistry(2525, null, new MyServerSocketFactory(address));
public MyRemoteObject(int port, InetAddress address) throws RemoteException
{
super(port, null, new MyServerSocketFactory(address);
}