Practical Netty (6) HTTP Server/Client
- 作者:柳大·Poechant(鐘超)
- 郵箱:zhongchao.ustc#gmail.com(# -> @)
- 部落格:Blog.CSDN.net/Poechant
- 微博:weibo.com/lauginhom
- 日期:June 18th, 2012
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.Names和HttpHeaders.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
-