Link to home
Start Free TrialLog in
Avatar of perdoname_
perdoname_

asked on

Convert single client to multiclient

Hello Experts,

I need your assistance how can i convert the server below as to be able to handle multiple clients

If anyone can be some sort of help it 'd be grateful !

Thanks in advance!
class LODServer
{
 
    ServerBase<ClientHandler> server = null;
 
    
    ArrayList<ClientHandler> clients = null;
 
    static final int TREASURE     = 1;
    /* Larger positive numbers are several lots of treasure */
    static final int EMPTY        = 0;
    static final int HEALTH       = -1;
    static final int LANTERN      = -2;
    static final int SWORD        = -3;
    static final int ARMOUR       = -4;
    static final int EXIT         = -5;
    static final int WALL         = -6;
 
    int mapWidth = 5;
    int mapHeight = 5;
    int map[/*mapHeight*/][/*mapWidth*/] =
    {
        {WALL,    WALL,     ARMOUR,  WALL,     WALL    },
        {WALL,    EXIT,     EMPTY,   TREASURE, TREASURE},
        {LANTERN, TREASURE, EMPTY,   HEALTH,   LANTERN },
        {WALL,    SWORD,    EMPTY,   ARMOUR,   TREASURE},
        {WALL,    WALL,     SWORD,   WALL,     WALL    }
    };
 
    boolean gameStarted = false;
    boolean gameFinished = false;
    int goal = 2;           // The amount of treasure to collect
 
 
    Semaphore playerTurn = new Semaphore(1);
        
 
    public void setup (int port, int players, String map) {
        // Limit to one player
        if (players > 1) {
            System.err.println("The current implementation is limited to one player.");
            players = 1;
        }
 
        // Create the object to handle the incoming connections???
        
        server = new ServerBase<ClientHandler>(ClientHandler.class, players, port, true);
 
 
        //xml-parsing
        LODServer extends XML_Handler
        {
                public void readFile(java.io.File f) {
                        try {
                        XMLReader xr = XMLReaderFactory.createXMLReader();
                        XML_Handler handler = new XML_Handler();
                        xr.setContentHandler(handler);
                        xr.setErrorHandler(handler);
                        xr.setDTDHandler(handler);
 
                        FileReader r = new FileReader(f);
                        xr.parse(new InputSource(r));
                        } catch (Exception e) {
                        System.err.println("XML_Handler.readFile " + e);
                        e.printStackTrace();
                        }
                }
        }
        
        //System.err.println("Map loading is not implemented, \"" + map + "\" ignored.");
 
 
 
        // Start accepting incoming connections.
        System.out.print("Waiting for players to connect ... ");
        server.start();
    }
 
    public void play () throws InterruptedException {
 
        // Wait for all of the clients to connect
        clients = server.getConnections();
        System.out.println(" done.");
 
        // Any set up for the game that is specific
        // to the clients goes here.
 
 
        // Give each ClientHandler a reference to this object
        // and thus access to the game data
        for (ClientHandler c : clients) {
            c.server = this;
        }
 
        // Fix the player's starting location
        clients.get(0).x = 2;
        clients.get(0).y = 2;
 
        // Let each client know the amount of treasure it needs
        for (ClientHandler c : clients) {
            c.serverGoal(goal);
        }
 
        // Play the game!
        System.out.println("Starting the game.");
        gameStarted = true;
        while (gameFinished == false) {
 
            // Check that there is at least one player connected
            if (clients.size() <= 0) {
                System.out.println("Game abandoned");
                break;
            }
 
            // Each player takes a turn
            //for (ClientHandler c : clients) {
            ClientHandler c = clients.get(0);
 
            // Start turn
            System.out.println("Starting the turn of player \"" + c.name + "\"");
            c.startTurn();     // During this, c will acquire() the playerTurn semaphore
 
            // Wait for the player to finish their turn
            // (they will release() the semaphore at the end of their turn)
            try {
                playerTurn.acquire();
            } catch (InterruptedException e) {
                // This shouldn't happen in normal operation
                // If it happens, it is because this code
                // has been used in a larger bit of software
                // thus the wrapper can deal with this condition
                throw(e);
            }
            System.out.println("End of turn");
 
          
            if (gameFinished == true) {
 
                System.out.println("Game over, \"" + c.name + "\" is the winner");
 
                // Tell the player they have won
                c.serverMessage("Congratulations " + c.name + " you won!");
                c.serverWin();
 
                // Tell everyone else that they haven't
                for (ClientHandler d : clients) {
 
                    if (d != c) {
                        d.serverMessage("Sorry " + d.name + " it looks like " + c.name + " beat you.");
                        d.serverLose();
                    }
 
                }
 
            }
 
            // Release the semaphore so that the next player can start their turn
            playerTurn.release();
            //}
 
 
        }
            
        return;
 
    }
 
    public static void printUsageAndDie(String error) {
        System.err.println(error);
        System.err.println("Usage:");
        System.err.println("\tjava LODServer <port> <players> <map>");
        System.exit(1);
    }
 
    
    public static void main(String args[])
    {
 
        if (args.length != 3) {
            printUsageAndDie("Incorrect number of command line arguements");
        } else {
            int port = Integer.parseInt(args[0]);
 
            if ((port <= 1024) || (port >= 65536)) {
                printUsageAndDie("Invalid port number");
            }
 
            int players = Integer.parseInt(args[1]);
            if (players < 0) {
                printUsageAndDie("Invalid number of users");
            }
 
            LODServer s = new LODServer();
 
            s.setup(port,players,args[2]);
        
            try {
                s.play();
            } catch (InterruptedException e) {
                System.err.println("Caught InterruptedException(?)");
                System.exit(1);
            }
        }
    }
}
 
 
class ClientHandler extends ConnectionBase
{
 
    String name = "Dave" + this.hashCode();
 
    LODServer server;
 
    int x = 0;
    int y = 0;
 
    int lantern = 0;
    int sword = 0;
    int armour = 0;
 
    int treasure = 0;
    int hp = 3;
    boolean dead = false;
 
    boolean isMyTurn = false;
    int ap = 0;
 
 
    synchronized void startTurn () throws InterruptedException {
 
	try {
	    server.playerTurn.acquire();
	} catch (InterruptedException e) {
	    throw(e);
	}
 
	ap = 6 - (lantern + sword + armour);
 
	isMyTurn = true;
 
	serverStartTurn();
 
	return;
    }
 
    void clientHello(String newName) {
	name = newName;
	return;
	
    }
	
    void clientLook() {
	if ((server.gameStarted == false) || (dead == true)) {
	    return;
	} else {
 
	    serverLookReplyBegin();
 
	    int distance = 2 + lantern;
 
	    for (int i = -distance; i <= distance; ++i) {
 
		String line = "";
 
		for (int j = -distance; j <= distance; ++j) {
 
		    char content = '?';
 
		    int targetX = x + j;
		    int targetY = y + i;
 
		    if (Math.abs(i) + Math.abs(j) > distance + 1) {
			content = 'X';
 
		    } else if ((targetX < 0) || (targetX >= server.mapWidth) ||
			       (targetY < 0) || (targetY >= server.mapHeight)) {
			content = '#';
		    } else {
 
			switch (server.map[targetY][targetX]) {
			case LODServer.EMPTY : content = '.'; break;
			case LODServer.HEALTH : content = 'H'; break;
			case LODServer.LANTERN : content = 'L'; break;
			case LODServer.SWORD : content = 'S'; break;
			case LODServer.ARMOUR : content = 'A'; break;
			case LODServer.EXIT : content = 'E'; break;
			case LODServer.WALL : content = '#'; break;
			default : 
			    if (server.map[targetY][targetX] > 0) {
				content = 'G';
			    } else {
				System.err.println("Invalid map location : [" + targetY + "][" + targetX + "] = " + server.map[targetY][targetX]);
				System.exit(1);
			    }
			}
 
			for (ClientHandler c : server.clients) {
 
			    if (c != this) {
				if ((c.x == targetX) && (c.y == targetY)) {
				    content = 'P';
				}
			    }
			}
					
		    }
 
 
		    line += content;
		}
			
		serverLookReply(line);
	    }
	}
    }
 
    void clientShout(String message) {
	
	if (server.gameStarted == false) {
	    return;
	} else {
 
	    for (ClientHandler c : server.clients) {
		if (c != this) {
		    c.serverMessage(name + " : " + message);
		}
	    }
 
	    return;
	}
    }
	
    void clientPickup() {
	String failMessage = "";
 
		if ((isMyTurn) && (ap > 0)) {
 
	   	    switch (server.map[y][x]) {
	   	 case LODServer.EXIT : 
	    	case LODServer.EMPTY : 
		failMessage = "Nothing to pick up";
		break;
 
	    case LODServer.HEALTH :
		ap = 0;
 
		server.map[y][x] = LODServer.EMPTY;
 
		serverSucceed();
 
		++hp;
 
		serverHitMod(1);
 
		sendChangeNotifications();
 
		return;
		//break;      // Commented out as never reached
 
	    case LODServer.LANTERN :
		if (lantern == 0) {
		    --ap;
 
		    server.map[y][x] = LODServer.EMPTY;
 
		    serverSucceed();
 
		    lantern = 1;
 
		    sendChangeNotifications();
 
		    return;
		} else {
		    failMessage = "Already have a lantern";
		}
		break;
 
	    case LODServer.SWORD :
 
		if (sword == 0) {
		    --ap;
		    server.map[y][x] = LODServer.EMPTY;
		    serverSucceed();
		    sword = 1;
		    sendChangeNotifications();
		    return;
		} else {
		    failMessage = "Already have a sword";
		}
		break;
 
 
	    case LODServer.ARMOUR :
		if (armour == 0) {
		    --ap;
		    server.map[y][x] = LODServer.EMPTY;
		    serverSucceed();
		    armour = 1;
		    sendChangeNotifications();
		    return;
		} else {
		    failMessage = "Already have a armour";
		}
		break;
	
	    default :
		if (server.map[y][x] > 0) {
 
		    --ap;
 
		    int treasurePickedUp = server.map[y][x];
		    server.map[y][x] = LODServer.EMPTY;
 
		    serverSucceed();
 
		    treasure += treasurePickedUp; 
 
		    serverTreasureMod(treasurePickedUp);
 
		    sendChangeNotifications();
 
		    return;
		} else {
		    System.err.println("Pickup at strange map location : [" + y + "][" + x + "] = " + server.map[y][x]);
		    System.exit(1);
		}
	    }
	} else {
	    if (!isMyTurn) {
		failMessage = "Faulty client : PICKUP outside of turn";
	    } else {
		failMessage = "No action points left";
	    }
	}
 
 
	serverFail(failMessage);
	return;
 
    }
 
    void clientMove(char direction) {
	String failMessage;
 
	if ((isMyTurn) && (ap > 0)) {
 
	    int targetX = x;
	    int targetY = y;
 
	    switch (direction) {
	    case 'N' : --targetY; break;
	    case 'S' : ++targetY; break;
	    case 'E' : ++targetX; break;
	    case 'W' : --targetX; break;
	    default :  // Shouldn't happen
		System.err.println("Internal error in connection base.");
		System.err.println("'" + direction + "' is not a direction.");
		System.exit(1);
	    }
 
	    if ((targetX >= 0) && (targetX < server.mapWidth) &&
		(targetY >= 0) && (targetY < server.mapHeight)) {
 
		if (server.map[targetY][targetX] != LODServer.WALL) {
 
		    boolean targetEmpty = true;
 
		    for (ClientHandler c : server.clients) {
			if ((c != this) && (c.x == targetX) && (c.y == targetY)) {
			    targetEmpty = false;
			}
		    }
 
		    if (targetEmpty) {
			--ap;
 
			x = targetX;
			y = targetY;
 
			serverSucceed();
 
			sendChangeNotifications();
 
			return;
		    } else {
			failMessage = "Can not move into another player";
		    }
 
		} else {
		    failMessage = "Can not move into a wall";
		}
	    } else {
		// Needs to be the same as above or
		// otherwise lets people know where
		// the edges of the labyrinth are.
		failMessage = "Can not move into a wall";			
	    }
	} else {
	    if (!isMyTurn) {
		// Only happens with faulty clients
		failMessage = "Faulty client : MOVE outside of turn";
	    } else {
		failMessage = "No action points left";
	    }
	}
 
 
	// Fail unless there is an explict reason why we succeed
	serverFail(failMessage);
	return;
    }
 
    // Handles the client message ATTACK
    void clientAttack(char direction) {
	String failMessage;
 
	// Can only attack if it is this player's turn
	// and they have action points left
	if ((isMyTurn) && (ap > 0)) {
 
	    // Work out which square we're targeting
	    int targetX = x;
	    int targetY = y;
 
	    switch (direction) {
	    case 'N' : --targetY; break;
	    case 'S' : ++targetY; break;
	    case 'E' : ++targetX; break;
	    case 'W' : --targetX; break;
	    default :  // Shouldn't happen
		System.err.println("Internal error in connection base.");
		System.err.println("'" + direction + "' is not a direction.");
		System.exit(1);
	    }
 
 
	    // Work out which player that is
	    ClientHandler target = null;
 
	    for (ClientHandler c : server.clients) {
		if ((c.x == targetX) && (c.y == targetY)) {
		    target = c;
		    break;
		}
	    }
 
	    // If there is another player in the target square
	    if (target != null) {
 
		// There is a 75% chance of hitting
		if (Math.random() < 0.75) {
 
		    // Reduce the target's hitpoints
		    int damage = 1 + sword - target.armour;
		    target.hp -= damage;
 
		    // Notify them of the change
		    target.serverMessage("You where hit by " + name +
					 " for " + damage + " points of damage");
		    target.serverHitMod(-damage);
 
		    // Notify the attacker of a successful attack
		    serverSucceed();
 
		    // If the target has been killed
		    if (target.hp <= 0) {
	                target.serverMessage(name + " has killed you");
			target.die();
		    }
		
		    return;
 
		} else {
		    // This message is not required by the spec
		    // but adds to the playability of the game
		    target.serverMessage("You dodged " + name + "'s attack");
 
		    failMessage = "They dodged your attack";
		}
	    } else {
		failMessage = "No one there to attack";
	    }
 
	} else {
	    if (!isMyTurn) {
		// Only happens with faulty clients
		failMessage = "Faulty client : ATTACK outside of turn";
	    } else {
		failMessage = "No action points left";
	    }
 
	}
 
	// Fail unless there is an explict reason why we succeed
	serverFail(failMessage);
	return;
    }
 
    // Handles the client message ENDTURN
    void clientEndTurn() {
 
	// Check to see if this player has won
	if ((treasure >= server.goal) && (server.map[y][x] == LODServer.EXIT)) {
	    server.gameFinished = true;
	}
 
	// Mark that it is no longer this player's turn
	isMyTurn = false;
 
	// Release the semaphore
	// (thus the LODServer can acquire it, and
	//  make it the next player's go).
	server.playerTurn.release();
 
	return;
    }
	
    // Not a message; what to do if the client disconnects
    void clientDisconnected() {
	die();
 
	// Disconnecting may occur during the player's turn,
	// unlike the other causes of death.
	if (isMyTurn) {
	    // Act as if an ENDTURN message had been sent
	    clientEndTurn();
	}
    }
 
    // Not a message; what to do if a player disconnects or is killed
    void die() {
 
	// Unlike horror film bad guys, ClientHandlers only die once
	if (!dead) {
	    dead = true;
 
	    // Drop any gold carried
	    server.map[y][x] = treasure * LODServer.TREASURE;
	    // BUG!
	    // Dropping gold will (correctly) destroy any item
	    // (i.e. sword, armour, lantern, health)
	    // however, it currently also (incorrectly) destroys
	    // any other gold or the exit if they are on the square
	    // that the gold is dropped on.
	    // The correct solution to this probably involves
	    // separate matrices for locations (walls, exits, etc.)
	    // items/treasure.
 
	    server.clients.remove(this);
 
	    // Note this does not disconnect the client
	    // but they will not get another turn
	    // nor effect the map,
	    // they can only shout and listen to messages
	    // To disconnect them as well:
	    // shutdown();
 
	    // Inform other players of their demise
	    for (ClientHandler c : server.clients) {
		c.serverMessage(name + " is no more!");
	    }
 
	    sendChangeNotifications();
	}
    }
 
    // A helper function which sends CHANGE messages
    // when an actions changes the map
    void sendChangeNotifications () {
	for (ClientHandler c : server.clients) {
	    c.serverChangeNotification();
	}
    }
	
}

Open in new window

Avatar of cmalakar
cmalakar
Flag of India image

When ever a client in connected to a server, the server should start the task in a separate thread..

and continue listening to accepting other connections..

like..

while(true)
{
socket.accept() //after this
//Create a thread and start the task..
}
Avatar of perdoname_
perdoname_

ASKER

The point is that there are things already made but im missing a couple of things which i cant figure out
Can you please be more specific to the code rather than general?
Thanks for the replies !
I dont see any socket.accept() in your code..

Hence general replies.. :)
I have those things ready in other class
I just want to modify that class as to be able to handle multiple clients
Then you should post that code..
Because... to handle multiple clients, change is required @ the place, where connections are accepted..
Okay thats the ServerBase but i don't think that it needs any modification.

import java.net.*;
import java.io.*;
import java.util.ArrayList;
 
 
final class ServerBase<T extends ConnectionBase> extends Thread
{
	
	public static final int DEFAULT_PORT = 4455;
	
	protected ServerSocket ss;
	protected int port;
	protected int players;
	protected boolean logging;
 
	protected Class<T> magic;
	protected volatile ArrayList<T> connections;
	
	/**
	 Creates a server, and opens a socket on the port given.
	 
	 The intended use is as following. First, extend ConnectionBase. In this
	 example this class is called Player. Then:
	 \code
	 ServerBase<Player> server = new ServerBase<Player>(Player.class, n, ServerBase.DEFAULT_PORT);
	 server.start();
	 
	 ArrayList<Player> players = server.getConnections();
	 
	 // do stuff, like playing the game
	 \endcode
	 
	 @param magic Must always be the class of your reimplementation of ConnectionBase
	 @param players The number of players the server requires to join
	 @param port The port the server listens on. Should be #DEFAULT_PORT
	 @param logging Whether the created instances will log the messages tthey send and receive
	 */
	public ServerBase(Class<T> magic, int players, int port, boolean logging)
	{
		this.port = port;
		this.magic = magic;
		this.players = players;
		this.logging = logging;
		
		connections = new ArrayList<T>(players);
		
		try {
			ss = new ServerSocket(port);
			ss.setSoTimeout(0);
		} catch (IOException e) {
			System.err.println("ServerBase: Can't create server socket.");
			System.err.println(e);
			System.exit(1);
		}
	}
	
	public void run()
	{
		while (connections.size() < players) {
			Socket s = null;
			try {
				s = ss.accept();
			} catch (IOException e) {
				System.err.println("ServerBase: Can't accept connection.");
				System.err.println(e);
			}
			
			if (s != null) {
				T foo = null;
				
				// Very general, because we want to quit on any fuck up
				try {
					// Watch carefully...
					foo = magic.newInstance();
					foo.init(s,connections.size(),logging);
				} catch (Exception e) {
					System.err.println(e);
					System.exit(1);
				}
 
				if (logging) {
					System.out.print(connections.size() + " ");
				}
				
				connections.add(foo);
			}
		}
 
		// Close the socket so no more connections can be accepted		
		try {
			ss.close();
		} catch (IOException e) {
			System.err.println(e);
		}
	}
	
	/**
	 Returns a list of all connected players. This function will block until
	 all players (as specified in the constructor) have joined.
	 */
	public ArrayList<T> getConnections()
	{
		// A busy wait for all players to connect
		while (connections.size() < players);
 
		return connections;
	}
	
}

Open in new window

Yes in the above class..

you need the above said modification after the line..

s = ss.accept(); //Which is 62nd line in the above post
So what do i have to change as to be multi-client ?

So what do i have to change as to be multi-client ?

s = ss.accept();

After the above line.. what ever you are going to do with the client..
All that operations should be performed in a separate thread...

For example, the if block that you are trying to execute after accept(), should be in a separate thread.. and
start the thread after accepting the connection.

while (connections.size() < players) {
                  Socket s = null;
                  try {
                        s = ss.accept();
                                new Thread(new ReceiveServerThread()).start();
                            //You other code...   ReceiveServerThread is the thread that does communicate with the client..
Do you mean something like that ?
 
ReceiveServerThread   readServerThread = new ReceiveServerThread();  
  readServerThread.start();  
  DataOutputStream   dataout = new   DataOutputStream(s.getOutputStream());      
  DataInputStream datain= new DataInputStream(s.getInputStream());  
yes you need to create a thread..

But dataout and datain should be passed to thread, while creating the thread..

So that thread takes care of every thing from that point..
Is that code okay ? will the server be multiple-client after that ?

while (connections.size() < players) {
                  Socket s = null;
                  try {
                        s = ss.accept();
                                new Thread(new ReceiveServerThread()).start();
                                 ReceiveServerThread   readServerThread = new ReceiveServerThread();  
                                  readServerThread.start();  
                                  DataOutputStream   dataout = new   DataOutputStream(s.getOutputStream());      
                                  DataInputStream datain= new DataInputStream(s.getInputStream());  
                                  while(runable)  
                                  {  
                                      dataout.writeUTF(toServer);  
                                 }
                     }
             }  
Why creating two ReceiveServerThread's..

>>new Thread(new ReceiveServerThread()).start();
>>ReceiveServerThread   readServerThread = new ReceiveServerThread();  
>> readServerThread.start();  

The code should be like this..

while (connections.size() < players) {
                  Socket s = null;
                  try {
                        s = ss.accept();
                                  DataOutputStream   dataout = new   DataOutputStream(s.getOutputStream());      
                                  DataInputStream datain= new DataInputStream(s.getInputStream());  
                                new Thread(new ReceiveServerThread(dataout, datain)).start();
                     }catch.....
             }  
I tried to add that part but it returns multiple errors

./ServerBase.java:73: '{' expected
                        
^
./ServerBase.java:64: 'try' without 'catch' or 'finally'
                  try {
                        ^
./ServerBase.java:113: illegal start of expression
      public ArrayList<T> getConnections()
        ^
./ServerBase.java:120: ';' expected
      
^
./ServerBase.java:135: '}' expected
^
LODServer.java:220: cannot find symbol
symbol  : method getConnections()
location: class ServerBase<ClientHandler>
            clients = server.getConnections();


import java.io.DataInputStream;
import java.io.DataOutputStream;
 
 
import java.net.*;
import java.io.*;
import java.util.ArrayList;
final class ServerBase<T extends ConnectionBase> extends Thread
{
	
	public static final int DEFAULT_PORT = 4455;
	
	protected ServerSocket ss;
	protected int port;
	protected int players;
	protected boolean logging;
 
	protected Class<T> magic;
	protected volatile ArrayList<T> connections;
	
	/**
	 Creates a server, and opens a socket on the port given.
	 
	 The intended use is as following. First, extend ConnectionBase. In this
	 example this class is called Player. Then:
	 \code
	 ServerBase<Player> server = new ServerBase<Player>(Player.class, n, ServerBase.DEFAULT_PORT);
	 server.start();
	 
	 ArrayList<Player> players = server.getConnections();
	 
	 // do stuff, like playing the game
	 \endcode
	 
	 @param magic Must always be the class of your reimplementation of ConnectionBase
	 @param players The number of players the server requires to join
	 @param port The port the server listens on. Should be #DEFAULT_PORT
	 @param logging Whether the created instances will log the messages tthey send and receive
	 */
	public ServerBase(Class<T> magic, int players, int port, boolean logging)
	{
		this.port = port;
		this.magic = magic;
		this.players = players;
		this.logging = logging;
		
		connections = new ArrayList<T>(players);
		
		try {
			ss = new ServerSocket(port);
			ss.setSoTimeout(0);
		} catch (IOException e) {
			System.err.println("ServerBase: Can't create server socket.");
			System.err.println(e);
			System.exit(1);
		}
	}
	
	public void run()
	{
		while (connections.size() < players) {
			Socket s = null;
			try {
				s = ss.accept();
				while (connections.size() < players) {
	                  try {
	                        s = ss.accept();
	                                  DataOutputStream   dataout = new   DataOutputStream(s.getOutputStream());      
	                                  DataInputStream datain= new DataInputStream(s.getInputStream());  
	                                new Thread(new ReceiveServerThread(dataout, datain)).start();
	                     }catch (IOException e)
				
			} catch (IOException e) {
				System.err.println("ServerBase: Can't accept connection.");
				System.err.println(e);
			}
			
			if (s != null) {
				T foo = null;
				
				// Very general, because we want to quit on any fuck up
				try {
					// Watch carefully...
					foo = magic.newInstance();
					foo.init(s,connections.size(),logging);
				} catch (Exception e) {
					System.err.println(e);
					System.exit(1);
				}
 
				if (logging) {
					System.out.print(connections.size() + " ");
				}
				
				connections.add(foo);
			}
		}
 
		// Close the socket so no more connections can be accepted		
		try {
			ss.close();
		} catch (IOException e) {
			System.err.println(e);
		}
	}
	}
	
	/**
	 Returns a list of all connected players. This function will block until
	 all players (as specified in the constructor) have joined.
	 */
	public ArrayList<T> getConnections()
	{
		// A busy wait for all players to connect
		while (connections.size() < players);
 
		return connections;
	}
	
}
 
 
class ReceiveServerThread implements Runnable {
 
	public ReceiveServerThread(DataOutputStream dataout, DataInputStream datain) {
	}
 
 
	public void run() {
 
	}
 
}

Open in new window

catch() does not have {...} at line 72

>>  }catch (IOException e)
                        
} catch (IOException e) {
Thanks but after adding that it returns error

ServerBase.java:63: 'try' without 'catch' or 'finally'
                  try {
                        ^
ServerBase.java:111: illegal start of expression
      public ArrayList<T> getConnections()

import java.io.DataInputStream;
import java.io.DataOutputStream;
 
 
import java.net.*;
import java.io.*;
import java.util.ArrayList;
final class ServerBase<T extends ConnectionBase> extends Thread
{
	
	public static final int DEFAULT_PORT = 4455;
	
	protected ServerSocket ss;
	protected int port;
	protected int players;
	protected boolean logging;
 
	protected Class<T> magic;
	protected volatile ArrayList<T> connections;
	
	/**
	 Creates a server, and opens a socket on the port given.
	 
	 The intended use is as following. First, extend ConnectionBase. In this
	 example this class is called Player. Then:
	 \code
	 ServerBase<Player> server = new ServerBase<Player>(Player.class, n, ServerBase.DEFAULT_PORT);
	 server.start();
	 
	 ArrayList<Player> players = server.getConnections();
	 
	 // do stuff, like playing the game
	 \endcode
	 
	 @param magic Must always be the class of your reimplementation of ConnectionBase
	 @param players The number of players the server requires to join
	 @param port The port the server listens on. Should be #DEFAULT_PORT
	 @param logging Whether the created instances will log the messages tthey send and receive
	 */
	public ServerBase(Class<T> magic, int players, int port, boolean logging)
	{
		this.port = port;
		this.magic = magic;
		this.players = players;
		this.logging = logging;
		
		connections = new ArrayList<T>(players);
		
		try {
			ss = new ServerSocket(port);
			ss.setSoTimeout(0);
		} catch (IOException e) {
			System.err.println("ServerBase: Can't create server socket.");
			System.err.println(e);
			System.exit(1);
		}
	}
	
	public void run()
	{
		while (connections.size() < players) {
			Socket s = null;
			try {
				s = ss.accept();
				while (connections.size() < players) {
	                  try {
	                        s = ss.accept();
	                                  DataOutputStream   dataout = new   DataOutputStream(s.getOutputStream());      
	                                  DataInputStream datain= new DataInputStream(s.getInputStream());  
	                                new Thread(new ReceiveServerThread(dataout, datain)).start();
	                     }catch (IOException e)
{			} catch (IOException e) {
				System.err.println("ServerBase: Can't accept connection.");
				System.err.println(e);
			}
			
			if (s != null) {
				T foo = null;
				
				// Very general, because we want to quit on any fuck up
				try {
					// Watch carefully...
					foo = magic.newInstance();
					foo.init(s,connections.size(),logging);
				} catch (Exception e) {
					System.err.println(e);
					System.exit(1);
				}
 
				if (logging) {
					System.out.print(connections.size() + " ");
				}
				
				connections.add(foo);
			}
		}
 
		// Close the socket so no more connections can be accepted		
		try {
			ss.close();
		} catch (IOException e) {
			System.err.println(e);
		}
	}
	}
	
	/**
	 Returns a list of all connected players. This function will block until
	 all players (as specified in the constructor) have joined.
	 */
	public ArrayList<T> getConnections()
	{
		// A busy wait for all players to connect
		while (connections.size() < players);
 
		return connections;
	};
}
 
 
class ReceiveServerThread implements Runnable {
 
	public ReceiveServerThread(DataOutputStream dataout, DataInputStream datain) {
	}
 
 
	public void run() {
 
	}
 
}
}

Open in new window

Code between lines 60 and 105 is still not properly organized...

See there is a while at line 65, and try at line 66. But after the corresponding catch(@71 line) of try @ 66,
you are not closing the while looping, trying to close another try catch block, which is giving error.

Are you not using any IDE for development.. ?

Im using Eclipse, but there it says that the code is okay and on the terminal shows errors
Im trying to correct the first error and then returns other errors :S
ServerBase.java:72: '{' expected
                        }
                                ^
ServerBase.java:117: 'class' or 'interface' expected
      public ArrayList<T> getConnections()

final class ServerBase<T extends ConnectionBase> extends Thread
{
	
	public static final int DEFAULT_PORT = 4455;
	
	protected ServerSocket ss;
	protected int port;
	protected int players;
	protected boolean logging;
 
	protected Class<T> magic;
	protected volatile ArrayList<T> connections;
	
	/**
	 Creates a server, and opens a socket on the port given.
	 
	 The intended use is as following. First, extend ConnectionBase. In this
	 example this class is called Player. Then:
	 \code
	 ServerBase<Player> server = new ServerBase<Player>(Player.class, n, ServerBase.DEFAULT_PORT);
	 server.start();
	 
	 ArrayList<Player> players = server.getConnections();
	 
	 // do stuff, like playing the game
	 \endcode
	 
	 @param magic Must always be the class of your reimplementation of ConnectionBase
	 @param players The number of players the server requires to join
	 @param port The port the server listens on. Should be #DEFAULT_PORT
	 @param logging Whether the created instances will log the messages tthey send and receive
	 */
	public ServerBase(Class<T> magic, int players, int port, boolean logging)
	{
		this.port = port;
		this.magic = magic;
		this.players = players;
		this.logging = logging;
		
		connections = new ArrayList<T>(players);
		
		try {
			ss = new ServerSocket(port);
			ss.setSoTimeout(0);
		} catch (IOException e) {
			System.err.println("ServerBase: Can't create server socket.");
			System.err.println(e);
			System.exit(1);
		}
	}
	
	public void run()
	{
		while (connections.size() < players) {
			Socket s = null;
			try {
				s = ss.accept();
				while (connections.size() < players) {
	                  try {
	                        s = ss.accept();
	                                  DataOutputStream   dataout = new   DataOutputStream(s.getOutputStream());      
	                                  DataInputStream datain= new DataInputStream(s.getInputStream());  
	                                new Thread(new ReceiveServerThread(dataout, datain)).start();
	                     }catch (IOException e)
				}
			}
 
		
		} catch (IOException e) {
				System.err.println("ServerBase: Can't accept connection.");
				System.err.println(e);
			}
			
			if (s != null) {
				T foo = null;
				
				// Very general, because we want to quit on any fuck up
				try {
					// Watch carefully...
					foo = magic.newInstance();
					foo.init(s,connections.size(),logging);
				} catch (Exception e) {
					System.err.println(e);
					System.exit(1);
				}
 
				if (logging) {
					System.out.print(connections.size() + " ");
				}
				
				connections.add(foo);
			
		}
	}
 
 
		// Close the socket so no more connections can be accepted		
		try {
			ss.close();
		} catch (IOException e) {
			System.err.println(e);
		}
	}
	}
	
	/**
	 Returns a list of all connected players. This function will block until
	 all players (as specified in the constructor) have joined.
	 */
	public ArrayList<T> getConnections()
	{
		// A busy wait for all players to connect
		while (connections.size() < players);
 
		return connections;
	};
}
 
class ReceiveServerThread implements Runnable {
 
	public ReceiveServerThread(DataOutputStream dataout, DataInputStream datain) {
	}
 
 
	public void run() {
 
	}
 
}

Open in new window

Thanks for you help !
Is there anything else needed in order to be concerned multi-client ? ???
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
 
final class ServerBase<T extends ConnectionBase> extends Thread
{
     
      public static final int DEFAULT_PORT = 4455;
     
      protected ServerSocket ss;
      protected int port;
      protected int players;
      protected boolean logging;
 
      protected Class<T> magic;
      protected volatile ArrayList<T> connections;
     
      /**
       Creates a server, and opens a socket on the port given.
       
       The intended use is as following. First, extend ConnectionBase. In this
       example this class is called Player. Then:
       \code
       ServerBase<Player> server = new ServerBase<Player>(Player.class, n, ServerBase.DEFAULT_PORT);
       server.start();
       
       ArrayList<Player> players = server.getConnections();
       
       // do stuff, like playing the game
       \endcode
       
       @param magic Must always be the class of your reimplementation of ConnectionBase
       @param players The number of players the server requires to join
       @param port The port the server listens on. Should be #DEFAULT_PORT
       @param logging Whether the created instances will log the messages tthey send and receive
       */
      public ServerBase(Class<T> magic, int players, int port, boolean logging)
      {
            this.port = port;
            this.magic = magic;
            this.players = players;
            this.logging = logging;
           
            connections = new ArrayList<T>(players);
           
            try {
                  ss = new ServerSocket(port);
                  ss.setSoTimeout(0);
            } catch (IOException e) {
                  System.err.println("ServerBase: Can't create server socket.");
                  System.err.println(e);
                  System.exit(1);
            }
      }
     
      public void run()
      {
            while (connections.size() < players) {
                  Socket s = null;
                  try {
                        s = ss.accept();
                        while (connections.size() < players) {
                        try {
                              s = ss.accept();
                                        DataOutputStream   dataout = new   DataOutputStream(s.getOutputStream());      
                                        DataInputStream datain= new DataInputStream(s.getInputStream());  
                                      new Thread(new ReceiveServerThread(dataout, datain)).start();
                           }catch (IOException e)  {
                        }
                  }
 
           
            } catch (IOException e) {
                        System.err.println("ServerBase: Can't accept connection.");
                        System.err.println(e);
                  }
                 
                  if (s != null) {
                        T foo = null;
                       
                        // Very general, because we want to quit on any fuck up
                        try {
                              // Watch carefully...
                              foo = magic.newInstance();
                              foo.init(s,connections.size(),logging);
                        } catch (Exception e) {
                              System.err.println(e);
                              System.exit(1);
                        }
 
                        if (logging) {
                              System.out.print(connections.size() + " ");
                        }
                       
                        connections.add(foo);
                 
            }
      }
 
 
            // Close the socket so no more connections can be accepted            
            try {
                  ss.close();
            } catch (IOException e) {
                  System.err.println(e);
            }
      }
 
     
      /**
       Returns a list of all connected players. This function will block until
       all players (as specified in the constructor) have joined.
       */
      public ArrayList<T> getConnections()
      {
            // A busy wait for all players to connect
            while (connections.size() < players);
 
            return connections;
      };
 
class ReceiveServerThread implements Runnable {
 
      public ReceiveServerThread(DataOutputStream dataout, DataInputStream datain) {
      }
 
 
      public void run() {
 
      }
 
}
} 

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of cmalakar
cmalakar
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Is it possible to tell me how can i make  the other class "LODServer" [1st post]  multli-playable ? [ instead of ServerBase ]
How the ReceiveServerThread should be modified ??
>> How the ReceiveServerThread should be modified ??

To Answer in a professional way...

A Server with multiple clients, will work as follows...

while (true)
{
   //Server Starts listening on a socket.
   //When a client connects,
   //Create a new thread, and pass all required parameters to the thread
   //start a new thread which works with client..
}

This way, server will always be running in one thread (bascially main thread), and when ever a client connects a new thread will be created for that..
Which makes the server to always listen on the socket and accept connections from multiple clients..