Netty入门实例 TCP服务
基于Netty开发一个入门程序,主要功能:服务端启动后监听一个端口,客户端启动后会给服务端发送一条消息,服务端收到后通过Handler读取消息,进行处理,读取完通过Handler反馈一条消息给客户端。
服务端:
Server
package com.tech.netty.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @author lw
* @since 2021/8/11
**/
public class NettyServer {
public static void main(String[] args) throws InterruptedException {
//1 创建两个线程组bossGroup workerGroup
//2 bossGroup处理客户端连接请求 workerGroup处理客户端数据读写请求
//3 他们都是事件循环组 默认含有CPU核数*2个事件循环NioEventLoop
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//创建服务器端启动对象,进行参数配置
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup) //设置两个线程组
.channel(NioServerSocketChannel.class) //设置服务器端通道为NioServerSocketChannel
.option(ChannelOption.SO_BACKLOG, 128) //设置连接队列允许的连接个数
.childOption(ChannelOption.SO_KEEPALIVE, true) //设置连接连接状态为活动连接
.childHandler(new ChannelInitializer<SocketChannel>() { //给workerGroup NioEventLoop通过管道添加处理器
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new NettyServerHandler());
}
});
System.out.println("...服务器 is ready...");
//启动服务器并绑定一个端口
ChannelFuture channelFuture = serverBootstrap.bind(6668).sync();
//对通道的关闭事件进行监听
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
ServerHandler
package com.tech.netty.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.util.CharsetUtil;
/**
* @author lw
* @since 2021/8/11
**/
//自定义一个Handler
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
//读取客户端发送的消息
// ChannelHandlerContext 是一个上下文对象,可以获取通道和管道信息
// msg 是客户端发送的消息
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("服务器读取线程 "+Thread.currentThread().getName());
System.out.println("server ctx:"+ctx);
Channel channel = ctx.channel();
ChannelPipeline pipeline = ctx.pipeline();
ByteBuf byteBuf = (ByteBuf) msg;
System.out.println("客户端发送消息是:"+byteBuf.toString(CharsetUtil.UTF_8));
System.out.println("客户端地址:"+channel.remoteAddress());
}
//数据读取完毕
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//发送数据
ctx.writeAndFlush(Unpooled.copiedBuffer("hello 客户端",CharsetUtil.UTF_8));
}
//处理异常 一般是需要关闭通道
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
客户端:
client
package com.tech.netty.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* @author lw
* @since 2021/8/11
**/
public class NettyClient {
public static void main(String[] args) throws InterruptedException {
//客户端需要一个事件循环组
NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
try {
// 创建客户端启动对象 并配置参数
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventExecutors) //设置线程组
.channel(NioSocketChannel.class) //设置客户端通道
.handler(new ChannelInitializer<SocketChannel>() { //设置处理器
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new NettyClientHandler());
}
});
System.out.println("...客户端 is ready...");
//连接服务器
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();
//对通道关闭事件进行监听
channelFuture.channel().closeFuture().sync();
} finally {
eventExecutors.shutdownGracefully();
}
}
}
ClientHandler
package com.tech.netty.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
/**
* @author lw
* @since 2021/8/11
**/
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
//当通道就绪会触发该方法 给服务器发送数据
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("client ctx:"+ctx);
ctx.writeAndFlush(Unpooled.copiedBuffer("hello 服务器", CharsetUtil.UTF_8));
}
//当通道有读取事件时触发
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
System.out.println("服务器回复的消息:"+byteBuf.toString(CharsetUtil.UTF_8));
System.out.println("服务器的地址:"+ctx.channel().remoteAddress());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
还没有评论,来说两句吧...