TheDarkShado
TheDarkShado

Reputation: 75

Why does my UDP connection stop working?

After creating an UDP connection and connecting from the client to the server, it stops working randomly. Why is this happening?

This doesn't usually happen when running the client and the server on the same computer using "localhost" as the IP, but when using different computers on the same network it happens.

When I try and connect using different computers at first it works but after some time it just stops; the connection is "terminated". Also, ignore the game.player stuff, it is just a player of mine.

This is my code:

Client:

public class GameClient extends Thread {
  private InetAddress ipAddress;
  private DatagramSocket socket;
  private Main game;

  public GameClient(Main main, String ipAddress) {
    this.game = main;
    try {
      this.socket = new DatagramSocket();
      this.ipAddress = InetAddress.getByName(ipAddress);
    } catch (SocketException e) {
      e.printStackTrace();
    } catch (UnknownHostException e) {
      e.printStackTrace();
    }
  }

  public void run() {
    while (true) {
      byte[] data = new byte[1024];
      DatagramPacket packet = new DatagramPacket(data, data.length);
      try {
        socket.receive(packet);
      } catch (IOException e) {
        e.printStackTrace();
      }
      String message = new String(packet.getData());
      message = message.trim();
      if (message.startsWith("00")) {
        System.out.println("Player connected. Got server response...");
        String msg = "01" + game.player.getPos();
        sendData(msg.getBytes());
      }
      if (message.startsWith("01")) {
        message = message.substring(2);
        List<String> coords = Arrays.asList(message.split(","));
        game.updateMP(coords);
        String msg = "01" + game.player.getPos();
        sendData(msg.getBytes());
      }

    }
  }

  public void sendData(byte[] data) {
    DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress,
        1331);
    try {
      socket.send(packet);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

My server class:

public class GameServer extends Thread {
  private DatagramSocket socket;
  private Main game;

  public GameServer(Main main) {
    this.game = main;
    try {
      this.socket = new DatagramSocket(1331);
    } catch (SocketException e) {
      e.printStackTrace();
    }
  }

  public void run() {
    while (true) {
      byte[] data = new byte[1024];
      DatagramPacket packet = new DatagramPacket(data, data.length);
      try {
        socket.receive(packet);
      } catch (IOException e) {
        e.printStackTrace();
      }
      String message = new String(packet.getData());
      message = message.trim();
      if (message.startsWith("00")) {
        message = message.substring(2);
        game.playerConnected = true;
        sendData("00".getBytes(), packet.getAddress(), packet.getPort());
      }
      if (message.startsWith("01")) {
        message = message.substring(2);
        List<String> coords = Arrays.asList(message.split(","));
        game.updateMP(coords);
        String msg = "01" + game.player.getPos();
        sendData(msg.getBytes(), packet.getAddress(), packet.getPort());
      }

    }
  }

  public void sendData(byte[] data, InetAddress ipAddress, int port) {
    DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress,
        port);
    System.out.println(ipAddress + ", " + port);
    try {
      socket.send(packet);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

And my "Main" class: (just a part of it):

if (JOptionPane.showConfirmDialog(null, "Do you want to run the server?") == 0) {
  socketServer = new GameServer(this);
  socketServer.start();
  socketType = 0;
} else {
  socketClient = new GameClient(this, JOptionPane.showInputDialog(null, "IP:"));
  socketClient.start();
  socketClient.sendData("00".getBytes());
  socketType = 1;
}

Upvotes: 3

Views: 2333

Answers (1)

nix
nix

Reputation: 268

Looks like you have a packet flow without any delays. My suspicion is, that this mass of packets just overflows the network, thus breaking the "connection" (UDP is connectionless).

Let's break the packet flow down:

  • Server thread is created (constructor), binding to port 1331 (UDP).
  • Server thread starts, first step: listen on socket (blocking).
  • Client thread is created, binds to a random (free) port.
  • Client thread is started, first step: listen on socket (blocking).
  • Main thread calls sendData("00") on client, which works fine of course.
  • Server thread receives the "00" packet, sets playerConnected to true and sends "00" back (to inform the client of successful connection to the game). Then server listens again on the socket.
  • Client thread receives the "00" packet, and sends a "01..." packet. Client listens again on socket.
  • Server thread receives the "01" packet, updates its game object and sends a "01" packet back to the client (with no delay).
  • Client thread receives the "01" packet, updates its game object and sends a "01" packet back (with no delay)

The last two steps repeat indefinitely, with no delay.

On the same computer it works better, because the loopback interface is virtual and can handle much more packets per second, so the overflow happens later than on a real network.

Updating a position of a player in a network game is an issue as old as network games. There are many articles on that topic. Search e.g. for "client side position prediction" or sth. like "online game compensate latency", read the Quake2 source code (https://github.com/id-Software/Quake-2/blob/master/client/cl_pred.c) etc.

Beside of that: avoid using Strings, avoid creating tons of new byte arrays, for performance. In Java you will be punished by the Garbage Collector.

Upvotes: 1

Related Questions