博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于Netty4的HttpServer和HttpClient的简单实现
阅读量:6273 次
发布时间:2019-06-22

本文共 9664 字,大约阅读时间需要 32 分钟。

Netty的主页:http://netty.io/index.html

使用的Netty的版本: ‐ 15-Aug-2014 (Stable, Recommended)

Http 消息格式:

Http request:

Method path-to-resource HTTPVersion-numberHeader-name-1: value1Header-name-2: value2Optional request body

Http response:

HTTP/Version-number response-code response-phrase Header-name-1: value1Header-name-2: value2Optional response body

实现一个简单的Http请求及响应过程:

1、Client向Server发送http请求。

2、Server端对http请求进行解析。

3、Server端向client发送http响应。

4、Client对http响应进行解析。

Netty中Http request消息格式:

Netty中Http response消息格式:

代码实例:

Http Server:

package com.netty.test;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; public class HttpServer {    private static Log log = LogFactory.getLog(HttpServer.class);        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)                    .childHandler(new ChannelInitializer
() { @Override public void initChannel(SocketChannel ch) throws Exception { // server端发送的是httpResponse,所以要使用HttpResponseEncoder进行编码 ch.pipeline().addLast(new HttpResponseEncoder()); // server端接收到的是httpRequest,所以要使用HttpRequestDecoder进行解码 ch.pipeline().addLast(new HttpRequestDecoder()); ch.pipeline().addLast(new HttpServerInboundHandler()); } }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { HttpServer server = new HttpServer(); log.info("Http Server listening on 8844 ..."); server.start(8844); }}

响应请求的HttpServerInboundHandler:

package com.netty.test;import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;import static io.netty.handler.codec.http.HttpResponseStatus.OK;import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.handler.codec.http.DefaultFullHttpResponse;import io.netty.handler.codec.http.FullHttpResponse;import io.netty.handler.codec.http.HttpContent;import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpHeaders.Values;import io.netty.handler.codec.http.HttpRequest;public class HttpServerInboundHandler extends ChannelInboundHandlerAdapter {    private static Log log = LogFactory.getLog(HttpServerInboundHandler.class);    private HttpRequest request;    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg)            throws Exception {        if (msg instanceof HttpRequest) {            request = (HttpRequest) msg;            String uri = request.getUri();            System.out.println("Uri:" + uri);        }        if (msg instanceof HttpContent) {            HttpContent content = (HttpContent) msg;            ByteBuf buf = content.content();            System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8));            buf.release(); String res = "I am OK";            FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1,                    OK, Unpooled.wrappedBuffer(res.getBytes("UTF-8")));            response.headers().set(CONTENT_TYPE, "text/plain");            response.headers().set(CONTENT_LENGTH,                    response.content().readableBytes());            if (HttpHeaders.isKeepAlive(request)) {                response.headers().set(CONNECTION, Values.KEEP_ALIVE);            }            ctx.write(response);            ctx.flush();        }    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {        ctx.flush();    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        log.error(cause.getMessage());        ctx.close();    }}

Http Client:

package com.netty.test;import io.netty.bootstrap.Bootstrap;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.http.DefaultFullHttpRequest;import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpMethod;import io.netty.handler.codec.http.HttpRequestEncoder;import io.netty.handler.codec.http.HttpResponseDecoder;import io.netty.handler.codec.http.HttpVersion;import java.net.URI;public class HttpClient {    public void connect(String host, int port) throws Exception {        EventLoopGroup workerGroup = new NioEventLoopGroup();        try {            Bootstrap b = new Bootstrap();            b.group(workerGroup);            b.channel(NioSocketChannel.class);            b.option(ChannelOption.SO_KEEPALIVE, true);            b.handler(new ChannelInitializer
() { @Override public void initChannel(SocketChannel ch) throws Exception { // 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码 ch.pipeline().addLast(new HttpResponseDecoder()); // 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码 ch.pipeline().addLast(new HttpRequestEncoder()); ch.pipeline().addLast(new HttpClientInboundHandler()); } }); // Start the client. ChannelFuture f = b.connect(host, port).sync(); URI uri = new URI("http://127.0.0.1:8844"); String msg = "Are you ok?"; DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toASCIIString(), Unpooled.wrappedBuffer(msg.getBytes("UTF-8"))); // 构建http请求 request.headers().set(HttpHeaders.Names.HOST, host); request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, request.content().readableBytes()); // 发送http请求 f.channel().write(request); f.channel().flush(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { HttpClient client = new HttpClient(); client.connect("127.0.0.1", 8844); }}

处理Server响应的HttpClientInboundHandler:

package com.netty.test;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.handler.codec.http.HttpContent;import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpResponse;public class HttpClientInboundHandler extends ChannelInboundHandlerAdapter {    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        if (msg instanceof HttpResponse)         {            HttpResponse response = (HttpResponse) msg;            System.out.println("CONTENT_TYPE:" + response.headers().get(HttpHeaders.Names.CONTENT_TYPE));        }        if(msg instanceof HttpContent)        {            HttpContent content = (HttpContent)msg;            ByteBuf buf = content.content();            System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8));            buf.release();        }    }}

log4j的配置:

# Root logger option

log4j.rootLogger=INFO, stdout, file

# Direct log messages to stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.appender.file = org.apache.log4j.DailyRollingFileAppender

log4j.appender.file.File = logs/log.log
log4j.appender.file.Append = true
log4j.appender.file.Threshold = INFO
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n

 

作者:
出处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
http://www.cnblogs.com/luxiaoxun/p/3959450.html
你可能感兴趣的文章
SAP MM 系统确定供应源优先级
查看>>
交货单打印时提示“没有输出被选择打印”
查看>>
UML在软件开发各个阶段的应用
查看>>
服务器硬件问题整理的一点总结
查看>>
MSSQL · 实现分析 · Extend Event实现审计日志对SQL Server性能影响
查看>>
互动报表 SAP ABAP
查看>>
11.10. loop devices
查看>>
菜鸟学算法--简单的交换和最大公约数算法入门篇
查看>>
SAP S/4HANA Cloud: Revolutionizing the Next Generation of Cloud ERP
查看>>
《分歧者3》观后感
查看>>
GIS基础软件及操作(九)
查看>>
10天学安卓-第一天
查看>>
view和activity的区别(转)
查看>>
MySQL的create table as 与 like区别(转)
查看>>
SQLserver 存储过程执行错误记录到表
查看>>
Spring Boot 之 RESRful API 权限控制
查看>>
Redis——常用命令操作
查看>>
UDP 单播、广播和多播
查看>>
windows linux—unix 跨平台通信集成控制系统----系统硬件信息获取
查看>>
ThinkPad E550 安装 WIN7 的启动 U 盘制作
查看>>