前言
现在,我们开始编写一个最简单的Netty示例,在这之前我们先熟悉一下最基本的编码实现步骤!
Netty实现通信的步骤:(客户端与服务器端基本一致)
- 创建两个的NIO线程组,一个专门用于网络事件处理(接受客户端的连接),另一个则进行网络通信读写。
- 创建一个ServerBootstrap对象,配置Netty的一系列参数,例如接受传出数据的缓存大小等等。
- 创建一个实际处理数据的类ChannelInitializer,进行初始化的准备工作,比如设置接受传出数据的字符集、格式、已经实际处理数据的接口。
- 绑定端口,执行同步阻塞方法等待服务器端启动即可。
Netty的使用非常简单,仅仅引入依赖即可快速开始:
1 2 3 4 5
| <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.12.Final</version> </dependency>
|
Netty Server
Netty Server端需要编写 Server 与 ServerHandler两个核心类!
Server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class Server {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) .option(ChannelOption.SO_BACKLOG, 1024) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_RCVBUF, 1024 * 32) .childOption(ChannelOption.SO_SNDBUF, 1024 * 32) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ServerHandler()); } });
ChannelFuture cf = b.bind(8765).sync(); cf.channel().closeFuture().sync();
bossGroup.shutdownGracefully(); workGroup.shutdownGracefully();
} }
|
ServerHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.err.println("server channel active.."); }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg; byte[] request = new byte[buf.readableBytes()]; buf.readBytes(request); String requestBody = new String(request, "utf-8"); System.err.println("Server: " + requestBody);
String responseBody = "返回响应数据," + requestBody; ctx.writeAndFlush(Unpooled.copiedBuffer(responseBody.getBytes()));
}
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.fireExceptionCaught(cause); }
}
|
Netty Client
Netty Client端需要编写 Client与 ClientHandler两个核心类!
Client
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class Client { public static void main(String[] args) throws InterruptedException { EventLoopGroup workGroup = new NioEventLoopGroup(); Bootstrap b = new Bootstrap(); b.group(workGroup) .channel(NioSocketChannel.class) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) .option(ChannelOption.SO_RCVBUF, 1024 * 32) .option(ChannelOption.SO_SNDBUF, 1024 * 32) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ClientHandler()); } }); ChannelFuture cf = b.connect("127.0.0.1", 8765).syncUninterruptibly();
cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty!".getBytes())); Thread.sleep(1000); cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty again!".getBytes()));
cf.channel().closeFuture().sync(); workGroup.shutdownGracefully(); } }
|
ClientHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class ClientHandler extends ChannelInboundHandlerAdapter {
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.err.println("client channel active.."); }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req);
String body = new String(req, "utf-8"); System.out.println("Client :" + body ); String response = "收到服务器端的返回信息:" + body; } finally { ReferenceCountUtil.release(msg); } }
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.fireExceptionCaught(cause); } }
|
结果

客户端向服务端发送数据

客户端收到服务端返回的数据