客服端的创建,与服务器端比较相似。所不同的是:
1、客户端只需要1个NioEventLoopGroup,服务器端需要2个;
2、客户端启动引导器使用的是Bootstap,服务器端使用的是ServerBootstrap;
3、客户端的Channel类型是NioSocketChannel,服务器使用的是NioServerSocketChannel;
4、客户端的Channel初始化方法是handler(),服务器端所使用的是childHandler();
5、客户端的bind需要传入服务器的host和port,服务器端只需传入port。
下面介绍下客户端的实现过程
一、创建一个客户端处理器
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyClientHandHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
}
/**
* 通道准备就绪时触发
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String message = "Hello, I'm client.";
ctx.writeAndFlush(Unpooled.copiedBuffer(message.getBytes()));
}
}
里边提到一个类Unpooled(属于非池化的ByteBuf)和一个方法writeAndFlush,这里简单介绍下:
- Unpooled创建非池化的ByteBuf,并将message转换为字节数组,通过writeAndFlush方法将字节数组写入到SocketChannel中。
- Unpooled适用于小数据量的写操作,如发送少量的文本消息。适用于快速创建ByteBuf对象并快速销毁缓冲区的场景。
- writeAndFlush包含了将消息写入到缓冲区、刷新缓冲区、将消息从缓冲区写入到
- SocketChannel的过程。
- write:将ByteBuf中的内容写入到SocketChannel的缓冲区ChannelOutboundBuffer中。
- flush:将SocketChannel的缓冲区中的内容刷新到SocketChannel中。
二、创建客户端
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@Slf4j
public class NettyClient {
@Value("${netty.server.host}")
private String host;
@Value("${netty.server.port}")
private int port;
private NioEventLoopGroup eventLoopGroup;
private Channel channel;
/**
* 启动Netty客户端
*/
public void start() {
eventLoopGroup = new NioEventLoopGroup();
// 创建客户端引导器Bootstrap,用于完成Netty整个程序的组件初始化,启动,服务器连接
Bootstrap serverBootstrap = new Bootstrap();
serverBootstrap.group(eventLoopGroup)
// 设置ServerSocketChannel的处理器为NioSocketChannel
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<>() {
// 给每个客户端连接都创建一个ChannelInitializer,用于初始化Channel,添加ChannelHandler
@Override
protected void initChannel(Channel channel) throws Exception {
//取出channelPipeline
ChannelPipeline pipeline = channel.pipeline();
// 添加ChannelHandler
pipeline.addLast(new MyClientHandHandler());
}
});
ChannelFuture future = null;
try {
//绑定地址和端口,启动客户端
future = serverBootstrap.connect(host,port).sync();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
// 关闭EventLoopGroup,释放资源
if (eventLoopGroup != null) {
eventLoopGroup.shutdownGracefully();
}
if (channel != null) {
channel.closeFuture();
}
}
if (future.isSuccess()) {
log.info("Netty服务器启动成功......");
}
}
/**
* 关闭前释放资源
*/
@PreDestroy
public void destroy() {
try {
// 关闭EventLoopGroup,释放资源
if (eventLoopGroup != null) {
eventLoopGroup.shutdownGracefully().sync();
}
if (channel != null) {
channel.closeFuture().sync();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
2万+

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



