@Slf4j
@Component
public class NettyTcpClient {
@Autowired
private PropertyUtils propertyUtils;
@Autowired
private NettyTcpClientInitializer nettyTcpClientInitializer;
private EventLoopGroup group;
private Bootstrap b;
private ChannelFuture cf;
@Bean
public void startTcpClient() {
group = new NioEventLoopGroup();
b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(nettyTcpClientInitializer);
}
public void connect() {
try {
this.cf = b.connect(propertyUtils.getNettyTcpIp(), propertyUtils.getNettyTcpPort()).sync();
} catch (InterruptedException e) {
log.error("客户端连接服务端异常:" + e);
}
}
public ChannelFuture getChannelFuture() {
if (this.cf == null) {
this.connect();
}
if (!this.cf.channel().isActive()) {
this.connect();
}
return this.cf;
}
public void close() {
try {
this.cf.channel().closeFuture().sync();
this.group.shutdownGracefully();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sendMessage(String msg) throws InterruptedException {
ChannelFuture cf = this.getChannelFuture();
cf.channel().writeAndFlush(msg);
}
}
@Slf4j
@Component
public class NettyTcpClientHandler extends ChannelInboundHandlerAdapter{
/**
* 计算有多少客户端接入,第一个string为客户端ip
*/
private static final ConcurrentHashMap<ChannelId, ChannelHandlerContext> CLIENT_MAP = new ConcurrentHashMap<>();
@Override
public void channelActive(ChannelHandlerContext ctx) {
CLIENT_MAP.put(ctx.channel().id(), ctx);
log.info("ClientHandler Active");
}
/**
* @param ctx
* @author xiongchuan on 2019/4/28 16:10
* @DESCRIPTION: 有服务端端终止连接服务器会触发此函数
* @return: void
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) {
ctx.close();
log.info("服务端终止了服务");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
log.info("回写数据:" + msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//cause.printStackTrace();
log.info("服务端发生异常【" + cause.getMessage() + "】");
ctx.close();
}
/**
* @param msg 需要发送的消息内容
* @param channelId 连接通道唯一id
* @author xiongchuan on 2019/4/28 16:10
* @DESCRIPTION: 客户端给服务端发送消息
* @return: void
*/
public void channelWrite(ChannelId channelId, String msg) {
ChannelHandlerContext ctx = CLIENT_MAP.get(channelId);
if (ctx == null) {
log.info("通道【" + channelId + "】不存在");
return;
}
//将客户端的信息直接返回写入ctx
ctx.write(msg);
//刷新缓存区
ctx.flush();
}
}
@Component
public class NettyTcpClientInitializer extends ChannelInitializer<SocketChannel>{
@Autowired
private NettyTcpClientHandler nettyClientHandler;
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
ch.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
ch.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(nettyClientHandler);
}
}
/**
* 向netty服务端发送消息
*/
@GetMapping("tcp")
public String tcp() {
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//nettyTcpClient.sendMessage("发送入网检测认证消息:" + df.format(new Date()));
ChannelFuture channelFuture=nettyTcpClient.getChannelFuture();
nettyTcpClientHandler.channelWrite(channelFuture.channel().id(), "发送入网检测认证消息:" + df.format(new Date()));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "TCP-success";
}
@Slf4j
@Component
public class NettyTcpClient {
@Autowired
private PropertyUtils propertyUtils;
@Autowired
private NettyTcpClientInitializer nettyTcpClientInitializer;
private EventLoopGroup group;
private Bootstrap b;
private ChannelFuture cf;
@Bean
public void startTcpClient() {
group = new NioEventLoopGroup();
b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(nettyTcpClientInitializer);
}
public void connect() {
try {
this.cf = b.connect(propertyUtils.getNettyTcpIp(), propertyUtils.getNettyTcpPort()).sync();
} catch (InterruptedException e) {
log.error("客户端连接服务端异常:" + e);
}
}
public ChannelFuture getChannelFuture() {
if (this.cf == null) {
this.connect();
}
if (!this.cf.channel().isActive()) {
this.connect();
}
return this.cf;
}
public void close() {
try {
this.cf.channel().closeFuture().sync();
this.group.shutdownGracefully();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sendMessage(String msg) throws InterruptedException {
ChannelFuture cf = this.getChannelFuture();
cf.channel().writeAndFlush(msg);
}
}