Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 4 of 4

Thread: Problem in chat program, Server sending Arraylist<String> but clients receiving old values

  1. #1
    Junior Member
    Join Date
    Dec 2013
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Problem in chat program, Server sending Arraylist<String> but clients receiving old values

    I wanted to create a simple game with a server and more than one clients. Server will have several Hashmaps and Arraylists. Server will broadcast these to clients, then one by one a client may modify these and send back to server and then server will broadcast updated values to all clients.

    To get started, I have created Server - Client chat app. When a client sends String message to server, Server will add that String message to it's Arraylist and will broadcast that arraylist to all clients. I have used threads so that multiple clients can send messages concurrently, but I haven't applied thread-safety yet.

    Lets come to the problem. for the first time when a client sends String to server, server prints it well, add to it's arraylist, then broadcasts it to all clients and all clients can see that too. But next time when client sends String message, server accepts it, adds to arraylist and broadcasts it, but this time all clients gets old arraylist ( list with only one String which was added first ). I have printed arraylist before broadcasting and it shows modified values, but at client side it shows list with one entry only.

    Part of Server code
    public class ServerGUI extends javax.swing.JFrame {
     
        public static final int SERVER_PORT = 4000;
        private ServerSocket ss;
        ArrayList<String> al;
        ArrayList<ClientHandler> clients;
     
        public ServerGUI() {
            initComponents();
            setVisible(true);
            al = new ArrayList<>();
            clients = new ArrayList<>();
            initNet();
        }
     
        private void initNet() {
            Socket ds = null;
            try {
                ss = new ServerSocket(SERVER_PORT, 1);
                while (true) {
     
                    ds = ss.accept();
     
                    clients.add(new ClientHandler(ds));
                }
            } catch (Exception e) {
     
                System.out.println("shutting down server......");
            }
        }
     
        class ClientHandler extends Thread {
     
            private Socket ds;
            private ObjectOutputStream out;
            private ObjectInputStream in;
     
            public ClientHandler(Socket ds) throws Exception {
                this.ds = ds;
                out = new ObjectOutputStream(ds.getOutputStream());
                in = new ObjectInputStream(ds.getInputStream());
                start();
            }
     
            public ObjectOutputStream getOut() {
                return out;
            }
     
           public void run() {
                try {
                    while (true) {
                        acceptData(in);
                        broadcastData();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    System.out.println("Finally called. socket closed");
                    if (ds != null) {
                        try {
                            ds.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
     
        private void acceptData(ObjectInputStream in) throws Exception {
            System.out.println("acceptData called by " + Thread.currentThread().getName());
            String s = (String) in.readObject();
            al.add(s);
            jta.setText(al.toString());
        }
     
        private void broadcastData() throws Exception {
            System.out.println("broadcast called by " + Thread.currentThread().getName());
            System.out.println("al is : \n" + al);
     
            for (ClientHandler clnt : clients) {
                clnt.getOut().writeObject(al);
                clnt.getOut().flush();
            }
        }

    Part of Client code

    public class ClientGUI extends javax.swing.JFrame {
     
        public static final int SERVER_PORT = 4000;
        public static final String SERVER_IP = "127.0.0.1";
        private Socket s1;
        private ObjectOutputStream out;
        private ObjectInputStream in;
        private ArrayList<String> al;
     
        public ClientGUI() {
            initComponents();
            setVisible(true);
            initNet();
        }
     
        private void initNet() {
            try {
                s1 = new Socket(SERVER_IP, SERVER_PORT);
                out = new ObjectOutputStream(s1.getOutputStream());            
                in = new ObjectInputStream(s1.getInputStream());
                System.out.println("connected to server");
     
                new ReadData();
     
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
        class ReadData extends Thread {
     
            public ReadData() {
                start();
            }
     
     
            public void run() {
                System.out.println("client thread started");
                try {
                    while (true) {
                        al = (ArrayList<String>) in.readObject();
                        System.out.println("client read completed, al is "+al);
     
                        jta.setText(al.toString());                    
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    private void textFieldActionPerformed(java.awt.event.ActionEvent evt) {                                    
        try {
            out.writeObject(jtf.getText());
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    I have attached netbeans projects if you want to try.
    Attached Files Attached Files


  2. #2
    Super Moderator
    Join Date
    Jun 2013
    Location
    So. Maryland, USA
    Posts
    4,728
    My Mood
    Mellow
    Thanks
    172
    Thanked 622 Times in 609 Posts

    Default Re: Problem in chat program, Server sending Arraylist<String> but clients receiving old values

    Since an ArrayList is not thread safe, I think choosing a collection that is will be fundamental to resolving your problem due to the multiple while( true ) loops accessing the same variables from separate threads. The Collections.synchronizedList() may be the answer. OR you may consider a design pattern that lends itself to managing multiple clients to a server, Observer/Observable, Event Bus, etc.

  3. #3
    Junior Member
    Join Date
    Dec 2013
    Posts
    2
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default Re: Problem in chat program, Server sending Arraylist<String> but clients receiving old values

    I don't think this problem is related to thread safety, because same problem is there when only one client is present. Still I tried replacing ArrayList with Vector since Vector is threadsafe

  4. #4
    Member andbin's Avatar
    Join Date
    Dec 2013
    Location
    Italy
    Posts
    443
    Thanks
    4
    Thanked 122 Times in 114 Posts

    Default Re: Problem in chat program, Server sending Arraylist<String> but clients receiving old values

    One issue I immediately found: you are accessing the user interface (setText) in a thread that is not the EDT, Event Dispatch Thread. This is wrong. Except for few well known (and documented) operations, Swing is not thread-safe. You should manipulate the user interface only in the EDT.

    And second (the most important for your question): you are using the object serialization and there is one important thing that you do not know yet: object serialization, by default (using writeObject) uses a "caching" mechanism. When you write an object for the first time, it sends the real content. The second time you send the same object, it doesn't send the content but only a sort of "reference", just to tell "hey, it's the same sent before".

    Solution: use writeUnshared instead of writeObject.

    And take care of thread-safety for the lists, since it's also another (potential) issue in your code.
    Andrea, www.andbin.net SCJP 5 (91%) SCWCD 5 (94%)

    Useful links for Java beginners My new project Java Examples on Google Code

Similar Threads

  1. Sending and Receiving Via Tcp And Udp
    By amit1983 in forum Java Theory & Questions
    Replies: 4
    Last Post: December 9th, 2013, 02:56 PM
  2. Sending and Receiving File
    By beer-in-box in forum Java Networking
    Replies: 8
    Last Post: March 31st, 2013, 07:57 PM
  3. Simple client-server chat program
    By Saloni Patil in forum Java Networking
    Replies: 3
    Last Post: October 22nd, 2011, 09:29 AM
  4. 1 Server- Multiple Clients Program
    By jclark1186 in forum Java Networking
    Replies: 2
    Last Post: September 23rd, 2011, 11:44 AM
  5. Sending and Receiving mail using J2ME without server
    By chals in forum Java ME (Mobile Edition)
    Replies: 5
    Last Post: June 2nd, 2009, 09:59 AM