View Javadoc

1   /**********************************************************************
2    * ConnectionAcceptor.java
3    * created on 01.03.2005 by netseeker
4    * $Source: /cvsroot/ejoe/EJOE/src/de/netseeker/ejoe/ConnectionAcceptor.java,v $
5    * $Date: 2006/03/22 00:06:58 $
6    * $Revision: 1.24 $
7    *
8    * ====================================================================
9    *
10   *  Copyright 2005-2006 netseeker aka Michael Manske
11   *
12   *  Licensed under the Apache License, Version 2.0 (the "License");
13   *  you may not use this file except in compliance with the License.
14   *  You may obtain a copy of the License at
15   *
16   *      http://www.apache.org/licenses/LICENSE-2.0
17   *
18   *  Unless required by applicable law or agreed to in writing, software
19   *  distributed under the License is distributed on an "AS IS" BASIS,
20   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21   *  See the License for the specific language governing permissions and
22   *  limitations under the License.
23   * ====================================================================
24   *
25   * This file is part of the ejoe framework.
26   * For more information on the author, please see
27   * <http://www.manskes.de/>.
28   *
29   *********************************************************************/
30  package de.netseeker.ejoe;
31  
32  import java.io.IOException;
33  import java.nio.channels.CancelledKeyException;
34  import java.nio.channels.SelectionKey;
35  import java.nio.channels.Selector;
36  import java.nio.channels.ServerSocketChannel;
37  import java.nio.channels.SocketChannel;
38  import java.nio.channels.spi.SelectorProvider;
39  import java.util.Iterator;
40  import java.util.logging.Level;
41  import java.util.logging.Logger;
42  
43  import de.netseeker.ejoe.io.IOUtils;
44  
45  /***
46   * The ConnectionAcceptor class is a server thread handling accepting of incoming client connections and simply hands
47   * over these connections to another thread for further processing. The adavantage of the separation of acception
48   * management and processing management *can* result in a significantly higher throughput if dealing with a lot of
49   * clients.
50   *
51   * @author netseeker
52   * @since 0.3.0
53   */
54  final class ConnectionAcceptor extends Thread
55  {
56  	private static final Logger	logger		= Logger.getLogger(ConnectionAcceptor.class.getName());
57  
58  	private ServerSocketChannel	_channel;
59  
60  	private ChannelRegistrar	_registrar;
61  
62  	private Selector			_selector	= null;
63  
64  	public ConnectionAcceptor(final ServerSocketChannel channel, final ChannelRegistrar registrar) throws IOException
65  	{
66  		this._channel = channel;
67  		this._registrar = registrar;
68  		this._selector = SelectorProvider.provider().openSelector();
69  	}
70  
71  	/*
72  	 * (non-Javadoc)
73  	 *
74  	 * @see java.lang.Thread#run()
75  	 */
76  	public void run()
77  	{
78  		try
79  		{
80  			this._channel.register(_selector, SelectionKey.OP_ACCEPT);
81  
82  			while (!isInterrupted())
83  			{
84  				if (_selector.select() == 0)
85  				{
86  					continue;
87  				}
88  
89  				Iterator it = _selector.selectedKeys().iterator();
90  				SelectionKey selKey = null;
91  				SocketChannel cChannel = null;
92  				ConnectionHeader header = null;
93  
94  				while (it.hasNext())
95  				{
96  					selKey = (SelectionKey) it.next();
97  					it.remove();
98  
99  					try
100 					{
101 						// validate the key
102 						if (!selKey.isValid())
103 						{
104 							continue;
105 						}
106 
107 						if (selKey.isAcceptable())
108 						{
109 							cChannel = this._channel.accept();
110 
111 							if (cChannel != null)
112 							{
113 								cChannel.socket().setTrafficClass(EJConstants.IPTOS_THROUGHPUT);
114 								cChannel.socket().setReuseAddress(true);
115 								cChannel.configureBlocking(false);
116 								// register the channel on another thread which
117 								// will do further connection handling
118 								header = new ConnectionHeader(cChannel );
119 								this._registrar.register(header, SelectionKey.OP_READ);
120 								if (logger.isLoggable(Level.FINE))
121 								{
122 									logger.log(Level.FINE, "Connection accepted from "
123 											+ cChannel.socket().getRemoteSocketAddress());
124 								}
125 							}
126 						}
127 					}
128 					catch (CancelledKeyException cke)
129 					{
130 						logger.log(Level.WARNING, "Key canceled!", cke);
131 					}
132 				}
133 			}
134 		}
135 		catch (IOException e)
136 		{
137 			logger.log(Level.SEVERE, "!!! IOException occured !!! ", e);
138 			throw new RuntimeException(e);
139 		}
140 		finally
141 		{
142 			try
143 			{
144 				IOUtils.closeQuite(_selector);
145 			}
146 			catch (Exception e)
147 			{
148 				logger.log(Level.SEVERE, "!!! Error while stopping server !!!", e);
149 			}
150 		}
151 	}
152 }