這與this question有關,但我試圖將我的問題分解成更小的步驟。如何解碼來自http請求的響應並使用netty中的內容?
我試圖寫一個簡單的http服務器使用接收HTTP請求網狀(服務器A),發出HTTP請求到另一臺服務器(服務器B),然後複製在響應到響應於內容最初的請求。我知道這裏有一些例子,比如LittleProxy,但是代碼相當複雜,而且因爲我是netb的n00b,所以我試圖儘可能簡單地使我的第一個代碼不會進入雜草。現在,我忽略了關於併發性的所有問題,並且只有一個通道從服務器A建立到服務器B(我知道這會與併發請求發生可怕的衝突,但它使我的初始任務更簡單)。
我的做法是這樣的:
設置客戶端引導並連接到本地主機端口18080.上運行的服務器B獲取相應的通道。
啓動服務器的端口2080與管道解碼的HTTP請求,然後聽音寫入通道將服務器B.
添加監聽器所產生的通道未來將複製的內容從服務器B響應到原始客戶端的請求到服務器A.
這裏的響應是在我試圖做的正是我所描述上面的代碼我有(很短)。我的問題是,我不知道如何將響應從服務器B複製到服務器的響應。當我在服務器A發送的響應(我檢查了ChannelBuffer的內容,並且被代理服務器返回了正確的文本)的響應中寫入原始客戶端時,我發現要做到這一點的方式會導致IllegalArgumentException。我粘貼了下面例外的部分堆棧跟蹤。其他意見歡迎,因爲有可能是我做除了明顯缺乏鎖定通道到服務器B上的其他錯誤:
public class NettyExample {
private static Channel channel;
private static Map<Channel, Channel> proxyToClient = new ConcurrentHashMap<Channel, Channel>();
public static void main(String[] args) throws Exception {
ChannelFactory clientFactory =
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
final ClientBootstrap cb = new ClientBootstrap(clientFactory);
cb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new HttpRequestEncoder(),
new HttpResponseDecoder(),
new ResponseHandler());
}
});
ChannelFuture cf = cb.connect(new InetSocketAddress("localhost", 18080));
channel = cf.awaitUninterruptibly().getChannel();
ChannelFactory factory =
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ServerBootstrap sb = new ServerBootstrap(factory);
sb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new HttpRequestDecoder(),
new RequestHandler());
}
});
sb.setOption("child.tcpNoDelay", true);
sb.setOption("child.keepAlive", true);
sb.bind(new InetSocketAddress(2080));
}
private static class ResponseHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
final HttpResponse proxyResponse = (HttpResponse) e.getMessage();
Channel clientChannel = proxyToClient.get(e.getChannel());
HttpResponse clientResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
clientResponse.setContent(proxyResponse.getContent());
clientChannel.write(clientResponse).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
Channel ch = future.getChannel();
ch.close();
}
});
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
}
}
private static class RequestHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
final HttpRequest request = (HttpRequest) e.getMessage();
System.out.println("calling client channel");
proxyToClient.put(channel, e.getChannel());
channel.write(request);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
}
}
}
此中繼呼叫似乎工作,直至調用clientChannel.write點(clientResponse)。在那裏,會產生以下異常:
java.lang.IllegalArgumentException: unsupported message type: class org.jboss.netty.handler.codec.http.DefaultHttpResponse
at org.jboss.netty.channel.socket.nio.SocketSendBufferPool.acquire(SocketSendBufferPool.java:53)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.write0(AbstractNioWorker.java:468)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromTaskLoop(AbstractNioWorker.java:432)
謝謝!編寫DefaultHttpResponse到通道仍然有問題。我不知道爲什麼它不適合我的情況。我已經編輯了上面的問題來反映這一點,並提出了一個單獨的問題(http://stackoverflow.com/questions/15795061/unable-to-write-defaulthttpresponse-to-a-channel-in-netty-unsupported-message )具體關於這個。 – jonderry