专栏总结java8:Socket编程nio—netty快速入门和运行原理

本文介绍了Netty作为高性能的网络通信框架,对比Tomcat的区别,以及Netty的NIO线程模型。文章详细阐述了Netty的启动流程,包括服务器端和客户端的创建步骤,并探讨了Netty的高性能原理,如基于NIO的多路复用和事件驱动的Reactor线程模型。此外,文章还提到了Netty的ByteBuf,指出其相比ByteBuffer的优点,如灵活的读写索引和引用计数机制。
摘要由CSDN通过智能技术生成

请不要付费,只是把历史笔记发布,包含专栏内容总结。

专栏总结1:基础网络相关
专栏总结2:数据结构和算法
专栏总结3:操作系统和计算机原理
专栏总结4:Linux和linux内核
专栏总结5:mysql相关
专栏总结6:redis相关

专栏总结7:中间件Nginx、消息队列
专栏总结java1:类型和String、反射
专栏总结java2:集合
专栏总结java3:类接口相关
专栏总结java4:异常
专栏总结java5:线程/多线程并发
专栏总结java6:jvm
专栏总结java7:jdk
专栏总结java8:Socket编程 nio
专栏总结java9:MyBatis+hibernate

专栏总结java10:Spring
专栏总结java11:Spring MVC
专栏总结java12:springboot
专栏总结java13:springcloud
专栏总结java14:dubbo

专栏总结:场景实践
专栏总结:架构设计总结

问题:

Socket编程 nio

NIO模型,select/epoll的区别,多路复用的原理

NIO是什么?适用于何种场景?

简述BIO,NIO的具体使用及原理

《Netty实战》和《Netty权威指南 第2版》笔记

一、netty是什么


        Netty是一个NIO网络编程框架,快速开发高性能、高可靠性的网络服务器/客户端程序。 极大地简化了TCP和UDP等网络编程。是一个异步事件驱动的网络框架。

Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。

Netty对JDK自带的NIO的API进行封装,解决上述问题,主要特点有:

  1. 设计优雅,适用于各种传输类型的统一API阻塞和非阻塞Socket;基于灵活且可扩展的事件模型,可以清晰地分析关注点;高度可定制的线程模型-单线程,一个或多个线程池;真正的无连接数据报套接字支持
  2. 使用方便,详细记录的Javadoc,用户指南和示例;没有其他依赖项,JDK5(Netty3.x)或6 (Netty4.x) 就足够了
  3. 高性能,吞吐量更高,延迟更低;减少资源消耗;最小化不必要的内存复制
  4. 安全,完整的SSL/TLS和StartTLS支持
  5. 社区活跃,不断更新,社区活跃,版本迭代周期短,发现的Bug可以被及时修复,同时,更多的新功能会被加入。

Netty常见的使用场景如下:

  1. 互联网行业。在分布式系统中,各个节点之间需要远程服务调用,高性能的RPC框架必不可少,Netty作为异步高性能的通信框架,往往作为基础通信组件被这些RPC框架使用。典型的应用有:阿里分布式服务框架Dubbo的RPC框架使用Dubbo协议进行节点间通信,Dubbo协议默认使用Netty作为基础通信组件,用于实现各进程节点之间的内部通信
  2. 游戏行业。无论是手游服务端还是大型的网络游戏,Java语言得到了越来越广泛的应用。Netty作为高性能的基础通信组件,它本身提供了TCP/UDP和HTTP协议栈。非常方便定制和开发私有协议栈,账号登录服务器,地图服务器之间可以方便的通过Netty进行高性能的通信
  3. 大数据领域。经典的Hadoop的高性能通信和序列化组件Avro的RPC框架,默认采用Netty进行跨节点通信,它的Netty Service基于Netty框架二次封装实现。

二、Netty和Tomcat有什么区别?


       Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基于http协议的web容器,但是Netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。

有人说netty的性能就一定比tomcat性能高,其实不然,tomcat从6.x开始就支持了nio模式,并且后续还有APR模式——一种通过jni调用apache网络库的模式,相比于旧的bio模式,并发性能得到了很大提高,特别是APR模式,而netty是否比tomcat性能更高,则要取决于netty程序作者的技术实力了。

web容器选择:

  • tomcat就是专门针对http服务器,tomcat从7开始默认就是nio的, 做web容器选择成熟tomcat。
  • netty是一个网络组件,tcp,udp,http都可以弄,但是官方文档都是些hello wolrd级别的。如果你非常了解http结构,完全可以基于netty搞出一个比tomcat牛的http server。如果做tcp开发,netty不二之选!拿Netty去整Http服务器需要自己造轮子,而且轮子可能随时崩溃。

 三、netty快速入门


1、引入Maven依赖

 <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.6.Final</version>
 </dependency>

2、服务器端:

package com.demo.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.nio.*;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.*;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
public class NettyServer {
    public static void main(String[] args) {
        // 创建mainReactor用来接收进来的连接
        NioEventLoopGroup boosGroup = new NioEventLoopGroup();
        // 创建工作线程组:用来处理已经被接收的连接,一旦bossGroup接收到连接,就会把连接信息注册到workerGroup上
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //服务端nio启动辅助类
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap
                    .group(boosGroup, workerGroup) //组装NioEventLoopGroup
                    .channel(NioServerSocketChannel.class)//设置channel类型为NIO类型
                    .option(ChannelOption.SO_BACKLOG, 128) // // 设置连接配置参数:tcp最大缓存链接个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true) //保持连接
                    .handler(new LoggingHandler(LogLevel.INFO)) // 打印日志级别
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) {
                            // 这里相当于过滤器,可以配置多个
                            ch.pipeline().addLast(new StringDecoder());

//                            ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
//                                @Override
//                                protected void channelRead0( ChannelHandlerContext ctx, String msg) {
//                                    System.out.println("receive:" + msg);
//                                    ctx.write("ok");//发送给客户端
//                                }
//                            });
                            // 自定义处理类

                            //注册OutboundHandler在前面 在channel队列中添加一个handler来处理业务:注册OutboundHandler
                            ch.pipeline().addLast(new ReponseHandler());

                            //注册InboundHandler
                            ch.pipeline().addLast(new ServerHandler());
                        }
                    });
            //绑定端口,开始接收进来的连接:通过调用sync同步方法阻塞直到绑定成功
            ChannelFuture cf = serverBootstrap.bind(8800).sync();
            // 等待服务器socket关闭
            cf.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 优雅退出,释放线程池资源
            System.out.println("finally:" );
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static class ServerHandler extends ChannelInboundHandlerAdapter  {
        /**
         * 收到数据时调用
         */
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            try {
                System.out.println("ServerHandler:" + msg);
                ctx.write(msg);
                ctx.flush();
            } finally {
                // 抛弃收到的数据
                //ReferenceCountUtil.release(msg);
            }
            // 通知执行下一个InboundHandler
            //ctx.fireChannelRead(msg);

        }
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            System.out.println("channelReadComplete");
            super.channelReadComplete(ctx);
            ctx.flush(); // 4
        }
        /**
         * 当Netty由于IO错误或者处理器在处理事件时抛出异常时调用
         */
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            // 当出现异常就关闭连接
            cause.printStackTrace();
            ctx.close();
        }
    }

    public static class ReponseHandler extends ChannelOutboundHandlerAdapter   {

        @Override
        public void read(ChannelHandlerContext ctx) throws Exception {
            ctx.writeAndFlush("ChannelOutboundHandlerAdapter.read 发来一条消息\r\n");
            super.read(ctx);
        }
        // 向client发送消息
        @Override
        public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
            System.out.println("ReponseHandler=========================write:");
            String response = "I am ok!";
            ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
            encoded.writeBytes(response.getBytes());
            ctx.write(encoded);
            ctx.flush();

        }

        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hguisu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值