写在前面
源码 。
http是应用层协议,是我们日常开发中直接用到最多的协议了。本文来看下通过netty如何实现。
1:程序
netty不仅仅提供了String相关的编解码器,还贴心
的提供了http相关的编码器和解码器,直接拿来用就行了,所以使用netty来实现http服务还是比较简单的。
1.1:server
server main:
package com.dahuyuo.netty.httpserver.server;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class NettyServer {public static void main(String[] args) {new NettyServer().bing(7397);}private void bing(int port) {//配置服务端NIO线程组EventLoopGroup parentGroup = new NioEventLoopGroup(); //NioEventLoopGroup extends MultithreadEventLoopGroup Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));EventLoopGroup childGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(parentGroup, childGroup).channel(NioServerSocketChannel.class) //非阻塞模式.option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new MyChannelInitializer());ChannelFuture f = b.bind(port).sync();System.out.println("netty http server start done on port: " + 7397);f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {childGroup.shutdownGracefully();parentGroup.shutdownGracefully();}}}
MyChannelInitializer:
package com.dahuyuo.netty.httpserver.server;import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;import java.nio.charset.Charset;public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel channel) {// 数据解码操作channel.pipeline().addLast(new HttpResponseEncoder());// 数据编码操作channel.pipeline().addLast(new HttpRequestDecoder());// 在管道中添加我们自己的接收数据实现方法channel.pipeline().addLast(new MyServerHandler());}}
HttpResponseEncoder,HttpRequestDecoder就是http响应和请求和编码器和解码器。MyServerHandler是自定义的inbound的消息处理器:
package com.dahuyuo.netty.httpserver.server;import io.netty.buffer.ByteBuf;
import io.netty.buffer.EmptyByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.*;import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;public class MyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {if (msg instanceof HttpRequest) {DefaultHttpRequest request = (DefaultHttpRequest) msg;System.out.println("URI:" + request.getUri());System.err.println(msg);}if (msg instanceof HttpContent) {LastHttpContent httpContent = (LastHttpContent) msg;ByteBuf byteData = httpContent.content();if (!(byteData instanceof EmptyByteBuf)) {//接收msg消息byte[] msgByte = new byte[byteData.readableBytes()];byteData.readBytes(msgByte);System.out.println(new String(msgByte, Charset.forName("UTF-8")));}}String sendMsg = "我是netty实现的http server响应的内容啊!!!";FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,Unpooled.wrappedBuffer(sendMsg.getBytes(Charset.forName("UTF-8"))));response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=UTF-8");response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);ctx.write(response);ctx.flush();}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {ctx.flush();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();cause.printStackTrace();}}
其中方法channelRead对http的请求信息做了解析,并输出了相关内容。最后写回了http的响应。