2010-02-09 78 views
2

我想编写一个应用程序以使用java rmi在客户机和服务器之间共享桌面。这是接口:帮助解决java rmi分配中的问题

public interface IServer extends Remote{ 

    public void share(BufferedImage image) throws RemoteException; 
} 
        ----------------------------- 

//这是服务器端代码:

public class ServerFrame extends JFrame implements IServer{ 
public static void main(String args[]) { 
     try { 

      ServerFrame frame = new ServerFrame(); 

      frame.setVisible(true); 
      LocateRegistry.createRegistry(1099); 
      Naming.bind("test", frame); 
      System.out.println("Server Started Successfully..."); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
. . . 
public ServerFrame() { 

     super(); 
      try { 
      UnicastRemoteObject.exportObject((Remote) this); 
     } catch (RemoteException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    . . . // bulding the ServerFrame GUI 
. . . 
public void share(BufferedImage image) throws RemoteException { 
     label.setIcon(new ImageIcon(image)); 
    } 
} 
        --------------- 

//最后是这样的客户端:存在,我想在桌面的ClientFrame按钮在点击这个按钮后在客户端和服务器之间共享。

public class ClientFrame extends JFrame implements Remote,Serializable{ 

    IServer serve; 
... 
public ClientFrame() { 
     super(); 
     try { 
      serve = (IServer) Naming.lookup("test"); 
     } catch (MalformedURLException e) { 

      e.printStackTrace(); 
     } catch (RemoteException e) { 

      e.printStackTrace(); 
     } catch (NotBoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     . . . // codes for building client gui 
    final JButton shareDesktopButton = new JButton(); 
     shareDesktopButton.addMouseListener(new MouseAdapter() { 
      public void mouseClicked(MouseEvent arg0) { 
       try { 
        BufferedImage screenShot = new Robot() 
        .createScreenCapture(new Rectangle(Toolkit 
          .getDefaultToolkit().getScreenSize())); 
        label.setIcon(new ImageIcon(screenShot)); 
        serve.share(screenShot); 
       } catch (HeadlessException e) { 

        e.printStackTrace(); 
       } catch (AWTException e) { 

        e.printStackTrace(); 
       } catch (RemoteException e) { 

        e.printStackTrace(); 
       } 

      } 
     }); 
      . . . 
    } 
// but there is a problem that causes these exceptions that I can not understand it. Please help me to complete my project. 

非常感谢

例外:

java.rmi.MarshalException: error marshalling arguments; nested exception is: 
    java.io.NotSerializableException: java.awt.image.BufferedImage 
    at sun.rmi.server.UnicastRef.invoke(Unknown Source) 
    at server.ServerFrame_Stub.share(Unknown Source) 
    at client.ClientFrame$1.mouseClicked(ClientFrame.java:86) 
    at java.awt.AWTEventMulticaster.mouseClicked(Unknown Source) 
    at java.awt.Component.processMouseEvent(Unknown Source) 
    at javax.swing.JComponent.processMouseEvent(Unknown Source) 
    at java.awt.Component.processEvent(Unknown Source) 
    at java.awt.Container.processEvent(Unknown Source) 
    at java.awt.Component.dispatchEventImpl(Unknown Source) 
    at java.awt.Container.dispatchEventImpl(Unknown Source) 
    at java.awt.Component.dispatchEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) 
    at java.awt.Container.dispatchEventImpl(Unknown Source) 
    at java.awt.Window.dispatchEventImpl(Unknown Source) 
    at java.awt.Component.dispatchEvent(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Caused by: java.io.NotSerializableException: java.awt.image.BufferedImage 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject(Unknown Source) 
    at sun.rmi.server.UnicastRef.marshalValue(Unknown Source) 
    ... 24 more 

回答

0

为堆栈跟踪显示,根本原因是:

Caused by: java.io.NotSerializableException: java.awt.image.BufferedImage 

这意味着你试图序列非 - 可串行化的类,即BufferedImage

另一种方法是使用和ImageIcon而不是BufferedImage

+0

对,没错。非常感谢 – samuel 2010-02-23 21:08:47

1

您不能使用BufferedImage作为远程参数,因为它既不是Remote也不是Serializable

您可以将BufferedImage包装在ImageIcon中,但效率非常低,因为它将转换为位图并通过网络进行未压缩传输。

我会做的参数Share表示压缩图像格式的字节数组(如PNG)

public interface IServer extends Remote{ 
    public void share(byte[] imagePNGBytes) throws RemoteException; 
} 

public void mouseClicked(MouseEvent arg0) { 
    try { 
     BufferedImage screenShot = new Robot() 
     .createScreenCapture(new Rectangle(Toolkit 
     .getDefaultToolkit().getScreenSize())); 
     ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
     ImageIO.write(screenShot, "PNG", bytes); 
     server.share(bytes.toByteArray()); 
    } catch (...) { 
     // ... 
    } 
} 

public class ServerFrame extends JFrame implements IServer { 

    // . . . 

    public void share(byte[] imagePNGBytes) throws IOException, RemoteException { 
     RenderedImage image = ImageIO.read(new ByteArrayInputStream(imagePNGBytes)); 
     label.setIcon(new ImageIcon(image)); 
    } 
} 
+0

+1:对于包含压缩,这对于远程处理很重要 – bguiz 2010-02-10 02:15:56

0

@finnw

你的代码工作正常,除了

label.setIcon(new ImageIcon(image)); 

ImageIcon类没有接受RenderedImage对象的构造函数。

所以你需要将RenderedImage转换成BufferedImage。而对于这些代码放在这里

public BufferedImage convertRenderedImage(RenderedImage img) { 
    if (img instanceof BufferedImage) { 
     return (BufferedImage) img; 
    } 
    ColorModel cm = img.getColorModel(); 
    int width = img.getWidth(); 
    int height = img.getHeight(); 
    WritableRaster raster = cm.createCompatibleWritableRaster(width, height); 
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); 
    Hashtable properties = new Hashtable(); 
    String[] keys = img.getPropertyNames(); 
    if (keys != null) { 
     for (int i = 0; i < keys.length; i++) { 
      properties.put(keys[i], img.getProperty(keys[i])); 
     } 
    } 
    BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties); 
    img.copyData(raster); 
    return result; 
} 

现在改变你的代码

label.setIcon(new ImageIcon(convertRenderedImage(image))); 

工作