All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.firefly.net.tcp.aio.AsynchronousTcpServer Maven / Gradle / Ivy

There is a newer version: 5.0.0-dev6
Show newest version
package com.firefly.net.tcp.aio;

import com.firefly.net.*;
import com.firefly.net.event.DefaultEventManager;
import com.firefly.net.exception.NetException;
import com.firefly.utils.lang.AbstractLifeCycle;
import com.firefly.utils.log.LogFactory;
import com.firefly.utils.time.Millisecond100Clock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static com.firefly.net.tcp.TcpPerformanceParameter.BACKLOG;

public class AsynchronousTcpServer extends AbstractLifeCycle implements Server {

	private static Logger log = LoggerFactory.getLogger("firefly-system");
	private Config config;
	private AtomicInteger id = new AtomicInteger();
	private AsynchronousTcpWorker worker;
	private AsynchronousChannelGroup group;

	public AsynchronousTcpServer() {
	}

	public AsynchronousTcpServer(Config config) {
		this.config = config;
	}

	public AsynchronousTcpServer(Decoder decoder, Encoder encoder, Handler handler) {
		config = new Config();
		config.setDecoder(decoder);
		config.setEncoder(encoder);
		config.setHandler(handler);
	}

	public AsynchronousTcpServer(Decoder decoder, Encoder encoder, Handler handler, int timeout) {
		config = new Config();
		config.setDecoder(decoder);
		config.setEncoder(encoder);
		config.setHandler(handler);
		config.setTimeout(timeout);
	}

	@Override
	public void setConfig(Config config) {
		this.config = config;
	}

	@Override
	public void listen(String host, int port) {
		start();
		listen(bind(host, port));
		log.info("start server. host: {}, port: {}", host, port);
	}

	private AsynchronousServerSocketChannel bind(String host, int port) {
		AsynchronousServerSocketChannel serverSocketChannel = null;
		try {
			serverSocketChannel = AsynchronousServerSocketChannel.open(group);
			serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
			serverSocketChannel.bind(new InetSocketAddress(host, port), BACKLOG);
		} catch (Exception e) {
			log.error("ServerSocket bind error", e);
		}
		return serverSocketChannel;
	}

	private void listen(final AsynchronousServerSocketChannel serverSocketChannel) {
		serverSocketChannel.accept(id.getAndIncrement(), new CompletionHandler() {

			@Override
			public void completed(AsynchronousSocketChannel socketChannel, Integer sessionId) {
				try {
					worker.registerChannel(socketChannel, sessionId);
				} finally {
					listen(serverSocketChannel);
				}
			}

			@Override
			public void failed(Throwable t, Integer sessionId) {
				try {
					try {
						config.getHandler().failedAcceptingSession(sessionId, t);
					} catch (Throwable e) {
						log.error("session {} accepting exception", e, sessionId);
					}
					log.error("server accepts channel {} error occurs", t, sessionId);
				} finally {
					listen(serverSocketChannel);
				}
			}
		});
	}

	@Override
	protected void init() {
		if (config == null)
			throw new NetException("server configuration is null");

		try {
			group = AsynchronousChannelGroup.withThreadPool(new ThreadPoolExecutor(config.getAsynchronousCorePoolSize(),
					config.getAsynchronousMaximumPoolSize(), config.getAsynchronousPoolKeepAliveTime(),
					TimeUnit.MILLISECONDS, new LinkedTransferQueue(), new ThreadFactory() {

						@Override
						public Thread newThread(Runnable r) {
							return new Thread(r, "firefly asynchronous server thread");
						}
					}));
			log.info(config.toString());
			EventManager eventManager = new DefaultEventManager(config);
			worker = new AsynchronousTcpWorker(config, eventManager);
		} catch (IOException e) {
			log.error("initialization server channel group error", e);
		}
	}

	@Override
	protected void destroy() {
		if (group != null) {
			group.shutdown();
		}
		LogFactory.getInstance().stop();
		Millisecond100Clock.stop();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy