Package de.netseeker.ejoe.core

Source Code of de.netseeker.ejoe.core.ConnectionAcceptor

/*********************************************************************
* ConnectionAcceptor.java
* created on 01.03.2005 by netseeker
* $Source: /cvsroot/ejoe/EJOE/src/de/netseeker/ejoe/core/ConnectionAcceptor.java,v $
* $Date: 2007/03/29 15:46:50 $
* $Revision: 1.4 $
*
* ====================================================================
*
*  Copyright 2005-2006 netseeker aka Michael Manske
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
* ====================================================================
*
* This file is part of the ejoe framework.
* For more information on the author, please see
* <http://www.manskes.de/>.
*
*********************************************************************/
package de.netseeker.ejoe.core;

import java.io.IOException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import de.netseeker.ejoe.ConnectionHeader;
import de.netseeker.ejoe.EJConstants;
import de.netseeker.ejoe.io.IOUtil;

/**
* The ConnectionAcceptor class is a server thread handling accepting of incoming client connections and simply hands
* over these connections to another thread for further processing. The adavantage of the separation of acception
* management and processing management *can* result in a significantly higher throughput if dealing with a lot of
* clients.
*
* @author netseeker
* @since 0.3.0
*/
public final class ConnectionAcceptor extends Thread
{
    private static final Logger logger = Logger.getLogger( ConnectionAcceptor.class.getName() );

    private ServerSocketChannel _channel;

    private ChannelRegistrar[]  _registrars;

    private Selector            _selector;

    public ConnectionAcceptor(final ServerSocketChannel channel, final ChannelRegistrar registrars[])
            throws IOException
    {
        super( "EJOE ConnectionAcceptor" );
        this._channel = channel;
        this._registrars = registrars;
        this._selector = Selector.open();
        // clean out previously cancelled keys - system might reuse selectors
        this._selector.selectNow();
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Thread#run()
     */
    public void run()
    {
        try
        {
            // register our server socket on the selector
            this._channel.register( _selector, SelectionKey.OP_ACCEPT );

            while ( !isInterrupted() )
            {
                // just do endless select operations until one or more intersted
                // socket channels will be found
                if ( _selector.select() == 0 )
                {
                    continue;
                }

                Iterator it = _selector.selectedKeys().iterator();
                SelectionKey selKey = null;
                SocketChannel cChannel = null;
                ConnectionHeader header = null;

                while ( it.hasNext() && !isInterrupted() )
                {
                    selKey = (SelectionKey) it.next();
                    it.remove();

                    try
                    {
                        // validate the key
                        if ( !selKey.isValid() )
                        {
                            continue;
                        }

                        // socket is ready for establishing a connection?
                        if ( selKey.isAcceptable() )
                        {
                            // establish the connection
                            cChannel = this._channel.accept();

                            // a little bit paranoia
                            if ( cChannel != null )
                            {
                                // little bit tuning
                                cChannel.socket().setTrafficClass( EJConstants.IPTOS_THROUGHPUT );
                                cChannel.socket().setReuseAddress( true );
                                cChannel.socket().setSoLinger( false, 0 );
                               
                                // ensure that the socket channel is prepared
                                // for non-blocking operations
                                cChannel.configureBlocking( false );
                                // create a new ConnectionHeader for all
                                // upcoming operations on the
                                // accepted socket connection
                                header = new ConnectionHeader( cChannel, cChannel.socket().getRemoteSocketAddress()
                                        .toString(), true );
                                // register the channel on another thread which
                                // will do further connection handling
                                getProcessor().register( header, SelectionKey.OP_READ );

                                if ( logger.isLoggable( Level.FINE ) )
                                {
                                    logger.log( Level.FINE, "Connection accepted from "
                                            + cChannel.socket().getRemoteSocketAddress() );
                                }
                            }
                        }
                    }
                    catch ( CancelledKeyException cke )
                    {
                        logger.log( Level.WARNING, "Key canceled!", cke );
                    }
                }
            }
        }
        catch ( IOException e )
        {
            logger.log( Level.SEVERE, "!!! IOException occured !!! ", e );
        }
        finally
        {
            try
            {
                IOUtil.closeQuiet( _selector );
            }
            catch ( Exception e )
            {
                logger.log( Level.SEVERE, "!!! Error while stopping server !!!", e );
            }
        }
    }

    /**
     * @return
     */
    private ChannelRegistrar getProcessor()
    {
        ChannelRegistrar rProcessor = null;
       
        if ( this._registrars.length == 1 )
        {
            rProcessor = this._registrars[0];
        }
        else
        {
            int load = -1, pLoad = 0;
            ChannelRegistrar tProcessor;

            for ( int i = 0; i < this._registrars.length; i++ )
            {
                tProcessor = this._registrars[i];
                pLoad = tProcessor.getLoad();
                if ( pLoad < load || load == -1 )
                {
                    rProcessor = tProcessor;
                }
            }
        }

        return rProcessor;
    }
}
TOP

Related Classes of de.netseeker.ejoe.core.ConnectionAcceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.