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

org.aoju.bus.socket.origin.AioQuickServer Maven / Gradle / Ivy

There is a newer version: 8.0.0
Show newest version
/*
 * The MIT License
 *
 * Copyright (c) 2017 aoju.org All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.aoju.bus.socket.origin;

import org.aoju.bus.core.io.segment.BufferPool;
import org.aoju.bus.core.io.segment.EventFactory;
import org.aoju.bus.core.io.segment.RingBuffer;
import org.aoju.bus.logger.Logger;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketOption;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.security.InvalidParameterException;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

/**
 * AIO服务端
 *
 * @author Kimi Liu
 * @version 5.0.8
 * @since JDK 1.8+
 */
public class AioQuickServer {

    /**
     * Server端服务配置。
     * 

调用AioQuickServer的各setXX()方法,都是为了设置config的各配置项

*/ protected ServerConfig config = new ServerConfig<>(); protected BufferPool bufferPool; /** * 读回调事件处理 */ protected TcpReadHandler aioReadCompletionHandler; /** * 写回调事件处理 */ protected TcpWriteHandler aioWriteCompletionHandler; private Function> aioSessionFunction; private AsynchronousServerSocketChannel serverSocketChannel = null; private AsynchronousChannelGroup asynchronousChannelGroup; private Thread acceptThread = null; private volatile boolean running = true; /** * 设置服务端启动必要参数配置 * * @param port 绑定服务端口号 * @param protocol 协议编解码 * @param messageProcessor 消息处理器 */ public AioQuickServer(int port, Protocol protocol, Message messageProcessor) { config.setPort(port); config.setProtocol(protocol); config.setProcessor(messageProcessor); config.setThreadNum(Runtime.getRuntime().availableProcessors()); } /** * @param host 绑定服务端Host地址 * @param port 绑定服务端口号 * @param protocol 协议编解码 * @param messageProcessor 消息处理器 */ public AioQuickServer(String host, int port, Protocol protocol, Message messageProcessor) { this(port, protocol, messageProcessor); config.setHost(host); } /** * 启动Server端的AIO服务 * * @throws IOException 异常 */ public void start() throws IOException { start0(new Function>() { @Override public TcpAioSession apply(AsynchronousSocketChannel channel) { return new TcpAioSession(channel, config, aioReadCompletionHandler, aioWriteCompletionHandler, bufferPool.allocateBufferPage()); } }); } /** * 内部启动逻辑 * * @param aioSessionFunction 会话信息 * @throws IOException 异常 */ protected final void start0(Function> aioSessionFunction) throws IOException { //确保单核CPU默认初始化至少2个线程 if (config.getThreadNum() == 1) { config.setThreadNum(2); } int threadNum = config.getThreadNum(); try { ThreadLocal recursionThreadLocal = new ThreadLocal<>(); RingBuffer buffer = new RingBuffer(config.getReadBacklog(), new EventFactory() { @Override public TcpReadEvent newInstance() { return new TcpReadEvent(); } @Override public void restEntity(TcpReadEvent entity) { entity.setReadSize(-1); entity.setSession(null); } }); aioReadCompletionHandler = new TcpReadHandler<>(buffer, recursionThreadLocal, new Semaphore(threadNum - 1)); aioWriteCompletionHandler = new TcpWriteHandler<>(); this.bufferPool = new BufferPool(ServerConfig.getIntProperty(ServerConfig.Property.SERVER_PAGE_SIZE, 1024 * 1024), ServerConfig.getIntProperty(ServerConfig.Property.BUFFER_PAGE_NUM, threadNum), ServerConfig.getBoolProperty(ServerConfig.Property.SERVER_PAGE_IS_DIRECT, true)); this.aioSessionFunction = aioSessionFunction; asynchronousChannelGroup = AsynchronousChannelGroup.withFixedThreadPool(threadNum, new ThreadFactory() { byte index = 0; @Override public Thread newThread(Runnable r) { return new Thread(r, "bus-socket:Thread-" + (++index)); } }); this.serverSocketChannel = AsynchronousServerSocketChannel.open(asynchronousChannelGroup); //set socket options if (config.getSocketOptions() != null) { for (Map.Entry, Object> entry : config.getSocketOptions().entrySet()) { this.serverSocketChannel.setOption(entry.getKey(), entry.getValue()); } } //bind host if (config.getHost() != null) { serverSocketChannel.bind(new InetSocketAddress(config.getHost(), config.getPort()), 1000); } else { serverSocketChannel.bind(new InetSocketAddress(config.getPort()), 1000); } acceptThread = new Thread(new Runnable() { NetMonitor monitor = config.getMonitor(); @Override public void run() { Future nextFuture = serverSocketChannel.accept(); while (running) { try { final AsynchronousSocketChannel channel = nextFuture.get(); nextFuture = serverSocketChannel.accept(); if (monitor == null || monitor.acceptMonitor(channel)) { createSession(channel); } else { config.getProcessor().stateEvent(null, StateMachine.REJECT_ACCEPT, null); Logger.warn("reject accept channel:{}", channel); closeChannel(channel); } } catch (Exception e) { Logger.error("AcceptThread Exception", e); } } } }, "bus-socket:AcceptThread"); acceptThread.start(); } catch (IOException e) { shutdown(); throw e; } Logger.info("server started on port {},threadNum:{}", config.getPort(), threadNum); Logger.info("server config is {}", config); } /** * 为每个新建立的连接创建AIOSession对象 * * @param channel 当前已建立连接通道 */ private void createSession(AsynchronousSocketChannel channel) { //连接成功则构造AIOSession对象 TcpAioSession session = null; try { session = aioSessionFunction.apply(channel); session.initSession(); } catch (Exception e1) { Logger.error(e1.getMessage(), e1); if (session == null) { closeChannel(channel); } else { session.close(); } } } private void closeChannel(AsynchronousSocketChannel channel) { try { channel.shutdownInput(); } catch (IOException e) { Logger.debug(e.getMessage(), e); } try { channel.shutdownOutput(); } catch (IOException e) { Logger.debug(e.getMessage(), e); } try { channel.close(); } catch (IOException e) { Logger.debug("close channel exception", e); } } /** * 停止服务端 */ public final void shutdown() { running = false; try { if (serverSocketChannel != null) { serverSocketChannel.close(); serverSocketChannel = null; } } catch (IOException e) { Logger.warn(e.getMessage(), e); } if (!asynchronousChannelGroup.isTerminated()) { try { asynchronousChannelGroup.shutdownNow(); } catch (IOException e) { Logger.error("shutdown exception", e); } } try { asynchronousChannelGroup.awaitTermination(3, TimeUnit.SECONDS); } catch (InterruptedException e) { Logger.error("shutdown exception", e); } } /** * 设置读缓存区大小 * * @param size 单位:byte * @return the object */ public final AioQuickServer setReadBufferSize(int size) { this.config.setReadBufferSize(size); return this; } /** * 是否启用控制台Banner打印 * * @param bannerEnabled true:启用,false:禁用 * @return the object */ public final AioQuickServer setBannerEnabled(boolean bannerEnabled) { config.setBannerEnabled(bannerEnabled); return this; } /** * 设置Socket的TCP参数配置。 *

* AIO客户端的有效可选范围为: * 2. StandardSocketOptions.SO_RCVBUF * 4. StandardSocketOptions.SO_REUSEADDR *

* * @param 对象 * @param socketOption 配置项 * @param value 配置值 * @return the object */ public final AioQuickServer setOption(SocketOption socketOption, V value) { config.setOption(socketOption, value); return this; } /** * 设置write缓冲区容量 * * @param writeQueueCapacity 缓冲区大小 * @return the object */ public final AioQuickServer setWriteQueueCapacity(int writeQueueCapacity) { config.setWriteQueueCapacity(writeQueueCapacity); return this; } /** * 设置服务工作线程数,设置数值必须大于等于2 * * @param threadNum 线程数 * @return the object */ public final AioQuickServer setThreadNum(int threadNum) { if (threadNum <= 1) { throw new InvalidParameterException("threadNum must >= 2"); } config.setThreadNum(threadNum); return this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy