2016-07-26 66 views
1

我想通過編程方式(不使用jvm設置)在端口和網絡接口上創建rmi服務器。例如,我想要rmi服務器監聽接口127.0.0.1和端口2525.我已經閱讀了互聯網上的信息,這是我終於來到的解決方案。RMI:在某個網絡地址和端口上創建服務器

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也有端口參數。我的錯誤是什麼?

P.S.這不是Remote method invocation port in use的重複,因爲它是關於選擇網絡接口而不是端口。

+0

@ close-voter不是這個問題的重複.. – EJP

回答

1

BindException表示該端口已被使用。所以你運行這個代碼兩次,或者其他的東西在端口上監聽。

您不必指定端口號兩次。只需使用作爲createServerSocket()的參數提供的端口號即可。它將是您在導出時指定的端口號,或者爲零。

如果您使用此套接字工廠的多個實例,則需要在套接字工廠類中實現equals(),以便此類的所有實例都返回true

NB RMIServerSocketFactory實現不需要是Serializable。事實上,除了綁定到127.0.0.1之外,你並不需要你的實現類。不清楚爲什麼你會這麼做,因爲這意味着你在同一個主機中做你的所有RMI,這是非常無用的。

因此,在總結,你需要:

registry = LocateRegistry.createRegistry(2525); 

myObject = new MyRemoteObject(2525); 

// constructor 
public MyRemoteObject(int port) throws RemoteException 
{ 
    super(port); 
} 

如果需要遠程對象(S)(包括註冊表)在聽只有一個本地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)); 

public MyRemoteObject(int port, InetAddress address) throws RemoteException 
{ 
    super(port, null, new MyServerSocketFactory(address); 
} 

這個遊戲的規則是端口從相同的JVM(其可以包括註冊表導出的遠程對象之間共享)當且僅當:

  1. 沒有人使用server soc KET工廠,或全部使用服務器套接字工廠是在equals()
  2. 它們都使用相同的端口號,或者爲零,或者沒有端口號,或者所有的第一對象導出使用零或沒有端口號後相等時(他們將分享第一個端口)。請注意,這意味着端口共享默認情況下發生,只要滿足(1)即可。
+0

@downvoter如果你認爲這裏有什麼問題,請說明什麼。但隨機抽查表明,正確的答案是不正確的,所以誤導OP,在這裏是不能容忍的。 – EJP

+0

因爲我發現我創建註冊表後,我得到這個異常我做UnicastRemoteObject.export(obj,2525)。你能說如何導出對象到我用createRegistry()創建的套接字嗎?說實話,糟糕的API。 –

+0

你已經完成了。不清楚你在問什麼。當然,如果你想要端口共享,註冊表和遠程對象都必須在同一個JVM中,並且它們也必須使用相同的套接字工廠。不清楚您認爲API錯誤。 – EJP

相關問題