在RMI中通过参考问题? [英] Pass by reference problem in RMI?

查看:165
本文介绍了在RMI中通过参考问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以告诉我哪里错了为什么这个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);
私人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;

保护静态ServerServices chatServer;
MessageImpl remomsg;

public ChatClient1()throws RemoteException {
super();

尝试{

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
.setHorizo​​ntalScrollBarPolicy(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
.setHorizo​​ntalScrollBarPolicy(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自动生成的catch块
e.printStackTrace();
}
char c = evt.getKeyChar();
if(c =='\\\
'){
try {
if(firstMessage){
name = textString;
// .join(name);
firstMessage = false;
} else {
remomsg.sendMessage(name,textString);
}
} catch(RemoteException ie){
TAUinDispMsg.append(无法发送消息);
System.err.println(ie.getMessage());
}
textString =;
} else {
textString = textString + c;
}
}

@Override
public void updateClients(final String msg)throws RemoteException {
// TODO自动生成的方法存根


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



}

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

ChatClient1 ch = null ;
try {
ch = new ChatClient1();
} catch(RemoteException e){
// TODO自动生成的catch块
e.printStackTrace();
}
}

}




** ICallback.java:从服务器回调的接口给客户**


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自动生成的构造函数stub
this.clients = clients2;

}

static ServerServicesImpl si;
//静态ArrayListDemo az;
私人列表< ICallback> clients = new ArrayList< ICallback>();
//私人列表< ICallback>客户;

private ServerEngine serverEngine = new ServerEngine();

//注意这个不被远程调用
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;
}

//注意这个不被远程调用
public void setMessage(String message)throws RemoteException {
this.message = message;
}

public String getMessage(){
返回消息;
}



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());
(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();


}

}

managaing客户端线程的类

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

class ServerEngine {

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

//获取threadList上的锁,并等待计数器为零 - 那
//是,没有读取正在发生。那么可以安全的添加线程。

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

//类似的删除。
public synchronized void remove(ICallback item){
try {
while(counter> 0){
wait();
}
threadList.remove(item);
}
catch(InterruptedException e){
System.out.println(Removal blocked。);
}
finally {
notifyAll();
}
}

//类似于更改计数器
public synchronized void incCounter(){
counter ++;
notifyAll();
}

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

//这是因为让这个类实现
//收集,返回自己的Iterator等等... \
//注意它是*不*一个错误,它不是同步的
public Collection getCollection(){
return threadList;
}
}

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

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

public interface ServerServices extends Remote {

//添加,因此客户端可以使用服务器注册自己的回调
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扩展UnicastRemoteObject实现ServerServices,
可序列化{

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

}

//将发布上述远程对象的服务器

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


public class ServiceLoader
{

public static void main(String [] args)
{
try
{
//安装一个安全管理器
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 rel =nofollow noreferrer>链接文本 http://www.coderanch.com/t/508960/java/java/pass-reference



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



OR



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



在这段代码中,使用本地引用而不是remote,所以在列表中得到了0个元素rom Serverservices类。



再次感谢: Ernest Friedman-Hill


can somebody please tell me where i m wrong why this RMI chat application not working,the goal is to achieve decoupleing between client, server and logic by remote objects or serialized objects.


    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;

    }

The object which i want to serve as business logic (gamelogic).

 import java.rmi.*;

        public interface Message extends Remote {

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

            public void updateClients() throws RemoteException;

        }

Its implementation:

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();


}

}

class for managaing client threads

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: server the object which will be register and will bind to.

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: implementation side of server

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

    }

解决方案

As answered by Ernest Friedman-Hill at link texthttp://www.coderanch.com/t/508960/java/java/pass-reference:

The root of problem was the fact that RMI doesn't support pass by reference , so making the message class serializable and creating the remote instance of ServerServices in that serializable class can make this application work

OR

creating the remote instance of Message class in client class and publishing that from RMI registry can also work.

In this code the local references were used instead of remote, so it was getting the 0 elements in the list from Serverservices class.

thanks again to: Ernest Friedman-Hill.

这篇关于在RMI中通过参考问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆