Netty 是什么?
先看看官网这段“英格力士”
Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients.
Netty 是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端
现在,用netty开发一个简单的服务器端和客户端,实现客户端发送消息给服务端,服务端收到之后反馈给客户端。
首先构建一个maven项目,名字自己随便取就行,构建好了之后再pom.xml引入依赖:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.39.Final</version>
</dependency>
创建NettyServer启动类
import com.niit.sky.serverHandler.ServerChildHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
/**
* @author Sky.yu
* @ClassName NettyServer.java
* @Description 服务器启动类
* @createTime 2022-08-13 12:44
**/
@Slf4j
public class NettyServer {
private final Integer PORT;
public NettyServer(Integer port) {
this.PORT = port;
}
public void startNettyServer() throws InterruptedException {
NioEventLoopGroup boss = new NioEventLoopGroup();
NioEventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
//EventLoop = selector 检测 + thread 线程
.group(boss, worker)
//选择服务器的实现
.channel(NioServerSocketChannel.class)
//handler
.childHandler(new ServerChildHandler());
ChannelFuture channelFuture = serverBootstrap
.bind(PORT)
.sync();
log.info("Netty服务器启动成功!");
channelFuture
.channel()
.closeFuture()
.sync();
} catch (Exception e) {
log.error("Netty服务器运行出错,错误信息————>{}",e.getMessage());
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
public static void main(String[] args) throws InterruptedException {
new NettyServer(8899).startNettyServer();
}
}
创建ServerChildHandler类,添加handler:
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LoggingHandler;
/**
* @author Sky.yu
* @ClassName serverChildHandler.java
* @Description 负责连接worker、处理读写
* @createTime 2022-08-13 12:51
**/
public class ServerChildHandler extends ChannelInitializer<NioSocketChannel> {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new LoggingHandler());
//编码 string转成ByteBuf
ch.pipeline().addLast(new StringEncoder());
//解码
ch.pipeline().addLast(new StringDecoder());
//自定义handler
ch.pipeline().addLast(new ServerHandler());
}
}
创建自定义handler类ServerHandler,继承了ChannelInboundHandlerAdapter,具体方法说明可看方法说明
@Slf4j
public class ServerHandler extends ChannelInboundHandlerAdapter {
/**
* 读事件
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 打印上一步转换好的字符串
System.out.println("收到来自"+ctx.channel()+"的消息:"+msg.toString());
ctx.channel().writeAndFlush("收到你的信息了!");
}
}
下面是客户端:
nettyClient:
import com.sky.mynettydemo.handler.ClientHandler.ClientChildHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
/**
* @author Sky.yu
* @ClassName NettyClient.java
* @Description 客户端
* @createTime 2022-08-13 13:06
**/
@Slf4j
public class NettyClient {
private final String HOST;
private final Integer PORT;
public NettyClient(String host,Integer port) {
this.HOST = host;
this.PORT = port;
}
public void startNettyClient() {
NioEventLoopGroup boss = new NioEventLoopGroup();
try {
//启动类
Bootstrap bootstrap = new Bootstrap();
Bootstrap handler = bootstrap
//添加eventLoop
.group(boss)
//选择客户端channel实现
.channel(NioSocketChannel.class)
//添加处理器
.handler(new ClientChildHandler());
ChannelFuture channelFuture = handler
.connect(HOST, PORT)
//阻塞方法,直到连接建立才继续执行
.sync();
log.info("Netty客户端连接服务器成功!");
//代表连接对象
Channel channel = channelFuture.channel();
channel.closeFuture().sync();
} catch (Exception e) {
log.debug("客户端连接错误!信息——>{}",e);
} finally {
boss.shutdownGracefully();
log.debug("客户端关闭连接!");
}
}
public static void main(String[] args) throws InterruptedException {
new NettyClient("127.0.0.1",8899).startNettyClient();
}
}
下面是handler,
ClientChildHandler:
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
* @author Sky.yu
* @ClassName ClientChildHandler.java
* @Description
* @createTime 2022-08-13 13:31
**/
public class ClientChildHandler extends ChannelInitializer<NioSocketChannel> {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
//编码 string转成ByteBuf
ch.pipeline().addLast(new StringEncoder());
//解码
ch.pipeline().addLast(new StringDecoder());
//自定义handler
ch.pipeline().addLast(new ClientHandler());
}
}
自定义ClientHandler:
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
/**
* @author Sky.yu
* @ClassName ClientHandler.java
* @Description 客户端处理器
* @createTime 2022-08-13 13:31
**/
@Slf4j
public class ClientHandler extends ChannelInboundHandlerAdapter {
/**
* active 连接建立成功后,触发该方法!
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ChannelFuture channelFuture = ctx.channel().writeAndFlush("你好,服务端!我是客户端!");
if (channelFuture.isSuccess()) log.info("客户端发送消息成功!");
}
/**
* 读事件
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("收到来自服务端的消息:"+msg);
}
}
然后启动服务端,再启动客户端即可,效果图如下: