2013-07-28 3 views
0

Я пытаюсь написать реализацию RemoteDesktop в Java. Я использую ObjectOutputStream и ObjectInputStream через сокет для отправки данных. Для передачи данных, я использую класс я создал под названием «Пакет»:Ошибки при чтении из ObjectInputStream Java

import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
import javax.swing.ImageIcon; 

/** 
* Holds data to send over network connection 
*/ 
class Packet<T extends Serializable> implements Serializable { 

    private T payload; 

    public Packet() { 
     super(); 
    } 

    public Packet(T data) { 
     super(); 
     setPayload(data); 
    } 

    public T getPayload() { 
     return payload; 
    } 

    public void setPayload(T payload) { 
     this.payload = payload; 
    } 

    public static void send(String message, ObjectOutputStream out) throws IOException { 
     out.writeObject(new Packet<>(message)); 
     out.flush(); 
    } 

    public static void send(Integer value, ObjectOutputStream out) throws IOException { 
     out.writeObject(new Packet<>(value)); 
     out.flush(); 
    } 

    public static void send(Block block, ObjectOutputStream out) throws IOException { 
     out.writeObject(new Packet<>(block)); 
     out.flush(); 
    } 

    public static void send(BufferedImage[][] images, ObjectOutputStream out) throws IOException { 
     //convert to ImageIcon 
     ImageIcon icons[][] = new ImageIcon[images.length][images[0].length]; 
     for (int x = 0; x < images.length; x++) { 
      for (int y = 0; y < images[0].length; y++) { 
       icons[x][y] = new ImageIcon(images[x][y]); 
      } 
     } 
     out.writeObject(new Packet<>(icons)); 
     out.flush(); 
    } 
} 

При первой установке соединения, сервер посылает массив ImageIcon в 2-D, который содержит различные «блоки» экрана. Экран разделен на этот массив блоков. Затем сервер выполняет регулярные скриншоты и сравнивает каждый «блок» экрана с последним, чтобы увидеть, изменился ли он. Если есть изменения, то сервер отправит новую область экрана в классе под названием «Блок», который удерживает координату х и у этого блока и ImageIcon:

import java.awt.image.BufferedImage; 
import java.io.Serializable; 
import javax.swing.ImageIcon; 

/** 
* Holds an image and its x and y coordinates on the screen 
*/ 
class Block implements Serializable { 

    private ImageIcon img; 
    private int x; 
    private int y; 

    public Block() { 
     super(); 
    } 

    public Block(BufferedImage image, int x, int y) { 
     img = new ImageIcon(image); 
     this.x = x; 
     this.y = y; 
    } 

    public Block(ImageIcon image, int x, int y) { 
     img = image; 
     this.x = x; 
     this.y = y; 
    } 

    public int getx() { 
     return x; 
    } 

    public int gety() { 
     return y; 
    } 

    public ImageIcon getImage() { 
     return img; 
    } 
} 

Вот основной код сервер

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 

public class Server { 

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

     ServerSocket s = new ServerSocket(5000); 
     do { 
      Socket c; 
      ObjectOutputStream out; 
      ObjectInputStream in; 

      //start listening 
      echo("Listening on port: 5000"); 

      //accept connection 
      c = s.accept(); 
      echo("Connected to client at address " + c.getInetAddress().getHostAddress()); 

      //open IO streams 
      out = new ObjectOutputStream(c.getOutputStream()); 
      in = new ObjectInputStream(c.getInputStream()); 

      ServerSession rdsession = new ServerSession(in, out); //start session 
     } while (true); 
    } 

    private static void err(String message) { 
     //prints error message and exits 
     System.err.println(message); 
     System.exit(1); 
    } 

    private static void echo(String message) { 
     //prints message 
     System.out.println(message); 
    } 
} 

Таким образом, когда соединение установлено, сервер создает экземпляр класса «ServerSession». Этот класс обрабатывает сеанс RD, определяя, когда отправлять новые изображения в объект «Блок». Когда ему нужно обновить блок для клиента, он использует метод Packet.send (Block, ObjectOutputStream).

Объект считывает объекты из потока, используя этот код:

import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 
import javax.swing.ImageIcon; 

public class Client { 

    public static void main(String[] args) throws IOException, ClassNotFoundException { 
     Socket c; 
     ObjectOutputStream out; 
     ObjectInputStream in; 
     String serverIP = "127.0.0.1"; //replace with server IP 
     int port = 5000; 

     //open connection and streams 
     c = new Socket(serverIP, port); 
     out = new ObjectOutputStream(c.getOutputStream()); 
     in = new ObjectInputStream(c.getInputStream()); 

     ClientSession cs = null; 

     do { 
       Packet<?> p; 
       Object o = in.readObject(); 
       if (o instanceof Packet) { 
        p = (Packet<?>) o; 
       } else { 
        continue; 
       } 
       if (p.getPayload() instanceof String) { //check if string 
        echo("Server>" + p.getPayload()); 
       } else if (p.getPayload() instanceof Block) { //check if block 
        Block b = (Block) p.getPayload(); 
        if (cs != null) { 
         cs.setImage(b.getImage(), b.getx(), b.gety()); 
        } 
       } else if (p.getPayload() instanceof ImageIcon[][]) { //check if 2-D image array 
        cs = new ClientSession(in, out, (ImageIcon[][]) p.getPayload()); //create session with image array 
       } 
     } while (true); 
    } 

    private static void err(String message) { 
     System.err.println(message); 
     System.exit(1); 
    } 

    private static void echo(String message) { 
     System.out.println(message); 
    } 
} 

Класс ClientSession просто хранит изображения экрана и ручки графического интерфейса пользователя.

Когда я запускаю сервер и клиент вместе, я получаю множество ошибок после отправки исходного массива ImageIcon [] [] каждый раз, когда клиент пытается прочитать экземпляр «Блок». Это ошибки, которые регулярно выброшенные:

1:

Exception in thread "main" java.io.InvalidClassException: Block; invalid descriptor for field 
    at java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:710) 
    at java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:828) 
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1599) 
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) 
    at Client.main(Client.java:46) 
Caused by: java.lang.IllegalArgumentException: illegal signature 
    at java.io.ObjectStreamField.<init>(ObjectStreamField.java:122) 
    at java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:708) 
    ... 11 more 

2:

Exception in thread "main" java.io.InvalidClassException: Block; invalid descriptor for field sq ~ sq 
    at java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:710) 
    at java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:828) 
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1599) 
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1515) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) 
    at Client.main(Client.java:25) 
Caused by: java.lang.IllegalArgumentException: illegal signature 
    at java.io.ObjectStreamField.<init>(ObjectStreamField.java:122) 
    at java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:708) 
    ... 19 more 

3:

Exception in thread "main" java.io.EOFException 
    at java.io.DataInputStream.readInt(DataInputStream.java:392) 
    at java.io.ObjectInputStream$BlockDataInputStream.readInt(ObjectInputStream.java:2818) 
    at java.io.ObjectInputStream.readInt(ObjectInputStream.java:969) 
    at javax.swing.ImageIcon.readObject(ImageIcon.java:481) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) 
    at Client.main(Client.java:25) 

4:

Exception in thread "main" java.io.StreamCorruptedException: invalid type code: 73 
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1769) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989) 
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) 
    at Client.main(Client.java:25) 

Спасибо, что нашли время, чтобы прочитать это сообщение. Любые советы будут очень признательны. Благодаря!

+1

Ваш вопрос очень длинный. Не могли бы вы решить эту проблему? –

+2

Проводка SSCCE поможет: http://sscce.org/ – Kon

+0

Что делает клиентская речь с потоками ввода и вывода? – jtahlborn

ответ

3

Проведя много времени на мой код, я решил, что проблема связана с тем, как я реализовал многопоточность на сервере. Потоки будут пытаться одновременно записывать в выходной поток, что приводит к повреждению потока. Спасибо всем за ваш вклад.

1

В файле Block.class есть что-то не так. Я бы перекомпилировал, повторно развернул на оба конца и перепробовал.

EOFException следует ожидать: вы пытались прочитать за конец ObjectInputStream, то есть когда сверстник закрыл свой конец соединения. Вам нужно поймать это отдельно, чтобы выбраться из вашего do/while (true).

NB Вы должны создать серверную сторону ObjectOutputStream и ObjectInputStream в методе run() начатой ​​нити. В настоящее время вы создаете их внутри цикла accept(), а также выполняете операции ввода-вывода, которые могут блокировать принятие потока от принятия других клиентов.

2

Ваша сериализация & данные об обмене/обмене выпадали из-под контроля - Клиент больше не выровнен и не считывает, откуда начинается действительный объект сервера (сериализованный).

Это, по-видимому, почему вы получаете InvalidClassException: Block; неверный дескриптор для поля и исключение StreamCorruptedException.

Ваш код передачи данных в основном зависит от сериализации & ImageIcon.

Не то, что этот подход является неправильным, но есть много предположений, необходимых для этой работы:

  1. версия класса является абсолютно идентичной,
  2. SerialVersion UIDS матча,
  3. ImageIcon сериализует,
  4. Внутренние данные ImageIcon совместимы между платформами,
  5. Сериализация & litte/big endian форматы совместимы.

Попробуйте удалить детали (например, материалы ImageIcon) и посмотреть, можете ли вы сохранить синхронизацию связи & в порядке. После того, как вы определили, почему связь была де-синхронизирована, вы можете выяснить причину.

+0

(1) не требуется. (3) указывается в Джавадоке. (5) гарантируется спецификацией сериализации объекта. Я согласен с вашим предложением о выходе из синхронизации, но я не вижу нигде в коде, где это может произойти. – EJP

+0

Ха-ха, я согласен;) Тем не менее, пока не доказано, что я предпочитаю придерживаться полностью широкого обзора проблемы. Это должно помочь его пониманию и исследованию, чтобы знать все факторы, которые он зависит от .. –

+1

(5) во внутренних классах ser spec (или были) не идеальны. diff VM ведут себя (d) по-разному – AlexWien

Смежные вопросы