案例要求

image.png

Server
  1. public class Server {
  2. public static void main(String[] args) throws Exception {
  3. EventLoopGroup bossGroup = new NioEventLoopGroup(1);
  4. EventLoopGroup workerGroup = new NioEventLoopGroup();
  5. try {
  6. ServerBootstrap serverBootstrap = new ServerBootstrap();
  7. serverBootstrap.group(bossGroup, workerGroup)
  8. .channel(NioServerSocketChannel.class)
  9. .childHandler(new ServerInitializer());
  10. //绑定端口
  11. ChannelFuture channelFuture = serverBootstrap.bind(8081).sync();
  12. channelFuture.channel().closeFuture().sync();
  13. } finally {
  14. bossGroup.shutdownGracefully();
  15. workerGroup.shutdownGracefully();
  16. }
  17. }
  18. }

ServerHandler
  1. /*
  2. 1.SimpleChannelInboundHandler是ChannelInboundHandlerAdapter的子类
  3. 2.HttpObject表示客户端和服务器端相互通讯的数据被封装成 HttpObject对象
  4. */
  5. public class ServerHandler extends SimpleChannelInboundHandler<HttpObject> {
  6. //读取客户端数据
  7. @Override
  8. protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
  9. //判断msg是不是HttpRequest请求
  10. if (msg instanceof HttpRequest) {
  11. System.out.println("msg的类型" + msg.getClass());
  12. System.out.println("客户端地址" + ctx.channel().remoteAddress());
  13. //过滤掉特定资源
  14. HttpRequest httpRequest = (HttpRequest) msg;
  15. //获取uri
  16. URI uri = new URI(httpRequest.uri());
  17. if ("/favicon.ico".equals(uri.getPath())) {
  18. System.out.println("请求了favicon.ico图标,但是不进行响应");
  19. return;
  20. }
  21. //回复信息给浏览器 【Http协议】
  22. ByteBuf content = Unpooled.copiedBuffer("hello,我是服务器", StandardCharsets.UTF_16);
  23. //构造Http响应 即HttpResponse--指定http版本和状态码
  24. FullHttpResponse response =
  25. new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
  26. response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
  27. response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
  28. //将构建好的response返回
  29. ctx.writeAndFlush(response);
  30. }
  31. }
  32. }

ServerInitializer
  1. public class ServerInitializer extends ChannelInitializer<SocketChannel> {
  2. @Override
  3. protected void initChannel(SocketChannel ch) throws Exception {
  4. //加入处理器
  5. //得到pipeline
  6. ChannelPipeline pipeline = ch.pipeline();
  7. //加入Netty提供的HttpServerCodec 编解码器
  8. pipeline.addLast("MyHttpServerCodec", new HttpServerCodec());
  9. //加入自定义处理器
  10. pipeline.addLast("MyServerHandler", new ServerHandler());
  11. }
  12. }

效果

image.png

注意点

1.http服务器的时候,ServerBootStrap在bind端口之后,可能收不到浏览器请求,可能是由于某些端口(6665-6669等)是浏览器的默认非安全端口,浏览器给拦截了
2.需要对某些资源请求设置不进行访问,比如浏览器页面的小图标
3.不同的浏览器来请求对应着各自的handler,并不是使用同一个,因为HTTP不是长连接,所有刷新一个页面也会再次分配一个新的handler
image.png