pom
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0.0.Alpha2</version> </dependency>
Server服务端
package com.lzh.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by 敲代码的卡卡罗特 * on 2018/8/12 17:31. */ public class Server { public static void main(String[] arg){ //服务类 ServerBootstrap b = new ServerBootstrap(); //boss线程监听端口,worker线程负责数据读写 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); b = b.group(bossGroup,workerGroup); b = b.option(ChannelOption.SO_BACKLOG, 128); b = b.childOption(ChannelOption.SO_KEEPALIVE, true); //设置niosocket工厂 b.channel(NioServerSocketChannel.class); b.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new MyServerHandler());// } }); try { //绑定端口并启动去接收进来的连接 ChannelFuture f = b.bind(8888).sync(); // 这里会一直等待,直到socket被关闭 f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { /*** * 优雅关闭 */ workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
服务端的处理类
package com.lzh.netty; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.util.CharsetUtil; import java.util.Date; /** * Created by 敲代码的卡卡罗特 * on 2018/8/12 21:21. */ public class MyServerHandler extends ChannelHandlerAdapter { /*** * 这里我们覆盖了chanelRead()事件处理方法。 * 每当从客户端收到新的数据时, * 这个方法会在收到消息时被调用, * 这个例子中,收到的消息的类型是ByteBuf * @param ctx 通道处理的上下文信息 * @param msg 接收的消息 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{ //读取客户端发来的信息 ByteBuf m = (ByteBuf) msg; // ByteBuf是netty提供的 System.out.println("client:"+m.toString(CharsetUtil.UTF_8)); //2两种打印信息的方法。都可以实现 /* byte[] b=new byte[m.readableBytes()]; m.readBytes(b); System.out.println("client:"+new String(b,"utf-8"));*/ //向客户端写信息 String name="你好客户端:这是服务端返回的信息!"; ctx.writeAndFlush(Unpooled.copiedBuffer(name.getBytes())); } /*** * 这个方法会在发生异常时触发 * @param ctx * @param cause */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { /*** * 发生异常后,关闭连接 */ cause.printStackTrace(); ctx.close(); } }
Client客户端
package com.lzh.netty; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; 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.NioSocketChannel; /** * Created by 敲代码的卡卡罗特 * on 2018/8/12 21:46. */ public class Client { public static void main(String[] arg){ /** * 如果你只指定了一个EventLoopGroup, * 那他就会即作为一个‘boss’线程, * 也会作为一个‘workder’线程, * 尽管客户端不需要使用到‘boss’线程。 */ Bootstrap b = new Bootstrap(); // (1) EventLoopGroup workerGroup = new NioEventLoopGroup(); b.group(workerGroup); // (2) b.channel(NioSocketChannel.class); // (3) b.option(ChannelOption.SO_KEEPALIVE, true); // (4) b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new MyClientHandler()); } }); try { ChannelFuture f = b.connect("127.0.0.1", 8888).sync(); //向服务端发送信息 f.channel().writeAndFlush(Unpooled.copiedBuffer("你好".getBytes())); f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { workerGroup.shutdownGracefully(); } } }
客户端的处理类
package com.lzh.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; /** * Created by 敲代码的卡卡罗特 * on 2018/8/12 21:49. */ public class MyClientHandler extends ChannelHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{ try { //读取服务端发来的信息 ByteBuf m = (ByteBuf) msg; // ByteBuf是netty提供的 System.out.println("client:"+m.toString(CharsetUtil.UTF_8)); } catch (Exception e) { e.printStackTrace(); } finally { //当没有写操作的时候要把msg给清空。如果有写操作,就不用清空,因为写操作会自动把msg清空。这是netty的特性。 ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }
netty有许多坑,建议你们多看官方文档
推荐:https://ifeve.com/netty5-user-guide/