Netty 4.x 實戰詳解
目前Netty的最新穩定版本是 Netty 4.1.9, 本文根據該版本進行開發介紹。
-
- Netty 4x 實戰詳解
- 開發前準備工作
- 代碼實作
- 一 伺服器
- 1伺服器啟動邏輯DemoServerjava
- 2伺服器Channel通道初始化設定ServerChannelInitializer java
- 3伺服器業務邏輯DemoServerHandlerjava
- 二 用戶端
- 1用戶端啟動邏輯DemoClientjava
- 2用戶端Channel通道初始化設定ClientChannelInitializer java
- 3用戶端業務邏輯DemoClientHandlerjava
- 運作結果
- 參考書籍Netty in action 和 Netty 權威指南
- Netty 4x 實戰詳解
開發前準備工作:
- 到Netty官網(http://netty.io/downloads.html),下載下傳開始所需的Netty包:netty-all-4.1.9.Final.jar;
- 安裝Java開發環境,這裡使用的是Jdk8;
- 這裡使用的編輯器是Intellij IDEA,也可以根據自己的喜好,選擇其他的,比如Eclipse等。
接下來,我們用Netty實作一個demo。主要功能如下:
- 1、服務端啟動,等待接受用戶端的連接配接和處理請求;
- 2、用戶端啟動和服務端建立連接配接,伺服器傳回“連接配接成功!”;
- 3、用戶端和伺服器進行資料傳輸操作。
代碼實作
一、 伺服器
1、伺服器啟動邏輯(DemoServer.java)
package server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* 伺服器啟動邏輯
*/
public class DemoServer {
public static void main(String[] args) throws Exception {
int port = ;
if (args != null && args.length > ) {
try {
port = Integer.valueOf(args[]);
} catch (NumberFormatException e) {
//采用預設值
}
}
new DemoServer().bind(port);
}
public void bind(int port) throws Exception {
//配置服務端的NIO線程組
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, )
.childHandler(new ServerChannelInitializer());
//綁定端口,同步等待成功
ChannelFuture f = b.bind(port).sync();
//等待伺服器監聽端口關閉
f.channel().closeFuture().sync();
} finally {
//優雅退出,釋放線程池資源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
2、伺服器Channel通道初始化設定(ServerChannelInitializer .java)
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
* 伺服器Channel通道初始化設定
*/
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//字元串解碼和編碼
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
//伺服器的邏輯
pipeline.addLast("handler", new DemoServerHandler());
}
}
3、伺服器業務邏輯(DemoServerHandler.java)
package server;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.net.Inet4Address;
/**
* 伺服器業務邏輯
*/
public class DemoServerHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("Client say : " + msg.toString());
//傳回用戶端消息 - 我已經接收到了你的消息
ctx.writeAndFlush("Received your message : " + msg.toString());
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("RemoteAddress : " + ctx.channel().remoteAddress() + " active !");
ctx.writeAndFlush("連接配接成功!");
super.channelActive(ctx);
}
}
二、 用戶端
1、用戶端啟動邏輯(DemoClient.java)
package client;
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;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* 用戶端啟動邏輯
*/
public class DemoClient {
public static String host = "127.0.0.1"; //伺服器IP位址
public static int port = ; //伺服器端口
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ClientChannelInitializer());
//連接配接用戶端
Channel channel = b.connect(host, port).sync().channel();
//控制台輸入
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
continue;
}
//向服務端發送資料
channel.writeAndFlush(line);
}
} finally {
//優雅退出,釋放線程池資源
group.shutdownGracefully();
}
}
}
2、用戶端Channel通道初始化設定(ClientChannelInitializer .java)
package client;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
* 用戶端Channel通道初始化設定
*/
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//字元串解碼和編碼
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
//用戶端的邏輯
pipeline.addLast("handler", new DemoClientHandler());
}
}
3、用戶端業務邏輯(DemoClientHandler.java)
package client;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* 用戶端業務邏輯
*/
public class DemoClientHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("Server say : " + msg.toString());
}
}
運作結果
- 先啟動伺服器,再啟動用戶端。
- 在用戶端的控制台輸入“服務端,你好!”,然後按“Enter”鍵,将資料發送到服務端。