先介绍Netty的主要构件
Channel:
代表一个到实体的开放连接,如读操作和写操作,可以把Channel看做传入和传出的数据载体
Future:
提供了一种在操作完成时通知应用程序的方式,这个对象可以看做是一个异步操作结果的占位符。它将在未来的某个时刻完成,并提供对其结果的访问。Netty提供了channelFuture,用于执行异步操作
ChannelHandler:
它是一个接口族的父接口,它的实现负责接收并相应事件通知
服务器的ChannelHandler
package com;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
//标记一个channelHandler可以被多个Channel安全的共享
@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
//对于每个传入的消息都要调用
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg){
ByteBuf in = (ByteBuf) msg;
System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));
//将接受到的消息写给发送者,而不冲刷出站消息
ctx.write(in);
}
//通知ChannelInboundHandler最后一次对channelRead()的调用是当前批量读取中的最后一条消息
@Override
public void channelReadComplete(ChannelHandlerContext ctx){
//将未决消息冲刷到远程节点并且关闭该Channel
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) {
cause.printStackTrace();;
ctx.close();
}
}
服务器
package com;
import io.netty.bootstrap.ServerBootstrap;
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.NioServerSocketChannel;
import java.net.InetSocketAddress;
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
int port = 9999;
new EchoServer(port).start();
}
public void start() throws Exception {
//@Shareable标记总是使用同样的实例
final EchoServerHandler serverHandler = new EchoServerHandler();
EventLoopGroup group = new NioEventLoopGroup();
try{
ServerBootstrap b = new ServerBootstrap();
b.group(group)
//指定所使用的NIO传输Channel
.channel(NioServerSocketChannel.class)
//使用指定的端口是指套接字地址
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception{
ch.pipeline().addLast(serverHandler);
}
});
//异步绑定服务器,调用sync方法阻塞等待直到绑定完成
ChannelFuture f = b.bind().sync();
//获取Channel的closeFuture并且阻塞当前线程直到它完成
f.channel().closeFuture().sync();
} finally {
//关闭EventLoopGroup释放所有的资源
group.shutdownGracefully().sync();
}
}
}
客户端的ChannelHandler
package com;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;
@ChannelHandler.Sharable
public class EchoClientHandler extends
SimpleChannelInboundHandler<ByteBuf> {
//在到服务器的连接已经建立之后将被调用
@Override
public void channelActive(ChannelHandlerContext ctx){
ctx.writeAndFlush(Unpooled.copiedBuffer("Neety rocks!",
CharsetUtil.UTF_8));
}
//当从服务器接收到一条消息时被调用
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf in) throws Exception {
System.out.println(
"Client received: " + in.toString(CharsetUtil.UTF_8)
);
}
//在处理过程中引发异常时被调用
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
客户端
package com;
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;
import java.net.InetSocketAddress;
public class EchoClient {
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
public void initChannel(SocketChannel ch) throws Exception{
ch.pipeline().addLast(
new EchoClientHandler()
);
}
});
ChannelFuture f = b.connect().sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception{
String host = "localhost";
int port = 9999;
new EchoClient(host, port).start();
}
}
575

被折叠的 条评论
为什么被折叠?



