Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Network sent Vector only updates once in client?  (Read 1544 times)
0 Members and 1 Guest are viewing this topic.
Offline CyanPrime
« Posted 2010-09-28 20:29:05 »


Okay, so I'm trying to send a vector of objects from server to client. the clients take control of one object from the vector and send it's x and y to the server vector.

Now the server is running fine from what I can tell. things are updating in real time, but the client only seems to update right once - when it starts.

this is the client code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

import java.io.*;
import java.net.*;
import java.util.Vector;

public class SlickClient extends BasicGame{

    ClientThread ct;
    Vector<Player> players;
    Player me;
    int ALL_KEYS = 0xFF;
    boolean keys[];

    public SlickClient()
    {
        super("Test Online Client - by William Starkovich");
    }

    public void init(GameContainer gc) throws SlickException {
        try{
            keys = new boolean[ALL_KEYS];

            for(int i = 0; i < ALL_KEYS; i++){
                keys[i] = false;
            }

            players = new Vector<Player>();

            connect();
        }

        catch(Exception e){

        }
    }

    public void connect(){
        String ip = "127.0.0.1";
        ct = new ClientThread(ip);
        ct.start();
        ct.setPriority(Thread.MAX_PRIORITY);

        me = ct.me;
        players = ct.players;
    }

    public void update(GameContainer gc, int delta)throws SlickException{
        controls();

        players = new Vector<Player>();

        System.out.println("ct size: " + ct.players.size());

        me = ct.me;
        players = ct.players;
    }

    public void render(GameContainer gc, Graphics g) throws SlickException{
        g.setColor(Color.black);
        g.fillRect(0,0,640,480);

        for(int i = 0; i < players.size(); i++){
            g.setColor(Color.cyan);
            g.fillRect(players.get(i).x, players.get(i).y, 50, 50);
        }

        g.drawString("Players: " + players.size(), 50, 10);
    }

    public void keyPressed(int key, char c) {
        keys[key] = true;
    }

    public void keyReleased(int key, char c) {
        keys[key] = false;
    }

    public void controls(){
        if(keys[Input.KEY_UP]){
            me.y--;
        }

        else if(keys[Input.KEY_DOWN]){
            me.y++;
        }

        else if(keys[Input.KEY_LEFT]){
            me.x--;
        }

        else if(keys[Input.KEY_RIGHT]){
            me.x++;
        }
    }

    public static void main(String[] args) throws SlickException{
     AppGameContainer app =
        new AppGameContainer( new SlickClient() );

     app.setShowFPS(false);
     app.setAlwaysRender(true);
     app.setTargetFrameRate(60);
     app.setDisplayMode(800, 600, false);
     app.start();
    }
}

class ClientThread extends Thread implements Runnable{
    Socket socket;
    Vector<Player> players;
    int playerID;
    Player me;
    DataOutputStream out;
    ObjectInputStream in;
    boolean loop = true;

    @SuppressWarnings("unchecked")
    public ClientThread(String ip){
        super("ClientThread");

        try{
            this.players = new Vector<Player>();
            socket = new Socket(ip, 4444);
            socket.setTcpNoDelay(true);
            out = new DataOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());
            playerID = in.readInt();
            this.players = (Vector<Player>) in.readObject();

            if(this.players != null)
                System.out.println("Not Null: " + this.players.size());

            boolean b = false;
            for(int i = 0; i < this.players.size(); i++){
                if(!b){
                    if(this.players.get(i).id == playerID){
                        me = this.players.get(i);
                        b = true;
                    }
                }
            }
        }

        catch(Exception e){
            e.printStackTrace();
        }
    }

    public void run(){
        try{
            while(loop){
                try{
                    if(!socket.isClosed() && socket.isConnected()){
                        out.writeInt(me.x);
                        out.writeInt(me.y);
                        out.flush();

                        this.players = new Vector<Player>();
                        this.players = (Vector<Player>) in.readObject();

                        System.out.println("size" + players.size());
                        sleep(15);
                    }

                    else
                        loop = false;

                }
                catch(Exception e){
                        e.printStackTrace();
                        socket.close();
                }  
            }



        }

        catch(Exception e){
            e.printStackTrace();
        }
    }
}


Edit: server code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
import java.net.*;
import java.util.Vector;
import java.io.*;
import javax.swing.*;
import java.io.Serializable;

public class SlickServer extends JFrame{

    private static final long serialVersionUID = 1L;

    JTextArea textArea;
    JScrollPane scrollPane;

    public SlickServer(){
        super("Test Online Server - by William Starkovich");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 100);
        setLocationRelativeTo(null);

        textArea = new JTextArea();

        scrollPane = new JScrollPane(textArea);

        //getContentPane().add(textArea);
       getContentPane().add(scrollPane);
    }

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

        Vector<Player> player = new Vector<Player>();

        SlickServer ss = new SlickServer();
        ss.setVisible(true);

        ServerSocket serverSocket = new ServerSocket(4444);
        boolean listening = true;

        int playerID = 0;

        while(listening){
            ss.textArea.append("Waiting to connect with player: " + playerID  + "\n");
            new ClientThread(serverSocket.accept(), player, playerID, ss.textArea).start();
            playerID++;
            ss.textArea.append("Players: " + player.size() + "\n");
        }

        serverSocket.close();
        System.exit(0);
    }
}


class ClientThread extends Thread implements Runnable{
    int playerID;
    Socket acceptedSocket;
    JTextArea textArea;
    Vector<Player> players;
    Player me;

    public ClientThread(Socket acceptedSocket, Vector<Player> players, int playerID, JTextArea textArea){
        super("ClientThread");
        this.acceptedSocket = acceptedSocket;
        this.players = players;
        players.add(new Player(50,50, playerID));

        if(players != null)
            System.out.println("Not Null: " + players.size());

        boolean b = false;
        for(int i = 0; i < players.size(); i++){
            if(!b){
                if(players.get(i).id == playerID){
                    me = players.get(i);
                    b = true;
                }
            }
        }

        this.playerID = playerID;
        this.textArea = textArea;
    }

    public void run(){
        try{
            Socket clientSocket = acceptedSocket;
            clientSocket.setTcpNoDelay(true);
            textArea.append("Accepted. Now creating I/O.\n");
            DataInputStream in = new DataInputStream(clientSocket.getInputStream());
            ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
            textArea.append("player connected. \n");
            out.writeInt(me.id);
            out.writeObject(players);
            out.flush();

            while(!clientSocket.isClosed() && clientSocket.isConnected()){

                me.x = in.readInt();
                me.y = in.readInt();

                if(players != null)
                    System.out.println("Not Null: " + players.size());


                textArea.append("PlayerID: " + playerID + " Players: " + players.size() + " me.x: " + me.x + " me.y: " + me.y + "\n");

                out.writeObject(players);
                out.flush();

               sleep(15);
            }

        }

        catch(Exception e){
            e.printStackTrace();
            System.exit(1);
        }


    }

}


class Player implements Serializable{
    private static final long serialVersionUID = 1L;
    int x;
    int y;
    int id;

    public Player(int x, int y, int id){
        this.x = x;
        this.y = y;
        this.id = id;
    }
}
Offline CyanPrime
« Reply #1 - Posted 2010-09-28 21:03:46 »

Added server code.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 12


Game Engineer


« Reply #2 - Posted 2010-09-28 22:00:05 »

I don't even see you using the InputStream in the client anywhere?

See my work:
OTC Software
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline CyanPrime
« Reply #3 - Posted 2010-09-28 22:31:42 »

I don't even see you using the InputStream in the client anywhere?

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
class ClientThread extends Thread implements Runnable{
...
     public ClientThread(String ip){
         ...
         in = new ObjectInputStream(socket.getInputStream());
         ...
         this.players = (Vector<Player>) in.readObject();
    }
...


    public void run(){
       ...
                    if(!socket.isClosed() && socket.isConnected()){
                        ...
                        this.players = (Vector<Player>) in.readObject();
                    }
}
Offline CyanPrime
« Reply #4 - Posted 2010-09-28 23:29:17 »

Tried taking out the multi-threading from the client. It worked, but  I still got the same errors:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

import java.io.*;
import java.net.*;
import java.util.Vector;

public class SlickClient extends BasicGame{
   
   //ClientThread ct;
  Vector<Player> players;
   Player me;
   int ALL_KEYS = 0xFF;
   boolean keys[];
   
   Socket socket;
   int playerID;
   DataOutputStream out;
    ObjectInputStream in;
    boolean loop = true;
   
   public SlickClient()
    {
        super("Test Online Client - by William Starkovich");
       
       
    }
   
   public void init(GameContainer gc) throws SlickException {
      try{
         keys = new boolean[ALL_KEYS];
         
         for(int i = 0; i < ALL_KEYS; i++){
            keys[i] = false;
         }
         
         players = new Vector<Player>();
         
         
         //connect();
     }
     
      catch(Exception e){
         
      }
     
      try{
         this.players = new Vector<Player>();
         socket = new Socket("127.0.0.1", 4444);
         socket.setTcpNoDelay(true);
         out = new DataOutputStream(socket.getOutputStream());
           in = new ObjectInputStream(socket.getInputStream());
         playerID = in.readInt();
         this.players = (Vector<Player>) in.readObject();
         
         if(this.players != null)
            System.out.println("Not Null: " + this.players.size());
         
         boolean b = false;
         for(int i = 0; i < this.players.size(); i++){
            if(!b){
               if(this.players.get(i).id == playerID){
                  me = this.players.get(i);
                  b = true;
               }
            }
         }
      }
     
      catch(Exception e){
         e.printStackTrace();
      }
   }
   
   public void update(GameContainer gc, int delta)throws SlickException{
      controls();
     
      try{
         if(!socket.isClosed() && socket.isConnected()){
              out.writeInt(me.x);
              out.writeInt(me.y);
              out.flush();
             
              this.players = new Vector<Player>();
              this.players = (Vector<Player>) in.readObject();
             
              System.out.println("size" + players.size());
              //sleep(15);
        }
         
         else
            loop = false;
     
        }
      catch(Exception e){
             e.printStackTrace();
             //socket.close();
      }  
     
      //players = new Vector<Player>();
     
      //System.out.println("ct size: " + ct.players.size());

   }
   
   public void render(GameContainer gc, Graphics g) throws SlickException{
      g.setColor(Color.black);
      g.fillRect(0,0,640,480);
     
      for(int i = 0; i < players.size(); i++){
         g.setColor(Color.cyan);
         g.fillRect(players.get(i).x, players.get(i).y, 50, 50);
      }
     
      g.drawString("Players: " + players.size(), 50, 10);
   }
   
   public void keyPressed(int key, char c) {
      keys[key] = true;
   }
   
   public void keyReleased(int key, char c) {
      keys[key] = false;
   }
   
   public void controls(){
      if(keys[Input.KEY_UP]){
         me.y--;
      }
     
      else if(keys[Input.KEY_DOWN]){
         me.y++;
      }
     
      else if(keys[Input.KEY_LEFT]){
         me.x--;
      }
     
      else if(keys[Input.KEY_RIGHT]){
         me.x++;
      }
   }
   
   public static void main(String[] args) throws SlickException{
    AppGameContainer app =
      new AppGameContainer( new SlickClient() );
   
    app.setShowFPS(false);
    app.setAlwaysRender(true);
    app.setTargetFrameRate(60);
    app.setDisplayMode(800, 600, false);
    app.start();
   }
}


going to revert it back to multi-threading though.
Offline lhkbob

JGO Knight


Medals: 32



« Reply #5 - Posted 2010-09-28 23:50:03 »

Can you be more specific on what the client "see's" from the server?  Does the client never even see other players connect when it reads in the new vector?  Does it only see its own position changing? Does it see any changes coming after each poll of the server, or does it even correctly loop and read in 2nd and 3rd states etc.

Are you absolutely positive that the server is working correctly?  Does one thread for player A in the server see changes to player B's position as B sends in updates, or do you only know that player B's thread sees B sending in updates.  Are you sure the server is sending the correct state vector back to the client?

Given your recent questions, I have to recommend taking a step back from multi-threading like this.  There are a lot of memory complications at risk.  One thread can see old memory values of variables updated by another thread, etc. unless you adequately protect yourself.  The only thing I'm seeing of that is that Vector is synchronized, which might inadvertently be making your server appear safe.

Offline CyanPrime
« Reply #6 - Posted 2010-09-28 23:58:32 »

the client only gets the server's player vector. It only gives it's x and y to the player object inside the vector with the same id.

the server threads see the changes from player vector because  the test text shows size 2 on id 1 when there's 2 connections. id 2 also shows 2 in size.

1  
 textArea.append("PlayerID: " + playerID + " Players: " + players.size() + " me.x: " + me.x + " me.y: " + me.y + "\n");


Offline CyanPrime
« Reply #7 - Posted 2010-09-29 02:52:26 »

For some reason I have to add reset before each time I write to the OOS.

code:
1  
2  
3  
out.reset();
out.writeObject(players);
out.flush();

Offline adon_y_coya

Senior Newbie





« Reply #8 - Posted 2010-09-29 07:51:50 »

I remember I've had some problems with serializing Vector objects over the Object streams as well.
Maybe serializing and deserializing the Vectors through Data streams will solve the issue.
Offline divxdede

Junior Member





« Reply #9 - Posted 2010-09-29 08:34:15 »

ObjectOutputStream keep track all object's references , until you invoke close() or reset().
So I you keep it as a long-lived OutputStream, invoke frequently #reset() for clear it's internal handle table.

The ObjectInputStream can has the same negate effect, it retain an handletable when it perform deserialization.
You can't manually discard it's handle table without closing the input stream.
But when you reset the OutputStream a TC_RESET is push on the stream that will be handled by the ObjectInputStream.
So, each time you reset the outputstream, the inputstream will perform also the reset in order to be in sync with their handles table.

So, the reset is a good thing, you MUST do it in order to preserve your memory and let the garbage collector done it's job.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline lhkbob

JGO Knight


Medals: 32



« Reply #10 - Posted 2010-09-29 16:44:09 »

the server threads see the changes from player vector because  the test text shows size 2 on id 1 when there's 2 connections. id 2 also shows 2 in size.

You didn't listen, of course the Vector will correctly report changes to its sizes. It's synchronized internally, so any add() will properly update the value returned by size(). That is not a good measurement of how correct your server is working.  Because of threading-memory issues it is possible that each thread saw a different version of the player's coordinates.  Thus any vector sent to the player would be wrong, even if it properly said it had a size of 2.

But, I think divxdede is probably right in this case so you can go about your way, using threads in a dangerous manner.

Offline divxdede

Junior Member





« Reply #11 - Posted 2010-09-29 18:43:11 »

The reset can be also an error in the deserialization process.

Studying this example:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
   Client:    Point playerLocation = getPlayerLocation();   // give instance A with x=22 , y=45
                oos.write( playerLocation );

   Server    Point playerLocation = (Point)ois.readObject(); // give instance B (deserialized) with x=22, y =45

    // stay a while

   Client:    Point playerLocation = getPlayerLocation();   // give instance A with x=30 , y=46
                oos.write( playerLocation );

   Server    Point playerLocation = (Point)ois.readObject(); // give instance B (deserialized) with x=22, y =45
                // You don't have the new location because the handletable was not reseted.
                // When the client sent the playerLocation, the ObjectOutputStream know it had already serialized this instance
                // and just push on the stream the "ref-handle" that is an identifier.
                // The object input stream read this ref-handle and return the previously deserialized instance.
                // This mecanism is done for preserve instance topology

           
So if you write a new time the same instance that has muted to the server, you must reset the ObjectOutputStream before.
Now, maybe you have also a threading issue and needs synchronization.


   
                 
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (55 views)
2014-04-15 18:08:23

BurntPizza (53 views)
2014-04-15 03:46:01

UprightPath (66 views)
2014-04-14 17:39:50

UprightPath (49 views)
2014-04-14 17:35:47

Porlus (66 views)
2014-04-14 15:48:38

tom_mai78101 (90 views)
2014-04-10 04:04:31

BurntPizza (151 views)
2014-04-08 23:06:04

tom_mai78101 (246 views)
2014-04-05 13:34:39

trollwarrior1 (204 views)
2014-04-04 12:06:45

CJLetsGame (211 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!