2010-08-28 33 views
-4

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


} 

} 

类managaing客户线程

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

    } 
+7

你不应该只粘贴一堆代码,你应该用stacktrace发布实际的错误。 – Esko 2010-08-28 14:51:45

+1

好吧,没有人会因为没有提供所有的代码而给你带来错误。不过,我有一种奇怪的感觉,就是你发布的代码量很多,都是** TLDR **帖子。你可以尝试将错误追溯到几个组件吗? – wheaties 2010-08-28 14:57:48

+5

顺便说一句,快速谷歌搜索表明这些类似于(*至少部分*)从http://www.uwplatt.edu/csse/tools/java/samples/在线提供的一些Java RMI示例复制粘贴。我并不是说这在意识到这会使问题无效的意义上是有意义的,但是,如果海​​报甚至能够理解他正在使用的代码,那么它就会让人怀疑。 – Esko 2010-08-28 15:03:45

回答

1

截至link texthttp://www.coderanch.com/t/508960/java/java/pass-reference回答欧内斯特弗里德曼 - 希尔

的问题的根源是,RMI不通过引用支持通,所以使消息类别序列化和创建的事实ServerServices在可序列化类的远程实例可以使这个应用程序的工作

OR

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

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

再次感谢:Ernest Friedman-Hill

1

你的问题不够清楚,但:

调试代码,或把一些日志(简单的System.out .println)之前,你正在获得NPE。也许你列表仍然是空的。

public void updateClients() throws RemoteException { 
    **if (serverList != null) {** 
     for (TTTClientRemote aClient : serverList) { 
      aClient.updateClients("slam"); 
     } 
    } 
} 
+0

@jibbylala:如果它为空,那么是它的问题,因为您试图遍历一个null集合,它会抛出NPE。 – mhshams 2010-08-28 15:06:24

+0

我想迭代来自其他remoteobject的列表 – 2010-08-28 16:29:19

+0

@jibbylala请注意,Java'null'不像Lisp'nil'。这并不意味着你有一个空的List对象,这意味着你什么都没有。你对'null'进行迭代,或者为此调用任何方法。 – 2010-08-28 17:25:08

2

变化

private List<TTTClientRemote> serverList; 

要:

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

之前某处updateClients的为()或初始化();

+0

内的标记,当我将再次重新实例我不会松散我从其他对象(TTTServiceImpl1) – 2010-08-28 16:28:04