1.客户端

①HelloClient.java

public class HelloClient {
	public static String host = "127.0.0.1";
	     public static int port = 7878;

	     /**
	      * @param args
	      * @throws InterruptedException
	      * @throws IOException
	      */
	     public static void main(String[] args) throws InterruptedException, IOException {
	         EventLoopGroup workGroup = new NioEventLoopGroup();
	         try {
	             Bootstrap b = new Bootstrap();
	             b.group(workGroup)
	             .channel(NioSocketChannel.class)
	             .handler(new HelloClientInitializer());

	             // 连接服务端
	             ChannelFuture future = b.connect(host, port).sync();

	             // 控制台输入
	             BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	             for (;;) {
	                 String line = in.readLine();
	                 if (line == null) {
	                     continue;
	                 }
	                 /*
	                  * 向服务端发送在控制台输入的文本 并用"\r\n"结尾
	                  * 之所以用\r\n结尾 是因为我们在handler中添加了 DelimiterBasedFrameDecoder 帧解码。
	                  * 这个解码器是一个根据\n符号位分隔符的解码器。所以每条消息的最后必须加上\n否则无法识别和解码
	                  * */
	                 future.channel().writeAndFlush(line + "\r\n");
	             }
	         } finally {
	             // The connection is closed automatically on shutdown.
	        	 workGroup.shutdownGracefully();
	         }
	     }
}

②HelloClientInitializer.java

主要功能是完成客户端的编解码工作

public class HelloClientInitializer extends ChannelInitializer<SocketChannel> {

	     protected void initChannel(SocketChannel ch) throws Exception {
	         ChannelPipeline pipeline = ch.pipeline();

	         /*
	          * 这个地方的 必须和服务端对应上。否则无法正常解码和编码
	          *
	          * 解码和编码 我将会在下一张为大家详细的讲解。再次暂时不做详细的描述
	          *
	          * */
	         pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
	         pipeline.addLast("decoder", new StringDecoder());
	         pipeline.addLast("encoder", new StringEncoder());

	         // 客户端的逻辑
	         pipeline.addLast("handler", new HelloClientHandler());
	    }

}

③ HelloClientHandler.java

业务处理类,主要有三个方法

客户端建立连接时调用:channelActive方法

客户端接收服务端消息时调用:channelRead0方法

连接断开时调用:channelInactive方法

public class HelloClientHandler extends SimpleChannelInboundHandler<String> {
	     @Override
	     protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {

	         System.out.println("Server say : " + msg);
	     }

	     @Override
	     public void channelActive(ChannelHandlerContext ctx) throws Exception {
	         System.out.println("Client active ");
	         super.channelActive(ctx);
	     }

	     @Override
	     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
	         System.out.println("Client close ");
	         super.channelInactive(ctx);
	     }
}

2.服务端

①HelloServer.java

public class HelloServer {
	 /**
     * 服务端监听的端口地址
     */
    private static final int portNumber = 7878;

    public static void main(String[] args) throws InterruptedException {
    	//第一个线程组用于接收client连接
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //第二个线程组用于具体的业务处理
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
        	//创建一个辅助类Boosatrap用于对Server进行一系列的配置
            ServerBootstrap b = new ServerBootstrap();
            //将两个线程组加入进来
            b.group(bossGroup, workerGroup);
            //指定使用NioServerSocketChannel这种类型的通道
            b.channel(NioServerSocketChannel.class);
            //一定要使用childHandler绑定具体的事件处理器
            b.childHandler(new HelloServerInitializer());

            //SocketChannel通道的配置项(保持连接)
            b.option(ChannelOption.SO_KEEPALIVE, true);

            // 服务器绑定端口监听
            ChannelFuture f = b.bind(portNumber).sync();
            // 监听服务器关闭监听
            f.channel().closeFuture().sync();

            // 可以简写为
            /* b.bind(portNumber).sync().channel().closeFuture().sync(); */
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

②HelloServerInitializer.java

主要功能是完成服务端的编解码工作

public class HelloServerInitializer extends ChannelInitializer<SocketChannel> {
	     @Override
	     protected void initChannel(SocketChannel ch) throws Exception {
	         ChannelPipeline pipeline = ch.pipeline();

	         // 以("\n")为结尾分割的 解码器
	         pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));

	         // 字符串解码 和 编码
	         pipeline.addLast("decoder", new StringDecoder());
	         pipeline.addLast("encoder", new StringEncoder());

	         // 自己的逻辑Handler
	         pipeline.addLast("handler", new HelloServerHandler());
	     }
}

③HelloServerHandler.java

服务端的业务处理类,主要包括channelRead0(),channelActive()方法

channelActive()建立连接时触发

channelRead0()接收客户端消息

public class HelloServerHandler extends SimpleChannelInboundHandler<String> {
	     @Override
	     protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
	         // 收到消息直接打印输出
	         System.out.println(ctx.channel().remoteAddress() + " Say : " + msg);

	         // 返回客户端消息 - 我已经接收到了你的消息
	         ctx.writeAndFlush("Received your message !\n");
	     }

	     /*
	      *
	      * 覆盖 channelActive 方法 在channel被启用的时候触发 (在建立连接的时候)
	      *
	      * channelActive 和 channelInActive 在后面的内容中讲述,这里先不做详细的描述
	      * */
	     @Override
	     public void channelActive(ChannelHandlerContext ctx) throws Exception {

	         System.out.println("RamoteAddress : " + ctx.channel().remoteAddress() + " active !");

	         ctx.writeAndFlush( "Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\n");

	         super.channelActive(ctx);
	     }
}

netty基本用法的更多相关文章

  1. Netty如何实现Reactor模式

    在前面的文章中(Reactor模型详解),我们讲解了Reactor模式的各种演变形式,本文主要讲解的则是Netty是如何实现Reactor模式的.这里关于Netty实现的Reactor模式,需要说明的 ...

  2. elasticsearch节点间通信的基础transport

    在前一篇中我们分析了cluster的一些元素.接下来的章节会对cluster的运作机制做详细分析.本节先分析一些transport,它是cluster间通信的基础.它有两种实现,一种是基于netty实 ...

  3. Netty学习笔记(二)——netty组件及其用法

    1.Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 原生NIO存在的问题 1) NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector.Se ...

  4. netty用法总结

    /**decoder和encoder,如果不需要解析,就使用系统的 * ch.pipeline().addLast(new StringDecoder()); * ch.pipeline().addL ...

  5. 基于Netty打造RPC服务器设计经验谈

    自从在园子里,发表了两篇如何基于Netty构建RPC服务器的文章:谈谈如何使用Netty开发实现高性能的RPC服务器.Netty实现高性能RPC服务器优化篇之消息序列化 之后,收到了很多同行.园友们热 ...

  6. (二)Netty源码学习笔记之服务端启动

    尊重原创,转载注明出处,原文地址:http://www.cnblogs.com/cishengchongyan/p/6129971.html  本文将不会对netty中每个点分类讲解,而是一个服务端启 ...

  7. ElasticSearch的基本用法与集群搭建

    一.简介 ElasticSearch和Solr都是基于Lucene的搜索引擎,不过ElasticSearch天生支持分布式,而Solr是4.0版本后的SolrCloud才是分布式版本,Solr的分布式 ...

  8. Netty系列之Netty百万级推送服务设计要点

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  9. Netty权威指南

    Netty权威指南(异步非阻塞通信领域的经典之作,国内首本深入剖析Netty的著作,全面系统讲解原理.实战和源码,带你完美进阶Netty工程师.) 李林锋 著   ISBN 978-7-121-233 ...

随机推荐

  1. docker的安装和基础使用

    Docker EE/Docker CE简介与版本规划 版本区别 Docker EE Docker EE由公司支持,可在经过认证的操作系统和云提供商中使用,并可运行来自Docker Store的.经过认 ...

  2. Day 网络协议介绍 简单通信的实现

    比如说实现两个手机之间的通信,需要做的几部: 服务端: 1,买手机 2,插卡 3,开机 4,等电话链接 5,基于建立的链接,收发协议 6,挂电话 7,关机 import socket #买手机 pho ...

  3. 关于运行springboot时报Unregistering JMX-exposed beans on shutdown的解决方案

    其实这个错误并不影响程序的运行,但是对于处女座的同仁来说,看到报错难免不舒服,那么看看解决方法,此错误信息的意思是说:在关机状态下未注册jmx暴露的bean. 解决方案是在入口类上加上  @Enabl ...

  4. 人脸姿态校正算法 附完整C++示例代码

    在一些特殊情况下,经常需要依据图像中的人脸,对图片进行倾斜矫正. 例如拍照角度幅度过大之类的情况,而进行人工矫正确实很叫人头大. 那是不是可以有一种算法,可以根据人脸的信息对图片进行角度的修复呢? 答 ...

  5. 我写的python代码的规则

    1.Python文件的命名: 采用每个单词的首字母大写,不使用下划线 2.Python类的命名: 采用每个单词的首字母大写,不使用下划线 3.Python包名的命名:采用每个单词都是小写,不使用下划线 ...

  6. python3 分布式爬虫

    背景 部门(东方IC.图虫)业务驱动,需要搜集大量图片资源,做数据分析,以及正版图片维权.前期主要用node做爬虫(业务比较简单,对node比较熟悉).随着业务需求的变化,大规模爬虫遇到各种问题.py ...

  7. java 字符串池【转】

    java 字符串池 java运行环境有一个字符串池.比如String str="abc"时,会首先查看字符串池中是否存在字符串"abc",如果存在则直接将&qu ...

  8. 洛谷 P1691 解题报告

    P1691 有重复元素的排列问题 题目描述 设\(R={r_1,r_2,--,r_n}\)是要进行排列的\(n\)个元素.其中元素\(r_1,r_2,--,r_n\)可能相同.使设计一个算法,列出\( ...

  9. JS响应数据

    页面中展示的信息都是存储在服务器中的数据,离开数据的页面就像是一块画板的作用,如何通过数据来描述一个页面,又怎么映射数据变化和页面渲染的关系. 当然,最直接的方法就是操作节点,页面加载之后获取节点,再 ...

  10. 学习CTF的经历-文件分析

    文件分析-ZIP伪加密 最近在准备铁人三项赛的比赛,所以在实验吧上尝试着学习CTF,目前菜鸡一枚 我主要负责的是Web和安全杂项这一块,安全杂项的知识点较为薄弱,在实验吧练习的过程中遇到一个很有趣的题 ...