Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用netty编写http代理_Java_Proxy_Netty - Fatal编程技术网

Java 如何使用netty编写http代理

Java 如何使用netty编写http代理,java,proxy,netty,Java,Proxy,Netty,我想写一个简单的程序,使用netty代理浏览器发送的http请求。 我认为它可以分为三个步骤 获取通过浏览器发送的请求 将其发送到网站 从网站接收数据并将其发送回浏览器 问题: 当我使用Bootstrap.connect(主机,端口)时,如何将url转换为主机和端口 当我使用HttpServerResponseHandler.connect和ChannelHandlerContext.writeAndFlush(httpMessage)时;要向网站发送数据,我如何从网站获取响应数据并将其发送回浏

我想写一个简单的程序,使用netty代理浏览器发送的http请求。 我认为它可以分为三个步骤

  • 获取通过浏览器发送的请求
  • 将其发送到网站
  • 从网站接收数据并将其发送回浏览器 问题:

  • 当我使用Bootstrap.connect(主机,端口)时,如何将url转换为主机和端口
  • 当我使用HttpServerResponseHandler.connect和ChannelHandlerContext.writeAndFlush(httpMessage)时;要向网站发送数据,我如何从网站获取响应数据并将其发送回浏览器 这是我学习netty的第一天,所以请尽量简单回答。多谢各位

    public class Server {
        public static void main(String[] args) throws InterruptedException {
            final int port = 8888;
    
            // copy from https://github.com/netty/netty/wiki/User-guide-for-4.x
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) throws Exception {
                                ch.pipeline().addLast(new HttpRequestDecoder(), new HttpServerRequestHandler());
                            }
                        })
                        .option(ChannelOption.SO_BACKLOG, 128)
                        .childOption(ChannelOption.SO_KEEPALIVE, true);
    
                // Bind and start to accept incoming connections.
                ChannelFuture f = b.bind(port).sync();
    
                // Wait until the server socket is closed.
                // In this example, this does not happen, but you can do that to gracefully
                // shut down your server.
                f.channel().closeFuture().sync();
            } finally {
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
        }
    } 
    

    巧合的是,为了学习,我也一直在开发一个Netty代理服务器。我有一个完整的工作代码,你可以在我的上找到,但我会在这里回答你的问题。Netty也有一个官方的代理服务器示例,但与我的代码不同,他们没有单元测试

    (仅供参考,我的代码是Kotlin)

    核心理念

    创建代理服务器时,需要一台服务器来接受客户端请求,还需要一台远程代理服务器的客户端。您创建了服务器,但没有创建客户端。最好重用由服务器创建的
    EventLoop
    ,而不是为客户端创建一个新的循环。每个事件循环都在一个专用线程上运行,因此创建更多的事件循环将产生额外的线程,在接受的
    通道
    和客户端
    通道
    之间交换数据时需要进行上下文切换

    如何将url转换为主机和端口

    为了简单起见,我使用了一个将
    HttpMessage
    及其后续
    HttpContents
    聚合为单个
    FullHttpRequest
    FullHttpResponse
    (取决于它是否用于处理请求或响应)。设置URL很简单:只需调用

    要获取主机和端口,请调用客户端通道,并将生成的
    SocketAddress
    强制转换为
    InetSocketAddress
    ,从中可以获取主机和端口。如果存在
    主机
    标题,请不要忘记以类似方式重置

    如何获取响应数据


    在建立客户端通道(您缺少的)之后,您需要在该通道上发出请求。客户机通道有一个引用原始服务器通道的处理程序。处理程序收到响应后,会将其写入服务器通道。

    您能修复它吗?@AcidBurn几乎无法修复它。你可以看到答案“呼救”。@Abhijit你能看到你对这个问题有什么意见吗?
    public class HttpServerRequestHandler extends ChannelInboundHandlerAdapter {
    
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            // step 1 get data from browser
            if (msg instanceof LastHttpContent) {
                ctx.close();
                return;
            }
            DefaultHttpRequest httpMessage = (DefaultHttpRequest) msg;
            System.out.println("浏览器请求====================");
            System.out.println(msg);
            System.out.println();
            doWork(ctx, httpMessage);
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    
        private void doWork(ChannelHandlerContext ctx, final DefaultHttpRequest msg) {
            // step 2 send data to website
            // translate url into host and port
            String host = msg.uri();
            int port = 80;
            if (host.startsWith("https://")) {
                host = host.replaceFirst("https://", "");
                port = 443;
            } else if (host.startsWith("http://")) {
                host = host.replaceFirst("http://", "");
                port = 80;
            }
            if (host.contains(":443")) {
                host = host.replace(":443", "");
                port = 443;
            }
    
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                Bootstrap b = new Bootstrap();
                b.group(workerGroup);
                b.channel(NioSocketChannel.class);
                //b.option(ChannelOption.AUTO_READ, true);
                b.handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new HttpServerResponseHandler(msg), new HttpRequestEncoder());
                    }
                });
    
                // question 1
                ChannelFuture f = b.connect(host, port).sync();
                //ChannelFuture f = b.connect("www.baidu.com", 443).sync();
                f.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                workerGroup.shutdownGracefully();
            }
        }
    }
    
    public class HttpServerResponseHandler extends ChannelOutboundHandlerAdapter {
    
        private Object httpMessage;
    
        public HttpServerResponseHandler(Object o) {
            this.httpMessage = o;
        }
    
    
        @Override
        public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
            System.out.println("网页请求结果=========================");
            System.out.println(httpMessage);
            System.out.println();
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
            cause.printStackTrace();
            ctx.close();
        }
    
        @Override
        public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
                            SocketAddress localAddress, ChannelPromise promise) throws Exception {
            System.out.println("connect !!!!!!!!!!!");
            // question 2
            ctx.writeAndFlush(httpMessage);
        }
    }