1、介绍
本文档使用Netty演示入门Demo,实现TCP服务端,实际网络编程中需要解决的各种问题均未处理,仅做入门演示使用。
此处使用4.1.80.Final版本Netty,采用maven引入依赖。
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.80.Final</version>
</dependency>
2、服务端代码
public class ServerDemo {
public static void main(String[] args) throws InterruptedException {
/**
* 创建两个线程组 bossGroup 和 workerGroup
* bossGroup:处理连接请求。
* workerGroup:处理已建立连接的数据读写操作。
* 线程组大小默认为 cpu核数 * 2,基于Selector实现。
*/
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
//创建服务器端的启动对象,配置参数
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup,workGroup) //设置两个线程组
.channel(NioServerSocketChannel.class) //NioServerSocketChannel 作为服务器的通道实现
.option(ChannelOption.SO_BACKLOG,128) //临时存放已完成三次握手的请求的队列的最大长度
.childOption(ChannelOption.SO_KEEPALIVE,true) //设置保持活动连接状态
//.handler(null) //给bossGroup设置handler
.childHandler(new ChannelInitializer<SocketChannel>() { //给workGroup设置handler
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DemoHandler()); //给pipeline添加handler
}
});
//绑定8080端口并且同步, 生成了一个 ChannelFuture 对象
ChannelFuture future = bootstrap.bind(8080).sync();
//ChannelFuture对象注册监听器
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if(channelFuture.isSuccess()){
System.out.println("服务端启动成功!");
}else {
System.out.println("服务端启动失败~");
}
}
});
//对关闭通道进行监听
future.channel().closeFuture().sync();
}finally {
//关闭EventLoopGroup
workGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
/**
* 自定义Hander,用于处理已建立连接的SocketChannel
*/
class DemoHandler extends ChannelInboundHandlerAdapter {
//客户端连接触发
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
//客户端断开连接触发
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
}
//读取到客户端发送的消息触发
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
int readableBytes = byteBuf.readableBytes();
byte[] bytes = new byte[readableBytes];
byteBuf.readBytes(bytes);
System.out.println("netty服务端接收到的字节内容:"+Arrays.toString(bytes));
//writeAndFlush 是 write + flush。将数据写入到缓存,并刷新传递给客户端
ctx.writeAndFlush(Unpooled.wrappedBuffer(bytes));
}
//客户端消息读取完成触发
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
super.channelReadComplete(ctx);
}
//发生异常触发
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
3、测试
这里TCP客户端代码就不单独编写了,在网上搜了个网络测试工具,用于连接编写的Netty服务端程序。https://pan.baidu.com/s/16ORXo5l6OzhGFO-VBVRLOQ?pwd=i1v8
。
使用测试工具连接Netty服务端程序,发送字节数据测试: