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 专栏——Netty 入门案例 TCP服务 -> 正文阅读

[网络协议]Netty 专栏——Netty 入门案例 TCP服务

一、项目需求

  • 1)服务端监听8001端口
  • 2)客户端能发送消息给服务器
  • 3)服务器可以返回消息给客户端

二、代码编辑

1、服务端

public class NettyServer {
    public static void main(String[] args) throws Exception {

        /*create boss group and worker group*/
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        /*both above all are thread group*/

        try{
            /*create initial object of server side*/
            ServerBootstrap bootstrap = new ServerBootstrap();
            /*setting initial parameter*/
            bootstrap.group(bossGroup,workerGroup)
                .channel(NioServerSocketChannel.class)
                /*setting connect limit num of thread queue*/
                .option(ChannelOption.SO_BACKLOG,128)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    /*adding handler to pipeline*/
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new NettyServerHandler());
                    }
                }); /*setting handler of EventLoop of Worker Group*/
            System.out.println("Server is ready");
            /*start up service*/
            ChannelFuture cf = bootstrap.bind(8001).sync();
            /*listen closed channel event*/
            cf.channel().closeFuture().sync();
        }finally{
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2、自定义服务端处理器

/**
	* Custom handler must extends some HandlerAdapter of netty library
	* @author 彭友聪
	*/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    /**Read handler
	* we can gain the pipeline and channel from ChannelHandlerContext
	* msg is the data come from client
	* */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("server ctx = " + ctx);
        /*transform the msg into byte buf*/
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("client sent: " + buf.toString(CharsetUtil.UTF_8));
        System.out.println("Address of Client: " + ctx.channel().remoteAddress());
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        /*write data into buf and flush*/
        /*we need to encode the msg we want to send*/
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Client~~~", CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.channel().close();
    }
}

4、客户端

public class NettyClient {
    public static void main(String[] args) throws Exception{
        /*client only need a event loop group*/
        EventLoopGroup eventExecutors = new NioEventLoopGroup();
        try{
            /*create start up assistant*/
            Bootstrap bootstrap = new Bootstrap();
            /*setting initial parameter*/
            bootstrap.group(eventExecutors)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new NettyClientHandler());
                    }
                });
            System.out.println("Client is ready~~~");
            ChannelFuture channelFuture = 
                bootstrap.connect("127.0.0.1", 8001).sync();
            channelFuture.channel().closeFuture().sync();
        }finally{
            eventExecutors.shutdownGracefully();
        }
    }
}

5、自定义客户端处理器

public class NettyClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client ctx=" + ctx);
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Netty Server!!", CharsetUtil.UTF_8));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("from server: " + buf.toString(CharsetUtil.UTF_8));
        System.out.println("Server Address: " + ctx.channel().remoteAddress());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println(cause.getMessage());
        ctx.close();
    }
}

6、输出结果

Server is ready
server ctx = ChannelHandlerContext(NettyServerHandler#0, [id: 0x97209815, L:/127.0.0.1:8001 - R:/127.0.0.1:50900])
client sent: Hello Netty Server!!
Address of Client: /127.0.0.1:50900

Client is ready~~~
client ctx=ChannelHandlerContext(NettyClientHandler#0, [id: 0xbdbdca5e, L:/127.0.0.1:50900 - R:/127.0.0.1:8001])
from server: Hello, Client~~~
Server Address: /127.0.0.1:8001

三、分析

  • 1)bossGroup 和 workerGroup 含有的子线程(NioEventLoop)的个数,默认是CPU核心数*2,循环分配
  • 2)Netty 抽象出两组线程池,BossGroup 专门负责接受客户的连接,WorkerGroup负责网络读写操作
  • 3)NioEventLoop 表示一个不断循环处理任务的线程,每个都含有用于监听绑定在其上的socket channel 的 selector
  • 4)NioEventLoop 内部采用串行化设计,从消息的读取-》解码-》处理-》编码-》发送,始终由 IO 线程的 NioEventLoop 负责

1、Netty 的异步模型(ChannelFuture)

所谓异步,就是指调用异步方法后不会立即得到结果,而是先去执行其他任务,而等到实际处理这个调用的组件完成后,通过状态、通知和回调来通知调用者Netty 的IO操作都是异步的,包括 Bind、Write和Connect 等操作会简单的返回一个ChannelFuture

Netty 的异步模型,是建立在 future 和 callback 之上的,future 的核心思想是:假设一个方法的处理过程非常耗时,显然一直等待方法处理显然不合适,通常都会在调用该方法时立马返回一个future,后续可以通过该future去监控对应方法的处理进度,这就是 Netty 的 Future-Listener机制
在这里插入图片描述

使用 Netty,拦截操作和转换出入站数据,只需提供对应的callback 或利用 future 即可,这使得链式操作简单、高效,并有利于编写可重用的、通用的代码

1.1、Future

1)表示异步的执行结果,可以通过它提供的方法来检测执行是否完成,如检索计算等
2)ChannelFuture 是一个接口,支持添加监听器,当监听的事件发生时就会通知监听器

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-12-13 13:13:40  更:2021-12-13 13:15:50 
 
开发: 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 10:17:59-

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