netty入门一(新手上路,高手绕道)

Hello World 入门(注意看注释)

gradle依赖

dependencies {
    // https://mvnrepository.com/artifact/io.netty/netty-all
	compile group: 'io.netty', name: 'netty-all', version: '4.1.30.Final'  
}

Server.java

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 Server {

	public static void main(String[] args) throws Exception {

		/**
		 * 1. netty推荐使用两个线程组处理事务
		 */
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();

		try {

			/**
			 * 2. 用于启动服务端的类
			 */
			ServerBootstrap serverBootstrap = new ServerBootstrap();

			serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
					.childHandler(new MyServerInitiallizer());

			ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
			channelFuture.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
}

MyServerInitiallizer.java

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

public class MyServerInitiallizer extends ChannelInitializer<SocketChannel> {

	@Override
	protected void initChannel(SocketChannel ch) throws Exception {

		ChannelPipeline pipeline = ch.pipeline();

		pipeline.addLast("httpServerCodec", new HttpServerCodec());
		pipeline.addLast("myHttpServerHandler", new MyHttpServerHandler());
	}

}

MyHttpServerHandler.java

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
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;

public class MyHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

	/**
	 * 0. 读取客户端发过来的请求,并将响应返回给客户端的方法
	 */
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
		
		if(msg instanceof HttpRequest) {
			/**
			 * 1. 构建响应的字符串信息
			 */
			ByteBuf content = Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8);

			/**
			 * 2. 构建FullHttpResponse 对象
			 */
			FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);

			/**
			 * 3. 设置 response 的头信息
			 */
			response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
			response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());

			/**
			 * 4. 将response对象返回到客户端
			 */
			ctx.writeAndFlush(response);
		}
	}

}

启动服务器,使用curl请求结果如下:

D:\Program Files\curl>curl "http://localhost:8899"
hello world

netty的执行流程:
修改 MyHttpServerHandler.java 为如下代码:

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
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;

import java.net.URI;

public class MyHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

	/**
	 * 0. 读取客户端发过来的请求,并将响应返回给客户端的方法
	 */
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

		if(msg instanceof HttpRequest) {

			System.out.println("执行channelRead0");

			HttpRequest httpRequest = (HttpRequest) msg;
			URI uri = new URI(httpRequest.uri());
			if("/favicon.ico".equals(uri.getPath())){
				System.out.println("请求.favicon.ico");
				return;
			}

			/**
			 * 1. 构建响应的字符串信息
			 */
			ByteBuf content = Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8);

			/**
			 * 2. 构建FullHttpResponse 对象
			 */
			FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);

			/**
			 * 3. 设置 response 的头信息
			 */
			response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
			response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());

			/**
			 * 4. 将response对象返回到客户端
			 */
			ctx.writeAndFlush(response);
		}
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("MyHttpServerHandler.channelActive");
		super.channelActive(ctx);
	}

	/**
	 * ChannelHandlerContext: 实例是 DefaultChannelHandlerContext
	 * 包含了一个ChannelHandler,这里是  MyHttpServerHandler 的实例
	 * 包含了一个 DefaultChannelPipeline pipeline:就是 MyServerInitiallizer#initChannel方法里面的 pipeline
	 * DefaultChannelPipeline{(httpServerCodec = io.netty.handler.codec.http.HttpServerCodec), (myHttpServerHandler = com.ghq.netty.one.MyHttpServerHandler)}
	 *
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		ChannelPipeline pipeline = ctx.pipeline();

		System.out.println("MyHttpServerHandler.channelRegistered");
		super.channelRegistered(ctx);
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		System.out.println("MyHttpServerHandler.channelRead");
		super.channelRead(ctx, msg);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("MyHttpServerHandler.channelInactive");
		super.channelInactive(ctx);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		System.out.println("MyHttpServerHandler.channelReadComplete");
		super.channelReadComplete(ctx);
	}

	@Override
	public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
		System.out.println("MyHttpServerHandler.channelUnregistered");
		super.channelUnregistered(ctx);
	}

	@Override
	public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
		System.out.println("MyHttpServerHandler.channelWritabilityChanged");
		super.channelWritabilityChanged(ctx);
	}
}

重启服务,curl访问: curl “http://localhost:8899” ,控制台输出如下:

MyHttpServerHandler.channelRegistered
MyHttpServerHandler.channelActive
MyHttpServerHandler.channelRead
执行channelRead0
MyHttpServerHandler.channelRead
MyHttpServerHandler.channelReadComplete
MyHttpServerHandler.channelReadComplete
MyHttpServerHandler.channelInactive
MyHttpServerHandler.channelUnregistered

结果很意外,channelRead执行了两次,channelReadComplete执行了两次。
后续会继续分析执行流程。

你可能感兴趣的:(netty)