Welcome to Dream.In.Code
Getting Java Help is Easy!

Join 136,158 Java Programmers for FREE! Get instant access to thousands of Java experts, tutorials, code snippets, and more! There are 2,111 people online right now. Registration is fast and FREE... Join Now!




Creating a server to serve clients

 
Reply to this topicStart new topic

> Creating a server to serve clients, For applications from MMORPGs to others

Rating  5
WolfCoder
Group Icon



post 3 Dec, 2007 - 10:48 AM
Post #1


Preface:
Alright! I've figured out how to do this in an efficient way to where the clients can connect and begin transmission to the server program quickly. For all of those who want to try out making an MMORPG, this is actually an easy way to start. Before going through my tutorial, please learn the basics of JAVA or you might get lost (however, you can at least try it out anyway but realize you may become a little lost).


I bet you wanna make the kinds of MMO games she plays all the time right?
IPB Image

Or maybe you just wanna special server and client system for something in particular? Well in JAVA it's much easier than even I thought! Pull up a chair and fire up your programming environment~

There are two JAVA objects in the API that are interesting to us. The ServerSocket and the Socket object. One to accept socket connections from the client and the other to connect to the server. Does it sound too simple? It's is! In fact, you'll run into problems with synchronization way more often than connecting the clients. Let's connect a simple client to a simple server! Compile both programs and run them as two different instances of a program.

CODE

import java.net.ServerSocket;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class ServerTest
{
    private static ServerSocket serverSocket;
    private static Socket clientSocket;
    private static BufferedReader bufferedReader;
    private static String inputLine;
    public static void main(String[] args)
    {
        // Wait for client to connect on 63400
        try
        {
            serverSocket = new ServerSocket(63400);
            clientSocket = serverSocket.accept();
            // Create a reader
            bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            // Get the client message
            while((inputLine = bufferedReader.readLine()) != null)
            System.out.println(inputLine);
        }
        catch(IOException e)
        {
            System.out.println(e);
        }
    }
}


and the client...

CODE

import java.net.Socket;
import java.io.PrintWriter;
public class ClientTest
{
    private static Socket socket;
    private static PrintWriter printWriter;
    public static void main(String[] args)
    {
        try
        {
            socket = new Socket("localhost",63400);
            printWriter = new PrintWriter(socket.getOutputStream(),true);
            printWriter.println("Hello Socket");
            printWriter.println("EYYYYYAAAAAAAA!!!!");
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}


Run the server... It looks like it's frozen but it's waiting for a socket from the client to connect. Run the client and it will finish. Take a look at the server program's console... There's your messages followed by an exception generated from the socket from the client disconnecting.

getInputStream() and getOutputStream() will hold the execution there until the client has established an output stream where the server establishes an input stream. Any sort of input or output stream can be created (like an ObjectInputStream). So you can send and receive data in any way you wish doing this. Whatever way is most comfortable to you (or the way you think is easiest to learn) is fine for now.

The parts of interest are the following lines:
socket = new Socket("localhost",63400);
serverSocket = new ServerSocket(63400);
To connect, the target is the local host on the same machine. It could be an IP address for a server if you want to connect over the internet. If you're on a LAN then you can try this on two separate machines. Use the IP of the machine running the server instead of "localhost" to try it out. Also, depending on your network structure, you may be able to do this over the internet with some other user.

But...
How do you connect multiple clients? I mean it is a server, it's got to serve multiple clients! What good is an MMORPG or a chat room with just you in there? You might want to have a loop accepting socket connections and save them in a list to track all the clients... But you'll encounter a problem! For sending, receiving, accepting, and connecting things, they all WAIT until the operation is complete! If you've got someone with a slow connection it will sit there and wait for them to complete the transaction or fail!

Think for a moment. You've got multiple people who want service and some are slower than others, but you gotta satisfy everyone. That is where you multitask! You need parallel operations for ALL clients. And... Thread will do just that for you!

Here's a cutout from my own server program.

CODE

import java.net.ServerSocket;
import java.net.Socket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.IOException;
import java.util.ArrayList;
/**
* This handles all of the Umbra clients in the room.
* It accepts new connections and adds them to the room.
* It is a runnable thread and when the start method is called, it will accept clients.
*/
public class UmbraRoom extends Thread
{
    private static final int UMBRA_PORT = 30480;
    private static final int ROOM_THROTTLE = 200;
    private ServerSocket serverSocket;
    private InetAddress hostAddress;
    private Socket socket;
    private ArrayList<UmbraUser> users = new ArrayList<UmbraUser>();
    /**
     * Creates a new Umbra room for clients to connect to.
     */
    public UmbraRoom()
    {
        // Attempt to get the host address
        try
        {
            hostAddress = InetAddress.getLocalHost();
        }
        catch(UnknownHostException e)
        {
            System.out.println("Could not get the host address.");
            return;
        }
        // Announce the host address
        System.out.println("Server host address is: "+hostAddress);
        // Attempt to create server socket
        try
        {
            serverSocket = new ServerSocket(UMBRA_PORT,0,hostAddress);
        }
        catch(IOException e)
        {
            System.out.println("Could not open server socket.");
            return;
        }
        // Announce the socket creation
        System.out.println("Socket "+serverSocket+" created.");
    }
    /**
     * Starts the client accepting process.
     */
    public void run()
    {
        // Announce the starting of the process
        System.out.println("Room has been started.");
        // Enter the main loop
        while(true)
        {
            // Remove all disconnected clients
            for(int i = 0;i < users.size();i++)
            {
                // Check connection, remove on dead
                if(!users.get(i).isConnected())
                {
                    System.out.println(users.get(i)+" removed due to lack of connection.");
                    users.remove(i);
                }
            }
            // Get a client trying to connect
            try
            {
                socket = serverSocket.accept();
            }
            catch(IOException e)
            {
                System.out.println("Could not get a client.");
            }
            // Client has connected
            System.out.println("Client "+socket+" has connected.");
            // Add user to list
            users.add(new UmbraUser(socket));
            // Sleep
            try
            {
                Thread.sleep(ROOM_THROTTLE);
            }
            catch(InterruptedException e)
            {
                System.out.println("Room has been interrupted.");
            }
        }
    }
}


CODE

import java.net.Socket;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* This object handles the execution for a single user.
*/
public class UmbraUser
{
    private static final int USER_THROTTLE = 200;
    private Socket socket;
    private boolean connected;
    private Inport inport;
    /**
     * Handles all incoming data from this user.
     */
    private class Inport extends Thread
    {
        private ObjectInputStream in;
        public void run()
        {
            // Open the InputStream
            try
            {
                in = new ObjectInputStream(socket.getInputStream());
            }
            catch(IOException e)
            {
                System.out.println("Could not get input stream from "+toString());
                return;
            }
            // Announce
            System.out.println(socket+" has connected input.");
            // Enter process loop
            while(true)
            {
                // Sleep
                try
                {
                    Thread.sleep(USER_THROTTLE);
                }
                catch(Exception e)
                {
                    System.out.println(toString()+" has input interrupted.");
                }
            }
        }
    }
    /**
     * Creates a new Umbra Client User with the socket from the newly connected client.
     *
     * @param newSocket  The socket from the connected client.
     */
    public UmbraUser(Socket newSocket)
    {
        // Set properties
        socket = newSocket;
        connected = true;
        // Get input
        inport = new Inport();
        inport.start();
    }
    /**
     * Gets the connection status of this user.
     *
     * @return  If this user is still connected.
     */
    public boolean isConnected()
    {
        return connected;
    }
    /**
     * Purges this user from connection.
     */
    public void purge()
    {
        // Close everything
        try
        {
            connected = false;
            socket.close();
        }
        catch(IOException e)
        {
            System.out.println("Could not purge "+socket+".");
        }
    }
    /**
     * Returns the String representation of this user.
     *
     * @return  A string representation.
     */
    public String toString()
    {
        return new String(socket.toString());
    }
}


This will accept Socket connections from a client. It also tries to establish an InputStream with the client. Look closely, notice how I start some threads for every client. The rest of the clients won't be effected when a different client is slow, it won't wait for it. Study carefully on how dead clients are closed and removed and how the threads quit on failure. Now, I purposefully left the threads to run even when the client is removed, but you can see where the connection can fail and where you should make the thread quit (using return is easy).

Lots of exceptions can occur for various reasons, it's important to do what is needed in their case. Try writing a client to connect to this server and connect lots of them. Then make the server remove them when they disconnect.

From here on out, I shouldn't tell you how to establish a stream pair going the other way (from server to client) or what the server and client should do to messages being received. This is because... It varies from what you need! Right in the thread process where you see the InputStream, you can read objects and act upon them, or with the OutputStream you can send objects. It's all up to you now, just be sure to use Threads or your program will sit there and wait, which isn't what you want!

OK, OK, you're losing your attention because you really want to make an MMORPG right?
IPB Image
You can't hide it from me! I'll make a Tutorial for that later when I have time so stick around. I'll get a little deeper in making a networked game with a server (which doesn't really need a and a client (which uses a video panel and everything).

While you wait, I suggest you practice just making the server echo Strings from the client and to periodically send Strings back to the client. If you can do this for multiple clients without errors or having the client or server freeze up and wait, then you're all set for my next tutorial smile.gif

Some images from Lucky Star (Kyoto Animation)
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

m78
*



post 10 Feb, 2008 - 12:08 PM
Post #2

Is this how I get multi-ple client on a netowrk to use the same application?
For example, I have to write a text-adventure game and such game is supposed to be played on the Internet by multiple users simultaneosly.

How do I go about that?
Go to the top of the page
+Quote Post

ever388
*



post 2 May, 2008 - 01:49 PM
Post #3
i think u and me could make the best game ever you no how to do it all and i hav played every adventure game there is


P.S please reply to me at pooman132132@hotmail.com

This post has been edited by ever388: 2 May, 2008 - 02:27 PM
Go to the top of the page
+Quote Post

Rickster0
Group Icon



post 10 Jul, 2008 - 02:32 AM
Post #4
This tutorial is BLOODY AWSOME. YAY WolfCoder

biggrin.gif
Go to the top of the page
+Quote Post


Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 

Lo-Fi Version Time is now: 12/1/08 11:29PM

Live Java Help!

Java Tutorials

Reference Sheets

Java Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month