netty+socket实现高并发

1、启动类

package com.abchina.intclr.socket.gjj;

import com.abchina.intclr.netty.socket.gjj.NettyGJJServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class SocketRunner extends HttpServlet {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private SocketServer socketServer;

	@Override
	public void init() throws ServletException {
		long time1 = System.currentTimeMillis();
		log.info("******* 监听socket服务端程序加载开始 init " + time1);
		//启动线程加载socket服务器
		new Thread() {
			public void run() {
				try {
					new NettyGJJServer(18032).run();
//					socketServer.initLocalSocketServer();
				} catch (Exception e) {
					log.error("监听socket服务端程序启动异常");
					e.printStackTrace();
				}
			};
		}.start();
		log.info("监听socket服务端程序加载结束");
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		super.doGet(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		super.doPost(req, resp);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see javax.servlet.GenericServlet#destroy()
	 */
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		//关闭Socket
		log.info("关闭Socket");
		super.destroy();
	}
}

2、创建socket服务

package com.abchina.intclr.netty.socket.gjj;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * netty服务器,主要用于与客户端通讯
 */
public class NettyGJJServer {
    protected final Logger log = LoggerFactory.getLogger(this.getClass());
    private final int port; //监听端口


    public NettyGJJServer(int port) {
        this.port = port;
    }

    //编写run方法,处理客户端的请求
    public void run() throws Exception {

        //创建两个线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(); //8个NioEventLoop

        try {
            ServerBootstrap b = new ServerBootstrap();

            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //获取到pipeline
                            ChannelPipeline pipeline = ch.pipeline();
                            //向pipeline加入解码器
                            pipeline.addLast("decoder", new ByteArrayDecoder());
                            //向pipeline加入编码器
                            pipeline.addLast("encoder", new ByteArrayDecoder());
                            //加入自己的业务处理handler
                            pipeline.addLast(new NettyGJJServerHandler());

                        }
                    });
            log.info("===============netty服务端口【{}】启动成功==================",port);
            ChannelFuture channelFuture = b.bind(port).sync();
            //监听关闭
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }

}

3、业务处理

package com.abchina.intclr.netty.socket.gjj;


import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class NettyGJJServerHandler extends SimpleChannelInboundHandler<byte[]> {
    protected final Logger log = LoggerFactory.getLogger(this.getClass());

    //定义一个channle 组,管理所有的channel
    //GlobalEventExecutor.INSTANCE) 是全局的事件执行器,是一个单例
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * 有客户端与服务器发生连接时执行此方法
     * 1.打印提示信息
     * 2.将客户端保存到 channelGroup 中
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        log.info("服务器新建连接。客户端地址:" + channel.remoteAddress());
        channelGroup.add(channel);
    }

    /**
     * 当有客户端与服务器断开连接时执行此方法,此时会自动将此客户端从 channelGroup 中移除
     * 1.打印提示信息
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        log.info("有客户端与服务器断开连接。客户端地址:" + channel.remoteAddress());
    }

    /**
     * 表示channel 处于活动状态
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info(ctx.channel().remoteAddress() + "========建立连接=======");
    }

    /**
     * 表示channel 处于不活动状态
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info(ctx.channel().remoteAddress() + "=======关闭连接=======");
    }

    /**
     * 读取到客户端发来的数据数据
     */
    @Override
    public void channelRead0(ChannelHandlerContext ctx, byte[] msg) {
        Map<String, Object> retMap = new HashMap<String, Object>();
        //获取到当前channel
        try {
            Channel channel = ctx.channel();
            log.info("【{}】开始接收请求数据" + channel.remoteAddress() + " 内容:" + new String(msg));
            String str="连接成功";
//响应
            ctx.channel().write(str);
            ctx.channel().flush();
        } catch (Exception e) {
            log.error("请求异常:{}",e.getMessage());
            e.printStackTrace();
        } finally {
            ctx.channel().close();
        }

    }

    /**
     * 处理异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("发生异常。异常信息:{}", cause.getMessage());
        //关闭通道
        ctx.close();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值