title: Java - Simple networked game is extremly laggy
body: <p><em>I already asked this on codereview a day ago but I haven't got any responses yet, so I though I'd try to ask it here.</em></p>
  
  <p><strong>Let me tell you what I'm trying to make:</strong></p>
  
  <p>A window pops up asking the user if they want to run a server, or a client. Choosing server will start a server on the LAN. Choosing client will try to connect to that server. Once a server is running and a client has connected, a window pops up with two squares. Both the server/client can move their square with the arrow-keys. </p>
  
  <p><strong>This is what I'm getting:</strong></p>
  
  <p>The square for the server moves at the wanted speed, but his movement is very choppy on the side of the client. The clients square, on the other hand, seems to move at about 3 pixels per second (way too slow).</p>
  
  <p><strong>This is what I'm asking:</strong></p>
  
  <p>I guess my question is pretty obvious. All I'm doing is sending 2 integers over the internet. Modern online games send <strong>much</strong> more data than this, and they hardly lag, so obviously I'm doing something wrong, but what?</p>
  
  <p><strong>Server.java:</strong></p>
  
  <pre><code>// server class
  public class Server {
      // networking objects
      private ServerSocket serverSocket;
      private Socket clientSocket;
      private DataOutputStream clientOutputStream;
      private DataInputStream clientInputStream;
      // game objects
      private Vec2D serverPos, clientPos;
      private GameManager gameManager;
      // run method
      public void run() {
          // intialization try-catch block 
          try {
              // setup sockets
              serverSocket = new ServerSocket(1111);
              clientSocket = serverSocket.accept();
              // setup I/O streams
              clientOutputStream = new DataOutputStream(clientSocket.getOutputStream());
              clientInputStream = new DataInputStream(clientSocket.getInputStream());
          } catch(IOException e) { Util.err(e); }
          // declare &amp; intialize data exchange thread
          Thread dataExchange = new Thread( 
              new Runnable() {
                  // run method
                  @Override
                  public void run() {
                      // I/O try-catch block
                      try {
                          // exchange-loop
                          while(true) {
                              // write x &amp; y, flush
                              synchronized(gameManager) {
                                  clientOutputStream.writeInt(serverPos.x);
                                  clientOutputStream.writeInt(serverPos.y);
                                  clientOutputStream.flush();
                              }
                              // read x &amp; y
                              clientPos.x = clientInputStream.readInt();
                              clientPos.y = clientInputStream.readInt();
                          }
                      } catch(IOException e) { Util.err(e); }
                  }
              }
          );
          // setup game data
          serverPos = new Vec2D(10, 10);
          clientPos = new Vec2D(300, 300);
          gameManager = new GameManager(serverPos, clientPos, serverPos);
          // start data exchange thread
          dataExchange.start();
          // start main loop
          while(true) {
              // get keyboard input
              synchronized(gameManager) {    
                  gameManager.update();
              }
              // repaint, sleep
              gameManager.repaint();
              Util.sleep(15);        
          }
      }
  }
  </code></pre>
  
  <p><strong>Client.java:</strong></p>
  
  <pre><code>// client class
  public class Client {
      // networking objects
      private Socket serverConnection;
      private DataOutputStream serverOutputStream;
      private DataInputStream serverInputStream;
      // game objects
      private Vec2D serverPos, clientPos;
      private GameManager gameManager;
      // run method
      public void run() {
          // intialization try-catch block 
          try {
              // setup socket
              serverConnection = new Socket(InetAddress.getByName("192.168.0.19"), 1111);
              // setup I/O streams
              serverOutputStream = new DataOutputStream(serverConnection.getOutputStream());
              serverInputStream = new DataInputStream(serverConnection.getInputStream());
          } catch(IOException e) { Util.err(e); }
          // declare &amp; intialize data exchange thread
          Thread dataExchange = new Thread( 
              new Runnable() {
                  // run method
                  @Override
                  public void run() {
                      // I/O try-catch block
                      try {
                          // exchange-loop
                          while(true) {
                              // read x &amp; y
                              synchronized(gameManager) {
                                  serverPos.x = serverInputStream.readInt();
                                  serverPos.y = serverInputStream.readInt();
                              }
                              // write x &amp; y, flush
                              serverOutputStream.writeInt(clientPos.x);
                              serverOutputStream.writeInt(clientPos.y);
                              serverOutputStream.flush();
                          }
                      } catch(IOException e) { Util.err(e); }
                  }
              }
          );
          // setup game data
          serverPos = new Vec2D(10, 10);
          clientPos = new Vec2D(300, 300);
          gameManager = new GameManager(serverPos, clientPos, clientPos);
          // start data exchange thread
          dataExchange.start();
          // start main loop
          while(true) {
              // get keyboard input
              synchronized(gameManager) {    
                  gameManager.update();
              }
              // repaint, sleep
              gameManager.repaint();
              Util.sleep(15);  
          }
      }
  }
  </code></pre>
  
  <p>I got rid of a bunch of the code - I hope it isn't confusing now. Thanks for the help!</p>