Practical Netty (6) HTTP Server/Client

Practical Netty (6) HTTP Server/Client


Netty 提供的 HTTP 功能,比较适合在 Netty 搭建的 TCP 或 UDP 服务器上做一些专用的 HTTP 服务,而非一般性的通用 HTTP 服务器。所以不要将 Netty 的自行实现的 HTTP 服务器的易用性与现有 Nginx、Lighttpd 等来比较。

1 HTTP Server

主要不同就是 Pipeline 用什么 handlers,以及我们自定义的 handler 如何处理 HttpRequest,并生成相应的 HttpResponse。

public class ServerPipelineFactory implements ChannelPipelineFactory {

    public ChannelPipeline getPipeline() throws Exception {
        ChannelPipeline pipeline = Channels.pipeline();

        pipeline.addLast("decoder", new HttpRequestDecoder());
        pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));
        pipeline.addLast("encoder", new HttpResponseEncoder());
        pipeline.addLast("handler", new PoechantRequestHandler());

        return pipeline;
    }
}

如何接收 request?如何解析 request?如何产生 response?就看下面的 request handler。

public class PoechantRequestHandler extends SimpleChannelUpstreamHandler {
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
            throws Exception {
        System.out.println("channel connected...");
        super.channelConnected(ctx, e);
    }
    
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        HttpRequest request = (HttpRequest) e.getMessage();
        System.out.println(
            "request length:  " + 
            ((HttpRequest) e.getMessage()).getContent().readableBytes());
        HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
        response.setContent(ChannelBuffers.copiedBuffer("I'm a response", CharsetUtil.UTF_8));
        response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
        e.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
    }
}

在 Response 中 还可以设置其他的 Headers:

response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, 123);
response.setHeader("Content", "keep-alive");

还有一些 Headers 相关的 Name 和 Value,可以在HttpHeaders.NamesHttpHeaders.Values中找到。

2. HTTP Client

ClientBootstrap 一旦连接成功,就可以发送 HttpRequest 了,连接的代码实例如下:

Channel channel =
    cb.connect(
        new InetSocketAddress("10.0.0.110", 9980)).awaitUninterruptibly().getChannel();

如上是一个阻塞式的连接方式,在连接确认成功或失败前,会一直 block 在那里。异步的方式则如下:

ChannelFuture future = cb.connect(new InetSocketAddress("10.0.0.110", 9980));
Channel channel = future.getChannel();

然后就可以用这个 channel 发消息了。如果是异步的,则要监听成功之后再发送。

future.addListener(new ChannelFutureListener() {
    public void operationComplete(ChannelFuture future) throws Exception {
        // send a request to the http server
    }
});

然后就可以发送数据了。如果是异步的,

HttpRequest request = 
    new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/docs/index.html");
request.addHeader(HttpHeaders.Names.HOST, "10.0.0.110");
channel.write(request).awaitUninterruptibly().getChannel().getCloseFuture().awaitUninterruptibly();

当然你也可以异步发送。

channel.write(request);channel.write(request);

-

转载请注明来自柳大的CSDN博客:Blog.CSDN.net/Poechant,微博:weibo.com/lauginhom

-

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页