hello Netty服务器的构建(步骤如下)
构建一堆主从线程组
定义服务器启动类
为服务器设置Channel
设置处理线程池的助手类初始化器(用图来理解channel的助手类)
每一个channel由多个handler共同的组成管道(pipeline)
监听和关闭服务器
具体的类和代码如下:
构建一个HelloNetty的类
package com.DrDeng.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class HelloNetty {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//定义一队线程组
//主线程组,用于接收客户端的连接,但是不做任何事,跟老板一样,不做事
EventLoopGroup bossGroup=new NioEventLoopGroup();
//从线程池,bossgroup会把任务交给他,让手下的线程去做
EventLoopGroup workGroup=new NioEventLoopGroup();
try {
//netty服务器的创建,ServerBootStrap是一个启动类
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workGroup)//设置主线程组
.channel(NioServerSocketChannel.class)//设置nio双向通道
.childHandler( new HelloServerInitializer());//子处理器,用于workGroup
//启动Server,并且设置8088为启动的端口号,同步方式为同步
ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();
//监听关闭的channel,设置为同步
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
构建一个HelloServerInitializer 的类
package com.DrDeng.netty;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
/*
* 初始化器,channel注册后,会执行里面的相应的初始化方法,
*
* */
public class HelloServerInitializer extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel channel) throws Exception {
//通过socketchannel进行获取行对应的通道
ChannelPipeline pipeline = channel.pipeline();
//通过管道进行添加相应的handler
//HttpServerCodec是有netty的提供的助手类,可以理解为拦截器
//当请求到服务端的时候,我们需要做解码,这里就响应到我们的服务端
pipeline.addLast("HttpServerCodec", new HttpServerCodec());
//添加自定义的handler,返回"hello netty"
pipeline.addLast("customHandler", new CustomHandler());
}
}
构建一个CustomHandler 的类
package com.DrDeng.netty;
import java.net.ResponseCache;
import java.nio.charset.Charset;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
/*
*
* 创建自定义的助手类
* */
//SimpleChannelInboundHandler:对于请求来讲,其实就是相当于【入站,入境】
public class CustomHandler extends SimpleChannelInboundHandler<HttpObject>{
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if(msg instanceof HttpRequest){
//获取channel
Channel channel = ctx.channel();
//显示远程的地址
System.out.println(channel.remoteAddress());
//定义发送的数据信息 bytebuf 为缓冲区
ByteBuf content = Unpooled.copiedBuffer("hello_netty", CharsetUtil.UTF_8);
//构建一个http response
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
content);
//为响应增加数据类型和长度
response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
//将响应刷到客户端
ctx.writeAndFlush(response);
}
}
}
点击运行后客户端和console端显示