Netty教程系列(一)——netty入门应答程序
来源:互联网 发布:mac输入法下载安装 编辑:程序博客网 时间:2024/05/16 06:10
Netty简介
Netty是一个异步通信、事件驱动基于NIO编写的高性能高并发的java网络编程框架。下面通过一个简单的服务器应答程序来完成Netty的初步学习。
代码地址:https://code.csdn.net/luo4105/study_netty/
Netty的编程例子——应答程序
设置开发环境
Jdk1.8
Mvn配置
<dependencies> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.12.Final</version> </dependency></dependencies>
应答服务器
一个Netty服务器主要有三个部分组成
l 服务器配置,配置端口、操作线程池等。
l 通道初始程序,传输的编解码格式、粘包处理、通道处理程序的调用。
l 实现通道处理程序,它包含业务逻辑,即实现服务器通道发生连接、读取信息等事件时的处理。
启动服务器
通过创建SerserBootstrap对象来启动服务器,然后配置对象的相关属性,如端口、线程模式、处理程序等。
import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel; public classHelloServer { private static final int protNumner= 7878; public static void main(String[] args) throws InterruptedException { // 事件循环组 /* * Main函数开始的位置定义了两个工作线程,一个命名为WorkerGroup,另一个命名为BossGroup。 * 都是实例化NioEventLoopGroup。这一点和3.x版本中基本思路是一致的。Worker线程用于管理线程为Boss线程服务。 * EventLoopGroup,它是4.x版本提出来的一个新概念。类似于3.x版本中的线程。用于管理Channel连接的。 * 在main函数的结尾就用到了EventLoopGroup提供的便捷的方法,shutdownGraceFully(), * 翻译为中文就是优雅的全部关闭。 */ EventLoopGroupbossGroup= newNioEventLoopGroup(); EventLoopGroupworkerGroup= newNioEventLoopGroup(); /* ServerBootstrap负责初始化netty服务器,并且开始监听端口的socket请求 */ ServerBootstrapb = new ServerBootstrap(); b.group(bossGroup, workerGroup); b.channel(NioServerSocketChannel.class); b.childHandler(newHelloServerInitializer()); // 服务器绑定端口监听 ChannelFuturef = b.bind(protNumner).sync(); // 监听服务器关闭监听 f.channel().closeFuture().sync(); }}
通道的初始化程序
初始化程序可以加上编解码、消息分割(粘包)、业务处理程序等。这些设置都是通过ChannelPipeline.addLast()来实现的。
import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.Delimiters;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder; public classHelloServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected voidinitChannel(SocketChannel ch) throwsException { ChannelPipelinepipeline= ch.pipeline(); // 以("\n")为结尾分割的解码器,最大帧长度为8192 // Delimiter Based Frame Decoder 基于定界符的帧解码器 // Delimiters.lineDelimiter()行分隔符 // 这里使用时,会把换行符作为一个消息的分隔界限使用,即接收时,换行符前为一条消息 pipeline.addLast("framer",newDelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); // 字符串解码和编码 // encoder 编码器, decoder 解码器 pipeline.addLast("decoder",newStringDecoder()); pipeline.addLast("encoder",newStringEncoder()); // 自己的逻辑Handler pipeline.addLast("handler",newHelloServerHandler()); }}
通道的业务处理程序
处理程序是事件驱动的,用于监控服务器事件的产生,自定义事件的处理。
import java.net.InetAddress; import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler; public classHelloServerHandler extends SimpleChannelInboundHandler<String> { @Override protected voidchannelRead0(ChannelHandlerContext ctx, String msg)throwsException { // 收到消息直接打印输出 System.out.println(ctx.channel().remoteAddress()+ " Say : "+ msg); // 返回客户端信息 - 我已经接收到了你的消息 // writeAndFlush写消息并发送 ctx.writeAndFlush("received your message !\n"); } // 当Channel变成活跃状态时被调用 public voidchannelActive(ChannelHandlerContext ctx) throwsException { System.out.println("RamoteAddress : "+ ctx.channel().remoteAddress()+ " active !"); ctx.writeAndFlush("welcome to "+ InetAddress.getLocalHost().getHostName() + " server.\n"); super.channelActive(ctx); }}
SimpleChannelInboundHandler这里实现事件处理,ChannelRead0是读取数据事件,channelActive是通道连接事件。
除了以上事件,还有如下事件
void channelInactive(ChannelHandlerContextctx) 连接中断时,调用它
void userEventTriggered(ChannelHandlerContext ctx, Object evt) 如果触发了用户事件,将调用它。
void channelWritabilityChanged(ChannelHandlerContextctx) 一旦更改了{连接信道}的可写状态,就调用。您可以检查状态
void exceptionCaught(ChannelHandlerContextctx, Throwable cause) 如果抛出异常,将调用它。
在writeAndFlush后要接”\n”,pipeline设置的是通过换行符来分割信息。
编写应答程序客户端
一个客户端程序主要有三部分组成,与服务器类似
l 连接服务器,配置服务器的ip、端口,创建服务器连接通道对象,向服务器发送数据
l 通道初始程序,传输的解编码格式、粘包处理、通道处理程序的调用。
l 实现通道处理程序,它包含业务逻辑,即实现客户端通道发生连接、读取信息等事件时的处理。
连接服务器
Netty4通过Bootstrap来创建通道连接对象Channel,通过Channel的writeAndFlush来向服务器发送数据。
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; import io.netty.bootstrap.Bootstrap;import io.netty.channel.Channel;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioSocketChannel; /** * netty客户端 * * @author逝兮诚 * @date 2017年6月26日下午5:37:23 * */public classHelloClient { public static String host = "127.0.0.1"; public static int port = 7878; public static void main(String[] args) throws IOException,InterruptedException { EventLoopGroupgroup= newNioEventLoopGroup(); Bootstrapb = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).handler(newHelloClientInitializer()); // 连接服务端 Channelch = b.connect(host, port).sync().channel(); // 控制台输入 BufferedReaderin = new BufferedReader(newInputStreamReader(System.in)); for (;;) { Stringline= in.readLine(); if (line == null) continue; ch.writeAndFlush(line + "\r\n"); } }}
通道的初始化设置程序
初始化设置程序同服务器一样,便不再过多累述。
import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.Delimiters;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder; public classHelloClientInitializer extends ChannelInitializer<SocketChannel> { @Override protected voidinitChannel(SocketChannel ch) throwsException { ChannelPipelinepipeline= ch.pipeline(); pipeline.addLast("framer",newDelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder",newStringDecoder()); pipeline.addLast("encoder",newStringEncoder()); // 客户端的逻辑 pipeline.addLast("handler",newHelloClientHandler()); }}
通道的业务处理程序
客户端的连接通道的业务处理程序与服务器类似,就不再过多累述。
import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler; public classHelloClientHandler extends SimpleChannelInboundHandler<String> { @Override protected voidchannelRead0(ChannelHandlerContext ctx, String msg)throwsException { System.out.println("Server say : "+ msg); } @Override public voidchannelActive(ChannelHandlerContext ctx) throwsException { System.out.println("Client active "); super.channelActive(ctx); } @Override public voidchannelInactive(ChannelHandlerContext ctx) throwsException { System.out.println("Client close "); super.channelInactive(ctx); }}
运行结果
客户端
服务端
- Netty教程系列(一)——netty入门应答程序
- Netty学习总结(1)——Netty入门介绍
- netty开发教程(一)
- Netty(一) 简单入门
- Netty系列-NIO入门
- netty学习系列(一)netty初体验
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- Java NIO框架Netty教程(一) – Hello Netty
- CSDN日报20170627——《回眸后那流泪的脸——从高考到程序猿》
- 在eclipse中删除原有的tomcat7之后再新建tomcat7的时候发现新建不了的解决办法
- mac下查看.mobileprovision文件
- 门描述符(gate descriptors)总结
- Cglib的动态代理
- Netty教程系列(一)——netty入门应答程序
- response.setContentType和request.setCharacterEncoding()区别
- OkHttp报错javax.net.ssl.SSLHandshakeException: Handshake failed
- Hyperledger Fabric1.0架构概览
- 如何使用控制台安装mysql-5.6.17-win32?
- linux dump_stack
- 遮蔽元素和去除遮蔽
- change()事件及val()/html()方法不会触发change事件
- 用正则表达式进行复杂密码校验