How to make a Multiplayer Applet game using UDP
Assuming you have the JDK installed and an IDE working where you can compile and run programs, we will get into the aspects of network coding. We will be working with a server/client method using UDP, not TCP/IP. UDP is best for fast paced games that need up to date info, but can handle lost packets every once in a while. We will be using an Applet for the client, but you can use a regular application for your game.
I will also be using a transfer method which utilizes the best defense against hackers, where the client only sends key presses vs. sending other important information like where the player is currently located.
First of all you will want to download, by right click and save as, the UDPServer.java and UDPClient.java source code to look at while reading this tutorial. For easier use I put all the class files related to each side in one file. So just paste the code in one java file for simple compiling and testing.
|The class structure of the Server is:||The class structure of the Client is:|
The Server Side
Lets take a look at the server code first. The server will house all the game's code, like the regular game loop and any other game related code. The ServerThread class runs along side the regular game loop, it receives all the packets sent from clients.
protected DatagramPacket packet = null;
We will start with the variables. DatagramSocket is the tunnel where all the packets are sent and received through, and the DatagramPacket is the package that gets transferred in byte format.
This creates the socket on port 5556, you can use any unsigned 16 bit number in the range of 1024 to 65535 as your port. Many of the ports below 1024 are reserved service ports used by other programs on your computer like e-mail.
//receive message from client
byte buf = new byte;
packet = new DatagramPacket(buf, buf.length);
//translate message in a thread
String message = new String(packet.getData(), 0, packet.getLength());
Translator translator = new Translator(playerList,message);
The receivePacket() method is one of the most important methods in the class. This will need the most optimization since it will be receiving all the packets that all of the clients will be sending through out the game. I have opted to put the translations of the packet strings in a seperate thread so the game loop can go on while the string is translated into usable information.
packet = new DatagramPacket(buf, buf.length); creates a packet with the constructor taking a byte array and its size for the packet. Be sure to keep the received packet size no bigger than this packet you specify or the received info will be truncated into this packet's size.
The Translator translator = new Translator(playerList,message); line creates a temporary thread that will translate the received message from the client. With the implementation I produced, all it does is retrieve wheather or not a key is pressed.
//create message of all xs and ys of all players
byte buf = playerList.toString().getBytes();
//send the message to the client to the given address and port
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buf, buf.length, address, port);
The sendPacket() method calls the playerList.toString() which converts all the players positions for transport along with all the player's names for distinction. You can fill in all the data you would like all players to know in the toString() method.
The next line retrieves the address from which the client sent the packet, and uses it as the destination address. The same thing happens with the port. The next line packs all that information into the packet, then sends it over the socket used earlier.
The Client Side
The important thing to remember about the client is the socket does not need a port but the packet does need the address and port of the server in which you are using. In this implementation the first thing the client does is retrieve the username and ip address through the getParameter() method.
ipAddress = getParameter("ip");
These variables can be set in the html code that starts up the applet when using a browser with the following code.
<param name="username" value="Guest">
<param name="ip" value="localhost">
Since we will be testing through our own IDE we will set username to Guest and the IP Adress to localhost.
receiveThread = new ReceiveThread(socket,playerList);
We then create a socket with no port as we stated above, and create a ReceiveThread passing the new socket and the playerList as parameters to the constructor. The receiveThread creates a thread that will receive repsonses from the server and translate them into player x and y locations.
The method above is the only important method that runs inside the client applet.
InetAddress address = InetAddress.getByName(ipAddress);
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 5556);
Similar to the sending method of the server, the client instead creates an InetAddress from the given ipAddress. The packet is then made from the address and the hardcoded port number 5556. The packet is then sent through the socket created earlier, with the message being the key presses.
The other method that is relevant to the network code is in the client receiving method which is running in the background waiting for any messages sent back by the server. But after going through the code above, it should be self explanitory.
Running The Game
To test out the given code, you will be able to test it through your IDE as long as the ip address is localhost. To put it out on the internet you will have to sign the client or run the server off where you host your website.
Running the server on your own computer for public use will require unlocking the port stated above in your firewall if no connections are being made otherwise. You may also need to port forward the port number to your local network router.
I hope this helps anyone in their own endeavors, everyone is free to use this code in any way. Be sure to check out our games and help us out by downloading and rating them up, we will always be an independent studio ;)
Published June 15, 2009
- By Oscar J. Gomez