java客户端服务器序列化问题

时间:2011-09-06 22:19:14

标签: java serialization client-server eofexception

嗨,我正在研究一个客户端服务器程序,其中包含一些特殊功能,如发送私人消息,显示在线列表等等所以我知道我必须使用序列化,首先我管理它但过了一段时间搞砸了:)现在我花时间学习序列化。我将只分享有意义的部分以防止混乱。我想知道我做错了什么。所以,谢谢你的帮助。这是服务器代码的一部分;

    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;
        }

所以我正在创建服务器并等待任何套接字的响应。而且我使用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();
            }
        }
    }

}

所以我将{_ 1}上的client_list发送给客户。

最后这里是客户端部分,它接受列表并反序列化person对象并读取信息......

ObjectOutputStream oos

在这里,private 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(); 获取可序列化对象并写入文件。这是我面临的一些错误

ObjectInputStream socketIn;

所以我很感激,如果你能帮助我处理这个问题。

3 个答案:

答案 0 :(得分:1)

看起来您正在使用相同流的流和装饰版本。因为有一些缓冲正在进行,这不会起作用。坚持只使用一个装饰实例。

答案 1 :(得分:1)

只发送自己的对象。例如

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);
        }
    }
}

每个人都将在客户端上使用已序列化的数据实现自己的performAction。定义行为时,不要将其放在客户端中,而是将其放入消息中。然后,您的客户端只不过是从套接字传递给它的各种消息和行为的显示机制。

答案 2 :(得分:0)

您认为您必须使用序列化'。序列化当然是一种选择,但肯定不是唯一的选择。

序列化有几个缺点:

  • Java的特定
  • 复杂 - 序列化是Java语言的更高级功能之一
  • 棘手的重构(如果你不能总是同时升级客户端和服务器,那么对序列化的类进行更改可能会很棘手)
  • 难以调试(如果出现问题,您无法手动检查线路上的内容,并查看是否正确)

使用为客户端 - 服务器通信设计的另一种编码(JSON可以想到)可能值得考虑。

(当我问一个问题“我怎么用X做foo”时,我知道这很烦人,人们回答“不要使用X,使用Y!”,但似乎你可能想要考虑这一点。 ..)