проблема сериализации сервера клиента java - PullRequest
1 голос
/ 07 сентября 2011

Привет, я работаю над клиент-серверной программой, содержащей некоторые специальные функции, такие как отправка личного сообщения, показ списка в Интернете и т. Д., Поэтому я знаю, что должен использовать сериализацию, и сначала мне это удалось, но через некоторое время он облажался :).тратить время на обучение сериализации.Я буду делиться только значимыми частями для предотвращения сплоченности.и я хочу узнать, где я делаю неправильно.так что спасибо за вашу помощь в любом случае.Вот часть кода сервера;

    public class Server {

        private ServerSocket ss;
        private Socket socket;
        private Map<Socket,DataOutputStream> list = new HashMap<Socket,DataOutputStream>();
        private LinkedList<Person> client_list = new LinkedList<Person>();
        private String socketName;
        private Object lockObj = new Object();

        public Server(int port_number) throws IOException{

            create_Server(port_number);
        }

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

            int port_number=23;

            new Server(port_number);
        }

        private void create_Server(int port_number) throws IOException{

            ss = new ServerSocket(port_number);

            System.out.println("Server is ready!");

            while(true){

                socket=ss.accept();

                System.out.println(socket.getLocalAddress().getHostName() + " was connected!");

                send_con_mes();

                list.put(socket,new DataOutputStream(socket.getOutputStream()) );

                ServerThread st = new ServerThread(socket,this);

                Person per = new Person(socket.getInetAddress().toString());

                client_list.add(per);

                st.start();


            }

        }

            public LinkedList<Person> send_list(){  

                   return client_list;
        }

, поэтому я создаю сервер и жду ответа для любого сокета.Более того, я использовал список для сохранения сокета и его выходных данных, а clien_list сохраняет объект Object person (person является сериализуемым объектом).

здесь - часть serverthread

public class ServerThread extends Thread {

    private Socket s;
    private Server srv;
    private String socketName;
    private StringTokenizer str;
    private String message = "";
    private LinkedList<Person> client_list;
    private ObjectOutputStream oos;

    private static int i=0;

    public ServerThread(Socket s,Server srv){
        this.s = s;
        this.srv = srv;

        try {
            oos = new ObjectOutputStream(s.getOutputStream());

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void setList(){

        client_list = srv.send_list();

    }

    private LinkedList<Person> getList(){

        return client_list;
    }

    @Override
    public void run() {

        String msg;
        String token;
        DataInputStream dis;

        try {
            dis = new DataInputStream(s.getInputStream());

            while(true){

                msg = dis.readUTF();
                srv.send_to_All(msg, s);

                setList();

                oos.writeObject(getList());
                oos.flush();

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally{
            try {
                srv.remove_Connection(s);

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

, поэтому я отправляю client_list поверхObjectOutputStream oos для клиентов.

наконец, здесь клиентская часть, которая берет список и десериализует объект person и считывает информацию ...

public class Client extends javax.swing.JFrame implements Runnable {

    private DataOutputStream dos;
    private DataInputStream dis;
    private Socket s;
    private String Client_name;
    private String Ip_addr;
    private Font font = new Font("Arial", Font.PLAIN, 13);
    private int click_num_b=0;
    private int click_num_i=0;
    private LinkedList<Person> client_list;

    private FileOutputStream fos;
    private PrintStream pts;
    private ObjectInputStream socketIn;

/** Creates new form Client */
public Client() {
    initComponents();
    Screen.setEditable(false);

    Text_Field.setFont(font);
    Screen.setFont(font);
    start_Chat();

}

    @Override
    public void run() {

        try {

            while(true){

                    read_list();

                String message = dis.readUTF();
                Screen.append(message + "\n");

            }

        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

    }


    private void read_list() throws IOException{

        socketIn = new ObjectInputStream(s.getInputStream());

        try {

            client_list = (LinkedList<Person>) socketIn.readObject();

            for (Iterator<Person> itr = client_list.iterator(); itr.hasNext();) {

                Person per = itr.next();

                pts.println(per.getnickName() );

            }

            socketIn.close();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void start_Chat() {
        try {

            Ip_addr = JOptionPane.showInputDialog("Enter the IP number of the server to connect : ");
            s = new Socket(Ip_addr, 23);

            Client_name = JOptionPane.showInputDialog("Enter your Nickname : ");

            dis = new DataInputStream(s.getInputStream());         
            dos = new DataOutputStream(s.getOutputStream());

            fos = new FileOutputStream("personList.txt");
            pts = new PrintStream(fos);

            new Thread(Client.this).start();

здесь private ObjectInputStream socketIn; принимает сериализуемыйобъект и пишет в файл.Вот некоторые ошибки, с которыми я сталкиваюсь

java.io.EOFException
    at java.io.DataInputStream.readUnsignedShort(Unknown Source)
    at java.io.DataInputStream.readUTF(Unknown Source)
    at java.io.DataInputStream.readUTF(Unknown Source)
    at ServerThread.run(ServerThread.java:58)


SEVERE: null
java.io.StreamCorruptedException: invalid type code: 00
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at Client.read_list(Client.java:81)
    at Client.run(Client.java:61)
    at java.lang.Thread.run(Unknown Source)

, поэтому я признателен, если вы поможете мне решить эту проблему.

Ответы [ 3 ]

1 голос
/ 07 сентября 2011

Отправляйте только свои собственные объекты.Например,

interface ServerToClientPacket { 
    void performAction(Client c); 
}

class MyMessage implements ServerToClientPacket {
    String message;
    MyMessage(String message) { this.message = message; }
    void performAction(Client c) {
        JOptionPane.showMessageDialog(message);
    }
}

class PersonList implements ServerToClientPacket {
    LinkedList<Person> people;
    // constructor here
    void performAction(Client c) {
        for(Person person : people) {
            c.pts.println(person);
        }
    }
}

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

1 голос
/ 07 сентября 2011

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

0 голосов
/ 07 сентября 2011

Вы предполагаете, что «должны использовать сериализацию».Сериализация, безусловно, является вариантом здесь, но, безусловно, не единственным вариантом.

Сериализация имеет пару недостатков:

  • Java-специфичный
  • Сложный - сериализация однаиз более продвинутых функций языка Java
  • Хитрость для рефакторинга (если вы не всегда можете одновременно обновить и клиент, и сервер, внесение изменений в сериализованные классы может быть хитрым)
  • Трудно отлаживать (если есть проблема, вы не можете вручную проверить, что происходит "по проводам" и посмотреть, правильно ли это)

Использование другой кодировки, которая была разработана для связи клиент-сервер (поставляется JSON)на ум) стоит подумать.

(я знаю, что это раздражает, когда вы задаете вопрос «как сделать foo с X», и люди отвечают «не используйте X, используйте Y!»,но кажется, что вы могли бы рассмотреть это ...)

...