您的位置:首页 > 其它

Netty系列:二、第一个Netty程序

2018-03-05 18:52 316 查看

不正经的开头

本文首先会介绍Netty的基本API,然后在实现一个小应用,那我们开始吧,是不是有点小激动呢 [滑稽]

本文主要从以下几个方面:

ChannelHandler
的作用和它的方法

服务端编写

Handler

BootStrap

客户端的编写

Handler

BootStrap

运行结果

1.
ChannelHandler
的API

之前我们也介绍过了ChannelHandler,此处详细介绍它的方法以及用途。它是一个接口,它的实现负责接收并响应事件。

我们比较常用的是
ChannelInboundHandlerAdapter
它是一个实现了
ChannelHandler
接口的类,一般也够我们用了,当然可以自己写一个类继承它,扩充自己的功能。

一些常用的方法:

channelRead()
对于每个传入的消息都要调用

channelReadComplete()
通知
ChannelInboundHandler
最后一次对
channelRead()
的调用时是当前批次中的最后一条消息

exceptionCaught()
读取操作期间,抛出异常时调用

再说一次,
ChannelHandler
负责接收并响应事件,即来了一个事件,它执行对应的方法。哎妈呀,我太机智了~

2.服务端编写

有了上面的基础就可以开始了

一个小插曲:Netty服务器结构

至少一个
ChannelHandler
:该组件实现了服务器接收的数据的处理,即它的业务逻辑

引导:这是配置服务器的启动代码。将服务器绑定到他要监听链接请求的端口上,配置Channel,将有关的消息通知给
ChannelHanler


Server端代码:

public class ServerDemo {
private int prot;
public ServerDemo(int prot) {
this.prot = prot;
}
public static void main(String[] args) throws InterruptedException {
new ServerDemo(9111).satart();
}

public void satart() throws InterruptedException {
final ServerHandller serverHandller = new ServerHandller();
//创建ServerBootstrap实例
ServerBootstrap boot = new ServerBootstrap();
//创建一个EventLoopGroup
EventLoopGroup group =  new NioEventLoopGroup();
//指定实例来接受和处理新的连接。
boot.group(group)
//指定使用NIO Channel传输
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(prot))
//当一个新的连接被接受时,一个新的子Channel会被创建,
// ChannelInitializer会把serverHandller的实例加入到该Channel的ChannelPipeLine
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(serverHandller);
}
});
try {
//异步绑定到服务器,调用sync方法阻塞当前线程,直到绑定完成
ChannelFuture future = boot.bind().sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
group.shutdownGracefully().sync();
}
}
}


ServerHandler代码:

public class ServerHandller extends ChannelInboundHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext ctx, Object o) {
ByteBuf in = (ByteBuf)o;
System.out.println("Server Receive:"+in.toString(CharsetUtil.UTF_8));
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.writeAndFlush((Unpooled.copiedBuffer("Thanks ~", CharsetUtil.UTF_8)));
/*ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);*/
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}


总结一下

ServerHandler
实现了业务逻辑

创建
ServerBootStrap
实例,引导以及绑定服务器

创建
EventLoopGroup
实例,进行事件的处理,如连接、读取、写入

用一个
ServerHandler
实例初始化每一个新的Channel

3.客户端

编写客户端也包括业务逻辑和引导,和服务器中一样。

3.1.
ChannelHandler
实现客户端的业务逻辑


介绍一个抽象类
SimpleChannelInboundHandler
,有点和
ChannelInboundHandlerAdapter
类似,它可以用来处理客户的业务逻辑。直接上代码

public class ClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
//当被通知Channel是活跃的时候,发送一条消息
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer("Netty is No.1", CharsetUtil.UTF_8));
}
@Override
//接收消息时会调用该方法
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("Client Recived:"+msg.toString(CharsetUtil.UTF_8));
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}


3.3.客户端

public class ClientDemo {
private final String host = "127.0.0.1";
private final int port = 9999;
public void start() throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
//创建Bootstrap
Bootstrap bootstrap = new Bootstrap();
try {
//指定EventLoopGroup处理客户端事件
bootstrap.group(group)
//适用于Nio传输的Channel类型
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host, port))
//在创建Chann时,向ChannelPipeline添加一个ClientHandler实例
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientHandler());
}
});

//连接到服务器,阻塞直到连接完成
ChannelFuture future = bootstrap.connect().sync();
//阻塞到Channel关闭
future.channel().closeFuture().sync();
}catch (Exception e) {
e.printStackTrace();
}finally {
//关闭线程池并释放资源
group.shutdownGracefully().sync();
}
}

public void main(String args[]) throws Exception {
new ClientDemo().start();
}

}


总结一下

实例化了
NioEventLoopGroup
实例,被用来处理创建新的连接以及数据的出入

实例化
InetSocketAddress
用来连接到服务器

当有连接建立,
ClientHandler
的实例会被加到
ChannelPipeline


正式连接到服务器
Bootstrap.connect()


运行结果

Server端输出:
Server Receive:Netty is No.1


Client端输出:
Client Recived:Thanks ~


下一篇:http://blog.csdn.net/theludlows/article/details/79463635
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: