代码之家  ›  专栏  ›  技术社区  ›  static void main

在RMI中传递参考问题?

  •  -4
  • static void main  · 技术社区  · 15 年前

    有人能告诉我为什么这个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;
    
        }
    

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

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

    java:server将要注册并绑定到的对象。

    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());
                }
            }
    
        }
    
    3 回复  |  直到 15 年前
        1
  •  2
  •   Mateusz Dymczyk    15 年前

    变化

    private List<TTTClientRemote> serverList;
    

    到:

    private List<TTTClientRemote> serverList = new ArrayList<TTTClientRemote>();
    

    或者在updateClients()中的for()之前进行初始化;

        2
  •  1
  •   mhshams    15 年前

    你的问题不够清楚,但:

    调试代码,或者在得到NPE的行之前放置一些日志(简单的system.out.println)。也许您的列表仍然为空。

    public void updateClients() throws RemoteException {
        **if (serverList != null) {**
            for (TTTClientRemote aClient : serverList) {
               aClient.updateClients("slam");
            }
        }
    }
    
        3
  •  1
  •   static void main    15 年前

    回答如下 欧内斯特·弗里德曼·希尔 link text http://www.coderanch.com/t/508960/java/java/pass-reference :

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

    在客户机类中创建消息类的远程实例,并从RMI注册表发布消息类也可以工作。

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

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