【发布时间】:2012-03-17 20:11:17
【问题描述】:
我是 netty 的新手,仍在努力寻找自己的方式。我正在寻找创建一个异步工作的http客户端。 http的netty示例只展示了如何等待IO操作,而不是如何使用addListener,所以这几天我一直在努力解决这个问题。
我正在尝试创建一个请求类来处理请求的所有不同状态,从连接、发送数据、处理响应到关闭连接。 为了做到这一点,我的类扩展了 SimpleChannelUpstreamHandler 并实现了 ChannelFutureListener。我使用 ChannelPipelineFactory 将(this)实例类(作为 SimpleChannelUpstreamHandler)添加到管道中作为处理程序。
连接是这样创建的:
this.state = State.Connecting;
this.clientBootstrap.connect(this.address).addListener(this);
然后是operationComplete方法:
@Override
public void operationComplete(ChannelFuture future) throws Exception {
State oldState = this.state;
if (!future.isSuccess()) {
this.status = Status.Failed;
future.getChannel().disconnect().addListener(this);
}
else if (future.isCancelled()) {
this.status = Status.Canceled;
future.getChannel().disconnect().addListener(this);
}
else switch (this.state) {
case Connecting:
this.state = State.Sending;
Channel channel = future.getChannel();
channel.write(this.createRequest()).addListener(this);
break;
case Sending:
this.state = State.Disconnecting;
future.getChannel().disconnect().addListener(this);
break;
case Disconnecting:
this.state = State.Closing;
future.getChannel().close().addListener(this);
break;
case Closing:
this.state = State.Finished;
break;
}
System.out.println("request operationComplete start state: " + oldState + ", end state: " + this.state + ", status: " + this.status);
}
private HttpRequest createRequest() {
String url = this.url.toString();
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, url);
request.setHeader(HttpHeaders.Names.HOST, this.url.getHost());
request.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
request.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
return request;
}
该类还覆盖了 messageReceived 方法:
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("messageReceived");
HttpResponse response = (HttpResponse) e.getMessage();
ChannelBuffer content = response.getContent();
if (content.readable()) {
System.out.println("CONTENT: " + content.toString(CharsetUtil.UTF_8));
}
}
问题是我得到了这个输出:
request operationComplete start state: Connecting, end state: Sending, status: Unknown
request operationComplete start state: Sending, end state: Disconnecting, status: Unknown
request operationComplete start state: Closing, end state: Finished, status: Unknown
request operationComplete start state: Disconnecting, end state: Finished, status: Unknown
正如您所见,由于某种原因,messageReceived 没有被执行,即使管道工厂将此类的实例添加到管道中。
任何想法我在这里缺少什么? 谢谢。
编辑
在@JestanNirojan 的帮助下,我终于成功地完成了这项工作,以防有人对解决方案感兴趣:
public class ClientRequest extends SimpleChannelUpstreamHandler {
....
public void connect() {
this.state = State.Connecting;
System.out.println(this.state);
this.clientBootstrap.connect(this.address);
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
this.state = State.Sending;
System.out.println(this.state);
ctx.getChannel().write(this.createRequest());
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
HttpResponse response = (HttpResponse) e.getMessage();
ChannelBuffer content = response.getContent();
if (content.readable()) {
System.out.println("CONTENT: " + content.toString(CharsetUtil.UTF_8));
}
this.state = State.Disconnecting;
System.out.println(this.state);
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
this.state = State.Closing;
System.out.println(this.state);
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
this.state = State.Finished;
System.out.println(this.state);
}
private HttpRequest createRequest() {
String url = this.url.toString();
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, url);
request.setHeader(HttpHeaders.Names.HOST, this.url.getHost());
request.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
request.setHeader(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
return request;
}
}
【问题讨论】:
-
HttpResponse 是完整的 HttpResponse 还是可以是一个块?我有 1000 个块返回,并且希望每个块有一个事件,否则内存会爆炸导致内存不足。
-
HttpResponse 是完整的响应,据我所知,您无法对其进行分块。你应该再低一点,可能是HttpResponseDecoder。
-
如果您对分块不感兴趣,请在此处使用轻型 http 客户端 @github.com/arungeorge81/netty-http-client
标签: java http asynchronous nio netty