Skip to content
js-labs edited this page Feb 23, 2014 · 5 revisions

Object model

Any network framework has a few key point requiring user interaction, they are:

  • new session
  • some data is ready to be processed
  • session close

The TCP/IP session in the JS-Collider framework is linked to the Session class instance and has a listener object responsible to handle session events (such as new data available and session close).

Empty Collider

Creating and running the Collider instance looks like:

public class ColliderApplication
{
    public static void main( String[] args )
    {
        try {
            final Collider collider = Collider.create();
            collider.run();
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Collider.run() method will not return until Collider.stop() method call. Let's add some more.

Accepting income connections

In a case if application needs to accept income TCP/IP connections it should use Acceptor derived class which is used a set of configuration properties and as a factory for the session listeners. First of all we will need to implement a Session.Listener interface which will handle session events:

class ServerListener extends Session.Listener
{
    private final Session session;

    public ServerListener( Session session )
    {
        this.session = session;
        System.out.println( session.getRemoteAddress() + ": connection accepted." );
    }

    public void onDataReceived( ByteBuffer data )
    {
        /* Let's just send the received data back.
         * Session.sendData() method is asynchronous, so we have to make a copy.
         * Yes, zero-copy is not a feature of the JS-Collider, but how many
         * applications needs to send copy of the received data to some other?
         */
         final int bytesReceived = data.remaining();
         final ByteBuffer byteBuffer = ByteBuffer.allocateDirect( bytesReceived );
         byteBuffer.put( data );
         byteBuffer.flip();
         session.sendData( byteBuffer );
    }

    public void onConnectionClosed()
    {
        System.out.println( session.getRemoteAddress() + ": connection closed" );
    }
}

That's it. The important thing is that ByteBuffer argument of the onDataReceived() method is valid only during the call. User should not retain it. The position in the ByteBuffer can be greater than 0, but still the data in a [position, limit] range is data to be handled.

Session listener class can not live on it's own. We need some code to instantiate listener object. Acceptor class acts as a set of properties for the related sessions and as a factory for session listeners.

class ServerAcceptor extends Acceptor
{
    public Session.Listener createSessionListener( Session session )
    {
        return new ServerListener( session );
    }
}

Let's start an acceptor:

public class ColliderApplication
{
    private static final int PORT_NUMBER = 12345;

    public static void main( String[] args )
    {
        try {
            final Collider collider = Collider.create();
            collider.addAcceptor( new ServerAcceptor(new InetSocketAddress(PORT_NUMBER)) );
            collider.run();
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
Clone this wiki locally