/** * Copyright (c) 2018-2019, Jie Li 李杰 ([email protected]). * <p> * 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 * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * 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. */ package com.momo.netty.service; import com.momo.common.core.util.JwtTokenUtil; import com.momo.common.core.util.RedisUtil; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.net.InetSocketAddress; /** * @ClassName: TCPServerTwo * @Author: Jie Li * @Date 2019-11-24 11:25 * @Description: TODO * @Version: 1.0 * <p>Copyright: Copyright (c) 2019</p> **/ @Component("tCPServerTwo") @Slf4j public class TCPServer { //读取yml中配置 //bossGroup的线程数 @Value("${netty.boss.thread.count}") private static int bossCount; @Value("${netty.worker.thread.count}") //# worker的线程数 private static int workerCount; @Value("${netty.tcp.port}") //#tcp监听的端口 private int tcpPort; @Value("${netty.so.keepalive}") //Socket参数,连接保活,默认值为False。启用该功能时,TCP会主动探测空闲连接的有效性。可以将此功能视为TCP的心跳机制, private boolean keepAlive; @Value("${netty.so.backlog}") //Socket参数,服务端接受连接的队列长度,如果队列已满,客户端连接将被拒绝 private int backlog; @Autowired private RedisUtil redisUtil; @Autowired private JwtTokenUtil jwtTokenUtil; @Autowired private NettyHandlerService nettyHandlerService; //NioEventLoopGroup extends MultithreadEventLoopGroup // Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2)); //配置服务端NIO线程组 private final EventLoopGroup bossGroup = new NioEventLoopGroup(bossCount); private final EventLoopGroup workerGroup = new NioEventLoopGroup(workerCount); private Channel channel; ChannelFuture bing() { ChannelFuture channelFuture = null; try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) //非阻塞模式 .handler(new LoggingHandler(LogLevel.DEBUG)) .option(ChannelOption.SO_REUSEADDR, true) .option(ChannelOption.SO_KEEPALIVE, keepAlive) .option(ChannelOption.SO_BACKLOG, backlog) .childHandler(new WSServerInitialzer(nettyHandlerService)); channelFuture = b.bind(new InetSocketAddress(tcpPort)).syncUninterruptibly(); channel = channelFuture.channel(); } catch (Exception e) { log.error("netty start error {} {}", e.getMessage(), e); } finally { if (null != channelFuture && channelFuture.isSuccess()) { log.info("tCPServerTwo start ok"); } else { log.error("tCPServerTwo start error "); } } return channelFuture; } void destroy() { if (null == channel) { return; } channel.close(); log.info("channel.close(); netty stop......."); bossGroup.shutdownGracefully(); log.info("bossGroup.shutdownGracefully()"); workerGroup.shutdownGracefully(); log.info("workerGroup.shutdownGracefully()"); } public Channel getChannel() { return channel; } }