Страницы

Поиск по вопросам

пятница, 5 июля 2019 г.

Проблема с ObjectInputStream. (StreamCorruptedException: invalid type code: AC)

Вообще изначальная задача - написать игру с двумя игроками, что-то типа точек. т.е. один игрок (клиент) делает ход, отправляет данные (координаты x и y) на сервер. Сервер обрабатывает эту информацию и отправляет сообщение с какими-то данными всем подключенным клиентам. Все это надо реализовать на сокетах. За основу взяла реализацию чата, но мне удобнее передавать объекты, поэтому использую ObjectInputStream и ObjectOutputStream. Написала пример: клиент вводит координаты x y, отправляет на сервер. На сервере хранится матрица А. Получаем от клиента x,y, присваиваем A[x][y]=1, отправляем всем клиентам объект класса ServerAnswer (матрица, x,y). Клиент получает и выводит матрицу. Для начала запускаю только один клиент. Первый раз все работает, но когда я ввожу новые координаты на клиенте, они отправляются на сервер, он посылает ответ и на клиенте при попытке выполнения - sa = (ServerAnswer)ois.readObject(); вылетает ошибка апр 17, 2014 12:06:45 PM client2.SocketInputThread run SEVERE: null java.io.StreamCorruptedException: invalid type code: AC at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1377) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) at client2.SocketInputThread.run(SocketInputThread.java:37) at java.lang.Thread.run(Thread.java:744) Подскажите. пожалуйста, что не так в коде. Код Сервера: public class Server2 {
public static void main(String[] args) { System.out.println("Program starting..."); try { ServerSocket ss = new ServerSocket(3129,0, InetAddress.getByName("localhost")); System.out.println("Server starting..."); while(true){ Socket s = ss.accept(); // ожидание новых клиентов SocketThread socketThread = new SocketThread(s); Thread t = new Thread(socketThread); t.start(); // запуск нового потока для каждого нового клиента } } catch (IOException ex) { Logger.getLogger(Server2.class.getName()).log(Level.SEVERE, null, ex); }
} } Класс SocketThread: public class SocketThread implements Runnable {
private Socket s = null;
private boolean exit = true; private int x = -1; private int y = -1; private int p = 0; private int [][]A; private ArrayList listSocket = null; private ObjectInputStream ois = null; private ObjectOutputStream oos = null;
public SocketThread(Socket s) { this.s = s; }
@Override public void run() { try { System.out.println("User connect..."); ListSocket.addSocketToList(s); // добавление текущого сокета с глобальной список сокетов
InputStream in = s.getInputStream(); ois = new ObjectInputStream(in);//получаем от игрока новое ребро
A = new int [5][5]; for (int i = 0; i<5; i++) for (int j = 0; j < 5; j++) { A[i][j] = 0; }
while (s.isConnected()) {
Para new_p = (Para)ois.readObject();
x = new_p.X(); y = new_p.Y(); p = new_p.P();
A[x][y] = p; System.out.println(x + ";" + y); ServerAnswer sa = new ServerAnswer(5, 5); sa.SetAns(new_p, A);
listSocket = ListSocket.getListSocket(); for (Socket socket : listSocket) { // отсылка сообщения всем сокетам
oos = new ObjectOutputStream(socket.getOutputStream()); oos.writeObject(sa); oos.flush(); }
} ListSocket.removeSocketWithList(s); // если поток завершается то сокет клиента удаляется из списка сокетов System.out.println("User disconnect..."); } catch (IOException ex) { try { s.close(); } catch (IOException ex1) { Logger.getLogger(SocketThread.class.getName()).log(Level.SEVERE, null, ex1); } Logger.getLogger(SocketThread.class.getName()).log(Level.SEVERE, null, ex); } catch (ClassNotFoundException ex) { Logger.getLogger(SocketThread.class.getName()).log(Level.SEVERE, null, ex); } } } Клиент: public class Client2 {
public static void main(String[] args) { try { System.out.println("Client starting..."); Socket s = new Socket("localhost",3129); System.out.println("Connect to server..."); Thread threadIn = new Thread(new SocketInputThread(s));// создание отдельного потока на считывание даных от сервера Thread threadOut = new Thread(new SocketOutputThread(s));// создание отдельного потока на ввод даных с клавиатуры threadIn.start(); threadOut.start(); } catch (UnknownHostException ex) { Logger.getLogger(Client2.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Client2.class.getName()).log(Level.SEVERE, null, ex); } } } SocketInputThread: public class SocketInputThread implements Runnable {
private Socket s = null; private ObjectInputStream ois = null;
public SocketInputThread(Socket s) { this.s = s; }
@Override public void run() { try { InputStream in = s.getInputStream(); ois = new ObjectInputStream(in);
while(true){ ServerAnswer sa;
sa = (ServerAnswer)ois.readObject(); String str = "";
for (int i=0; iprivate Socket s = null; private ObjectOutputStream oos = null;
public SocketOutputThread(Socket s) { this.s = s; }
@Override public void run() { try { Scanner sc = new Scanner(System.in);
oos = new ObjectOutputStream(s.getOutputStream()); while (true) { int x = sc.nextInt(); int y = sc.nextInt(); Para p = new Para(); p.SetPara(x,y,1);
oos.writeObject(p); oos.flush(); } } catch (IOException ex) { Logger.getLogger(SocketOutputThread.class.getName()).log(Level.SEVERE, null, ex); } } }


Ответ

На один ObjectOutputStream должен приходиться ровно один ObjectInputStream Поясню: Корректный object stream выглядит так: [stream header], [object], [object], [object],... У вас object stream'ы выглядят так: [stream header], [object], [object], [stream header], [object], ... Stream header записывается каждый раз при создании нового ObjectOutputStream. Ваш invalid type code: AC означает, что ObjectInputStream ожидал прочитать объект, а прочитал хидер начала потока. То есть ошибка тут: for (Socket socket : listSocket) { // отсылка сообщения всем сокетам oos = new ObjectOutputStream(socket.getOutputStream()); Нужно хранить не список сокетов, чтобы каждый раз, проходясь по ним, создавать новые ObjectOutputStream'ы, а хранить список ObjectOutputStream'ов и переиспользовать их.

Комментариев нет:

Отправить комментарий