#java #sockets #serialization
#java #Сокеты #Сериализация
Вопрос:
Я задал еще один вопрос
У меня есть сервер классов:
package server;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import javax.swing.DefaultListModel;
import objects.Player;
public class Servidor implements Runnable, Observer {
int puerto;
public DefaultListModel<Player> players = new DefaultListModel<>();
public ArrayList<Socket> clients = new ArrayList<>();
public static Send m;
public Servidor(int puerto, Send m) {
this.m = m;
this.m.addObserver(this);
this.puerto = puerto;
System.out.println(this.m " from the server")
}
@Override
public void run() {
ServerSocket servidor = null;
Socket sc = null;
ObjectOutputStream output;
try {
servidor = new ServerSocket(puerto);
System.out.println("Server Started");
while (true) {
sc = servidor.accept();
System.out.println("New Cliente");
output = new ObjectOutputStream(sc.getOutputStream());
output.writeObject(m);
clientes.add(sc);
}
} catch (IOException ex) {
}
}
public void Send_Players() throws IOException {
for (Socket sc : clients) {
ObjectOutputStream output = new ObjectOutputStream(sc.getOutputStream());
output.writeObject(players);
}
}
@Override
public void update(Observable o, Object arg) {
//Stuff
}
Тогда у меня есть свой клиентский класс:
package server;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.Observable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import objects.Player;
public class Client extends Observable implements Runnable {
String host;
int puerto;
Socket sc;
public Client(int purto, String host) {
this.puerto = purto;
this.host = host;
try {
sc = new Socket(host, puerto);
} catch (IOException ex) {
}
}
@Override
public void run() {
DataInputStream in;
ObjectInputStream input = null;
DefaultListModel<Player> players = new DefaultListModel<>();
try {
in = new DataInputStream(sc.getInputStream());
input = new ObjectInputStream(in);
} catch (IOException ex) {
}
while (true) {
Object objeto = null;
try {
objeto = input.readObject();
} catch (ClassNotFoundException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
if (objeto != null) {
System.out.println("Is: " objeto.getClass().getName());
if (objeto instanceof DefaultListModel) {
players = (DefaultListModel<Player>) objeto;
this.setChanged();
this.notifyObservers(players);
this.clearChanged();
} else {
Send m = (Send) objeto;
this.setChanged();
this.notifyObservers(m);
this.clearChanged();
}
}
}
}
}
А также класс отправки:
package server;
import java.io.Serializable;
import java.util.Observable;
public class Send extends Observable implements Serializable{
private static final long serialVersionUID = 1L;
public void Send_(Object arg){
this.setChanged();
this.notifyObservers(arg);
this.clearChanged();
}
}
Теперь я объясню, как это работает:
-
Когда я создаю сервер, я добавляю его в качестве наблюдателя класса Send
-
Когда я создаю нового клиента, сервер обнаруживает его
-
Когда пришел новый клиент. Он отправляет объект типа Send.
-
В клиентском классе он обнаруживает с помощью observable, что что-то пришло, и уведомляет класс с именем Main.
-
Когда наблюдатель класса Main получает уведомление, он делает это:
this.m = (Send) arg; System.out.println(this.m " from the class Main");
Но класс, отправляемый с сервера, не равен классу, отправляемому из класса Main
Но мне нужно, чтобы они были равны, чтобы я мог использовать метод Send_ в классе send для уведомления наблюдателя
Вывод: сервер.Отправка @6576a5d6 с сервера запускает сервер новых клиентов: server.Отправьте сервер sipili.Отправить @156ecdb0 с клиента
и мне нужно, чтобы первая строка вывода (объект 1) должна совпадать с последней строкой вывода
Примечание: я думаю, что это как-то связано с сериализованной версией
Комментарии:
1. В чем здесь вопрос? Что вы подразумеваете под «класс не равен»? Вы получаете исключение? Неожиданное поведение?
2. нет, я говорю так, как будто класс не является одним и тем же экземпляром, например: статическая переменная всегда одна и та же, но нестатическая переменная отличается при создании новой
3. Когда вы делаете это: ExampleClass class = новый класс, вы создали новый класс. когда вы печатаете класс, например, так: System.out.println(class); , Он печатает что-то вроде этого ExampleClass@8483de6 конечные номера присутствуют, потому что вы можете создавать несколько классов этого типа, поэтому они могут быть разными, и каждый из них использует свои собственные переменные. Когда я создаю его из своего серверного класса, это выглядит так: Send@138nf5, но когда я использую ObjectOutputStream, он не отправляет это: Send@138nf5, он отправляет новый класс, поэтому я не могу использовать переменные из этого класса
4. Нет. Пожалуйста, исправьте свою терминологию. У вас есть путаница между классами и объектами (или экземплярами). Когда вы это делаете
new ExampleClass()
, вы создаете новый объект типаExampleClass
.ObjectOutputStream
отправляет то, что вы говорите ему отправить, но оно принимается как новый объект, если только оно уже не было отправлено и вы не использовалиreset()
илиwriteUnshared()
, и в этом случае он возвращает вам существующий объект, но в этом случае, конечно, без каких-либо изменений, которые могли быть внесены на отправляющей стороне. Неясно, что вы на самом деле спрашиваете здесь.5. Да, я ссылаюсь на это как на объект. И нет, когда я отправляю объект, он создает новый, откуда я это знаю? Просто используя System.out.println(), и он печатает 2 разных объекта в 2 разных классах
Ответ №1:
К сожалению, вы не можете, в https://docs.oracle.com/javase/8/docs/api/java/io/ObjectInputStream.html в нем говорится, что способ, которым это работает, заключается в том, чтобы.
- Отправка типа объекта.
- Создание нового объекта.
- Замена значений на те, которые находятся в вашем другом классе.
Таким образом, невозможно сделать точную копию.