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("发送数据");
posted @ 2025-05-23 23:18  窃窃私语QAQ  阅读(9)  评论(0)    收藏  举报