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();
}
}