我对Netty很陌生,我试图为POST和GET请求创建一个异步http客户端。下面粘贴的代码无论如何工作都很重,我偶尔会遇到以下错误:
[18:49:56] [nioEventLoopGroup-2-1/WARN]: Failed to fail the promise because it's done already: DefaultChannelPromise@363154df(failure(io.netty.util.IllegalReferenceCountException: refCnt: 0)
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:101) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf$Component.freeIfNecessary(CompositeByteBuf.java:1335) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.CompositeByteBuf.deallocate(CompositeByteBuf.java:1590) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:106) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:59) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:661) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1054) ~[server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:658) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:716) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:651) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:125) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.CombinedChannelDuplexHandler.write(CombinedChannelDuplexHandler.java:192) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:658) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:716) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:651) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:637) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.handler.stream.ChunkedWriteHandler.doFlush(ChunkedWriteHandler.java:258) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:141) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:688) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:669) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.DefaultChannelPipeline.flush(DefaultChannelPipeline.java:838) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.AbstractChannel.flush(AbstractChannel.java:188) [server.jar:git-Spigot-f928e7a-e91aed8]
at com.werter03886.wtlevelcommand.HttpClient$2.operationComplete(HttpClient.java:120) [WTLevelCommand-1.1.2.jar:?]
at com.werter03886.wtlevelcommand.HttpClient$2.operationComplete(HttpClient.java:90) [WTLevelCommand-1.1.2.jar:?]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:680) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:603) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:563) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:406) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:82) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:253) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:288) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [server.jar:git-Spigot-f928e7a-e91aed8]
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [server.jar:git-Spigot-f928e7a-e91aed8]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_31]
这些是我的网络处理程序:
ChannelInitializer
public class HttpInitalizer extends ChannelInitializer<Channel> {
private final Callback<String> callback;
public HttpInitalizer(Callback<String> callback) {
this.callback = callback;
}
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast("codec", new HttpClientCodec());
ch.pipeline().addLast("inflater", new HttpContentDecompressor());
ch.pipeline().addLast("chunkedWriter", new ChunkedWriteHandler());
ch.pipeline().addLast("handler", new HttpHandler( callback ) );
}
}
SimpleChannelInboundHandler
@Sharable
public class HttpHandler extends SimpleChannelInboundHandler<HttpObject> {
private final Callback<String> callback;
private final StringBuilder buffer = new StringBuilder();
public HttpHandler (Callback<String> callback) {
this.callback = callback;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
try {
callback.done(null, cause);
}
catch(Exception ex) {
ex.printStackTrace();
}
finally {
ctx.channel().close();
}
}
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpResponse) {
HttpResponse response = (HttpResponse) msg;
int responseCode = response.getStatus().code();
if (responseCode == HttpResponseStatus.NO_CONTENT.code()) {
done(ctx);
return;
}
if (responseCode != HttpResponseStatus.OK.code()) {
throw new IllegalStateException("Expected HTTP response 200 OK, got " + response.getStatus());
}
}
if (msg instanceof HttpContent) {
HttpContent content = (HttpContent) msg;
buffer.append(content.content().toString(CharsetUtil.UTF_8));
if (msg instanceof LastHttpContent) {
done(ctx);
}
}
}
private void done(ChannelHandlerContext ctx) {
try {
callback.done(buffer.toString(), null);
}
catch(Exception ex) {
ex.printStackTrace();
}
finally {
ctx.channel().close();
}
}
}
HttpClient的
public final class HttpClient {
public static final int TIMEOUT = 500000;
private static EventLoopGroup group;
public HttpClient () {
group = new NioEventLoopGroup();
}
public static void get (String url, final Callback<String> callback) {
final URI uri = URI.create(url);
InetAddress inetHost = null;
try {
inetHost = InetAddress.getByName(uri.getHost());
}
catch (UnknownHostException e) {
e.printStackTrace();
}
int port = 80;
ChannelFutureListener future = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
String path = uri.getRawPath() + ( ( uri.getRawQuery() == null ) ? "" : "?" + uri.getRawQuery() );
HttpRequest request = new DefaultHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, path );
request.headers().set(HttpHeaders.Names.HOST, uri.getHost());
future.channel().writeAndFlush( request );
} else {
callback.done(null, future.cause());
}
}
};
new Bootstrap().channel(NioSocketChannel.class).group(group).handler(new HttpInitalizer(callback)).
option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT).remoteAddress(inetHost, port).connect().addListener(future);
}
public static void post (String url, final Map<String, Object> params, final Callback<String> callback) {
final URI uri = URI.create(url);
InetAddress inetHost = null;
try {
inetHost = InetAddress.getByName(uri.getHost());
}
catch (UnknownHostException e) {
e.printStackTrace();
}
int port = 80;
ChannelFutureListener future = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
String path = uri.getRawPath() + ( ( uri.getRawQuery() == null ) ? "" : "?" + uri.getRawQuery() );
HttpRequest request = new DefaultHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.POST, path );
HttpPostRequestEncoder bodyRequestEncoder = new HttpPostRequestEncoder(request, false);
for(Entry<String, Object> es : params.entrySet()) {
bodyRequestEncoder.addBodyAttribute(es.getKey(), es.getValue().toString());
}
request = bodyRequestEncoder.finalizeRequest();
request.headers().set(HttpHeaders.Names.HOST, uri.getHost() );
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
request.headers().set(HttpHeaders.Names.CONTENT_TYPE, "application/x-www-form-urlencoded");
future.channel().write(request);
if (bodyRequestEncoder.isChunked()) {
future.channel().write(bodyRequestEncoder);
}
future.channel().flush();
bodyRequestEncoder.cleanFiles();
future.channel().closeFuture();
}
else {
callback.done(null, future.cause());
}
}
};
new Bootstrap().channel(NioSocketChannel.class).group(group).handler(new HttpInitalizer(callback)).
option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT).remoteAddress(inetHost, port).connect().addListener(future);
}
}
如果有人能指出我正确的方向,我们将非常感激!
提前谢谢
答案 0 :(得分:0)
当我将NioSocketChannel用于网络程序时,我遇到了这个问题。我从ChannelHandler接口实现了handlder,没有使用ChannelHandlerAdapter作为扩展的父类。我没有实现的默认方法也没有使用super方法。因此程序运行时有例外,由于IDE的帮助,这是一个愚蠢的错误。