springboot-netty创建TCP客户端
springboot创建TCP客户端
实现客户端向服务端发送数据,接收服务端的响应数据,
配置类,改下ip和端口即可用
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class NettyTcpClient {
@Autowired
private NettyTcpClientInitializer nettyTcpClientInitializer;
private EventLoopGroup group;
private Bootstrap b;
private ChannelFuture cf;
@Value("${tcp.server.host}")
private String host;
@Value("${tcp.server.port}")
private int port;
@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(host, port).sync();
} catch (InterruptedException e) {
log.error("客户端连接服务端异常:" + e);
}
}
public ChannelFuture getChannelFuture() {
// if (this.cf == null) {
// this.connect();
// }
// if (!this.cf.channel().isActive()) {
// this.connect();
// }
// TODO 每次发送数据均重新链接TCP服务,是否可行
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);
}
}
配置类,监听服务端状态和响应的
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;
@Slf4j
@Component
@ChannelHandler.Sharable
public class NettyTcpClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) {
log.info("ClientHandler Active");
}
/**
* @param ctx
* @DESCRIPTION: 有服务端端终止连接服务器会触发此函数
* @return: void
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) {
ctx.close();
log.error("服务端终止了服务");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object object) {
log.info("接收服务端返回的消息:{}", object.toString());
// 可实现一些业务
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//cause.printStackTrace();
log.info("服务端发生异常【" + cause.getMessage() + "】");
ctx.close();
}
// @Override
// public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// log.info("尝试重新连接三方服务端");
//// ctx.channel().eventLoop().schedule(() -> {
//// ReconnectClient.connect();
//// }, ReconnectClient.RECONNECT_DELAY, TimeUnit.SECONDS);
// }
/**
* @param msg 需要发送的消息内容
* @param channelId 连接通道唯一id
* @DESCRIPTION: 客户端给服务端发送消息
* @return: void
*/
// public void channelWrite(String msg) {
//
// ChannelHandlerContext ctx = CLIENT_MAP.get("1");
// //将客户端的信息直接返回写入ctx
// ctx.write(msg);
// //刷新缓存区
// ctx.flush();
// }
}
配置类,无需改动
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class NettyTcpClientInitializer extends ChannelInitializer<SocketChannel> {
@Autowired
private NettyTcpClientHandler nettyClientHandler;
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
ch.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(nettyClientHandler);
}
}
发送数据
@Resource
private NettyTcpClient nettyClient;
nettyClient.sendMessage("发送数据");