如何创建一个一次只接受一个连接的 rmi 服务器?

发布于 2024-11-16 04:25:56 字数 75 浏览 0 评论 0原文

我正在使用 rmi java 编写一个客户端-服务器对。我希望服务器侦听连接,当一个客户端连接时,服务器应拒绝任何其他尝试连接的客户端。

I'm writing a client-server pair in java using rmi java. I want the server to listen for a connection, and while one client is connected the server should reject any other clients that try to connect.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

佼人 2024-11-23 04:25:56

您需要使用 http://download.oracle.com/javase/6/docs/api/java/rmi/registry/LocateRegistry.html#createRegistry%28int,%20java.rmi.server.RMIClientSocketFactory,%20java.rmi.server .RMIServerSocketFactory%29,并编写自定义的RMIServerSocketFactory 返回仅接受的 ServerSocket单个连接。

编辑:混搭 LocateRegistry.createRegistryhttp://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();
    }
    }
}

You would need to start the RMI registry in code using http://download.oracle.com/javase/6/docs/api/java/rmi/registry/LocateRegistry.html#createRegistry%28int,%20java.rmi.server.RMIClientSocketFactory,%20java.rmi.server.RMIServerSocketFactory%29, and write a custom RMIServerSocketFactory that returns a ServerSocket that only accepts a single connection.

EDIT: with a mashup of LocateRegistry.createRegistry and http://download.oracle.com/javase/1.5.0/docs/guide/rmi/hello/Server.java with a little extra code thrown in (note that I didn't compile this, so you will need to sort out any compile errors yourself; it is intended to show you the general usage):

EDIT 2: fixed it to incorporate @EJP's suggestion (for more detail see 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();
    }
    }
}
许久 2024-11-23 04:25:56

一种简单的本土方法是通过单个方法传递所有内容,该方法跟踪请求线程的数量。如果已经有一个请求线程正在进行中,则可能会引发异常。否则,请求线程被允许继续。

一些代码来说明这个概念,但不一定是实现......

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;
         }
    }

}

One simple home-grown approach would be to pass everything through a single method which keeps track of the number of requesting threads. If there is already a requesting thread in progress, an exception can be thrown. Otherwise, the requesting thread is allowed to proceed.

Some code to illustrate the concept but not necessarily an implementation ...

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;
         }
    }

}

爱格式化 2024-11-23 04:25:56

您在这里所要做的就是将您的远程方法声明为同步的。那么一次只有一个客户可以输入它/他们。

All you have to do here is declare your remote method(s) as synchronized. Then only one client can enter it/them at a time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文