2011-06-18 87 views
2

我正在使用rmi java在java中編寫客戶機 - 服務器對。我希望服務器監聽連接,並且在連接一個客戶端時,服務器應拒絕嘗試連接的任何其他客戶端。如何創建一次只能接受一個連接的rmi服務器?

+1

爲什麼要限制服務器性能? – user774411

+0

因爲如果我使用更多的客戶端客戶端和服務器之間的流量可能會增加,因爲無論客戶端發送到服務器它必須重新傳輸到其他客戶端,我試過了,但我的服務器無法響應。 – sanu

回答

-1

一個簡單的自制方法是通過一個跟蹤請求線程數量的單一方法來傳遞所有內容。如果已經有正在請求的線程正在進行,則可能會拋出異常。否則,請求線程被允許繼續。

一些代碼來說明這個概念,但不一定是實現...

public class RequestHandler { 

    private boolean activeRequest = false; 


    public void handeRequest() throws Exception { 
     synchronized(this) { 
      if (activeRequest) { 
       throw new Exception("Request in progress"); 
      } 
      else { 
       activeRequest = true; 
      } 
     } 

     // delegate to something else to perform the request logic 


     synchronized(this) { 
      activeRequest = false; 
     } 
    } 

}

+0

謝謝,但如果客戶端崩潰或客戶端的計算機突然重新啓動時會發生什麼.....因爲我認爲它仍然是真實的,如果clinet不正確斷開與服務器...........對不起,如果我worng 。 – sanu

+0

客戶端和服務器是單獨的進程,所以即使客戶端機器/進程在此期間關閉,服務器線程仍將繼續執行handleRequest方法。 – btreat

+0

談論這麼做的困難;-( – EJP

2

您需要使用http://download.oracle.com/javase/6/docs/api/java/rmi/registry/LocateRegistry.html#createRegistry%28int,%20java.rmi.server.RMIClientSocketFactory,%20java.rmi.server.RMIServerSocketFactory%29啓動代碼的RMI註冊表,並編寫自定義RMIServerSocketFactory返回一個只接受單個連接的ServerSocket。

編輯:用LocateRegistry.createRegistry混搭和http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/Server.java在拋出一點點額外的代碼(注意,我沒有編譯這個,所以你需要理清自己的任何編譯錯誤,它的目的是向您展示一般使用):

編輯2:修正它以合併@ EJP的建議(更多詳細信息請參閱this)。

import java.rmi.registry.Registry; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.RemoteException; 
import java.rmi.server.UnicastRemoteObject; 

public class Server implements Hello { 

    public Server() {} 

    public String sayHello() { 
    return "Hello, world!"; 
    } 

    public static void main(String args[]) { 

    try { 
     Server obj = new Server(); 
     RMIClientSocketFactory csf = new RMIClientSocketFactory() { 
      @Override 
      public Socket createSocket(String host, int port) throws IOException { 
       InetAddress addr = InetAddress.getByName(host); 
       if (addr.equals(InetAddress.getLocalHost())) { 
        return new Socket(addr, port); 
       } else { 
        throw new IOException("remote socket bind forbidden."); 
       } 
      } 
     }; 
     RMIServerSocketFactory ssf = new RMIServerSocketFactory() { 
      @Override 
      public ServerSocket createServerSocket(int port) throws IOException { 
       System.out.println("RMIServerSocketFactory().createServerSocket()"); 
       return new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1")); 
      } 
     }; 
     Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0, csf, ssf); 

     // Bind the remote object's stub in the registry 
     Registry registry = LocateRegistry.createRegistry(uri.getPort(), csf, ssf); 

     registry.bind("Hello", stub); 

     System.err.println("Server ready"); 
    } catch (Exception e) { 
     System.err.println("Server exception: " + e.toString()); 
     e.printStackTrace(); 
    } 
    } 
} 
+0

可以使用give simple.example請問 – sanu

+0

所有這些都不是很好,它限制了與註冊表的併發連接,而​​不是他所要求的。在現代操作系統上,積壓1會被提升到50以上。套接字綁定'是完全多餘的:註冊表已經檢測到。 – EJP

+0

從問題:**我想要t他服務器監聽連接,而當一個客戶端連接時,服務器應該拒絕任何其他嘗試連接的客戶端。**我可能會讓我的RMI錯誤,但不是連接管理方式的註冊表,如果註冊表只接受單個連接不會拒絕所有其他連接?他沒有說**我只想要一個客戶端執行**,他說**我只想要一個客戶端連接**。 – Femi

0

所有你需要做的就是聲明你的遠程方法是同步的。然後,只有一個客戶可以一次輸入它/他們。