1.目录结构
maven依赖 pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>NettyIntroduction</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.8.Final</version> </dependency> </dependencies> <!--maven编译插件--> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <showWarnings>true</showWarnings> </configuration> </plugin> </plugins> </build> </project>
2.客户端和服务器端都有一个自定义Handler类继承ChannelInboundHandlerAdapter
3.服务器端处理类
NettyServerHandler.java
package cn.cmdzz.netty.introduction; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; /** * 处理服务器端的业务 * */ //找到父类方法快捷键:ctrl+o public class NettyServerHandler extends ChannelInboundHandlerAdapter { /** * 读取数据事件 * @param ctx * @param msg 消息 * @throws Exception */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Server ctx:"+ctx); ByteBuf buf = (ByteBuf) msg; System.out.println("客户端发来的消息:"+buf.toString(CharsetUtil.UTF_8)); } /** * 数据读取完毕事件 * @param ctx * @throws Exception */ @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //创建一个缓冲区写入字符串返回 Unpooled.copiedBuffer("我是服务器端",CharsetUtil.UTF_8) ctx.writeAndFlush(Unpooled.copiedBuffer("我是服务器端",CharsetUtil.UTF_8)); } /** * 异常发生事件 * @param ctx * @param t * @throws Exception */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception { //异常发生时关闭一下 ctx.close(); } }
4.服务器类
NettyServer.java
package cn.cmdzz.netty.introduction; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * 服务器端 */ public class NettyServer { public static void main(String[] args) throws Exception{ //1.创建一个线程数组,接受客户端连接 EventLoopGroup bossGroup = new NioEventLoopGroup(); //2.创建一个线程数组,处理网络操作 EventLoopGroup workerGroup = new NioEventLoopGroup(); //3.创建服务器端启动助手来配置参数 ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup,workerGroup)//设置两个线程数组 .channel(NioServerSocketChannel.class)//使用NioServerSocketChannel作为服务器端通道的实现 .option(ChannelOption.SO_BACKLOG,128)//设置线程队列中等待连接的个数 .childOption(ChannelOption.SO_KEEPALIVE,true)//保持活动连接状态 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception {//初始化通道 socketChannel.pipeline().addLast(new NettyServerHandler());//把自定义Handler加入管道 } }); System.out.println("........Server is ready..........."); ChannelFuture cf = bootstrap.bind(9999).sync();//绑定端口 非阻塞 System.out.println("......Server is starting.........."); //关闭通道 关闭线程组 cf.channel().closeFuture().sync();//异步 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
5.客户端处理类
NettyClientHandler.java
package cn.cmdzz.netty.introduction; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.CharsetUtil; /** * 处理客户端业务 */ public class NettyClientHandler extends ChannelInboundHandlerAdapter { //通道就绪事件 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client ctx:"+ctx); ctx.writeAndFlush(Unpooled.copiedBuffer("服务器,我是客户端", CharsetUtil.UTF_8)); } //读服务器返回的数据 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; System.out.println("服务器端发来的消息:"+buf.toString(CharsetUtil.UTF_8)); } }
6.客户端类
NettyClient.java
package cn.cmdzz.netty.introduction; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; /** * 客户端 */ public class NettyClient { public static void main(String[] args) throws Exception{ //创建一个线程组 EventLoopGroup group = new NioEventLoopGroup(); //创建客户端的启动助手,完成相关配置 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) //设置线程组 .channel(NioSocketChannel.class)//设置客户端通道的实现类 .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new NettyClientHandler());//往Pipeline链中添加自定义的handler } }); System.out.println("......client ready......"); //启动客户端连接服务器 ChannelFuture cf = bootstrap.connect("127.0.0.1",9999).sync(); System.out.println(".........client starting....."); //关闭连接 cf.channel().closeFuture().sync(); } }
7.控制台输出
client
server
原文:https://www.cnblogs.com/cmdzhizhu/p/12798014.html