java - 使用 Java 将多个客户端连接到 RMI 服务器时出现 "ObjectID already in use"错误

标签 java multithreading client-server rmi

在我们的项目中,我们尝试将多个客户端连接到单个服务器。客户端正在使用 RMI 函数调用在 Button-CLick 上调用 RMI 服务器上定义的所有函数。服务器也是多线程的。在第一个客户端连接上,所有 RMI 服务器在各自的端口上正常启动,但当第二个客户端尝试连接时,将为客户端创建一个新线程,但 RMI 服务器不会启动,因为端口已在使用中。这里它给出了“ObjID Already”使用错误。

我们必须使用不同 Swing 客户端表单上的不同按钮单击来为客户端提供文件上传和下载功能,最终调用服务器端的 RMI 函数。

请建议我们应该做什么?

有没有更好的方法来进行多客户端服务器端函数调用?

服务器端Begin.java代码

package sedas;
public class Begin implements Runnable {
protected static Socket clientsocket;
public static String directorypath = "C:\\BEProject\\";


public Begin(Socket sock) {
    Begin.clientsocket = sock;
}

public static void main(String args[]) throws Exception {
    ServerSocket ssock = new ServerSocket(15127);
    System.out.println("Listening");
    while (true) {
        Socket sock = ssock.accept();
        System.out.println("Connected to " + sock.getInetAddress());
        new Thread(new Begin(sock)).start();
    }
}

@Override
public void run() {
    try {
        RMILogIn rmilogin = new RMILogIn();

//Port for RMILogIn is 3230 defined in RMILogIn.java file
//Similarly for all others RMI files
        RMIRegistration rmiregister = new RMIRegistration();
        RMILogout rmilgout = new RMILogout();
        RMISendFiles rmiSend = new RMISendFiles();
        RMIShowFiles rmiSendfiles = new RMIShowFiles();
        RMIGetFiles newrmi = new RMIGetFiles();

    } catch (RemoteException ex) {
        Logger.getLogger(Begin.class.getName()).log(Level.SEVERE, null, ex);
    }

}
}

客户端连接代码

package sedas;

public class Sedaslogin extends javax.swing.JFrame {

OutputStream osuname = null;
private static Component frame;
public static InetAddress address;
public static Socket socket;

/**
 * Creates new form
 */
public Sedaslogin() {
    initComponents();
}                       
private void initComponents() {

    jDesktopPane1 = new javax.swing.JDesktopPane();
    jPanel1 = new javax.swing.JPanel();
    jLabel1 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();
    username = new javax.swing.JTextField();
    password = new javax.swing.JPasswordField();
    login = new javax.swing.JButton();
    signup = new javax.swing.JButton();
    jLabel3 = new javax.swing.JLabel();


private void signupActionPerformed(java.awt.event.ActionEvent evt) {                                       
    // TODO add your handling code here:
    this.setVisible(false);
    new Registration().setVisible(true);
}                                      

private void loginActionPerformed(java.awt.event.ActionEvent evt) {                                      
     try {

    LoginInterface RMILogin;
    Registry registry;
    String serverAddress = address.getHostAddress();
    String serverPort = "3230";
    //System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort);
    try {

        registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)));
        // look up the remote object
        RMILogin = (LoginInterface) (registry.lookup("RMILogIn"));
        // call the remote method
        osuname = socket.getOutputStream();
        DataOutputStream doucred = new DataOutputStream(osuname);
        doucred.writeUTF(username.getText());
        char[] pw = password.getPassword();
        String password = new String(pw);
        doucred.writeUTF(password);
        RMILogin.LogIn();


        //System.out.print(password);
        InputStream is = socket.getInputStream();
        DataInputStream status = new DataInputStream(is);
        String receivedstat = status.readUTF();
        if (receivedstat.equals("Successful")) {
            this.setVisible(false);
            new Choice().setVisible(true);
        } else if (receivedstat.equalsIgnoreCase("error")) {
            jLabel3.setText("Invalid Username/Password");
        }
    } catch (RemoteException | NotBoundException e) {
    }
   } catch (IOException ex) {
        Logger.getLogger(Sedaslogin.class.getName()).log(Level.SEVERE, null, ex);
    }
}
public static void main(String args[]) {
    try {
        // TODO add your handling code here:
        address = InetAddress.getByName("hp-hp");
        //System.out.println(address.getHostAddress());
        socket = new Socket(address.getHostAddress(), 15127);
        JOptionPane.showMessageDialog(frame, "Connection Accepted by Server!");
    } catch (IOException ex) {
        Logger.getLogger(ClientUpload.class.getName()).log(Level.SEVERE, null, ex);
        JOptionPane.showMessageDialog(frame, "Connection Rejected by Server!");
        System.exit(1);
    }

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            new Sedaslogin().setVisible(true);
        }
    });
}

P.S.:假设所有导入均已完成并且客户端具有 Swing GUI。

最佳答案

您正在尝试在同一个 JVM 中创建多个注册表。你不能,除非你为每个端口使用不同的端口,而这样做是没有意义的,而且你一开始就不需要它。

你从头到尾都在做错事。

  • 去掉监听套接字、接受和线程。
  • 创建并注册一组远程对象。
  • 重新定义远程接口(interface)以获取参数,而不是将它们写入套接字。
  • 让客户端查找远程对象并仅使用参数调用它们,同时摆脱客户端套接字。

RMI 比您想象的更强大。

关于java - 使用 Java 将多个客户端连接到 RMI 服务器时出现 "ObjectID already in use"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28856457/

相关文章:

JAVA 保存多个 X 和 Y 鼠标位置

java - java中的事件是在单独的线程中处理还是我必须自己做?

linux - 线程在什么情况下会退出或停止运行

java - 如何知道哪个客户端调用了服务器上的RMI方法

java - 从 C 客户端向 Java 服务器发送一个字符串

java - 为什么我在 Java 中收到 NoClassDefFoundError 错误?

java - 树(有向无环图)实现

java - 如何在tomcat servlet应用程序中打印日志

c++ - 嵌套 boost::bind 与 io_service::post

java - 重新启动 java 线程