当前位置: 首页 > 面试题库 >

在RMI中通过引用传递问题?

姚实
2023-03-14
问题内容

有人可以告诉我这个RMI聊天应用程序为什么不能正常工作的地方,目的是通过远程对象或序列化对象实现客户端,服务器和逻辑之间的分离。

    import javax.swing.*;
    import java.awt.event.*;
    import java.rmi.*;
    import java.rmi.server.*;

    public class ChatClient1 implements ICallback {

        JFrame frame = new JFrame("Chat Client");
        private JTextArea myText;
        private static JTextArea TAUinDispMsg;
        private JScrollPane myTextScroll;
        private JScrollPane TAUinDispMsgScroll;
        private String textString = "";
        private boolean firstMessage = true;
        private static String name = null;

        private static final int HOR_SIZE = 400;
        private static final int VER_SIZE = 150;

        protected static ServerServices chatServer;
        MessageImpl remomsg ;

        public ChatClient1() throws RemoteException {
            super();

            try {

                this.chatServer = (ServerServices) Naming.lookup("rmi://localhost"
                        + "/ChatServer");

                 UnicastRemoteObject.exportObject(this);
                 chatServer.register(this);
            } catch (Exception e) {
                System.err.println("RemoteException: " + e.getMessage());
                System.exit(0);
            }
            ;

            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    initComponents();
                }
            });

            frame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    try {
                        if (name != null) {
                            // chatServer.leave(displayChat, name);
                        }
                    } catch (Exception ex) {
                        TAUinDispMsg.append("Exit failed.");
                    }
                    System.exit(0);
                }
            });
        }


        private void initComponents() {

            myText = new JTextArea();

            myTextScroll = new JScrollPane(myText);
            myTextScroll
                    .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            myTextScroll
                    .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            myTextScroll.setMaximumSize(new java.awt.Dimension(HOR_SIZE, VER_SIZE));
            myTextScroll.setMinimumSize(new java.awt.Dimension(HOR_SIZE, VER_SIZE));
            myTextScroll
                    .setPreferredSize(new java.awt.Dimension(HOR_SIZE, VER_SIZE));

            myText.addKeyListener(new java.awt.event.KeyAdapter() {
                public void keyTyped(java.awt.event.KeyEvent evt) {
                    textTyped(evt);
                }
            });

            frame.getContentPane().add(myTextScroll, java.awt.BorderLayout.NORTH);

            TAUinDispMsg = new JTextArea();

            TAUinDispMsgScroll = new JScrollPane(TAUinDispMsg);
            TAUinDispMsg.setBackground(new java.awt.Color(200, 200, 200));
            TAUinDispMsgScroll
                    .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            TAUinDispMsgScroll
                    .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            TAUinDispMsgScroll.setMaximumSize(new java.awt.Dimension(HOR_SIZE,
                    VER_SIZE));
            TAUinDispMsgScroll.setMinimumSize(new java.awt.Dimension(HOR_SIZE,
                    VER_SIZE));
            TAUinDispMsgScroll.setPreferredSize(new java.awt.Dimension(HOR_SIZE,
                    VER_SIZE));
            TAUinDispMsg.setEditable(false);

            frame.getContentPane().add(TAUinDispMsgScroll,
                    java.awt.BorderLayout.CENTER);

            frame.pack();
            frame.setVisible(true);
        }

        private void textTyped(java.awt.event.KeyEvent evt) {

             try {
                remomsg = new MessageImpl();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
            char c = evt.getKeyChar();
            if (c == '\n') {
                try {
                    if (firstMessage) {
                        name = textString;
                    //  .join(name);
                        firstMessage = false;
                    } else {
                        remomsg.sendMessage(name, textString);
                    }
                } catch (RemoteException ie) {
                    TAUinDispMsg.append("Failed to send message.");
                    System.err.println(ie.getMessage());
                }
                textString = "";
            } else {
                textString = textString + c;
            }
        }

        @Override
        public void updateClients(final String msg) throws RemoteException {
            // TODO Auto-generated method stub


            System.out.println("Recived Message: " + msg);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    TAUinDispMsg.append(name + " says: " + msg + "\n");
                }
            });



        }

        public static void main(String args[]) throws RemoteException {

            ChatClient1 ch = null;
            try {
                ch = new ChatClient1();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }




 **ICallback.java: interface for callbacks from server to client**


    import java.rmi.*;

    public interface ICallback extends Remote {
        void updateClients(String msg) throws RemoteException;

    }

我想用作业务逻辑(游戏逻辑)的对象。

 import java.rmi.*;

        public interface Message extends Remote {

            public void sendMessage(String name, String message) throws RemoteException;

            public void updateClients() throws RemoteException;

        }

其实现:

import java.io.Serializable;
import java.rmi.*;
import java.rmi.server.*;
import java.util.ArrayList;
import java.util.Iterator;

import java.util.List;

public class MessageImpl extends UnicastRemoteObject implements Message {
private String name;
private String message;

public MessageImpl() throws RemoteException {
    super();

}
public MessageImpl(ArrayList clients2) throws RemoteException {
    // TODO Auto-generated constructor stub
    this.clients = clients2;

}

static ServerServicesImpl si;
// static ArrayListDemo az;
private List<ICallback> clients = new ArrayList<ICallback>();
// private List<ICallback> clients;

private ServerEngine serverEngine = new ServerEngine();

// Notice this one not called remotely
public void setName(String name) throws RemoteException {
    this.name = name;
}

public String getName() {
    return name;
}

public void setServerList(ServerEngine serverList2) throws RemoteException {
    this.serverEngine = serverList2;

}

public void setClientList(List<ICallback> aclients) throws RemoteException {
    this.clients = (ArrayList<ICallback>) aclients;
    System.err.println("in setClientlist");
}

public ServerEngine getServerList() {
    return serverEngine;
}

// Notice this one not called remotely
public void setMessage(String message) throws RemoteException {
    this.message = message;
}

public String getMessage() {
    return message;
}



public void updateClients() throws RemoteException {


    si = new ServerServicesImpl();
    ArrayList j = si.getClientNames();
    System.out.println(j.size());
    if (clients != null) {
        System.out.println(clients.size());
        for (ICallback aClient : clients) {
            aClient.updateClients(message);
        }

    } else
        System.err.println("Clientlist is empty");

    if (clients != null) {
        System.out.println(j.size());


    } else
        System.err.println("Clientlist is empty");

}

public void sendMessage(String name, String message1)
throws RemoteException {

    setName(name);
    setMessage(message1);
    updateClients();


}

}

管理客户端线程的类

import java.lang.*;
import java.util.*;

class ServerEngine {

    private Collection<ICallback> threadList =
                new ArrayList<ICallback>();
    private int counter = 0;

    //  Get the lock on threadList, and wait until the counter is zero - that
    //is, no reads are taking place. Then it's safe to add the thread.

    public synchronized void add(ICallback item) {
        try {
            while (counter > 0) {
                wait();
            }
            threadList.add(item);
        }
        catch (InterruptedException e) {
            System.out.println("Addition interrupted.");
        }
        finally{
            notifyAll();
        }
    }

    // Similarly for removal.
    public synchronized void remove(ICallback item) {
        try {
            while (counter > 0) {
                wait();
            }
            threadList.remove(item);
        }
        catch (InterruptedException e) {
            System.out.println("Removal interrupted.");
        }
        finally {
            notifyAll();
        }
    }

    // Similarly for changing counter
    public synchronized void incCounter() {
        counter++;
        notifyAll();
    }

    public synchronized void decCounter() {
        counter--;
        notifyAll();
    }

    //This is because it would be too much effort to make this class implement
    //Collection, return it's own Iterator etc. etc...\
    //Note it is *not* a bug that it isn't synchronized
    public Collection getCollection() {
        return threadList;
    }
}

Service.java:服务器将要注册并绑定到的对象。

import java.rmi.*;
import java.util.ArrayList;

public interface ServerServices extends Remote {

    // added so client can register self with server for callbacks
    public void register(ICallback newClient) throws RemoteException;

    public ArrayList getClients() throws RemoteException;

}

ServerServicesImpl.java:服务器的实现端

import java.io.Serializable;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;

class ServerServicesImpl extends UnicastRemoteObject implements ServerServices,
        Serializable {

    String message;
    MessageImpl msgimpl;
    static Vector data = new Vector();

    private static ArrayList Aclients = new ArrayList<ICallback>();
    private static ArrayList testlist;

    public ServerServicesImpl() throws RemoteException {
        super();
        testlist = new ArrayList();

    }

    public synchronized void register(ICallback newClient)
            throws RemoteException {
        data.addElement(newClient);
        Aclients.add(newClient);
        // //serverEngine.add(newClient);

        testlist.add("testing");
        System.out.println("testlist size =" + testlist.size());

        System.out.println(Aclients.size());

        setClientList(Aclients);

    }

    ArrayList getClientNames() {
        // Aclients.add(ic);
        System.out.println("vector size =" + data.size());
        System.out.println("testlist size =" + testlist.size());
        System.out.println(" Aclientlist size =" + Aclients.size());
        return Aclients;
    }

    public void setClientList(ArrayList aclients2) {
        this.Aclients = aclients2;
    }

}

   // the server  which will publish the above remote object

    import java.net.MalformedURLException;
    import java.rmi.*;


    public class ServiceLoader
    {

        public static void main(String[] args)
        {
            try
            {
                // Install a security manager
                System.setSecurityManager(new RMISecurityManager());
                ServerServicesImpl obj = new ServerServicesImpl();

                Naming.rebind("ChatServer", obj);


                System.out.println("ServiceLoader running.");

            }
            catch (MalformedURLException e)
            {
                System.err.println(e.getMessage());
            }
            catch (RemoteException e)
            {
                System.err.println(e.getMessage());
            }
        }

    }

问题答案:

正如 Ernest Friedman-Hill
在链接文本
http://www.coderanch.com/t/508960/java/java/pass-
reference上


回答的那样:

问题的根源在于RMI不支持按引用传递,因此使消息类可序列化并在该可序列化类中创建ServerServices的远程实例可以使此应用程序正常工作

要么

在客户端类中创建Message类的远程实例并从RMI注册表中发布它也可以工作。

在此代码中,使用本地引用而不是远程引用,因此它从Serverservices类获取列表中的0元素。

再次感谢: 欧内斯特·弗里德曼·希尔



 类似资料:
  • 问题内容: 我有以下代码: 有人可以解释为什么输出是:零一二二。 摘自zend认证学习指南。 问题答案: 因为在第二个循环中,仍然是对最后一个数组项的引用,所以每次都将其覆盖。 您可以看到这样的内容: 如您所见,最后一个数组项采用当前循环值:“零”,“一个”,“两个”,然后就是“两个” …:)

  • 问题内容: 这两个代码有什么区别: 代码A: 哪里 VS. 代码B: 这两个代码之间有什么区别吗? 问题答案: Java始终按值传递参数,而不按引用传递参数。 让我通过一个例子解释一下: 我将逐步解释这一点: 声明一个名为ftype 的引用,Foo并将其分配给Foo具有属性的type的新对象”f”。 从方法方面,声明Foo具有名称的类型引用,a并将其初始分配给null。 调用方法时changeRe

  • 问题内容: Go中的地图是否通过值或引用传递? 始终可以将函数定义为以下形式,但这是一个过大的杀伤力吗? 相同的返回值问题。我应该返回指向地图的指针,还是将地图作为值返回? 这样做的目的当然是避免不必要的数据复制。 问题答案: 在此线程中,您将找到答案: Golang:使用地图参考来访问地图 您不需要在地图上使用指针。 映射类型是引用类型,例如指针或切片[1] 如果需要更改会话,可以使用一个指针:

  • 问题内容: 如何在Python中通过引用传递整数? 我想修改传递给函数的变量的值。我读过Python中的所有内容都是按值传递的,但是必须有一个简单的技巧。例如,在Java中,你可以通过引用类型的,等等。 如何通过引用将整数传递给函数? 最佳做法是什么? 问题答案: 在Python中,这种方式不太有效。Python将引用传递给对象。在函数内部,你有一个对象-你可以随意更改该对象(如果可能)。但是,整

  • 问题内容: 如何在JavaScript中通过引用传递变量?我要对3个变量执行一些操作,因此我想将它们放在for循环中并对每个变量执行操作。 伪代码: 做这个的最好方式是什么? 问题答案: JavaScript中没有可用的“通过引用传递”。您可以传递一个对象(也就是说,您可以按值传递对一个对象的引用),然后让一个函数修改该对象的内容: 您可以使用数字索引遍历数组的属性,并根据需要修改数组的每个单元格

  • 问题内容: 我想知道在您仅读取变量时是否将其作为按引用传递的优良作法,还是应始终将其作为值传递。 引用传递示例: 传递值的示例: 哪个更好 ?例如,如果我要循环运行1000次? 循环示例: 问题答案: 如果您打算传递一个 值 (因此该函数不会对其进行修改) ,则没有理由通过引用传递它:这只会使您的代码更难以理解,因为人们会认为“ 此函数可以修改我将要修改的内容。传递给它-哦,它没有修改? ” 在您