Skip to content

Instantly share code, notes, and snippets.

@Jire
Created August 4, 2011 16:36
Show Gist options
  • Save Jire/1125588 to your computer and use it in GitHub Desktop.
Save Jire/1125588 to your computer and use it in GitHub Desktop.
package com.fijeo;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.logging.Logger;
/**
* This class represents the application that will form the base
* of other source files which will be able to run within fijeo.
*
* <p>A single server instance is introduced on start-time. Each
* instance contains objects necessary to operate the fijeo
* network components along with fields containing required
* data to initialize those components.</p>
*
* @author Thomas Nappo
*/
public class Server implements Runnable, AutoCloseable {
/**
* This logger is utilized by the class to display information
* to developers about the actions being performed by the server
* and, should any problems occur, will display reported problems.
*/
private static final Logger logger = Logger.getLogger(Server.class.getName());
/**
* The entry point of the application. Fijeo is expected to
* implement the standard Java run-time procedure.
*
* <p>Within the block a new <tt>Server</tt> instance will
* be introduced, configured, and launched. From so, other
* components of the application will also be initialized
* as a result of the instance.</p>
*
* @param args The program arguments. Passed through these
* arguments are run-time parameters used to initialize the
* application. Fijeo will use default arguments should the
* company of those be not.
*/
public static void main(String... args) {
/*
* We begin initialization by forming a new server
* instance. Note that this instance should be unique
* to the application yet this class's constraints
* do not enforce the singletoness of the instance.
*/
Server server;
try {
/*
* In order to form the instance we use a switch set
* on the length of the program arguments.
*/
switch (args.length) {
case 0:
/*
* Should no arguments be present we use the no-param
* constructor. This constructor creates a new server
* using the local machine's address as the hostname
* and 43594 as its port.
*/
server = new Server();
break;
case 1:
/*
* Should one argument be present, it is assumed that
* the user only wishes to specify the network port.
*
* We use the single-param constructor which uses the
* local machine's address as the hostname.
*/
server = new Server(Integer.parseInt(args[0]));
break;
default:
/*
* Enforce that in the default case the argument
* length is greater than one.
*/
assert args.length > 1 : "Program argument length of " + args.length
+ "does not meet the requirements for the default case.";
/*
* For any other number of arguments we pass the
* hostname as the first argument and the port as
* the second argument.
*/
server = new Server(args[0], Integer.parseInt(args[1]));
break;
}
/*
* The instance is started.
*/
server.start();
} catch (IOException e) {
/*
* Deliver developers with the stack trace, should
* an I/O exception occur.
*/
e.printStackTrace();
}
}
/**
* The name used to identify a particular instance of machine,
* and used to distinguish it from all other hosts connected
* to the network device.
*/
private final String hostname;
/**
* Serves as a communications endpoint for each Fijeo server.
*/
private final int port;
/**
* Maintains the selection keys of the server.
*/
private Selector selector;
/**
* The channel in which the server rests over. This channel
* is responsible for encapsulating data.
*/
private ServerSocketChannel channel;
/**
* Whether or not the server is running.
*/
private boolean running;
/**
* Constructs a new server.
* @param hostname The name used to identify a particular
* instance of machine, and used to distinguish it from all
* other hosts connected to the network device.
* @param port The communications endpoint identifier which
* is placed as a singleton entry into a registry of ports
* which are bound to a device.
*/
private Server(String hostname, int port) {
this.hostname = hostname;
this.port = port;
}
/**
* Constructs a new server using the local machine's address
* as the hostname.
* @param port The communications endpoint identifier which
* is placed as a singleton entry into a registry of ports
* which are bound to a device.
*/
private Server(int port) {
this("localhost", port);
}
/**
* Constructs a new server using the local machine's address
* as the hostname and <tt>43594</tt> as its port.
*/
private Server() {
this(43594);
}
/**
* Performs processing command to receive incoming connections.
* @throws InterruptedException Should any exception occur, specifically
* related to synchronization and thread-interuppted actions.
*/
@Override
public void run() {
try {
while (running) {
logger.info("Connection parser online.");
Thread.sleep(600);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Initializes the server by first initializing other required
* components. Note that this method should only be called once
* regardless that it is only enforced by an assertion.
* @throws IOException Should any operations related to I/O fail.
*/
private void start() throws IOException {
/*
* Enforce that the server is not running.
*/
assert !running : "Start may be only called once.";
/*
* Set the internal selector reference to the system-wide
* selector.
*/
selector = SelectorProvider.provider().openSelector();
/*
* Instantate the channel.
*/
channel = ServerSocketChannel.open();
/*
* And configure the channel to be non-blocking.
*/
channel.configureBlocking(false);
/*
* Instantize a new internet socket address.
*/
InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName(hostname), port);
/*
* And bind the channel's socket towards it.
*/
channel.socket().bind(isa);
/*
* Finally register the server socket channel, indicating
* an interest in accepting new connections.
*/
channel.register(selector, SelectionKey.OP_ACCEPT);
/*
* Now the server is ready.
*/
running = true;
/*
* Since the process has been completed, notify developers
* that the server is ready for incoming connections.
*/
logger.info("Fijeo server ready.");
}
@Override
public void close() throws Exception {
channel.close();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment