在我们的项目中,我们尝试将多个客户端连接到单个服务器。客户端正在使用 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/