IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 使用netty实现并维护TCP长连接 -> 正文阅读

[网络协议]使用netty实现并维护TCP长连接

Netty是什么

Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。
Netty 是一个广泛使用的 Java 网络编程框架(Netty 在 2011 年获得了Duke’s Choice Award,见https://www.java.net/dukeschoice/2011)。它活跃和成长于用户社区,像大型公司 Facebook 和 Instagram 以及流行 开源项目如 Infinispan, HornetQ, Vert.x, Apache Cassandra 和 Elasticsearch 等,都利用其强大的对于网络抽象的核心代码。

Netty的优点

1.并发高
2.传输快
3.封装好

Netty为什么并发高

Netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高

创建TCP长连接实例

  1. 该类的作用是创建客户端连接与创建该链接的监听并无限重连
mport java.util.concurrent.TimeUnit;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class CreateTCPConnection {

    private String host; //连接主机ip
    private Integer port; //连接主机端口
    public EventLoopGroup group; 
    public Channel channel;
    public ChannelFuture f;

    public CreateTCPConnection(String host, Integer port) {
        this.host = host;
        this.port = port;
    }

    /**
     * 创建TCP长连接并实例化channel
     */
    public void connect() {
        if(group!=null){
            group.shutdownGracefully();  //这里调用这个看看会不会释放
        }
        group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group) //1 设置reactor 线程
                    .option(ChannelOption.SO_KEEPALIVE, true) //1 设置通道选项
                    .channel(NioSocketChannel.class) //2 设置nio类型的channel
                    .handler(new ClientChannelInitializer(CreateTCPConnection.this));  //3 装配流水线
            //创建连接
            f = b.connect(host, port);

            //检测并执行断线重连
            f.addListener((ChannelFutureListener) channelFuture -> {
                if (!channelFuture.isSuccess()) {
                    final EventLoop loop = channelFuture.channel().eventLoop();
                    loop.schedule(() -> {
                        TdLog.error(host + " : 服务端链接不上,开始重连操作...");
                        connect();
                        //此处处理重连次数
                    }, 1L, TimeUnit.SECONDS);
                } else {
                    channel = channelFuture.channel();
                    TdLog.info("服务端链接成功...");
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
  1. 客户端通道配置类
import java.util.concurrent.TimeUnit;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * 类描述:TCP通道配置
 */
public class ClientChannelInitializer extends ChannelInitializer {

    private CreateTCPConnection createTCPConnection;

    public ClientChannelInitializer(CreateTCPConnection createTCPConnection) {
        this.createTCPConnection = createTCPConnection;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        //心跳检测
        pipeline.addLast(new IdleStateHandler(0, 30, 0, TimeUnit.SECONDS));
        //字符串编码(默认编码)
        pipeline.addLast("encoder", new StringEncoder());
        //字符串解码(重写类,如不需要可使用默认)
        pipeline.addLast(new TCPBaseMessageDecoder());
        //客户端的逻辑
        pipeline.addLast("handler", new NettyClientHandler(createTCPConnection));
    }
}
  1. 重写decode类
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.apache.commons.collections.CollectionUtils;

/**
 * TCP消息解码器
 * @author 07408
 *
 */
@TdClassLog
public class TCPBaseMessageDecoder extends ByteToMessageDecoder {
    private List<byte[]> byteList =new ArrayList<>();
    @Override
    protected void  decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
            //处理实际业务
            while (in.isReadable()) {
                System.err.print((char)in.readByte());
            }
    }
}
  1. SimpleChannelInboundHandler实现类能管理并使用该客户端连接
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.EventLoop;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;


/**
 * 类描述:TCP客户端适配器
 */
public class NettyClientHandler extends SimpleChannelInboundHandler {

    private CreateTCPConnection nettyClient;
    private int heartNumber;

    public NettyClientHandler(CreateTCPConnection createTCPConnection) {
        nettyClient = createTCPConnection;
    }

    //这个方法接收不到数据
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg){}

    /**
     * 长连接读取数据方法-处理业务逻辑
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIP = insocket.getAddress().getHostAddress();
        System.out.println(clientIP+" Server say : " + msg.toString());
    }

    /**
     * 通道连接时调用-处理业务逻辑
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIP = insocket.getAddress().getHostAddress();
        TdLog.error(clientIP + " :通道已连接!");
    }

    /**
     * 通道闲置触发-启动断线重连功能
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        //使用过程中断线重连
        final EventLoop eventLoop = ctx.channel().eventLoop();
        eventLoop.schedule(() -> {
            TdLog.error("断线连接中...");
            nettyClient.connect();
        }, 1, TimeUnit.SECONDS);
        ctx.fireChannelInactive();
    }

    /**
     * 心跳方法
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state().equals(IdleState.READER_IDLE)) {
                System.out.println("READER_IDLE");
            } else if (event.state().equals(IdleState.WRITER_IDLE)) {
                /**发送心跳,保持长连接*/
                byte[] buff = {'V','Z',1,0,0,0,0,0};
                String cmd = new String(buff);
                ctx.channel().writeAndFlush(cmd);
                
            } else if (event.state().equals(IdleState.ALL_IDLE)) {
                System.out.println("ALL_IDLE");
            }
        }
        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        super.handlerRemoved(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }
}
  1. 本地调试测试连接能否正常使用
public static void main(String[] args) throws InterruptedException {
   CreateTCPConnection pu = new CreateTCPConnection("10.30.20.185", 8131);
    pu.connect();
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-12-02 17:07:55  更:2021-12-02 17:09:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:54:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码