无法将(服务)对象从 RMI 服务器发送到客户端

Cannot send (Service) object from RMI server to Client

我一直在绞尽脑汁想找出问题所在,我很确定服务器连接已经正常建立。我什至放了一些系统打印件来确保对象被发送和接收。让我先 post 我的代码。

RemoteService.java(接口):

package testrmi;

import java.rmi.*;
import javax.swing.JPanel;

public interface RemoteService extends Remote {

    public Object[] getServiceList() throws RemoteException;
    public Service getService(Object SvcKey) throws RemoteException;

}

Service.java 服务器提供的服务使用的(接口):

package testrmi;

import javax.swing.*;
import java.io.*;
import java.rmi.Remote;

public interface Service extends Serializable {

    public JPanel getGuiPanel();

}

RSimpl.java(RemoteService接口实现者)

package testrmi;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;

public class RSimpl implements RemoteService {

    HashMap<String, Service> map;

    public RSimpl() throws RemoteException
    {
        //super();
        setUpServices();
    }

    public void setUpServices()
    {
        map = new HashMap<String, Service>();
        map.put("Dice Roll Service", new DiceRoll());
        map.put("Calculator Service", new Calculator());
        map.put("Clock Service", new DigitalClock1());
        // Keep Adding Services On The Go!
    }

    public Object[] getServiceList()
    {
        return map.keySet().toArray();
    }

    public Service getService(Object SvcKey)
    {
        System.out.println(SvcKey + " request has been recieved");
        Service theService = map.get(SvcKey);
        return theService;
    }
}

Client.java(客户端,这看起来很脏:p)

package testrmi;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {

    JFrame frame;
    JPanel mainPanel;
    JComboBox<Object> comboBox;
    RemoteService server;
    int i = 0;
    Object[] error = {"Cannot Load Services"};

    public void buildGUI()
    {
        frame = new JFrame("Service Browser");
        mainPanel = new JPanel();

        attemptConnect();

        frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
        frame.getContentPane().add(BorderLayout.NORTH, comboBox);
        frame.setVisible(true);
        frame.setSize(300, 150);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        //centerFrame();
    }

    public void attemptConnect()
    {
        if(i==0)
        {
            i++;
            Object[] services = getServiceList();
            try {
                comboBox = new JComboBox<Object>(services);
                if (!services.toString().equalsIgnoreCase("Cannot Load Services"))
                comboBox.addActionListener(new MyListListener());
            }
            catch(Exception ex) {
                System.out.println("Cannot Establish Connection");
            }
        }
    }

    public void centerFrame()
    {
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (int) (d.getWidth()-frame.getWidth() / 2);
        int y = (int) (d.getHeight()-frame.getHeight() / 2);
        frame.setLocation(x, y);
    }

    public Object[] getServiceList()
    {
        boolean connectionsuccess = false;
        Object[] objList = null;
        try {
            Registry rs = LocateRegistry.getRegistry("127.0.0.1", 9797); //CHANGE TO 192.168.1.97
            server = (RemoteService) rs.lookup("RService");
            connectionsuccess = true;
        }
        catch(Exception ex) {
            Object[] options = {"Retry","Cancel"};
            int o = JOptionPane.showOptionDialog(frame, "Cannot Establish Connection To The Server. \n Do You Want To Retry?", "Connection Error", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]);
            if(o==0)
            {
                i=0;
                attemptConnect();
            }
            else
            {
                i=1;
                return error;
            }
        }
        if(connectionsuccess) {
            try {
                objList = server.getServiceList();
            }
            catch(Exception ex) {
                Object[] options = {"Retry","Cancel"};
                int o = JOptionPane.showOptionDialog(frame, "Cannot Fetch Services List From The Server. \n Do You Want To Retry?", "Fetch Error", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]);
                if(o==0)
                {
                    i=0;
                    attemptConnect();
                }
                else
                {
                    i=1;
                    return error;
                }
            }
        }
        return objList;
    }

    public void loadService(Object SvcKey)
    {
        try {
            System.out.println(" I am going to send key: " + SvcKey);
            Service svc = (Service) server.getService(SvcKey); //THIS IS CAUSING THE ERROR!
            System.out.println("i am yet working"); //THIS LINE IS NOT WORKING
            mainPanel.removeAll();
            //frame.setContentPane(svc.getGuiPanel());
            mainPanel.add(svc.getGuiPanel());
            mainPanel.validate();
            mainPanel.repaint();
            frame.pack();
            frame.setMinimumSize(new Dimension(300,150));
        }
        catch(Exception ex) {
            Object[] options = {"Retry","Cancel"};
            int o = JOptionPane.showOptionDialog(frame, "Cannot Load The Service From The Server. \n Do You Want To Retry?", "Connection Error", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]);
            if(o==0)
            {
                new MyListListener();
            }
            else
            {
                i=1;
                frame.repaint();
            }
        }
    }

    public class MyListListener implements ActionListener
    {
        public void actionPerformed(ActionEvent ev)
        {
            Object selection = comboBox.getSelectedItem();
            System.out.println(comboBox.getSelectedItem()); //DO NOT FORGET TO TEST THIS!
            loadService(selection);
        }
    }

    public static void main(String[] args)
    {
        Client cl = new Client();
        cl.buildGUI();
    }
}

StartServer.java(实例化 RSimpl 对象并启动服务器)

package testrmi;

import java.net.InetAddress;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class StartServer {

    public static void main(String[] args)
    {
        try {
            RSimpl obj = new RSimpl();
            RemoteService stub = (RemoteService) UnicastRemoteObject.exportObject(obj, 0);
            System.setProperty("java.rmi.server.hostname","192.168.1.97");
            //RemoteService rs = new RSimpl();
            Registry r = LocateRegistry.getRegistry(9797);
            r.rebind("RService", stub);
            System.out.println("Remote Service Is Running");
            System.out.println(""+ InetAddress.getLocalHost().getHostAddress());
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Sorry, Cannot Start Remote Service");
        }
    }   

}

Calculator.java(计算器服务,无需检查)

package testrmi;

import javax.script.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;

public class Calculator implements Service, Serializable {

    JPanel mainPanel;

    public JPanel getGuiPanel()
    {
        mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());

        //JPanel p1 = new JPanel();
        //p1.setLayout(new GridLayout(4,4));

        JPanel p1 = new JPanel();
        JPanel p2 = new JPanel();
        JPanel p3 = new JPanel();
        JPanel p4 = new JPanel();

        final JTextField t = new JTextField(10);
        t.setEditable(false);
        t.setBackground(Color.green);
        t.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
        Font myFont = new Font("MS Sans Serif", Font.BOLD, 24);
        t.setFont(myFont);

        mainPanel.add(t,BorderLayout.NORTH);

        final JButton n1 =  new JButton("1");
        n1.setFocusable(false);
        n1.setFont(myFont);
        n1.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n1.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);
            }
        });

        final JButton  n2 =  new JButton("2");
        n2.setFocusable(false);
        n2.setFont(myFont);
        n2.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n2.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);    
            }
        });

        final JButton  n3 =  new JButton("3");
        n3.setFocusable(false);
        n3.setFont(myFont);
        n3.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n3.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);
            }
        });

        final JButton  n4 =  new JButton("4");
        n4.setFocusable(false);
        n4.setFont(myFont);
        n4.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n4.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);
            }
        });

        final JButton  n5 =  new JButton("5");
        n5.setFocusable(false);
        n5.setFont(myFont);
        n5.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n5.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global); 
            }
        });

        final JButton  n6 =  new JButton("6");
        n6.setFocusable(false);
        n6.setFont(myFont);
        n6.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n6.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);
            }
        });

        final JButton  n7 =  new JButton("7");
        n7.setFocusable(false);
        n7.setFont(myFont);
        n7.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n7.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);  
            }
        }); 

        final JButton  n8 =  new JButton("8");
        n8.setFocusable(false);
        n8.setFont(myFont);
        n8.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n8.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);  
            }
        }); 

        final JButton  n9 =  new JButton("9");
        n9.setFocusable(false);
        n9.setFont(myFont);
        n9.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n9.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);  
            }
        });


        final JButton  n10 =  new JButton("0");
        n10.setFocusable(false);
        n10.setFont(myFont);
        n10.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n10.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);
            }
        });

        final JButton  n11 =  new JButton("+");
        n11.setFocusable(false);
        n11.setFont(myFont);
        n11.setForeground(Color.MAGENTA);
        n11.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n11.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);  
            }   
        });


        final JButton  n12 =  new JButton("-");
        n12.setFocusable(false);
        n12.setFont(myFont);
        n12.setForeground(Color.MAGENTA);
        n12.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n12.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global); 
            }
        });

        final JButton  n13 =  new JButton("*");
        n13.setFocusable(false);
        n13.setFont(myFont);
        n13.setForeground(Color.MAGENTA);
        n13.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n13.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global); 
            }           
        });

        final  JButton  n14 =  new JButton("/");
        n14.setFocusable(false);
        n14.setFont(myFont);
        n14.setForeground(Color.MAGENTA);
        n14.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                String num1 = n14.getText();
                String global = t.getText();
                global = global.concat(num1);
                t.setText(global);  
            }
        });

        final JButton  n15 =  new JButton("=");
        n15.setFocusable(false);
        n15.setFont(myFont);
        n15.setForeground(Color.BLUE);
        n15.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                //String num1 = n15.getText();
                String global = t.getText();
                //global = global.concat(num1);

                ScriptEngineManager mgr = new ScriptEngineManager();
                ScriptEngine engine = mgr.getEngineByName("JavaScript");
                try {
                    String s = engine.eval(global).toString();
                    t.setText(s); 
                } 
                catch (ScriptException e1) {
                    e1.printStackTrace();
                }  
            }
        });

        final  JButton  n16 =  new JButton("C");
        n16.setFocusable(false);
        n16.setFont(myFont);
        n16.setForeground(Color.RED);
        n16.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                //String num1 = n16.getText();
                String global = t.getText();
                global = null;
                t.setText(global);
            }
        });

        p1.add(n1);
        p1.add(n2);
        p1.add(n3);
        p1.add(n4);
        p2.add(n5);
        p2.add(n6);
        p2.add(n7);
        p2.add(n8);
        p3.add(n9);
        p3.add(n10);
        p3.add(n11);
        p3.add(n12);
        p4.add(n13);
        p4.add(n14);
        p4.add(n15);
        p4.add(n16);

        JPanel pPanel = new JPanel();
        pPanel.setLayout(new BoxLayout(pPanel, BoxLayout.Y_AXIS));
        pPanel.add(p1);
        pPanel.add(p2);
        pPanel.add(p3);
        pPanel.add(p4);

        mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        mainPanel.add(pPanel);
        return mainPanel;
    }
}

DiceRoll.java(DiceRoll 服务,无需检查)

package testrmi;

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

public class DiceRoll implements Service {

    int i = 0;
    int h = 0;
    JPanel mainPanel;
    JButton roll;
    MyDrawPanel drawPanel;

    public JPanel getGuiPanel()
    {
        mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        roll = new JButton("Roll The Dice!");
        roll.setFont(new Font("Comic Sans Ms", Font.BOLD, 16));
        roll.setFocusable(false);
        roll.setAlignmentX(Component.CENTER_ALIGNMENT);
        roll.addActionListener(new rollListener());

        drawPanel = new MyDrawPanel();
        drawPanel.setPreferredSize(new Dimension(150,150));

        mainPanel.add(roll);
        mainPanel.add(Box.createRigidArea(new Dimension(0,10)));
        mainPanel.add(drawPanel);
        mainPanel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
        return mainPanel;
    }

    public int roll()
    {
        while (i==0 || i==h)
        {
            i = (int) (Math.random()*7);
        }
        h = i;
        return i;
    }

    public class rollListener implements ActionListener
    {
        public void actionPerformed(ActionEvent ev)
        {
            int x = roll();
            drawPanel.sendNum(x);
            drawPanel.repaint();
        }
    }

    public class MyDrawPanel extends JPanel
    {
        Graphics g;
        int least = 0, x;
        int fx=0, fy=0, fw=150, fh=150;
        int dw=100, dh=100;
        int dx=((fw-dw)/2), dy=((fh-dh)/2);
        int dxc,dyc,dx1,dy1,dx2,dy2,dx3,dy3,dx4,dy4,dx5,dy5,dx6,dy6;

        public void paintComponent(Graphics gn)
        {
            g = gn;
            super.paintComponent(g);
            g.setColor(Color.LIGHT_GRAY);
            g.fillRect(fx, fy, fw, fh);
            g.setColor(Color.WHITE);
            g.fillRoundRect(dx, dy, dw, dh, 30, 30);
            g.setColor(Color.BLACK); // set black for dots and border
            g.drawRoundRect(dx, dy, dw, dh, 30, 30);
            if(least>=1)
            {
                if(x==1)
                {
                    g.fillOval(dxc, dyc, 20, 20);
                }
                else if(x==2)
                {
                    g.fillOval(dx1, dy1, 20, 20);
                    g.fillOval(dx6, dy6, 20, 20);
                }
                else if(x==3)
                {
                    g.fillOval(dx1, dy1, 20, 20);
                    g.fillOval(dxc, dyc, 20, 20);
                    g.fillOval(dx6, dy6, 20, 20);
                }
                else if(x==4)
                {
                    g.fillOval(dx1, dy1, 20, 20);
                    g.fillOval(dx2, dy2, 20, 20);
                    g.fillOval(dx5, dy5, 20, 20);
                    g.fillOval(dx6, dy6, 20, 20);
                }
                else if(x==5)
                {
                    g.fillOval(dx1, dy1, 20, 20);
                    g.fillOval(dx2, dy2, 20, 20);
                    g.fillOval(dxc, dyc, 20, 20);
                    g.fillOval(dx5, dy5, 20, 20);
                    g.fillOval(dx6, dy6, 20, 20);
                }
                else if(x==6)
                {
                    g.fillOval(dx1, dy1, 20, 20);
                    g.fillOval(dx2, dy2, 20, 20);
                    g.fillOval(dx3, dy3, 20, 20);
                    g.fillOval(dx4, dy4, 20, 20);
                    g.fillOval(dx5, dy5, 20, 20);
                    g.fillOval(dx6, dy6, 20, 20);
                }
            }
        }

        public void sendNum(int xx)
        {
            least = 1;
            x = xx;
            // REMEMBER: dx+40=CENTER_X and dy+40=CENTER_Y because dice size 100, dot size 20
            dxc=dx+40;
            dyc=dy+40;
            dx1=dx+10;
            dy1=dy+10;
            dx2=dx+70;
            dy2=dy+10;
            dx3=dx+10;
            dy3=dy+40;
            dx4=dx+70;
            dy4=dy+40;
            dx5=dx+10;
            dy5=dy+70;
            dx6=dx+70;
            dy6=dy+70;
        }
    } // close class MyDrawPanel
}

DigitalClock1.java(无需检查——这些仅用于编译目的)

package testrmi;

import java.awt.*; 
import java.util.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import java.awt.event.ActionEvent;

public class DigitalClock1 implements Service
{
        public JPanel getGuiPanel()
        {
            SimpleDigitalClock clock1 = new SimpleDigitalClock();
            return clock1;
        }
        static class SimpleDigitalClock extends JPanel
        { 
            String stringTime;
            int hour, minute, second;
            String aHour = "";
            String bMinute = "";
            String cSecond = ""; 
            public void setStringTime(String abc)
            {
                this.stringTime = abc;
            } 
            public int Number(int a, int b)
            {
                return (a <= b) ? a : b;
            } 
            SimpleDigitalClock()
            { 
                Timer t = new Timer(1000, new ActionListener()
                { 
                    public void actionPerformed(ActionEvent e)
                    {
                        repaint();
                    }
                });
                t.start();
            }
            @Override 
            public void paintComponent(Graphics v)
            {
                super.paintComponent(v);
                Calendar rite = Calendar.getInstance();
                hour = rite.get(Calendar.HOUR_OF_DAY);
                minute = rite.get(Calendar.MINUTE);
                second = rite.get(Calendar.SECOND);
                if (hour < 10)
                {
                    this.aHour = "0"; 
                } 
                if (hour >= 10)
                {
                    this.aHour = "";
                } 
                if (minute < 10)
                {
                    this.bMinute = "0";
                } 
                if (minute >= 10)
                {
                    this.bMinute = "";
                }
                if (second < 10)
                {
                    this.cSecond = "0";
                }
                if (second >= 10)
                {
                    this.cSecond = "";
                } 
                setStringTime(aHour + hour + ":" + bMinute+ minute + ":" + cSecond + second);
                v.setColor(Color.BLACK);
                int length = Number(this.getWidth(),this.getHeight());
                Font Font1 = new Font("Comic Sans MS", Font.PLAIN, length / 5);
                v.setFont(Font1);
                v.drawString(stringTime, (int) length/6, length/2);
            } 
            @Override 
            public Dimension getPreferredSize()
            {
                return new Dimension(200, 200);
            }
        }
}

我运行宁start rmiregistry 9797来自testrmi目录(包)所在的目录。然后我从同一目录 运行 java testrmi.StartServer 。我得到服务器是 运行ning 消息,然后我从另一个目录 运行 客户端但具有相同的包名称,它只包含 Client.class、RemoteService.class 和 Service.class;客户端启动正常,显示所有三个服务,但是当我从列表中 select 时,我得到异常错误 'Cannot load service, retry?'.

注意:如果我在客户端包目录中复制服务(calculator.class、diceroll.class 和 digitalclock1.class),客户端会正确加载服务。我不希望客户端在不连接到服务器的情况下直接访问这些服务。

如果您希望能够 return 将不在客户端类路径中的对象序列化到客户端,您需要使用 RMI codebase feature,除其他外,这需要您部署代码库服务器,并在客户端使用 SecurityManager