Openfire连接的加载
Openfire重要的一项就是连接的加载,包括好多种连接。
// Load this module always last since we don't want to start listening for clients
// before the rest of the modules have been started
loadModule(ConnectionManagerImpl.class.getName());
1.载入
在所有的准备好之后在加载连接。 loadModule:
/**
* Loads a module.
*
* @param module the name of the class that implements the Module interface.
*/
private void loadModule(String module) {
try {
Class<Module> modClass = (Class<Module>) loader.loadClass(module);
Module mod = modClass.newInstance();
this.modules.put(modClass, mod);
}
catch (Exception e) {
e.printStackTrace();
logger.error(LocaleUtils.getLocalizedString("admin.error"), e);
}
}
使用class.loadClass 然后newInstance创建实例对象
2.初始化
initModule: 每一个module都有继承BasicModule 然后有
然后在加载
3.启动
startModule:
@Override
public void start() {
super.start();
startListeners();
SocketSendingTracker.getInstance().start();
CertificateManager.addListener(this);
}
然后startListeners(); 方法其中有判断插件是否全部被加载了,如果不被没有被加载完全那么,就会递归的调用startListeners() 方法来启动监听。
for ( final ConnectionListener listener : getListeners() )
{
try
{
listener.start();
}
catch ( RuntimeException ex )
{
Log.error( "An exception occurred while starting listener " + listener, ex );
}
}
挨个开启连接监听
if ( getType() == ConnectionType.SOCKET_S2S )
{
System.out.println("看看还用不用喽");
connectionAcceptor = new LegacyConnectionAcceptor( generateConnectionConfiguration() );
}
else
{
connectionAcceptor = new MINAConnectionAcceptor( generateConnectionConfiguration() );
}
connectionAcceptor.start();
Log.info( "Started." );
上面的只有服务端对服务端的监听还在用。我们主要看看下面的MINAConnectionAcceptor的东西。
然后connectionAcceptor.start();
我们从资料就可以知道,Openfire是一个底层基于MINA的。在这里我们终于见到了MINA的真容啊真不容易。。
/**
* Starts this acceptor by binding the socket acceptor. When the acceptor is already started, a warning will be
* logged and the method invocation is otherwise ignored.
*/
@Override
public synchronized void start()
{
if ( socketAcceptor != null )
{
Log.warn( "Unable to start acceptor (it is already started!)" );
return;
}
try
{
// Configure the thread pool that is to be used.
final int initialSize = ( configuration.getMaxThreadPoolSize() / 4 ) + 1;
final ExecutorFilter executorFilter = new ExecutorFilter( initialSize, configuration.getMaxThreadPoolSize(), 60, TimeUnit.SECONDS );
final ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor) executorFilter.getExecutor();
final ThreadFactory threadFactory = new NamedThreadFactory( name + "-thread-", eventExecutor.getThreadFactory(), true, null );
eventExecutor.setThreadFactory( threadFactory );
// Construct a new socket acceptor, and configure it.
socketAcceptor = buildSocketAcceptor();
if ( JMXManager.isEnabled() )
{
configureJMX( socketAcceptor, name );
}
final DefaultIoFilterChainBuilder filterChain = socketAcceptor.getFilterChain();
filterChain.addFirst( ConnectionManagerImpl.EXECUTOR_FILTER_NAME, executorFilter );
// Add the XMPP codec filter
filterChain.addAfter( ConnectionManagerImpl.EXECUTOR_FILTER_NAME, ConnectionManagerImpl.XMPP_CODEC_FILTER_NAME, new ProtocolCodecFilter( new XMPPCodecFactory() ) );
// Kill sessions whose outgoing queues keep growing and fail to send traffic
filterChain.addAfter( ConnectionManagerImpl.XMPP_CODEC_FILTER_NAME, ConnectionManagerImpl.CAPACITY_FILTER_NAME, new StalledSessionsFilter() );
// Ports can be configured to start connections in SSL (as opposed to upgrade a non-encrypted socket to an encrypted one, typically using StartTLS)
if ( configuration.getTlsPolicy() == Connection.TLSPolicy.legacyMode )
{
final SslFilter sslFilter = encryptionArtifactFactory.createServerModeSslFilter();
filterChain.addAfter( ConnectionManagerImpl.EXECUTOR_FILTER_NAME, ConnectionManagerImpl.TLS_FILTER_NAME, sslFilter );
}
// Throttle sessions who send data too fast
if ( configuration.getMaxBufferSize() > 0 )
{
socketAcceptor.getSessionConfig().setMaxReadBufferSize( configuration.getMaxBufferSize() );
Log.debug( "Throttling read buffer for connections to max={} bytes", configuration.getMaxBufferSize() );
}
// Start accepting connections
socketAcceptor.setHandler( connectionHandler );
socketAcceptor.bind( new InetSocketAddress( configuration.getBindAddress(), configuration.getPort() ) );
}
catch ( Exception e )
{
System.err.println( "Error starting " + configuration.getPort() + ": " + e.getMessage() );
Log.error( "Error starting: " + configuration.getPort(), e );
// Reset for future use.
if (socketAcceptor != null) {
try {
socketAcceptor.unbind();
} finally {
socketAcceptor = null;
}
}
}
}
如果看过MINA的API的话就会很容易理解上面这个过程
就是建立一个NioSocketAcceptor对象,然后进行一些操作,之后可以参考MINA的小DEMO
socketAcceptor.setHandler( connectionHandler );
MINA的框架交给这个业务类来处理消息
ConnectionHandler这个类就是我们来处理所有来自客户端的消息IO处理。
/**
* An adapter class for {@link IoHandler}. You can extend this
* class and selectively override required event handler methods only. All
* methods do nothing by default.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class IoHandlerAdapter implements IoHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(IoHandlerAdapter.class);
public void sessionCreated(IoSession session) throws Exception {
// Empty handler
}
public void sessionOpened(IoSession session) throws Exception {
// Empty handler
}
public void sessionClosed(IoSession session) throws Exception {
// Empty handler
}
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
// Empty handler
}
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("EXCEPTION, please implement " + getClass().getName()
+ ".exceptionCaught() for proper handling:", cause);
}
}
public void messageReceived(IoSession session, Object message) throws Exception {
// Empty handler
}
public void messageSent(IoSession session, Object message) throws Exception {
// Empty handler
}
}