我正在使用rmi-java用java编写一个客户端-服务器对。我希望服务器侦听连接,当一个客户端连接时,服务器应该拒绝任何其他尝试连接的客户端。
您需要使用http://download.oracle.com/javase/6/docs/api/java/rmi/registry/LocateRegistry.html#createRegistry%28int,%20java.rmi.server.RMClientSocketFactory,%20java.rmi.server.RMServerSocketFactory%29,并编写一个自定义RMIServerSocketFactory以返回仅接受单个连接的ServerSocket。
EDIT:使用LocateRegistry.createRegistry和http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/Server.java添加了一些额外的代码(注意,我没有编译这个,所以你需要自己解决任何编译错误;它旨在向你展示一般用法):
第2版:将其修改为包含@EJP的建议(有关更多详细信息,请参阅此)。
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();
}
}
}
一种简单的自制方法是通过一个跟踪请求线程数量的方法传递所有内容。如果已经有一个请求线程在进行中,则可以引发异常。否则,请求线程将被允许继续。
一些代码来说明概念,但不一定是实现。。。
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;
}
}
}
这里所要做的就是将远程方法声明为已同步。然后一次只能有一个客户端输入。