搭建第一個(gè)Netty應(yīng)用程序
本篇文章主要記錄如何搭建一個(gè)簡單的Netty服務(wù)器和客戶端。
依賴環(huán)境:
- Java 8
- Netty4
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.11.Final</version>
</dependency>
</dependencies>
編寫Echo服務(wù)器
所有的Netty服務(wù)器都需要以下兩個(gè)部分嗽仪。
- 至少一個(gè)ChannelHandler:用來處理業(yè)務(wù)邏輯
- 引導(dǎo):配置服務(wù)器啟動(dòng)代碼产舞,將服務(wù)器綁定到監(jiān)聽連接請(qǐng)求的端口上豁辉。
EchoServerHandler類:用來處理核心業(yè)務(wù)邏輯
@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext context, Object msg) {
ByteBuf in = (ByteBuf) msg;
System.out.println("server received: " + in.toString(CharsetUtil.UTF_8));
context.write(in);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext context, Throwable couse) {
couse.printStackTrace();
context.close();
}
}
EchoServer類:配置服務(wù)器屋确,并將入站消息通知給EchoServerHandler實(shí)例撮奏。
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
System.err.println("Usage: " + EchoServer.class.getSimpleName() + "<port>");
int port = 8999;
new EchoServer(port).start();
}
public void start() throws Exception{
final EchoServerHandler serverHandler = new EchoServerHandler();
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group).channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(serverHandler);
}
});
ChannelFuture future = b.bind().sync();
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
}
服務(wù)器主要的代碼組件
- EchoServerHandler實(shí)現(xiàn)業(yè)務(wù)邏輯
- main()引導(dǎo)服務(wù)器
引導(dǎo)過程:
- 創(chuàng)建一個(gè)ServerBootstap實(shí)例以引導(dǎo)和綁定服務(wù)器隅要;
- 創(chuàng)建并分配一個(gè)NioEventLoopGroup實(shí)例以進(jìn)行事件的處理报账,如接受新連接以及讀寫數(shù)據(jù)研底;
- 指定服務(wù)器綁定的本地的InetSocketAddress;
- 使用一個(gè)Handler實(shí)例初始化新的Channel透罢;
- 調(diào)用ServerBootstap.bind()方法以綁定服務(wù)器榜晦;
編寫Echo客戶端
Echo客戶端:
- 連接服務(wù)器
- 發(fā)送一個(gè)或多個(gè)消息
- 對(duì)于每個(gè)消息,等待并接受從服務(wù)器發(fā)回的相同的消息
- 關(guān)閉連接
ChannelHandler類:實(shí)現(xiàn)客戶端邏輯
- channelActive()和服務(wù)器建立連接后調(diào)用
- channelRead()從服務(wù)器接受到一條信息后調(diào)用
- exceptionCaught()處理過程中出現(xiàn)異常時(shí)被調(diào)用
@ChannelHandler.Sharable
public class EchoClientHandle extends SimpleChannelInboundHandler<ByteBuf>{
@Override
public void channelActive(ChannelHandlerContext context) {
context.writeAndFlush(Unpooled.copiedBuffer("Netty rocks", CharsetUtil.UTF_8));
}
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
System.out.println("Client received: " + byteBuf.toString(CharsetUtil.UTF_8));
}
@Override
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
cause.printStackTrace();
context.close();
}
}
EchoClient類:引導(dǎo)客戶端
public class EchoClient {
// 使用的是服務(wù)器的地址
private final String host;
private final int port;
public EchoClient(String host, int port) {
this.host = host;
this.port = port;
}
public void start() throws Exception{
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host, port))
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new EchoClientHandle());
}
});
ChannelFuture future = b.connect().sync();
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception {
new EchoClient("localhost", 8999).start();
}
}
GitHub地址:https://github.com/huangbuhuan/netty-demo
參考連接
- 《Netty In Action》