引言
前两天学习网络IO的知识,基于netty架构,利用jdk自带的Selector实现了简易的netty模型。今天翻了翻官网,参照大牛的课程,实操了一把netty的api,搭建了简易的server-client通讯模型。不得不说,从原理开始学习,再去调api,会有种得心应手的感觉。在此记录下,一是分享,二是复盘。
知识点
先备知识:NIO知识,响应式编程。
参照上篇《IO模型实战—实现Netty模型》,效果更佳。
代码&注解
创建服务端
public void nettyServer() throws InterruptedException {
// 事件环。 类似上篇《IO模型实战—实现Netty模型》中的SelectorThreadGroup
NioEventLoopGroup group = new NioEventLoopGroup(1);
// 设置服务端帮助类
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 设置服务端属性,返回连接对象
ChannelFuture connect = serverBootstrap.group(group)
// 设置channel为NioServerSocketChannel类
.channel(NioServerSocketChannel.class)
// 服务端必须有childHandler
// 过渡对象,可以通过其个性化多个自己的handler
.childHandler(new ChannelInitializer<NioSocketChannel>() {
// 回调事件处理方法
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
ChannelPipeline pipeline = nioSocketChannel.pipeline();
// 个性化的handler
pipeline.addLast(new MyHandler());
}
})
// 绑定url及端口
.bind(new InetSocketAddress("192.168.137.1", 9999));
// 保证异步的连接建立成功后执行
connect.sync().channel().closeFuture().sync();
}
创建客户端
public void nettyClient() throws InterruptedException {
// 事件环。 类似上篇《IO模型实战—实现Netty模型》中的SelectorThreadGroup
NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(1);
// 设置客户端帮助类
Bootstrap bs = new Bootstrap();
// 设置客户端,返回连接对象
ChannelFuture channel = bs.group(nioEventLoopGroup)
// 设置channel为NioSocketChannel类
.channel(NioSocketChannel.class)
// 绑定回调处理器handler
// 过渡对象,可以通过其个性化多个自己的handler
.handler(new ChannelInitializer<SocketChannel>() {
// 回调事件处理方法
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
// 个性化的handler
pipeline.addLast(new MyHandler());
}
})
// 绑定url及端口
.connect(new InetSocketAddress("192.168.137.1", 9999));
// 获取客户端channel
Channel client = channel.channel();
// IO数据载体,底层数组
ByteBuf buf = Unpooled.copiedBuffer("hi, I am client".getBytes());
// 异步发送返回对象
ChannelFuture send = client.writeAndFlush(buf);
// 保证异步发送成功释放
send.sync();
// 保证异步连接建立成功后释放
client.closeFuture().sync();
}
自定义handler
class MyHandler extends ChannelInboundHandlerAdapter {
// 连接注册事件处理
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("client registed...");
}
// 连接建立成功事件
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("client active...");
}
// 读数据事件
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
CharSequence str = buf.getCharSequence(0,buf.readableBytes(), CharsetUtil.UTF_8);
ctx.writeAndFlush(buf);
}
}
实验
实验目的
验证server和client能启动并互相发送数据
实验步骤
依次启动server端和client端
实验结果
server端
client registed...
client active...
hi, I am client
hi, I am client
client端
client registed...
client active...
hi, I am client
hi, I am client