服务端启动的demo
所有 Netty 服务端的启动类都可以采用如下代码结构进行开发。简单梳理一下流程:首先创建引导器;然后配置线程模型,通过引导器绑定业务逻辑处理器,并配置一些网络参数;最后绑定端口,就可以完成服务器的启动了。
public class HttpServer {
public void start(int port) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
ch.pipeline()
.addLast("codec", new HttpServerCodec()) // HTTP 编解码
.addLast("compressor", new HttpContentCompressor()) // HttpContent 压缩
.addLast("aggregator", new HttpObjectAggregator(65536)) // HTTP 消息聚合
.addLast("handler", new HttpServerHandler()); // 自定义业务逻辑处理器
}
})
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind().sync();
System.out.println("Http Server started, Listening on " + port);
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new HttpServer().start(8088);
}
}
public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) {
String content = String.format("Receive http request, uri: %s, method: %s, content: %s%n", msg.uri(), msg.method(), msg.content().toString(CharsetUtil.UTF_8));
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
Unpooled.wrappedBuffer(content.getBytes()));
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
}
Q1:服务端的Socket在哪里初始化?
Q2:在哪里accpet连接?
一.创建服务端Channel
1.bind() ----用户代码入口
2.initAndRegister() ---- 初始化并注册
3.new Channel() -----创建服务端Channel
NioServerSocketChannel:
反射创建服务端Channel
1.new Socket() ----通过jdk来创建底层jdk channel
2.NioServerSocketChannelConfig ----- tcp参数配置类
3.AbstractNioChannel()
configureBlocking(false) ------ 阻塞模式
AbstractChannel() -----创建id,unsafe,pipeline
二.初始化服务端Channel
init() — 初始化入口
set ChannelOptions, ChannelAttrs
set ChildOptions,ChildAttrs
config handler 配置服务端pipeline
add ServerBootstrapAcceptor 添加连接器
三.注册selector
AbstractChannel.register(channel)[入口]
this.eventLoop = eventLoop[绑定线程]
register0()[实际注册]
doRegister()[调用jdk底层注册]
invokeHandlerAddedIfNeeded()
fireChannelRegistered[传播时间]
四.端口绑定
AbstractUnsafe.bind()[入口]
doBind()
javaChannel().bind()[jdk底层绑定]
pipeline.fireChannelActive()[传播事件]
HeadContext.readIfIsAutoRead()