I have a client/server setup. When both are loaded they are identical(Buttons, labels, TextFields and such). When I click a button on the client it performs an action on the server, displaying other TextFields, Labels and buttons. Now I need the same actions to be performed on all clients. What is the best way to perform these actions. The objects are already created on the client just need to make them visible and set the values of the Objects(set visible, set text, set Icon, set location and set size).

Any help is greatly appreciated.

Recommended Answers

All 28 Replies

so ... what you want is that two users can simultaneously use the application, but if one user does something, that immediately changes the application's behaviour on the other machine as well ?
what 's the point of that? for showing information, I can understand, but to set whether or not a button is enabled ... this should not be dependent on a click on a button in another client (not if that client is of the same module)

you could (on update on the server) broadcast a message to all registered clients to update their screen.

And updating Client's screen is what I don't know how to do. I'm trying to do a LAN based card game. So each player will need to see the same events on their screen as they happen. I have never done any server programing before, and new to java. I think I may be going about it the hard way, BUT I currently have once the client clicks on a button it sends a statment to the server to perform the click on the server. Once the server Completes it "Click Function" it sends a statment to the client/clients to perform the same action on their side. I have read up a little on Java's RMI and don't "think" that's what I need. I looked at "object serialization" and that looks close but would I need to send the complete objoect everytime a label changes color or button changes text. If so, if the object changes would I have multiple occurances of the object or would the old one get replaced by the new one.

ehm .... you think RMI is not (in the direction of) what you need, but serialization is ? serialization doesn't inform your server/client from anything, it just allows you to send your data. it's using rmi, or another messaging system that you actually send the signal.

no, you don't need to send the entire object (I assume, since I don't know what your object is, or what exactly you are trying to do).
if you try to run a thread where someone clicks a button, and all followers of that thread get a message on their screen, or the field for all clients open on that thread need to display something, you just need to send the id of the thread and what to display (to whom)

The "(on update on the server) broadcast a message to all registered clients to update their screen." you mentioned earlier sounds like the direction I need to go, but I have no idea how to get there. What method would I need to use?

The way I have handled this in the past is by creating a simple text based messaging system and using UDP to broadcast the messages. This requires that all the clients have a thread running that just listend for incoming messages. When a UDP packet is received, that thread needs to update your data model, but it CAN NOT update the UI. In Swing, only the EventDispatch Thread can update the UI. This leaves you with something like this:

   if(newCardPlayedOrSomething) {
      //change some data to bring the client in sync with the server.
      javax.swing.SwingUtilities.invokeLater(new Runnable() {
         public void run() {
           methodThatUpdatesUI();
         }
      });
   }

Are you using Datagrams? (for example, see http://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html)

llaspina I'm using a TCP connection. Per stultuske's hint that using RMI would be the way to do what I need, I have been researching ORACLE tutorial on using RMIs trying to get the jist of what needs to be done. There can be up to 6 clients connected at any given time. The players can come and go as they please. When a client joins the game, the current game state will need to be sent to the client and all other clients will need to recieve an update that the client has joined the game. Also if a player leaves the game the other clients will need to recieve an update that the player has left the game. This is an Object oriented card game. Thank you for your suggestion llaspina, I have tried something like what your speaking off in your example but the problem I have is if a client joins in the middle of the game they don't recieve the current game state.

if you use a classic model/view pattern then this is straighforward.
Your "model" classes encapsulate the current state of the game (who has which cards, whose turn is it next etc) in a purely logical form (no user interface artifacts). Your "view" classes display the current state as a GUI or whatever (no involvement in how that state evolved).
The model is maintained on the server. The GUI(s) live on the client(s). All clients have a thread that sits in a loop listening on an ObjectInputStream on their server connection. Whenever anything happens to change the model the server sends the latest state to all the clients. When a client receives a new state it displays it.
When the user does something the client sends the corresponding request to the server, which updates the model (and thus sends its latest state to all clients).

THAT sounds like it fits my criteria perfectly. Off to do more learning. This time on Model/Veiw.

O.K., I've read though a couple docs about MVC. My program is server based. Currently my server has a GUI identical to client with the exception of being setup as server. Which means I click a button that starts the server and the server waits for clients to connect. Now if the server and the controller are on the same machine and the clients are on a different machine since the controller is the only line of communication between the Model and the View then it would seem the server should reside on the controler. The Model would tell the server to connect when the connect button on the model GUI was clicked. Then when a client clicked connect on the view GUI, it would send to the controller which would update both model and view that they are connected. If that is correct then all the button listeners would need to be on the controller correct?

The "controller" part of the MVC model is always a point of confusion with Swing-type GUIs because the listeners are hard to separate from their controls.
My best advice is to ignore it in this case; just go MV, let the GUI talk directly to the model.

Doesn't that still leave me the issue of updating new views/clients as they join?

Please post your code or a link to it on github.

James I think I understand what your saying. The setup of the code is the same the view just request form the model the information and the model sends the update to all the views.

llaspina the code is massive.

Massive is relative, but I expected it's too long to just post here. That's why I suggested git.

view just request form the model the information and the model sends the update to all the views.

No. No request. The clients just listen. The model sends new data when it needs to. The model knows when that is, the clients don't know when to ask for new data.

@Jim, I know it has been a while but I have been adding a server/client that will accept multiple clients (Not easy for a newbie). Can you give me more details on how you would approach Model/View/Controller or Model/View pattern.

Note: The server and client are currently 2 seperate programs.

I know the server will be the model and the client will be the view. With them being seperate it almost seems I would need to use a controller. I'm not locked in to doing it in this manner and open to any suggestons.

Please review the answer I gave earlier about how the client and server interact - no need for a controller.

The client connects to the server and waits for update messages.
When it receieves an update message it updates its display using the current state of the model. (The update message can include the complete latest state, unless that's very large, in which case the cliens can request the bits they are interested in)

When a client connects, the server sends it one update message.

When a user does something, his client sends a corresponding request to the server.
When the server receives a request it updates its model and sends an update message to every connected client.

At this level of abstraction, that's all you need.

If I understand correctly. Client clicks on a button in the view, the button has an action listener that detects the button has been clicked and calls for an action to be performed. The action will be to send a message to the server/model stating that a client has clicked this button. The server recieves the message that the button was clicked on clients view. The server performs the action caused by the button being clicked then sends the result as an update to all clients that updates the GUIs on all views. If this is correct, how would I package the update to send to the clients. I know I will need to send it as an object but a single button click could change the state of several objects. So I guess I'm asking would I need to send an update each time an objects state is changed or is there a way to send a single object that includes the current state of all the objects.

Unless the server's model is very large it's easier just to send a copy of the whole model as a single object. (If you don't have a top-level object that encapsulates the whole current state, then maybe you should do that first).

I have my GUI created in a JPanel on the server/model side. I know I don't have to have a Gui on the server side but I believe that it needs to be created there and passed to the Client(s)/View(s) as an object from the server. If that's not the case then please inform me of such. 

Also in one of my game project files (I have tried a few different things with this game which has left me with a few different projects) I used a PrintWriter and a BufferedReader on the server and client to send and recieve messages(works in certain scenarios but not what I needed). I believe these are used primarily for reading and writing String messages and I need to send objects. In the mentioned project I have a loop in the server that checks for a message the server wants to send to the client like:

NOTE: toSend ia a variable that contains the message to be sent and includes           the \n to indicate the end of the message.

`if (toSend.length() != 0) {
     out.print(toSend);
     out.flush();
     toSend.setLength(0);
}`

and also checks for any messages the client(s) have sent to the server like:

`if (in.ready()) {
    s = in.readLine();
    if ((s != null) && (s.length() != 0)) {
        // Check if it is the end of a trasmission
        if (s.equals(END_CHAT_SESSION)) {
            changeStatusTS(DISCONNECTING, true);
            } // Otherwise, receive what text
        else {
            switch (s) {

            */Some other code/*
        }
    }
}`

How would I do this using ObjectOutputStream and ObjectInputStream.
  1. No. Each client creates its own GUI. All it neeeds from the server is the current model data. (Different clients mayhave completely different GUIs, eg PC vs smartPhone)

  2. Yes, use object streams. You can send commands as strings via the object stream because Strings are Objects (no need for the \n).

  3. Just open the streams and use their read & write methods (see API doc). It's very easy.

That is way far too much code for you to debug your first attempt at client/server object passing. I suggest you park it, and write a tiny proof of concept that just passes a couple of objects from a client to a server and back again. When you get that working you will know how to do it in a more complex environment. It's a standard novice mistake to write too much code before starting to test. Real programmers test early, test often, and thus only have to deal with one bug at a time. I also didn't see much on the way of debugging or trace output, so you will have no idea what's happening and what's going wrong.

It's far too much code for anyone to read and understand just for fun, but I did notice you had both print and object strteams declared on the same socket. You can't mix two types of stream on one socket.

Thank you for your time. I will make some changes that will reduce the code. I know of a few things in the gui that I don't need and getting rid of those items will greatly reduce the code in the layout and create table methods and maybe the server and client methods also. Once again THANK YOU for all of your help on this whole project.

I'm not able to update the GUI/View on the "Client" to the current state of the model. I'm getting - Server has closed the connection: java.io.InvalidClassException: javax.swing.text.JTextComponent; local class incompatible: stream classdesc serialVersionUID = -8043358055867187832, local class serialVersionUID = -4317496854124604564 from client even after setting the serialVersionUID myself. I'm totaly lost on this part of the project.

This is the start of the "Server side" program:

public static void main(String args[]) {
        //Create the GUI
        createAndShowGUI();

        //Create a model of GUI
        GUI model = new GUI();

        //Create view from the model
        GUIView view = new GUIView();

        //Create game controller and add the model and view
        GameController controller = new GameController(model, view);

        //Set GUI to current state of the GUI
        controller.setGUITableLayout(TableLayout);

        //Update the view
        controller.updateView();
    }

The first line of code run is:
The CreateAndShowGUI code:

private static void createAndShowGUI() {

        Connection1();

        //Create and set up the window.
        frame = new JFrame("Blackjack by Henderson Games  -SERVER-");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                server.stop();
                server = null;
            }
        });

        TableLayout = new Create_Server_Layout(port);
    }

The variable "TableLayout" is what I'm using to encapsulate all the controlls in the GUI with the line of code, "TableLayout = new Create_Server_Layout(port);", Create_Server_Layout(port) method creates and adds the controlls to a layered pane and creates the server conection.

public Create_Server_Layout(int port) {

        server = null;

        ...Code to add all the controlls and button action listeners omitted

        ConnectServer();

         add(Pane);
    }

The next line of code is:
The GUI model = new GUI(); code:

public class GUI implements Serializable{

    private JComponent TableLayout;

    public JComponent getTableLayout(){
        return TableLayout;
    }

    public void setTableLayout(JComponent TableLayout){
        this.TableLayout = TableLayout;
    }
}

The next line of code is the
GUIView view = new GUIView(); code:

public class GUIView{

    public void UpdateAllViews(JComponent GUImodel){

        frame.add(GUImodel);
        frame.setContentPane(GUImodel);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }
}

I know something else has to go in here(But WHAT?) since this just adds the model to the frame and makes frame visible, or maybe I need to add another method that actually updates something. I'm currently only using this method at startup after that I have a line of code at the end certain methods the broadcast to all clients. The line of code is:

broadcastObj(model);
That line of code calls the broadcastObj(model):

public static synchronized void broadcastObj(GUI model) {

        GUI messageLf = model;

        // we loop in reverse order in case we would have to remove a Client
        // because it has disconnected
        for (int i = al.size(); --i >= 0;) {
            ClientThread ct = al.get(i);

            // try to write to the Client if it fails remove it from the list
            if (!ct.sendObj(messageLf)) {
                al.remove(i);
                System.out.println("Disconnected Client " + ct.username + " removed from list.");
            }
        }
    }

Which calls sendObj() method:

private boolean sendObj(GUI model) {
            // if Client is still connected send the object to it
            if (!socket.isConnected()) {
                close();
                return false;
            }

            // write the object to the stream
            try {
                sOutput.writeObject(model); //BLOCKING HERE
            } // if an error occurs, do not abort just inform the user
            catch (IOException e) {
                System.out.println("Error sending message to " + username);
                System.out.println(e.toString());
            }
            return true;
        }

The next line of code is:
The GameController controller = new GameController(model, view); code:

public class GameController {
    public static GUI model;
    public static GUIView view;

    public GameController(GUI model, GUIView view){
        this.model = model;
        this.view = view;
    }

    public void setGUITableLayout(JComponent TableLayout){
        model.setTableLayout(TableLayout);
    }

    public JComponent getGUITableLayout(){
        return model.getTableLayout();
    }

    public void updateView(){

        view.UpdateAllViews(model.getTableLayout());

    }
}

The next line of code is the
controller.setGUITableLayout(TableLayout); code:

public void setGUITableLayout(JComponent TableLayout){
        model.setTableLayout(TableLayout);
    }

From the GameController Class.

Followed by:
controller.updateView();

as noted earlier, dosen't do much.
_______________________________________________________________________

Am I going in the right direction with this project? What am I missing? Havn't found any examples of using MVC with a GUI over a Server/Client setup. So any help is very much appreciated.

I have absolutely no idea where that code is going!
You have something called "model" but it's an instance of "GUI" and has table layouts and some such. That seems to contradict the whole concept of MVC. And why on earth would a "GUI" be serialisable?

All I can suggest is that you forget client/server for the moment and correctly partition your code into a view (no state or state transition logic, contains all the GUI) and a model (all the state info and logic, no GUI) with a clean interface between them. If you have done that correctly then you should be able to write a tiny and simple test class that updates and runs the model without the gui being present at all. Then you can expose that interface in a client/server way.

The class Create_Table_Layout is where all my controls or control arrays are created. I read that any object that is passed through the ObjectOutputStream must be serializable so the class Create_Table_Layout is serializable. TableLayout is a JComponent that is a layout created using that class. I have also cast TableLayout to model for the purpose of using MVC. The GUI may have been made serializable as a result of me chasing my tail trying to get this working. I have searched vastly trying to figure this out and have had no luck finding anything that uses MVC with a GUI and Client/Server. If this were a simple output to console game I feel I would have it working already. I'm not asking for copy & paste code just a push in the right direction.

As far as seperating the model from the view then creating an interface between the two. Would these be three seperate projects or one project with three seperate classes.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.