简述
编写一个简单的 netty 实现的客户端和服务端程序,以及知悉其流程
服务端
package cn.inetty.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
// 使用 netty 实现服务器和客户端
public class HelloServer {
public static void main(String[] args) {
// 1. ServerBootstrap 是一个服务器启动器 负责组装 netty 组件并启动服务器
new ServerBootstrap()
// 2. 包含 BossEventLoop 和 WorkerEventLoop(selector, thread)
.group(new NioEventLoopGroup())
// 3. 选择 NioServerSocketChannel 实现作为服务器通道
.channel(NioServerSocketChannel.class)
// 4. netty 提供了 很多 handler 这些 handler 提供不同的功能 通过 childHandler 添加 handler 的方式可以决定 worker 处理那些事情
.childHandler(
// 5. ChannelInitializer 用于初始化通道并负责添加 handler 通道可以和客户端进行数据读写
new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nch) throws Exception {
// 6. 添加具体的 handler
nch.pipeline().addLast(new StringDecoder()); // StringDecoder 将 ByteBuf 转换成 String
// 7. 自定义了一个 handler
nch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
// 触发读事件
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 打印 StringDecoder 转换的字符串
System.out.println(msg);
}
});
}
})
// 8. 绑定 NioServerSocketChannel 的监听端口
.bind(8888);
}
}
客户端
package cn.inetty.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import java.net.InetSocketAddress;
public class HelloClient {
public static void main(String[] args) throws InterruptedException {
// 1. 启动类
new Bootstrap()
// 2. 添加 EventLoop
.group(new NioEventLoopGroup())
// 3. 选择 channel 实现
.channel(NioSocketChannel.class)
// 4. 添加 handler
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override // initChannel 在建立连接时被调用
protected void initChannel(NioSocketChannel nsc) throws Exception {
nsc.pipeline().addLast(new StringEncoder());
}
})
// 5. 连接到服务器
.connect(new InetSocketAddress("localhost", 8888))
.sync() // 阻塞方法 等待连接建立
.channel() // 连接对象
// 6 向服务器发送数据
.writeAndFlush("hello, netty");
}
}